Merge branch 'next' of https://git.do.srb2.org/STJr/SRB2 into lua-skinsprites

This commit is contained in:
Steel Titanium 2020-12-03 17:29:08 -05:00
commit 7d45a7c91a
121 changed files with 18630 additions and 15317 deletions

View file

@ -13,6 +13,9 @@ set(SRB2_CORE_SOURCES
d_netcmd.c d_netcmd.c
d_netfil.c d_netfil.c
dehacked.c dehacked.c
deh_soc.c
deh_lua.c
deh_tables.c
f_finale.c f_finale.c
f_wipe.c f_wipe.c
filesrch.c filesrch.c
@ -66,6 +69,9 @@ set(SRB2_CORE_HEADERS
d_think.h d_think.h
d_ticcmd.h d_ticcmd.h
dehacked.h dehacked.h
deh_soc.h
deh_lua.h
deh_tables.h
doomdata.h doomdata.h
doomdef.h doomdef.h
doomstat.h doomstat.h
@ -130,6 +136,8 @@ set(SRB2_CORE_RENDER_SOURCES
r_splats.c r_splats.c
r_things.c r_things.c
r_textures.c r_textures.c
r_patch.c
r_patchrotation.c
r_picformats.c r_picformats.c
r_portal.c r_portal.c
@ -147,6 +155,8 @@ set(SRB2_CORE_RENDER_SOURCES
r_state.h r_state.h
r_things.h r_things.h
r_textures.h r_textures.h
r_patch.h
r_patchrotation.h
r_picformats.h r_picformats.h
r_portal.h r_portal.h
) )
@ -169,6 +179,7 @@ set(SRB2_CORE_GAME_SOURCES
p_telept.c p_telept.c
p_tick.c p_tick.c
p_user.c p_user.c
taglist.c
p_local.h p_local.h
p_maputl.h p_maputl.h
@ -180,6 +191,7 @@ set(SRB2_CORE_GAME_SOURCES
p_slopes.h p_slopes.h
p_spec.h p_spec.h
p_tick.h p_tick.h
taglist.h
) )
if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))

View file

@ -465,6 +465,9 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/d_netfil.o \ $(OBJDIR)/d_netfil.o \
$(OBJDIR)/d_netcmd.o \ $(OBJDIR)/d_netcmd.o \
$(OBJDIR)/dehacked.o \ $(OBJDIR)/dehacked.o \
$(OBJDIR)/deh_soc.o \
$(OBJDIR)/deh_lua.o \
$(OBJDIR)/deh_tables.o \
$(OBJDIR)/z_zone.o \ $(OBJDIR)/z_zone.o \
$(OBJDIR)/f_finale.o \ $(OBJDIR)/f_finale.o \
$(OBJDIR)/f_wipe.o \ $(OBJDIR)/f_wipe.o \
@ -519,9 +522,12 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/r_splats.o \ $(OBJDIR)/r_splats.o \
$(OBJDIR)/r_things.o \ $(OBJDIR)/r_things.o \
$(OBJDIR)/r_textures.o \ $(OBJDIR)/r_textures.o \
$(OBJDIR)/r_patch.o \
$(OBJDIR)/r_patchrotation.o \
$(OBJDIR)/r_picformats.o \ $(OBJDIR)/r_picformats.o \
$(OBJDIR)/r_portal.o \ $(OBJDIR)/r_portal.o \
$(OBJDIR)/screen.o \ $(OBJDIR)/screen.o \
$(OBJDIR)/taglist.o \
$(OBJDIR)/v_video.o \ $(OBJDIR)/v_video.o \
$(OBJDIR)/s_sound.o \ $(OBJDIR)/s_sound.o \
$(OBJDIR)/sounds.o \ $(OBJDIR)/sounds.o \
@ -538,6 +544,15 @@ OBJS:=$(i_main_o) \
$(i_sound_o) \ $(i_sound_o) \
$(OBJS) $(OBJS)
ifndef ECHO
ifndef NOECHOFILENAMES
define echoName =
@echo -- $< ...
endef
endif
endif
# List of languages to compile. # List of languages to compile.
# For reference, this is the command I use to build a srb2.pot file from the source code. # For reference, this is the command I use to build a srb2.pot file from the source code.
# (The listed source files are the ones containing translated strings). # (The listed source files are the ones containing translated strings).
@ -698,6 +713,7 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
else else
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
@ -707,6 +723,7 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@
endif endif
endif endif
@ -735,43 +752,55 @@ endif
ifdef VALGRIND ifdef VALGRIND
$(OBJDIR)/z_zone.o: z_zone.c $(OBJDIR)/z_zone.o: z_zone.c
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -DHAVE_VALGRIND $(VALGRIND_CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -DHAVE_VALGRIND $(VALGRIND_CFLAGS) -c $< -o $@
endif endif
$(OBJDIR)/comptime.o: comptime.c pre-build $(OBJDIR)/comptime.o: comptime.c pre-build
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
$(BIN)/%.mo: locale/%.po $(BIN)/%.mo: locale/%.po
-$(MKDIR) $(BIN) -$(MKDIR) $(BIN)
$(echoName)
$(MSGFMT) -f -o $@ $< $(MSGFMT) -f -o $@ $<
$(OBJDIR)/%.o: %.c $(OBJDIR)/%.o: %.c
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
$(OBJDIR)/%.o: $(INTERFACE)/%.c $(OBJDIR)/%.o: $(INTERFACE)/%.c
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
ifdef MACOSX ifdef MACOSX
$(OBJDIR)/%.o: sdl/macosx/%.c $(OBJDIR)/%.o: sdl/macosx/%.c
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
endif endif
$(OBJDIR)/%.o: hardware/%.c $(OBJDIR)/%.o: hardware/%.c
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
$(OBJDIR)/%.o: blua/%.c $(OBJDIR)/%.o: blua/%.c
$(echoName)
$(CC) $(CFLAGS) $(LUA_CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(LUA_CFLAGS) $(WFLAGS) -c $< -o $@
$(OBJDIR)/%.o: %.nas $(OBJDIR)/%.o: %.nas
$(echoName)
$(NASM) $(NASMOPTS) -o $@ -f $(NASMFORMAT) $< $(NASM) $(NASMOPTS) -o $@ -f $(NASMFORMAT) $<
$(OBJDIR)/vid_copy.o: vid_copy.s asm_defs.inc $(OBJDIR)/vid_copy.o: vid_copy.s asm_defs.inc
$(echoName)
$(CC) $(OPTS) $(ASFLAGS) -x assembler-with-cpp -c $< -o $@ $(CC) $(OPTS) $(ASFLAGS) -x assembler-with-cpp -c $< -o $@
$(OBJDIR)/%.o: %.s $(OBJDIR)/%.o: %.s
$(echoName)
$(CC) $(OPTS) -x assembler-with-cpp -c $< -o $@ $(CC) $(OPTS) -x assembler-with-cpp -c $< -o $@
$(OBJDIR)/SRB2.res: win32/Srb2win.rc win32/afxres.h win32/resource.h $(OBJDIR)/SRB2.res: win32/Srb2win.rc win32/afxres.h win32/resource.h
$(echoName)
$(WINDRES) -i $< -O rc $(WINDRESFLAGS) --include-dir=win32 -o $@ -O coff $(WINDRES) -i $< -O rc $(WINDRESFLAGS) --include-dir=win32 -o $@ -O coff
@ -785,6 +814,7 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
$(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \ $(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
@ -794,6 +824,7 @@ $(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
endif endif
@ -804,31 +835,37 @@ ifdef SDL
ifdef MINGW ifdef MINGW
$(OBJDIR)/win_dbg.o: win32/win_dbg.c $(OBJDIR)/win_dbg.o: win32/win_dbg.c
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
endif endif
ifdef STATICHS ifdef STATICHS
$(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \ $(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \
hardware/hw_dll.h hardware/hw_dll.h
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
$(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \ $(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \
hardware/hw_dll.h hardware/hw_dll.h
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
ifdef MINGW ifdef MINGW
$(OBJDIR)/s_ds3d.o: hardware/s_ds3d/s_ds3d.c hardware/hw3dsdrv.h \ $(OBJDIR)/s_ds3d.o: hardware/s_ds3d/s_ds3d.c hardware/hw3dsdrv.h \
hardware/hw_dll.h hardware/hw_dll.h
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
endif endif
else else
$(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \ $(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \
hardware/hw_dll.h hardware/hw_dll.h
$(echoName)
$(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_fmod.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_fmod/s_fmod.c $(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_fmod.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_fmod/s_fmod.c
$(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \ $(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \
hardware/hw_dll.h hardware/hw_dll.h
$(echoName)
$(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_openal.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_openal/s_openal.c $(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_openal.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_openal/s_openal.c
endif endif
endif endif

View file

@ -9,6 +9,7 @@
#include "utils/Log.h" #include "utils/Log.h"
rendermode_t rendermode = render_soft; rendermode_t rendermode = render_soft;
rendermode_t chosenrendermode = render_none;
boolean highcolor = false; boolean highcolor = false;
@ -52,8 +53,15 @@ INT32 VID_SetMode(INT32 modenum)
return 0; return 0;
} }
void VID_CheckRenderer(void) {} boolean VID_CheckRenderer(void)
void VID_CheckGLLoaded(rendermode_t oldrender) {} {
return false;
}
void VID_CheckGLLoaded(rendermode_t oldrender)
{
(void)oldrender;
}
const char *VID_GetModeName(INT32 modenum) const char *VID_GetModeName(INT32 modenum)
{ {

View file

@ -277,6 +277,9 @@ void Got_LuaFile(UINT8 **cp, INT32 playernum)
if (!luafiletransfers) if (!luafiletransfers)
I_Error("No Lua file transfer\n"); I_Error("No Lua file transfer\n");
lua_settop(gL, 0); // Just in case...
lua_pushcfunction(gL, LUA_GetErrorMessage);
// Retrieve the callback and push it on the stack // Retrieve the callback and push it on the stack
lua_pushfstring(gL, FMT_FILECALLBACKID, luafiletransfers->id); lua_pushfstring(gL, FMT_FILECALLBACKID, luafiletransfers->id);
lua_gettable(gL, LUA_REGISTRYINDEX); lua_gettable(gL, LUA_REGISTRYINDEX);
@ -304,7 +307,8 @@ void Got_LuaFile(UINT8 **cp, INT32 playernum)
lua_pushstring(gL, luafiletransfers->filename); lua_pushstring(gL, luafiletransfers->filename);
// Call the callback // Call the callback
LUA_Call(gL, 2); LUA_Call(gL, 2, 0, 1);
lua_settop(gL, 0);
if (success) if (success)
{ {

View file

@ -56,7 +56,8 @@ I_mutex con_mutex;
#endif/*HAVE_THREADS*/ #endif/*HAVE_THREADS*/
static boolean con_started = false; // console has been initialised static boolean con_started = false; // console has been initialised
boolean con_startup = false; // true at game startup, screen need refreshing boolean con_startup = false; // true at game startup
boolean con_refresh = false; // screen needs refreshing
static boolean con_forcepic = true; // at startup toggle console translucency when first off static boolean con_forcepic = true; // at startup toggle console translucency when first off
boolean con_recalc; // set true when screen size has changed boolean con_recalc; // set true when screen size has changed
@ -439,7 +440,8 @@ void CON_Init(void)
Lock_state(); Lock_state();
con_started = true; con_started = true;
con_startup = true; // need explicit screen refresh until we are in Doom loop con_startup = true;
con_refresh = true; // needs explicit screen refresh until we are in the main game loop
consoletoggle = false; consoletoggle = false;
Unlock_state(); Unlock_state();
@ -457,7 +459,8 @@ void CON_Init(void)
Lock_state(); Lock_state();
con_started = true; con_started = true;
con_startup = false; // need explicit screen refresh until we are in Doom loop con_startup = false;
con_refresh = false; // disable explicit screen refresh
consoletoggle = true; consoletoggle = true;
Unlock_state(); Unlock_state();
@ -1438,7 +1441,7 @@ void CONS_Printf(const char *fmt, ...)
{ {
va_list argptr; va_list argptr;
static char *txt = NULL; static char *txt = NULL;
boolean startup; boolean refresh;
if (txt == NULL) if (txt == NULL)
txt = malloc(8192); txt = malloc(8192);
@ -1454,32 +1457,21 @@ void CONS_Printf(const char *fmt, ...)
if (con_started) if (con_started)
CON_Print(txt); CON_Print(txt);
CON_LogMessage(txt); CON_LogMessage(txt);
Lock_state(); Lock_state();
// make sure new text is visible // make sure new text is visible
con_scrollup = 0; con_scrollup = 0;
startup = con_startup; refresh = con_refresh;
Unlock_state(); Unlock_state();
// if not in display loop, force screen update // if not in display loop, force screen update
if (startup && (!setrenderneeded)) if (refresh)
{ {
#ifdef _WINDOWS CON_Drawer(); // here we display the console text
patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH);
// Jimita: CON_DrawBackpic just called V_DrawScaledPatch
V_DrawScaledPatch(0, 0, 0, con_backpic);
W_UnlockCachedPatch(con_backpic);
I_LoadingScreen(txt); // Win32/OS2 only
#else
// here we display the console text
CON_Drawer();
I_FinishUpdate(); // page flip or blit buffer I_FinishUpdate(); // page flip or blit buffer
#endif
} }
} }
@ -1541,7 +1533,7 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...)
// //
void CONS_Error(const char *msg) void CONS_Error(const char *msg)
{ {
#ifdef RPC_NO_WINDOWS_H #if defined(RPC_NO_WINDOWS_H) && defined(_WINDOWS)
if (!graphics_started) if (!graphics_started)
{ {
MessageBoxA(vid.WndParent, msg, "SRB2 Warning", MB_OK); MessageBoxA(vid.WndParent, msg, "SRB2 Warning", MB_OK);
@ -1690,7 +1682,7 @@ static void CON_DrawHudlines(void)
;//charwidth = 4 * con_scalefactor; ;//charwidth = 4 * con_scalefactor;
else else
{ {
//charwidth = SHORT(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor; //charwidth = (hu_font['A'-HU_FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true); V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true);
} }
} }
@ -1719,8 +1711,8 @@ static void CON_DrawBackpic(void)
if (piclump == LUMPERROR) if (piclump == LUMPERROR)
piclump = W_GetNumForName("MISSING"); piclump = W_GetNumForName("MISSING");
// Cache the Software patch. // Cache the patch.
con_backpic = W_CacheSoftwarePatchNum(piclump, PU_PATCH); con_backpic = W_CachePatchNum(piclump, PU_PATCH);
// Center the backpic, and draw a vertically cropped patch. // Center the backpic, and draw a vertically cropped patch.
w = (con_backpic->width * vid.dupx); w = (con_backpic->width * vid.dupx);
@ -1731,7 +1723,7 @@ static void CON_DrawBackpic(void)
// then fill the sides with a solid color. // then fill the sides with a solid color.
if (x > 0) if (x > 0)
{ {
column_t *column = (column_t *)((UINT8 *)(con_backpic) + LONG(con_backpic->columnofs[0])); column_t *column = (column_t *)((UINT8 *)(con_backpic->columns) + (con_backpic->columnofs[0]));
if (!column->topdelta) if (!column->topdelta)
{ {
UINT8 *source = (UINT8 *)(column) + 3; UINT8 *source = (UINT8 *)(column) + 3;
@ -1743,8 +1735,7 @@ static void CON_DrawBackpic(void)
} }
} }
// Cache the patch normally. // Draw the patch.
con_backpic = W_CachePatchNum(piclump, PU_PATCH);
V_DrawCroppedPatch(x << FRACBITS, 0, FRACUNIT, V_NOSCALESTART, con_backpic, V_DrawCroppedPatch(x << FRACBITS, 0, FRACUNIT, V_NOSCALESTART, con_backpic,
0, ( BASEVIDHEIGHT - h ), BASEVIDWIDTH, h); 0, ( BASEVIDHEIGHT - h ), BASEVIDWIDTH, h);
@ -1829,9 +1820,6 @@ void CON_Drawer(void)
return; return;
} }
if (needpatchrecache)
HU_LoadGraphics();
if (con_recalc) if (con_recalc)
{ {
CON_RecalcSize(); CON_RecalcSize();

View file

@ -25,8 +25,12 @@ extern I_mutex con_mutex;
// set true when screen size has changed, to adapt console // set true when screen size has changed, to adapt console
extern boolean con_recalc; extern boolean con_recalc;
// console being displayed at game startup
extern boolean con_startup; extern boolean con_startup;
// needs explicit screen refresh until we are in the main game loop
extern boolean con_refresh;
// top clip value for view render: do not draw part of view hidden by console // top clip value for view render: do not draw part of view hidden by console
extern INT32 con_clipviewtop; extern INT32 con_clipviewtop;

View file

@ -2501,10 +2501,14 @@ static void CL_RemovePlayer(INT32 playernum, kickreason_t reason)
} }
count--; count--;
spheres = players[playernum].spheres; sincrement = spheres = players[playernum].spheres;
rings = players[playernum].rings; rincrement = rings = players[playernum].rings;
sincrement = spheres/count;
rincrement = rings/count; if (count)
{
sincrement /= count;
rincrement /= count;
}
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {

View file

@ -107,8 +107,6 @@ boolean devparm = false; // started game with -devparm
boolean singletics = false; // timedemo boolean singletics = false; // timedemo
boolean lastdraw = false; boolean lastdraw = false;
static void D_CheckRendererState(void);
postimg_t postimgtype = postimg_none; postimg_t postimgtype = postimg_none;
INT32 postimgparam; INT32 postimgparam;
postimg_t postimgtype2 = postimg_none; postimg_t postimgtype2 = postimg_none;
@ -237,7 +235,6 @@ INT16 wipetypepost = -1;
static void D_Display(void) static void D_Display(void)
{ {
INT32 setrenderstillneeded = 0;
boolean forcerefresh = false; boolean forcerefresh = false;
static boolean wipe = false; static boolean wipe = false;
INT32 wipedefindex = 0; INT32 wipedefindex = 0;
@ -260,48 +257,28 @@ static void D_Display(void)
// create plane polygons, if necessary. // create plane polygons, if necessary.
// 3. Functions related to switching video // 3. Functions related to switching video
// modes (resolution) are called. // modes (resolution) are called.
// 4. Patch data is freed from memory, // 4. The frame is ready to be drawn!
// and recached if necessary.
// 5. The frame is ready to be drawn!
// stop movie if needs to change renderer // Check for change of renderer or screen size (video mode)
if (setrenderneeded && (moviemode == MM_APNG))
M_StopMovie();
// check for change of renderer or screen size (video mode)
if ((setrenderneeded || setmodeneeded) && !wipe) if ((setrenderneeded || setmodeneeded) && !wipe)
{
if (setrenderneeded)
{
CONS_Debug(DBG_RENDER, "setrenderneeded set (%d)\n", setrenderneeded);
setrenderstillneeded = setrenderneeded;
}
SCR_SetMode(); // change video mode SCR_SetMode(); // change video mode
}
if (vid.recalc || setrenderstillneeded) // Recalc the screen
{ if (vid.recalc)
SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc() SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc()
#ifdef HWRENDER
// Shoot! The screen texture was flushed!
if ((rendermode == render_opengl) && (gamestate == GS_INTERMISSION))
usebuffer = false;
#endif
}
// View morph
if (rendermode == render_soft && !splitscreen) if (rendermode == render_soft && !splitscreen)
R_CheckViewMorph(); R_CheckViewMorph();
// change the view size if needed // Change the view size if needed
if (setsizeneeded || setrenderstillneeded) // Set by changing video mode or renderer
if (setsizeneeded)
{ {
R_ExecuteSetViewSize(); R_ExecuteSetViewSize();
forcerefresh = true; // force background redraw forcerefresh = true; // force background redraw
} }
// Lactozilla: Renderer switching
D_CheckRendererState();
// draw buffered stuff to screen // draw buffered stuff to screen
// Used only by linux GGI version // Used only by linux GGI version
I_UpdateNoBlit(); I_UpdateNoBlit();
@ -530,7 +507,7 @@ static void D_Display(void)
else else
py = viewwindowy + 4; py = viewwindowy + 4;
patch = W_CachePatchName("M_PAUSE", PU_PATCH); patch = W_CachePatchName("M_PAUSE", PU_PATCH);
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - SHORT(patch->width))/2, py, 0, patch); V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - patch->width)/2, py, 0, patch);
#else #else
INT32 y = ((automapactive) ? (32) : (BASEVIDHEIGHT/2)); INT32 y = ((automapactive) ? (32) : (BASEVIDHEIGHT/2));
M_DrawTextBox((BASEVIDWIDTH/2) - (60), y - (16), 13, 2); M_DrawTextBox((BASEVIDWIDTH/2) - (60), y - (16), 13, 2);
@ -642,26 +619,6 @@ static void D_Display(void)
I_FinishUpdate(); // page flip or blit buffer I_FinishUpdate(); // page flip or blit buffer
ps_swaptime = I_GetTimeMicros() - ps_swaptime; ps_swaptime = I_GetTimeMicros() - ps_swaptime;
} }
needpatchflush = false;
needpatchrecache = false;
}
// Check the renderer's state
// after a possible renderer switch.
void D_CheckRendererState(void)
{
// flush all patches from memory
if (needpatchflush)
{
Z_FlushCachedPatches();
needpatchflush = false;
}
// some patches have been freed,
// so cache them again
if (needpatchrecache)
R_ReloadHUDGraphics();
} }
// ========================================================================= // =========================================================================
@ -688,12 +645,15 @@ void D_SRB2Loop(void)
oldentertics = I_GetTime(); oldentertics = I_GetTime();
// end of loading screen: CONS_Printf() will no more call FinishUpdate() // end of loading screen: CONS_Printf() will no more call FinishUpdate()
con_refresh = false;
con_startup = false; con_startup = false;
// make sure to do a d_display to init mode _before_ load a level // make sure to do a d_display to init mode _before_ load a level
SCR_SetMode(); // change video mode SCR_SetMode(); // change video mode
SCR_Recalc(); SCR_Recalc();
chosenrendermode = render_none;
// Check and print which version is executed. // Check and print which version is executed.
// Use this as the border between setup and the main game loop being entered. // Use this as the border between setup and the main game loop being entered.
CONS_Printf( CONS_Printf(
@ -1338,24 +1298,6 @@ void D_SRB2Main(void)
// set user default mode or mode set at cmdline // set user default mode or mode set at cmdline
SCR_CheckDefaultMode(); SCR_CheckDefaultMode();
// Lactozilla: Does the render mode need to change?
if ((setrenderneeded != 0) && (setrenderneeded != rendermode))
{
CONS_Printf(M_GetText("Switching the renderer...\n"));
Z_PreparePatchFlush();
// set needpatchflush / needpatchrecache true for D_CheckRendererState
needpatchflush = true;
needpatchrecache = true;
// Set cv_renderer to the new render mode
VID_CheckRenderer();
SCR_ChangeRendererCVars(rendermode);
// check the renderer's state
D_CheckRendererState();
}
wipegamestate = gamestate; wipegamestate = gamestate;
savedata.lives = 0; // flag this as not-used savedata.lives = 0; // flag this as not-used

View file

@ -374,6 +374,7 @@ consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL)
static CV_PossibleValue_t perfstats_cons_t[] = { static CV_PossibleValue_t perfstats_cons_t[] = {
{0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}}; {0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}};
consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", 0, perfstats_cons_t, NULL); consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", 0, perfstats_cons_t, NULL);
consvar_t cv_freedemocamera = CVAR_INIT("freedemocamera", "Off", CV_SAVE, CV_OnOff, NULL);
char timedemo_name[256]; char timedemo_name[256];
boolean timedemo_csv; boolean timedemo_csv;
@ -675,10 +676,6 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_gif_dynamicdelay); CV_RegisterVar(&cv_gif_dynamicdelay);
CV_RegisterVar(&cv_gif_localcolortable); CV_RegisterVar(&cv_gif_localcolortable);
#ifdef WALLSPLATS
CV_RegisterVar(&cv_splats);
#endif
// register these so it is saved to config // register these so it is saved to config
CV_RegisterVar(&cv_playername); CV_RegisterVar(&cv_playername);
CV_RegisterVar(&cv_playercolor); CV_RegisterVar(&cv_playercolor);
@ -880,6 +877,8 @@ void D_RegisterClientCommands(void)
// CV_RegisterVar(&cv_grid); // CV_RegisterVar(&cv_grid);
// CV_RegisterVar(&cv_snapto); // CV_RegisterVar(&cv_snapto);
CV_RegisterVar(&cv_freedemocamera);
// add cheat commands // add cheat commands
COM_AddCommand("noclip", Command_CheatNoClip_f); COM_AddCommand("noclip", Command_CheatNoClip_f);
COM_AddCommand("god", Command_CheatGod_f); COM_AddCommand("god", Command_CheatGod_f);

View file

@ -75,9 +75,6 @@ extern consvar_t cv_teamscramble;
extern consvar_t cv_scrambleonchange; extern consvar_t cv_scrambleonchange;
extern consvar_t cv_netstat; extern consvar_t cv_netstat;
#ifdef WALLSPLATS
extern consvar_t cv_splats;
#endif
extern consvar_t cv_countdowntime; extern consvar_t cv_countdowntime;
extern consvar_t cv_runscripts; extern consvar_t cv_runscripts;
@ -121,6 +118,8 @@ extern boolean timedemo_csv;
extern char timedemo_csv_id[256]; extern char timedemo_csv_id[256];
extern boolean timedemo_quit; extern boolean timedemo_quit;
extern consvar_t cv_freedemocamera;
typedef enum typedef enum
{ {
XD_NAMEANDCOLOR = 1, XD_NAMEANDCOLOR = 1,

697
src/deh_lua.c Normal file
View file

@ -0,0 +1,697 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file deh_lua.c
/// \brief Lua SOC library
#include "g_game.h"
#include "s_sound.h"
#include "z_zone.h"
#include "m_menu.h"
#include "m_misc.h"
#include "p_local.h"
#include "st_stuff.h"
#include "fastcmp.h"
#include "lua_script.h"
#include "lua_libs.h"
#include "dehacked.h"
#include "deh_lua.h"
#include "deh_tables.h"
#ifdef MUSICSLOT_COMPATIBILITY
#include "deh_soc.h" // for get_mus
#endif
// freeslot takes a name (string only!)
// and allocates it to the appropriate free slot.
// Returns the slot number allocated for it or nil if failed.
// ex. freeslot("MT_MYTHING","S_MYSTATE1","S_MYSTATE2")
// TODO: Error checking! @.@; There's currently no way to know which ones failed and why!
//
static inline int lib_freeslot(lua_State *L)
{
int n = lua_gettop(L);
int r = 0; // args returned
char *s, *type,*word;
if (!lua_lumploading)
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
while (n-- > 0)
{
s = Z_StrDup(luaL_checkstring(L,1));
type = strtok(s, "_");
if (type)
strupr(type);
else {
Z_Free(s);
return luaL_error(L, "Unknown enum type in '%s'\n", luaL_checkstring(L, 1));
}
word = strtok(NULL, "\n");
if (word)
strupr(word);
else {
Z_Free(s);
return luaL_error(L, "Missing enum name in '%s'\n", luaL_checkstring(L, 1));
}
if (fastcmp(type, "SFX")) {
sfxenum_t sfx;
strlwr(word);
CONS_Printf("Sound sfx_%s allocated.\n",word);
sfx = S_AddSoundFx(word, false, 0, false);
if (sfx != sfx_None) {
lua_pushinteger(L, sfx);
r++;
} else
CONS_Alert(CONS_WARNING, "Ran out of free SFX slots!\n");
}
else if (fastcmp(type, "SPR"))
{
char wad;
spritenum_t j;
lua_getfield(L, LUA_REGISTRYINDEX, "WAD");
wad = (char)lua_tointeger(L, -1);
lua_pop(L, 1);
for (j = SPR_FIRSTFREESLOT; j <= SPR_LASTFREESLOT; j++)
{
if (used_spr[(j-SPR_FIRSTFREESLOT)/8] & (1<<(j%8)))
{
if (!sprnames[j][4] && memcmp(sprnames[j],word,4)==0)
sprnames[j][4] = wad;
continue; // Already allocated, next.
}
// Found a free slot!
CONS_Printf("Sprite SPR_%s allocated.\n",word);
strncpy(sprnames[j],word,4);
//sprnames[j][4] = 0;
used_spr[(j-SPR_FIRSTFREESLOT)/8] |= 1<<(j%8); // Okay, this sprite slot has been named now.
lua_pushinteger(L, j);
r++;
break;
}
if (j > SPR_LASTFREESLOT)
CONS_Alert(CONS_WARNING, "Ran out of free sprite slots!\n");
}
else if (fastcmp(type, "S"))
{
statenum_t i;
for (i = 0; i < NUMSTATEFREESLOTS; i++)
if (!FREE_STATES[i]) {
CONS_Printf("State S_%s allocated.\n",word);
FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_STATES[i],word);
lua_pushinteger(L, S_FIRSTFREESLOT + i);
r++;
break;
}
if (i == NUMSTATEFREESLOTS)
CONS_Alert(CONS_WARNING, "Ran out of free State slots!\n");
}
else if (fastcmp(type, "MT"))
{
mobjtype_t i;
for (i = 0; i < NUMMOBJFREESLOTS; i++)
if (!FREE_MOBJS[i]) {
CONS_Printf("MobjType MT_%s allocated.\n",word);
FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_MOBJS[i],word);
lua_pushinteger(L, MT_FIRSTFREESLOT + i);
r++;
break;
}
if (i == NUMMOBJFREESLOTS)
CONS_Alert(CONS_WARNING, "Ran out of free MobjType slots!\n");
}
else if (fastcmp(type, "SKINCOLOR"))
{
skincolornum_t i;
for (i = 0; i < NUMCOLORFREESLOTS; i++)
if (!FREE_SKINCOLORS[i]) {
CONS_Printf("Skincolor SKINCOLOR_%s allocated.\n",word);
FREE_SKINCOLORS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_SKINCOLORS[i],word);
M_AddMenuColor(numskincolors++);
lua_pushinteger(L, SKINCOLOR_FIRSTFREESLOT + i);
r++;
break;
}
if (i == NUMCOLORFREESLOTS)
CONS_Alert(CONS_WARNING, "Ran out of free skincolor slots!\n");
}
else if (fastcmp(type, "SPR2"))
{
// Search if we already have an SPR2 by that name...
playersprite_t i;
for (i = SPR2_FIRSTFREESLOT; i < free_spr2; i++)
if (memcmp(spr2names[i],word,4) == 0)
break;
// We don't, so allocate a new one.
if (i >= free_spr2) {
if (free_spr2 < NUMPLAYERSPRITES)
{
CONS_Printf("Sprite SPR2_%s allocated.\n",word);
strncpy(spr2names[free_spr2],word,4);
spr2defaults[free_spr2] = 0;
lua_pushinteger(L, free_spr2);
r++;
spr2names[free_spr2++][4] = 0;
} else
CONS_Alert(CONS_WARNING, "Ran out of free SPR2 slots!\n");
}
}
else if (fastcmp(type, "TOL"))
{
// Search if we already have a typeoflevel by that name...
int i;
for (i = 0; TYPEOFLEVEL[i].name; i++)
if (fastcmp(word, TYPEOFLEVEL[i].name))
break;
// We don't, so allocate a new one.
if (TYPEOFLEVEL[i].name == NULL) {
if (lastcustomtol == (UINT32)MAXTOL) // Unless you have way too many, since they're flags.
CONS_Alert(CONS_WARNING, "Ran out of free typeoflevel slots!\n");
else {
CONS_Printf("TypeOfLevel TOL_%s allocated.\n",word);
G_AddTOL(lastcustomtol, word);
lua_pushinteger(L, lastcustomtol);
lastcustomtol <<= 1;
r++;
}
}
}
Z_Free(s);
lua_remove(L, 1);
continue;
}
return r;
}
// Wrapper for ALL A_Action functions.
// Arguments: mobj_t actor, int var1, int var2
static int action_call(lua_State *L)
{
//actionf_t *action = lua_touserdata(L,lua_upvalueindex(1));
actionf_t *action = *((actionf_t **)luaL_checkudata(L, 1, META_ACTION));
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
var1 = (INT32)luaL_optinteger(L, 3, 0);
var2 = (INT32)luaL_optinteger(L, 4, 0);
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
action->acp1(actor);
return 0;
}
// Hardcoded A_Action name to call for super() or NULL if super() would be invalid.
// Set in lua_infolib.
const char *superactions[MAXRECURSION];
UINT8 superstack = 0;
static int lib_dummysuper(lua_State *L)
{
return luaL_error(L, "Can't call super() outside of hardcode-replacing A_Action functions being called by state changes!"); // convoluted, I know. @_@;;
}
static inline int lib_getenum(lua_State *L)
{
const char *word, *p;
fixed_t i;
boolean mathlib = lua_toboolean(L, lua_upvalueindex(1));
if (lua_type(L,2) != LUA_TSTRING)
return 0;
word = lua_tostring(L,2);
if (strlen(word) == 1) { // Assume sprite frame if length 1.
if (*word >= 'A' && *word <= '~')
{
lua_pushinteger(L, *word-'A');
return 1;
}
if (mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word);
return 0;
}
else if (fastncmp("MF_", word, 3)) {
p = word+3;
for (i = 0; MOBJFLAG_LIST[i]; i++)
if (fastcmp(p, MOBJFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mobjflag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MF2_", word, 4)) {
p = word+4;
for (i = 0; MOBJFLAG2_LIST[i]; i++)
if (fastcmp(p, MOBJFLAG2_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mobjflag2 '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MFE_", word, 4)) {
p = word+4;
for (i = 0; MOBJEFLAG_LIST[i]; i++)
if (fastcmp(p, MOBJEFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mobjeflag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MTF_", word, 4)) {
p = word+4;
for (i = 0; i < 4; i++)
if (MAPTHINGFLAG_LIST[i] && fastcmp(p, MAPTHINGFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mapthingflag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("PF_", word, 3)) {
p = word+3;
for (i = 0; PLAYERFLAG_LIST[i]; i++)
if (fastcmp(p, PLAYERFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (fastcmp(p, "FULLSTASIS"))
{
lua_pushinteger(L, (lua_Integer)PF_FULLSTASIS);
return 1;
}
else if (fastcmp(p, "USEDOWN")) // Remove case when 2.3 nears release...
{
lua_pushinteger(L, (lua_Integer)PF_SPINDOWN);
return 1;
}
if (mathlib) return luaL_error(L, "playerflag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("GT_", word, 3)) {
p = word;
for (i = 0; Gametype_ConstantNames[i]; i++)
if (fastcmp(p, Gametype_ConstantNames[i])) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "gametype '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("GTR_", word, 4)) {
p = word+4;
for (i = 0; GAMETYPERULE_LIST[i]; i++)
if (fastcmp(p, GAMETYPERULE_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "game type rule '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("TOL_", word, 4)) {
p = word+4;
for (i = 0; TYPEOFLEVEL[i].name; i++)
if (fastcmp(p, TYPEOFLEVEL[i].name)) {
lua_pushinteger(L, TYPEOFLEVEL[i].flag);
return 1;
}
if (mathlib) return luaL_error(L, "typeoflevel '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("ML_", word, 3)) {
p = word+3;
for (i = 0; i < 16; i++)
if (ML_LIST[i] && fastcmp(p, ML_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "linedef flag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("S_",word,2)) {
p = word+2;
for (i = 0; i < NUMSTATEFREESLOTS; i++) {
if (!FREE_STATES[i])
break;
if (fastcmp(p, FREE_STATES[i])) {
lua_pushinteger(L, S_FIRSTFREESLOT+i);
return 1;
}
}
for (i = 0; i < S_FIRSTFREESLOT; i++)
if (fastcmp(p, STATE_LIST[i]+2)) {
lua_pushinteger(L, i);
return 1;
}
return luaL_error(L, "state '%s' does not exist.\n", word);
}
else if (fastncmp("MT_",word,3)) {
p = word+3;
for (i = 0; i < NUMMOBJFREESLOTS; i++) {
if (!FREE_MOBJS[i])
break;
if (fastcmp(p, FREE_MOBJS[i])) {
lua_pushinteger(L, MT_FIRSTFREESLOT+i);
return 1;
}
}
for (i = 0; i < MT_FIRSTFREESLOT; i++)
if (fastcmp(p, MOBJTYPE_LIST[i]+3)) {
lua_pushinteger(L, i);
return 1;
}
return luaL_error(L, "mobjtype '%s' does not exist.\n", word);
}
else if (fastncmp("SPR_",word,4)) {
p = word+4;
for (i = 0; i < NUMSPRITES; i++)
if (!sprnames[i][4] && fastncmp(p,sprnames[i],4)) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "sprite '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("SPR2_",word,5)) {
p = word+5;
for (i = 0; i < (fixed_t)free_spr2; i++)
if (!spr2names[i][4])
{
// special 3-char cases, e.g. SPR2_RUN
// the spr2names entry will have "_" on the end, as in "RUN_"
if (spr2names[i][3] == '_' && !p[3]) {
if (fastncmp(p,spr2names[i],3)) {
lua_pushinteger(L, i);
return 1;
}
}
else if (fastncmp(p,spr2names[i],4)) {
lua_pushinteger(L, i);
return 1;
}
}
if (mathlib) return luaL_error(L, "player sprite '%s' could not be found.\n", word);
return 0;
}
else if (!mathlib && fastncmp("sfx_",word,4)) {
p = word+4;
for (i = 0; i < NUMSFX; i++)
if (S_sfx[i].name && fastcmp(p, S_sfx[i].name)) {
lua_pushinteger(L, i);
return 1;
}
return 0;
}
else if (mathlib && fastncmp("SFX_",word,4)) { // SOCs are ALL CAPS!
p = word+4;
for (i = 0; i < NUMSFX; i++)
if (S_sfx[i].name && fasticmp(p, S_sfx[i].name)) {
lua_pushinteger(L, i);
return 1;
}
return luaL_error(L, "sfx '%s' could not be found.\n", word);
}
else if (mathlib && fastncmp("DS",word,2)) {
p = word+2;
for (i = 0; i < NUMSFX; i++)
if (S_sfx[i].name && fasticmp(p, S_sfx[i].name)) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "sfx '%s' could not be found.\n", word);
return 0;
}
#ifdef MUSICSLOT_COMPATIBILITY
else if (!mathlib && fastncmp("mus_",word,4)) {
p = word+4;
if ((i = get_mus(p, false)) == 0)
return 0;
lua_pushinteger(L, i);
return 1;
}
else if (mathlib && fastncmp("MUS_",word,4)) { // SOCs are ALL CAPS!
p = word+4;
if ((i = get_mus(p, false)) == 0)
return luaL_error(L, "music '%s' could not be found.\n", word);
lua_pushinteger(L, i);
return 1;
}
else if (mathlib && (fastncmp("O_",word,2) || fastncmp("D_",word,2))) {
p = word+2;
if ((i = get_mus(p, false)) == 0)
return luaL_error(L, "music '%s' could not be found.\n", word);
lua_pushinteger(L, i);
return 1;
}
#endif
else if (!mathlib && fastncmp("pw_",word,3)) {
p = word+3;
for (i = 0; i < NUMPOWERS; i++)
if (fasticmp(p, POWERS_LIST[i])) {
lua_pushinteger(L, i);
return 1;
}
return 0;
}
else if (mathlib && fastncmp("PW_",word,3)) { // SOCs are ALL CAPS!
p = word+3;
for (i = 0; i < NUMPOWERS; i++)
if (fastcmp(p, POWERS_LIST[i])) {
lua_pushinteger(L, i);
return 1;
}
return luaL_error(L, "power '%s' could not be found.\n", word);
}
else if (fastncmp("HUD_",word,4)) {
p = word+4;
for (i = 0; i < NUMHUDITEMS; i++)
if (fastcmp(p, HUDITEMS_LIST[i])) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "huditem '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("SKINCOLOR_",word,10)) {
p = word+10;
for (i = 0; i < NUMCOLORFREESLOTS; i++) {
if (!FREE_SKINCOLORS[i])
break;
if (fastcmp(p, FREE_SKINCOLORS[i])) {
lua_pushinteger(L, SKINCOLOR_FIRSTFREESLOT+i);
return 1;
}
}
for (i = 0; i < SKINCOLOR_FIRSTFREESLOT; i++)
if (fastcmp(p, COLOR_ENUMS[i])) {
lua_pushinteger(L, i);
return 1;
}
return luaL_error(L, "skincolor '%s' could not be found.\n", word);
}
else if (fastncmp("GRADE_",word,6))
{
p = word+6;
for (i = 0; NIGHTSGRADE_LIST[i]; i++)
if (*p == NIGHTSGRADE_LIST[i])
{
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "NiGHTS grade '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MN_",word,3)) {
p = word+3;
for (i = 0; i < NUMMENUTYPES; i++)
if (fastcmp(p, MENUTYPES_LIST[i])) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "menutype '%s' could not be found.\n", word);
return 0;
}
else if (!mathlib && fastncmp("A_",word,2)) {
char *caps;
// Try to get a Lua action first.
/// \todo Push a closure that sets superactions[] and superstack.
lua_getfield(L, LUA_REGISTRYINDEX, LREG_ACTIONS);
// actions are stored in all uppercase.
caps = Z_StrDup(word);
strupr(caps);
lua_getfield(L, -1, caps);
Z_Free(caps);
if (!lua_isnil(L, -1))
return 1; // Success! :D That was easy.
// Welp, that failed.
lua_pop(L, 2); // pop nil and LREG_ACTIONS
// Hardcoded actions as callable Lua functions!
// Retrieving them from this metatable allows them to be case-insensitive!
for (i = 0; actionpointers[i].name; i++)
if (fasticmp(word, actionpointers[i].name)) {
// We push the actionf_t* itself as userdata!
LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION);
return 1;
}
return 0;
}
else if (!mathlib && fastcmp("super",word))
{
if (!superstack)
{
lua_pushcfunction(L, lib_dummysuper);
return 1;
}
for (i = 0; actionpointers[i].name; i++)
if (fasticmp(superactions[superstack-1], actionpointers[i].name)) {
LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION);
return 1;
}
return 0;
}
if (fastcmp(word, "BT_USE")) // Remove case when 2.3 nears release...
{
lua_pushinteger(L, (lua_Integer)BT_SPIN);
return 1;
}
for (i = 0; INT_CONST[i].n; i++)
if (fastcmp(word,INT_CONST[i].n)) {
lua_pushinteger(L, INT_CONST[i].v);
return 1;
}
if (mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word);
// DYNAMIC variables too!!
// Try not to add anything that would break netgames or timeattack replays here.
// You know, like consoleplayer, displayplayer, secondarydisplayplayer, or gametime.
return LUA_PushGlobals(L, word);
}
int LUA_EnumLib(lua_State *L)
{
if (lua_gettop(L) == 0)
lua_pushboolean(L, 0);
// Set the global metatable
lua_createtable(L, 0, 1);
lua_pushvalue(L, 1); // boolean passed to LUA_EnumLib as first argument.
lua_pushcclosure(L, lib_getenum, 1);
lua_setfield(L, -2, "__index");
lua_setmetatable(L, LUA_GLOBALSINDEX);
return 0;
}
// getActionName(action) -> return action's string name
static int lib_getActionName(lua_State *L)
{
if (lua_isuserdata(L, 1)) // arg 1 is built-in action, expect action userdata
{
actionf_t *action = *((actionf_t **)luaL_checkudata(L, 1, META_ACTION));
const char *name = NULL;
if (!action)
return luaL_error(L, "not a valid action?");
name = LUA_GetActionName(action);
if (!name) // that can't be right?
return luaL_error(L, "no name string could be found for this action");
lua_pushstring(L, name);
return 1;
}
else if (lua_isfunction(L, 1)) // arg 1 is a function (either C or Lua)
{
lua_settop(L, 1); // set top of stack to 1 (removing any extra args, which there shouldn't be)
// get the name for this action, if possible.
lua_getfield(L, LUA_REGISTRYINDEX, LREG_ACTIONS);
lua_pushnil(L);
// Lua stack at this point:
// 1 ... -2 -1
// arg ... LREG_ACTIONS nil
while (lua_next(L, -2))
{
// Lua stack at this point:
// 1 ... -3 -2 -1
// arg ... LREG_ACTIONS "A_ACTION" function
if (lua_rawequal(L, -1, 1)) // is this the same as the arg?
{
// make sure the key (i.e. "A_ACTION") is a string first
// (note: we don't use lua_isstring because it also returns true for numbers)
if (lua_type(L, -2) == LUA_TSTRING)
{
lua_pushvalue(L, -2); // push "A_ACTION" string to top of stack
return 1;
}
lua_pop(L, 2); // pop the name and function
break; // probably should have succeeded but we didn't, so end the loop
}
lua_pop(L, 1);
}
lua_pop(L, 1); // pop LREG_ACTIONS
return 0; // return nothing (don't error)
}
return luaL_typerror(L, 1, "action userdata or Lua function");
}
int LUA_SOCLib(lua_State *L)
{
lua_register(L,"freeslot",lib_freeslot);
lua_register(L,"getActionName",lib_getActionName);
luaL_newmetatable(L, META_ACTION);
lua_pushcfunction(L, action_call);
lua_setfield(L, -2, "__call");
lua_pop(L, 1);
return 0;
}
const char *LUA_GetActionName(void *action)
{
actionf_t *act = (actionf_t *)action;
size_t z;
for (z = 0; actionpointers[z].name; z++)
{
if (actionpointers[z].action.acv == act->acv)
return actionpointers[z].name;
}
return NULL;
}
void LUA_SetActionByName(void *state, const char *actiontocompare)
{
state_t *st = (state_t *)state;
size_t z;
for (z = 0; actionpointers[z].name; z++)
{
if (fasticmp(actiontocompare, actionpointers[z].name))
{
st->action = actionpointers[z].action;
st->action.acv = actionpointers[z].action.acv; // assign
st->action.acp1 = actionpointers[z].action.acp1;
return;
}
}
}
enum actionnum LUA_GetActionNumByName(const char *actiontocompare)
{
size_t z;
for (z = 0; actionpointers[z].name; z++)
if (fasticmp(actiontocompare, actionpointers[z].name))
return z;
return z;
}

21
src/deh_lua.h Normal file
View file

@ -0,0 +1,21 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file deh_lua.h
/// \brief Lua SOC library
#ifndef __DEH_LUA_H__
#define __DEH_LUA_H__
boolean LUA_SetLuaAction(void *state, const char *actiontocompare);
const char *LUA_GetActionName(void *action);
void LUA_SetActionByName(void *state, const char *actiontocompare);
enum actionnum LUA_GetActionNumByName(const char *actiontocompare);
#endif

4527
src/deh_soc.c Normal file

File diff suppressed because it is too large Load diff

89
src/deh_soc.h Normal file
View file

@ -0,0 +1,89 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file deh_soc.h
/// \brief Load SOC file and change tables and text
#ifndef __DEH_SOC_H__
#define __DEH_SOC_H__
#include "doomdef.h"
#include "g_game.h"
#include "sounds.h"
#include "info.h"
#include "d_think.h"
#include "m_argv.h"
#include "z_zone.h"
#include "w_wad.h"
#include "m_menu.h"
#include "m_misc.h"
#include "f_finale.h"
#include "st_stuff.h"
#include "i_system.h"
#include "p_setup.h"
#include "r_data.h"
#include "r_textures.h"
#include "r_draw.h"
#include "r_picformats.h"
#include "r_things.h" // R_Char2Frame
#include "r_sky.h"
#include "fastcmp.h"
#include "lua_script.h" // Reluctantly included for LUA_EvalMath
#include "d_clisrv.h"
#ifdef HWRENDER
#include "hardware/hw_light.h"
#endif
#include "info.h"
#include "dehacked.h"
#include "doomdef.h" // MUSICSLOT_COMPATIBILITY, HWRENDER
// Crazy word-reading stuff
/// \todo Put these in a seperate file or something.
mobjtype_t get_mobjtype(const char *word);
statenum_t get_state(const char *word);
spritenum_t get_sprite(const char *word);
playersprite_t get_sprite2(const char *word);
sfxenum_t get_sfx(const char *word);
#ifdef MUSICSLOT_COMPATIBILITY
UINT16 get_mus(const char *word, UINT8 dehacked_mode);
#endif
hudnum_t get_huditem(const char *word);
menutype_t get_menutype(const char *word);
//INT16 get_gametype(const char *word);
//powertype_t get_power(const char *word);
skincolornum_t get_skincolor(const char *word);
void readwipes(MYFILE *f);
void readmaincfg(MYFILE *f);
void readconditionset(MYFILE *f, UINT8 setnum);
void readunlockable(MYFILE *f, INT32 num);
void readextraemblemdata(MYFILE *f, INT32 num);
void reademblemdata(MYFILE *f, INT32 num);
void readsound(MYFILE *f, INT32 num);
void readframe(MYFILE *f, INT32 num);
void readhuditem(MYFILE *f, INT32 num);
void readmenu(MYFILE *f, INT32 num);
void readtextprompt(MYFILE *f, INT32 num);
void readcutscene(MYFILE *f, INT32 num);
void readlevelheader(MYFILE *f, INT32 num);
void readgametype(MYFILE *f, char *gtname);
void readsprite2(MYFILE *f, INT32 num);
void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2);
#ifdef HWRENDER
void readlight(MYFILE *f, INT32 num);
#endif
void readskincolor(MYFILE *f, INT32 num);
void readthing(MYFILE *f, INT32 num);
void readfreeslots(MYFILE *f);
void readPlayer(MYFILE *f, INT32 num);
void clear_levels(void);
void clear_conditionsets(void);
#endif

5423
src/deh_tables.c Normal file

File diff suppressed because it is too large Load diff

75
src/deh_tables.h Normal file
View file

@ -0,0 +1,75 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file deh_tables.h
/// \brief Define DeHackEd tables.
#ifndef __DEH_TABLES_H__
#define __DEH_TABLES_H__
#include "doomdef.h" // Constants
#include "d_think.h" // actionf_t
#include "info.h" // Mobj, state, sprite, etc constants
#include "lua_script.h"
// Free slot names
// The crazy word-reading stuff uses these.
extern char *FREE_STATES[NUMSTATEFREESLOTS];
extern char *FREE_MOBJS[NUMMOBJFREESLOTS];
extern char *FREE_SKINCOLORS[NUMCOLORFREESLOTS];
extern UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway.
#define initfreeslots() {\
memset(FREE_STATES,0,sizeof(char *) * NUMSTATEFREESLOTS);\
memset(FREE_MOBJS,0,sizeof(char *) * NUMMOBJFREESLOTS);\
memset(FREE_SKINCOLORS,0,sizeof(char *) * NUMCOLORFREESLOTS);\
memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));\
}
struct flickytypes_s {
const char *name;
const mobjtype_t type;
};
#define MAXFLICKIES 64
/** Action pointer for reading actions from Dehacked lumps.
*/
typedef struct
{
actionf_t action; ///< Function pointer corresponding to the actual action.
const char *name; ///< Name of the action in ALL CAPS.
} actionpointer_t;
struct int_const_s {
const char *n;
// has to be able to hold both fixed_t and angle_t, so drastic measure!!
lua_Integer v;
};
extern const char NIGHTSGRADE_LIST[];
extern struct flickytypes_s FLICKYTYPES[];
extern actionpointer_t actionpointers[]; // Array mapping action names to action functions.
extern const char *const STATE_LIST[];
extern const char *const MOBJTYPE_LIST[];
extern const char *const MOBJFLAG_LIST[];
extern const char *const MOBJFLAG2_LIST[]; // \tMF2_(\S+).*// (.+) --> \t"\1", // \2
extern const char *const MOBJEFLAG_LIST[];
extern const char *const MAPTHINGFLAG_LIST[4];
extern const char *const PLAYERFLAG_LIST[];
extern const char *const GAMETYPERULE_LIST[];
extern const char *const ML_LIST[16]; // Linedef flags
extern const char *COLOR_ENUMS[];
extern const char *const POWERS_LIST[];
extern const char *const HUDITEMS_LIST[];
extern const char *const MENUTYPES_LIST[];
extern struct int_const_s const INT_CONST[];
#endif

File diff suppressed because it is too large Load diff

View file

@ -33,13 +33,15 @@ void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump, boolean mainfile);
void DEH_Check(void); void DEH_Check(void);
fixed_t get_number(const char *word); fixed_t get_number(const char *word);
FUNCPRINTF void deh_warning(const char *first, ...);
boolean LUA_SetLuaAction(void *state, const char *actiontocompare); void deh_strlcpy(char *dst, const char *src, size_t size, const char *warntext);
const char *LUA_GetActionName(void *action);
void LUA_SetActionByName(void *state, const char *actiontocompare);
extern boolean deh_loaded; extern boolean deh_loaded;
extern boolean gamedataadded;
extern boolean titlechanged;
extern boolean introchanged;
#define MAXRECURSION 30 #define MAXRECURSION 30
extern const char *superactions[MAXRECURSION]; extern const char *superactions[MAXRECURSION];
extern UINT8 superstack; extern UINT8 superstack;
@ -60,4 +62,5 @@ typedef struct
} MYFILE; } MYFILE;
#define myfeof(a) (a->data + a->size <= a->curpos) #define myfeof(a) (a->data + a->size <= a->curpos)
char *myfgets(char *buf, size_t bufsize, MYFILE *f); char *myfgets(char *buf, size_t bufsize, MYFILE *f);
char *myhashfgets(char *buf, size_t bufsize, MYFILE *f);
#endif #endif

View file

@ -23,6 +23,7 @@
// Some global defines, that configure the game. // Some global defines, that configure the game.
#include "doomdef.h" #include "doomdef.h"
#include "taglist.h"
#include "m_fixed.h" // See the mapthing_t scale. #include "m_fixed.h" // See the mapthing_t scale.
// //
@ -208,11 +209,10 @@ typedef struct
UINT16 options; UINT16 options;
INT16 z; INT16 z;
UINT8 extrainfo; UINT8 extrainfo;
taglist_t tags;
fixed_t scale; fixed_t scale;
INT16 tag;
INT32 args[NUMMAPTHINGARGS]; INT32 args[NUMMAPTHINGARGS];
char *stringargs[NUMMAPTHINGSTRINGARGS]; char *stringargs[NUMMAPTHINGSTRINGARGS];
struct mobj_s *mobj; struct mobj_s *mobj;
} mapthing_t; } mapthing_t;

View file

@ -628,9 +628,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// \note Required for proper collision with moving sloped surfaces that have sector specials on them. /// \note Required for proper collision with moving sloped surfaces that have sector specials on them.
#define SECTORSPECIALSAFTERTHINK #define SECTORSPECIALSAFTERTHINK
/// Cache patches in Lua in a way that renderer switching will work flawlessly.
//#define LUA_PATCH_SAFETY
/// Sprite rotation /// Sprite rotation
#define ROTSPRITE #define ROTSPRITE
#define ROTANGLES 72 // Needs to be a divisor of 360 (45, 60, 90, 120...) #define ROTANGLES 72 // Needs to be a divisor of 360 (45, 60, 90, 120...)

View file

@ -410,7 +410,7 @@ enum GameType
GT_LASTFREESLOT = GT_FIRSTFREESLOT + NUMGAMETYPEFREESLOTS - 1, GT_LASTFREESLOT = GT_FIRSTFREESLOT + NUMGAMETYPEFREESLOTS - 1,
NUMGAMETYPES NUMGAMETYPES
}; };
// If you alter this list, update dehacked.c, MISC_ChangeGameTypeMenu in m_menu.c, and Gametype_Names in g_game.c // If you alter this list, update deh_tables.c, MISC_ChangeGameTypeMenu in m_menu.c, and Gametype_Names in g_game.c
// Gametype rules // Gametype rules
enum GameTypeRules enum GameTypeRules

View file

@ -3,6 +3,7 @@
#include "../i_video.h" #include "../i_video.h"
rendermode_t rendermode = render_none; rendermode_t rendermode = render_none;
rendermode_t chosenrendermode = render_none;
boolean highcolor = false; boolean highcolor = false;
@ -40,8 +41,15 @@ INT32 VID_SetMode(INT32 modenum)
return 0; return 0;
} }
void VID_CheckRenderer(void) {} boolean VID_CheckRenderer(void)
void VID_CheckGLLoaded(rendermode_t oldrender) {} {
return false;
}
void VID_CheckGLLoaded(rendermode_t oldrender)
{
(void)oldrender;
}
const char *VID_GetModeName(INT32 modenum) const char *VID_GetModeName(INT32 modenum)
{ {

View file

@ -533,78 +533,78 @@ static void F_IntroDrawScene(void)
bgxoffs = 28; bgxoffs = 28;
break; break;
case 1: case 1:
background = W_CachePatchName("INTRO1", PU_PATCH); background = W_CachePatchName("INTRO1", PU_PATCH_LOWPRIORITY);
break; break;
case 2: case 2:
background = W_CachePatchName("INTRO2", PU_PATCH); background = W_CachePatchName("INTRO2", PU_PATCH_LOWPRIORITY);
break; break;
case 3: case 3:
background = W_CachePatchName("INTRO3", PU_PATCH); background = W_CachePatchName("INTRO3", PU_PATCH_LOWPRIORITY);
break; break;
case 4: case 4:
background = W_CachePatchName("INTRO4", PU_PATCH); background = W_CachePatchName("INTRO4", PU_PATCH_LOWPRIORITY);
break; break;
case 5: case 5:
if (intro_curtime >= 5*TICRATE) if (intro_curtime >= 5*TICRATE)
background = W_CachePatchName("RADAR", PU_PATCH); background = W_CachePatchName("RADAR", PU_PATCH_LOWPRIORITY);
else else
background = W_CachePatchName("DRAT", PU_PATCH); background = W_CachePatchName("DRAT", PU_PATCH_LOWPRIORITY);
break; break;
case 6: case 6:
background = W_CachePatchName("INTRO6", PU_PATCH); background = W_CachePatchName("INTRO6", PU_PATCH_LOWPRIORITY);
cx = 180; cx = 180;
cy = 8; cy = 8;
break; break;
case 7: case 7:
{ {
if (intro_curtime >= 7*TICRATE + ((TICRATE/7)*2)) if (intro_curtime >= 7*TICRATE + ((TICRATE/7)*2))
background = W_CachePatchName("SGRASS5", PU_PATCH); background = W_CachePatchName("SGRASS5", PU_PATCH_LOWPRIORITY);
else if (intro_curtime >= 7*TICRATE + (TICRATE/7)) else if (intro_curtime >= 7*TICRATE + (TICRATE/7))
background = W_CachePatchName("SGRASS4", PU_PATCH); background = W_CachePatchName("SGRASS4", PU_PATCH_LOWPRIORITY);
else if (intro_curtime >= 7*TICRATE) else if (intro_curtime >= 7*TICRATE)
background = W_CachePatchName("SGRASS3", PU_PATCH); background = W_CachePatchName("SGRASS3", PU_PATCH_LOWPRIORITY);
else if (intro_curtime >= 6*TICRATE) else if (intro_curtime >= 6*TICRATE)
background = W_CachePatchName("SGRASS2", PU_PATCH); background = W_CachePatchName("SGRASS2", PU_PATCH_LOWPRIORITY);
else else
background = W_CachePatchName("SGRASS1", PU_PATCH); background = W_CachePatchName("SGRASS1", PU_PATCH_LOWPRIORITY);
break; break;
} }
case 8: case 8:
background = W_CachePatchName("WATCHING", PU_PATCH); background = W_CachePatchName("WATCHING", PU_PATCH_LOWPRIORITY);
break; break;
case 9: case 9:
background = W_CachePatchName("ZOOMING", PU_PATCH); background = W_CachePatchName("ZOOMING", PU_PATCH_LOWPRIORITY);
break; break;
case 10: case 10:
break; break;
case 11: case 11:
background = W_CachePatchName("INTRO5", PU_PATCH); background = W_CachePatchName("INTRO5", PU_PATCH_LOWPRIORITY);
break; break;
case 12: case 12:
background = W_CachePatchName("REVENGE", PU_PATCH); background = W_CachePatchName("REVENGE", PU_PATCH_LOWPRIORITY);
cx = 208; cx = 208;
cy = 8; cy = 8;
break; break;
case 13: case 13:
background = W_CachePatchName("CONFRONT", PU_PATCH); background = W_CachePatchName("CONFRONT", PU_PATCH_LOWPRIORITY);
cy += 48; cy += 48;
break; break;
case 14: case 14:
background = W_CachePatchName("TAILSSAD", PU_PATCH); background = W_CachePatchName("TAILSSAD", PU_PATCH_LOWPRIORITY);
bgxoffs = 144; bgxoffs = 144;
cx = 8; cx = 8;
cy = 8; cy = 8;
break; break;
case 15: case 15:
if (intro_curtime >= 7*TICRATE) if (intro_curtime >= 7*TICRATE)
background = W_CachePatchName("SONICDO2", PU_PATCH); background = W_CachePatchName("SONICDO2", PU_PATCH_LOWPRIORITY);
else else
background = W_CachePatchName("SONICDO1", PU_PATCH); background = W_CachePatchName("SONICDO1", PU_PATCH_LOWPRIORITY);
cx = 224; cx = 224;
cy = 8; cy = 8;
break; break;
case 16: case 16:
background = W_CachePatchName("INTRO7", PU_PATCH); background = W_CachePatchName("INTRO7", PU_PATCH_LOWPRIORITY);
break; break;
default: default:
break; break;
@ -635,7 +635,7 @@ static void F_IntroDrawScene(void)
strncpy(stjrintro, "STJRI029", 9); strncpy(stjrintro, "STJRI029", 9);
S_ChangeMusicInternal("_stjr", false); S_ChangeMusicInternal("_stjr", false);
background = W_CachePatchName(stjrintro, PU_PATCH); background = W_CachePatchName(stjrintro, PU_PATCH_LOWPRIORITY);
wipestyleflags = WSF_FADEIN; wipestyleflags = WSF_FADEIN;
F_WipeStartScreen(); F_WipeStartScreen();
F_TryColormapFade(31); F_TryColormapFade(31);
@ -646,7 +646,7 @@ static void F_IntroDrawScene(void)
if (!WipeInAction) // Draw the patch if not in a wipe if (!WipeInAction) // Draw the patch if not in a wipe
{ {
background = W_CachePatchName(stjrintro, PU_PATCH); background = W_CachePatchName(stjrintro, PU_PATCH_LOWPRIORITY);
V_DrawSmallScaledPatch(bgxoffs, 84, 0, background); V_DrawSmallScaledPatch(bgxoffs, 84, 0, background);
} }
} }
@ -656,27 +656,27 @@ static void F_IntroDrawScene(void)
if (timetonext > 5*TICRATE && timetonext < 6*TICRATE) if (timetonext > 5*TICRATE && timetonext < 6*TICRATE)
{ {
if (!(finalecount & 3)) if (!(finalecount & 3))
background = W_CachePatchName("BRITEGG1", PU_PATCH); background = W_CachePatchName("BRITEGG1", PU_PATCH_LOWPRIORITY);
else else
background = W_CachePatchName("DARKEGG1", PU_PATCH); background = W_CachePatchName("DARKEGG1", PU_PATCH_LOWPRIORITY);
V_DrawSmallScaledPatch(0, 0, 0, background); V_DrawSmallScaledPatch(0, 0, 0, background);
} }
else if (timetonext > 3*TICRATE && timetonext < 4*TICRATE) else if (timetonext > 3*TICRATE && timetonext < 4*TICRATE)
{ {
if (!(finalecount & 3)) if (!(finalecount & 3))
background = W_CachePatchName("BRITEGG2", PU_PATCH); background = W_CachePatchName("BRITEGG2", PU_PATCH_LOWPRIORITY);
else else
background = W_CachePatchName("DARKEGG2", PU_PATCH); background = W_CachePatchName("DARKEGG2", PU_PATCH_LOWPRIORITY);
V_DrawSmallScaledPatch(0, 0, 0, background); V_DrawSmallScaledPatch(0, 0, 0, background);
} }
else if (timetonext > 1*TICRATE && timetonext < 2*TICRATE) else if (timetonext > 1*TICRATE && timetonext < 2*TICRATE)
{ {
if (!(finalecount & 3)) if (!(finalecount & 3))
background = W_CachePatchName("BRITEGG3", PU_PATCH); background = W_CachePatchName("BRITEGG3", PU_PATCH_LOWPRIORITY);
else else
background = W_CachePatchName("DARKEGG3", PU_PATCH); background = W_CachePatchName("DARKEGG3", PU_PATCH_LOWPRIORITY);
V_DrawSmallScaledPatch(0, 0, 0, background); V_DrawSmallScaledPatch(0, 0, 0, background);
} }
@ -708,79 +708,79 @@ static void F_IntroDrawScene(void)
knucklesx += sonicx; knucklesx += sonicx;
sonicx += P_ReturnThrustX(NULL, finalecount * ANG10, 3); sonicx += P_ReturnThrustX(NULL, finalecount * ANG10, 3);
V_DrawSmallScaledPatch(skyx, 0, 0, (patch = W_CachePatchName("INTROSKY", PU_PATCH))); V_DrawSmallScaledPatch(skyx, 0, 0, (patch = W_CachePatchName("INTROSKY", PU_PATCH_LOWPRIORITY)));
V_DrawSmallScaledPatch(skyx - 320, 0, 0, patch); V_DrawSmallScaledPatch(skyx - 320, 0, 0, patch);
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
V_DrawSmallScaledPatch(grassx, 0, 0, (patch = W_CachePatchName("INTROGRS", PU_PATCH))); V_DrawSmallScaledPatch(grassx, 0, 0, (patch = W_CachePatchName("INTROGRS", PU_PATCH_LOWPRIORITY)));
V_DrawSmallScaledPatch(grassx - 320, 0, 0, patch); V_DrawSmallScaledPatch(grassx - 320, 0, 0, patch);
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
if (finalecount & 1) if (finalecount & 1)
{ {
// Sonic // Sonic
V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN2", PU_PATCH))); V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
// Appendages // Appendages
if (finalecount & 2) if (finalecount & 2)
{ {
// Sonic's feet // Sonic's feet
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT4", PU_PATCH))); V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT4", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
// Tails' tails // Tails' tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH))); V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
} }
else else
{ {
// Sonic's feet // Sonic's feet
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT2", PU_PATCH))); V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
// Tails' tails // Tails' tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH))); V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
} }
// Tails // Tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY2", PU_PATCH))); V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
// Knuckles // Knuckles
V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE2", PU_PATCH))); V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
} }
else else
{ {
// Sonic // Sonic
V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN1", PU_PATCH))); V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
// Appendages // Appendages
if (finalecount & 2) if (finalecount & 2)
{ {
// Sonic's feet // Sonic's feet
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT3", PU_PATCH))); V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT3", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
// Tails' tails // Tails' tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH))); V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
} }
else else
{ {
// Sonic's feet // Sonic's feet
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT1", PU_PATCH))); V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
// Tails' tails // Tails' tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH))); V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
} }
// Tails // Tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY1", PU_PATCH))); V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
// Knuckles // Knuckles
V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE1", PU_PATCH))); V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
} }
@ -813,8 +813,8 @@ static void F_IntroDrawScene(void)
y += (30*(FRACUNIT-scale)); y += (30*(FRACUNIT-scale));
} }
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (worktics % 35)), PU_PATCH); rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (worktics % 35)), PU_PATCH_LOWPRIORITY);
glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(worktics & 1)), PU_PATCH); glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(worktics & 1)), PU_PATCH_LOWPRIORITY);
if (worktics >= 5) if (worktics >= 5)
trans = (worktics-5)>>1; trans = (worktics-5)>>1;
@ -934,7 +934,7 @@ void F_IntroDrawer(void)
{ {
if (intro_scenenum == 5 && intro_curtime == 5*TICRATE) if (intro_scenenum == 5 && intro_curtime == 5*TICRATE)
{ {
patch_t *radar = W_CachePatchName("RADAR", PU_PATCH); patch_t *radar = W_CachePatchName("RADAR", PU_PATCH_LOWPRIORITY);
F_WipeStartScreen(); F_WipeStartScreen();
F_WipeColorFill(31); F_WipeColorFill(31);
@ -947,7 +947,7 @@ void F_IntroDrawer(void)
} }
else if (intro_scenenum == 7 && intro_curtime == 6*TICRATE) // Force a wipe here else if (intro_scenenum == 7 && intro_curtime == 6*TICRATE) // Force a wipe here
{ {
patch_t *grass = W_CachePatchName("SGRASS2", PU_PATCH); patch_t *grass = W_CachePatchName("SGRASS2", PU_PATCH_LOWPRIORITY);
F_WipeStartScreen(); F_WipeStartScreen();
F_WipeColorFill(31); F_WipeColorFill(31);
@ -960,7 +960,7 @@ void F_IntroDrawer(void)
} }
/*else if (intro_scenenum == 11 && intro_curtime == 7*TICRATE) /*else if (intro_scenenum == 11 && intro_curtime == 7*TICRATE)
{ {
patch_t *confront = W_CachePatchName("CONFRONT", PU_PATCH); patch_t *confront = W_CachePatchName("CONFRONT", PU_PATCH_LOWPRIORITY);
F_WipeStartScreen(); F_WipeStartScreen();
F_WipeColorFill(31); F_WipeColorFill(31);
@ -973,7 +973,7 @@ void F_IntroDrawer(void)
}*/ }*/
if (intro_scenenum == 15 && intro_curtime == 7*TICRATE) if (intro_scenenum == 15 && intro_curtime == 7*TICRATE)
{ {
patch_t *sdo = W_CachePatchName("SONICDO2", PU_PATCH); patch_t *sdo = W_CachePatchName("SONICDO2", PU_PATCH_LOWPRIORITY);
F_WipeStartScreen(); F_WipeStartScreen();
F_WipeColorFill(31); F_WipeColorFill(31);
@ -1303,14 +1303,14 @@ void F_CreditDrawer(void)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
// Zig Zagz // Zig Zagz
V_DrawScaledPatch(-16, zagpos, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH)); V_DrawScaledPatch(-16, zagpos, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY));
V_DrawScaledPatch(-16, zagpos - 320, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH)); V_DrawScaledPatch(-16, zagpos - 320, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY));
V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH)); V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY));
V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos - 320, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH)); V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos - 320, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY));
// Draw background pictures first // Draw background pictures first
for (i = 0; credits_pics[i].patch; i++) for (i = 0; credits_pics[i].patch; i++)
V_DrawSciencePatch(credits_pics[i].x<<FRACBITS, (280<<FRACBITS) + (((i*credits_height)<<FRACBITS)/(credits_numpics)) - 4*(animtimer<<FRACBITS)/5, 0, W_CachePatchName(credits_pics[i].patch, PU_PATCH), FRACUNIT>>1); V_DrawSciencePatch(credits_pics[i].x<<FRACBITS, (280<<FRACBITS) + (((i*credits_height)<<FRACBITS)/(credits_numpics)) - 4*(animtimer<<FRACBITS)/5, 0, W_CachePatchName(credits_pics[i].patch, PU_PATCH_LOWPRIORITY), FRACUNIT>>1);
// Dim the background // Dim the background
V_DrawFadeScreen(0xFF00, 16); V_DrawFadeScreen(0xFF00, 16);
@ -1519,14 +1519,14 @@ void F_GameEvaluationDrawer(void)
if (goodending) if (goodending)
{ {
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (finalecount % 35)), PU_PATCH); rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (finalecount % 35)), PU_PATCH_LOWPRIORITY);
glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(finalecount & 1)), PU_PATCH); glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(finalecount & 1)), PU_PATCH_LOWPRIORITY);
x -= FRACUNIT; x -= FRACUNIT;
} }
else else
{ {
rockpat = W_CachePatchName("ROID0000", PU_LEVEL); rockpat = W_CachePatchName("ROID0000", PU_PATCH_LOWPRIORITY);
glow = W_CachePatchName(va("ENDGLOW%.1d", (finalecount & 1)), PU_PATCH); glow = W_CachePatchName(va("ENDGLOW%.1d", (finalecount & 1)), PU_PATCH_LOWPRIORITY);
} }
if (finalecount >= 5) if (finalecount >= 5)
@ -1558,20 +1558,20 @@ void F_GameEvaluationDrawer(void)
// if j == 0 - alternate between 0 and 1 // if j == 0 - alternate between 0 and 1
// 1 - 1 and 2 // 1 - 1 and 2
// 2 - 2 and not rendered // 2 - 2 and not rendered
V_DrawFixedPatch(x+sparkloffs[j-1][0], y+sparkloffs[j-1][1], FRACUNIT, 0, W_CachePatchName(va("ENDSPKL%.1d", (j - ((sparklloop & 1) ? 0 : 1))), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_AQUA, GTC_CACHE)); V_DrawFixedPatch(x+sparkloffs[j-1][0], y+sparkloffs[j-1][1], FRACUNIT, 0, W_CachePatchName(va("ENDSPKL%.1d", (j - ((sparklloop & 1) ? 0 : 1))), PU_PATCH_LOWPRIORITY), R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_AQUA, GTC_CACHE));
} }
j--; j--;
} }
} }
else else
{ {
patch_t *eggrock = W_CachePatchName("ENDEGRK5", PU_PATCH); patch_t *eggrock = W_CachePatchName("ENDEGRK5", PU_PATCH_LOWPRIORITY);
V_DrawFixedPatch(x, y, scale, 0, eggrock, colormap[0]); V_DrawFixedPatch(x, y, scale, 0, eggrock, colormap[0]);
if (trans < 10) if (trans < 10)
V_DrawFixedPatch(x, y, scale, trans<<V_ALPHASHIFT, eggrock, colormap[1]); V_DrawFixedPatch(x, y, scale, trans<<V_ALPHASHIFT, eggrock, colormap[1]);
else if (sparklloop) else if (sparklloop)
V_DrawFixedPatch(x, y, scale, (10-sparklloop)<<V_ALPHASHIFT, V_DrawFixedPatch(x, y, scale, (10-sparklloop)<<V_ALPHASHIFT,
W_CachePatchName("ENDEGRK0", PU_PATCH), colormap[1]); W_CachePatchName("ENDEGRK0", PU_PATCH_LOWPRIORITY), colormap[1]);
} }
} }
@ -1585,7 +1585,7 @@ void F_GameEvaluationDrawer(void)
eemeralds_cur += (360<<FRACBITS)/7; eemeralds_cur += (360<<FRACBITS)/7;
patchname[4] = 'A'+(char)i; patchname[4] = 'A'+(char)i;
V_DrawFixedPatch(x, y, FRACUNIT, ((emeralds & (1<<i)) ? 0 : V_80TRANS), W_CachePatchName(patchname, PU_PATCH), NULL); V_DrawFixedPatch(x, y, FRACUNIT, ((emeralds & (1<<i)) ? 0 : V_80TRANS), W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY), NULL);
} }
V_DrawCreditString((BASEVIDWIDTH - V_CreditStringWidth(endingtext))<<(FRACBITS-1), (BASEVIDHEIGHT-100)<<(FRACBITS-1), 0, endingtext); V_DrawCreditString((BASEVIDWIDTH - V_CreditStringWidth(endingtext))<<(FRACBITS-1), (BASEVIDHEIGHT-100)<<(FRACBITS-1), 0, endingtext);
@ -1714,32 +1714,32 @@ void F_GameEvaluationTicker(void)
static void F_CacheEnding(void) static void F_CacheEnding(void)
{ {
endbrdr[1] = W_CachePatchName("ENDBRDR1", PU_PATCH); endbrdr[1] = W_CachePatchName("ENDBRDR1", PU_PATCH_LOWPRIORITY);
endegrk[0] = W_CachePatchName("ENDEGRK0", PU_PATCH); endegrk[0] = W_CachePatchName("ENDEGRK0", PU_PATCH_LOWPRIORITY);
endegrk[1] = W_CachePatchName("ENDEGRK1", PU_PATCH); endegrk[1] = W_CachePatchName("ENDEGRK1", PU_PATCH_LOWPRIORITY);
endglow[0] = W_CachePatchName("ENDGLOW0", PU_PATCH); endglow[0] = W_CachePatchName("ENDGLOW0", PU_PATCH_LOWPRIORITY);
endglow[1] = W_CachePatchName("ENDGLOW1", PU_PATCH); endglow[1] = W_CachePatchName("ENDGLOW1", PU_PATCH_LOWPRIORITY);
endbgsp[0] = W_CachePatchName("ENDBGSP0", PU_PATCH); endbgsp[0] = W_CachePatchName("ENDBGSP0", PU_PATCH_LOWPRIORITY);
endbgsp[1] = W_CachePatchName("ENDBGSP1", PU_PATCH); endbgsp[1] = W_CachePatchName("ENDBGSP1", PU_PATCH_LOWPRIORITY);
endbgsp[2] = W_CachePatchName("ENDBGSP2", PU_PATCH); endbgsp[2] = W_CachePatchName("ENDBGSP2", PU_PATCH_LOWPRIORITY);
endspkl[0] = W_CachePatchName("ENDSPKL0", PU_PATCH); endspkl[0] = W_CachePatchName("ENDSPKL0", PU_PATCH_LOWPRIORITY);
endspkl[1] = W_CachePatchName("ENDSPKL1", PU_PATCH); endspkl[1] = W_CachePatchName("ENDSPKL1", PU_PATCH_LOWPRIORITY);
endspkl[2] = W_CachePatchName("ENDSPKL2", PU_PATCH); endspkl[2] = W_CachePatchName("ENDSPKL2", PU_PATCH_LOWPRIORITY);
endxpld[0] = W_CachePatchName("ENDXPLD0", PU_PATCH); endxpld[0] = W_CachePatchName("ENDXPLD0", PU_PATCH_LOWPRIORITY);
endxpld[1] = W_CachePatchName("ENDXPLD1", PU_PATCH); endxpld[1] = W_CachePatchName("ENDXPLD1", PU_PATCH_LOWPRIORITY);
endxpld[2] = W_CachePatchName("ENDXPLD2", PU_PATCH); endxpld[2] = W_CachePatchName("ENDXPLD2", PU_PATCH_LOWPRIORITY);
endxpld[3] = W_CachePatchName("ENDXPLD3", PU_PATCH); endxpld[3] = W_CachePatchName("ENDXPLD3", PU_PATCH_LOWPRIORITY);
endescp[0] = W_CachePatchName("ENDESCP0", PU_PATCH); endescp[0] = W_CachePatchName("ENDESCP0", PU_PATCH_LOWPRIORITY);
endescp[1] = W_CachePatchName("ENDESCP1", PU_PATCH); endescp[1] = W_CachePatchName("ENDESCP1", PU_PATCH_LOWPRIORITY);
endescp[2] = W_CachePatchName("ENDESCP2", PU_PATCH); endescp[2] = W_CachePatchName("ENDESCP2", PU_PATCH_LOWPRIORITY);
endescp[3] = W_CachePatchName("ENDESCP3", PU_PATCH); endescp[3] = W_CachePatchName("ENDESCP3", PU_PATCH_LOWPRIORITY);
endescp[4] = W_CachePatchName("ENDESCP4", PU_PATCH); endescp[4] = W_CachePatchName("ENDESCP4", PU_PATCH_LOWPRIORITY);
// so we only need to check once // so we only need to check once
if ((goodending = ALL7EMERALDS(emeralds))) if ((goodending = ALL7EMERALDS(emeralds)))
@ -1752,41 +1752,41 @@ static void F_CacheEnding(void)
sprdef = &skins[skinnum].sprites[SPR2_XTRA]; sprdef = &skins[skinnum].sprites[SPR2_XTRA];
// character head, skin specific // character head, skin specific
sprframe = &sprdef->spriteframes[XTRA_ENDING]; sprframe = &sprdef->spriteframes[XTRA_ENDING];
endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH_LOWPRIORITY);
sprframe = &sprdef->spriteframes[XTRA_ENDING+1]; sprframe = &sprdef->spriteframes[XTRA_ENDING+1];
endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH_LOWPRIORITY);
sprframe = &sprdef->spriteframes[XTRA_ENDING+2]; sprframe = &sprdef->spriteframes[XTRA_ENDING+2];
endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH_LOWPRIORITY);
} }
else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this) else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this)
{ {
endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_PATCH); endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_PATCH_LOWPRIORITY);
endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_PATCH); endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_PATCH_LOWPRIORITY);
endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_PATCH); endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_PATCH_LOWPRIORITY);
} }
endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_PATCH); endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_PATCH_LOWPRIORITY);
} }
else else
{ {
// eggman, skin nonspecific // eggman, skin nonspecific
endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_PATCH); endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_PATCH_LOWPRIORITY);
endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_PATCH); endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_PATCH_LOWPRIORITY);
endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_PATCH); endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_PATCH_LOWPRIORITY);
endbrdr[0] = W_CachePatchName("ENDBRDR0", PU_LEVEL); endbrdr[0] = W_CachePatchName("ENDBRDR0", PU_PATCH_LOWPRIORITY);
} }
} }
static void F_CacheGoodEnding(void) static void F_CacheGoodEnding(void)
{ {
endegrk[0] = W_CachePatchName("ENDEGRK2", PU_PATCH); endegrk[0] = W_CachePatchName("ENDEGRK2", PU_PATCH_LOWPRIORITY);
endegrk[1] = W_CachePatchName("ENDEGRK3", PU_PATCH); endegrk[1] = W_CachePatchName("ENDEGRK3", PU_PATCH_LOWPRIORITY);
endglow[0] = W_CachePatchName("ENDGLOW2", PU_PATCH); endglow[0] = W_CachePatchName("ENDGLOW2", PU_PATCH_LOWPRIORITY);
endglow[1] = W_CachePatchName("ENDGLOW3", PU_PATCH); endglow[1] = W_CachePatchName("ENDGLOW3", PU_PATCH_LOWPRIORITY);
endxpld[0] = W_CachePatchName("ENDEGRK4", PU_PATCH); endxpld[0] = W_CachePatchName("ENDEGRK4", PU_PATCH_LOWPRIORITY);
} }
void F_StartEnding(void) void F_StartEnding(void)
@ -1843,17 +1843,10 @@ void F_EndingDrawer(void)
INT32 x, y, i, j, parallaxticker; INT32 x, y, i, j, parallaxticker;
patch_t *rockpat; patch_t *rockpat;
if (needpatchrecache)
{
F_CacheEnding();
if (goodending && finalecount >= INFLECTIONPOINT) // time to swap some assets
F_CacheGoodEnding();
}
if (!goodending || finalecount < INFLECTIONPOINT) if (!goodending || finalecount < INFLECTIONPOINT)
rockpat = W_CachePatchName("ROID0000", PU_PATCH); rockpat = W_CachePatchName("ROID0000", PU_PATCH_LOWPRIORITY);
else else
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - ((finalecount - INFLECTIONPOINT) % 35)), PU_PATCH); rockpat = W_CachePatchName(va("ROID00%.2d", 34 - ((finalecount - INFLECTIONPOINT) % 35)), PU_PATCH_LOWPRIORITY);
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
@ -2190,7 +2183,7 @@ void F_EndingDrawer(void)
eemeralds_cur[0] += (360<<FRACBITS)/7; eemeralds_cur[0] += (360<<FRACBITS)/7;
patchname[4] = 'A'+(char)i; patchname[4] = 'A'+(char)i;
V_DrawFixedPatch(x, y, FRACUNIT, 0, W_CachePatchName(patchname, PU_LEVEL), NULL); V_DrawFixedPatch(x, y, FRACUNIT, 0, W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY), NULL);
} }
} // if (goodending... } // if (goodending...
} // (finalecount > 20) } // (finalecount > 20)
@ -2337,14 +2330,14 @@ void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname)
if (!scrollxspeed && !scrollyspeed) if (!scrollxspeed && !scrollyspeed)
{ {
V_DrawPatchFill(W_CachePatchName(patchname, PU_PATCH)); V_DrawPatchFill(W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY));
return; return;
} }
pat = W_CachePatchName(patchname, PU_PATCH); pat = W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY);
patwidth = SHORT(pat->width); patwidth = pat->width;
patheight = SHORT(pat->height); patheight = pat->height;
pw = patwidth * dupz; pw = patwidth * dupz;
ph = patheight * dupz; ph = patheight * dupz;
@ -2380,7 +2373,7 @@ void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname)
lumpnum = W_CheckNumForName(name); \ lumpnum = W_CheckNumForName(name); \
if (lumpnum != LUMPERROR) \ if (lumpnum != LUMPERROR) \
{ \ { \
arr[0] = W_CachePatchName(name, PU_LEVEL); \ arr[0] = W_CachePatchName(name, PU_PATCH_LOWPRIORITY); \
arr[min(1, maxf-1)] = 0; \ arr[min(1, maxf-1)] = 0; \
} \ } \
else if (strlen(name) <= 6) \ else if (strlen(name) <= 6) \
@ -2393,7 +2386,7 @@ else if (strlen(name) <= 6) \
lumpname[8] = 0; \ lumpname[8] = 0; \
lumpnum = W_CheckNumForName(lumpname); \ lumpnum = W_CheckNumForName(lumpname); \
if (lumpnum != LUMPERROR) \ if (lumpnum != LUMPERROR) \
arr[i] = W_CachePatchName(lumpname, PU_LEVEL); \ arr[i] = W_CachePatchName(lumpname, PU_PATCH_LOWPRIORITY); \
else \ else \
break; \ break; \
} \ } \
@ -2408,21 +2401,21 @@ static void F_CacheTitleScreen(void)
{ {
case TTMODE_OLD: case TTMODE_OLD:
case TTMODE_NONE: case TTMODE_NONE:
ttbanner = W_CachePatchName("TTBANNER", PU_LEVEL); ttbanner = W_CachePatchName("TTBANNER", PU_PATCH_LOWPRIORITY);
ttwing = W_CachePatchName("TTWING", PU_LEVEL); ttwing = W_CachePatchName("TTWING", PU_PATCH_LOWPRIORITY);
ttsonic = W_CachePatchName("TTSONIC", PU_LEVEL); ttsonic = W_CachePatchName("TTSONIC", PU_PATCH_LOWPRIORITY);
ttswave1 = W_CachePatchName("TTSWAVE1", PU_LEVEL); ttswave1 = W_CachePatchName("TTSWAVE1", PU_PATCH_LOWPRIORITY);
ttswave2 = W_CachePatchName("TTSWAVE2", PU_LEVEL); ttswave2 = W_CachePatchName("TTSWAVE2", PU_PATCH_LOWPRIORITY);
ttswip1 = W_CachePatchName("TTSWIP1", PU_LEVEL); ttswip1 = W_CachePatchName("TTSWIP1", PU_PATCH_LOWPRIORITY);
ttsprep1 = W_CachePatchName("TTSPREP1", PU_LEVEL); ttsprep1 = W_CachePatchName("TTSPREP1", PU_PATCH_LOWPRIORITY);
ttsprep2 = W_CachePatchName("TTSPREP2", PU_LEVEL); ttsprep2 = W_CachePatchName("TTSPREP2", PU_PATCH_LOWPRIORITY);
ttspop1 = W_CachePatchName("TTSPOP1", PU_LEVEL); ttspop1 = W_CachePatchName("TTSPOP1", PU_PATCH_LOWPRIORITY);
ttspop2 = W_CachePatchName("TTSPOP2", PU_LEVEL); ttspop2 = W_CachePatchName("TTSPOP2", PU_PATCH_LOWPRIORITY);
ttspop3 = W_CachePatchName("TTSPOP3", PU_LEVEL); ttspop3 = W_CachePatchName("TTSPOP3", PU_PATCH_LOWPRIORITY);
ttspop4 = W_CachePatchName("TTSPOP4", PU_LEVEL); ttspop4 = W_CachePatchName("TTSPOP4", PU_PATCH_LOWPRIORITY);
ttspop5 = W_CachePatchName("TTSPOP5", PU_LEVEL); ttspop5 = W_CachePatchName("TTSPOP5", PU_PATCH_LOWPRIORITY);
ttspop6 = W_CachePatchName("TTSPOP6", PU_LEVEL); ttspop6 = W_CachePatchName("TTSPOP6", PU_PATCH_LOWPRIORITY);
ttspop7 = W_CachePatchName("TTSPOP7", PU_LEVEL); ttspop7 = W_CachePatchName("TTSPOP7", PU_PATCH_LOWPRIORITY);
break; break;
// don't load alacroix gfx yet; we do that upon first draw. // don't load alacroix gfx yet; we do that upon first draw.
@ -2542,7 +2535,7 @@ void F_StartTitleScreen(void)
static void F_UnloadAlacroixGraphics(SINT8 oldttscale) static void F_UnloadAlacroixGraphics(SINT8 oldttscale)
{ {
// This all gets freed by PU_LEVEL when exiting the menus. // This all gets freed by PU_PATCH_LOWPRIORITY when exiting the menus.
// When re-visiting the menus (e.g., from exiting in-game), the gfx are force-reloaded. // When re-visiting the menus (e.g., from exiting in-game), the gfx are force-reloaded.
// So leftover addresses here should not be a problem. // So leftover addresses here should not be a problem.
@ -2648,17 +2641,12 @@ static void F_FigureActiveTtScale(void)
SINT8 newttscale = max(1, min(6, vid.dupx)); SINT8 newttscale = max(1, min(6, vid.dupx));
SINT8 oldttscale = activettscale; SINT8 oldttscale = activettscale;
if (needpatchrecache) if (newttscale == testttscale)
ttloaded[0] = ttloaded[1] = ttloaded[2] = ttloaded[3] = ttloaded[4] = ttloaded[5] = 0; return;
else
{
if (newttscale == testttscale)
return;
// We have a new ttscale, so load gfx // We have a new ttscale, so load gfx
if(oldttscale > 0) if(oldttscale > 0)
F_UnloadAlacroixGraphics(oldttscale); F_UnloadAlacroixGraphics(oldttscale);
}
testttscale = newttscale; testttscale = newttscale;
@ -2692,9 +2680,6 @@ void F_TitleScreenDrawer(void)
if (modeattacking) if (modeattacking)
return; // We likely came here from retrying. Don't do a damn thing. return; // We likely came here from retrying. Don't do a damn thing.
if (needpatchrecache && (curttmode != TTMODE_ALACROIX))
F_CacheTitleScreen();
// Draw that sky! // Draw that sky!
if (curbgcolor >= 0) if (curbgcolor >= 0)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor);
@ -3658,7 +3643,7 @@ void F_ContinueDrawer(void)
V_DrawLevelTitle(x - (V_LevelNameWidth("Continue?")>>1), 16, 0, "Continue?"); V_DrawLevelTitle(x - (V_LevelNameWidth("Continue?")>>1), 16, 0, "Continue?");
// Two stars... // Two stars...
patch = W_CachePatchName("CONTSTAR", PU_PATCH); patch = W_CachePatchName("CONTSTAR", PU_PATCH_LOWPRIORITY);
V_DrawScaledPatch(x-32, 160, 0, patch); V_DrawScaledPatch(x-32, 160, 0, patch);
V_DrawScaledPatch(x+32, 160, 0, patch); V_DrawScaledPatch(x+32, 160, 0, patch);
@ -3666,14 +3651,14 @@ void F_ContinueDrawer(void)
if (timeleft > 9) if (timeleft > 9)
{ {
numbuf[7] = '1'; numbuf[7] = '1';
V_DrawScaledPatch(x - 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH)); V_DrawScaledPatch(x - 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH_LOWPRIORITY));
numbuf[7] = '0'; numbuf[7] = '0';
V_DrawScaledPatch(x + 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH)); V_DrawScaledPatch(x + 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH_LOWPRIORITY));
} }
else else
{ {
numbuf[7] = '0'+timeleft; numbuf[7] = '0'+timeleft;
V_DrawScaledPatch(x, 160, 0, W_CachePatchName(numbuf, PU_PATCH)); V_DrawScaledPatch(x, 160, 0, W_CachePatchName(numbuf, PU_PATCH_LOWPRIORITY));
} }
// Draw the continue markers! Show continues. // Draw the continue markers! Show continues.
@ -3702,7 +3687,7 @@ void F_ContinueDrawer(void)
} }
// Spotlight // Spotlight
V_DrawScaledPatch(x, 140, 0, W_CachePatchName("CONTSPOT", PU_PATCH)); V_DrawScaledPatch(x, 140, 0, W_CachePatchName("CONTSPOT", PU_PATCH_LOWPRIORITY));
// warping laser // warping laser
if (continuetime) if (continuetime)
@ -3739,7 +3724,7 @@ void F_ContinueDrawer(void)
#define drawchar(dx, dy, n) {\ #define drawchar(dx, dy, n) {\
sprdef = &contskins[n]->sprites[cont_spr2[n][0]];\ sprdef = &contskins[n]->sprites[cont_spr2[n][0]];\
sprframe = &sprdef->spriteframes[cont_spr2[n][1]];\ sprframe = &sprdef->spriteframes[cont_spr2[n][1]];\
patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_PATCH);\ patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_PATCH_LOWPRIORITY);\
V_DrawFixedPatch((dx), (dy), contskins[n]->highresscale, (sprframe->flip & (1<<cont_spr2[n][2])) ? V_FLIP : 0, patch, contcolormaps[n]);\ V_DrawFixedPatch((dx), (dy), contskins[n]->highresscale, (sprframe->flip & (1<<cont_spr2[n][2])) ? V_FLIP : 0, patch, contcolormaps[n]);\
} }
@ -4004,10 +3989,10 @@ void F_CutsceneDrawer(void)
{ {
if (cutscenes[cutnum]->scene[scenenum].pichires[picnum]) if (cutscenes[cutnum]->scene[scenenum].pichires[picnum])
V_DrawSmallScaledPatch(picxpos, picypos, 0, V_DrawSmallScaledPatch(picxpos, picypos, 0,
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH)); W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY));
else else
V_DrawScaledPatch(picxpos,picypos, 0, V_DrawScaledPatch(picxpos,picypos, 0,
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH)); W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY));
} }
if (dofadenow && rendermode != render_none) if (dofadenow && rendermode != render_none)
@ -4493,10 +4478,10 @@ void F_TextPromptDrawer(void)
{ {
if (textprompts[cutnum]->page[scenenum].pichires[picnum]) if (textprompts[cutnum]->page[scenenum].pichires[picnum])
V_DrawSmallScaledPatch(picxpos, picypos, 0, V_DrawSmallScaledPatch(picxpos, picypos, 0,
W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH)); W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY));
else else
V_DrawScaledPatch(picxpos,picypos, 0, V_DrawScaledPatch(picxpos,picypos, 0,
W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH)); W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY));
} }
// Draw background // Draw background
@ -4506,7 +4491,7 @@ void F_TextPromptDrawer(void)
if (iconlump != LUMPERROR) if (iconlump != LUMPERROR)
{ {
INT32 iconx, icony, scale, scaledsize; INT32 iconx, icony, scale, scaledsize;
patch = W_CachePatchName(textprompts[cutnum]->page[scenenum].iconname, PU_PATCH); patch = W_CachePatchName(textprompts[cutnum]->page[scenenum].iconname, PU_PATCH_LOWPRIORITY);
// scale and center // scale and center
if (patch->width > patch->height) if (patch->width > patch->height)

View file

@ -293,7 +293,7 @@ static void F_DoWipe(fademask_t *fademask)
else else
{ {
// pointer to transtable that this mask would use // pointer to transtable that this mask would use
transtbl = transtables + ((9 - *mask)<<FF_TRANSSHIFT); transtbl = R_GetTranslucencyTable((9 - *mask) + 1);
// DRAWING LOOP // DRAWING LOOP
while (draw_linestogo--) while (draw_linestogo--)

View file

@ -453,8 +453,7 @@ void G_WriteGhostTic(mobj_t *ghost)
WRITEUINT16(demo_p,oldghost.sprite); WRITEUINT16(demo_p,oldghost.sprite);
if (ghostext.flags & EZT_HEIGHT) if (ghostext.flags & EZT_HEIGHT)
{ {
height >>= FRACBITS; WRITEFIXED(demo_p, height);
WRITEINT16(demo_p, height);
} }
ghostext.flags = 0; ghostext.flags = 0;
} }
@ -610,7 +609,7 @@ void G_ConsGhostTic(void)
if (xziptic & EZT_SPRITE) if (xziptic & EZT_SPRITE)
demo_p += sizeof(UINT16); demo_p += sizeof(UINT16);
if (xziptic & EZT_HEIGHT) if (xziptic & EZT_HEIGHT)
demo_p += sizeof(INT16); demo_p += (demoversion < 0x000e) ? sizeof(INT16) : sizeof(fixed_t);
} }
if (ziptic & GZT_FOLLOW) if (ziptic & GZT_FOLLOW)
@ -842,7 +841,7 @@ void G_GhostTicker(void)
g->mo->sprite = READUINT16(g->p); g->mo->sprite = READUINT16(g->p);
if (xziptic & EZT_HEIGHT) if (xziptic & EZT_HEIGHT)
{ {
fixed_t temp = READINT16(g->p)<<FRACBITS; fixed_t temp = (g->version < 0x000e) ? READINT16(g->p)<<FRACBITS : READFIXED(g->p);
g->mo->height = FixedMul(temp, g->mo->scale); g->mo->height = FixedMul(temp, g->mo->scale);
} }
} }
@ -1106,7 +1105,7 @@ void G_ReadMetalTic(mobj_t *metal)
metal->sprite = READUINT16(metal_p); metal->sprite = READUINT16(metal_p);
if (xziptic & EZT_HEIGHT) if (xziptic & EZT_HEIGHT)
{ {
fixed_t temp = READINT16(metal_p)<<FRACBITS; fixed_t temp = (metalversion < 0x000e) ? READINT16(metal_p)<<FRACBITS : READFIXED(metal_p);
metal->height = FixedMul(temp, metal->scale); metal->height = FixedMul(temp, metal->scale);
} }
} }
@ -1293,8 +1292,7 @@ void G_WriteMetalTic(mobj_t *metal)
WRITEUINT16(demo_p,oldmetal.sprite); WRITEUINT16(demo_p,oldmetal.sprite);
if (ghostext.flags & EZT_HEIGHT) if (ghostext.flags & EZT_HEIGHT)
{ {
height >>= FRACBITS; WRITEFIXED(demo_p, height);
WRITEINT16(demo_p, height);
} }
ghostext.flags = 0; ghostext.flags = 0;
} }
@ -1474,8 +1472,8 @@ void G_BeginRecording(void)
WRITEUINT8(demo_p,player->thrustfactor); WRITEUINT8(demo_p,player->thrustfactor);
WRITEUINT8(demo_p,player->accelstart); WRITEUINT8(demo_p,player->accelstart);
WRITEUINT8(demo_p,player->acceleration); WRITEUINT8(demo_p,player->acceleration);
WRITEUINT8(demo_p,player->height>>FRACBITS); WRITEFIXED(demo_p,player->height);
WRITEUINT8(demo_p,player->spinheight>>FRACBITS); WRITEFIXED(demo_p,player->spinheight);
WRITEUINT8(demo_p,player->camerascale>>FRACBITS); WRITEUINT8(demo_p,player->camerascale>>FRACBITS);
WRITEUINT8(demo_p,player->shieldscale>>FRACBITS); WRITEUINT8(demo_p,player->shieldscale>>FRACBITS);
@ -1901,8 +1899,8 @@ void G_DoPlayDemo(char *defdemoname)
thrustfactor = READUINT8(demo_p); thrustfactor = READUINT8(demo_p);
accelstart = READUINT8(demo_p); accelstart = READUINT8(demo_p);
acceleration = READUINT8(demo_p); acceleration = READUINT8(demo_p);
height = (fixed_t)READUINT8(demo_p)<<FRACBITS; height = (demoversion < 0x000e) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
spinheight = (fixed_t)READUINT8(demo_p)<<FRACBITS; spinheight = (demoversion < 0x000e) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
camerascale = (fixed_t)READUINT8(demo_p)<<FRACBITS; camerascale = (fixed_t)READUINT8(demo_p)<<FRACBITS;
shieldscale = (fixed_t)READUINT8(demo_p)<<FRACBITS; shieldscale = (fixed_t)READUINT8(demo_p)<<FRACBITS;
jumpfactor = READFIXED(demo_p); jumpfactor = READFIXED(demo_p);
@ -2150,8 +2148,7 @@ void G_AddGhost(char *defdemoname)
p++; // thrustfactor p++; // thrustfactor
p++; // accelstart p++; // accelstart
p++; // acceleration p++; // acceleration
p++; // height p += (ghostversion < 0x000e) ? 2 : 2 * sizeof(fixed_t); // height and spinheight
p++; // spinheight
p++; // camerascale p++; // camerascale
p++; // shieldscale p++; // shieldscale
p += 4; // jumpfactor p += 4; // jumpfactor

View file

@ -1677,10 +1677,26 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
} }
} }
// Note: Lat originally made the PlayerCmd hook for SRB2 Kart so credit goes to him. // At this point, cmd doesn't contain the final angle yet,
// So we need to temporarily transform it so Lua scripters
// don't need to handle it differently than in other hooks.
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
{
INT16 extra = ticcmd_oldangleturn[forplayer] - player->oldrelangleturn;
INT16 origangle = cmd->angleturn;
INT16 orighookangle = (INT16)(origangle + player->angleturn + extra);
INT16 origaiming = cmd->aiming;
cmd->angleturn = orighookangle;
LUAh_PlayerCmd(player, cmd); LUAh_PlayerCmd(player, cmd);
extra = cmd->angleturn - orighookangle;
cmd->angleturn = origangle + extra;
*myangle += extra << 16;
*myaiming += (cmd->aiming - origaiming) << 16;
}
//Reset away view if a command is given. //Reset away view if a command is given.
if (ssplayer == 1 && (cmd->forwardmove || cmd->sidemove || cmd->buttons) if (ssplayer == 1 && (cmd->forwardmove || cmd->sidemove || cmd->buttons)
&& displayplayer != consoleplayer) && displayplayer != consoleplayer)

View file

@ -25,6 +25,7 @@
#include "../z_zone.h" #include "../z_zone.h"
#include "../v_video.h" #include "../v_video.h"
#include "../r_draw.h" #include "../r_draw.h"
#include "../r_patch.h"
#include "../r_picformats.h" #include "../r_picformats.h"
#include "../p_setup.h" #include "../p_setup.h"
@ -306,7 +307,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
// Draw each column to the block cache // Draw each column to the block cache
for (; ncols--; block += bpp, xfrac += xfracstep) for (; ncols--; block += bpp, xfrac += xfracstep)
{ {
patchcol = (const column_t *)((const UINT8 *)realpatch + LONG(realpatch->columnofs[xfrac>>FRACBITS])); patchcol = (const column_t *)((const UINT8 *)realpatch->columns + (realpatch->columnofs[xfrac>>FRACBITS]));
HWR_DrawColumnInCache(patchcol, block, mipmap, HWR_DrawColumnInCache(patchcol, block, mipmap,
pblockheight, blockmodulo, pblockheight, blockmodulo,
@ -320,7 +321,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
INT32 pblockwidth, INT32 pblockheight, INT32 pblockwidth, INT32 pblockheight,
texture_t *texture, texpatch_t *patch, texture_t *texture, texpatch_t *patch,
const patch_t *realpatch) const softwarepatch_t *realpatch)
{ {
INT32 x, x1, x2; INT32 x, x1, x2;
INT32 col, ncols; INT32 col, ncols;
@ -391,7 +392,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
bpp = format2bpp(mipmap->format); bpp = format2bpp(mipmap->format);
if (bpp < 1 || bpp > 4) if (bpp < 1 || bpp > 4)
I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp); I_Error("HWR_DrawTexturePatchInCache: no drawer defined for this bpp (%d)\n",bpp);
// NOTE: should this actually be pblockwidth*bpp? // NOTE: should this actually be pblockwidth*bpp?
blockmodulo = pblockwidth*bpp; blockmodulo = pblockwidth*bpp;
@ -446,7 +447,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
UINT8 *block; UINT8 *block;
texture_t *texture; texture_t *texture;
texpatch_t *patch; texpatch_t *patch;
patch_t *realpatch; softwarepatch_t *realpatch;
UINT8 *pdata; UINT8 *pdata;
INT32 blockwidth, blockheight, blocksize; INT32 blockwidth, blockheight, blocksize;
@ -502,16 +503,16 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
boolean dealloc = true; boolean dealloc = true;
size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump); size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump);
pdata = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); pdata = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
realpatch = (patch_t *)pdata; realpatch = (softwarepatch_t *)pdata;
#ifndef NO_PNG_LUMPS #ifndef NO_PNG_LUMPS
if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength)) if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength))
realpatch = (patch_t *)Picture_PNGConvert(pdata, PICFMT_PATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0); realpatch = (softwarepatch_t *)Picture_PNGConvert(pdata, PICFMT_DOOMPATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0);
else else
#endif #endif
#ifdef WALLFLATS #ifdef WALLFLATS
if (texture->type == TEXTURETYPE_FLAT) if (texture->type == TEXTURETYPE_FLAT)
realpatch = (patch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_PATCH, 0, NULL, texture->width, texture->height, 0, 0, 0); realpatch = (softwarepatch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_DOOMPATCH, 0, NULL, texture->width, texture->height, 0, 0, 0);
else else
#endif #endif
{ {
@ -544,36 +545,20 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
// patch may be NULL if grMipmap has been initialised already and makebitmap is false // patch may be NULL if grMipmap has been initialised already and makebitmap is false
void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap) void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap)
{ {
#ifndef NO_PNG_LUMPS
// lump is a png so convert it
size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum);
if ((patch != NULL) && Picture_IsLumpPNG((const UINT8 *)patch, len))
patch = (patch_t *)Picture_PNGConvert((const UINT8 *)patch, PICFMT_PATCH, NULL, NULL, NULL, NULL, len, NULL, 0);
#endif
// don't do it twice (like a cache)
if (grMipmap->width == 0) if (grMipmap->width == 0)
{ {
// save the original patch header so that the GLPatch can be casted
// into a standard patch_t struct and the existing code can get the
// orginal patch dimensions and offsets.
grPatch->width = SHORT(patch->width);
grPatch->height = SHORT(patch->height);
grPatch->leftoffset = SHORT(patch->leftoffset);
grPatch->topoffset = SHORT(patch->topoffset);
grMipmap->width = grMipmap->height = 1; grMipmap->width = grMipmap->height = 1;
while (grMipmap->width < grPatch->width) grMipmap->width <<= 1; while (grMipmap->width < patch->width) grMipmap->width <<= 1;
while (grMipmap->height < grPatch->height) grMipmap->height <<= 1; while (grMipmap->height < patch->height) grMipmap->height <<= 1;
// no wrap around, no chroma key // no wrap around, no chroma key
grMipmap->flags = 0; grMipmap->flags = 0;
// setup the texture info // setup the texture info
grMipmap->format = patchformat; grMipmap->format = patchformat;
//grPatch->max_s = grPatch->max_t = 1.0f; grPatch->max_s = (float)patch->width / (float)grMipmap->width;
grPatch->max_s = (float)grPatch->width / (float)grMipmap->width; grPatch->max_t = (float)patch->height / (float)grMipmap->height;
grPatch->max_t = (float)grPatch->height / (float)grMipmap->height;
} }
Z_Free(grMipmap->data); Z_Free(grMipmap->data);
@ -585,7 +570,7 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
HWR_DrawPatchInCache(grMipmap, HWR_DrawPatchInCache(grMipmap,
grMipmap->width, grMipmap->height, grMipmap->width, grMipmap->height,
grPatch->width, grPatch->height, patch->width, patch->height,
patch); patch);
} }
} }
@ -598,20 +583,56 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
static size_t gl_numtextures = 0; // Texture count static size_t gl_numtextures = 0; // Texture count
static GLMapTexture_t *gl_textures; // For all textures static GLMapTexture_t *gl_textures; // For all textures
static GLMapTexture_t *gl_flats; // For all (texture) flats, as normal flats don't need to be cached static GLMapTexture_t *gl_flats; // For all (texture) flats, as normal flats don't need to be cached
boolean gl_maptexturesloaded = false;
void HWR_InitTextureCache(void) void HWR_FreeTextureData(patch_t *patch)
{ {
gl_textures = NULL; GLPatch_t *grPatch;
gl_flats = NULL;
if (!patch || !patch->hardware)
return;
grPatch = patch->hardware;
if (vid.glstate == VID_GL_LIBRARY_LOADED)
HWD.pfnDeleteTexture(grPatch->mipmap);
if (grPatch->mipmap->data)
Z_Free(grPatch->mipmap->data);
} }
// Callback function for HWR_FreeTextureCache. void HWR_FreeTexture(patch_t *patch)
static void FreeMipmapColormap(INT32 patchnum, void *patch)
{ {
GLPatch_t* const pat = patch; if (!patch)
(void)patchnum; //unused return;
if (patch->hardware)
{
GLPatch_t *grPatch = patch->hardware;
HWR_FreeTextureColormaps(patch);
if (grPatch->mipmap)
{
HWR_FreeTextureData(patch);
Z_Free(grPatch->mipmap);
}
Z_Free(patch->hardware);
}
patch->hardware = NULL;
}
// Called by HWR_FreePatchCache.
void HWR_FreeTextureColormaps(patch_t *patch)
{
GLPatch_t *pat;
// The patch must be valid, obviously // The patch must be valid, obviously
if (!patch)
return;
pat = patch->hardware;
if (!pat) if (!pat)
return; return;
@ -627,7 +648,7 @@ static void FreeMipmapColormap(INT32 patchnum, void *patch)
if (!pat->mipmap) if (!pat->mipmap)
break; break;
// No colormap mipmap either. // No colormap mipmaps either.
if (!pat->mipmap->nextcolormap) if (!pat->mipmap->nextcolormap)
break; break;
@ -639,34 +660,61 @@ static void FreeMipmapColormap(INT32 patchnum, void *patch)
if (next->data) if (next->data)
Z_Free(next->data); Z_Free(next->data);
next->data = NULL; next->data = NULL;
HWD.pfnDeleteTexture(next);
// Free the old colormap mipmap from memory. // Free the old colormap mipmap from memory.
free(next); free(next);
} }
} }
void HWR_FreeMipmapCache(void) static void HWR_FreePatchCache(boolean freeall)
{ {
INT32 i; INT32 i;
// free references to the textures
HWD.pfnClearMipMapCache();
// free all hardware-converted graphics cached in the heap
// our gool is only the textures since user of the texture is the texture cache
Z_FreeTag(PU_HWRCACHE);
Z_FreeTag(PU_HWRCACHE_UNLOCKED);
// Alam: free the Z_Blocks before freeing it's users
// free all patch colormaps after each level: must be done after ClearMipMapCache!
for (i = 0; i < numwadfiles; i++) for (i = 0; i < numwadfiles; i++)
M_AATreeIterate(wadfiles[i]->hwrcache, FreeMipmapColormap); {
INT32 j = 0;
for (; j < wadfiles[i]->numlumps; j++)
(freeall ? HWR_FreeTexture : HWR_FreeTextureColormaps)(wadfiles[i]->patchcache[j]);
}
} }
void HWR_FreeTextureCache(void) // free all textures after each level
void HWR_ClearAllTextures(void)
{ {
// free references to the textures HWD.pfnClearMipMapCache(); // free references to the textures
HWR_FreeMipmapCache(); HWR_FreePatchCache(true);
}
void HWR_FreeColormapCache(void)
{
HWR_FreePatchCache(false);
}
void HWR_InitMapTextures(void)
{
gl_textures = NULL;
gl_flats = NULL;
gl_maptexturesloaded = false;
}
static void FreeMapTexture(GLMapTexture_t *tex)
{
HWD.pfnDeleteTexture(&tex->mipmap);
if (tex->mipmap.data)
Z_Free(tex->mipmap.data);
tex->mipmap.data = NULL;
}
void HWR_FreeMapTextures(void)
{
size_t i;
for (i = 0; i < gl_numtextures; i++)
{
FreeMapTexture(&gl_textures[i]);
FreeMapTexture(&gl_flats[i]);
}
// now the heap don't have any 'user' pointing to our // now the heap don't have any 'user' pointing to our
// texturecache info, we can free it // texturecache info, we can free it
@ -677,22 +725,22 @@ void HWR_FreeTextureCache(void)
gl_textures = NULL; gl_textures = NULL;
gl_flats = NULL; gl_flats = NULL;
gl_numtextures = 0; gl_numtextures = 0;
gl_maptexturesloaded = false;
} }
void HWR_LoadTextures(size_t pnumtextures) void HWR_LoadMapTextures(size_t pnumtextures)
{ {
// we must free it since numtextures changed // we must free it since numtextures may have changed
HWR_FreeTextureCache(); HWR_FreeMapTextures();
// Why not Z_Malloc?
gl_numtextures = pnumtextures; gl_numtextures = pnumtextures;
gl_textures = calloc(gl_numtextures, sizeof(*gl_textures)); gl_textures = calloc(gl_numtextures, sizeof(*gl_textures));
gl_flats = calloc(gl_numtextures, sizeof(*gl_flats)); gl_flats = calloc(gl_numtextures, sizeof(*gl_flats));
// Doesn't tell you which it _is_, but hopefully
// should never ever happen (right?!)
if ((gl_textures == NULL) || (gl_flats == NULL)) if ((gl_textures == NULL) || (gl_flats == NULL))
I_Error("HWR_LoadTextures: ran out of memory for OpenGL textures. Sad!"); I_Error("HWR_LoadMapTextures: ran out of memory for OpenGL textures");
gl_maptexturesloaded = true;
} }
void HWR_SetPalette(RGBA_t *palette) void HWR_SetPalette(RGBA_t *palette)
@ -730,7 +778,6 @@ GLMapTexture_t *HWR_GetTexture(INT32 tex)
// If hardware does not have the texture, then call pfnSetTexture to upload it // If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grtex->mipmap.downloaded) if (!grtex->mipmap.downloaded)
HWD.pfnSetTexture(&grtex->mipmap); HWD.pfnSetTexture(&grtex->mipmap);
HWR_SetCurrentTexture(&grtex->mipmap); HWR_SetCurrentTexture(&grtex->mipmap);
// The system-memory data can be purged now. // The system-memory data can be purged now.
@ -806,17 +853,19 @@ static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum)
void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum) void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum)
{ {
GLMipmap_t *grmip; GLMipmap_t *grmip;
patch_t *patch;
if (flatlumpnum == LUMPERROR) if (flatlumpnum == LUMPERROR)
return; return;
grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap; patch = HWR_GetCachedGLPatch(flatlumpnum);
grmip = ((GLPatch_t *)Patch_AllocateHardwarePatch(patch))->mipmap;
if (!grmip->downloaded && !grmip->data) if (!grmip->downloaded && !grmip->data)
HWR_CacheFlat(grmip, flatlumpnum); HWR_CacheFlat(grmip, flatlumpnum);
// If hardware does not have the texture, then call pfnSetTexture to upload it // If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grmip->downloaded) if (!grmip->downloaded)
HWD.pfnSetTexture(grmip); HWD.pfnSetTexture(grmip);
HWR_SetCurrentTexture(grmip); HWR_SetCurrentTexture(grmip);
// The system-memory data can be purged now. // The system-memory data can be purged now.
@ -854,7 +903,6 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
// If hardware does not have the texture, then call pfnSetTexture to upload it // If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grtex->mipmap.downloaded) if (!grtex->mipmap.downloaded)
HWD.pfnSetTexture(&grtex->mipmap); HWD.pfnSetTexture(&grtex->mipmap);
HWR_SetCurrentTexture(&grtex->mipmap); HWR_SetCurrentTexture(&grtex->mipmap);
// The system-memory data can be purged now. // The system-memory data can be purged now.
@ -862,9 +910,9 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
} }
else if (levelflat->type == LEVELFLAT_PATCH) else if (levelflat->type == LEVELFLAT_PATCH)
{ {
GLPatch_t *patch = W_CachePatchNum(levelflat->u.flat.lumpnum, PU_CACHE); patch_t *patch = W_CachePatchNum(levelflat->u.flat.lumpnum, PU_CACHE);
levelflat->width = (UINT16)SHORT(patch->width); levelflat->width = (UINT16)(patch->width);
levelflat->height = (UINT16)SHORT(patch->height); levelflat->height = (UINT16)(patch->height);
HWR_GetPatch(patch); HWR_GetPatch(patch);
} }
#ifndef NO_PNG_LUMPS #ifndef NO_PNG_LUMPS
@ -911,89 +959,61 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
HWR_SetCurrentTexture(NULL); HWR_SetCurrentTexture(NULL);
} }
// // --------------------+
// HWR_LoadMappedPatch(): replace the skin color of the sprite in cache // HWR_LoadPatchMipmap : Generates a patch into a mipmap, usually the mipmap inside the patch itself
// : load it first in doom cache if not already // --------------------+
// static void HWR_LoadPatchMipmap(patch_t *patch, GLMipmap_t *grMipmap)
static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch)
{ {
if (!grmip->downloaded && !grmip->data) GLPatch_t *grPatch = patch->hardware;
{ if (!grMipmap->downloaded && !grMipmap->data)
patch_t *patch = gpatch->rawpatch; HWR_MakePatch(patch, grPatch, grMipmap, true);
if (!patch)
patch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
HWR_MakePatch(patch, gpatch, grmip, true);
// You can't free rawpatch for some reason?
// (Obviously I can't, sprite rotation needs that...)
if (!gpatch->rawpatch)
Z_Free(patch);
}
// If hardware does not have the texture, then call pfnSetTexture to upload it // If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grmip->downloaded) if (!grMipmap->downloaded)
HWD.pfnSetTexture(grmip); HWD.pfnSetTexture(grMipmap);
HWR_SetCurrentTexture(grMipmap);
HWR_SetCurrentTexture(grmip);
// The system-memory data can be purged now. // The system-memory data can be purged now.
Z_ChangeTag(grmip->data, PU_HWRCACHE_UNLOCKED); Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED);
} }
// -----------------+ // -----------------+
// HWR_GetPatch : Download a patch to the hardware cache and make it ready for use // HWR_GetPatch : Download a patch to the hardware cache and make it ready for use
// -----------------+ // -----------------+
void HWR_GetPatch(GLPatch_t *gpatch) void HWR_GetPatch(patch_t *patch)
{ {
// is it in hardware cache if (!patch->hardware)
if (!gpatch->mipmap->downloaded && !gpatch->mipmap->data) Patch_CreateGL(patch);
{ HWR_LoadPatchMipmap(patch, ((GLPatch_t *)patch->hardware)->mipmap);
// load the software patch, PU_STATIC or the Z_Malloc for hardware patch will
// flush the software patch before the conversion! oh yeah I suffered
patch_t *ptr = gpatch->rawpatch;
if (!ptr)
ptr = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
HWR_MakePatch(ptr, gpatch, gpatch->mipmap, true);
// this is inefficient.. but the hardware patch in heap is purgeable so it should
// not fragment memory, and besides the REAL cache here is the hardware memory
if (!gpatch->rawpatch)
Z_Free(ptr);
}
// If hardware does not have the texture, then call pfnSetTexture to upload it
if (!gpatch->mipmap->downloaded)
HWD.pfnSetTexture(gpatch->mipmap);
HWR_SetCurrentTexture(gpatch->mipmap);
// The system-memory patch data can be purged now.
Z_ChangeTag(gpatch->mipmap->data, PU_HWRCACHE_UNLOCKED);
} }
// -------------------+ // -------------------+
// HWR_GetMappedPatch : Same as HWR_GetPatch for sprite color // HWR_GetMappedPatch : Same as HWR_GetPatch for sprite color
// -------------------+ // -------------------+
void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap) void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap)
{ {
GLMipmap_t *grmip, *newmip; GLPatch_t *grPatch;
GLMipmap_t *grMipmap, *newMipmap;
if (!patch->hardware)
Patch_CreateGL(patch);
grPatch = patch->hardware;
if (colormap == colormaps || colormap == NULL) if (colormap == colormaps || colormap == NULL)
{ {
// Load the default (green) color in doom cache (temporary?) AND hardware cache // Load the default (green) color in hardware cache
HWR_GetPatch(gpatch); HWR_GetPatch(patch);
return; return;
} }
// search for the mimmap // search for the mimmap
// skip the first (no colormap translated) // skip the first (no colormap translated)
for (grmip = gpatch->mipmap; grmip->nextcolormap; ) for (grMipmap = grPatch->mipmap; grMipmap->nextcolormap; )
{ {
grmip = grmip->nextcolormap; grMipmap = grMipmap->nextcolormap;
if (grmip->colormap == colormap) if (grMipmap->colormap == colormap)
{ {
HWR_LoadMappedPatch(grmip, gpatch); HWR_LoadPatchMipmap(patch, grMipmap);
return; return;
} }
} }
@ -1002,15 +1022,15 @@ void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap)
//BP: WARNING: don't free it manually without clearing the cache of harware renderer //BP: WARNING: don't free it manually without clearing the cache of harware renderer
// (it have a liste of mipmap) // (it have a liste of mipmap)
// this malloc is cleared in HWR_FreeTextureCache // this malloc is cleared in HWR_FreeColormapCache
// (...) unfortunately z_malloc fragment alot the memory :(so malloc is better // (...) unfortunately z_malloc fragment alot the memory :(so malloc is better
newmip = calloc(1, sizeof (*newmip)); newMipmap = calloc(1, sizeof (*newMipmap));
if (newmip == NULL) if (newMipmap == NULL)
I_Error("%s: Out of memory", "HWR_GetMappedPatch"); I_Error("%s: Out of memory", "HWR_GetMappedPatch");
grmip->nextcolormap = newmip; grMipmap->nextcolormap = newMipmap;
newmip->colormap = colormap; newMipmap->colormap = colormap;
HWR_LoadMappedPatch(newmip, gpatch); HWR_LoadPatchMipmap(patch, newMipmap);
} }
void HWR_UnlockCachedPatch(GLPatch_t *gpatch) void HWR_UnlockCachedPatch(GLPatch_t *gpatch)
@ -1100,79 +1120,73 @@ static void HWR_DrawPicInCache(UINT8 *block, INT32 pblockwidth, INT32 pblockheig
// HWR_GetPic : Download a Doom pic (raw row encoded with no 'holes') // HWR_GetPic : Download a Doom pic (raw row encoded with no 'holes')
// Returns : // Returns :
// -----------------+ // -----------------+
GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) patch_t *HWR_GetPic(lumpnum_t lumpnum)
{ {
GLPatch_t *grpatch = HWR_GetCachedGLPatch(lumpnum); patch_t *patch = HWR_GetCachedGLPatch(lumpnum);
if (!grpatch->mipmap->downloaded && !grpatch->mipmap->data) GLPatch_t *grPatch = (GLPatch_t *)(patch->hardware);
if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data)
{ {
pic_t *pic; pic_t *pic;
UINT8 *block; UINT8 *block;
size_t len; size_t len;
pic = W_CacheLumpNum(lumpnum, PU_CACHE); pic = W_CacheLumpNum(lumpnum, PU_CACHE);
grpatch->width = SHORT(pic->width); patch->width = SHORT(pic->width);
grpatch->height = SHORT(pic->height); patch->height = SHORT(pic->height);
len = W_LumpLength(lumpnum) - sizeof (pic_t); len = W_LumpLength(lumpnum) - sizeof (pic_t);
grpatch->leftoffset = 0; grPatch->mipmap->width = (UINT16)patch->width;
grpatch->topoffset = 0; grPatch->mipmap->height = (UINT16)patch->height;
grpatch->mipmap->width = (UINT16)grpatch->width;
grpatch->mipmap->height = (UINT16)grpatch->height;
if (pic->mode == PALETTE) if (pic->mode == PALETTE)
grpatch->mipmap->format = textureformat; // can be set by driver grPatch->mipmap->format = textureformat; // can be set by driver
else else
grpatch->mipmap->format = picmode2GR[pic->mode]; grPatch->mipmap->format = picmode2GR[pic->mode];
Z_Free(grpatch->mipmap->data); Z_Free(grPatch->mipmap->data);
// allocate block // allocate block
block = MakeBlock(grpatch->mipmap); block = MakeBlock(grPatch->mipmap);
if (grpatch->width == SHORT(pic->width) && if (patch->width == SHORT(pic->width) &&
grpatch->height == SHORT(pic->height) && patch->height == SHORT(pic->height) &&
format2bpp(grpatch->mipmap->format) == format2bpp(picmode2GR[pic->mode])) format2bpp(grPatch->mipmap->format) == format2bpp(picmode2GR[pic->mode]))
{ {
// no conversion needed // no conversion needed
M_Memcpy(grpatch->mipmap->data, pic->data,len); M_Memcpy(grPatch->mipmap->data, pic->data,len);
} }
else else
HWR_DrawPicInCache(block, SHORT(pic->width), SHORT(pic->height), HWR_DrawPicInCache(block, SHORT(pic->width), SHORT(pic->height),
SHORT(pic->width)*format2bpp(grpatch->mipmap->format), SHORT(pic->width)*format2bpp(grPatch->mipmap->format),
pic, pic,
format2bpp(grpatch->mipmap->format)); format2bpp(grPatch->mipmap->format));
Z_Unlock(pic); Z_Unlock(pic);
Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED); Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED);
grpatch->mipmap->flags = 0; grPatch->mipmap->flags = 0;
grpatch->max_s = grpatch->max_t = 1.0f; grPatch->max_s = grPatch->max_t = 1.0f;
} }
HWD.pfnSetTexture(grpatch->mipmap); HWD.pfnSetTexture(grPatch->mipmap);
//CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grpatch->mipmap.data, grpatch->mipmap.downloaded); //CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grPatch->mipmap->data, grPatch->mipmap->downloaded);
return grpatch; return patch;
} }
GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum) patch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum)
{ {
aatree_t *hwrcache = wadfiles[wadnum]->hwrcache; lumpcache_t *lumpcache = wadfiles[wadnum]->patchcache;
GLPatch_t *grpatch; if (!lumpcache[lumpnum])
if (!(grpatch = M_AATreeGet(hwrcache, lumpnum)))
{ {
grpatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL); void *ptr = Z_Calloc(sizeof(patch_t), PU_PATCH, &lumpcache[lumpnum]);
grpatch->wadnum = wadnum; Patch_Create(NULL, 0, ptr);
grpatch->lumpnum = lumpnum; Patch_AllocateHardwarePatch(ptr);
grpatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL);
M_AATreeSet(hwrcache, lumpnum, grpatch);
} }
return (patch_t *)(lumpcache[lumpnum]);
return grpatch;
} }
GLPatch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum) patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum)
{ {
return HWR_GetCachedGLPatchPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum)); return HWR_GetCachedGLPatchPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum));
} }
@ -1192,8 +1206,8 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32
W_ReadLump(fademasklumpnum, Z_Malloc(W_LumpLength(fademasklumpnum), W_ReadLump(fademasklumpnum, Z_Malloc(W_LumpLength(fademasklumpnum),
PU_HWRCACHE, &flat)); PU_HWRCACHE, &flat));
stepy = ((INT32)SHORT(fmheight)<<FRACBITS)/pblockheight; stepy = ((INT32)fmheight<<FRACBITS)/pblockheight;
stepx = ((INT32)SHORT(fmwidth)<<FRACBITS)/pblockwidth; stepx = ((INT32)fmwidth<<FRACBITS)/pblockwidth;
posy = 0; posy = 0;
for (j = 0; j < pblockheight; j++) for (j = 0; j < pblockheight; j++)
{ {
@ -1265,7 +1279,8 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum)
void HWR_GetFadeMask(lumpnum_t fademasklumpnum) void HWR_GetFadeMask(lumpnum_t fademasklumpnum)
{ {
GLMipmap_t *grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap; patch_t *patch = HWR_GetCachedGLPatch(fademasklumpnum);
GLMipmap_t *grmip = ((GLPatch_t *)Patch_AllocateHardwarePatch(patch))->mipmap;
if (!grmip->downloaded && !grmip->data) if (!grmip->downloaded && !grmip->data)
HWR_CacheFadeMask(grmip, fademasklumpnum); HWR_CacheFadeMask(grmip, fademasklumpnum);

View file

@ -43,20 +43,19 @@ typedef enum GLTextureFormat_e
// NULL if the texture is not in Doom heap cache. // NULL if the texture is not in Doom heap cache.
struct GLMipmap_s struct GLMipmap_s
{ {
//for TexDownloadMipMap // for TexDownloadMipMap
GLTextureFormat_t format; GLTextureFormat_t format;
void *data; void *data;
UINT32 flags; UINT32 flags;
UINT16 height; UINT16 height;
UINT16 width; UINT16 width;
UINT32 downloaded; // the dll driver have it in there cache ? UINT32 downloaded; // The GPU has this texture.
struct GLMipmap_s *nextcolormap; struct GLMipmap_s *nextcolormap;
const UINT8 *colormap; const UINT8 *colormap;
// opengl struct GLMipmap_s *nextmipmap; // Linked list of all textures
struct GLMipmap_s *nextmipmap; // opengl : liste of all texture in opengl driver
}; };
typedef struct GLMipmap_s GLMipmap_t; typedef struct GLMipmap_s GLMipmap_t;
@ -73,23 +72,10 @@ struct GLMapTexture_s
typedef struct GLMapTexture_s GLMapTexture_t; typedef struct GLMapTexture_s GLMapTexture_t;
// a cached patch as converted to hardware format, holding the original patch_t // a cached patch as converted to hardware format
// header so that the existing code can retrieve ->width, ->height as usual
// This is returned by W_CachePatchNum()/W_CachePatchName(), when rendermode
// is 'render_opengl'. Else it returns the normal patch_t data.
struct GLPatch_s struct GLPatch_s
{ {
// the 4 first fields come right away from the original patch_t
INT16 width;
INT16 height;
INT16 leftoffset; // pixels to the left of origin
INT16 topoffset; // pixels below the origin
//
float max_s,max_t; float max_s,max_t;
UINT16 wadnum; // the software patch lump num for when the hardware patch
UINT16 lumpnum; // was flushed, and we need to re-create it
void *rawpatch; // :^)
GLMipmap_t *mipmap; GLMipmap_t *mipmap;
} ATTRPACK; } ATTRPACK;
typedef struct GLPatch_s GLPatch_t; typedef struct GLPatch_s GLPatch_t;

View file

@ -212,35 +212,32 @@ typedef struct
// You pass a combination of these flags to DrawPolygon() // You pass a combination of these flags to DrawPolygon()
enum EPolyFlags enum EPolyFlags
{ {
// the first 5 are mutually exclusive // Mutually exclusive blend flags
PF_Masked = 0x00000001, // Poly is alpha scaled and 0 alpha pixels are discarded (holes in texture)
PF_Masked = 0x00000001, // Poly is alpha scaled and 0 alpha pels are discarded (holes in texture)
PF_Translucent = 0x00000002, // Poly is transparent, alpha = level of transparency PF_Translucent = 0x00000002, // Poly is transparent, alpha = level of transparency
PF_Additive = 0x00000004, // Poly is added to the frame buffer PF_Environment = 0x00000004, // Poly should be drawn environment mapped. (Hurdler: used for text drawing)
PF_Environment = 0x00000008, // Poly should be drawn environment mapped. PF_Additive = 0x00000008, // Additive color blending
// Hurdler: used for text drawing PF_AdditiveSource = 0x00000010, // Source blending factor is additive. This is the opposite of regular additive blending.
PF_Substractive = 0x00000010, // for splat PF_Subtractive = 0x00000020, // Subtractive color blending
PF_NoAlphaTest = 0x00000020, // hiden param PF_ReverseSubtract = 0x00000040, // Reverse subtract, used in wall splats (decals)
PF_Fog = 0x00000040, // Fog blocks PF_Multiplicative = 0x00000080, // Multiplicative color blending
PF_Blending = (PF_Environment|PF_Additive|PF_Translucent|PF_Masked|PF_Substractive|PF_Fog)&~PF_NoAlphaTest, PF_Fog = 0x20000000, // Fog blocks
PF_NoAlphaTest = 0x40000000, // Disables alpha testing
PF_Blending = (PF_Masked|PF_Translucent|PF_Environment|PF_Additive|PF_AdditiveSource|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative|PF_Fog) & ~PF_NoAlphaTest,
// other flag bits // other flag bits
PF_Occlude = 0x00000100, // Updates the depth buffer
PF_Occlude = 0x00000100, // Update the depth buffer PF_NoDepthTest = 0x00000200, // Disables the depth test mode
PF_NoDepthTest = 0x00000200, // Disable the depth test mode PF_Invisible = 0x00000400, // Disables write to color buffer
PF_Invisible = 0x00000400, // Disable write to color buffer PF_Decal = 0x00000800, // Enables polygon offset
PF_Decal = 0x00000800, // Enable polygon offset
PF_Modulated = 0x00001000, // Modulation (multiply output with constant ARGB) PF_Modulated = 0x00001000, // Modulation (multiply output with constant ARGB)
// When set, pass the color constant into the FSurfaceInfo -> PolyColor // When set, pass the color constant into the FSurfaceInfo -> PolyColor
PF_NoTexture = 0x00002000, // Use the small white texture PF_NoTexture = 0x00002000, // Disables texturing
PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona PF_Corona = 0x00004000, // Tells the renderer we are drawing a corona
PF_Ripple = 0x00008000, // Water shader effect PF_Ripple = 0x00008000, // Water effect shader
PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y PF_RemoveYWrap = 0x00010000, // Forces clamp texture on Y
PF_ForceWrapX = 0x00020000, // Force repeat texture on X PF_ForceWrapX = 0x00020000, // Forces repeat texture on X
PF_ForceWrapY = 0x00040000, // Force repeat texture on Y PF_ForceWrapY = 0x00040000 // Forces repeat texture on Y
PF_Clip = 0x40000000, // clip to frustum and nearz plane (glide only, automatic in opengl)
PF_NoZClip = 0x20000000, // in conjonction with PF_Clip
PF_Debug = 0x80000000 // print debug message in driver :)
}; };
@ -295,6 +292,16 @@ enum hwdsetspecialstate
typedef enum hwdsetspecialstate hwdspecialstate_t; typedef enum hwdsetspecialstate hwdspecialstate_t;
// Lactozilla: Shader options
enum hwdshaderoption
{
HWD_SHADEROPTION_OFF,
HWD_SHADEROPTION_ON,
HWD_SHADEROPTION_NOCUSTOM,
};
typedef enum hwdshaderoption hwdshaderoption_t;
// Lactozilla: Shader info // Lactozilla: Shader info
// Generally set at the start of the frame. // Generally set at the start of the frame.
enum hwdshaderinfo enum hwdshaderinfo

View file

@ -68,10 +68,11 @@ static UINT8 softwaretranstogl_lo[11] = { 0, 12, 24, 36, 48, 60, 71, 83, 95,111
// Notes : x,y : positions relative to the original Doom resolution // Notes : x,y : positions relative to the original Doom resolution
// : textes(console+score) + menus + status bar // : textes(console+score) + menus + status bar
// -----------------+ // -----------------+
void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
{ {
FOutVector v[4]; FOutVector v[4];
FBITFIELD flags; FBITFIELD flags;
GLPatch_t *hwrPatch;
// 3--2 // 3--2
// | /| // | /|
@ -84,6 +85,7 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option)
// make patch ready in hardware cache // make patch ready in hardware cache
HWR_GetPatch(gpatch); HWR_GetPatch(gpatch);
hwrPatch = ((GLPatch_t *)gpatch->hardware);
switch (option & V_SCALEPATCHMASK) switch (option & V_SCALEPATCHMASK)
{ {
@ -103,17 +105,17 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option)
if (option & V_NOSCALESTART) if (option & V_NOSCALESTART)
sdupx = sdupy = 2.0f; sdupx = sdupy = 2.0f;
v[0].x = v[3].x = (x*sdupx-SHORT(gpatch->leftoffset)*pdupx)/vid.width - 1; v[0].x = v[3].x = (x*sdupx-(gpatch->leftoffset)*pdupx)/vid.width - 1;
v[2].x = v[1].x = (x*sdupx+(SHORT(gpatch->width)-SHORT(gpatch->leftoffset))*pdupx)/vid.width - 1; v[2].x = v[1].x = (x*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1;
v[0].y = v[1].y = 1-(y*sdupy-SHORT(gpatch->topoffset)*pdupy)/vid.height; v[0].y = v[1].y = 1-(y*sdupy-(gpatch->topoffset)*pdupy)/vid.height;
v[2].y = v[3].y = 1-(y*sdupy+(SHORT(gpatch->height)-SHORT(gpatch->topoffset))*pdupy)/vid.height; v[2].y = v[3].y = 1-(y*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = 0.0f; v[0].s = v[3].s = 0.0f;
v[2].s = v[1].s = gpatch->max_s; v[2].s = v[1].s = hwrPatch->max_s;
v[0].t = v[1].t = 0.0f; v[0].t = v[1].t = 0.0f;
v[2].t = v[3].t = gpatch->max_t; v[2].t = v[3].t = hwrPatch->max_t;
flags = PF_Translucent|PF_NoDepthTest; flags = PF_Translucent|PF_NoDepthTest;
@ -126,13 +128,14 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option)
HWD.pfnDrawPolygon(NULL, v, 4, flags); HWD.pfnDrawPolygon(NULL, v, 4, flags);
} }
void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap) void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap)
{ {
FOutVector v[4]; FOutVector v[4];
FBITFIELD flags; FBITFIELD flags;
float cx = FIXED_TO_FLOAT(x); float cx = FIXED_TO_FLOAT(x);
float cy = FIXED_TO_FLOAT(y); float cy = FIXED_TO_FLOAT(y);
UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT); UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT);
GLPatch_t *hwrPatch;
// 3--2 // 3--2
// | /| // | /|
@ -151,6 +154,8 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
else else
HWR_GetMappedPatch(gpatch, colormap); HWR_GetMappedPatch(gpatch, colormap);
hwrPatch = ((GLPatch_t *)gpatch->hardware);
dupx = (float)vid.dupx; dupx = (float)vid.dupx;
dupy = (float)vid.dupy; dupy = (float)vid.dupy;
@ -181,13 +186,13 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
// left offset // left offset
if (option & V_FLIP) if (option & V_FLIP)
offsetx = (float)(SHORT(gpatch->width) - SHORT(gpatch->leftoffset)) * fscalew; offsetx = (float)(gpatch->width - gpatch->leftoffset) * fscalew;
else else
offsetx = (float)SHORT(gpatch->leftoffset) * fscalew; offsetx = (float)(gpatch->leftoffset) * fscalew;
// top offset // top offset
// TODO: make some kind of vertical version of V_FLIP, maybe by deprecating V_OFFSET in future?!? // TODO: make some kind of vertical version of V_FLIP, maybe by deprecating V_OFFSET in future?!?
offsety = (float)SHORT(gpatch->topoffset) * fscaleh; offsety = (float)(gpatch->topoffset) * fscaleh;
if ((option & (V_NOSCALESTART|V_OFFSET)) == (V_NOSCALESTART|V_OFFSET)) // Multiply by dupx/dupy for crosshairs if ((option & (V_NOSCALESTART|V_OFFSET)) == (V_NOSCALESTART|V_OFFSET)) // Multiply by dupx/dupy for crosshairs
{ {
@ -277,17 +282,14 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
// if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT) // if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT)
// cx and cy are possibly *slightly* off from float maths // cx and cy are possibly *slightly* off from float maths
// This is done before here compared to software because we directly alter cx and cy to centre // This is done before here compared to software because we directly alter cx and cy to centre
if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) if (cx >= -0.1f && cx <= 0.1f && gpatch->width == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && gpatch->height == BASEVIDHEIGHT)
{ {
// Need to temporarily cache the real patch to get the colour of the top left pixel const column_t *column = (const column_t *)((const UINT8 *)(gpatch->columns) + (gpatch->columnofs[0]));
patch_t *realpatch = W_CacheSoftwarePatchNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0]));
if (!column->topdelta) if (!column->topdelta)
{ {
const UINT8 *source = (const UINT8 *)(column) + 3; const UINT8 *source = (const UINT8 *)(column) + 3;
HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
} }
Z_Free(realpatch);
} }
// centre screen // centre screen
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
@ -317,13 +319,13 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
if (pscale != FRACUNIT || (splitscreen && option & V_PERPLAYER)) if (pscale != FRACUNIT || (splitscreen && option & V_PERPLAYER))
{ {
fwidth = (float)SHORT(gpatch->width) * fscalew * dupx; fwidth = (float)(gpatch->width) * fscalew * dupx;
fheight = (float)SHORT(gpatch->height) * fscaleh * dupy; fheight = (float)(gpatch->height) * fscaleh * dupy;
} }
else else
{ {
fwidth = (float)SHORT(gpatch->width) * dupx; fwidth = (float)(gpatch->width) * dupx;
fheight = (float)SHORT(gpatch->height) * dupy; fheight = (float)(gpatch->height) * dupy;
} }
// positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1 // positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1
@ -345,17 +347,17 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
if (option & V_FLIP) if (option & V_FLIP)
{ {
v[0].s = v[3].s = gpatch->max_s; v[0].s = v[3].s = hwrPatch->max_s;
v[2].s = v[1].s = 0.0f; v[2].s = v[1].s = 0.0f;
} }
else else
{ {
v[0].s = v[3].s = 0.0f; v[0].s = v[3].s = 0.0f;
v[2].s = v[1].s = gpatch->max_s; v[2].s = v[1].s = hwrPatch->max_s;
} }
v[0].t = v[1].t = 0.0f; v[0].t = v[1].t = 0.0f;
v[2].t = v[3].t = gpatch->max_t; v[2].t = v[3].t = hwrPatch->max_t;
flags = PF_Translucent|PF_NoDepthTest; flags = PF_Translucent|PF_NoDepthTest;
@ -380,13 +382,14 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
HWD.pfnDrawPolygon(NULL, v, 4, flags); HWD.pfnDrawPolygon(NULL, v, 4, flags);
} }
void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h)
{ {
FOutVector v[4]; FOutVector v[4];
FBITFIELD flags; FBITFIELD flags;
float cx = FIXED_TO_FLOAT(x); float cx = FIXED_TO_FLOAT(x);
float cy = FIXED_TO_FLOAT(y); float cy = FIXED_TO_FLOAT(y);
UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT); UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT);
GLPatch_t *hwrPatch;
// 3--2 // 3--2
// | /| // | /|
@ -399,6 +402,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
// make patch ready in hardware cache // make patch ready in hardware cache
HWR_GetPatch(gpatch); HWR_GetPatch(gpatch);
hwrPatch = ((GLPatch_t *)gpatch->hardware);
dupx = (float)vid.dupx; dupx = (float)vid.dupx;
dupy = (float)vid.dupy; dupy = (float)vid.dupy;
@ -423,8 +427,8 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
// fuck it, no GL support for croppedpatch v_perplayer right now. it's not like it's accessible to Lua or anything, and we only use it for menus... // fuck it, no GL support for croppedpatch v_perplayer right now. it's not like it's accessible to Lua or anything, and we only use it for menus...
cy -= (float)SHORT(gpatch->topoffset) * fscale; cy -= (float)(gpatch->topoffset) * fscale;
cx -= (float)SHORT(gpatch->leftoffset) * fscale; cx -= (float)(gpatch->leftoffset) * fscale;
if (!(option & V_NOSCALESTART)) if (!(option & V_NOSCALESTART))
{ {
@ -436,17 +440,14 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
// if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT) // if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT)
// cx and cy are possibly *slightly* off from float maths // cx and cy are possibly *slightly* off from float maths
// This is done before here compared to software because we directly alter cx and cy to centre // This is done before here compared to software because we directly alter cx and cy to centre
if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) if (cx >= -0.1f && cx <= 0.1f && gpatch->width == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && gpatch->height == BASEVIDHEIGHT)
{ {
// Need to temporarily cache the real patch to get the colour of the top left pixel const column_t *column = (const column_t *)((const UINT8 *)(gpatch->columns) + (gpatch->columnofs[0]));
patch_t *realpatch = W_CacheSoftwarePatchNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0]));
if (!column->topdelta) if (!column->topdelta)
{ {
const UINT8 *source = (const UINT8 *)(column) + 3; const UINT8 *source = (const UINT8 *)(column) + 3;
HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
} }
Z_Free(realpatch);
} }
// centre screen // centre screen
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
@ -469,11 +470,11 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
fwidth = w; fwidth = w;
fheight = h; fheight = h;
if (fwidth > SHORT(gpatch->width)) if (fwidth > gpatch->width)
fwidth = SHORT(gpatch->width); fwidth = gpatch->width;
if (fheight > SHORT(gpatch->height)) if (fheight > gpatch->height)
fheight = SHORT(gpatch->height); fheight = gpatch->height;
if (pscale != FRACUNIT) if (pscale != FRACUNIT)
{ {
@ -503,17 +504,17 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = ((sx )/(float)SHORT(gpatch->width) )*gpatch->max_s; v[0].s = v[3].s = ((sx)/(float)(gpatch->width))*hwrPatch->max_s;
if (sx + w > SHORT(gpatch->width)) if (sx + w > gpatch->width)
v[2].s = v[1].s = gpatch->max_s; v[2].s = v[1].s = hwrPatch->max_s;
else else
v[2].s = v[1].s = ((sx+w)/(float)SHORT(gpatch->width) )*gpatch->max_s; v[2].s = v[1].s = ((sx+w)/(float)(gpatch->width))*hwrPatch->max_s;
v[0].t = v[1].t = ((sy )/(float)SHORT(gpatch->height))*gpatch->max_t; v[0].t = v[1].t = ((sy)/(float)(gpatch->height))*hwrPatch->max_t;
if (sy + h > SHORT(gpatch->height)) if (sy + h > gpatch->height)
v[2].t = v[3].t = gpatch->max_t; v[2].t = v[3].t = hwrPatch->max_t;
else else
v[2].t = v[3].t = ((sy+h)/(float)SHORT(gpatch->height))*gpatch->max_t; v[2].t = v[3].t = ((sy+h)/(float)(gpatch->height))*hwrPatch->max_t;
flags = PF_Translucent|PF_NoDepthTest; flags = PF_Translucent|PF_NoDepthTest;
@ -541,7 +542,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum) void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
{ {
FOutVector v[4]; FOutVector v[4];
const GLPatch_t *patch; const patch_t *patch;
// make pic ready in hardware cache // make pic ready in hardware cache
patch = HWR_GetPic(lumpnum); patch = HWR_GetPic(lumpnum);
@ -558,10 +559,10 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = 0; v[0].s = v[3].s = 0;
v[2].s = v[1].s = patch->max_s; v[2].s = v[1].s = ((GLPatch_t *)patch->hardware)->max_s;
v[0].t = v[1].t = 0; v[0].t = v[1].t = 0;
v[2].t = v[3].t = patch->max_t; v[2].t = v[3].t = ((GLPatch_t *)patch->hardware)->max_t;
//Hurdler: Boris, the same comment as above... but maybe for pics //Hurdler: Boris, the same comment as above... but maybe for pics
@ -570,7 +571,7 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
// But then, the question is: why not 0 instead of PF_Masked ? // But then, the question is: why not 0 instead of PF_Masked ?
// or maybe PF_Environment ??? (like what I said above) // or maybe PF_Environment ??? (like what I said above)
// BP: PF_Environment don't change anything ! and 0 is undifined // BP: PF_Environment don't change anything ! and 0 is undifined
HWD.pfnDrawPolygon(NULL, v, 4, PF_Translucent | PF_NoDepthTest | PF_Clip | PF_NoZClip); HWD.pfnDrawPolygon(NULL, v, 4, PF_Translucent | PF_NoDepthTest);
} }
// ========================================================================== // ==========================================================================
@ -934,7 +935,7 @@ void HWR_DrawViewBorder(INT32 clearlines)
INT32 top, side; INT32 top, side;
INT32 baseviewwidth, baseviewheight; INT32 baseviewwidth, baseviewheight;
INT32 basewindowx, basewindowy; INT32 basewindowx, basewindowy;
GLPatch_t *patch; patch_t *patch;
// if (gl_viewwidth == vid.width) // if (gl_viewwidth == vid.width)
// return; // return;

View file

@ -42,9 +42,11 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags);
EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor);
EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo);
EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *TexInfo); EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *TexInfo);
EXPORT void HWRAPI(DeleteTexture) (FTextureInfo *TexInfo);
EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data); EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data);
EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip); EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip);
EXPORT void HWRAPI(ClearMipMapCache) (void); EXPORT void HWRAPI(ClearMipMapCache) (void);
EXPORT void HWRAPI(ClearCacheList) (void);
//Hurdler: added for backward compatibility //Hurdler: added for backward compatibility
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
@ -70,7 +72,7 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
// jimita // jimita
EXPORT boolean HWRAPI(CompileShaders) (void); EXPORT boolean HWRAPI(CompileShaders) (void);
EXPORT void HWRAPI(CleanShaders) (void); EXPORT void HWRAPI(CleanShaders) (void);
EXPORT void HWRAPI(SetShader) (int shader); EXPORT void HWRAPI(SetShader) (int type);
EXPORT void HWRAPI(UnSetShader) (void); EXPORT void HWRAPI(UnSetShader) (void);
EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value); EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value);
@ -95,9 +97,11 @@ struct hwdriver_s
ClearBuffer pfnClearBuffer; ClearBuffer pfnClearBuffer;
SetTexture pfnSetTexture; SetTexture pfnSetTexture;
UpdateTexture pfnUpdateTexture; UpdateTexture pfnUpdateTexture;
DeleteTexture pfnDeleteTexture;
ReadRect pfnReadRect; ReadRect pfnReadRect;
GClipRect pfnGClipRect; GClipRect pfnGClipRect;
ClearMipMapCache pfnClearMipMapCache; ClearMipMapCache pfnClearMipMapCache;
ClearCacheList pfnClearCacheList;
SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility
DrawModel pfnDrawModel; DrawModel pfnDrawModel;
CreateModelVBOs pfnCreateModelVBOs; CreateModelVBOs pfnCreateModelVBOs;

View file

@ -62,19 +62,32 @@ typedef struct
typedef struct gl_vissprite_s typedef struct gl_vissprite_s
{ {
float x1, x2; float x1, x2;
float tz, ty; float z1, z2;
float gz, gzt;
float tz;
float tracertz; // for MF2_LINKDRAW sprites, this contains tracer's tz for use in sorting float tracertz; // for MF2_LINKDRAW sprites, this contains tracer's tz for use in sorting
//lumpnum_t patchlumpnum;
GLPatch_t *gpatch; float scale;
boolean flip; float shadowheight, shadowscale;
UINT8 translucency; //alpha level 0-255
mobj_t *mobj; // NOTE: This is a precipmobj_t if precip is true !!! Watch out. float spritexscale, spriteyscale;
float spritexoffset, spriteyoffset;
UINT32 renderflags;
UINT8 rotateflags;
boolean flip, vflip;
boolean precip; // Tails 08-25-2002 boolean precip; // Tails 08-25-2002
boolean vflip; boolean rotated;
//Hurdler: 25/04/2000: now support colormap in hardware mode UINT8 translucency; //alpha level 0-255
//Hurdler: 25/04/2000: now support colormap in hardware mode
UINT8 *colormap; UINT8 *colormap;
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
float z1, z2;
patch_t *gpatch;
mobj_t *mobj; // NOTE: This is a precipmobj_t if precip is true !!! Watch out.
} gl_vissprite_t; } gl_vissprite_t;
// -------- // --------
@ -86,25 +99,36 @@ extern size_t addsubsector;
void HWR_InitPolyPool(void); void HWR_InitPolyPool(void);
void HWR_FreePolyPool(void); void HWR_FreePolyPool(void);
void HWR_FreeExtraSubsectors(void);
// -------- // --------
// hw_cache.c // hw_cache.c
// -------- // --------
void HWR_InitTextureCache(void); void HWR_InitMapTextures(void);
void HWR_FreeTextureCache(void); void HWR_LoadMapTextures(size_t pnumtextures);
void HWR_FreeMipmapCache(void); void HWR_FreeMapTextures(void);
void HWR_FreeExtraSubsectors(void);
patch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump);
patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum);
void HWR_GetPatch(patch_t *patch);
void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap);
void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
patch_t *HWR_GetPic(lumpnum_t lumpnum);
GLMapTexture_t *HWR_GetTexture(INT32 tex);
void HWR_GetLevelFlat(levelflat_t *levelflat); void HWR_GetLevelFlat(levelflat_t *levelflat);
void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum); void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum);
GLMapTexture_t *HWR_GetTexture(INT32 tex);
void HWR_GetPatch(GLPatch_t *gpatch); void HWR_FreeTexture(patch_t *patch);
void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap); void HWR_FreeTextureData(patch_t *patch);
void HWR_FreeTextureColormaps(patch_t *patch);
void HWR_ClearAllTextures(void);
void HWR_FreeColormapCache(void);
void HWR_UnlockCachedPatch(GLPatch_t *gpatch); void HWR_UnlockCachedPatch(GLPatch_t *gpatch);
GLPatch_t *HWR_GetPic(lumpnum_t lumpnum);
void HWR_SetPalette(RGBA_t *palette); void HWR_SetPalette(RGBA_t *palette);
GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump);
GLPatch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum);
void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
// -------- // --------
// hw_draw.c // hw_draw.c

View file

@ -35,8 +35,7 @@
#define DL_HIGH_QUALITY #define DL_HIGH_QUALITY
//#define STATICLIGHT //Hurdler: TODO! //#define STATICLIGHT //Hurdler: TODO!
//#define LIGHTMAPFLAGS (PF_Masked|PF_Clip|PF_NoAlphaTest) // debug see overdraw #define LIGHTMAPFLAGS (PF_Modulated|PF_AdditiveSource)
#define LIGHTMAPFLAGS (PF_Modulated|PF_Additive|PF_Clip)
#ifdef ALAM_LIGHTING #ifdef ALAM_LIGHTING
static dynlights_t view_dynlights[2]; // 2 players in splitscreen mode static dynlights_t view_dynlights[2]; // 2 players in splitscreen mode
@ -1056,7 +1055,7 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gl_vissprite_t *spr)
HWR_GetPic(coronalumpnum); /// \todo use different coronas HWR_GetPic(coronalumpnum); /// \todo use different coronas
HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_Corona | PF_NoDepthTest); HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_AdditiveSource | PF_Corona | PF_NoDepthTest);
} }
} }
#endif #endif
@ -1144,7 +1143,7 @@ void HWR_DrawCoronas(void)
light[3].y = cy+size*1.33f; light[3].y = cy+size*1.33f;
light[3].s = 0.0f; light[3].t = 1.0f; light[3].s = 0.0f; light[3].t = 1.0f;
HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_NoDepthTest | PF_Corona); HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_AdditiveSource | PF_NoDepthTest | PF_Corona);
} }
} }
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -37,13 +37,12 @@ void HWR_DrawViewBorder(INT32 clearlines);
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);
void HWR_InitTextureMapping(void); void HWR_InitTextureMapping(void);
void HWR_SetViewSize(void); void HWR_SetViewSize(void);
void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option);
void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap); void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap);
void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap); void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap);
void HWR_CreatePlanePolygons(INT32 bspnum); void HWR_CreatePlanePolygons(INT32 bspnum);
void HWR_CreateStaticLightmaps(INT32 bspnum); void HWR_CreateStaticLightmaps(INT32 bspnum);
void HWR_LoadTextures(size_t pnumtextures);
void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color); void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color);
void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 actualcolor, UINT8 strength); void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 actualcolor, UINT8 strength);
void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32 actualcolor); // Lat: separate flags from color since color needs to be an uint to work right. void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32 actualcolor); // Lat: separate flags from color since color needs to be an uint to work right.
@ -55,7 +54,6 @@ boolean HWR_Screenshot(const char *pathname);
void HWR_AddCommands(void); void HWR_AddCommands(void);
void HWR_AddSessionCommands(void); void HWR_AddSessionCommands(void);
void transform(float *cx, float *cy, float *cz); void transform(float *cx, float *cy, float *cz);
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf);
INT32 HWR_GetTextureUsed(void); INT32 HWR_GetTextureUsed(void);
void HWR_DoPostProcessor(player_t *player); void HWR_DoPostProcessor(player_t *player);
void HWR_StartScreenWipe(void); void HWR_StartScreenWipe(void);
@ -66,10 +64,15 @@ void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum);
void HWR_MakeScreenFinalTexture(void); void HWR_MakeScreenFinalTexture(void);
void HWR_DrawScreenFinalTexture(int width, int height); void HWR_DrawScreenFinalTexture(int width, int height);
// This stuff is put here so MD2's can use them // This stuff is put here so models can use them
void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap); void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap);
UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work
UINT8 HWR_GetTranstableAlpha(INT32 transtablenum);
FBITFIELD HWR_GetBlendModeFlag(INT32 ast);
FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf);
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf);
boolean HWR_CompileShaders(void); boolean HWR_CompileShaders(void);
void HWR_LoadAllCustomShaders(void); void HWR_LoadAllCustomShaders(void);
@ -78,7 +81,7 @@ const char *HWR_GetShaderName(INT32 shader);
extern customshaderxlat_t shaderxlat[]; extern customshaderxlat_t shaderxlat[];
extern CV_PossibleValue_t granisotropicmode_cons_t[]; extern CV_PossibleValue_t glanisotropicmode_cons_t[];
#ifdef ALAM_LIGHTING #ifdef ALAM_LIGHTING
extern consvar_t cv_gldynamiclighting; extern consvar_t cv_gldynamiclighting;
@ -87,7 +90,7 @@ extern consvar_t cv_glcoronas;
extern consvar_t cv_glcoronasize; extern consvar_t cv_glcoronasize;
#endif #endif
extern consvar_t cv_glshaders; extern consvar_t cv_glshaders, cv_glallowshaders;
extern consvar_t cv_glmodels; extern consvar_t cv_glmodels;
extern consvar_t cv_glmodelinterpolation; extern consvar_t cv_glmodelinterpolation;
extern consvar_t cv_glmodellighting; extern consvar_t cv_glmodellighting;
@ -130,6 +133,10 @@ extern int ps_hw_numcolors;
extern int ps_hw_batchsorttime; extern int ps_hw_batchsorttime;
extern int ps_hw_batchdrawtime; extern int ps_hw_batchdrawtime;
extern boolean gl_init;
extern boolean gl_maploaded;
extern boolean gl_maptexturesloaded;
extern boolean gl_sessioncommandsadded;
extern boolean gl_shadersavailable; extern boolean gl_shadersavailable;
#endif #endif

View file

@ -364,48 +364,53 @@ static GLTextureFormat_t PCX_Load(const char *filename, int *w, int *h,
// -----------------+ // -----------------+
static void md2_loadTexture(md2_t *model) static void md2_loadTexture(md2_t *model)
{ {
GLPatch_t *grpatch; patch_t *patch;
GLPatch_t *grPatch = NULL;
const char *filename = model->filename; const char *filename = model->filename;
if (model->grpatch) if (model->grpatch)
{ {
grpatch = model->grpatch; patch = model->grpatch;
Z_Free(grpatch->mipmap->data); grPatch = (GLPatch_t *)(patch->hardware);
if (grPatch)
Z_Free(grPatch->mipmap->data);
} }
else else
{ model->grpatch = patch = Patch_Create(NULL, 0, NULL);
grpatch = Z_Calloc(sizeof *grpatch, PU_HWRPATCHINFO,
&(model->grpatch));
grpatch->mipmap = Z_Calloc(sizeof (GLMipmap_t), PU_HWRPATCHINFO, NULL);
}
if (!grpatch->mipmap->downloaded && !grpatch->mipmap->data) if (!patch->hardware)
Patch_AllocateHardwarePatch(patch);
if (grPatch == NULL)
grPatch = (GLPatch_t *)(patch->hardware);
if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data)
{ {
int w = 0, h = 0; int w = 0, h = 0;
UINT32 size; UINT32 size;
RGBA_t *image; RGBA_t *image;
#ifdef HAVE_PNG #ifdef HAVE_PNG
grpatch->mipmap->format = PNG_Load(filename, &w, &h, grpatch); grPatch->mipmap->format = PNG_Load(filename, &w, &h, grPatch);
if (grpatch->mipmap->format == 0) if (grPatch->mipmap->format == 0)
#endif #endif
grpatch->mipmap->format = PCX_Load(filename, &w, &h, grpatch); grPatch->mipmap->format = PCX_Load(filename, &w, &h, grPatch);
if (grpatch->mipmap->format == 0) if (grPatch->mipmap->format == 0)
{ {
model->notexturefile = true; // mark it so its not searched for again repeatedly model->notexturefile = true; // mark it so its not searched for again repeatedly
return; return;
} }
grpatch->mipmap->downloaded = 0; grPatch->mipmap->downloaded = 0;
grpatch->mipmap->flags = 0; grPatch->mipmap->flags = 0;
grpatch->width = (INT16)w; patch->width = (INT16)w;
grpatch->height = (INT16)h; patch->height = (INT16)h;
grpatch->mipmap->width = (UINT16)w; grPatch->mipmap->width = (UINT16)w;
grpatch->mipmap->height = (UINT16)h; grPatch->mipmap->height = (UINT16)h;
// Lactozilla: Apply colour cube // Lactozilla: Apply colour cube
image = grpatch->mipmap->data; image = grPatch->mipmap->data;
size = w*h; size = w*h;
while (size--) while (size--)
{ {
@ -413,7 +418,7 @@ static void md2_loadTexture(md2_t *model)
image++; image++;
} }
} }
HWD.pfnSetTexture(grpatch->mipmap); HWD.pfnSetTexture(grPatch->mipmap);
} }
// -----------------+ // -----------------+
@ -421,48 +426,53 @@ static void md2_loadTexture(md2_t *model)
// -----------------+ // -----------------+
static void md2_loadBlendTexture(md2_t *model) static void md2_loadBlendTexture(md2_t *model)
{ {
GLPatch_t *grpatch; patch_t *patch;
GLPatch_t *grPatch = NULL;
char *filename = Z_Malloc(strlen(model->filename)+7, PU_STATIC, NULL); char *filename = Z_Malloc(strlen(model->filename)+7, PU_STATIC, NULL);
strcpy(filename, model->filename);
strcpy(filename, model->filename);
FIL_ForceExtension(filename, "_blend.png"); FIL_ForceExtension(filename, "_blend.png");
if (model->blendgrpatch) if (model->blendgrpatch)
{ {
grpatch = model->blendgrpatch; patch = model->blendgrpatch;
Z_Free(grpatch->mipmap->data); grPatch = (GLPatch_t *)(patch->hardware);
if (grPatch)
Z_Free(grPatch->mipmap->data);
} }
else else
{ model->blendgrpatch = patch = Patch_Create(NULL, 0, NULL);
grpatch = Z_Calloc(sizeof *grpatch, PU_HWRPATCHINFO,
&(model->blendgrpatch));
grpatch->mipmap = Z_Calloc(sizeof (GLMipmap_t), PU_HWRPATCHINFO, NULL);
}
if (!grpatch->mipmap->downloaded && !grpatch->mipmap->data) if (!patch->hardware)
Patch_AllocateHardwarePatch(patch);
if (grPatch == NULL)
grPatch = (GLPatch_t *)(patch->hardware);
if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data)
{ {
int w = 0, h = 0; int w = 0, h = 0;
#ifdef HAVE_PNG #ifdef HAVE_PNG
grpatch->mipmap->format = PNG_Load(filename, &w, &h, grpatch); grPatch->mipmap->format = PNG_Load(filename, &w, &h, grPatch);
if (grpatch->mipmap->format == 0) if (grPatch->mipmap->format == 0)
#endif #endif
grpatch->mipmap->format = PCX_Load(filename, &w, &h, grpatch); grPatch->mipmap->format = PCX_Load(filename, &w, &h, grPatch);
if (grpatch->mipmap->format == 0) if (grPatch->mipmap->format == 0)
{ {
model->noblendfile = true; // mark it so its not searched for again repeatedly model->noblendfile = true; // mark it so its not searched for again repeatedly
Z_Free(filename); Z_Free(filename);
return; return;
} }
grpatch->mipmap->downloaded = 0; grPatch->mipmap->downloaded = 0;
grpatch->mipmap->flags = 0; grPatch->mipmap->flags = 0;
grpatch->width = (INT16)w; patch->width = (INT16)w;
grpatch->height = (INT16)h; patch->height = (INT16)h;
grpatch->mipmap->width = (UINT16)w; grPatch->mipmap->width = (UINT16)w;
grpatch->mipmap->height = (UINT16)h; grPatch->mipmap->height = (UINT16)h;
} }
HWD.pfnSetTexture(grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary HWD.pfnSetTexture(grPatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary
Z_Free(filename); Z_Free(filename);
} }
@ -517,7 +527,7 @@ void HWR_InitModels(void)
return; return;
} }
} }
// length of the player model prefix // length of the player model prefix
prefixlen = strlen(PLAYERMODELPREFIX); prefixlen = strlen(PLAYERMODELPREFIX);
@ -692,8 +702,10 @@ spritemodelfound:
#define SETBRIGHTNESS(brightness,r,g,b) \ #define SETBRIGHTNESS(brightness,r,g,b) \
brightness = (UINT8)(((1063*(UINT16)(r))/5000) + ((3576*(UINT16)(g))/5000) + ((361*(UINT16)(b))/5000)) brightness = (UINT8)(((1063*(UINT16)(r))/5000) + ((3576*(UINT16)(g))/5000) + ((361*(UINT16)(b))/5000))
static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolornum_t color) static void HWR_CreateBlendedTexture(patch_t *gpatch, patch_t *blendgpatch, GLMipmap_t *grMipmap, INT32 skinnum, skincolornum_t color)
{ {
GLPatch_t *hwrPatch = gpatch->hardware;
GLPatch_t *hwrBlendPatch = blendgpatch->hardware;
UINT16 w = gpatch->width, h = gpatch->height; UINT16 w = gpatch->width, h = gpatch->height;
UINT32 size = w*h; UINT32 size = w*h;
RGBA_t *image, *blendimage, *cur, blendcolor; RGBA_t *image, *blendimage, *cur, blendcolor;
@ -706,28 +718,29 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
memset(translation, 0, sizeof(translation)); memset(translation, 0, sizeof(translation));
memset(cutoff, 0, sizeof(cutoff)); memset(cutoff, 0, sizeof(cutoff));
if (grmip->width == 0) if (grMipmap->width == 0)
{ {
grmip->width = gpatch->width; grMipmap->width = gpatch->width;
grmip->height = gpatch->height; grMipmap->height = gpatch->height;
// no wrap around, no chroma key // no wrap around, no chroma key
grmip->flags = 0; grMipmap->flags = 0;
// setup the texture info // setup the texture info
grmip->format = GL_TEXFMT_RGBA; grMipmap->format = GL_TEXFMT_RGBA;
} }
if (grmip->data) if (grMipmap->data)
{ {
Z_Free(grmip->data); Z_Free(grMipmap->data);
grmip->data = NULL; grMipmap->data = NULL;
} }
cur = Z_Malloc(size*4, PU_HWRMODELTEXTURE, &grmip->data); cur = Z_Malloc(size*4, PU_HWRMODELTEXTURE, &grMipmap->data);
memset(cur, 0x00, size*4); memset(cur, 0x00, size*4);
image = gpatch->mipmap->data; image = hwrPatch->mipmap->data;
blendimage = blendgpatch->mipmap->data; blendimage = hwrBlendPatch->mipmap->data;
// TC_METALSONIC includes an actual skincolor translation, on top of its flashing. // TC_METALSONIC includes an actual skincolor translation, on top of its flashing.
if (skinnum == TC_METALSONIC) if (skinnum == TC_METALSONIC)
@ -1066,37 +1079,39 @@ skippixel:
#undef SETBRIGHTNESS #undef SETBRIGHTNESS
static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT32 skinnum, const UINT8 *colormap, skincolornum_t color) static void HWR_GetBlendedTexture(patch_t *patch, patch_t *blendpatch, INT32 skinnum, const UINT8 *colormap, skincolornum_t color)
{ {
// mostly copied from HWR_GetMappedPatch, hence the similarities and comment // mostly copied from HWR_GetMappedPatch, hence the similarities and comment
GLMipmap_t *grmip, *newmip; GLPatch_t *grPatch = patch->hardware;
GLPatch_t *grBlendPatch = NULL;
GLMipmap_t *grMipmap, *newMipmap;
if (colormap == colormaps || colormap == NULL) if (blendpatch == NULL || colormap == colormaps || colormap == NULL)
{ {
// Don't do any blending // Don't do any blending
HWD.pfnSetTexture(gpatch->mipmap); HWD.pfnSetTexture(grPatch->mipmap);
return; return;
} }
if ((blendgpatch && blendgpatch->mipmap->format) if ((blendpatch && (grBlendPatch = blendpatch->hardware) && grBlendPatch->mipmap->format)
&& (gpatch->width != blendgpatch->width || gpatch->height != blendgpatch->height)) && (patch->width != blendpatch->width || patch->height != blendpatch->height))
{ {
// Blend image exists, but it's bad. // Blend image exists, but it's bad.
HWD.pfnSetTexture(gpatch->mipmap); HWD.pfnSetTexture(grPatch->mipmap);
return; return;
} }
// search for the mipmap // search for the mipmap
// skip the first (no colormap translated) // skip the first (no colormap translated)
for (grmip = gpatch->mipmap; grmip->nextcolormap; ) for (grMipmap = grPatch->mipmap; grMipmap->nextcolormap; )
{ {
grmip = grmip->nextcolormap; grMipmap = grMipmap->nextcolormap;
if (grmip->colormap == colormap) if (grMipmap->colormap == colormap)
{ {
if (grmip->downloaded && grmip->data) if (grMipmap->downloaded && grMipmap->data)
{ {
HWD.pfnSetTexture(grmip); // found the colormap, set it to the correct texture HWD.pfnSetTexture(grMipmap); // found the colormap, set it to the correct texture
Z_ChangeTag(grmip->data, PU_HWRMODELTEXTURE_UNLOCKED); Z_ChangeTag(grMipmap->data, PU_HWRMODELTEXTURE_UNLOCKED);
return; return;
} }
} }
@ -1107,18 +1122,18 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT
//BP: WARNING: don't free it manually without clearing the cache of harware renderer //BP: WARNING: don't free it manually without clearing the cache of harware renderer
// (it have a liste of mipmap) // (it have a liste of mipmap)
// this malloc is cleared in HWR_FreeTextureCache // this malloc is cleared in HWR_FreeColormapCache
// (...) unfortunately z_malloc fragment alot the memory :(so malloc is better // (...) unfortunately z_malloc fragment alot the memory :(so malloc is better
newmip = calloc(1, sizeof (*newmip)); newMipmap = calloc(1, sizeof (*newMipmap));
if (newmip == NULL) if (newMipmap == NULL)
I_Error("%s: Out of memory", "HWR_GetBlendedTexture"); I_Error("%s: Out of memory", "HWR_GetBlendedTexture");
grmip->nextcolormap = newmip; grMipmap->nextcolormap = newMipmap;
newmip->colormap = colormap; newMipmap->colormap = colormap;
HWR_CreateBlendedTexture(gpatch, blendgpatch, newmip, skinnum, color); HWR_CreateBlendedTexture(patch, blendpatch, newMipmap, skinnum, color);
HWD.pfnSetTexture(newmip); HWD.pfnSetTexture(newMipmap);
Z_ChangeTag(newmip->data, PU_HWRMODELTEXTURE_UNLOCKED); Z_ChangeTag(newMipmap->data, PU_HWRMODELTEXTURE_UNLOCKED);
} }
#define NORMALFOG 0x00000000 #define NORMALFOG 0x00000000
@ -1206,9 +1221,11 @@ static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t
} }
// Adjust texture coords of model to fit into a patch's max_s and max_t // Adjust texture coords of model to fit into a patch's max_s and max_t
static void adjustTextureCoords(model_t *model, GLPatch_t *gpatch) static void adjustTextureCoords(model_t *model, patch_t *patch)
{ {
int i; int i;
GLPatch_t *gpatch = ((GLPatch_t *)patch->hardware);
for (i = 0; i < model->numMeshes; i++) for (i = 0; i < model->numMeshes; i++)
{ {
int j; int j;
@ -1308,7 +1325,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
// Look at HWR_ProjectSprite for more // Look at HWR_ProjectSprite for more
{ {
GLPatch_t *gpatch; patch_t *gpatch, *blendgpatch;
GLPatch_t *hwrPatch = NULL, *hwrBlendPatch = NULL;
INT32 durs = spr->mobj->state->tics; INT32 durs = spr->mobj->state->tics;
INT32 tics = spr->mobj->tics; INT32 tics = spr->mobj->tics;
//mdlframe_t *next = NULL; //mdlframe_t *next = NULL;
@ -1326,15 +1344,16 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
//if (tics > durs) //if (tics > durs)
//durs = tics; //durs = tics;
if (spr->mobj->flags2 & MF2_SHADOW) if (spr->mobj->frame & FF_TRANSMASK)
Surf.PolyColor.s.alpha = 0x40; Surf.PolyFlags = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
else if (spr->mobj->frame & FF_TRANSMASK)
HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
else else
Surf.PolyColor.s.alpha = 0xFF; {
Surf.PolyColor.s.alpha = (spr->mobj->flags2 & MF2_SHADOW) ? 0x40 : 0xff;
Surf.PolyFlags = HWR_GetBlendModeFlag(spr->mobj->blendmode);
}
// dont forget to enabled the depth test because we can't do this like // don't forget to enable the depth test because we can't do this
// before: polygons models are not sorted // like before: model polygons are not sorted
// 1. load model+texture if not already loaded // 1. load model+texture if not already loaded
// 2. draw model with correct position, rotation,... // 2. draw model with correct position, rotation,...
@ -1353,14 +1372,26 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
// texture loading before model init, so it knows if sprite graphics are used, which // texture loading before model init, so it knows if sprite graphics are used, which
// means that texture coordinates have to be adjusted // means that texture coordinates have to be adjusted
gpatch = md2->grpatch; gpatch = md2->grpatch;
if (!gpatch || ((!gpatch->mipmap->format || !gpatch->mipmap->downloaded) && !md2->notexturefile)) if (gpatch)
md2_loadTexture(md2); hwrPatch = ((GLPatch_t *)gpatch->hardware);
gpatch = md2->grpatch; // Load it again, because it isn't being loaded into gpatch after md2_loadtexture...
if ((gpatch && gpatch->mipmap->format) // don't load the blend texture if the base texture isn't available if (!gpatch || !hwrPatch
&& (!md2->blendgrpatch || ((!hwrPatch->mipmap->format || !hwrPatch->mipmap->downloaded) && !md2->notexturefile))
|| ((!((GLPatch_t *)md2->blendgrpatch)->mipmap->format || !((GLPatch_t *)md2->blendgrpatch)->mipmap->downloaded) md2_loadTexture(md2);
&& !md2->noblendfile)))
// Load it again, because it isn't being loaded into gpatch after md2_loadtexture...
gpatch = md2->grpatch;
if (gpatch)
hwrPatch = ((GLPatch_t *)gpatch->hardware);
// Load blend texture
blendgpatch = md2->blendgrpatch;
if (blendgpatch)
hwrBlendPatch = ((GLPatch_t *)blendgpatch->hardware);
if ((gpatch && hwrPatch && hwrPatch->mipmap->format) // don't load the blend texture if the base texture isn't available
&& (!blendgpatch || !hwrBlendPatch
|| ((!hwrBlendPatch->mipmap->format || !hwrBlendPatch->mipmap->downloaded) && !md2->noblendfile)))
md2_loadBlendTexture(md2); md2_loadBlendTexture(md2);
if (md2->error) if (md2->error)
@ -1376,7 +1407,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
md2_printModelInfo(md2->model); md2_printModelInfo(md2->model);
// If model uses sprite patch as texture, then // If model uses sprite patch as texture, then
// adjust texture coordinates to take power of two textures into account // adjust texture coordinates to take power of two textures into account
if (!gpatch || !gpatch->mipmap->format) if (!gpatch || !hwrPatch->mipmap->format)
adjustTextureCoords(md2->model, spr->gpatch); adjustTextureCoords(md2->model, spr->gpatch);
// note down the max_s and max_t that end up in the VBO // note down the max_s and max_t that end up in the VBO
md2->model->vbo_max_s = md2->model->max_s; md2->model->vbo_max_s = md2->model->max_s;
@ -1395,7 +1426,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
finalscale = md2->scale; finalscale = md2->scale;
//Hurdler: arf, I don't like that implementation at all... too much crappy //Hurdler: arf, I don't like that implementation at all... too much crappy
if (gpatch && gpatch->mipmap->format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture if (gpatch && hwrPatch && hwrPatch->mipmap->format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture
{ {
INT32 skinnum = TC_DEFAULT; INT32 skinnum = TC_DEFAULT;
@ -1428,21 +1459,19 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
} }
// Translation or skin number found // Translation or skin number found
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolornum_t)spr->mobj->color); HWR_GetBlendedTexture(gpatch, blendgpatch, skinnum, spr->colormap, (skincolornum_t)spr->mobj->color);
} }
else else // Sprite
{ {
// Sprite
gpatch = spr->gpatch; //W_CachePatchNum(spr->patchlumpnum, PU_CACHE);
// Check if sprite dimensions are different from previously used sprite. // Check if sprite dimensions are different from previously used sprite.
// If so, uvs need to be readjusted. // If so, uvs need to be readjusted.
// Comparing floats with the != operator here should be okay because they // Comparing floats with the != operator here should be okay because they
// are just copies of glpatches' max_s and max_t values. // are just copies of glpatches' max_s and max_t values.
// Instead of the != operator, memcmp is used to avoid a compiler warning. // Instead of the != operator, memcmp is used to avoid a compiler warning.
if (memcmp(&(gpatch->max_s), &(md2->model->max_s), sizeof(md2->model->max_s)) != 0 || if (memcmp(&(hwrPatch->max_s), &(md2->model->max_s), sizeof(md2->model->max_s)) != 0 ||
memcmp(&(gpatch->max_t), &(md2->model->max_t), sizeof(md2->model->max_t)) != 0) memcmp(&(hwrPatch->max_t), &(md2->model->max_t), sizeof(md2->model->max_t)) != 0)
adjustTextureCoords(md2->model, gpatch); adjustTextureCoords(md2->model, spr->gpatch);
HWR_GetMappedPatch(gpatch, spr->colormap); HWR_GetMappedPatch(spr->gpatch, spr->colormap);
} }
if (spr->mobj->frame & FF_ANIMATE) if (spr->mobj->frame & FF_ANIMATE)

View file

@ -91,13 +91,6 @@ static GLuint startScreenWipe = 0;
static GLuint endScreenWipe = 0; static GLuint endScreenWipe = 0;
static GLuint finalScreenTexture = 0; static GLuint finalScreenTexture = 0;
// Lactozilla: Shader functions
static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade);
static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade);
static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum);
static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f};
// shortcut for ((float)1/i) // shortcut for ((float)1/i)
static const GLfloat byte2float[256] = { static const GLfloat byte2float[256] = {
0.000000f, 0.003922f, 0.007843f, 0.011765f, 0.015686f, 0.019608f, 0.023529f, 0.027451f, 0.000000f, 0.003922f, 0.007843f, 0.011765f, 0.015686f, 0.019608f, 0.023529f, 0.027451f,
@ -426,6 +419,10 @@ static PFNglBufferData pglBufferData;
typedef void (APIENTRY * PFNglDeleteBuffers) (GLsizei n, const GLuint *buffers); typedef void (APIENTRY * PFNglDeleteBuffers) (GLsizei n, const GLuint *buffers);
static PFNglDeleteBuffers pglDeleteBuffers; static PFNglDeleteBuffers pglDeleteBuffers;
/* 2.0 functions */
typedef void (APIENTRY * PFNglBlendEquation) (GLenum mode);
static PFNglBlendEquation pglBlendEquation;
/* 1.2 Parms */ /* 1.2 Parms */
/* GL_CLAMP_TO_EDGE_EXT */ /* GL_CLAMP_TO_EDGE_EXT */
@ -533,8 +530,8 @@ boolean SetupGLfunc(void)
return true; return true;
} }
static boolean gl_allowshaders = false;
static boolean gl_shadersenabled = false; static boolean gl_shadersenabled = false;
static hwdshaderoption_t gl_allowshaders = HWD_SHADEROPTION_OFF;
#ifdef GL_SHADERS #ifdef GL_SHADERS
typedef GLuint (APIENTRY *PFNglCreateShader) (GLenum); typedef GLuint (APIENTRY *PFNglCreateShader) (GLenum);
@ -544,6 +541,7 @@ typedef void (APIENTRY *PFNglGetShaderiv) (GLuint, GLenum, GLint*);
typedef void (APIENTRY *PFNglGetShaderInfoLog) (GLuint, GLsizei, GLsizei*, GLchar*); typedef void (APIENTRY *PFNglGetShaderInfoLog) (GLuint, GLsizei, GLsizei*, GLchar*);
typedef void (APIENTRY *PFNglDeleteShader) (GLuint); typedef void (APIENTRY *PFNglDeleteShader) (GLuint);
typedef GLuint (APIENTRY *PFNglCreateProgram) (void); typedef GLuint (APIENTRY *PFNglCreateProgram) (void);
typedef void (APIENTRY *PFNglDeleteProgram) (GLuint);
typedef void (APIENTRY *PFNglAttachShader) (GLuint, GLuint); typedef void (APIENTRY *PFNglAttachShader) (GLuint, GLuint);
typedef void (APIENTRY *PFNglLinkProgram) (GLuint); typedef void (APIENTRY *PFNglLinkProgram) (GLuint);
typedef void (APIENTRY *PFNglGetProgramiv) (GLuint, GLenum, GLint*); typedef void (APIENTRY *PFNglGetProgramiv) (GLuint, GLenum, GLint*);
@ -565,6 +563,7 @@ static PFNglGetShaderiv pglGetShaderiv;
static PFNglGetShaderInfoLog pglGetShaderInfoLog; static PFNglGetShaderInfoLog pglGetShaderInfoLog;
static PFNglDeleteShader pglDeleteShader; static PFNglDeleteShader pglDeleteShader;
static PFNglCreateProgram pglCreateProgram; static PFNglCreateProgram pglCreateProgram;
static PFNglDeleteProgram pglDeleteProgram;
static PFNglAttachShader pglAttachShader; static PFNglAttachShader pglAttachShader;
static PFNglLinkProgram pglLinkProgram; static PFNglLinkProgram pglLinkProgram;
static PFNglGetProgramiv pglGetProgramiv; static PFNglGetProgramiv pglGetProgramiv;
@ -579,12 +578,6 @@ static PFNglUniform2fv pglUniform2fv;
static PFNglUniform3fv pglUniform3fv; static PFNglUniform3fv pglUniform3fv;
static PFNglGetUniformLocation pglGetUniformLocation; static PFNglGetUniformLocation pglGetUniformLocation;
// 18032019
static GLuint gl_currentshaderprogram = 0;
static boolean gl_shaderprogramchanged = true;
static shadersource_t gl_customshaders[HWR_MAXSHADERS];
// 13062019 // 13062019
typedef enum typedef enum
{ {
@ -602,17 +595,37 @@ typedef enum
gluniform_max, gluniform_max,
} gluniform_t; } gluniform_t;
typedef struct gl_shaderprogram_s typedef struct gl_shader_s
{ {
GLuint program; GLuint program;
boolean custom;
GLint uniforms[gluniform_max+1]; GLint uniforms[gluniform_max+1];
} gl_shaderprogram_t; boolean custom;
static gl_shaderprogram_t gl_shaderprograms[HWR_MAXSHADERS]; } gl_shader_t;
static gl_shader_t gl_shaders[HWR_MAXSHADERS];
static gl_shader_t gl_usershaders[HWR_MAXSHADERS];
static shadersource_t gl_customshaders[HWR_MAXSHADERS];
// 09102020
typedef struct gl_shaderstate_s
{
gl_shader_t *current;
GLuint type;
GLuint program;
boolean changed;
} gl_shaderstate_t;
static gl_shaderstate_t gl_shaderstate;
// Shader info // Shader info
static INT32 shader_leveltime = 0; static INT32 shader_leveltime = 0;
// Lactozilla: Shader functions
static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader);
static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum);
static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade);
static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f};
// ================ // ================
// Vertex shaders // Vertex shaders
// ================ // ================
@ -865,6 +878,9 @@ void SetupGLFunc4(void)
pglBufferData = GetGLFunc("glBufferData"); pglBufferData = GetGLFunc("glBufferData");
pglDeleteBuffers = GetGLFunc("glDeleteBuffers"); pglDeleteBuffers = GetGLFunc("glDeleteBuffers");
/* 2.0 funcs */
pglBlendEquation = GetGLFunc("glBlendEquation");
#ifdef GL_SHADERS #ifdef GL_SHADERS
pglCreateShader = GetGLFunc("glCreateShader"); pglCreateShader = GetGLFunc("glCreateShader");
pglShaderSource = GetGLFunc("glShaderSource"); pglShaderSource = GetGLFunc("glShaderSource");
@ -873,6 +889,7 @@ void SetupGLFunc4(void)
pglGetShaderInfoLog = GetGLFunc("glGetShaderInfoLog"); pglGetShaderInfoLog = GetGLFunc("glGetShaderInfoLog");
pglDeleteShader = GetGLFunc("glDeleteShader"); pglDeleteShader = GetGLFunc("glDeleteShader");
pglCreateProgram = GetGLFunc("glCreateProgram"); pglCreateProgram = GetGLFunc("glCreateProgram");
pglDeleteProgram = GetGLFunc("glDeleteProgram");
pglAttachShader = GetGLFunc("glAttachShader"); pglAttachShader = GetGLFunc("glAttachShader");
pglLinkProgram = GetGLFunc("glLinkProgram"); pglLinkProgram = GetGLFunc("glLinkProgram");
pglGetProgramiv = GetGLFunc("glGetProgramiv"); pglGetProgramiv = GetGLFunc("glGetProgramiv");
@ -896,20 +913,40 @@ void SetupGLFunc4(void)
EXPORT boolean HWRAPI(CompileShaders) (void) EXPORT boolean HWRAPI(CompileShaders) (void)
{ {
#ifdef GL_SHADERS #ifdef GL_SHADERS
GLuint gl_vertShader, gl_fragShader; GLint i;
GLint i, result;
if (!pglUseProgram) return false; if (!pglUseProgram)
return false;
gl_customshaders[0].vertex = NULL; gl_customshaders[SHADER_DEFAULT].vertex = NULL;
gl_customshaders[0].fragment = NULL; gl_customshaders[SHADER_DEFAULT].fragment = NULL;
for (i = 0; gl_shadersources[i].vertex && gl_shadersources[i].fragment; i++) for (i = 0; gl_shadersources[i].vertex && gl_shadersources[i].fragment; i++)
{ {
gl_shaderprogram_t *shader; gl_shader_t *shader, *usershader;
const GLchar *vert_shader = gl_shadersources[i].vertex; const GLchar *vert_shader = gl_shadersources[i].vertex;
const GLchar *frag_shader = gl_shadersources[i].fragment; const GLchar *frag_shader = gl_shadersources[i].fragment;
boolean custom = ((gl_customshaders[i].vertex || gl_customshaders[i].fragment) && (i > 0));
if (i >= HWR_MAXSHADERS)
break;
shader = &gl_shaders[i];
usershader = &gl_usershaders[i];
if (shader->program)
pglDeleteProgram(shader->program);
if (usershader->program)
pglDeleteProgram(usershader->program);
shader->program = 0;
usershader->program = 0;
if (!Shader_CompileProgram(shader, i, vert_shader, frag_shader))
shader->program = 0;
// Compile custom shader
if ((i == SHADER_DEFAULT) || !(gl_customshaders[i].vertex || gl_customshaders[i].fragment))
continue;
// 18032019 // 18032019
if (gl_customshaders[i].vertex) if (gl_customshaders[i].vertex)
@ -917,92 +954,15 @@ EXPORT boolean HWRAPI(CompileShaders) (void)
if (gl_customshaders[i].fragment) if (gl_customshaders[i].fragment)
frag_shader = gl_customshaders[i].fragment; frag_shader = gl_customshaders[i].fragment;
if (i >= HWR_MAXSHADERS) if (!Shader_CompileProgram(usershader, i, vert_shader, frag_shader))
break;
shader = &gl_shaderprograms[i];
shader->program = 0;
shader->custom = custom;
//
// Load and compile vertex shader
//
gl_vertShader = pglCreateShader(GL_VERTEX_SHADER);
if (!gl_vertShader)
{ {
GL_MSG_Error("CompileShaders: Error creating vertex shader %s\n", HWR_GetShaderName(i)); GL_MSG_Warning("CompileShaders: Could not compile custom shader program for %s\n", HWR_GetShaderName(i));
continue; usershader->program = 0;
} }
pglShaderSource(gl_vertShader, 1, &vert_shader, NULL);
pglCompileShader(gl_vertShader);
// check for compile errors
pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
Shader_CompileError("Error compiling vertex shader", gl_vertShader, i);
continue;
}
//
// Load and compile fragment shader
//
gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER);
if (!gl_fragShader)
{
GL_MSG_Error("CompileShaders: Error creating fragment shader %s\n", HWR_GetShaderName(i));
continue;
}
pglShaderSource(gl_fragShader, 1, &frag_shader, NULL);
pglCompileShader(gl_fragShader);
// check for compile errors
pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
Shader_CompileError("Error compiling fragment shader", gl_fragShader, i);
continue;
}
shader->program = pglCreateProgram();
pglAttachShader(shader->program, gl_vertShader);
pglAttachShader(shader->program, gl_fragShader);
pglLinkProgram(shader->program);
// check link status
pglGetProgramiv(shader->program, GL_LINK_STATUS, &result);
// delete the shader objects
pglDeleteShader(gl_vertShader);
pglDeleteShader(gl_fragShader);
// couldn't link?
if (result != GL_TRUE)
{
shader->program = 0;
shader->custom = false;
GL_MSG_Error("CompileShaders: Error linking shader program %s\n", HWR_GetShaderName(i));
continue;
}
// 13062019
#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");
// misc. (custom shaders)
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
#undef GETUNI
} }
SetShader(SHADER_DEFAULT);
return true; return true;
#else #else
return false; return false;
@ -1070,26 +1030,45 @@ EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boole
#endif #endif
} }
EXPORT void HWRAPI(SetShader) (int shader) EXPORT void HWRAPI(SetShader) (int type)
{ {
#ifdef GL_SHADERS #ifdef GL_SHADERS
if (gl_allowshaders) if (gl_allowshaders != HWD_SHADEROPTION_OFF)
{ {
gl_shader_t *shader = gl_shaderstate.current;
// If using model lighting, set the appropriate shader. // If using model lighting, set the appropriate shader.
// However don't override a custom shader. // However don't override a custom shader.
if (shader == SHADER_MODEL && model_lighting if (type == SHADER_MODEL && model_lighting
&& !(gl_shaderprograms[SHADER_MODEL].custom && !gl_shaderprograms[SHADER_MODEL_LIGHTING].custom)) && !(gl_shaders[SHADER_MODEL].custom && !gl_shaders[SHADER_MODEL_LIGHTING].custom))
shader = SHADER_MODEL_LIGHTING; type = SHADER_MODEL_LIGHTING;
if ((GLuint)shader != gl_currentshaderprogram)
if ((shader == NULL) || (GLuint)type != gl_shaderstate.type)
{ {
gl_currentshaderprogram = shader; gl_shader_t *baseshader = &gl_shaders[type];
gl_shaderprogramchanged = true; gl_shader_t *usershader = &gl_usershaders[type];
if (usershader->program)
shader = (gl_allowshaders == HWD_SHADEROPTION_NOCUSTOM) ? baseshader : usershader;
else
shader = baseshader;
gl_shaderstate.current = shader;
gl_shaderstate.type = type;
gl_shaderstate.changed = true;
} }
gl_shadersenabled = true;
if (gl_shaderstate.program != shader->program)
{
gl_shaderstate.program = shader->program;
gl_shaderstate.changed = true;
}
gl_shadersenabled = (shader->program != 0);
return; return;
} }
#else #else
(void)shader; (void)type;
#endif #endif
gl_shadersenabled = false; gl_shadersenabled = false;
} }
@ -1097,11 +1076,15 @@ EXPORT void HWRAPI(SetShader) (int shader)
EXPORT void HWRAPI(UnSetShader) (void) EXPORT void HWRAPI(UnSetShader) (void)
{ {
#ifdef GL_SHADERS #ifdef GL_SHADERS
gl_shadersenabled = false; gl_shaderstate.current = NULL;
gl_currentshaderprogram = 0; gl_shaderstate.type = 0;
if (!pglUseProgram) return; gl_shaderstate.program = 0;
pglUseProgram(0);
if (pglUseProgram)
pglUseProgram(0);
#endif #endif
gl_shadersenabled = false;
} }
EXPORT void HWRAPI(CleanShaders) (void) EXPORT void HWRAPI(CleanShaders) (void)
@ -1258,6 +1241,7 @@ void SetStates(void)
pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
pglEnable(GL_ALPHA_TEST);
pglAlphaFunc(GL_NOTEQUAL, 0.0f); pglAlphaFunc(GL_NOTEQUAL, 0.0f);
//pglBlendFunc(GL_ONE, GL_ZERO); // copy pixel to frame buffer (opaque) //pglBlendFunc(GL_ONE, GL_ZERO); // copy pixel to frame buffer (opaque)
@ -1300,6 +1284,17 @@ void SetStates(void)
} }
// -----------------+
// DeleteTexture : Deletes a texture from the GPU and frees its data
// -----------------+
EXPORT void HWRAPI(DeleteTexture) (FTextureInfo *pTexInfo)
{
if (pTexInfo->downloaded)
pglDeleteTextures(1, (GLuint *)&pTexInfo->downloaded);
pTexInfo->downloaded = 0;
}
// -----------------+ // -----------------+
// Flush : flush OpenGL textures // Flush : flush OpenGL textures
// : Clear list of downloaded mipmaps // : Clear list of downloaded mipmaps
@ -1310,17 +1305,24 @@ void Flush(void)
while (gl_cachehead) while (gl_cachehead)
{ {
if (gl_cachehead->downloaded) DeleteTexture(gl_cachehead);
pglDeleteTextures(1, (GLuint *)&gl_cachehead->downloaded);
gl_cachehead->downloaded = 0;
gl_cachehead = gl_cachehead->nextmipmap; gl_cachehead = gl_cachehead->nextmipmap;
} }
gl_cachetail = gl_cachehead = NULL; //Hurdler: well, gl_cachehead is already NULL
ClearCacheList(); //Hurdler: well, gl_cachehead is already NULL
tex_downloaded = 0; tex_downloaded = 0;
} }
// -----------------+
// ClearCacheList : Clears the texture cache tail and head
// -----------------+
EXPORT void HWRAPI(ClearCacheList) (void)
{
gl_cachetail = gl_cachehead = NULL;
}
// -----------------+ // -----------------+
// isExtAvailable : Look if an OpenGL extension is available // isExtAvailable : Look if an OpenGL extension is available
// Returns : true if extension available // Returns : true if extension available
@ -1517,64 +1519,110 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1,
pglEnable(GL_TEXTURE_2D); pglEnable(GL_TEXTURE_2D);
} }
static void Clamp2D(GLenum pname)
{
pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP); // fallback clamp
pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP_TO_EDGE);
}
// -----------------+ // -----------------+
// SetBlend : Set render mode // SetBlend : Set render mode
// -----------------+ // -----------------+
// PF_Masked - we could use an ALPHA_TEST of GL_EQUAL, and alpha ref of 0, // PF_Masked - we could use an ALPHA_TEST of GL_EQUAL, and alpha ref of 0,
// is it faster when pixels are discarded ? // is it faster when pixels are discarded ?
static void Clamp2D(GLenum pname)
{
pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP); // fallback clamp
pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP_TO_EDGE);
}
static void SetBlendEquation(GLenum mode)
{
if (pglBlendEquation)
pglBlendEquation(mode);
}
static void SetBlendMode(FBITFIELD flags)
{
// Set blending function
switch (flags)
{
case PF_Translucent & PF_Blending:
pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency
break;
case PF_Masked & PF_Blending:
// Hurdler: does that mean lighting is only made by alpha src?
// it sounds ok, but not for polygonsmooth
pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture
break;
case PF_Additive & PF_Blending:
case PF_Subtractive & PF_Blending:
case PF_ReverseSubtract & PF_Blending:
case PF_Environment & PF_Blending:
pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
break;
case PF_AdditiveSource & PF_Blending:
pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest
break;
case PF_Multiplicative & PF_Blending:
pglBlendFunc(GL_DST_COLOR, GL_ZERO);
break;
case PF_Fog & PF_Fog:
// Sryder: Fog
// multiplies input colour by input alpha, and destination colour by input colour, then adds them
pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR);
break;
default: // must be 0, otherwise it's an error
// No blending
pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending
break;
}
// Set blending equation
switch (flags)
{
case PF_Subtractive & PF_Blending:
SetBlendEquation(GL_FUNC_SUBTRACT);
break;
case PF_ReverseSubtract & PF_Blending:
// good for shadow
// not really but what else ?
SetBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
break;
default:
SetBlendEquation(GL_FUNC_ADD);
break;
}
// Alpha test
switch (flags)
{
case PF_Masked & PF_Blending:
pglAlphaFunc(GL_GREATER, 0.5f);
break;
case PF_Translucent & PF_Blending:
case PF_Additive & PF_Blending:
case PF_AdditiveSource & PF_Blending:
case PF_Subtractive & PF_Blending:
case PF_ReverseSubtract & PF_Blending:
case PF_Environment & PF_Blending:
case PF_Multiplicative & PF_Blending:
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Fog & PF_Fog:
pglAlphaFunc(GL_ALWAYS, 0.0f); // Don't discard zero alpha fragments
break;
default:
pglAlphaFunc(GL_GREATER, 0.5f);
break;
}
}
EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
{ {
FBITFIELD Xor; FBITFIELD Xor;
Xor = CurrentPolyFlags^PolyFlags; Xor = CurrentPolyFlags^PolyFlags;
if (Xor & (PF_Blending|PF_RemoveYWrap|PF_ForceWrapX|PF_ForceWrapY|PF_Occlude|PF_NoTexture|PF_Modulated|PF_NoDepthTest|PF_Decal|PF_Invisible|PF_NoAlphaTest)) if (Xor & (PF_Blending|PF_RemoveYWrap|PF_ForceWrapX|PF_ForceWrapY|PF_Occlude|PF_NoTexture|PF_Modulated|PF_NoDepthTest|PF_Decal|PF_Invisible))
{ {
if (Xor&(PF_Blending)) // if blending mode must be changed if (Xor & PF_Blending) // if blending mode must be changed
{ SetBlendMode(PolyFlags & PF_Blending);
switch (PolyFlags & PF_Blending) {
case PF_Translucent & PF_Blending:
pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Masked & PF_Blending:
// Hurdler: does that mean lighting is only made by alpha src?
// it sounds ok, but not for polygonsmooth
pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture
pglAlphaFunc(GL_GREATER, 0.5f);
break;
case PF_Additive & PF_Blending:
pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Environment & PF_Blending:
pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Substractive & PF_Blending:
// good for shadow
// not really but what else ?
pglBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Fog & PF_Fog:
// Sryder: Fog
// multiplies input colour by input alpha, and destination colour by input colour, then adds them
pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR);
pglAlphaFunc(GL_ALWAYS, 0.0f); // Don't discard zero alpha fragments
break;
default : // must be 0, otherwise it's an error
// No blending
pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending
pglAlphaFunc(GL_GREATER, 0.5f);
break;
}
}
if (Xor & PF_NoAlphaTest) if (Xor & PF_NoAlphaTest)
{ {
if (PolyFlags & PF_NoAlphaTest) if (PolyFlags & PF_NoAlphaTest)
@ -1591,7 +1639,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
pglDisable(GL_POLYGON_OFFSET_FILL); pglDisable(GL_POLYGON_OFFSET_FILL);
} }
if (Xor&PF_NoDepthTest) if (Xor & PF_NoDepthTest)
{ {
if (PolyFlags & PF_NoDepthTest) if (PolyFlags & PF_NoDepthTest)
pglDepthFunc(GL_ALWAYS); //pglDisable(GL_DEPTH_TEST); pglDepthFunc(GL_ALWAYS); //pglDisable(GL_DEPTH_TEST);
@ -1599,25 +1647,25 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
pglDepthFunc(GL_LEQUAL); //pglEnable(GL_DEPTH_TEST); pglDepthFunc(GL_LEQUAL); //pglEnable(GL_DEPTH_TEST);
} }
if (Xor&PF_RemoveYWrap) if (Xor & PF_RemoveYWrap)
{ {
if (PolyFlags & PF_RemoveYWrap) if (PolyFlags & PF_RemoveYWrap)
Clamp2D(GL_TEXTURE_WRAP_T); Clamp2D(GL_TEXTURE_WRAP_T);
} }
if (Xor&PF_ForceWrapX) if (Xor & PF_ForceWrapX)
{ {
if (PolyFlags & PF_ForceWrapX) if (PolyFlags & PF_ForceWrapX)
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
} }
if (Xor&PF_ForceWrapY) if (Xor & PF_ForceWrapY)
{ {
if (PolyFlags & PF_ForceWrapY) if (PolyFlags & PF_ForceWrapY)
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
} }
if (Xor&PF_Modulated) if (Xor & PF_Modulated)
{ {
#if defined (__unix__) || defined (UNIXCOMMON) #if defined (__unix__) || defined (UNIXCOMMON)
if (oglflags & GLF_NOTEXENV) if (oglflags & GLF_NOTEXENV)
@ -1891,52 +1939,36 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo)
{ {
UpdateTexture(pTexInfo); UpdateTexture(pTexInfo);
pTexInfo->nextmipmap = NULL; pTexInfo->nextmipmap = NULL;
// insertion at the tail
if (gl_cachetail) if (gl_cachetail)
{ // insertion at the tail {
gl_cachetail->nextmipmap = pTexInfo; gl_cachetail->nextmipmap = pTexInfo;
gl_cachetail = pTexInfo; gl_cachetail = pTexInfo;
} }
else // initialization of the linked list else // initialization of the linked list
gl_cachetail = gl_cachehead = pTexInfo; gl_cachetail = gl_cachehead = pTexInfo;
} }
} }
static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade)
{
#ifdef GL_SHADERS
if (gl_shadersenabled && pglUseProgram)
{
gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram];
if (shader->program)
{
if (gl_shaderprogramchanged)
{
pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program);
gl_shaderprogramchanged = false;
}
Shader_SetUniforms(Surface, poly, tint, fade);
return shader;
}
else
pglUseProgram(0);
}
#else
(void)Surface;
(void)poly;
(void)tint;
(void)fade;
#endif
return NULL;
}
static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade)
{ {
#ifdef GL_SHADERS #ifdef GL_SHADERS
if (gl_shadersenabled) gl_shader_t *shader = gl_shaderstate.current;
if (gl_shadersenabled && (shader != NULL) && pglUseProgram)
{ {
gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram];
if (!shader->program) if (!shader->program)
{
pglUseProgram(0);
return; return;
}
if (gl_shaderstate.changed)
{
pglUseProgram(shader->program);
gl_shaderstate.changed = false;
}
// Color uniforms can be left NULL and will be set to white (1.0f, 1.0f, 1.0f, 1.0f) // Color uniforms can be left NULL and will be set to white (1.0f, 1.0f, 1.0f, 1.0f)
if (poly == NULL) if (poly == NULL)
@ -1989,6 +2021,97 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF
#endif #endif
} }
static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader)
{
GLuint gl_vertShader, gl_fragShader;
GLint result;
//
// Load and compile vertex shader
//
gl_vertShader = pglCreateShader(GL_VERTEX_SHADER);
if (!gl_vertShader)
{
GL_MSG_Error("Shader_CompileProgram: Error creating vertex shader %s\n", HWR_GetShaderName(i));
return false;
}
pglShaderSource(gl_vertShader, 1, &vert_shader, NULL);
pglCompileShader(gl_vertShader);
// check for compile errors
pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
Shader_CompileError("Error compiling vertex shader", gl_vertShader, i);
pglDeleteShader(gl_vertShader);
return false;
}
//
// Load and compile fragment shader
//
gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER);
if (!gl_fragShader)
{
GL_MSG_Error("Shader_CompileProgram: Error creating fragment shader %s\n", HWR_GetShaderName(i));
pglDeleteShader(gl_vertShader);
pglDeleteShader(gl_fragShader);
return false;
}
pglShaderSource(gl_fragShader, 1, &frag_shader, NULL);
pglCompileShader(gl_fragShader);
// check for compile errors
pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
Shader_CompileError("Error compiling fragment shader", gl_fragShader, i);
pglDeleteShader(gl_vertShader);
pglDeleteShader(gl_fragShader);
return false;
}
shader->program = pglCreateProgram();
pglAttachShader(shader->program, gl_vertShader);
pglAttachShader(shader->program, gl_fragShader);
pglLinkProgram(shader->program);
// check link status
pglGetProgramiv(shader->program, GL_LINK_STATUS, &result);
// delete the shader objects
pglDeleteShader(gl_vertShader);
pglDeleteShader(gl_fragShader);
// couldn't link?
if (result != GL_TRUE)
{
GL_MSG_Error("Shader_CompileProgram: Error linking shader program %s\n", HWR_GetShaderName(i));
pglDeleteProgram(shader->program);
return false;
}
// 13062019
#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");
// misc. (custom shaders)
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
#undef GETUNI
return true;
}
static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum) static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum)
{ {
GLchar *infoLog = NULL; GLchar *infoLog = NULL;
@ -2002,7 +2125,7 @@ static void Shader_CompileError(const char *message, GLuint program, INT32 shade
pglGetShaderInfoLog(program, logLength, NULL, infoLog); pglGetShaderInfoLog(program, logLength, NULL, infoLog);
} }
GL_MSG_Error("CompileShaders: %s (%s)\n%s", message, HWR_GetShaderName(shadernum), (infoLog ? infoLog : "")); GL_MSG_Error("Shader_CompileProgram: %s (%s)\n%s", message, HWR_GetShaderName(shadernum), (infoLog ? infoLog : ""));
if (infoLog) if (infoLog)
free(infoLog); free(infoLog);
@ -2112,7 +2235,7 @@ static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD
pglColor4ubv(c); pglColor4ubv(c);
} }
Shader_Load(pSurf, &poly, &tint, &fade); Shader_SetUniforms(pSurf, &poly, &tint, &fade);
} }
// -----------------+ // -----------------+
@ -2158,7 +2281,7 @@ EXPORT void HWRAPI(RenderSkyDome) (gl_sky_t *sky)
{ {
int i, j; int i, j;
Shader_Load(NULL, NULL, NULL, NULL); Shader_SetUniforms(NULL, NULL, NULL, NULL);
// Build the sky dome! Yes! // Build the sky dome! Yes!
if (sky->rebuild) if (sky->rebuild)
@ -2250,15 +2373,7 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value)
break; break;
case HWD_SET_SHADERS: case HWD_SET_SHADERS:
switch (Value) gl_allowshaders = (hwdshaderoption_t)Value;
{
case 1:
gl_allowshaders = true;
break;
default:
gl_allowshaders = false;
break;
}
break; break;
case HWD_SET_TEXTUREFILTERMODE: case HWD_SET_TEXTUREFILTERMODE:
@ -2528,6 +2643,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
boolean useVBO = true; boolean useVBO = true;
FBITFIELD flags;
int i; int i;
// Because otherwise, scaling the screen negatively vertically breaks the lighting // Because otherwise, scaling the screen negatively vertically breaks the lighting
@ -2595,8 +2711,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
else else
pglColor4ubv((GLubyte*)&Surface->PolyColor.s); pglColor4ubv((GLubyte*)&Surface->PolyColor.s);
SetBlend((poly.alpha < 1 ? PF_Translucent : (PF_Masked|PF_Occlude))|PF_Modulated);
tint.red = byte2float[Surface->TintColor.s.red]; tint.red = byte2float[Surface->TintColor.s.red];
tint.green = byte2float[Surface->TintColor.s.green]; tint.green = byte2float[Surface->TintColor.s.green];
tint.blue = byte2float[Surface->TintColor.s.blue]; tint.blue = byte2float[Surface->TintColor.s.blue];
@ -2607,7 +2721,14 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
fade.blue = byte2float[Surface->FadeColor.s.blue]; fade.blue = byte2float[Surface->FadeColor.s.blue];
fade.alpha = byte2float[Surface->FadeColor.s.alpha]; fade.alpha = byte2float[Surface->FadeColor.s.alpha];
Shader_Load(Surface, &poly, &tint, &fade); flags = (Surface->PolyFlags | PF_Modulated);
if (Surface->PolyFlags & (PF_Additive|PF_AdditiveSource|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative))
flags |= PF_Occlude;
else if (Surface->PolyColor.s.alpha == 0xFF)
flags |= (PF_Occlude | PF_Masked);
SetBlend(flags);
Shader_SetUniforms(Surface, &poly, &tint, &fade);
pglEnable(GL_CULL_FACE); pglEnable(GL_CULL_FACE);
pglEnable(GL_NORMALIZE); pglEnable(GL_NORMALIZE);
@ -3176,7 +3297,7 @@ EXPORT void HWRAPI(DoScreenWipe)(void)
pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
SetBlend(PF_Modulated|PF_NoDepthTest|PF_Clip|PF_NoZClip); SetBlend(PF_Modulated|PF_NoDepthTest);
pglEnable(GL_TEXTURE_2D); pglEnable(GL_TEXTURE_2D);
// Draw the original screen // Draw the original screen
@ -3186,7 +3307,7 @@ EXPORT void HWRAPI(DoScreenWipe)(void)
pglVertexPointer(3, GL_FLOAT, 0, screenVerts); pglVertexPointer(3, GL_FLOAT, 0, screenVerts);
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest|PF_Clip|PF_NoZClip); SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest);
// Draw the end screen that fades in // Draw the end screen that fades in
pglActiveTexture(GL_TEXTURE0); pglActiveTexture(GL_TEXTURE0);

View file

@ -1794,8 +1794,8 @@ static void HU_DrawChat_Old(void)
size_t i = 0; size_t i = 0;
const char *ntalk = "Say: ", *ttalk = "Say-Team: "; const char *ntalk = "Say: ", *ttalk = "Say-Team: ";
const char *talk = ntalk; const char *talk = ntalk;
INT32 charwidth = 8 * con_scalefactor; //SHORT(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor; INT32 charwidth = 8 * con_scalefactor; //(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor;
INT32 charheight = 8 * con_scalefactor; //SHORT(hu_font['A'-HU_FONTSTART]->height) * con_scalefactor; INT32 charheight = 8 * con_scalefactor; //(hu_font['A'-HU_FONTSTART]->height) * con_scalefactor;
if (teamtalk) if (teamtalk)
{ {
talk = ttalk; talk = ttalk;
@ -1816,7 +1816,7 @@ static void HU_DrawChat_Old(void)
} }
else else
{ {
//charwidth = SHORT(hu_font[talk[i]-HU_FONTSTART]->width) * con_scalefactor; //charwidth = (hu_font[talk[i]-HU_FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | cv_constextsize.value | V_NOSCALESTART, true); V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | cv_constextsize.value | V_NOSCALESTART, true);
} }
c += charwidth; c += charwidth;
@ -1844,7 +1844,7 @@ static void HU_DrawChat_Old(void)
} }
else else
{ {
//charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor; //charwidth = (hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | cv_constextsize.value | V_NOSCALESTART | t, true); V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | cv_constextsize.value | V_NOSCALESTART | t, true);
} }
@ -2364,7 +2364,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
} }
if (players[tab[i].num].exiting || (players[tab[i].num].pflags & PF_FINISHED)) if (players[tab[i].num].exiting || (players[tab[i].num].pflags & PF_FINISHED))
V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon); V_DrawSmallScaledPatch(x - exiticon->width/2 - 1, y-3, 0, exiticon);
if (gametyperankings[gametype] == GT_RACE) if (gametyperankings[gametype] == GT_RACE)
{ {
@ -2668,7 +2668,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
V_DrawSmallScaledPatch(x-28, y-4, 0, tagico); V_DrawSmallScaledPatch(x-28, y-4, 0, tagico);
if (players[tab[i].num].exiting || (players[tab[i].num].pflags & PF_FINISHED)) if (players[tab[i].num].exiting || (players[tab[i].num].pflags & PF_FINISHED))
V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon); V_DrawSmallScaledPatch(x - exiticon->width/2 - 1, y-3, 0, exiticon);
// Draw emeralds // Draw emeralds
if (players[tab[i].num].powers[pw_invulnerability] && (players[tab[i].num].powers[pw_invulnerability] == players[tab[i].num].powers[pw_sneakers]) && ((leveltime/7) & 1)) if (players[tab[i].num].powers[pw_invulnerability] && (players[tab[i].num].powers[pw_invulnerability] == players[tab[i].num].powers[pw_sneakers]) && ((leveltime/7) & 1))
@ -3094,7 +3094,7 @@ static void HU_DrawCoopOverlay(void)
if (LUA_HudEnabled(hud_tabemblems) && (!modifiedgame || savemoddata)) if (LUA_HudEnabled(hud_tabemblems) && (!modifiedgame || savemoddata))
{ {
V_DrawString(160, 144, 0, va("- %d/%d", M_CountEmblems(), numemblems+numextraemblems)); V_DrawString(160, 144, 0, va("- %d/%d", M_CountEmblems(), numemblems+numextraemblems));
V_DrawScaledPatch(128, 144 - SHORT(emblemicon->height)/4, 0, emblemicon); V_DrawScaledPatch(128, 144 - emblemicon->height/4, 0, emblemicon);
} }
if (!LUA_HudEnabled(hud_coopemeralds)) if (!LUA_HudEnabled(hud_coopemeralds))

View file

@ -21,15 +21,12 @@
// copied from SDL mixer, plus GME // copied from SDL mixer, plus GME
typedef enum { typedef enum {
MU_NONE, MU_NONE,
MU_CMD,
MU_WAV, MU_WAV,
MU_MOD, MU_MOD,
MU_MID, MU_MID,
MU_OGG, MU_OGG,
MU_MP3, MU_MP3,
MU_MP3_MAD_UNUSED, // use MU_MP3 instead
MU_FLAC, MU_FLAC,
MU_MODPLUG_UNUSED, // use MU_MOD instead
MU_GME, MU_GME,
MU_MOD_EX, // libopenmpt MU_MOD_EX, // libopenmpt
MU_MID_EX // Non-native MIDI MU_MID_EX // Non-native MIDI

View file

@ -36,10 +36,9 @@ typedef enum
*/ */
extern rendermode_t rendermode; extern rendermode_t rendermode;
/** \brief OpenGL state /** \brief render mode set by command line arguments
0 = never loaded, 1 = loaded successfully, -1 = failed loading
*/ */
extern INT32 vid_opengl_state; extern rendermode_t chosenrendermode;
/** \brief use highcolor modes if true /** \brief use highcolor modes if true
*/ */
@ -90,8 +89,9 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h);
INT32 VID_SetMode(INT32 modenum); INT32 VID_SetMode(INT32 modenum);
/** \brief Checks the render state /** \brief Checks the render state
\return true if the renderer changed
*/ */
void VID_CheckRenderer(void); boolean VID_CheckRenderer(void);
/** \brief Load OpenGL mode /** \brief Load OpenGL mode
*/ */

View file

@ -19,11 +19,279 @@
#include "sounds.h" #include "sounds.h"
#include "m_fixed.h" #include "m_fixed.h"
// dehacked.c now has lists for the more named enums! PLEASE keep them up to date! // deh_tables.c now has lists for the more named enums! PLEASE keep them up to date!
// For great modding!! // For great modding!!
// IMPORTANT!
// DO NOT FORGET TO SYNC THIS LIST WITH THE ACTIONPOINTERS ARRAY IN DEH_TABLES.C
enum actionnum
{
A_EXPLODE = 0,
A_PAIN,
A_FALL,
A_MONITORPOP,
A_GOLDMONITORPOP,
A_GOLDMONITORRESTORE,
A_GOLDMONITORSPARKLE,
A_LOOK,
A_CHASE,
A_FACESTABCHASE,
A_FACESTABREV,
A_FACESTABHURL,
A_FACESTABMISS,
A_STATUEBURST,
A_FACETARGET,
A_FACETRACER,
A_SCREAM,
A_BOSSDEATH,
A_CUSTOMPOWER,
A_GIVEWEAPON,
A_RINGBOX,
A_INVINCIBILITY,
A_SUPERSNEAKERS,
A_BUNNYHOP,
A_BUBBLESPAWN,
A_FANBUBBLESPAWN,
A_BUBBLERISE,
A_BUBBLECHECK,
A_AWARDSCORE,
A_EXTRALIFE,
A_GIVESHIELD,
A_GRAVITYBOX,
A_SCORERISE,
A_ATTRACTCHASE,
A_DROPMINE,
A_FISHJUMP,
A_THROWNRING,
A_SETSOLIDSTEAM,
A_UNSETSOLIDSTEAM,
A_SIGNSPIN,
A_SIGNPLAYER,
A_OVERLAYTHINK,
A_JETCHASE,
A_JETBTHINK,
A_JETGTHINK,
A_JETGSHOOT,
A_SHOOTBULLET,
A_MINUSDIGGING,
A_MINUSPOPUP,
A_MINUSCHECK,
A_CHICKENCHECK,
A_MOUSETHINK,
A_DETONCHASE,
A_CAPECHASE,
A_ROTATESPIKEBALL,
A_SLINGAPPEAR,
A_UNIDUSBALL,
A_ROCKSPAWN,
A_SETFUSE,
A_CRAWLACOMMANDERTHINK,
A_SMOKETRAILER,
A_RINGEXPLODE,
A_OLDRINGEXPLODE,
A_MIXUP,
A_RECYCLEPOWERS,
A_BOSS1CHASE,
A_FOCUSTARGET,
A_BOSS2CHASE,
A_BOSS2POGO,
A_BOSSZOOM,
A_BOSSSCREAM,
A_BOSS2TAKEDAMAGE,
A_BOSS7CHASE,
A_GOOPSPLAT,
A_BOSS2POGOSFX,
A_BOSS2POGOTARGET,
A_BOSSJETFUME,
A_EGGMANBOX,
A_TURRETFIRE,
A_SUPERTURRETFIRE,
A_TURRETSTOP,
A_JETJAWROAM,
A_JETJAWCHOMP,
A_POINTYTHINK,
A_CHECKBUDDY,
A_HOODFIRE,
A_HOODTHINK,
A_HOODFALL,
A_ARROWBONKS,
A_SNAILERTHINK,
A_SHARPCHASE,
A_SHARPSPIN,
A_SHARPDECEL,
A_CRUSHSTACEANWALK,
A_CRUSHSTACEANPUNCH,
A_CRUSHCLAWAIM,
A_CRUSHCLAWLAUNCH,
A_VULTUREVTOL,
A_VULTURECHECK,
A_VULTUREHOVER,
A_VULTUREBLAST,
A_VULTUREFLY,
A_SKIMCHASE,
A_1UPTHINKER,
A_SKULLATTACK,
A_LOBSHOT,
A_FIRESHOT,
A_SUPERFIRESHOT,
A_BOSSFIRESHOT,
A_BOSS7FIREMISSILES,
A_BOSS1LASER,
A_BOSS4REVERSE,
A_BOSS4SPEEDUP,
A_BOSS4RAISE,
A_SPARKFOLLOW,
A_BUZZFLY,
A_GUARDCHASE,
A_EGGSHIELD,
A_SETREACTIONTIME,
A_BOSS1SPIKEBALLS,
A_BOSS3TAKEDAMAGE,
A_BOSS3PATH,
A_BOSS3SHOCKTHINK,
A_LINEDEFEXECUTE,
A_PLAYSEESOUND,
A_PLAYATTACKSOUND,
A_PLAYACTIVESOUND,
A_SPAWNOBJECTABSOLUTE,
A_SPAWNOBJECTRELATIVE,
A_CHANGEANGLERELATIVE,
A_CHANGEANGLEABSOLUTE,
A_ROLLANGLE,
A_CHANGEROLLANGLERELATIVE,
A_CHANGEROLLANGLEABSOLUTE,
A_PLAYSOUND,
A_FINDTARGET,
A_FINDTRACER,
A_SETTICS,
A_SETRANDOMTICS,
A_CHANGECOLORRELATIVE,
A_CHANGECOLORABSOLUTE,
A_DYE,
A_MOVERELATIVE,
A_MOVEABSOLUTE,
A_THRUST,
A_ZTHRUST,
A_SETTARGETSTARGET,
A_SETOBJECTFLAGS,
A_SETOBJECTFLAGS2,
A_RANDOMSTATE,
A_RANDOMSTATERANGE,
A_DUALACTION,
A_REMOTEACTION,
A_TOGGLEFLAMEJET,
A_ORBITNIGHTS,
A_GHOSTME,
A_SETOBJECTSTATE,
A_SETOBJECTTYPESTATE,
A_KNOCKBACK,
A_PUSHAWAY,
A_RINGDRAIN,
A_SPLITSHOT,
A_MISSILESPLIT,
A_MULTISHOT,
A_INSTALOOP,
A_CUSTOM3DROTATE,
A_SEARCHFORPLAYERS,
A_CHECKRANDOM,
A_CHECKTARGETRINGS,
A_CHECKRINGS,
A_CHECKTOTALRINGS,
A_CHECKHEALTH,
A_CHECKRANGE,
A_CHECKHEIGHT,
A_CHECKTRUERANGE,
A_CHECKTHINGCOUNT,
A_CHECKAMBUSH,
A_CHECKCUSTOMVALUE,
A_CHECKCUSVALMEMO,
A_SETCUSTOMVALUE,
A_USECUSVALMEMO,
A_RELAYCUSTOMVALUE,
A_CUSVALACTION,
A_FORCESTOP,
A_FORCEWIN,
A_SPIKERETRACT,
A_INFOSTATE,
A_REPEAT,
A_SETSCALE,
A_REMOTEDAMAGE,
A_HOMINGCHASE,
A_TRAPSHOT,
A_VILETARGET,
A_VILEATTACK,
A_VILEFIRE,
A_BRAKCHASE,
A_BRAKFIRESHOT,
A_BRAKLOBSHOT,
A_NAPALMSCATTER,
A_SPAWNFRESHCOPY,
A_FLICKYSPAWN,
A_FLICKYCENTER,
A_FLICKYAIM,
A_FLICKYFLY,
A_FLICKYSOAR,
A_FLICKYCOAST,
A_FLICKYHOP,
A_FLICKYFLOUNDER,
A_FLICKYCHECK,
A_FLICKYHEIGHTCHECK,
A_FLICKYFLUTTER,
A_FLAMEPARTICLE,
A_FADEOVERLAY,
A_BOSS5JUMP,
A_LIGHTBEAMRESET,
A_MINEEXPLODE,
A_MINERANGE,
A_CONNECTTOGROUND,
A_SPAWNPARTICLERELATIVE,
A_MULTISHOTDIST,
A_WHOCARESIFYOURSONISABEE,
A_PARENTTRIESTOSLEEP,
A_CRYINGTOMOMMA,
A_CHECKFLAGS2,
A_BOSS5FINDWAYPOINT,
A_DONPCSKID,
A_DONPCPAIN,
A_PREPAREREPEAT,
A_BOSS5EXTRAREPEAT,
A_BOSS5CALM,
A_BOSS5CHECKONGROUND,
A_BOSS5CHECKFALLING,
A_BOSS5PINCHSHOT,
A_BOSS5MAKEITRAIN,
A_BOSS5MAKEJUNK,
A_LOOKFORBETTER,
A_BOSS5BOMBEXPLODE,
A_DUSTDEVILTHINK,
A_TNTEXPLODE,
A_DEBRISRANDOM,
A_TRAINCAMEO,
A_TRAINCAMEO2,
A_CANARIVOREGAS,
A_KILLSEGMENTS,
A_SNAPPERSPAWN,
A_SNAPPERTHINKER,
A_SALOONDOORSPAWN,
A_MINECARTSPARKTHINK,
A_MODULOTOSTATE,
A_LAVAFALLROCKS,
A_LAVAFALLLAVA,
A_FALLINGLAVACHECK,
A_FIRESHRINK,
A_SPAWNPTERABYTES,
A_PTERABYTEHOVER,
A_ROLLOUTSPAWN,
A_ROLLOUTROCK,
A_DRAGONBOMBERSPAWN,
A_DRAGONWING,
A_DRAGONSEGMENT,
A_CHANGEHEIGHT,
NUMACTIONS
};
// IMPORTANT NOTE: If you add/remove from this list of action // IMPORTANT NOTE: If you add/remove from this list of action
// functions, don't forget to update them in dehacked.c! // functions, don't forget to update them in deh_tables.c!
void A_Explode(); void A_Explode();
void A_Pain(); void A_Pain();
void A_Fall(); void A_Fall();
@ -286,6 +554,8 @@ void A_DragonWing();
void A_DragonSegment(); void A_DragonSegment();
void A_ChangeHeight(); void A_ChangeHeight();
extern boolean actionsoverridden[NUMACTIONS];
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1 // ratio of states to sprites to mobj types is roughly 6 : 1 : 1
#define NUMMOBJFREESLOTS 512 #define NUMMOBJFREESLOTS 512
#define NUMSPRITEFREESLOTS NUMMOBJFREESLOTS #define NUMSPRITEFREESLOTS NUMMOBJFREESLOTS

View file

@ -32,6 +32,7 @@
#include "lua_script.h" #include "lua_script.h"
#include "lua_libs.h" #include "lua_libs.h"
#include "lua_hud.h" // hud_running errors #include "lua_hud.h" // hud_running errors
#include "taglist.h" // P_FindSpecialLineFromTag
#include "lua_hook.h" // hook_cmd_running errors #include "lua_hook.h" // hook_cmd_running errors
#define NOHUD if (hud_running)\ #define NOHUD if (hud_running)\
@ -248,6 +249,56 @@ static int lib_userdataType(lua_State *L)
return luaL_typerror(L, 1, "userdata"); return luaL_typerror(L, 1, "userdata");
} }
// Takes a metatable as first and only argument
// Only callable during script loading
static int lib_registerMetatable(lua_State *L)
{
static UINT16 nextid = 1;
if (!lua_lumploading)
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
luaL_checktype(L, 1, LUA_TTABLE);
if (nextid == 0)
return luaL_error(L, "Too many metatables registered?! Please consider rewriting your script once you are sober again.\n");
lua_getfield(L, LUA_REGISTRYINDEX, LREG_METATABLES); // 2
// registry.metatables[metatable] = nextid
lua_pushvalue(L, 1); // 3
lua_pushnumber(L, nextid); // 4
lua_settable(L, 2);
// registry.metatables[nextid] = metatable
lua_pushnumber(L, nextid); // 3
lua_pushvalue(L, 1); // 4
lua_settable(L, 2);
lua_pop(L, 1);
nextid++;
return 0;
}
// Takes a string as only argument and returns the metatable
// associated to the userdata type this string refers to
// Returns nil if the string does not refer to a valid userdata type
static int lib_userdataMetatable(lua_State *L)
{
UINT32 i;
const char *udname = luaL_checkstring(L, 1);
// Find internal metatable name
for (i = 0; meta2utype[i].meta; i++)
if (!strcmp(udname, meta2utype[i].utype))
{
luaL_getmetatable(L, meta2utype[i].meta);
return 1;
}
lua_pushnil(L);
return 1;
}
static int lib_isPlayerAdmin(lua_State *L) static int lib_isPlayerAdmin(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@ -917,6 +968,28 @@ static int lib_pMaceRotate(lua_State *L)
return 0; return 0;
} }
static int lib_pCreateFloorSpriteSlope(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
LUA_PushUserdata(L, (pslope_t *)P_CreateFloorSpriteSlope(mobj), META_SLOPE);
return 1;
}
static int lib_pRemoveFloorSpriteSlope(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
P_RemoveFloorSpriteSlope(mobj);
return 1;
}
static int lib_pRailThinker(lua_State *L) static int lib_pRailThinker(lua_State *L)
{ {
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -3008,6 +3081,185 @@ static int lib_sStartMusicCaption(lua_State *L)
return 0; return 0;
} }
static int lib_sMusicType(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushinteger(L, S_MusicType());
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicPlaying(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_MusicPlaying());
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicPaused(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_MusicPaused());
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicName(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushstring(L, S_MusicName());
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicExists(lua_State *L)
{
boolean checkMIDI = lua_opttrueboolean(L, 2);
boolean checkDigi = lua_opttrueboolean(L, 3);
#ifdef MUSICSLOT_COMPATIBILITY
const char *music_name;
UINT32 music_num;
char music_compat_name[7];
UINT16 music_flags = 0;
NOHUD
if (lua_isnumber(L, 1))
{
music_num = (UINT32)luaL_checkinteger(L, 1);
music_flags = (UINT16)(music_num & 0x0000FFFF);
if (music_flags && music_flags <= 1035)
snprintf(music_compat_name, 7, "%sM", G_BuildMapName((INT32)music_flags));
else if (music_flags && music_flags <= 1050)
strncpy(music_compat_name, compat_special_music_slots[music_flags - 1036], 7);
else
music_compat_name[0] = 0; // becomes empty string
music_compat_name[6] = 0;
music_name = (const char *)&music_compat_name;
}
else
{
music_num = 0;
music_name = luaL_checkstring(L, 1);
}
#else
const char *music_name = luaL_checkstring(L, 1);
#endif
NOHUD
lua_pushboolean(L, S_MusicExists(music_name, checkMIDI, checkDigi));
return 1;
}
static int lib_sSetMusicLoopPoint(lua_State *L)
{
UINT32 looppoint = (UINT32)luaL_checkinteger(L, 1);
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
{
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_SetMusicLoopPoint(looppoint));
else
lua_pushnil(L);
return 1;
}
static int lib_sGetMusicLoopPoint(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushinteger(L, (int)S_GetMusicLoopPoint());
else
lua_pushnil(L);
return 1;
}
static int lib_sPauseMusic(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
S_PauseAudio();
lua_pushboolean(L, true);
}
else
lua_pushnil(L);
return 1;
}
static int lib_sResumeMusic(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
S_ResumeAudio();
lua_pushboolean(L, true);
}
else
lua_pushnil(L);
return 1;
}
// G_GAME // G_GAME
//////////// ////////////
@ -3496,6 +3748,8 @@ static luaL_Reg lib[] = {
{"chatprint", lib_chatprint}, {"chatprint", lib_chatprint},
{"chatprintf", lib_chatprintf}, {"chatprintf", lib_chatprintf},
{"userdataType", lib_userdataType}, {"userdataType", lib_userdataType},
{"registerMetatable", lib_registerMetatable},
{"userdataMetatable", lib_userdataMetatable},
{"IsPlayerAdmin", lib_isPlayerAdmin}, {"IsPlayerAdmin", lib_isPlayerAdmin},
{"reserveLuabanks", lib_reserveLuabanks}, {"reserveLuabanks", lib_reserveLuabanks},
@ -3555,6 +3809,8 @@ static luaL_Reg lib[] = {
{"P_CheckSolidLava",lib_pCheckSolidLava}, {"P_CheckSolidLava",lib_pCheckSolidLava},
{"P_CanRunOnWater",lib_pCanRunOnWater}, {"P_CanRunOnWater",lib_pCanRunOnWater},
{"P_MaceRotate",lib_pMaceRotate}, {"P_MaceRotate",lib_pMaceRotate},
{"P_CreateFloorSpriteSlope",lib_pCreateFloorSpriteSlope},
{"P_RemoveFloorSpriteSlope",lib_pRemoveFloorSpriteSlope},
{"P_RailThinker",lib_pRailThinker}, {"P_RailThinker",lib_pRailThinker},
{"P_XYMovement",lib_pXYMovement}, {"P_XYMovement",lib_pXYMovement},
{"P_RingXYMovement",lib_pRingXYMovement}, {"P_RingXYMovement",lib_pRingXYMovement},
@ -3714,6 +3970,15 @@ static luaL_Reg lib[] = {
{"S_IdPlaying",lib_sIdPlaying}, {"S_IdPlaying",lib_sIdPlaying},
{"S_SoundPlaying",lib_sSoundPlaying}, {"S_SoundPlaying",lib_sSoundPlaying},
{"S_StartMusicCaption", lib_sStartMusicCaption}, {"S_StartMusicCaption", lib_sStartMusicCaption},
{"S_MusicType",lib_sMusicType},
{"S_MusicPlaying",lib_sMusicPlaying},
{"S_MusicPaused",lib_sMusicPaused},
{"S_MusicName",lib_sMusicName},
{"S_MusicExists",lib_sMusicExists},
{"S_SetMusicLoopPoint",lib_sSetMusicLoopPoint},
{"S_GetMusicLoopPoint",lib_sGetMusicLoopPoint},
{"S_PauseMusic",lib_sPauseMusic},
{"S_ResumeMusic", lib_sResumeMusic},
// g_game // g_game
{"G_AddGametype", lib_gAddGametype}, {"G_AddGametype", lib_gAddGametype},

View file

@ -40,6 +40,10 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
// like sending random junk lua commands to crash the server // like sending random junk lua commands to crash the server
if (!gL) goto deny; if (!gL) goto deny;
lua_settop(gL, 0); // Just in case...
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command
if (!lua_istable(gL, -1)) goto deny; if (!lua_istable(gL, -1)) goto deny;
@ -76,7 +80,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
READSTRINGN(*cp, buf, 255); READSTRINGN(*cp, buf, 255);
lua_pushstring(gL, buf); lua_pushstring(gL, buf);
} }
LUA_Call(gL, (int)argc); // argc is 1-based, so this will cover the player we passed too. LUA_Call(gL, (int)argc, 0, 1); // argc is 1-based, so this will cover the player we passed too.
return; return;
deny: deny:
@ -98,6 +102,10 @@ void COM_Lua_f(void)
INT32 playernum = consoleplayer; INT32 playernum = consoleplayer;
I_Assert(gL != NULL); I_Assert(gL != NULL);
lua_settop(gL, 0); // Just in case...
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command
I_Assert(lua_istable(gL, -1)); I_Assert(lua_istable(gL, -1));
@ -167,7 +175,7 @@ void COM_Lua_f(void)
LUA_PushUserdata(gL, &players[playernum], META_PLAYER); LUA_PushUserdata(gL, &players[playernum], META_PLAYER);
for (i = 1; i < COM_Argc(); i++) for (i = 1; i < COM_Argc(); i++)
lua_pushstring(gL, COM_Argv(i)); lua_pushstring(gL, COM_Argv(i));
LUA_Call(gL, (int)COM_Argc()); // COM_Argc is 1-based, so this will cover the player we passed too. LUA_Call(gL, (int)COM_Argc(), 0, 1); // COM_Argc is 1-based, so this will cover the player we passed too.
} }
// Wrapper for COM_AddCommand // Wrapper for COM_AddCommand
@ -277,6 +285,9 @@ static void Lua_OnChange(void)
/// \todo Network this! XD_LUAVAR /// \todo Network this! XD_LUAVAR
lua_settop(gL, 0); // Just in case...
lua_pushcfunction(gL, LUA_GetErrorMessage);
// From CV_OnChange registry field, get the function for this cvar by name. // From CV_OnChange registry field, get the function for this cvar by name.
lua_getfield(gL, LUA_REGISTRYINDEX, "CV_OnChange"); lua_getfield(gL, LUA_REGISTRYINDEX, "CV_OnChange");
I_Assert(lua_istable(gL, -1)); I_Assert(lua_istable(gL, -1));
@ -288,7 +299,7 @@ static void Lua_OnChange(void)
lua_getfield(gL, -1, cvname); // get consvar_t* userdata. lua_getfield(gL, -1, cvname); // get consvar_t* userdata.
lua_remove(gL, -2); // pop the CV_Vars table. lua_remove(gL, -2); // pop the CV_Vars table.
LUA_Call(gL, 1); // call function(cvar) LUA_Call(gL, 1, 0, 1); // call function(cvar)
lua_pop(gL, 1); // pop CV_OnChange table lua_pop(gL, 1); // pop CV_OnChange table
} }
@ -440,6 +451,9 @@ static int CVarSetFunction
){ ){
consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR); consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR);
if (cvar->flags & CV_NOLUA)
return luaL_error(L, "Variable %s cannot be set from Lua.", cvar->name);
switch (lua_type(L, 2)) switch (lua_type(L, 2))
{ {
case LUA_TSTRING: case LUA_TSTRING:
@ -468,7 +482,12 @@ static int lib_cvStealthSet(lua_State *L)
static int lib_cvAddValue(lua_State *L) static int lib_cvAddValue(lua_State *L)
{ {
consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR); consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR);
if (cvar->flags & CV_NOLUA)
return luaL_error(L, "Variable %s cannot be set from Lua.", cvar->name);
CV_AddValue(cvar, (INT32)luaL_checknumber(L, 2)); CV_AddValue(cvar, (INT32)luaL_checknumber(L, 2));
return 0; return 0;
} }

View file

@ -60,6 +60,7 @@ enum hook {
hook_ShouldJingleContinue, hook_ShouldJingleContinue,
hook_GameQuit, hook_GameQuit,
hook_PlayerCmd, hook_PlayerCmd,
hook_MusicChange,
hook_MAX // last hook hook_MAX // last hook
}; };
@ -118,3 +119,4 @@ boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_
boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing
void LUAh_GameQuit(void); // Hook for game quitting void LUAh_GameQuit(void); // Hook for game quitting
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Hook for building player's ticcmd struct (Ported from SRB2Kart) boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Hook for building player's ticcmd struct (Ported from SRB2Kart)
boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms); // Hook for music changes

View file

@ -76,6 +76,7 @@ const char *const hookNames[hook_MAX+1] = {
"ShouldJingleContinue", "ShouldJingleContinue",
"GameQuit", "GameQuit",
"PlayerCmd", "PlayerCmd",
"MusicChange",
NULL NULL
}; };
@ -1912,3 +1913,62 @@ boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd)
hook_cmd_running = false; hook_cmd_running = false;
return hooked; return hooked;
} }
// Hook for music changes
boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping,
UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms)
{
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_MusicChange/8] & (1<<(hook_MusicChange%8))))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_MusicChange)
{
PushHook(gL, hookp);
lua_pushstring(gL, oldname);
lua_pushstring(gL, newname);
lua_pushinteger(gL, *mflags);
lua_pushboolean(gL, *looping);
lua_pushinteger(gL, *position);
lua_pushinteger(gL, *prefadems);
lua_pushinteger(gL, *fadeinms);
if (lua_pcall(gL, 7, 6, 1)) {
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
lua_pop(gL, 1);
continue;
}
// output 1: true, false, or string musicname override
if (lua_isboolean(gL, -6) && lua_toboolean(gL, -6))
hooked = true;
else if (lua_isstring(gL, -6))
strncpy(newname, lua_tostring(gL, -6), 7);
// output 2: mflags override
if (lua_isnumber(gL, -5))
*mflags = lua_tonumber(gL, -5);
// output 3: looping override
if (lua_isboolean(gL, -4))
*looping = lua_toboolean(gL, -4);
// output 4: position override
if (lua_isboolean(gL, -3))
*position = lua_tonumber(gL, -3);
// output 5: prefadems override
if (lua_isboolean(gL, -2))
*prefadems = lua_tonumber(gL, -2);
// output 6: fadeinms override
if (lua_isboolean(gL, -1))
*fadeinms = lua_tonumber(gL, -1);
lua_pop(gL, 7); // Pop returned values and error handler
}
lua_settop(gL, 0);
newname[6] = 0;
return hooked;
}

View file

@ -35,11 +35,6 @@ static UINT8 hud_enabled[(hud_MAX/8)+1];
static UINT8 hudAvailable; // hud hooks field static UINT8 hudAvailable; // hud hooks field
#ifdef LUA_PATCH_SAFETY
static patchinfo_t *patchinfo, *patchinfohead;
static int numluapatches;
#endif
// must match enum hud in lua_hud.h // must match enum hud in lua_hud.h
static const char *const hud_disable_options[] = { static const char *const hud_disable_options[] = {
"stagetitle", "stagetitle",
@ -292,11 +287,7 @@ static int colormap_get(lua_State *L)
static int patch_get(lua_State *L) static int patch_get(lua_State *L)
{ {
#ifdef LUA_PATCH_SAFETY
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH)); patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
#else
patchinfo_t *patch = *((patchinfo_t **)luaL_checkudata(L, 1, META_PATCH));
#endif
enum patch field = luaL_checkoption(L, 2, NULL, patch_opt); enum patch field = luaL_checkoption(L, 2, NULL, patch_opt);
// patches are invalidated when switching renderers // patches are invalidated when switching renderers
@ -314,16 +305,16 @@ static int patch_get(lua_State *L)
lua_pushboolean(L, patch != NULL); lua_pushboolean(L, patch != NULL);
break; break;
case patch_width: case patch_width:
lua_pushinteger(L, SHORT(patch->width)); lua_pushinteger(L, patch->width);
break; break;
case patch_height: case patch_height:
lua_pushinteger(L, SHORT(patch->height)); lua_pushinteger(L, patch->height);
break; break;
case patch_leftoffset: case patch_leftoffset:
lua_pushinteger(L, SHORT(patch->leftoffset)); lua_pushinteger(L, patch->leftoffset);
break; break;
case patch_topoffset: case patch_topoffset:
lua_pushinteger(L, SHORT(patch->topoffset)); lua_pushinteger(L, patch->topoffset);
break; break;
} }
return 1; return 1;
@ -403,59 +394,8 @@ static int libd_patchExists(lua_State *L)
static int libd_cachePatch(lua_State *L) static int libd_cachePatch(lua_State *L)
{ {
#ifdef LUA_PATCH_SAFETY
int i;
lumpnum_t lumpnum;
patchinfo_t *luapat;
patch_t *realpatch;
HUDONLY
luapat = patchinfohead;
lumpnum = W_CheckNumForLongName(luaL_checkstring(L, 1));
if (lumpnum == LUMPERROR)
lumpnum = W_GetNumForLongName("MISSING");
for (i = 0; i < numluapatches; i++)
{
// check if already cached
if (luapat->wadnum == WADFILENUM(lumpnum) && luapat->lumpnum == LUMPNUM(lumpnum))
{
LUA_PushUserdata(L, luapat, META_PATCH);
return 1;
}
luapat = luapat->next;
if (!luapat)
break;
}
if (numluapatches > 0)
{
patchinfo->next = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL);
patchinfo = patchinfo->next;
}
else
{
patchinfo = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL);
patchinfohead = patchinfo;
}
realpatch = W_CachePatchNum(lumpnum, PU_PATCH);
patchinfo->width = realpatch->width;
patchinfo->height = realpatch->height;
patchinfo->leftoffset = realpatch->leftoffset;
patchinfo->topoffset = realpatch->topoffset;
patchinfo->wadnum = WADFILENUM(lumpnum);
patchinfo->lumpnum = LUMPNUM(lumpnum);
LUA_PushUserdata(L, patchinfo, META_PATCH);
numluapatches++;
#else
HUDONLY HUDONLY
LUA_PushUserdata(L, W_CachePatchLongName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH); LUA_PushUserdata(L, W_CachePatchLongName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH);
#endif
return 1; return 1;
} }
@ -518,9 +458,8 @@ static int libd_getSpritePatch(lua_State *L)
INT32 rot = R_GetRollAngle(rollangle); INT32 rot = R_GetRollAngle(rollangle);
if (rot) { if (rot) {
if (!(sprframe->rotsprite.cached & (1<<angle))) patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), true, &spriteinfo[i], rot);
R_CacheRotSprite(i, frame, NULL, sprframe, angle, sprframe->flip & (1<<angle)); LUA_PushUserdata(L, rotsprite, META_PATCH);
LUA_PushUserdata(L, sprframe->rotsprite.patch[angle][rot], META_PATCH);
lua_pushboolean(L, false); lua_pushboolean(L, false);
lua_pushboolean(L, true); lua_pushboolean(L, true);
return 3; return 3;
@ -529,7 +468,7 @@ static int libd_getSpritePatch(lua_State *L)
#endif #endif
// push both the patch and it's "flip" value // push both the patch and it's "flip" value
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH); LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_SPRITE), META_PATCH);
lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0); lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
return 2; return 2;
} }
@ -631,9 +570,8 @@ static int libd_getSprite2Patch(lua_State *L)
INT32 rot = R_GetRollAngle(rollangle); INT32 rot = R_GetRollAngle(rollangle);
if (rot) { if (rot) {
if (!(sprframe->rotsprite.cached & (1<<angle))) patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), true, &skins[i].sprinfo[j], rot);
R_CacheRotSprite(SPR_PLAY, frame, &skins[i].sprinfo[j], sprframe, angle, sprframe->flip & (1<<angle)); LUA_PushUserdata(L, rotsprite, META_PATCH);
LUA_PushUserdata(L, sprframe->rotsprite.patch[angle][rot], META_PATCH);
lua_pushboolean(L, false); lua_pushboolean(L, false);
lua_pushboolean(L, true); lua_pushboolean(L, true);
return 3; return 3;
@ -642,7 +580,7 @@ static int libd_getSprite2Patch(lua_State *L)
#endif #endif
// push both the patch and it's "flip" value // push both the patch and it's "flip" value
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH); LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_SPRITE), META_PATCH);
lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0); lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
return 2; return 2;
} }
@ -651,22 +589,14 @@ static int libd_draw(lua_State *L)
{ {
INT32 x, y, flags; INT32 x, y, flags;
patch_t *patch; patch_t *patch;
#ifdef LUA_PATCH_SAFETY
patchinfo_t *luapat;
#endif
const UINT8 *colormap = NULL; const UINT8 *colormap = NULL;
HUDONLY HUDONLY
x = luaL_checkinteger(L, 1); x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2); y = luaL_checkinteger(L, 2);
#ifdef LUA_PATCH_SAFETY
luapat = *((patchinfo_t **)luaL_checkudata(L, 3, META_PATCH));
patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH);
#else
patch = *((patch_t **)luaL_checkudata(L, 3, META_PATCH)); patch = *((patch_t **)luaL_checkudata(L, 3, META_PATCH));
if (!patch) if (!patch)
return LUA_ErrInvalid(L, "patch_t"); return LUA_ErrInvalid(L, "patch_t");
#endif
flags = luaL_optinteger(L, 4, 0); flags = luaL_optinteger(L, 4, 0);
if (!lua_isnoneornil(L, 5)) if (!lua_isnoneornil(L, 5))
colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP)); colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP));
@ -682,9 +612,6 @@ static int libd_drawScaled(lua_State *L)
fixed_t x, y, scale; fixed_t x, y, scale;
INT32 flags; INT32 flags;
patch_t *patch; patch_t *patch;
#ifdef LUA_PATCH_SAFETY
patchinfo_t *luapat;
#endif
const UINT8 *colormap = NULL; const UINT8 *colormap = NULL;
HUDONLY HUDONLY
@ -693,14 +620,9 @@ static int libd_drawScaled(lua_State *L)
scale = luaL_checkinteger(L, 3); scale = luaL_checkinteger(L, 3);
if (scale < 0) if (scale < 0)
return luaL_error(L, "negative scale"); return luaL_error(L, "negative scale");
#ifdef LUA_PATCH_SAFETY
luapat = *((patchinfo_t **)luaL_checkudata(L, 4, META_PATCH));
patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH);
#else
patch = *((patch_t **)luaL_checkudata(L, 4, META_PATCH)); patch = *((patch_t **)luaL_checkudata(L, 4, META_PATCH));
if (!patch) if (!patch)
return LUA_ErrInvalid(L, "patch_t"); return LUA_ErrInvalid(L, "patch_t");
#endif
flags = luaL_optinteger(L, 5, 0); flags = luaL_optinteger(L, 5, 0);
if (!lua_isnoneornil(L, 6)) if (!lua_isnoneornil(L, 6))
colormap = *((UINT8 **)luaL_checkudata(L, 6, META_COLORMAP)); colormap = *((UINT8 **)luaL_checkudata(L, 6, META_COLORMAP));
@ -1261,10 +1183,6 @@ int LUA_HudLib(lua_State *L)
{ {
memset(hud_enabled, 0xff, (hud_MAX/8)+1); memset(hud_enabled, 0xff, (hud_MAX/8)+1);
#ifdef LUA_PATCH_SAFETY
numluapatches = 0;
#endif
lua_newtable(L); // HUD registry table lua_newtable(L); // HUD registry table
lua_newtable(L); lua_newtable(L);
luaL_register(L, NULL, lib_draw); luaL_register(L, NULL, lib_draw);
@ -1343,7 +1261,9 @@ void LUAh_GameHUD(player_t *stplayr)
return; return;
hud_running = true; hud_running = true;
lua_pop(gL, -1); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1)); I_Assert(lua_istable(gL, -1));
@ -1365,9 +1285,9 @@ void LUAh_GameHUD(player_t *stplayr)
lua_pushvalue(gL, -5); // graphics library (HUD[1]) lua_pushvalue(gL, -5); // graphics library (HUD[1])
lua_pushvalue(gL, -5); // stplayr lua_pushvalue(gL, -5); // stplayr
lua_pushvalue(gL, -5); // camera lua_pushvalue(gL, -5); // camera
LUA_Call(gL, 3); LUA_Call(gL, 3, 0, 1);
} }
lua_pop(gL, -1); lua_settop(gL, 0);
hud_running = false; hud_running = false;
} }
@ -1377,7 +1297,9 @@ void LUAh_ScoresHUD(void)
return; return;
hud_running = true; hud_running = true;
lua_pop(gL, -1); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1)); I_Assert(lua_istable(gL, -1));
@ -1390,9 +1312,9 @@ void LUAh_ScoresHUD(void)
lua_pushnil(gL); lua_pushnil(gL);
while (lua_next(gL, -3) != 0) { while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // graphics library (HUD[1]) lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1); LUA_Call(gL, 1, 0, 1);
} }
lua_pop(gL, -1); lua_settop(gL, 0);
hud_running = false; hud_running = false;
} }
@ -1402,7 +1324,9 @@ void LUAh_TitleHUD(void)
return; return;
hud_running = true; hud_running = true;
lua_pop(gL, -1); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1)); I_Assert(lua_istable(gL, -1));
@ -1415,9 +1339,9 @@ void LUAh_TitleHUD(void)
lua_pushnil(gL); lua_pushnil(gL);
while (lua_next(gL, -3) != 0) { while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // graphics library (HUD[1]) lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1); LUA_Call(gL, 1, 0, 1);
} }
lua_pop(gL, -1); lua_settop(gL, 0);
hud_running = false; hud_running = false;
} }
@ -1427,7 +1351,9 @@ void LUAh_TitleCardHUD(player_t *stplayr)
return; return;
hud_running = true; hud_running = true;
lua_pop(gL, -1); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1)); I_Assert(lua_istable(gL, -1));
@ -1448,10 +1374,10 @@ void LUAh_TitleCardHUD(player_t *stplayr)
lua_pushvalue(gL, -6); // stplayr lua_pushvalue(gL, -6); // stplayr
lua_pushvalue(gL, -6); // lt_ticker lua_pushvalue(gL, -6); // lt_ticker
lua_pushvalue(gL, -6); // lt_endtime lua_pushvalue(gL, -6); // lt_endtime
LUA_Call(gL, 4); LUA_Call(gL, 4, 0, 1);
} }
lua_pop(gL, -1); lua_settop(gL, 0);
hud_running = false; hud_running = false;
} }
@ -1461,7 +1387,9 @@ void LUAh_IntermissionHUD(void)
return; return;
hud_running = true; hud_running = true;
lua_pop(gL, -1); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1)); I_Assert(lua_istable(gL, -1));
@ -1474,8 +1402,8 @@ void LUAh_IntermissionHUD(void)
lua_pushnil(gL); lua_pushnil(gL);
while (lua_next(gL, -3) != 0) { while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // graphics library (HUD[1]) lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1); LUA_Call(gL, 1, 0, 1);
} }
lua_pop(gL, -1); lua_settop(gL, 0);
hud_running = false; hud_running = false;
} }

View file

@ -14,9 +14,12 @@
#include "fastcmp.h" #include "fastcmp.h"
#include "info.h" #include "info.h"
#include "dehacked.h" #include "dehacked.h"
#include "deh_tables.h"
#include "deh_lua.h"
#include "p_mobj.h" #include "p_mobj.h"
#include "p_local.h" #include "p_local.h"
#include "z_zone.h" #include "z_zone.h"
#include "r_patch.h"
#include "r_picformats.h" #include "r_picformats.h"
#include "r_things.h" #include "r_things.h"
#include "r_draw.h" // R_GetColorByName #include "r_draw.h" // R_GetColorByName
@ -30,7 +33,7 @@
extern CV_PossibleValue_t Color_cons_t[]; extern CV_PossibleValue_t Color_cons_t[];
extern UINT8 skincolor_modified[]; extern UINT8 skincolor_modified[];
boolean LUA_CallAction(const char *action, mobj_t *actor); boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor);
state_t *astate; state_t *astate;
enum sfxinfo_read { enum sfxinfo_read {
@ -63,6 +66,8 @@ const char *const sfxinfo_wopt[] = {
"caption", "caption",
NULL}; NULL};
boolean actionsoverridden[NUMACTIONS] = {false};
// //
// Sprite Names // Sprite Names
// //
@ -375,17 +380,13 @@ static int lib_setSpriteInfo(lua_State *L)
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter spriteinfo_t in HUD rendering code!"); return luaL_error(L, "Do not alter spriteinfo_t in HUD rendering code!");
if (hook_cmd_running) if (hook_cmd_running)
return luaL_error(L, "Do not alter spriteinfo_t in CMD building code!"); return luaL_error(L, "Do not alter spriteinfo_t in CMD building code!");
lua_remove(L, 1); lua_remove(L, 1);
{ {
UINT32 i = luaL_checkinteger(L, 1); UINT32 i = luaL_checkinteger(L, 1);
if (i == 0 || i >= NUMSPRITES) if (i == 0 || i >= NUMSPRITES)
return luaL_error(L, "spriteinfo[] index %d out of range (1 - %d)", i, NUMSPRITES-1); return luaL_error(L, "spriteinfo[] index %d out of range (1 - %d)", i, NUMSPRITES-1);
#ifdef ROTSPRITE
if (sprites != NULL)
R_FreeSingleRotSprite(&sprites[i]);
#endif
info = &spriteinfo[i]; // get the spriteinfo to assign to. info = &spriteinfo[i]; // get the spriteinfo to assign to.
} }
luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table. luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table.
@ -469,11 +470,6 @@ static int spriteinfo_set(lua_State *L)
lua_remove(L, 1); // remove field lua_remove(L, 1); // remove field
lua_settop(L, 1); // leave only one value lua_settop(L, 1); // leave only one value
#ifdef ROTSPRITE
if (sprites != NULL)
R_FreeSingleRotSprite(&sprites[sprinfo-spriteinfo]);
#endif
if (fastcmp(field, "pivot")) if (fastcmp(field, "pivot"))
{ {
// pivot[] is a table // pivot[] is a table
@ -630,6 +626,9 @@ static void A_Lua(mobj_t *actor)
boolean found = false; boolean found = false;
I_Assert(actor != NULL); I_Assert(actor != NULL);
lua_settop(gL, 0); // Just in case...
lua_pushcfunction(gL, LUA_GetErrorMessage);
// get the action for this state // get the action for this state
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_STATEACTION); lua_getfield(gL, LUA_REGISTRYINDEX, LREG_STATEACTION);
I_Assert(lua_istable(gL, -1)); I_Assert(lua_istable(gL, -1));
@ -658,7 +657,7 @@ static void A_Lua(mobj_t *actor)
LUA_PushUserdata(gL, actor, META_MOBJ); LUA_PushUserdata(gL, actor, META_MOBJ);
lua_pushinteger(gL, var1); lua_pushinteger(gL, var1);
lua_pushinteger(gL, var2); lua_pushinteger(gL, var2);
LUA_Call(gL, 3); LUA_Call(gL, 3, 0, 1);
if (found) if (found)
{ {
@ -813,36 +812,33 @@ boolean LUA_SetLuaAction(void *stv, const char *action)
return true; // action successfully set. return true; // action successfully set.
} }
boolean LUA_CallAction(const char *csaction, mobj_t *actor) boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor)
{ {
I_Assert(csaction != NULL);
I_Assert(actor != NULL); I_Assert(actor != NULL);
if (!gL) // Lua isn't loaded, if (!actionsoverridden[actionnum]) // The action is not overriden,
return false; // action not called. return false; // action not called.
if (superstack && fasticmp(csaction, superactions[superstack-1])) // the action is calling itself, if (superstack && fasticmp(actionpointers[actionnum].name, superactions[superstack-1])) // the action is calling itself,
return false; // let it call the hardcoded function instead. return false; // let it call the hardcoded function instead.
lua_pushcfunction(gL, LUA_GetErrorMessage);
// grab function by uppercase name. // grab function by uppercase name.
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_ACTIONS); lua_getfield(gL, LUA_REGISTRYINDEX, LREG_ACTIONS);
{ lua_getfield(gL, -1, actionpointers[actionnum].name);
char *action = Z_StrDup(csaction);
strupr(action);
lua_getfield(gL, -1, action);
Z_Free(action);
}
lua_remove(gL, -2); // pop LREG_ACTIONS lua_remove(gL, -2); // pop LREG_ACTIONS
if (lua_isnil(gL, -1)) // no match if (lua_isnil(gL, -1)) // no match
{ {
lua_pop(gL, 1); // pop nil lua_pop(gL, 2); // pop nil and error handler
return false; // action not called. return false; // action not called.
} }
if (superstack == MAXRECURSION) if (superstack == MAXRECURSION)
{ {
CONS_Alert(CONS_WARNING, "Max Lua Action recursion reached! Cool it on the calling A_Action functions from inside A_Action functions!\n"); CONS_Alert(CONS_WARNING, "Max Lua Action recursion reached! Cool it on the calling A_Action functions from inside A_Action functions!\n");
lua_pop(gL, 2); // pop function and error handler
return true; return true;
} }
@ -853,10 +849,11 @@ boolean LUA_CallAction(const char *csaction, mobj_t *actor)
lua_pushinteger(gL, var1); lua_pushinteger(gL, var1);
lua_pushinteger(gL, var2); lua_pushinteger(gL, var2);
superactions[superstack] = csaction; superactions[superstack] = actionpointers[actionnum].name;
++superstack; ++superstack;
LUA_Call(gL, 3); LUA_Call(gL, 3, 0, -(2 + 3));
lua_pop(gL, -1); // Error handler
--superstack; --superstack;
superactions[superstack] = NULL; superactions[superstack] = NULL;

View file

@ -16,6 +16,7 @@ extern lua_State *gL;
#define LREG_EXTVARS "LUA_VARS" #define LREG_EXTVARS "LUA_VARS"
#define LREG_STATEACTION "STATE_ACTION" #define LREG_STATEACTION "STATE_ACTION"
#define LREG_ACTIONS "MOBJ_ACTION" #define LREG_ACTIONS "MOBJ_ACTION"
#define LREG_METATABLES "METATABLES"
#define META_STATE "STATE_T*" #define META_STATE "STATE_T*"
#define META_MOBJINFO "MOBJINFO_T*" #define META_MOBJINFO "MOBJINFO_T*"

View file

@ -99,8 +99,6 @@ enum line_e {
line_slopetype, line_slopetype,
line_frontsector, line_frontsector,
line_backsector, line_backsector,
line_firsttag,
line_nexttag,
line_polyobj, line_polyobj,
line_text, line_text,
line_callcount line_callcount
@ -125,8 +123,6 @@ static const char *const line_opt[] = {
"slopetype", "slopetype",
"frontsector", "frontsector",
"backsector", "backsector",
"firsttag",
"nexttag",
"polyobj", "polyobj",
"text", "text",
"callcount", "callcount",
@ -583,7 +579,7 @@ static int sector_get(lua_State *L)
lua_pushinteger(L, sector->special); lua_pushinteger(L, sector->special);
return 1; return 1;
case sector_tag: case sector_tag:
lua_pushinteger(L, sector->tag); lua_pushinteger(L, Tag_FGet(&sector->tags));
return 1; return 1;
case sector_thinglist: // thinglist case sector_thinglist: // thinglist
lua_pushcfunction(L, lib_iterateSectorThinglist); lua_pushcfunction(L, lib_iterateSectorThinglist);
@ -684,7 +680,7 @@ static int sector_set(lua_State *L)
sector->special = (INT16)luaL_checkinteger(L, 3); sector->special = (INT16)luaL_checkinteger(L, 3);
break; break;
case sector_tag: case sector_tag:
P_ChangeSectorTag((UINT32)(sector - sectors), (INT16)luaL_checkinteger(L, 3)); Tag_SectorFSet((UINT32)(sector - sectors), (INT16)luaL_checkinteger(L, 3));
break; break;
} }
return 0; return 0;
@ -823,7 +819,7 @@ static int line_get(lua_State *L)
lua_pushinteger(L, line->special); lua_pushinteger(L, line->special);
return 1; return 1;
case line_tag: case line_tag:
lua_pushinteger(L, line->tag); lua_pushinteger(L, Tag_FGet(&line->tags));
return 1; return 1;
case line_args: case line_args:
LUA_PushUserdata(L, line->args, META_LINEARGS); LUA_PushUserdata(L, line->args, META_LINEARGS);
@ -871,12 +867,6 @@ static int line_get(lua_State *L)
case line_backsector: case line_backsector:
LUA_PushUserdata(L, line->backsector, META_SECTOR); LUA_PushUserdata(L, line->backsector, META_SECTOR);
return 1; return 1;
case line_firsttag:
lua_pushinteger(L, line->firsttag);
return 1;
case line_nexttag:
lua_pushinteger(L, line->nexttag);
return 1;
case line_polyobj: case line_polyobj:
LUA_PushUserdata(L, line->polyobj, META_POLYOBJ); LUA_PushUserdata(L, line->polyobj, META_POLYOBJ);
return 1; return 1;

View file

@ -39,6 +39,11 @@ enum mobj_e {
mobj_frame, mobj_frame,
mobj_sprite2, mobj_sprite2,
mobj_anim_duration, mobj_anim_duration,
mobj_spritexscale,
mobj_spriteyscale,
mobj_spritexoffset,
mobj_spriteyoffset,
mobj_floorspriteslope,
mobj_touching_sectorlist, mobj_touching_sectorlist,
mobj_subsector, mobj_subsector,
mobj_floorz, mobj_floorz,
@ -56,8 +61,10 @@ enum mobj_e {
mobj_flags, mobj_flags,
mobj_flags2, mobj_flags2,
mobj_eflags, mobj_eflags,
mobj_renderflags,
mobj_skin, mobj_skin,
mobj_color, mobj_color,
mobj_blendmode,
mobj_bnext, mobj_bnext,
mobj_bprev, mobj_bprev,
mobj_hnext, mobj_hnext,
@ -108,6 +115,11 @@ static const char *const mobj_opt[] = {
"frame", "frame",
"sprite2", "sprite2",
"anim_duration", "anim_duration",
"spritexscale",
"spriteyscale",
"spritexoffset",
"spriteyoffset",
"floorspriteslope",
"touching_sectorlist", "touching_sectorlist",
"subsector", "subsector",
"floorz", "floorz",
@ -125,8 +137,10 @@ static const char *const mobj_opt[] = {
"flags", "flags",
"flags2", "flags2",
"eflags", "eflags",
"renderflags",
"skin", "skin",
"color", "color",
"blendmode",
"bnext", "bnext",
"bprev", "bprev",
"hnext", "hnext",
@ -227,6 +241,21 @@ static int mobj_get(lua_State *L)
case mobj_anim_duration: case mobj_anim_duration:
lua_pushinteger(L, mo->anim_duration); lua_pushinteger(L, mo->anim_duration);
break; break;
case mobj_spritexscale:
lua_pushfixed(L, mo->spritexscale);
break;
case mobj_spriteyscale:
lua_pushfixed(L, mo->spriteyscale);
break;
case mobj_spritexoffset:
lua_pushfixed(L, mo->spritexoffset);
break;
case mobj_spriteyoffset:
lua_pushfixed(L, mo->spriteyoffset);
break;
case mobj_floorspriteslope:
LUA_PushUserdata(L, mo->floorspriteslope, META_SLOPE);
break;
case mobj_touching_sectorlist: case mobj_touching_sectorlist:
return UNIMPLEMENTED; return UNIMPLEMENTED;
case mobj_subsector: case mobj_subsector:
@ -277,6 +306,9 @@ static int mobj_get(lua_State *L)
case mobj_eflags: case mobj_eflags:
lua_pushinteger(L, mo->eflags); lua_pushinteger(L, mo->eflags);
break; break;
case mobj_renderflags:
lua_pushinteger(L, mo->renderflags);
break;
case mobj_skin: // skin name or nil, not struct case mobj_skin: // skin name or nil, not struct
if (!mo->skin) if (!mo->skin)
return 0; return 0;
@ -285,6 +317,9 @@ static int mobj_get(lua_State *L)
case mobj_color: case mobj_color:
lua_pushinteger(L, mo->color); lua_pushinteger(L, mo->color);
break; break;
case mobj_blendmode:
lua_pushinteger(L, mo->blendmode);
break;
case mobj_bnext: case mobj_bnext:
LUA_PushUserdata(L, mo->bnext, META_MOBJ); LUA_PushUserdata(L, mo->bnext, META_MOBJ);
break; break;
@ -492,6 +527,20 @@ static int mobj_set(lua_State *L)
case mobj_anim_duration: case mobj_anim_duration:
mo->anim_duration = (UINT16)luaL_checkinteger(L, 3); mo->anim_duration = (UINT16)luaL_checkinteger(L, 3);
break; break;
case mobj_spritexscale:
mo->spritexscale = luaL_checkfixed(L, 3);
break;
case mobj_spriteyscale:
mo->spriteyscale = luaL_checkfixed(L, 3);
break;
case mobj_spritexoffset:
mo->spritexoffset = luaL_checkfixed(L, 3);
break;
case mobj_spriteyoffset:
mo->spriteyoffset = luaL_checkfixed(L, 3);
break;
case mobj_floorspriteslope:
return NOSET;
case mobj_touching_sectorlist: case mobj_touching_sectorlist:
return UNIMPLEMENTED; return UNIMPLEMENTED;
case mobj_subsector: case mobj_subsector:
@ -580,6 +629,9 @@ static int mobj_set(lua_State *L)
case mobj_eflags: case mobj_eflags:
mo->eflags = (UINT32)luaL_checkinteger(L, 3); mo->eflags = (UINT32)luaL_checkinteger(L, 3);
break; break;
case mobj_renderflags:
mo->renderflags = (UINT32)luaL_checkinteger(L, 3);
break;
case mobj_skin: // set skin by name case mobj_skin: // set skin by name
{ {
INT32 i; INT32 i;
@ -603,6 +655,9 @@ static int mobj_set(lua_State *L)
mo->color = newcolor; mo->color = newcolor;
break; break;
} }
case mobj_blendmode:
mo->blendmode = (INT32)luaL_checkinteger(L, 3);
break;
case mobj_bnext: case mobj_bnext:
return NOSETPOS; return NOSETPOS;
case mobj_bprev: case mobj_bprev:
@ -848,7 +903,7 @@ static int mapthing_get(lua_State *L)
else if(fastcmp(field,"extrainfo")) else if(fastcmp(field,"extrainfo"))
number = mt->extrainfo; number = mt->extrainfo;
else if(fastcmp(field,"tag")) else if(fastcmp(field,"tag"))
number = mt->tag; number = Tag_FGet(&mt->tags);
else if(fastcmp(field,"args")) else if(fastcmp(field,"args"))
{ {
LUA_PushUserdata(L, mt->args, META_THINGARGS); LUA_PushUserdata(L, mt->args, META_THINGARGS);
@ -910,7 +965,7 @@ static int mapthing_set(lua_State *L)
mt->extrainfo = (UINT8)extrainfo; mt->extrainfo = (UINT8)extrainfo;
} }
else if (fastcmp(field,"tag")) else if (fastcmp(field,"tag"))
mt->tag = (INT16)luaL_checkinteger(L, 3); Tag_FSet(&mt->tags, (INT16)luaL_checkinteger(L, 3));
else if(fastcmp(field,"mobj")) else if(fastcmp(field,"mobj"))
mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
else else

View file

@ -13,6 +13,7 @@
#include "doomdef.h" #include "doomdef.h"
#include "fastcmp.h" #include "fastcmp.h"
#include "dehacked.h" #include "dehacked.h"
#include "deh_lua.h"
#include "z_zone.h" #include "z_zone.h"
#include "w_wad.h" #include "w_wad.h"
#include "p_setup.h" #include "p_setup.h"
@ -133,6 +134,19 @@ int LUA_GetErrorMessage(lua_State *L)
return 1; return 1;
} }
int LUA_Call(lua_State *L, int nargs, int nresults, int errorhandlerindex)
{
int err = lua_pcall(L, nargs, nresults, errorhandlerindex);
if (err)
{
CONS_Alert(CONS_WARNING, "%s\n", lua_tostring(L, -1));
lua_pop(L, 1);
}
return err;
}
// Moved here from lib_getenum. // Moved here from lib_getenum.
int LUA_PushGlobals(lua_State *L, const char *word) int LUA_PushGlobals(lua_State *L, const char *word)
{ {
@ -376,6 +390,44 @@ int LUA_CheckGlobals(lua_State *L, const char *word)
redscore = (UINT32)luaL_checkinteger(L, 2); redscore = (UINT32)luaL_checkinteger(L, 2);
else if (fastcmp(word, "bluescore")) else if (fastcmp(word, "bluescore"))
bluescore = (UINT32)luaL_checkinteger(L, 2); bluescore = (UINT32)luaL_checkinteger(L, 2);
else if (fastcmp(word, "skincolor_redteam"))
skincolor_redteam = (UINT16)luaL_checkinteger(L, 2);
else if (fastcmp(word, "skincolor_blueteam"))
skincolor_blueteam = (UINT16)luaL_checkinteger(L, 2);
else if (fastcmp(word, "skincolor_redring"))
skincolor_redring = (UINT16)luaL_checkinteger(L, 2);
else if (fastcmp(word, "skincolor_bluering"))
skincolor_bluering = (UINT16)luaL_checkinteger(L, 2);
else if (fastcmp(word, "emeralds"))
emeralds = (UINT16)luaL_checkinteger(L, 2);
else if (fastcmp(word, "token"))
token = (UINT32)luaL_checkinteger(L, 2);
else if (fastcmp(word, "gravity"))
gravity = (fixed_t)luaL_checkinteger(L, 2);
else if (fastcmp(word, "stoppedclock"))
stoppedclock = luaL_checkboolean(L, 2);
else if (fastcmp(word, "displayplayer"))
{
player_t *player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (player)
displayplayer = player - players;
}
else if (fastcmp(word, "mapmusname"))
{
size_t strlength;
const char *str = luaL_checklstring(L, 2, &strlength);
if (strlength > 6)
return luaL_error(L, "string length out of range (maximum 6 characters)");
if (strlen(str) < strlength)
return luaL_error(L, "string must not contain embedded zeros!");
strncpy(mapmusname, str, strlength);
}
else if (fastcmp(word, "mapmusflags"))
mapmusflags = (UINT16)luaL_checkinteger(L, 2);
else else
return 0; return 0;
@ -388,6 +440,7 @@ static int setglobals(lua_State *L)
{ {
const char *csname; const char *csname;
char *name; char *name;
enum actionnum actionnum;
lua_remove(L, 1); // we're not gonna be using _G lua_remove(L, 1); // we're not gonna be using _G
csname = lua_tostring(L, 1); csname = lua_tostring(L, 1);
@ -406,6 +459,10 @@ static int setglobals(lua_State *L)
lua_rawset(L, -3); // rawset doesn't trigger this metatable again. lua_rawset(L, -3); // rawset doesn't trigger this metatable again.
// otherwise we would've used setfield, obviously. // otherwise we would've used setfield, obviously.
actionnum = LUA_GetActionNumByName(name);
if (actionnum < NUMACTIONS)
actionsoverridden[actionnum] = true;
Z_Free(name); Z_Free(name);
return 0; return 0;
} }
@ -437,12 +494,16 @@ static void LUA_ClearState(void)
// open base libraries // open base libraries
luaL_openlibs(L); luaL_openlibs(L);
lua_pop(L, -1); lua_settop(L, 0);
// make LREG_VALID table for all pushed userdata cache. // make LREG_VALID table for all pushed userdata cache.
lua_newtable(L); lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, LREG_VALID); lua_setfield(L, LUA_REGISTRYINDEX, LREG_VALID);
// make LREG_METATABLES table for all registered metatables
lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, LREG_METATABLES);
// open srb2 libraries // open srb2 libraries
for(i = 0; liblist[i]; i++) { for(i = 0; liblist[i]; i++) {
lua_pushcfunction(L, liblist[i]); lua_pushcfunction(L, liblist[i]);
@ -636,7 +697,7 @@ fixed_t LUA_EvalMath(const char *word)
*b = '\0'; *b = '\0';
// eval string. // eval string.
lua_pop(L, -1); lua_settop(L, 0);
if (luaL_dostring(L, buf)) if (luaL_dostring(L, buf))
{ {
p = lua_tostring(L, -1); p = lua_tostring(L, -1);
@ -980,8 +1041,17 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
lua_pop(gL, 1); lua_pop(gL, 1);
} }
if (!found) if (!found)
{
t++; t++;
if (t == 0)
{
CONS_Alert(CONS_ERROR, "Too many tables to archive!\n");
WRITEUINT8(save_p, ARCH_NULL);
return 0;
}
}
WRITEUINT8(save_p, ARCH_TABLE); WRITEUINT8(save_p, ARCH_TABLE);
WRITEUINT16(save_p, t); WRITEUINT16(save_p, t);
@ -1294,8 +1364,22 @@ static void ArchiveTables(void)
lua_pop(gL, 1); lua_pop(gL, 1);
} }
lua_pop(gL, 1);
WRITEUINT8(save_p, ARCH_TEND); WRITEUINT8(save_p, ARCH_TEND);
// Write metatable ID
if (lua_getmetatable(gL, -1))
{
// registry.metatables[metatable]
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_METATABLES);
lua_pushvalue(gL, -2);
lua_gettable(gL, -2);
WRITEUINT16(save_p, lua_isnil(gL, -1) ? 0 : lua_tointeger(gL, -1));
lua_pop(gL, 3);
}
else
WRITEUINT16(save_p, 0);
lua_pop(gL, 1);
} }
} }
@ -1466,6 +1550,7 @@ static void UnArchiveTables(void)
{ {
int TABLESINDEX; int TABLESINDEX;
UINT16 i, n; UINT16 i, n;
UINT16 metatableid;
if (!gL) if (!gL)
return; return;
@ -1490,6 +1575,19 @@ static void UnArchiveTables(void)
else else
lua_rawset(gL, -3); lua_rawset(gL, -3);
} }
metatableid = READUINT16(save_p);
if (metatableid)
{
// setmetatable(table, registry.metatables[metatableid])
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_METATABLES);
lua_rawgeti(gL, -1, metatableid);
if (lua_isnil(gL, -1))
I_Error("Unknown metatable ID %d\n", metatableid);
lua_setmetatable(gL, -3);
lua_pop(gL, 1);
}
lua_pop(gL, 1); lua_pop(gL, 1);
} }
} }

View file

@ -40,6 +40,7 @@ void LUA_ClearExtVars(void);
extern INT32 lua_lumploading; // is LUA_LoadLump being called? extern INT32 lua_lumploading; // is LUA_LoadLump being called?
int LUA_GetErrorMessage(lua_State *L); int LUA_GetErrorMessage(lua_State *L);
int LUA_Call(lua_State *L, int nargs, int nresults, int errorhandlerindex);
void LUA_LoadLump(UINT16 wad, UINT16 lump, boolean noresults); void LUA_LoadLump(UINT16 wad, UINT16 lump, boolean noresults);
#ifdef LUA_ALLOW_BYTECODE #ifdef LUA_ALLOW_BYTECODE
void LUA_DumpFile(const char *filename); void LUA_DumpFile(const char *filename);
@ -65,14 +66,6 @@ void LUAh_NetArchiveHook(lua_CFunction archFunc);
// Console wrapper // Console wrapper
void COM_Lua_f(void); void COM_Lua_f(void);
#define LUA_Call(L,a)\
{\
if (lua_pcall(L, a, 0, 0)) {\
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(L,-1));\
lua_pop(L, 1);\
}\
}
#define LUA_ErrInvalid(L, type) luaL_error(L, "accessed " type " doesn't exist anymore, please check 'valid' before using " type "."); #define LUA_ErrInvalid(L, type) luaL_error(L, "accessed " type " doesn't exist anymore, please check 'valid' before using " type ".");
// Deprecation warnings // Deprecation warnings

View file

@ -29,15 +29,21 @@
// GIFs are always little-endian // GIFs are always little-endian
#include "byteptr.h" #include "byteptr.h"
CV_PossibleValue_t gif_dynamicdelay_cons_t[] = {
{0, "Off"},
{1, "On"},
{2, "Accurate, experimental"},
{0, NULL}};
consvar_t cv_gif_optimize = CVAR_INIT ("gif_optimize", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_gif_optimize = CVAR_INIT ("gif_optimize", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_gif_downscale = CVAR_INIT ("gif_downscale", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_gif_downscale = CVAR_INIT ("gif_downscale", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_gif_dynamicdelay = CVAR_INIT ("gif_dynamicdelay", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_gif_dynamicdelay = CVAR_INIT ("gif_dynamicdelay", "On", CV_SAVE, gif_dynamicdelay_cons_t, NULL);
consvar_t cv_gif_localcolortable = CVAR_INIT ("gif_localcolortable", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_gif_localcolortable = CVAR_INIT ("gif_localcolortable", "On", CV_SAVE, CV_OnOff, NULL);
#ifdef HAVE_ANIGIF #ifdef HAVE_ANIGIF
static boolean gif_optimize = false; // So nobody can do something dumb static boolean gif_optimize = false; // So nobody can do something dumb
static boolean gif_downscale = false; // like changing cvars mid output static boolean gif_downscale = false; // like changing cvars mid output
static boolean gif_dynamicdelay = false; // and messing something up static UINT8 gif_dynamicdelay = (UINT8)0; // and messing something up
// Palette handling // Palette handling
static boolean gif_localcolortable = false; static boolean gif_localcolortable = false;
@ -598,7 +604,8 @@ static void GIF_framewrite(void)
UINT16 delay = 0; UINT16 delay = 0;
INT32 startline; INT32 startline;
if (gif_dynamicdelay) { if (gif_dynamicdelay ==(UINT8) 2)
{
// golden's attempt at creating a "dynamic delay" // golden's attempt at creating a "dynamic delay"
UINT16 mingifdelay = 10; // minimum gif delay in milliseconds (keep at 10 because gifs can't get more precise). UINT16 mingifdelay = 10; // minimum gif delay in milliseconds (keep at 10 because gifs can't get more precise).
gif_delayus += (I_GetTimeMicros() - gif_prevframeus); // increase delay by how much time was spent between last measurement gif_delayus += (I_GetTimeMicros() - gif_prevframeus); // increase delay by how much time was spent between last measurement
@ -610,6 +617,15 @@ static void GIF_framewrite(void)
gif_delayus -= frames*(mingifdelay*1000); // remove frames by the amount of milliseconds they take. don't reset to 0, the microseconds help consistency. gif_delayus -= frames*(mingifdelay*1000); // remove frames by the amount of milliseconds they take. don't reset to 0, the microseconds help consistency.
} }
} }
else if (gif_dynamicdelay ==(UINT8) 1)
{
float delayf = ceil(100.0f/NEWTICRATE);
delay = (UINT16)((I_GetTimeMicros() - gif_prevframeus)/10/1000);
if (delay < (UINT16)(delayf))
delay = (UINT16)(delayf);
}
else else
{ {
// the original code // the original code
@ -716,7 +732,7 @@ INT32 GIF_open(const char *filename)
gif_optimize = (!!cv_gif_optimize.value); gif_optimize = (!!cv_gif_optimize.value);
gif_downscale = (!!cv_gif_downscale.value); gif_downscale = (!!cv_gif_downscale.value);
gif_dynamicdelay = (!!cv_gif_dynamicdelay.value); gif_dynamicdelay = (UINT8)cv_gif_dynamicdelay.value;
gif_localcolortable = (!!cv_gif_localcolortable.value); gif_localcolortable = (!!cv_gif_localcolortable.value);
gif_colorprofile = (!!cv_screenshot_colorprofile.value); gif_colorprofile = (!!cv_screenshot_colorprofile.value);
gif_headerpalette = GIF_getpalette(0); gif_headerpalette = GIF_getpalette(0);

View file

@ -1108,7 +1108,6 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
mt->options = (mt->z << ZSHIFT) | (UINT16)cv_opflags.value; mt->options = (mt->z << ZSHIFT) | (UINT16)cv_opflags.value;
mt->scale = player->mo->scale; mt->scale = player->mo->scale;
mt->tag = 0;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->pitch = mt->roll = 0; mt->pitch = mt->roll = 0;
@ -1435,7 +1434,7 @@ void Command_Writethings_f(void)
REQUIRE_SINGLEPLAYER; REQUIRE_SINGLEPLAYER;
REQUIRE_OBJECTPLACE; REQUIRE_OBJECTPLACE;
P_WriteThings(W_GetNumForName(G_BuildMapName(gamemap)) + ML_THINGS); P_WriteThings();
} }
void Command_ObjectPlace_f(void) void Command_ObjectPlace_f(void)

View file

@ -425,7 +425,7 @@ static CV_PossibleValue_t skins_cons_t[MAXSKINS+1] = {{1, DEFAULTSKIN}};
consvar_t cv_chooseskin = CVAR_INIT ("chooseskin", DEFAULTSKIN, CV_HIDEN|CV_CALL, skins_cons_t, Nextmap_OnChange); consvar_t cv_chooseskin = CVAR_INIT ("chooseskin", DEFAULTSKIN, CV_HIDEN|CV_CALL, skins_cons_t, Nextmap_OnChange);
// This gametype list is integral for many different reasons. // This gametype list is integral for many different reasons.
// When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h! // When you add gametypes here, don't forget to update them in deh_tables.c and doomstat.h!
CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1]; CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1];
consvar_t cv_newgametype = CVAR_INIT ("newgametype", "Co-op", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange); consvar_t cv_newgametype = CVAR_INIT ("newgametype", "Co-op", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange);
@ -1483,7 +1483,7 @@ static menuitem_t OP_SoundOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "MIDI Music", &cv_gamemidimusic, 36}, {IT_STRING | IT_CVAR, NULL, "MIDI Music", &cv_gamemidimusic, 36},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "MIDI Music Volume", &cv_midimusicvolume, 41}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "MIDI Music Volume", &cv_midimusicvolume, 41},
{IT_STRING | IT_CVAR, NULL, "Music Preference", &cv_musicpref, 51}, {IT_STRING | IT_CVAR, NULL, "Music Preference", &cv_musicpref, 51},
{IT_HEADER, NULL, "Miscellaneous", NULL, 61}, {IT_HEADER, NULL, "Miscellaneous", NULL, 61},
@ -2145,15 +2145,20 @@ menu_t OP_PlaystyleDef = {
static void M_VideoOptions(INT32 choice) static void M_VideoOptions(INT32 choice)
{ {
(void)choice; (void)choice;
#ifdef HWRENDER
if (vid_opengl_state == -1)
{
OP_VideoOptionsMenu[op_video_renderer].status = (IT_TRANSTEXT | IT_PAIR);
OP_VideoOptionsMenu[op_video_renderer].patch = "Renderer";
OP_VideoOptionsMenu[op_video_renderer].text = "Software";
}
OP_VideoOptionsMenu[op_video_renderer].status = (IT_TRANSTEXT | IT_PAIR);
OP_VideoOptionsMenu[op_video_renderer].patch = "Renderer";
OP_VideoOptionsMenu[op_video_renderer].text = "Software";
#ifdef HWRENDER
if (vid.glstate != VID_GL_LIBRARY_ERROR)
{
OP_VideoOptionsMenu[op_video_renderer].status = (IT_STRING | IT_CVAR);
OP_VideoOptionsMenu[op_video_renderer].patch = NULL;
OP_VideoOptionsMenu[op_video_renderer].text = "Renderer";
}
#endif #endif
M_SetupNextMenu(&OP_VideoOptionsDef); M_SetupNextMenu(&OP_VideoOptionsDef);
} }
@ -4026,7 +4031,7 @@ static void M_DrawThermo(INT32 x, INT32 y, consvar_t *cv)
cursorlump = W_GetNumForName("M_THERMO"); cursorlump = W_GetNumForName("M_THERMO");
V_DrawScaledPatch(xx, y, 0, p = W_CachePatchNum(leftlump,PU_PATCH)); V_DrawScaledPatch(xx, y, 0, p = W_CachePatchNum(leftlump,PU_PATCH));
xx += SHORT(p->width) - SHORT(p->leftoffset); xx += p->width - p->leftoffset;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
{ {
V_DrawScaledPatch(xx, y, V_WRAPX, W_CachePatchNum(centerlump[i & 1], PU_PATCH)); V_DrawScaledPatch(xx, y, V_WRAPX, W_CachePatchNum(centerlump[i & 1], PU_PATCH));
@ -4165,7 +4170,7 @@ static void M_DrawStaticBox(fixed_t x, fixed_t y, INT32 flags, fixed_t w, fixed_
fixed_t sw, pw; fixed_t sw, pw;
patch = W_CachePatchName("LSSTATIC", PU_PATCH); patch = W_CachePatchName("LSSTATIC", PU_PATCH);
pw = SHORT(patch->width) - (sw = w*2); //FixedDiv(w, scale); -- for scale FRACUNIT/2 pw = patch->width - (sw = w*2); //FixedDiv(w, scale); -- for scale FRACUNIT/2
/*if (pw > 0) -- model code for modders providing weird LSSTATIC /*if (pw > 0) -- model code for modders providing weird LSSTATIC
{ {
@ -4262,8 +4267,8 @@ static void M_DrawMenuTitle(void)
if (p->height > 24) // title is larger than normal if (p->height > 24) // title is larger than normal
{ {
INT32 xtitle = (BASEVIDWIDTH - (SHORT(p->width)/2))/2; INT32 xtitle = (BASEVIDWIDTH - (p->width/2))/2;
INT32 ytitle = (30 - (SHORT(p->height)/2))/2; INT32 ytitle = (30 - (p->height/2))/2;
if (xtitle < 0) if (xtitle < 0)
xtitle = 0; xtitle = 0;
@ -4274,8 +4279,8 @@ static void M_DrawMenuTitle(void)
} }
else else
{ {
INT32 xtitle = (BASEVIDWIDTH - SHORT(p->width))/2; INT32 xtitle = (BASEVIDWIDTH - p->width)/2;
INT32 ytitle = (30 - SHORT(p->height))/2; INT32 ytitle = (30 - p->height)/2;
if (xtitle < 0) if (xtitle < 0)
xtitle = 0; xtitle = 0;
@ -4311,7 +4316,7 @@ static void M_DrawGenericMenu(void)
{ {
patch_t *p; patch_t *p;
p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_PATCH); p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_PATCH);
V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, y, 0, p); V_DrawScaledPatch((BASEVIDWIDTH - p->width)/2, y, 0, p);
} }
else else
{ {
@ -4842,7 +4847,7 @@ static void M_DrawCenteredMenu(void)
{ {
patch_t *p; patch_t *p;
p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_PATCH); p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_PATCH);
V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, y, 0, p); V_DrawScaledPatch((BASEVIDWIDTH - p->width)/2, y, 0, p);
} }
else else
{ {
@ -5585,9 +5590,6 @@ static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, bo
if (map <= 0) if (map <= 0)
return; return;
if (needpatchrecache)
M_CacheLevelPlatter();
// A 564x100 image of the level as entry MAPxxW // A 564x100 image of the level as entry MAPxxW
if (!(levelselect.rows[row].mapavailable[col])) if (!(levelselect.rows[row].mapavailable[col]))
{ {
@ -5619,9 +5621,6 @@ static void M_DrawLevelPlatterMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolea
if (map <= 0) if (map <= 0)
return; return;
if (needpatchrecache)
M_CacheLevelPlatter();
// A 160x100 image of the level as entry MAPxxP // A 160x100 image of the level as entry MAPxxP
if (!(levelselect.rows[row].mapavailable[col])) if (!(levelselect.rows[row].mapavailable[col]))
{ {
@ -5696,7 +5695,7 @@ static void M_DrawRecordAttackForeground(void)
angle_t fa; angle_t fa;
INT32 i; INT32 i;
INT32 height = (SHORT(fg->height)/2); INT32 height = (fg->height / 2);
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
for (i = -12; i < (BASEVIDHEIGHT/height) + 12; i++) for (i = -12; i < (BASEVIDHEIGHT/height) + 12; i++)
@ -5731,9 +5730,9 @@ static void M_DrawNightsAttackMountains(void)
static INT32 bgscrollx; static INT32 bgscrollx;
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
patch_t *background = W_CachePatchName(curbgname, PU_PATCH); patch_t *background = W_CachePatchName(curbgname, PU_PATCH);
INT16 w = SHORT(background->width); INT16 w = background->width;
INT32 x = FixedInt(-bgscrollx) % w; INT32 x = FixedInt(-bgscrollx) % w;
INT32 y = BASEVIDHEIGHT - SHORT(background->height)*2; INT32 y = BASEVIDHEIGHT - (background->height * 2);
if (vid.height != BASEVIDHEIGHT * dupz) if (vid.height != BASEVIDHEIGHT * dupz)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 158); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 158);
@ -5758,18 +5757,18 @@ static void M_DrawNightsAttackBackground(void)
// top // top
patch_t *backtopfg = W_CachePatchName("NTSATKT1", PU_PATCH); patch_t *backtopfg = W_CachePatchName("NTSATKT1", PU_PATCH);
patch_t *fronttopfg = W_CachePatchName("NTSATKT2", PU_PATCH); patch_t *fronttopfg = W_CachePatchName("NTSATKT2", PU_PATCH);
INT32 backtopwidth = SHORT(backtopfg->width); INT32 backtopwidth = backtopfg->width;
//INT32 backtopheight = SHORT(backtopfg->height); //INT32 backtopheight = backtopfg->height;
INT32 fronttopwidth = SHORT(fronttopfg->width); INT32 fronttopwidth = fronttopfg->width;
//INT32 fronttopheight = SHORT(fronttopfg->height); //INT32 fronttopheight = fronttopfg->height;
// bottom // bottom
patch_t *backbottomfg = W_CachePatchName("NTSATKB1", PU_PATCH); patch_t *backbottomfg = W_CachePatchName("NTSATKB1", PU_PATCH);
patch_t *frontbottomfg = W_CachePatchName("NTSATKB2", PU_PATCH); patch_t *frontbottomfg = W_CachePatchName("NTSATKB2", PU_PATCH);
INT32 backbottomwidth = SHORT(backbottomfg->width); INT32 backbottomwidth = backbottomfg->width;
INT32 backbottomheight = SHORT(backbottomfg->height); INT32 backbottomheight = backbottomfg->height;
INT32 frontbottomwidth = SHORT(frontbottomfg->width); INT32 frontbottomwidth = frontbottomfg->width;
INT32 frontbottomheight = SHORT(frontbottomfg->height); INT32 frontbottomheight = frontbottomfg->height;
// background // background
M_DrawNightsAttackMountains(); M_DrawNightsAttackMountains();
@ -5831,8 +5830,6 @@ static void M_DrawNightsAttackSuperSonic(void)
const UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_YELLOW, GTC_CACHE); const UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_YELLOW, GTC_CACHE);
INT32 timer = (ntsatkdrawtimer/4) % 2; INT32 timer = (ntsatkdrawtimer/4) % 2;
angle_t fa = (FixedAngle(((ntsatkdrawtimer * 4) % 360)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK; angle_t fa = (FixedAngle(((ntsatkdrawtimer * 4) % 360)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK;
ntssupersonic[0] = W_CachePatchName("NTSSONC1", PU_PATCH);
ntssupersonic[1] = W_CachePatchName("NTSSONC2", PU_PATCH);
V_DrawFixedPatch(235<<FRACBITS, (120<<FRACBITS) - (8*FINESINE(fa)), FRACUNIT, 0, ntssupersonic[timer], colormap); V_DrawFixedPatch(235<<FRACBITS, (120<<FRACBITS) - (8*FINESINE(fa)), FRACUNIT, 0, ntssupersonic[timer], colormap);
} }
@ -6154,7 +6151,7 @@ static void M_DrawMessageMenu(void)
} }
V_DrawString((BASEVIDWIDTH - V_StringWidth(string, 0))/2,y,V_ALLOWLOWERCASE,string); V_DrawString((BASEVIDWIDTH - V_StringWidth(string, 0))/2,y,V_ALLOWLOWERCASE,string);
y += 8; //SHORT(hu_font[0]->height); y += 8; //hu_font[0]->height;
} }
} }
@ -6176,7 +6173,7 @@ static void M_StopMessage(INT32 choice)
static void M_DrawImageDef(void) static void M_DrawImageDef(void)
{ {
// Grr. Need to autodetect for pic_ts. // Grr. Need to autodetect for pic_ts.
pic_t *pictest = (pic_t *)W_CachePatchName(currentMenu->menuitems[itemOn].text,PU_CACHE); pic_t *pictest = (pic_t *)W_CacheLumpName(currentMenu->menuitems[itemOn].text,PU_CACHE);
if (!pictest->zero) if (!pictest->zero)
V_DrawScaledPic(0,0,0,W_GetNumForName(currentMenu->menuitems[itemOn].text)); V_DrawScaledPic(0,0,0,W_GetNumForName(currentMenu->menuitems[itemOn].text));
else else
@ -6444,10 +6441,6 @@ static void M_DrawAddons(void)
return; return;
} }
// Lactozilla: Load addons menu patches.
if (needpatchrecache)
M_LoadAddonsPatches();
if (Playing()) if (Playing())
V_DrawCenteredString(BASEVIDWIDTH/2, 5, warningflags, "Adding files mid-game may cause problems."); V_DrawCenteredString(BASEVIDWIDTH/2, 5, warningflags, "Adding files mid-game may cause problems.");
else else
@ -7602,9 +7595,6 @@ static void M_DrawSoundTest(void)
fixed_t hscale = FRACUNIT/2, vscale = FRACUNIT/2, bounce = 0; fixed_t hscale = FRACUNIT/2, vscale = FRACUNIT/2, bounce = 0;
UINT8 frame[4] = {0, 0, -1, SKINCOLOR_RUBY}; UINT8 frame[4] = {0, 0, -1, SKINCOLOR_RUBY};
if (needpatchrecache)
M_CacheSoundTest();
// let's handle the ticker first. ideally we'd tick this somewhere else, BUT... // let's handle the ticker first. ideally we'd tick this somewhere else, BUT...
if (curplaying) if (curplaying)
{ {
@ -8252,9 +8242,6 @@ static void M_DrawLoadGameData(void)
if (vid.width != BASEVIDWIDTH*vid.dupx) if (vid.width != BASEVIDWIDTH*vid.dupx)
hsep = (hsep*vid.width)/(BASEVIDWIDTH*vid.dupx); hsep = (hsep*vid.width)/(BASEVIDWIDTH*vid.dupx);
if (needpatchrecache)
M_CacheLoadGameData();
for (i = 2; prev_i; i = -(i + ((UINT32)i >> 31))) // draws from outwards in; 2, -2, 1, -1, 0 for (i = 2; prev_i; i = -(i + ((UINT32)i >> 31))) // draws from outwards in; 2, -2, 1, -1, 0
{ {
prev_i = i; prev_i = i;
@ -8958,6 +8945,7 @@ void M_ForceSaveSlotSelected(INT32 sslot)
// ================ // ================
// CHARACTER SELECT // CHARACTER SELECT
// ================ // ================
static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum) static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum)
{ {
if (!(description[i].picname[0])) if (!(description[i].picname[0]))
@ -8978,22 +8966,6 @@ static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum)
description[i].namepic = W_CachePatchName(description[i].nametag, PU_PATCH); description[i].namepic = W_CachePatchName(description[i].nametag, PU_PATCH);
} }
static void M_CacheCharacterSelect(void)
{
INT32 i, skinnum;
for (i = 0; i < MAXSKINS; i++)
{
if (!description[i].used)
continue;
// Already set in M_SetupChoosePlayer
skinnum = description[i].skinnum[0];
if ((skinnum != -1) && (R_SkinUsable(-1, skinnum)))
M_CacheCharacterSelectEntry(i, skinnum);
}
}
static UINT8 M_SetupChoosePlayerDirect(INT32 choice) static UINT8 M_SetupChoosePlayerDirect(INT32 choice)
{ {
INT32 skinnum; INT32 skinnum;
@ -9193,16 +9165,13 @@ static void M_DrawSetupChoosePlayerMenu(void)
patch_t *charbg = W_CachePatchName("CHARBG", PU_PATCH); patch_t *charbg = W_CachePatchName("CHARBG", PU_PATCH);
patch_t *charfg = W_CachePatchName("CHARFG", PU_PATCH); patch_t *charfg = W_CachePatchName("CHARFG", PU_PATCH);
INT16 bgheight = SHORT(charbg->height); INT16 bgheight = charbg->height;
INT16 fgheight = SHORT(charfg->height); INT16 fgheight = charfg->height;
INT16 bgwidth = SHORT(charbg->width); INT16 bgwidth = charbg->width;
INT16 fgwidth = SHORT(charfg->width); INT16 fgwidth = charfg->width;
INT32 x, y; INT32 x, y;
INT32 w = (vid.width/vid.dupx); INT32 w = (vid.width/vid.dupx);
if (needpatchrecache)
M_CacheCharacterSelect();
if (abs(char_scroll) > FRACUNIT) if (abs(char_scroll) > FRACUNIT)
char_scroll -= (char_scroll>>2); char_scroll -= (char_scroll>>2);
else // close enough. else // close enough.
@ -9291,14 +9260,14 @@ static void M_DrawSetupChoosePlayerMenu(void)
curoutlinecolor = col = skincolors[charskin->prefcolor].invcolor; curoutlinecolor = col = skincolors[charskin->prefcolor].invcolor;
txsh = oxsh; txsh = oxsh;
ox = 8 + SHORT((description[char_on].charpic)->width)/2; ox = 8 + ((description[char_on].charpic)->width)/2;
y = my + 144; y = my + 144;
// cur // cur
{ {
x = ox - txsh; x = ox - txsh;
if (curpatch) if (curpatch)
x -= (SHORT(curpatch->width)/2); x -= curpatch->width / 2;
if (curtext[0] != '\0') if (curtext[0] != '\0')
{ {
@ -9331,7 +9300,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
x = (ox - txsh) - w; x = (ox - txsh) - w;
if (prevpatch) if (prevpatch)
x -= (SHORT(prevpatch->width)/2); x -= prevpatch->width / 2;
if (prevtext[0] != '\0') if (prevtext[0] != '\0')
{ {
@ -9361,7 +9330,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
x = (ox - txsh) + w; x = (ox - txsh) + w;
if (nextpatch) if (nextpatch)
x -= (SHORT(nextpatch->width)/2); x -= nextpatch->width / 2;
if (nexttext[0] != '\0') if (nexttext[0] != '\0')
{ {
@ -9383,7 +9352,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
{ {
patch_t *header = W_CachePatchName("M_PICKP", PU_PATCH); patch_t *header = W_CachePatchName("M_PICKP", PU_PATCH);
INT32 xtitle = 146; INT32 xtitle = 146;
INT32 ytitle = (35 - SHORT(header->height))/2; INT32 ytitle = (35 - header->height) / 2;
V_DrawFixedPatch(xtitle<<FRACBITS, ytitle<<FRACBITS, FRACUNIT/2, 0, header, NULL); V_DrawFixedPatch(xtitle<<FRACBITS, ytitle<<FRACBITS, FRACUNIT/2, 0, header, NULL);
} }
#endif // CHOOSEPLAYER_DRAWHEADER #endif // CHOOSEPLAYER_DRAWHEADER
@ -9849,8 +9818,8 @@ void M_DrawTimeAttackMenu(void)
empatch = W_CachePatchName(M_GetEmblemPatch(em, true), PU_PATCH); empatch = W_CachePatchName(M_GetEmblemPatch(em, true), PU_PATCH);
empatx = SHORT(empatch->leftoffset)/2; empatx = empatch->leftoffset / 2;
empaty = SHORT(empatch->topoffset)/2; empaty = empatch->topoffset / 2;
if (em->collected) if (em->collected)
V_DrawSmallMappedPatch(104+76+empatx, yHeight+lsheadingheight/2+empaty, 0, empatch, V_DrawSmallMappedPatch(104+76+empatx, yHeight+lsheadingheight/2+empaty, 0, empatch,
@ -10086,7 +10055,7 @@ void M_DrawNightsAttackMenu(void)
// Super Sonic // Super Sonic
M_DrawNightsAttackSuperSonic(); M_DrawNightsAttackSuperSonic();
//if (P_HasGrades(cv_nextmap.value, 0)) //if (P_HasGrades(cv_nextmap.value, 0))
// V_DrawScaledPatch(235 - (SHORT((ngradeletters[bestoverall])->width)*3)/2, 135, 0, ngradeletters[bestoverall]); // V_DrawScaledPatch(235 - (((ngradeletters[bestoverall])->width)*3)/2, 135, 0, ngradeletters[bestoverall]);
if (P_HasGrades(cv_nextmap.value, cv_dummymares.value)) if (P_HasGrades(cv_nextmap.value, cv_dummymares.value))
{//make bigger again {//make bigger again
@ -10173,6 +10142,9 @@ static void M_NightsAttack(INT32 choice)
// This is really just to make sure Sonic is the played character, just in case // This is really just to make sure Sonic is the played character, just in case
M_PatchSkinNameTable(); M_PatchSkinNameTable();
ntssupersonic[0] = W_CachePatchName("NTSSONC1", PU_PATCH);
ntssupersonic[1] = W_CachePatchName("NTSSONC2", PU_PATCH);
G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching
titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please
M_SetupNextMenu(&SP_NightsAttackDef); M_SetupNextMenu(&SP_NightsAttackDef);
@ -10574,10 +10546,6 @@ void M_DrawMarathon(void)
angle_t fa; angle_t fa;
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy), xspan = (vid.width/dupz), yspan = (vid.height/dupz), diffx = (xspan - BASEVIDWIDTH)/2, diffy = (yspan - BASEVIDHEIGHT)/2, maxy = BASEVIDHEIGHT + diffy; INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy), xspan = (vid.width/dupz), yspan = (vid.height/dupz), diffx = (xspan - BASEVIDWIDTH)/2, diffy = (yspan - BASEVIDHEIGHT)/2, maxy = BASEVIDHEIGHT + diffy;
// lactozilla: the renderer changed so recache patches
if (needpatchrecache)
M_CacheCharacterSelect();
curbgxspeed = 0; curbgxspeed = 0;
curbgyspeed = 18; curbgyspeed = 18;
@ -10644,7 +10612,7 @@ void M_DrawMarathon(void)
{ {
patch_t *fg = W_CachePatchName("RECATKFG", PU_PATCH); patch_t *fg = W_CachePatchName("RECATKFG", PU_PATCH);
INT32 trans = V_60TRANS+((cnt&~3)<<(V_ALPHASHIFT-2)); INT32 trans = V_60TRANS+((cnt&~3)<<(V_ALPHASHIFT-2));
INT32 height = (SHORT(fg->height)/2); INT32 height = fg->height / 2;
char patchname[7] = "CEMGx0"; char patchname[7] = "CEMGx0";
dupz = (w*7)/6; //(w*42*120)/(360*6); -- I don't know why this works but I'm not going to complain. dupz = (w*7)/6; //(w*42*120)/(360*6); -- I don't know why this works but I'm not going to complain.
@ -11414,7 +11382,7 @@ static void M_DrawServerMenu(void)
else else
PictureOfLevel = W_CachePatchName("BLANKLVL", PU_PATCH); PictureOfLevel = W_CachePatchName("BLANKLVL", PU_PATCH);
V_DrawSmallScaledPatch(319 - (currentMenu->x + (SHORT(PictureOfLevel->width)/2)), currentMenu->y + imgheight, 0, PictureOfLevel); V_DrawSmallScaledPatch(319 - (currentMenu->x + (PictureOfLevel->width / 2)), currentMenu->y + imgheight, 0, PictureOfLevel);
} }
} }

View file

@ -394,8 +394,10 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
INT32 secnum = -1; INT32 secnum = -1;
sector_t *sec; sector_t *sec;
ceiling_t *ceiling; ceiling_t *ceiling;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_DECLARECOUNTER(0);
while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0) TAG_ITER_SECTORS(0, tag, secnum)
{ {
sec = &sectors[secnum]; sec = &sectors[secnum];
@ -593,7 +595,7 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
} }
ceiling->tag = sec->tag; ceiling->tag = tag;
ceiling->type = type; ceiling->type = type;
firstone = 0; firstone = 0;
} }
@ -614,8 +616,10 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
INT32 secnum = -1; INT32 secnum = -1;
sector_t *sec; sector_t *sec;
ceiling_t *ceiling; ceiling_t *ceiling;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_DECLARECOUNTER(0);
while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0) TAG_ITER_SECTORS(0, tag, secnum)
{ {
sec = &sectors[secnum]; sec = &sectors[secnum];
@ -670,7 +674,7 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
break; break;
} }
ceiling->tag = sec->tag; ceiling->tag = tag;
ceiling->type = type; ceiling->type = type;
} }
return rtn; return rtn;

File diff suppressed because it is too large Load diff

View file

@ -632,8 +632,10 @@ void T_BounceCheese(bouncecheese_t *bouncer)
fixed_t waterheight; fixed_t waterheight;
fixed_t floorheight; fixed_t floorheight;
sector_t *actionsector; sector_t *actionsector;
INT32 i;
boolean remove; boolean remove;
INT32 i;
mtag_t tag = Tag_FGet(&bouncer->sourceline->tags);
TAG_ITER_DECLARECOUNTER(0);
if (bouncer->sector->crumblestate == CRUMBLE_RESTORE || bouncer->sector->crumblestate == CRUMBLE_WAIT if (bouncer->sector->crumblestate == CRUMBLE_RESTORE || bouncer->sector->crumblestate == CRUMBLE_WAIT
|| bouncer->sector->crumblestate == CRUMBLE_ACTIVATED) // Oops! Crumbler says to remove yourself! || bouncer->sector->crumblestate == CRUMBLE_ACTIVATED) // Oops! Crumbler says to remove yourself!
@ -648,7 +650,7 @@ void T_BounceCheese(bouncecheese_t *bouncer)
} }
// You can use multiple target sectors, but at your own risk!!! // You can use multiple target sectors, but at your own risk!!!
for (i = -1; (i = P_FindSectorFromTag(bouncer->sourceline->tag, i)) >= 0 ;) TAG_ITER_SECTORS(0, tag, i)
{ {
actionsector = &sectors[i]; actionsector = &sectors[i];
actionsector->moved = true; actionsector->moved = true;
@ -772,6 +774,8 @@ void T_StartCrumble(crumble_t *crumble)
ffloor_t *rover; ffloor_t *rover;
sector_t *sector; sector_t *sector;
INT32 i; INT32 i;
mtag_t tag = Tag_FGet(&crumble->sourceline->tags);
TAG_ITER_DECLARECOUNTER(0);
// Once done, the no-return thinker just sits there, // Once done, the no-return thinker just sits there,
// constantly 'returning'... kind of an oxymoron, isn't it? // constantly 'returning'... kind of an oxymoron, isn't it?
@ -800,7 +804,7 @@ void T_StartCrumble(crumble_t *crumble)
} }
else if (++crumble->timer == 0) // Reposition back to original spot else if (++crumble->timer == 0) // Reposition back to original spot
{ {
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;) TAG_ITER_SECTORS(0, tag, i)
{ {
sector = &sectors[i]; sector = &sectors[i];
@ -836,7 +840,7 @@ void T_StartCrumble(crumble_t *crumble)
// Flash to indicate that the platform is about to return. // Flash to indicate that the platform is about to return.
if (crumble->timer > -224 && (leveltime % ((abs(crumble->timer)/8) + 1) == 0)) if (crumble->timer > -224 && (leveltime % ((abs(crumble->timer)/8) + 1) == 0))
{ {
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;) TAG_ITER_SECTORS(0, tag, i)
{ {
sector = &sectors[i]; sector = &sectors[i];
@ -928,7 +932,7 @@ void T_StartCrumble(crumble_t *crumble)
P_RemoveThinker(&crumble->thinker); P_RemoveThinker(&crumble->thinker);
} }
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;) TAG_ITER_SECTORS(0, tag, i)
{ {
sector = &sectors[i]; sector = &sectors[i];
sector->moved = true; sector->moved = true;
@ -944,6 +948,7 @@ void T_StartCrumble(crumble_t *crumble)
void T_MarioBlock(mariothink_t *block) void T_MarioBlock(mariothink_t *block)
{ {
INT32 i; INT32 i;
TAG_ITER_DECLARECOUNTER(0);
T_MovePlane T_MovePlane
( (
@ -978,8 +983,7 @@ void T_MarioBlock(mariothink_t *block)
block->sector->ceilspeed = 0; block->sector->ceilspeed = 0;
block->direction = 0; block->direction = 0;
} }
TAG_ITER_SECTORS(0, (INT16)block->tag, i)
for (i = -1; (i = P_FindSectorFromTag(block->tag, i)) >= 0 ;)
P_RecalcPrecipInSector(&sectors[i]); P_RecalcPrecipInSector(&sectors[i]);
} }
@ -992,8 +996,7 @@ void T_FloatSector(floatthink_t *floater)
// Just find the first sector with the tag. // Just find the first sector with the tag.
// Doesn't work with multiple sectors that have different floor/ceiling heights. // Doesn't work with multiple sectors that have different floor/ceiling heights.
secnum = P_FindSectorFromTag(floater->tag, -1); if ((secnum = Tag_Iterate_Sectors((INT16)floater->tag, 0)) < 0)
if (secnum <= 0)
return; return;
actionsector = &sectors[secnum]; actionsector = &sectors[secnum];
@ -1131,10 +1134,8 @@ void T_ThwompSector(thwomp_t *thwomp)
// Just find the first sector with the tag. // Just find the first sector with the tag.
// Doesn't work with multiple sectors that have different floor/ceiling heights. // Doesn't work with multiple sectors that have different floor/ceiling heights.
secnum = P_FindSectorFromTag(thwomp->tag, -1); if ((secnum = Tag_Iterate_Sectors((INT16)thwomp->tag, 0)) < 0)
return;
if (secnum <= 0)
return; // Bad bad bad!
actionsector = &sectors[secnum]; actionsector = &sectors[secnum];
@ -1293,8 +1294,10 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
sector_t *sec = NULL; sector_t *sec = NULL;
INT32 secnum = -1; INT32 secnum = -1;
boolean FOFsector = false; boolean FOFsector = false;
mtag_t tag = Tag_FGet(&nobaddies->sourceline->tags);
TAG_ITER_DECLARECOUNTER(0);
while ((secnum = P_FindSectorFromTag(nobaddies->sourceline->tag, secnum)) >= 0) TAG_ITER_SECTORS(0, tag, secnum)
{ {
sec = &sectors[secnum]; sec = &sectors[secnum];
@ -1304,13 +1307,15 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
for (i = 0; i < sec->linecount; i++) for (i = 0; i < sec->linecount; i++)
{ {
INT32 targetsecnum = -1; INT32 targetsecnum = -1;
mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags);
TAG_ITER_DECLARECOUNTER(1);
if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300) if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300)
continue; continue;
FOFsector = true; FOFsector = true;
while ((targetsecnum = P_FindSectorFromTag(sec->lines[i]->tag, targetsecnum)) >= 0) TAG_ITER_SECTORS(1, tag2, targetsecnum)
{ {
if (T_SectorHasEnemies(&sectors[targetsecnum])) if (T_SectorHasEnemies(&sectors[targetsecnum]))
return; return;
@ -1321,7 +1326,7 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
return; return;
} }
CONS_Debug(DBG_GAMELOGIC, "Running no-more-enemies exec with tag of %d\n", nobaddies->sourceline->tag); CONS_Debug(DBG_GAMELOGIC, "Running no-more-enemies exec with tag of %d\n", tag);
// No enemies found, run the linedef exec and terminate this thinker // No enemies found, run the linedef exec and terminate this thinker
P_RunTriggerLinedef(nobaddies->sourceline, NULL, NULL); P_RunTriggerLinedef(nobaddies->sourceline, NULL, NULL);
@ -1396,6 +1401,8 @@ void T_EachTimeThinker(eachtime_t *eachtime)
boolean floortouch = false; boolean floortouch = false;
fixed_t bottomheight, topheight; fixed_t bottomheight, topheight;
ffloor_t *rover; ffloor_t *rover;
mtag_t tag = Tag_FGet(&eachtime->sourceline->tags);
TAG_ITER_DECLARECOUNTER(0);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
@ -1405,7 +1412,7 @@ void T_EachTimeThinker(eachtime_t *eachtime)
eachtime->playersOnArea[i] = false; eachtime->playersOnArea[i] = false;
} }
while ((secnum = P_FindSectorFromTag(eachtime->sourceline->tag, secnum)) >= 0) TAG_ITER_SECTORS(0, tag, secnum)
{ {
sec = &sectors[secnum]; sec = &sectors[secnum];
@ -1422,13 +1429,15 @@ void T_EachTimeThinker(eachtime_t *eachtime)
for (i = 0; i < sec->linecount; i++) for (i = 0; i < sec->linecount; i++)
{ {
INT32 targetsecnum = -1; INT32 targetsecnum = -1;
mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags);
TAG_ITER_DECLARECOUNTER(1);
if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300) if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300)
continue; continue;
FOFsector = true; FOFsector = true;
while ((targetsecnum = P_FindSectorFromTag(sec->lines[i]->tag, targetsecnum)) >= 0) TAG_ITER_SECTORS(1, tag2, targetsecnum)
{ {
targetsec = &sectors[targetsecnum]; targetsec = &sectors[targetsecnum];
@ -1530,7 +1539,7 @@ void T_EachTimeThinker(eachtime_t *eachtime)
if (!playersArea[i] && (!eachtime->triggerOnExit || !P_IsPlayerValid(i))) if (!playersArea[i] && (!eachtime->triggerOnExit || !P_IsPlayerValid(i)))
continue; continue;
CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", eachtime->sourceline->tag); CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", tag);
// 03/08/14 -Monster Iestyn // 03/08/14 -Monster Iestyn
// No more stupid hacks involving changing eachtime->sourceline's tag or special or whatever! // No more stupid hacks involving changing eachtime->sourceline's tag or special or whatever!
@ -1562,11 +1571,13 @@ void T_RaiseSector(raise_t *raise)
fixed_t distToNearestEndpoint; fixed_t distToNearestEndpoint;
INT32 direction; INT32 direction;
result_e res = 0; result_e res = 0;
mtag_t tag = raise->tag;
TAG_ITER_DECLARECOUNTER(0);
if (raise->sector->crumblestate >= CRUMBLE_FALL || raise->sector->ceilingdata) if (raise->sector->crumblestate >= CRUMBLE_FALL || raise->sector->ceilingdata)
return; return;
for (i = -1; (i = P_FindSectorFromTag(raise->tag, i)) >= 0 ;) TAG_ITER_SECTORS(0, tag, i)
{ {
sector = &sectors[i]; sector = &sectors[i];
@ -1693,7 +1704,7 @@ void T_RaiseSector(raise_t *raise)
raise->sector->ceilspeed = 42; raise->sector->ceilspeed = 42;
raise->sector->floorspeed = speed*direction; raise->sector->floorspeed = speed*direction;
for (i = -1; (i = P_FindSectorFromTag(raise->tag, i)) >= 0 ;) TAG_ITER_SECTORS(0, tag, i)
P_RecalcPrecipInSector(&sectors[i]); P_RecalcPrecipInSector(&sectors[i]);
} }
@ -1810,8 +1821,10 @@ void EV_DoFloor(line_t *line, floor_e floortype)
INT32 secnum = -1; INT32 secnum = -1;
sector_t *sec; sector_t *sec;
floormove_t *dofloor; floormove_t *dofloor;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_DECLARECOUNTER(0);
while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0) TAG_ITER_SECTORS(0, tag, secnum)
{ {
sec = &sectors[secnum]; sec = &sectors[secnum];
@ -2025,9 +2038,11 @@ void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
INT32 secnum = -1; INT32 secnum = -1;
sector_t *sec; sector_t *sec;
elevator_t *elevator; elevator_t *elevator;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_DECLARECOUNTER(0);
// act on all sectors with the same tag as the triggering linedef // act on all sectors with the same tag as the triggering linedef
while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0) TAG_ITER_SECTORS(0, tag, secnum)
{ {
sec = &sectors[secnum]; sec = &sectors[secnum];
@ -2148,6 +2163,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
INT16 flags; INT16 flags;
sector_t *controlsec = rover->master->frontsector; sector_t *controlsec = rover->master->frontsector;
mtag_t tag = Tag_FGet(&controlsec->tags);
if (sec == NULL) if (sec == NULL)
{ {
@ -2176,9 +2192,9 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
lifetime = 3*TICRATE; lifetime = 3*TICRATE;
flags = 0; flags = 0;
if (controlsec->tag != 0) if (tag != 0)
{ {
INT32 tagline = P_FindSpecialLineFromTag(14, controlsec->tag, -1); INT32 tagline = Tag_FindLineSpecial(14, tag);
if (tagline != -1) if (tagline != -1)
{ {
if (sides[lines[tagline].sidenum[0]].toptexture) if (sides[lines[tagline].sidenum[0]].toptexture)
@ -2322,6 +2338,8 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
crumble_t *crumble; crumble_t *crumble;
sector_t *foundsec; sector_t *foundsec;
INT32 i; INT32 i;
mtag_t tag = Tag_FGet(&rover->master->tags);
TAG_ITER_DECLARECOUNTER(0);
// If floor is already activated, skip it // If floor is already activated, skip it
if (sec->floordata) if (sec->floordata)
@ -2364,7 +2382,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
crumble->sector->crumblestate = CRUMBLE_ACTIVATED; crumble->sector->crumblestate = CRUMBLE_ACTIVATED;
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;) TAG_ITER_SECTORS(0, tag, i)
{ {
foundsec = &sectors[i]; foundsec = &sectors[i];
@ -2413,7 +2431,7 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
block->direction = 1; block->direction = 1;
block->floorstartheight = block->sector->floorheight; block->floorstartheight = block->sector->floorheight;
block->ceilingstartheight = block->sector->ceilingheight; block->ceilingstartheight = block->sector->ceilingheight;
block->tag = (INT16)sector->tag; block->tag = (INT16)Tag_FGet(&sector->tags);
if (itsamonitor) if (itsamonitor)
{ {

View file

@ -1388,7 +1388,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->bot) if (player->bot)
return; return;
junk.tag = LE_AXE; Tag_FSet(&junk.tags, LE_AXE);
EV_DoElevator(&junk, bridgeFall, false); EV_DoElevator(&junk, bridgeFall, false);
// scan the remaining thinkers to find koopa // scan the remaining thinkers to find koopa

View file

@ -374,8 +374,10 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean
void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force) void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force)
{ {
INT32 i; INT32 i;
TAG_ITER_DECLARECOUNTER(0);
// search all sectors for ones with tag // search all sectors for ones with tag
for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0 ;) TAG_ITER_SECTORS(0, tag, i)
{ {
if (!force && ticbased // always let speed fader execute if (!force && ticbased // always let speed fader execute
&& sectors[i].lightingdata && sectors[i].lightingdata

View file

@ -2735,7 +2735,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
// Step up // Step up
if (thing->z < tmfloorz) if (thing->z < tmfloorz)
{ {
if (tmfloorz - thing->z <= maxstep) if (maxstep > 0 && tmfloorz - thing->z <= maxstep)
{ {
thing->z = thing->floorz = tmfloorz; thing->z = thing->floorz = tmfloorz;
thing->floorrover = tmfloorrover; thing->floorrover = tmfloorrover;
@ -2748,7 +2748,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
} }
else if (tmceilingz < thingtop) else if (tmceilingz < thingtop)
{ {
if (thingtop - tmceilingz <= maxstep) if (maxstep > 0 && thingtop - tmceilingz <= maxstep)
{ {
thing->z = ( thing->ceilingz = tmceilingz ) - thing->height; thing->z = ( thing->ceilingz = tmceilingz ) - thing->height;
thing->ceilingrover = tmceilingrover; thing->ceilingrover = tmceilingrover;
@ -3107,7 +3107,7 @@ static void P_HitSlideLine(line_t *ld)
lineangle >>= ANGLETOFINESHIFT; lineangle >>= ANGLETOFINESHIFT;
deltaangle >>= ANGLETOFINESHIFT; deltaangle >>= ANGLETOFINESHIFT;
movelen = P_AproxDistance(tmxmove, tmymove); movelen = R_PointToDist2(0, 0, tmxmove, tmymove);
newlen = FixedMul(movelen, FINECOSINE(deltaangle)); newlen = FixedMul(movelen, FINECOSINE(deltaangle));
tmxmove = FixedMul(newlen, FINECOSINE(lineangle)); tmxmove = FixedMul(newlen, FINECOSINE(lineangle));

View file

@ -38,10 +38,6 @@
static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}}; static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL); consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL);
#ifdef WALLSPLATS
consvar_t cv_splats = CVAR_INIT ("splats", "On", CV_SAVE, CV_OnOff, NULL);
#endif
actioncache_t actioncachehead; actioncache_t actioncachehead;
static mobj_t *overlaycap = NULL; static mobj_t *overlaycap = NULL;
@ -1961,29 +1957,6 @@ void P_XYMovement(mobj_t *mo)
return; return;
} }
// draw damage on wall
//SPLAT TEST ----------------------------------------------------------
#ifdef WALLSPLATS
if (blockingline && mo->type != MT_REDRING && mo->type != MT_FIREBALL
&& !(mo->flags2 & (MF2_AUTOMATIC|MF2_RAILRING|MF2_BOUNCERING|MF2_EXPLOSION|MF2_SCATTER)))
// set by last P_TryMove() that failed
{
divline_t divl;
divline_t misl;
fixed_t frac;
P_MakeDivline(blockingline, &divl);
misl.x = mo->x;
misl.y = mo->y;
misl.dx = mo->momx;
misl.dy = mo->momy;
frac = P_InterceptVector(&divl, &misl);
R_AddWallSplat(blockingline, P_PointOnLineSide(mo->x,mo->y,blockingline),
"A_DMG3", mo->z, frac, SPLATDRAWMODE_SHADE);
}
#endif
// --------------------------------------------------------- SPLAT TEST
P_ExplodeMissile(mo); P_ExplodeMissile(mo);
return; return;
} }
@ -3536,16 +3509,19 @@ static boolean P_CameraCheckHeat(camera_t *thiscam)
{ {
sector_t *sector; sector_t *sector;
fixed_t halfheight = thiscam->z + (thiscam->height >> 1); fixed_t halfheight = thiscam->z + (thiscam->height >> 1);
size_t i;
// see if we are in water // see if we are in water
sector = thiscam->subsector->sector; sector = thiscam->subsector->sector;
if (P_FindSpecialLineFromTag(13, sector->tag, -1) != -1) for (i = 0; i < sector->tags.count; i++)
return true; if (Tag_FindLineSpecial(13, sector->tags.tags[i]) != -1)
return true;
if (sector->ffloors) if (sector->ffloors)
{ {
ffloor_t *rover; ffloor_t *rover;
size_t j;
for (rover = sector->ffloors; rover; rover = rover->next) for (rover = sector->ffloors; rover; rover = rover->next)
{ {
@ -3557,7 +3533,8 @@ static boolean P_CameraCheckHeat(camera_t *thiscam)
if (halfheight <= P_GetFFloorBottomZAt(rover, thiscam->x, thiscam->y)) if (halfheight <= P_GetFFloorBottomZAt(rover, thiscam->x, thiscam->y))
continue; continue;
if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1) for (j = 0; j < rover->master->frontsector->tags.count; j++)
if (Tag_FindLineSpecial(13, rover->master->frontsector->tags.tags[j]) != -1)
return true; return true;
} }
} }
@ -4626,16 +4603,18 @@ static boolean P_Boss4MoveCage(mobj_t *mobj, fixed_t delta)
const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0); const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0);
INT32 snum; INT32 snum;
sector_t *sector; sector_t *sector;
for (snum = sectors[tag%numsectors].firsttag; snum != -1; snum = sector->nexttag) boolean gotcage = false;
TAG_ITER_DECLARECOUNTER(0);
TAG_ITER_SECTORS(0, tag, snum)
{ {
sector = &sectors[snum]; sector = &sectors[snum];
if (sector->tag != tag)
continue;
sector->floorheight += delta; sector->floorheight += delta;
sector->ceilingheight += delta; sector->ceilingheight += delta;
P_CheckSector(sector, true); P_CheckSector(sector, true);
gotcage = true;
} }
return sectors[tag%numsectors].firsttag != -1; return gotcage;
} }
// Move Boss4's arms to angle // Move Boss4's arms to angle
@ -4707,26 +4686,16 @@ static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t dz)
static void P_Boss4DestroyCage(mobj_t *mobj) static void P_Boss4DestroyCage(mobj_t *mobj)
{ {
const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0); const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0);
INT32 snum, next; INT32 snum;
size_t a; size_t a;
sector_t *sector, *rsec; sector_t *sector, *rsec;
ffloor_t *rover; ffloor_t *rover;
TAG_ITER_DECLARECOUNTER(0);
// This will be the final iteration of sector tag. TAG_ITER_SECTORS(0, tag, snum)
// We'll destroy the tag list as we go.
next = sectors[tag%numsectors].firsttag;
sectors[tag%numsectors].firsttag = -1;
for (snum = next; snum != -1; snum = next)
{ {
sector = &sectors[snum]; sector = &sectors[snum];
next = sector->nexttag;
sector->nexttag = -1;
if (sector->tag != tag)
continue;
sector->tag = 0;
// Destroy the FOFs. // Destroy the FOFs.
for (a = 0; a < sector->numattached; a++) for (a = 0; a < sector->numattached; a++)
{ {
@ -9614,12 +9583,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
mobj->fuse = 1; // Return to base. mobj->fuse = 1; // Return to base.
break; break;
} }
case MT_CANNONBALL:
#ifdef FLOORSPLATS
R_AddFloorSplat(mobj->tracer->subsector, mobj->tracer, "TARGET", mobj->tracer->x,
mobj->tracer->y, mobj->tracer->floorz, SPLATDRAWMODE_SHADE);
#endif
break;
case MT_SPINDUST: // Spindash dust case MT_SPINDUST: // Spindash dust
mobj->momx = FixedMul(mobj->momx, (3*FRACUNIT)/4); // originally 50000 mobj->momx = FixedMul(mobj->momx, (3*FRACUNIT)/4); // originally 50000
mobj->momy = FixedMul(mobj->momy, (3*FRACUNIT)/4); // same mobj->momy = FixedMul(mobj->momy, (3*FRACUNIT)/4); // same
@ -10046,11 +10009,12 @@ void P_MobjThinker(mobj_t *mobj)
// Sector special (2,8) allows ANY mobj to trigger a linedef exec // Sector special (2,8) allows ANY mobj to trigger a linedef exec
if (mobj->subsector && GETSECSPECIAL(mobj->subsector->sector->special, 2) == 8) if (mobj->subsector && GETSECSPECIAL(mobj->subsector->sector->special, 2) == 8)
{ {
sector_t *sec2; sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj);
sec2 = P_ThingOnSpecial3DFloor(mobj);
if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1) if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1)
P_LinedefExecute(sec2->tag, mobj, sec2); {
mtag_t tag = Tag_FGet(&sec2->tags);
P_LinedefExecute(tag, mobj, sec2);
}
} }
if (mobj->scale != mobj->destscale) if (mobj->scale != mobj->destscale)
@ -10274,14 +10238,19 @@ void P_PushableThinker(mobj_t *mobj)
sec = mobj->subsector->sector; sec = mobj->subsector->sector;
if (GETSECSPECIAL(sec->special, 2) == 1 && mobj->z == sec->floorheight) if (GETSECSPECIAL(sec->special, 2) == 1 && mobj->z == sec->floorheight)
P_LinedefExecute(sec->tag, mobj, sec); {
mtag_t tag = Tag_FGet(&sec->tags);
P_LinedefExecute(tag, mobj, sec);
}
// else if (GETSECSPECIAL(sec->special, 2) == 8) // else if (GETSECSPECIAL(sec->special, 2) == 8)
{ {
sector_t *sec2; sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj);
sec2 = P_ThingOnSpecial3DFloor(mobj);
if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1) if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1)
P_LinedefExecute(sec2->tag, mobj, sec2); {
mtag_t tag = Tag_FGet(&sec2->tags);
P_LinedefExecute(tag, mobj, sec2);
}
} }
// it has to be pushable RIGHT NOW for this part to happen // it has to be pushable RIGHT NOW for this part to happen
@ -10502,6 +10471,12 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
if ((maptol & TOL_ERZ3) && !(mobj->type == MT_BLACKEGGMAN)) if ((maptol & TOL_ERZ3) && !(mobj->type == MT_BLACKEGGMAN))
mobj->destscale = FRACUNIT/2; mobj->destscale = FRACUNIT/2;
// Sprite rendering
mobj->blendmode = AST_TRANSLUCENT;
mobj->spritexscale = mobj->spriteyscale = mobj->scale;
mobj->spritexoffset = mobj->spriteyoffset = 0;
mobj->floorspriteslope = NULL;
// set subsector and/or block links // set subsector and/or block links
P_SetThingPosition(mobj); P_SetThingPosition(mobj);
I_Assert(mobj->subsector != NULL); I_Assert(mobj->subsector != NULL);
@ -10902,6 +10877,22 @@ static inline precipmobj_t *P_SpawnSnowMobj(fixed_t x, fixed_t y, fixed_t z, mob
return mo; return mo;
} }
void *P_CreateFloorSpriteSlope(mobj_t *mobj)
{
if (mobj->floorspriteslope)
Z_Free(mobj->floorspriteslope);
mobj->floorspriteslope = Z_Calloc(sizeof(pslope_t), PU_LEVEL, NULL);
mobj->floorspriteslope->normal.z = FRACUNIT;
return (void *)mobj->floorspriteslope;
}
void P_RemoveFloorSpriteSlope(mobj_t *mobj)
{
if (mobj->floorspriteslope)
Z_Free(mobj->floorspriteslope);
mobj->floorspriteslope = NULL;
}
// //
// P_RemoveMobj // P_RemoveMobj
// //
@ -10958,11 +10949,14 @@ void P_RemoveMobj(mobj_t *mobj)
P_DelSeclist(sector_list); P_DelSeclist(sector_list);
sector_list = NULL; sector_list = NULL;
} }
mobj->flags |= MF_NOSECTOR|MF_NOBLOCKMAP; mobj->flags |= MF_NOSECTOR|MF_NOBLOCKMAP;
mobj->subsector = NULL; mobj->subsector = NULL;
mobj->state = NULL; mobj->state = NULL;
mobj->player = NULL; mobj->player = NULL;
P_RemoveFloorSpriteSlope(mobj);
// stop any playing sound // stop any playing sound
S_StopSound(mobj); S_StopSound(mobj);
@ -12030,8 +12024,7 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle)
const size_t mthingi = (size_t)(mthing - mapthings); const size_t mthingi = (size_t)(mthing - mapthings);
// Find the corresponding linedef special, using angle as tag // Find the corresponding linedef special, using angle as tag
// P_FindSpecialLineFromTag works here now =D line = Tag_FindLineSpecial(9, mthing->angle);
line = P_FindSpecialLineFromTag(9, mthing->angle, -1);
if (line == -1) if (line == -1)
{ {
@ -12341,7 +12334,7 @@ static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj)
const size_t mthingi = (size_t)(mthing - mapthings); const size_t mthingi = (size_t)(mthing - mapthings);
// Find the corresponding linedef special, using angle as tag // Find the corresponding linedef special, using angle as tag
line = P_FindSpecialLineFromTag(15, mthing->angle, -1); line = Tag_FindLineSpecial(15, mthing->angle);
if (line == -1) if (line == -1)
{ {
@ -12580,17 +12573,20 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
break; break;
} }
case MT_SKYBOX: case MT_SKYBOX:
if (mthing->tag < 0 || mthing->tag > 15) {
mtag_t tag = Tag_FGet(&mthing->tags);
if (tag < 0 || tag > 15)
{ {
CONS_Debug(DBG_GAMELOGIC, "P_SetupSpawnedMapThing: Skybox ID %d of mapthing %s is not between 0 and 15!\n", mthing->tag, sizeu1((size_t)(mthing - mapthings))); CONS_Debug(DBG_GAMELOGIC, "P_SetupSpawnedMapThing: Skybox ID %d of mapthing %s is not between 0 and 15!\n", tag, sizeu1((size_t)(mthing - mapthings)));
break; break;
} }
if (mthing->options & MTF_OBJECTSPECIAL) if (mthing->options & MTF_OBJECTSPECIAL)
skyboxcenterpnts[mthing->tag] = mobj; skyboxcenterpnts[tag] = mobj;
else else
skyboxviewpnts[mthing->tag] = mobj; skyboxviewpnts[tag] = mobj;
break; break;
}
case MT_EGGSTATUE: case MT_EGGSTATUE:
if (mthing->options & MTF_EXTRA) if (mthing->options & MTF_EXTRA)
{ {
@ -13077,8 +13073,8 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y,
mobj = P_SpawnMobj(x, y, z, i); mobj = P_SpawnMobj(x, y, z, i);
mobj->spawnpoint = mthing; mobj->spawnpoint = mthing;
P_SetScale(mobj, mthing->scale); P_SetScale(mobj, FixedMul(mobj->scale, mthing->scale));
mobj->destscale = mthing->scale; mobj->destscale = FixedMul(mobj->destscale, mthing->scale);
if (!P_SetupSpawnedMapThing(mthing, mobj, &doangle)) if (!P_SetupSpawnedMapThing(mthing, mobj, &doangle))
return mobj; return mobj;

View file

@ -194,6 +194,7 @@ typedef enum
MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH
MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position) MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use) MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
MF2_SPLAT = 1<<30, // Renders as a splat
// free: to and including 1<<31 // free: to and including 1<<31
} mobjflag2_t; } mobjflag2_t;
@ -264,6 +265,7 @@ typedef enum {
// Ran the thinker this tic. // Ran the thinker this tic.
PCF_THUNK = 32, PCF_THUNK = 32,
} precipflag_t; } precipflag_t;
// Map Object definition. // Map Object definition.
typedef struct mobj_s typedef struct mobj_s
{ {
@ -285,6 +287,12 @@ typedef struct mobj_s
UINT8 sprite2; // player sprites UINT8 sprite2; // player sprites
UINT16 anim_duration; // for FF_ANIMATE states UINT16 anim_duration; // for FF_ANIMATE states
UINT32 renderflags; // render flags
INT32 blendmode; // blend mode
fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset;
struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by
struct msecnode_s *touching_sectorlist; // a linked list of sectors where this object appears struct msecnode_s *touching_sectorlist; // a linked list of sectors where this object appears
struct subsector_s *subsector; // Subsector the mobj resides in. struct subsector_s *subsector; // Subsector the mobj resides in.
@ -399,13 +407,19 @@ typedef struct precipmobj_s
struct precipmobj_s **sprev; // killough 8/11/98: change to ptr-to-ptr struct precipmobj_s **sprev; // killough 8/11/98: change to ptr-to-ptr
// More drawing info: to determine current sprite. // More drawing info: to determine current sprite.
angle_t angle, pitch, roll; // orientation angle_t angle, pitch, roll; // orientation
angle_t rollangle; angle_t rollangle;
spritenum_t sprite; // used to find patch_t and flip value spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h UINT32 frame; // frame number, plus bits see p_pspr.h
UINT8 sprite2; // player sprites UINT8 sprite2; // player sprites
UINT16 anim_duration; // for FF_ANIMATE states UINT16 anim_duration; // for FF_ANIMATE states
UINT32 renderflags; // render flags
INT32 blendmode; // blend mode
fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset;
struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by
struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears
struct subsector_s *subsector; // Subsector the mobj resides in. struct subsector_s *subsector; // Subsector the mobj resides in.
@ -462,6 +476,8 @@ void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime);
void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle); void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle);
void P_SpawnPrecipitation(void); void P_SpawnPrecipitation(void);
void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, statenum_t nstate, angle_t rotangle, boolean spawncenter); void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, statenum_t nstate, angle_t rotangle, boolean spawncenter);
void *P_CreateFloorSpriteSlope(mobj_t *mobj);
void P_RemoveFloorSpriteSlope(mobj_t *mobj);
boolean P_BossTargetPlayer(mobj_t *actor, boolean closest); boolean P_BossTargetPlayer(mobj_t *actor, boolean closest);
boolean P_SupermanLook4Players(mobj_t *actor); boolean P_SupermanLook4Players(mobj_t *actor);
void P_DestroyRobots(void); void P_DestroyRobots(void);

View file

@ -556,10 +556,11 @@ static void Polyobj_moveToSpawnSpot(mapthing_t *anchor)
polyobj_t *po; polyobj_t *po;
vertex_t dist, sspot; vertex_t dist, sspot;
size_t i; size_t i;
mtag_t tag = Tag_FGet(&anchor->tags);
if (!(po = Polyobj_GetForNum(anchor->tag))) if (!(po = Polyobj_GetForNum(tag)))
{ {
CONS_Debug(DBG_POLYOBJ, "Bad polyobject %d for anchor point\n", anchor->tag); CONS_Debug(DBG_POLYOBJ, "Bad polyobject %d for anchor point\n", tag);
return; return;
} }
@ -1342,7 +1343,7 @@ void Polyobj_InitLevel(void)
{ {
qitem = (mobjqitem_t *)M_QueueIterator(&spawnqueue); qitem = (mobjqitem_t *)M_QueueIterator(&spawnqueue);
Polyobj_spawnPolyObj(i, qitem->mo, qitem->mo->spawnpoint->tag); Polyobj_spawnPolyObj(i, qitem->mo, Tag_FGet(&qitem->mo->spawnpoint->tags));
} }
// move polyobjects to spawn points // move polyobjects to spawn points
@ -2444,10 +2445,11 @@ boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata)
polymove_t *th; polymove_t *th;
size_t i; size_t i;
INT32 start; INT32 start;
mtag_t tag = pfdata->polyObjNum;
if (!(po = Polyobj_GetForNum(pfdata->polyObjNum))) if (!(po = Polyobj_GetForNum(tag)))
{ {
CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: bad polyobj %d\n", pfdata->polyObjNum); CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: bad polyobj %d\n", tag);
return false; return false;
} }
@ -2470,7 +2472,7 @@ boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata)
po->thinker = &th->thinker; po->thinker = &th->thinker;
// set fields // set fields
th->polyObjNum = pfdata->polyObjNum; th->polyObjNum = tag;
th->distance = 0; th->distance = 0;
th->speed = pfdata->speed; th->speed = pfdata->speed;
th->angle = pfdata->angle; th->angle = pfdata->angle;

View file

@ -923,7 +923,7 @@ static void UnArchiveFFloors(const sector_t *ss)
static void ArchiveSectors(void) static void ArchiveSectors(void)
{ {
size_t i; size_t i, j;
const sector_t *ss = sectors; const sector_t *ss = sectors;
const sector_t *spawnss = spawnsectors; const sector_t *spawnss = spawnsectors;
UINT8 diff, diff2, diff3; UINT8 diff, diff2, diff3;
@ -961,10 +961,8 @@ static void ArchiveSectors(void)
if (ss->ceilingpic_angle != spawnss->ceilingpic_angle) if (ss->ceilingpic_angle != spawnss->ceilingpic_angle)
diff2 |= SD_CEILANG; diff2 |= SD_CEILANG;
if (ss->tag != spawnss->tag) if (!Tag_Compare(&ss->tags, &spawnss->tags))
diff2 |= SD_TAG; diff2 |= SD_TAG;
if (ss->nexttag != spawnss->nexttag || ss->firsttag != spawnss->firsttag)
diff3 |= SD_TAGLIST;
if (ss->extra_colormap != spawnss->extra_colormap) if (ss->extra_colormap != spawnss->extra_colormap)
diff3 |= SD_COLORMAP; diff3 |= SD_COLORMAP;
@ -1012,12 +1010,11 @@ static void ArchiveSectors(void)
WRITEANGLE(save_p, ss->floorpic_angle); WRITEANGLE(save_p, ss->floorpic_angle);
if (diff2 & SD_CEILANG) if (diff2 & SD_CEILANG)
WRITEANGLE(save_p, ss->ceilingpic_angle); WRITEANGLE(save_p, ss->ceilingpic_angle);
if (diff2 & SD_TAG) // save only the tag if (diff2 & SD_TAG)
WRITEINT16(save_p, ss->tag); {
if (diff3 & SD_TAGLIST) // save both firsttag and nexttag WRITEUINT32(save_p, ss->tags.count);
{ // either of these could be changed even if tag isn't for (j = 0; j < ss->tags.count; j++)
WRITEINT32(save_p, ss->firsttag); WRITEINT16(save_p, ss->tags.tags[j]);
WRITEINT32(save_p, ss->nexttag);
} }
if (diff3 & SD_COLORMAP) if (diff3 & SD_COLORMAP)
@ -1035,7 +1032,7 @@ static void ArchiveSectors(void)
static void UnArchiveSectors(void) static void UnArchiveSectors(void)
{ {
UINT16 i; UINT16 i, j;
UINT8 diff, diff2, diff3; UINT8 diff, diff2, diff3;
for (;;) for (;;)
{ {
@ -1089,13 +1086,29 @@ static void UnArchiveSectors(void)
if (diff2 & SD_CEILANG) if (diff2 & SD_CEILANG)
sectors[i].ceilingpic_angle = READANGLE(save_p); sectors[i].ceilingpic_angle = READANGLE(save_p);
if (diff2 & SD_TAG) if (diff2 & SD_TAG)
sectors[i].tag = READINT16(save_p); // DON'T use P_ChangeSectorTag
if (diff3 & SD_TAGLIST)
{ {
sectors[i].firsttag = READINT32(save_p); size_t ncount = READUINT32(save_p);
sectors[i].nexttag = READINT32(save_p);
// Remove entries from global lists.
for (j = 0; j < sectors[i].tags.count; j++)
Taggroup_Remove(tags_sectors, sectors[i].tags.tags[j], i);
// Reallocate if size differs.
if (ncount != sectors[i].tags.count)
{
sectors[i].tags.count = ncount;
sectors[i].tags.tags = Z_Realloc(sectors[i].tags.tags, ncount*sizeof(mtag_t), PU_LEVEL, NULL);
}
for (j = 0; j < ncount; j++)
sectors[i].tags.tags[j] = READINT16(save_p);
// Add new entries.
for (j = 0; j < sectors[i].tags.count; j++)
Taggroup_Remove(tags_sectors, sectors[i].tags.tags[j], i);
} }
if (diff3 & SD_COLORMAP) if (diff3 & SD_COLORMAP)
sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p)); sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p));
if (diff3 & SD_CRUMBLESTATE) if (diff3 & SD_CRUMBLESTATE)
@ -1404,6 +1417,13 @@ typedef enum
MD2_MIRRORED = 1<<13, MD2_MIRRORED = 1<<13,
MD2_ROLLANGLE = 1<<14, MD2_ROLLANGLE = 1<<14,
MD2_SHADOWSCALE = 1<<15, MD2_SHADOWSCALE = 1<<15,
MD2_RENDERFLAGS = 1<<16,
MD2_BLENDMODE = 1<<17,
MD2_SPRITEXSCALE = 1<<18,
MD2_SPRITEYSCALE = 1<<19,
MD2_SPRITEXOFFSET = 1<<20,
MD2_SPRITEYOFFSET = 1<<21,
MD2_FLOORSPRITESLOPE = 1<<22,
} mobj_diff2_t; } mobj_diff2_t;
typedef enum typedef enum
@ -1616,6 +1636,27 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_ROLLANGLE; diff2 |= MD2_ROLLANGLE;
if (mobj->shadowscale) if (mobj->shadowscale)
diff2 |= MD2_SHADOWSCALE; diff2 |= MD2_SHADOWSCALE;
if (mobj->renderflags)
diff2 |= MD2_RENDERFLAGS;
if (mobj->renderflags)
diff2 |= MD2_BLENDMODE;
if (mobj->spritexscale != FRACUNIT)
diff2 |= MD2_SPRITEXSCALE;
if (mobj->spriteyscale != FRACUNIT)
diff2 |= MD2_SPRITEYSCALE;
if (mobj->spritexoffset)
diff2 |= MD2_SPRITEXOFFSET;
if (mobj->floorspriteslope)
{
pslope_t *slope = mobj->floorspriteslope;
if (slope->zangle || slope->zdelta || slope->xydirection
|| slope->o.x || slope->o.y || slope->o.z
|| slope->d.x || slope->d.y
|| slope->normal.x || slope->normal.y
|| (slope->normal.z != FRACUNIT))
diff2 |= MD2_FLOORSPRITESLOPE;
}
if (diff2 != 0) if (diff2 != 0)
diff |= MD_MORE; diff |= MD_MORE;
@ -1758,6 +1799,37 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
WRITEANGLE(save_p, mobj->rollangle); WRITEANGLE(save_p, mobj->rollangle);
if (diff2 & MD2_SHADOWSCALE) if (diff2 & MD2_SHADOWSCALE)
WRITEFIXED(save_p, mobj->shadowscale); WRITEFIXED(save_p, mobj->shadowscale);
if (diff2 & MD2_RENDERFLAGS)
WRITEUINT32(save_p, mobj->renderflags);
if (diff2 & MD2_BLENDMODE)
WRITEINT32(save_p, mobj->blendmode);
if (diff2 & MD2_SPRITEXSCALE)
WRITEFIXED(save_p, mobj->spritexscale);
if (diff2 & MD2_SPRITEYSCALE)
WRITEFIXED(save_p, mobj->spriteyscale);
if (diff2 & MD2_SPRITEXOFFSET)
WRITEFIXED(save_p, mobj->spritexoffset);
if (diff2 & MD2_SPRITEYOFFSET)
WRITEFIXED(save_p, mobj->spriteyoffset);
if (diff2 & MD2_FLOORSPRITESLOPE)
{
pslope_t *slope = mobj->floorspriteslope;
WRITEFIXED(save_p, slope->zdelta);
WRITEANGLE(save_p, slope->zangle);
WRITEANGLE(save_p, slope->xydirection);
WRITEFIXED(save_p, slope->o.x);
WRITEFIXED(save_p, slope->o.y);
WRITEFIXED(save_p, slope->o.z);
WRITEFIXED(save_p, slope->d.x);
WRITEFIXED(save_p, slope->d.y);
WRITEFIXED(save_p, slope->normal.x);
WRITEFIXED(save_p, slope->normal.y);
WRITEFIXED(save_p, slope->normal.z);
}
WRITEUINT32(save_p, mobj->mobjnum); WRITEUINT32(save_p, mobj->mobjnum);
} }
@ -2767,6 +2839,37 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->rollangle = READANGLE(save_p); mobj->rollangle = READANGLE(save_p);
if (diff2 & MD2_SHADOWSCALE) if (diff2 & MD2_SHADOWSCALE)
mobj->shadowscale = READFIXED(save_p); mobj->shadowscale = READFIXED(save_p);
if (diff2 & MD2_RENDERFLAGS)
mobj->renderflags = READUINT32(save_p);
if (diff2 & MD2_BLENDMODE)
mobj->blendmode = READINT32(save_p);
if (diff2 & MD2_SPRITEXSCALE)
mobj->spritexscale = READFIXED(save_p);
if (diff2 & MD2_SPRITEYSCALE)
mobj->spriteyscale = READFIXED(save_p);
if (diff2 & MD2_SPRITEXOFFSET)
mobj->spritexoffset = READFIXED(save_p);
if (diff2 & MD2_SPRITEYOFFSET)
mobj->spriteyoffset = READFIXED(save_p);
if (diff2 & MD2_FLOORSPRITESLOPE)
{
pslope_t *slope = (pslope_t *)P_CreateFloorSpriteSlope(mobj);
slope->zdelta = READFIXED(save_p);
slope->zangle = READANGLE(save_p);
slope->xydirection = READANGLE(save_p);
slope->o.x = READFIXED(save_p);
slope->o.y = READFIXED(save_p);
slope->o.z = READFIXED(save_p);
slope->d.x = READFIXED(save_p);
slope->d.y = READFIXED(save_p);
slope->normal.x = READFIXED(save_p);
slope->normal.y = READFIXED(save_p);
slope->normal.z = READFIXED(save_p);
}
if (diff & MD_REDFLAG) if (diff & MD_REDFLAG)
{ {
@ -4003,6 +4106,12 @@ static void P_NetArchiveMisc(boolean resending)
WRITEINT32(save_p, sstimer); WRITEINT32(save_p, sstimer);
WRITEUINT32(save_p, bluescore); WRITEUINT32(save_p, bluescore);
WRITEUINT32(save_p, redscore); WRITEUINT32(save_p, redscore);
WRITEUINT16(save_p, skincolor_redteam);
WRITEUINT16(save_p, skincolor_blueteam);
WRITEUINT16(save_p, skincolor_redring);
WRITEUINT16(save_p, skincolor_bluering);
WRITEINT32(save_p, modulothing); WRITEINT32(save_p, modulothing);
WRITEINT16(save_p, autobalance); WRITEINT16(save_p, autobalance);
@ -4092,6 +4201,12 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
sstimer = READINT32(save_p); sstimer = READINT32(save_p);
bluescore = READUINT32(save_p); bluescore = READUINT32(save_p);
redscore = READUINT32(save_p); redscore = READUINT32(save_p);
skincolor_redteam = READUINT16(save_p);
skincolor_blueteam = READUINT16(save_p);
skincolor_redring = READUINT16(save_p);
skincolor_bluering = READUINT16(save_p);
modulothing = READINT32(save_p); modulothing = READINT32(save_p);
autobalance = READINT16(save_p); autobalance = READINT16(save_p);

View file

@ -29,6 +29,7 @@
#include "r_data.h" #include "r_data.h"
#include "r_things.h" // for R_AddSpriteDefs #include "r_things.h" // for R_AddSpriteDefs
#include "r_textures.h" #include "r_textures.h"
#include "r_patch.h"
#include "r_picformats.h" #include "r_picformats.h"
#include "r_sky.h" #include "r_sky.h"
#include "r_draw.h" #include "r_draw.h"
@ -82,6 +83,8 @@
#include "fastcmp.h" // textmap parsing #include "fastcmp.h" // textmap parsing
#include "taglist.h"
// //
// Map MD5, calculated on level load. // Map MD5, calculated on level load.
// Sent to clients in PT_SERVERINFO. // Sent to clients in PT_SERVERINFO.
@ -548,7 +551,7 @@ Ploadflat (levelflat_t *levelflat, const char *flatname, boolean resize)
lumpnum_t flatnum; lumpnum_t flatnum;
int texturenum; int texturenum;
patch_t *flatpatch; UINT8 *flatpatch;
size_t lumplength; size_t lumplength;
size_t i; size_t i;
@ -608,7 +611,7 @@ flatfound:
/* This could be a flat, patch, or PNG. */ /* This could be a flat, patch, or PNG. */
flatpatch = W_CacheLumpNum(flatnum, PU_CACHE); flatpatch = W_CacheLumpNum(flatnum, PU_CACHE);
lumplength = W_LumpLength(flatnum); lumplength = W_LumpLength(flatnum);
if (Picture_CheckIfPatch(flatpatch, lumplength)) if (Picture_CheckIfDoomPatch((softwarepatch_t *)flatpatch, lumplength))
levelflat->type = LEVELFLAT_PATCH; levelflat->type = LEVELFLAT_PATCH;
else else
{ {
@ -904,16 +907,13 @@ static void P_SpawnMapThings(boolean spawnemblems)
} }
// Experimental groovy write function! // Experimental groovy write function!
void P_WriteThings(lumpnum_t lumpnum) void P_WriteThings(void)
{ {
size_t i, length; size_t i, length;
mapthing_t *mt; mapthing_t *mt;
UINT8 *data;
UINT8 *savebuffer, *savebuf_p; UINT8 *savebuffer, *savebuf_p;
INT16 temp; INT16 temp;
data = W_CacheLumpNum(lumpnum, PU_LEVEL);
savebuf_p = savebuffer = (UINT8 *)malloc(nummapthings * sizeof (mapthing_t)); savebuf_p = savebuffer = (UINT8 *)malloc(nummapthings * sizeof (mapthing_t));
if (!savebuf_p) if (!savebuf_p)
@ -935,8 +935,6 @@ void P_WriteThings(lumpnum_t lumpnum)
WRITEUINT16(savebuf_p, mt->options); WRITEUINT16(savebuf_p, mt->options);
} }
Z_Free(data);
length = savebuf_p - savebuffer; length = savebuf_p - savebuffer;
FIL_WriteFile(va("newthings%d.lmp", gamemap), savebuffer, length); FIL_WriteFile(va("newthings%d.lmp", gamemap), savebuffer, length);
@ -968,8 +966,6 @@ static void P_LoadVertices(UINT8 *data)
static void P_InitializeSector(sector_t *ss) static void P_InitializeSector(sector_t *ss)
{ {
ss->nexttag = ss->firsttag = -1;
memset(&ss->soundorg, 0, sizeof(ss->soundorg)); memset(&ss->soundorg, 0, sizeof(ss->soundorg));
ss->validcount = 0; ss->validcount = 0;
@ -1040,7 +1036,7 @@ static void P_LoadSectors(UINT8 *data)
ss->lightlevel = SHORT(ms->lightlevel); ss->lightlevel = SHORT(ms->lightlevel);
ss->special = SHORT(ms->special); ss->special = SHORT(ms->special);
ss->tag = SHORT(ms->tag); Tag_FSet(&ss->tags, SHORT(ms->tag));
ss->floor_xoffs = ss->floor_yoffs = 0; ss->floor_xoffs = ss->floor_yoffs = 0;
ss->ceiling_xoffs = ss->ceiling_yoffs = 0; ss->ceiling_xoffs = ss->ceiling_yoffs = 0;
@ -1079,10 +1075,6 @@ static void P_InitializeLinedef(line_t *ld)
ld->frontsector = ld->backsector = NULL; ld->frontsector = ld->backsector = NULL;
ld->validcount = 0; ld->validcount = 0;
#ifdef WALLSPLATS
ld->splats = NULL;
#endif
ld->firsttag = ld->nexttag = -1;
ld->polyobj = NULL; ld->polyobj = NULL;
ld->text = NULL; ld->text = NULL;
@ -1154,7 +1146,7 @@ static void P_LoadLinedefs(UINT8 *data)
{ {
ld->flags = SHORT(mld->flags); ld->flags = SHORT(mld->flags);
ld->special = SHORT(mld->special); ld->special = SHORT(mld->special);
ld->tag = SHORT(mld->tag); Tag_FSet(&ld->tags, SHORT(mld->tag));
memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args)); memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args));
memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs)); memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs));
ld->alpha = FRACUNIT; ld->alpha = FRACUNIT;
@ -1347,7 +1339,7 @@ static void P_LoadSidedefs(UINT8 *data)
|| (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'F')) || (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'F'))
sd->toptexture = axtoi(msd->toptexture); sd->toptexture = axtoi(msd->toptexture);
else else
I_Error("Custom FOF (tag %d) needs a value in the linedef's back side upper texture field.", sd->line->tag); I_Error("Custom FOF (line id %s) needs a value in the linedef's back side upper texture field.", sizeu1(sd->line - lines));
sd->midtexture = R_TextureNumForName(msd->midtexture); sd->midtexture = R_TextureNumForName(msd->midtexture);
sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
@ -1387,8 +1379,8 @@ static void P_LoadThings(UINT8 *data)
mt->type = READUINT16(data); mt->type = READUINT16(data);
mt->options = READUINT16(data); mt->options = READUINT16(data);
mt->extrainfo = (UINT8)(mt->type >> 12); mt->extrainfo = (UINT8)(mt->type >> 12);
Tag_FSet(&mt->tags, 0);
mt->scale = FRACUNIT; mt->scale = FRACUNIT;
mt->tag = 0;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->pitch = mt->roll = 0; mt->pitch = mt->roll = 0;
@ -1524,7 +1516,17 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val)
else if (fastcmp(param, "special")) else if (fastcmp(param, "special"))
sectors[i].special = atol(val); sectors[i].special = atol(val);
else if (fastcmp(param, "id")) else if (fastcmp(param, "id"))
sectors[i].tag = atol(val); Tag_FSet(&sectors[i].tags, atol(val));
else if (fastcmp(param, "moreids"))
{
char* id = val;
while (id)
{
Tag_Add(&sectors[i].tags, atol(id));
if ((id = strchr(id, ' ')))
id++;
}
}
else if (fastcmp(param, "xpanningfloor")) else if (fastcmp(param, "xpanningfloor"))
sectors[i].floor_xoffs = FLOAT_TO_FIXED(atof(val)); sectors[i].floor_xoffs = FLOAT_TO_FIXED(atof(val));
else if (fastcmp(param, "ypanningfloor")) else if (fastcmp(param, "ypanningfloor"))
@ -1602,7 +1604,17 @@ static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val)
static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val) static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val)
{ {
if (fastcmp(param, "id")) if (fastcmp(param, "id"))
lines[i].tag = atol(val); Tag_FSet(&lines[i].tags, atol(val));
else if (fastcmp(param, "moreids"))
{
char* id = val;
while (id)
{
Tag_Add(&lines[i].tags, atol(id));
if ((id = strchr(id, ' ')))
id++;
}
}
else if (fastcmp(param, "special")) else if (fastcmp(param, "special"))
lines[i].special = atol(val); lines[i].special = atol(val);
else if (fastcmp(param, "v1")) else if (fastcmp(param, "v1"))
@ -1671,8 +1683,18 @@ static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val)
static void ParseTextmapThingParameter(UINT32 i, char *param, char *val) static void ParseTextmapThingParameter(UINT32 i, char *param, char *val)
{ {
if (fastcmp(param, "id")) if (fastcmp(param, "id"))
mapthings[i].tag = atol(val); Tag_FSet(&mapthings[i].tags, atol(val));
if (fastcmp(param, "x")) else if (fastcmp(param, "moreids"))
{
char* id = val;
while (id)
{
Tag_Add(&mapthings[i].tags, atol(id));
if ((id = strchr(id, ' ')))
id++;
}
}
else if (fastcmp(param, "x"))
mapthings[i].x = atol(val); mapthings[i].x = atol(val);
else if (fastcmp(param, "y")) else if (fastcmp(param, "y"))
mapthings[i].y = atol(val); mapthings[i].y = atol(val);
@ -1829,7 +1851,7 @@ static void P_LoadTextmap(void)
sc->lightlevel = 255; sc->lightlevel = 255;
sc->special = 0; sc->special = 0;
sc->tag = 0; Tag_FSet(&sc->tags, 0);
sc->floor_xoffs = sc->floor_yoffs = 0; sc->floor_xoffs = sc->floor_yoffs = 0;
sc->ceiling_xoffs = sc->ceiling_yoffs = 0; sc->ceiling_xoffs = sc->ceiling_yoffs = 0;
@ -1847,6 +1869,7 @@ static void P_LoadTextmap(void)
textmap_colormap.fadeend = 31; textmap_colormap.fadeend = 31;
textmap_colormap.flags = 0; textmap_colormap.flags = 0;
TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter); TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter);
P_InitializeSector(sc); P_InitializeSector(sc);
if (textmap_colormap.used) if (textmap_colormap.used)
{ {
@ -1863,7 +1886,8 @@ static void P_LoadTextmap(void)
ld->v1 = ld->v2 = NULL; ld->v1 = ld->v2 = NULL;
ld->flags = 0; ld->flags = 0;
ld->special = 0; ld->special = 0;
ld->tag = 0; Tag_FSet(&ld->tags, 0);
memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args)); memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args));
memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs)); memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs));
ld->alpha = FRACUNIT; ld->alpha = FRACUNIT;
@ -1911,8 +1935,8 @@ static void P_LoadTextmap(void)
mt->options = 0; mt->options = 0;
mt->z = 0; mt->z = 0;
mt->extrainfo = 0; mt->extrainfo = 0;
Tag_FSet(&mt->tags, 0);
mt->scale = FRACUNIT; mt->scale = FRACUNIT;
mt->tag = 0;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->mobj = NULL; mt->mobj = NULL;
@ -2080,9 +2104,6 @@ static boolean P_LoadMapData(const virtres_t *virt)
static void P_InitializeSubsector(subsector_t *ss) static void P_InitializeSubsector(subsector_t *ss)
{ {
ss->sector = NULL; ss->sector = NULL;
#ifdef FLOORSPLATS
ss->splats = NULL;
#endif
ss->validcount = 0; ss->validcount = 0;
} }
@ -2127,7 +2148,7 @@ static void P_LoadNodes(UINT8 *data)
* \param seg Seg to compute length for. * \param seg Seg to compute length for.
* \return Length in fracunits. * \return Length in fracunits.
*/ */
fixed_t P_SegLength(seg_t *seg) static fixed_t P_SegLength(seg_t *seg)
{ {
INT64 dx = (seg->v2->x - seg->v1->x)>>1; INT64 dx = (seg->v2->x - seg->v1->x)>>1;
INT64 dy = (seg->v2->y - seg->v1->y)>>1; INT64 dy = (seg->v2->y - seg->v1->y)>>1;
@ -2929,30 +2950,6 @@ static void P_LinkMapData(void)
} }
} }
/** Hashes the sector tags across the sectors and linedefs.
*
* \sa P_FindSectorFromTag, P_ChangeSectorTag
* \author Lee Killough
*/
static inline void P_InitTagLists(void)
{
register size_t i;
for (i = numsectors - 1; i != (size_t)-1; i--)
{
size_t j = (unsigned)sectors[i].tag % numsectors;
sectors[i].nexttag = sectors[j].firsttag;
sectors[j].firsttag = (INT32)i;
}
for (i = numlines - 1; i != (size_t)-1; i--)
{
size_t j = (unsigned)lines[i].tag % numlines;
lines[i].nexttag = lines[j].firsttag;
lines[j].firsttag = (INT32)i;
}
}
//For maps in binary format, converts setup of specials to UDMF format. //For maps in binary format, converts setup of specials to UDMF format.
static void P_ConvertBinaryMap(void) static void P_ConvertBinaryMap(void)
{ {
@ -2960,14 +2957,28 @@ static void P_ConvertBinaryMap(void)
for (i = 0; i < numlines; i++) for (i = 0; i < numlines; i++)
{ {
mtag_t tag = Tag_FGet(&lines[i].tags);
switch (lines[i].special) switch (lines[i].special)
{ {
case 20: //PolyObject first line case 20: //PolyObject first line
{ {
INT32 paramline = P_FindSpecialLineFromTag(22, lines[i].tag, -1); INT32 check = -1;
INT32 paramline = -1;
TAG_ITER_DECLARECOUNTER(0);
TAG_ITER_LINES(0, tag, check)
{
if (lines[check].special == 22)
{
paramline = check;
break;
}
}
//PolyObject ID //PolyObject ID
lines[i].args[0] = lines[i].tag; lines[i].args[0] = tag;
//Default: Invisible planes //Default: Invisible planes
lines[i].args[3] |= TMPF_INVISIBLEPLANES; lines[i].args[3] |= TMPF_INVISIBLEPLANES;
@ -3013,7 +3024,7 @@ static void P_ConvertBinaryMap(void)
CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in the front texture fields)\n", sizeu1(i)); CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in the front texture fields)\n", sizeu1(i));
break; break;
case 447: //Change colormap case 447: //Change colormap
lines[i].args[0] = lines[i].tag; lines[i].args[0] = Tag_FGet(&lines[i].tags);
if (lines[i].flags & ML_EFFECT3) if (lines[i].flags & ML_EFFECT3)
lines[i].args[2] |= TMCF_RELATIVE; lines[i].args[2] |= TMCF_RELATIVE;
if (lines[i].flags & ML_EFFECT1) if (lines[i].flags & ML_EFFECT1)
@ -3029,7 +3040,7 @@ static void P_ConvertBinaryMap(void)
abs(sides[lines[i].sidenum[1]].rowoffset >> FRACBITS) abs(sides[lines[i].sidenum[1]].rowoffset >> FRACBITS)
: abs(sides[lines[i].sidenum[0]].rowoffset >> FRACBITS)); : abs(sides[lines[i].sidenum[0]].rowoffset >> FRACBITS));
lines[i].args[0] = lines[i].tag; lines[i].args[0] = Tag_FGet(&lines[i].tags);
if (lines[i].flags & ML_EFFECT4) if (lines[i].flags & ML_EFFECT4)
lines[i].args[2] = speed; lines[i].args[2] = speed;
else else
@ -3049,10 +3060,10 @@ static void P_ConvertBinaryMap(void)
break; break;
} }
case 456: //Stop fading colormap case 456: //Stop fading colormap
lines[i].args[0] = lines[i].tag; lines[i].args[0] = Tag_FGet(&lines[i].tags);
break; break;
case 606: //Colormap case 606: //Colormap
lines[i].args[0] = lines[i].tag; lines[i].args[0] = Tag_FGet(&lines[i].tags);
break; break;
case 700: //Slope front sector floor case 700: //Slope front sector floor
case 701: //Slope front sector ceiling case 701: //Slope front sector ceiling
@ -3093,7 +3104,7 @@ static void P_ConvertBinaryMap(void)
else if (lines[i].special == 715) else if (lines[i].special == 715)
lines[i].args[0] = TMSP_BACKCEILING; lines[i].args[0] = TMSP_BACKCEILING;
lines[i].args[1] = lines[i].tag; lines[i].args[1] = tag;
if (lines[i].flags & ML_EFFECT6) if (lines[i].flags & ML_EFFECT6)
{ {
@ -3125,9 +3136,9 @@ static void P_ConvertBinaryMap(void)
case 721: //Copy front side ceiling slope case 721: //Copy front side ceiling slope
case 722: //Copy front side floor and ceiling slope case 722: //Copy front side floor and ceiling slope
if (lines[i].special != 721) if (lines[i].special != 721)
lines[i].args[0] = lines[i].tag; lines[i].args[0] = tag;
if (lines[i].special != 720) if (lines[i].special != 720)
lines[i].args[1] = lines[i].tag; lines[i].args[1] = tag;
lines[i].special = 720; lines[i].special = 720;
break; break;
case 900: //Translucent wall (10%) case 900: //Translucent wall (10%)
@ -3160,21 +3171,39 @@ static void P_ConvertBinaryMap(void)
switch (mapthings[i].type) switch (mapthings[i].type)
{ {
case 750: case 750:
Tag_Add(&mapthings[i].tags, mapthings[i].angle);
break;
case 760: case 760:
case 761: case 761:
mapthings[i].tag = mapthings[i].angle; Tag_FSet(&mapthings[i].tags, mapthings[i].angle);
break; break;
case 762: case 762:
{ {
INT32 firstline = P_FindSpecialLineFromTag(20, mapthings[i].angle, -1); INT32 check = -1;
INT32 firstline = -1;
mtag_t tag = mapthings[i].angle;
TAG_ITER_DECLARECOUNTER(0);
Tag_FSet(&mapthings[i].tags, tag);
TAG_ITER_LINES(0, tag, check)
{
if (lines[check].special == 20)
{
firstline = check;
break;
}
}
if (firstline != -1) if (firstline != -1)
lines[firstline].args[3] |= TMPF_CRUSH; lines[firstline].args[3] |= TMPF_CRUSH;
mapthings[i].tag = mapthings[i].angle;
mapthings[i].type = 761; mapthings[i].type = 761;
break; break;
} }
case 780: case 780:
mapthings[i].tag = mapthings[i].extrainfo; Tag_FSet(&mapthings[i].tags, mapthings[i].extrainfo);
break; break;
default: default:
break; break;
@ -3248,6 +3277,7 @@ static boolean P_LoadMapFromFile(void)
{ {
virtres_t *virt = vres_GetMap(lastloadedmaplumpnum); virtres_t *virt = vres_GetMap(lastloadedmaplumpnum);
virtlump_t *textmap = vres_Find(virt, "TEXTMAP"); virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
size_t i;
udmf = textmap != NULL; udmf = textmap != NULL;
if (!P_LoadMapData(virt)) if (!P_LoadMapData(virt))
@ -3257,7 +3287,7 @@ static boolean P_LoadMapFromFile(void)
P_LinkMapData(); P_LinkMapData();
P_InitTagLists(); // Create xref tables for tags Taglist_InitGlobalTables();
if (!udmf) if (!udmf)
P_ConvertBinaryMap(); P_ConvertBinaryMap();
@ -3271,6 +3301,10 @@ static boolean P_LoadMapFromFile(void)
memcpy(spawnlines, lines, numlines * sizeof(*lines)); memcpy(spawnlines, lines, numlines * sizeof(*lines));
memcpy(spawnsides, sides, numsides * sizeof(*sides)); memcpy(spawnsides, sides, numsides * sizeof(*sides));
for (i = 0; i < numsectors; i++)
if (sectors[i].tags.count)
spawnsectors[i].tags.tags = memcpy(Z_Malloc(sectors[i].tags.count*sizeof(mtag_t), PU_LEVEL, NULL), sectors[i].tags.tags, sectors[i].tags.count*sizeof(mtag_t));
P_MakeMapMD5(virt, &mapmd5); P_MakeMapMD5(virt, &mapmd5);
vres_Free(virt); vres_Free(virt);
@ -4099,13 +4133,16 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
// Clear pointers that would be left dangling by the purge // Clear pointers that would be left dangling by the purge
R_FlushTranslationColormapCache(); R_FlushTranslationColormapCache();
Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); #ifdef HWRENDER
// Free GPU textures before freeing patches.
#if defined (WALLSPLATS) || defined (FLOORSPLATS) if (vid.glstate == VID_GL_LIBRARY_LOADED)
// clear the splats from previous level HWR_ClearAllTextures();
R_ClearLevelSplats();
#endif #endif
Patch_FreeTag(PU_PATCH_LOWPRIORITY);
Patch_FreeTag(PU_PATCH_ROTATED);
Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1);
P_InitThinkers(); P_InitThinkers();
P_InitCachedActions(); P_InitCachedActions();
@ -4162,14 +4199,14 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
P_SpawnPrecipitation(); P_SpawnPrecipitation();
#ifdef HWRENDER // not win32 only 19990829 by Kin #ifdef HWRENDER // not win32 only 19990829 by Kin
gl_maploaded = false;
// Lactozilla: Free extrasubsectors regardless of renderer. // Lactozilla: Free extrasubsectors regardless of renderer.
// Maybe we're not in OpenGL anymore. HWR_FreeExtraSubsectors();
if (extrasubsectors)
free(extrasubsectors); // Create plane polygons.
extrasubsectors = NULL;
// stuff like HWR_CreatePlanePolygons is called there
if (rendermode == render_opengl) if (rendermode == render_opengl)
HWR_SetupLevel(); HWR_LoadLevel();
#endif #endif
// oh god I hope this helps // oh god I hope this helps
@ -4256,33 +4293,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
return true; return true;
} }
#ifdef HWRENDER
void HWR_SetupLevel(void)
{
// Lactozilla (December 8, 2019)
// Level setup used to free EVERY mipmap from memory.
// Even mipmaps that aren't related to level textures.
// Presumably, the hardware render code used to store textures as level data.
// Meaning, they had memory allocated and marked with the PU_LEVEL tag.
// Level textures are only reloaded after R_LoadTextures, which is
// when the texture list is loaded.
// Sal: Unfortunately, NOT freeing them causes the dreaded Color Bug.
HWR_FreeMipmapCache();
#ifdef ALAM_LIGHTING
// BP: reset light between levels (we draw preview frame lights on current frame)
HWR_ResetLights();
#endif
HWR_CreatePlanePolygons((INT32)numnodes - 1);
// Build the sky dome
HWR_ClearSkyDome();
HWR_BuildSkyDome();
}
#endif
// //
// P_RunSOC // P_RunSOC
// //
@ -4488,10 +4498,17 @@ boolean P_AddWadFile(const char *wadfilename)
if (!devparm && digmreplaces) if (!devparm && digmreplaces)
CONS_Printf(M_GetText("%s digital musics replaced\n"), sizeu1(digmreplaces)); CONS_Printf(M_GetText("%s digital musics replaced\n"), sizeu1(digmreplaces));
#ifdef HWRENDER
// Free GPU textures before freeing patches.
if (vid.glstate == VID_GL_LIBRARY_LOADED)
HWR_ClearAllTextures();
#endif
// //
// search for sprite replacements // search for sprite replacements
// //
Patch_FreeTag(PU_SPRITE);
Patch_FreeTag(PU_PATCH_ROTATED);
R_AddSpriteDefs(wadnum); R_AddSpriteDefs(wadnum);
// Reload it all anyway, just in case they // Reload it all anyway, just in case they

View file

@ -99,13 +99,13 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum);
void P_RespawnThings(void); void P_RespawnThings(void);
boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate); boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate);
#ifdef HWRENDER #ifdef HWRENDER
void HWR_SetupLevel(void); void HWR_LoadLevel(void);
#endif #endif
boolean P_AddWadFile(const char *wadfilename); boolean P_AddWadFile(const char *wadfilename);
boolean P_RunSOC(const char *socfilename); boolean P_RunSOC(const char *socfilename);
void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num); void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num);
void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num); void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num);
void P_WriteThings(lumpnum_t lump); void P_WriteThings(void);
size_t P_PrecacheLevelFlats(void); size_t P_PrecacheLevelFlats(void);
void P_AllocMapHeader(INT16 i); void P_AllocMapHeader(INT16 i);

View file

@ -139,7 +139,7 @@ void T_DynamicSlopeVert (dynplanethink_t* th)
INT32 l; INT32 l;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
l = P_FindSpecialLineFromTag(799, th->tags[i], -1); l = Tag_FindLineSpecial(799, th->tags[i]);
if (l != -1) { if (l != -1) {
th->vex[i].z = lines[l].frontsector->floorheight; th->vex[i].z = lines[l].frontsector->floorheight;
} }
@ -405,9 +405,6 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker)
P_AddDynSlopeThinker(cslope, DP_BACKCEIL, line, extent, NULL, NULL); P_AddDynSlopeThinker(cslope, DP_BACKCEIL, line, extent, NULL, NULL);
} }
} }
if(!line->tag)
return;
} }
/// Creates a new slope from three mapthings with the specified IDs /// Creates a new slope from three mapthings with the specified IDs
@ -426,11 +423,11 @@ static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag
if (mt->type != 750) // Haha, I'm hijacking the old Chaos Spawn thingtype for something! if (mt->type != 750) // Haha, I'm hijacking the old Chaos Spawn thingtype for something!
continue; continue;
if (!vertices[0] && mt->tag == tag1) if (!vertices[0] && Tag_Find(&mt->tags, tag1))
vertices[0] = mt; vertices[0] = mt;
else if (!vertices[1] && mt->tag == tag2) else if (!vertices[1] && Tag_Find(&mt->tags, tag2))
vertices[1] = mt; vertices[1] = mt;
else if (!vertices[2] && mt->tag == tag3) else if (!vertices[2] && Tag_Find(&mt->tags, tag3))
vertices[2] = mt; vertices[2] = mt;
} }
@ -549,11 +546,11 @@ static boolean P_SetSlopeFromTag(sector_t *sec, INT32 tag, boolean ceiling)
{ {
INT32 i; INT32 i;
pslope_t **secslope = ceiling ? &sec->c_slope : &sec->f_slope; pslope_t **secslope = ceiling ? &sec->c_slope : &sec->f_slope;
TAG_ITER_DECLARECOUNTER(0);
if (!tag || *secslope) if (!tag || *secslope)
return false; return false;
TAG_ITER_SECTORS(0, tag, i)
for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0;)
{ {
pslope_t *srcslope = ceiling ? sectors[i].c_slope : sectors[i].f_slope; pslope_t *srcslope = ceiling ? sectors[i].c_slope : sectors[i].f_slope;
if (srcslope) if (srcslope)

File diff suppressed because it is too large Load diff

View file

@ -55,9 +55,6 @@ fixed_t P_FindNextLowestFloor(sector_t *sec, fixed_t currentheight);
fixed_t P_FindLowestCeilingSurrounding(sector_t *sec); fixed_t P_FindLowestCeilingSurrounding(sector_t *sec);
fixed_t P_FindHighestCeilingSurrounding(sector_t *sec); fixed_t P_FindHighestCeilingSurrounding(sector_t *sec);
INT32 P_FindSectorFromTag(INT16 tag, INT32 start);
INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start);
INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max); INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max);
void P_SetupSignExit(player_t *player); void P_SetupSignExit(player_t *player);
@ -67,7 +64,6 @@ void P_SwitchWeather(INT32 weathernum);
boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller); boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller);
void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller); void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller);
void P_ChangeSectorTag(UINT32 sector, INT16 newtag);
void P_RunNightserizeExecutors(mobj_t *actor); void P_RunNightserizeExecutors(mobj_t *actor);
void P_RunDeNightserizeExecutors(mobj_t *actor); void P_RunDeNightserizeExecutors(mobj_t *actor);
void P_RunNightsLapExecutors(mobj_t *actor); void P_RunNightsLapExecutors(mobj_t *actor);

View file

@ -643,7 +643,15 @@ void P_Ticker(boolean run)
if (demorecording) if (demorecording)
G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0); G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0);
if (demoplayback) if (demoplayback)
G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0); {
player_t* p = &players[consoleplayer];
G_ReadDemoTiccmd(&p->cmd, 0);
if (!cv_freedemocamera.value)
{
P_ForceLocalAngle(p, p->cmd.angleturn << 16);
localaiming = p->aiming;
}
}
ps_lua_mobjhooks = 0; ps_lua_mobjhooks = 0;
ps_checkposition_calls = 0; ps_checkposition_calls = 0;

View file

@ -4836,6 +4836,8 @@ void P_DoJumpShield(player_t *player)
} }
#undef limitangle #undef limitangle
#undef numangles #undef numangles
player->pflags &= ~PF_NOJUMPDAMAGE;
P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_s3k45); S_StartSound(player->mo, sfx_s3k45);
} }
else else
@ -5108,6 +5110,8 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock
player->pflags |= PF_THOKKED|PF_SHIELDABILITY; player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale)); P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale));
player->drawangle = player->mo->angle; player->drawangle = player->mo->angle;
player->pflags &= ~PF_NOJUMPDAMAGE;
P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_s3k43); S_StartSound(player->mo, sfx_s3k43);
default: default:
break; break;
@ -8692,12 +8696,6 @@ void P_MovePlayer(player_t *player)
player->fovadd = 0; player->fovadd = 0;
#endif #endif
#ifdef FLOORSPLATS
if (cv_shadow.value && rendermode == render_soft)
R_AddFloorSplat(player->mo->subsector, player->mo, "SHADOW", player->mo->x,
player->mo->y, player->mo->floorz, SPLATDRAWMODE_OPAQUE);
#endif
// Look for blocks to bust up // Look for blocks to bust up
// Because of FF_SHATTER, we should look for blocks constantly, // Because of FF_SHATTER, we should look for blocks constantly,
// not just when spinning or playing as Knuckles // not just when spinning or playing as Knuckles
@ -10579,6 +10577,7 @@ static void P_CalcPostImg(player_t *player)
postimg_t *type; postimg_t *type;
INT32 *param; INT32 *param;
fixed_t pviewheight; fixed_t pviewheight;
size_t i;
if (player->mo->eflags & MFE_VERTICALFLIP) if (player->mo->eflags & MFE_VERTICALFLIP)
pviewheight = player->mo->z + player->mo->height - player->viewheight; pviewheight = player->mo->z + player->mo->height - player->viewheight;
@ -10603,28 +10602,45 @@ static void P_CalcPostImg(player_t *player)
} }
// see if we are in heat (no, not THAT kind of heat...) // see if we are in heat (no, not THAT kind of heat...)
for (i = 0; i < sector->tags.count; i++)
if (P_FindSpecialLineFromTag(13, sector->tag, -1) != -1)
*type = postimg_heat;
else if (sector->ffloors)
{ {
ffloor_t *rover; if (Tag_FindLineSpecial(13, sector->tags.tags[i]) != -1)
fixed_t topheight;
fixed_t bottomheight;
for (rover = sector->ffloors; rover; rover = rover->next)
{ {
if (!(rover->flags & FF_EXISTS)) *type = postimg_heat;
continue; break;
}
else if (sector->ffloors)
{
ffloor_t *rover;
fixed_t topheight;
fixed_t bottomheight;
boolean gotres = false;
topheight = P_GetFFloorTopZAt (rover, player->mo->x, player->mo->y); for (rover = sector->ffloors; rover; rover = rover->next)
bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y); {
size_t j;
if (pviewheight >= topheight || pviewheight <= bottomheight) if (!(rover->flags & FF_EXISTS))
continue; continue;
if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1) topheight = P_GetFFloorTopZAt (rover, player->mo->x, player->mo->y);
*type = postimg_heat; bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y);
if (pviewheight >= topheight || pviewheight <= bottomheight)
continue;
for (j = 0; j < rover->master->frontsector->tags.count; j++)
{
if (Tag_FindLineSpecial(13, rover->master->frontsector->tags.tags[j]) != -1)
{
*type = postimg_heat;
gotres = true;
break;
}
}
}
if (gotres)
break;
} }
} }
@ -10723,22 +10739,21 @@ static sector_t *P_GetMinecartSector(fixed_t x, fixed_t y, fixed_t z, fixed_t *n
static INT32 P_GetMinecartSpecialLine(sector_t *sec) static INT32 P_GetMinecartSpecialLine(sector_t *sec)
{ {
INT32 line = -1; INT32 line = -1;
size_t i;
if (!sec) if (!sec)
return line; return line;
if (sec->tag != 0) for (i = 0; i < sec->tags.count; i++)
line = P_FindSpecialLineFromTag(16, sec->tag, -1); if (sec->tags.tags[i] != 0)
line = Tag_FindLineSpecial(16, sec->tags.tags[i]);
// Also try for lines facing the sector itself, with tag 0. // Also try for lines facing the sector itself, with tag 0.
for (i = 0; i < sec->linecount; i++)
{ {
UINT32 i; line_t *li = sec->lines[i];
for (i = 0; i < sec->linecount; i++) if (Tag_Find(&li->tags, 0) && li->special == 16 && li->frontsector == sec)
{ line = li - lines;
line_t *li = sec->lines[i];
if (li->tag == 0 && li->special == 16 && li->frontsector == sec)
line = li - lines;
}
} }
return line; return line;
@ -12297,12 +12312,14 @@ void P_PlayerThink(player_t *player)
sector_t *controlsec; sector_t *controlsec;
for (j=0; j<numsectors; j++) for (j=0; j<numsectors; j++)
{ {
mtag_t sectag = Tag_FGet(&sectors[j].tags);
controlsec = NULL; controlsec = NULL;
// Does this sector have a water linedef? // Does this sector have a water linedef?
for (i=0; i<numlines;i++) for (i=0; i<numlines;i++)
{ {
mtag_t linetag = Tag_FGet(&lines[i].tags);
if ((lines[i].special == 121 || lines[i].special == 123) if ((lines[i].special == 121 || lines[i].special == 123)
&& lines[i].tag == sectors[j].tag) && linetag == sectag)
{ {
controlsec = lines[i].frontsector; controlsec = lines[i].frontsector;
break; break;
@ -12311,15 +12328,16 @@ void P_PlayerThink(player_t *player)
if (i < numlines && controlsec) if (i < numlines && controlsec)
{ {
controlsectag = Tag_FGet(&controlsec->tags);
// Does this sector have a colormap? // Does this sector have a colormap?
for (i=0; i<numlines;i++) for (i=0; i<numlines;i++)
{ {
if (lines[i].special == 606 && lines[i].tag == controlsec->tag) if (lines[i].special == 606 && linetag == controlsectag)
break; break;
} }
if (i == numlines) if (i == numlines)
CONS_Debug(DBG_GAMELOGIC, "%d, %d\n", j, sectors[j].tag); CONS_Debug(DBG_GAMELOGIC, "%d, %d\n", j, sectag);
} }
} }

View file

@ -21,6 +21,7 @@
#include "p_local.h" // camera #include "p_local.h" // camera
#include "p_slopes.h" #include "p_slopes.h"
#include "z_zone.h" // Check R_Prep3DFloors #include "z_zone.h" // Check R_Prep3DFloors
#include "taglist.h"
seg_t *curline; seg_t *curline;
side_t *sidedef; side_t *sidedef;
@ -374,7 +375,7 @@ boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back)
// Consider colormaps // Consider colormaps
&& back->extra_colormap == front->extra_colormap && back->extra_colormap == front->extra_colormap
&& ((!front->ffloors && !back->ffloors) && ((!front->ffloors && !back->ffloors)
|| front->tag == back->tag)); || Tag_Compare(&front->tags, &back->tags)));
} }
// //
@ -448,21 +449,25 @@ static void R_AddLine(seg_t *line)
// Portal line // Portal line
if (line->linedef->special == 40 && line->side == 0) if (line->linedef->special == 40 && line->side == 0)
{ {
// Render portal if recursiveness limit hasn't been reached.
// Otherwise, render the wall normally.
if (portalrender < cv_maxportals.value) if (portalrender < cv_maxportals.value)
{ {
// Find the other side! size_t p;
INT32 line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, -1); mtag_t tag = Tag_FGet(&line->linedef->tags);
if (line->linedef == &lines[line2]) INT32 li1 = line->linedef-lines;
line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, line2); INT32 li2;
if (line2 >= 0) // found it!
for (p = 0; (li2 = Tag_Iterate_Lines(tag, p)) >= 0; p++)
{ {
Portal_Add2Lines(line->linedef-lines, line2, x1, x2); // Remember the lines for later rendering // Skip invalid lines.
//return; // Don't fill in that space now! if ((tag != Tag_FGet(&lines[li2].tags)) || (lines[li1].special != lines[li2].special) || (li1 == li2))
continue;
Portal_Add2Lines(li1, li2, x1, x2);
goto clipsolid; goto clipsolid;
} }
} }
// Recursed TOO FAR (viewing a portal within a portal)
// So uhhh, render it as a normal wall instead or something ???
} }
// Single sided line? // Single sided line?
@ -483,7 +488,7 @@ static void R_AddLine(seg_t *line)
if (!line->polyseg && if (!line->polyseg &&
!line->sidedef->midtexture !line->sidedef->midtexture
&& ((!frontsector->ffloors && !backsector->ffloors) && ((!frontsector->ffloors && !backsector->ffloors)
|| (frontsector->tag == backsector->tag))) || Tag_Compare(&frontsector->tags, &backsector->tags)))
return; // line is empty, don't even bother return; // line is empty, don't even bother
goto clippass; // treat like wide open window instead goto clippass; // treat like wide open window instead
@ -1048,11 +1053,6 @@ static void R_Subsector(size_t num)
} }
} }
#ifdef FLOORSPLATS
if (sub->splats)
R_AddVisibleFloorSplats(sub);
#endif
// killough 9/18/98: Fix underwater slowdown, by passing real sector // killough 9/18/98: Fix underwater slowdown, by passing real sector
// instead of fake one. Improve sprite lighting by basing sprite // instead of fake one. Improve sprite lighting by basing sprite
// lightlevels on floor & ceiling lightlevels in the surrounding area. // lightlevels on floor & ceiling lightlevels in the surrounding area.

View file

@ -20,6 +20,7 @@
#include "m_misc.h" #include "m_misc.h"
#include "r_data.h" #include "r_data.h"
#include "r_textures.h" #include "r_textures.h"
#include "r_patch.h"
#include "r_picformats.h" #include "r_picformats.h"
#include "w_wad.h" #include "w_wad.h"
#include "z_zone.h" #include "z_zone.h"
@ -174,13 +175,15 @@ UINT8 ASTBlendPaletteIndexes(UINT8 background, UINT8 foreground, int style, UINT
if (alpha <= ASTTextureBlendingThreshold[1]) if (alpha <= ASTTextureBlendingThreshold[1])
{ {
UINT8 *mytransmap; UINT8 *mytransmap;
INT32 trans;
// Is the patch way too translucent? Don't blend then. // Is the patch way too translucent? Don't blend then.
if (alpha < ASTTextureBlendingThreshold[0]) if (alpha < ASTTextureBlendingThreshold[0])
return background; return background;
// The equation's not exact but it works as intended. I'll call it a day for now. // The equation's not exact but it works as intended. I'll call it a day for now.
mytransmap = transtables + ((8*(alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); trans = (8*(alpha) + 255/8)/(255 - 255/11);
mytransmap = R_GetTranslucencyTable(trans + 1);
if (background != 0xFF) if (background != 0xFF)
return *(mytransmap + (background<<8) + foreground); return *(mytransmap + (background<<8) + foreground);
} }
@ -1307,7 +1310,7 @@ void R_PrecacheLevel(void)
lump = sf->lumppat[a];\ lump = sf->lumppat[a];\
if (devparm)\ if (devparm)\
spritememory += W_LumpLength(lump);\ spritememory += W_LumpLength(lump);\
W_CachePatchNum(lump, PU_PATCH);\ W_CachePatchNum(lump, PU_SPRITE);\
} }
// see R_InitSprites for more about lumppat,lumpid // see R_InitSprites for more about lumppat,lumpid
switch (sf->rotate) switch (sf->rotate)

View file

@ -28,6 +28,8 @@
#include "m_aatree.h" #include "m_aatree.h"
#endif #endif
#include "taglist.h"
// //
// ClipWallSegment // ClipWallSegment
// Clips the given range of columns // Clips the given range of columns
@ -281,8 +283,7 @@ typedef struct sector_s
INT32 ceilingpic; INT32 ceilingpic;
INT16 lightlevel; INT16 lightlevel;
INT16 special; INT16 special;
UINT16 tag; taglist_t tags;
INT32 nexttag, firsttag; // for fast tag searches
// origin for any sounds played by the sector // origin for any sounds played by the sector
// also considered the center for e.g. Mario blocks // also considered the center for e.g. Mario blocks
@ -389,7 +390,7 @@ typedef struct line_s
// Animation related. // Animation related.
INT16 flags; INT16 flags;
INT16 special; INT16 special;
INT16 tag; taglist_t tags;
INT32 args[NUMLINEARGS]; INT32 args[NUMLINEARGS];
char *stringargs[NUMLINESTRINGARGS]; char *stringargs[NUMLINESTRINGARGS];
@ -409,10 +410,6 @@ typedef struct line_s
sector_t *backsector; sector_t *backsector;
size_t validcount; // if == validcount, already checked size_t validcount; // if == validcount, already checked
#if 1//#ifdef WALLSPLATS
void *splats; // wallsplat_t list
#endif
INT32 firsttag, nexttag; // improves searches for tags.
polyobj_t *polyobj; // Belongs to a polyobject? polyobj_t *polyobj; // Belongs to a polyobject?
char *text; // a concatenation of all front and back texture names, for linedef specials that require a string. char *text; // a concatenation of all front and back texture names, for linedef specials that require a string.
@ -457,9 +454,6 @@ typedef struct subsector_s
INT16 numlines; INT16 numlines;
UINT16 firstline; UINT16 firstline;
struct polyobj_s *polyList; // haleyjd 02/19/06: list of polyobjects struct polyobj_s *polyList; // haleyjd 02/19/06: list of polyobjects
#if 1//#ifdef FLOORSPLATS
void *splats; // floorsplat_t list
#endif
size_t validcount; size_t validcount;
} subsector_t; } subsector_t;
@ -652,8 +646,12 @@ typedef enum
RGBA32 = 4, // 32 bit rgba RGBA32 = 4, // 32 bit rgba
} pic_mode_t; } pic_mode_t;
#if defined(_MSC_VER) #ifdef ROTSPRITE
#pragma pack(1) typedef struct
{
INT32 angles;
void **patches;
} rotsprite_t;
#endif #endif
// Patches. // Patches.
@ -661,7 +659,26 @@ typedef enum
// Patches are used for sprites and all masked pictures, and we compose // Patches are used for sprites and all masked pictures, and we compose
// textures from the TEXTURES list of patches. // textures from the TEXTURES list of patches.
// //
// WARNING: this structure is cloned in GLPatch_t typedef struct
{
INT16 width, height;
INT16 leftoffset, topoffset;
INT32 *columnofs; // Column offsets. This is relative to patch->columns
UINT8 *columns; // Software column data
void *hardware; // OpenGL patch, allocated whenever necessary
void *flats[4]; // The patch as flats
#ifdef ROTSPRITE
rotsprite_t *rotated; // Rotated patches
#endif
} patch_t;
#if defined(_MSC_VER)
#pragma pack(1)
#endif
typedef struct typedef struct
{ {
INT16 width; // bounding box size INT16 width; // bounding box size
@ -670,7 +687,7 @@ typedef struct
INT16 topoffset; // pixels below the origin INT16 topoffset; // pixels below the origin
INT32 columnofs[8]; // only [width] used INT32 columnofs[8]; // only [width] used
// the [0] is &columnofs[width] // the [0] is &columnofs[width]
} ATTRPACK patch_t; } ATTRPACK softwarepatch_t;
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable : 4200) #pragma warning(disable : 4200)
@ -696,14 +713,32 @@ typedef struct
#pragma pack() #pragma pack()
#endif #endif
// rotsprite typedef enum
#ifdef ROTSPRITE
typedef struct
{ {
patch_t *patch[16][ROTANGLES]; RF_HORIZONTALFLIP = 0x0001, // Flip sprite horizontally
UINT16 cached; RF_VERTICALFLIP = 0x0002, // Flip sprite vertically
} rotsprite_t; RF_ABSOLUTEOFFSETS = 0x0004, // Sprite uses the object's offsets absolutely, instead of relatively
#endif/*ROTSPRITE*/ RF_FLIPOFFSETS = 0x0008, // Relative object offsets are flipped with the sprite
RF_SPLATMASK = 0x00F0, // --Floor sprite flags
RF_SLOPESPLAT = 0x0010, // Rotate floor sprites by a slope
RF_OBJECTSLOPESPLAT = 0x0020, // Rotate floor sprites by the object's standing slope
RF_NOSPLATBILLBOARD = 0x0040, // Don't billboard floor sprites (faces forward from the view angle)
RF_NOSPLATROLLANGLE = 0x0080, // Don't rotate floor sprites by the object's rollangle (uses rotated patches instead)
RF_BLENDMASK = 0x0F00, // --Blending modes
RF_FULLBRIGHT = 0x0100, // Sprite is drawn at full brightness
RF_FULLDARK = 0x0200, // Sprite is drawn completely dark
RF_NOCOLORMAPS = 0x0400, // Sprite is not drawn with colormaps
RF_SPRITETYPEMASK = 0x7000, // ---Different sprite types
RF_PAPERSPRITE = 0x1000, // Paper sprite
RF_FLOORSPRITE = 0x2000, // Floor sprite
RF_SHADOWDRAW = 0x10000, // Stretches and skews the sprite like a shadow.
RF_SHADOWEFFECTS = 0x20000, // Scales and becomes transparent like a shadow.
RF_DROPSHADOW = (RF_SHADOWDRAW | RF_SHADOWEFFECTS | RF_FULLDARK),
} renderflags_t;
typedef enum typedef enum
{ {
@ -717,24 +752,6 @@ typedef enum
SRF_NONE = 0xff // Initial value SRF_NONE = 0xff // Initial value
} spriterotateflags_t; // SRF's up! } spriterotateflags_t; // SRF's up!
// Same as a patch_t, except just the header
// and the wadnum/lumpnum combination that points
// to wherever the patch is in memory.
struct patchinfo_s
{
INT16 width; // bounding box size
INT16 height;
INT16 leftoffset; // pixels to the left of origin
INT16 topoffset; // pixels below the origin
UINT16 wadnum; // the software patch lump num for when the patch
UINT16 lumpnum; // was flushed, and we need to re-create it
// next patchinfo_t in memory
struct patchinfo_s *next;
};
typedef struct patchinfo_s patchinfo_t;
// //
// Sprites are patches with a special naming convention so they can be // Sprites are patches with a special naming convention so they can be
// recognized by R_InitSprites. // recognized by R_InitSprites.
@ -764,7 +781,7 @@ typedef struct
UINT16 flip; UINT16 flip;
#ifdef ROTSPRITE #ifdef ROTSPRITE
rotsprite_t rotsprite; rotsprite_t *rotated[2][16]; // Rotated patches
#endif #endif
} spriteframe_t; } spriteframe_t;

View file

@ -75,6 +75,7 @@ UINT8 *dc_source;
#define NUMTRANSTABLES 9 // how many translucency tables are used #define NUMTRANSTABLES 9 // how many translucency tables are used
UINT8 *transtables; // translucency tables UINT8 *transtables; // translucency tables
UINT8 *blendtables[NUMBLENDMAPS];
/** \brief R_DrawTransColumn uses this /** \brief R_DrawTransColumn uses this
*/ */
@ -98,15 +99,19 @@ INT32 dc_numlights = 0, dc_maxlights, dc_texheight;
INT32 ds_y, ds_x1, ds_x2; INT32 ds_y, ds_x1, ds_x2;
lighttable_t *ds_colormap; lighttable_t *ds_colormap;
lighttable_t *ds_translation; // Lactozilla: Sprite splat drawer
fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
INT32 ds_waterofs, ds_bgofs;
UINT16 ds_flatwidth, ds_flatheight; UINT16 ds_flatwidth, ds_flatheight;
boolean ds_powersoftwo; boolean ds_powersoftwo;
UINT8 *ds_source; // start of a 64*64 tile image UINT8 *ds_source; // points to the start of a flat
UINT8 *ds_transmap; // one of the translucency tables UINT8 *ds_transmap; // one of the translucency tables
pslope_t *ds_slope; // Current slope being used // Vectors for Software's tilted slope drawers
floatv3_t ds_su[MAXVIDHEIGHT], ds_sv[MAXVIDHEIGHT], ds_sz[MAXVIDHEIGHT]; // Vectors for... stuff? floatv3_t *ds_su, *ds_sv, *ds_sz;
floatv3_t *ds_sup, *ds_svp, *ds_szp; floatv3_t *ds_sup, *ds_svp, *ds_szp;
float focallengthf, zeroheight; float focallengthf, zeroheight;
@ -115,10 +120,6 @@ float focallengthf, zeroheight;
UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask; UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
// ==========================================================================
// OLD DOOM FUZZY EFFECT
// ==========================================================================
// ========================================================================= // =========================================================================
// TRANSLATION COLORMAP CODE // TRANSLATION COLORMAP CODE
// ========================================================================= // =========================================================================
@ -138,11 +139,11 @@ UINT8 skincolor_modified[MAXSKINCOLORS];
CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1];
/** \brief The R_InitTranslationTables #define TRANSTAB_AMTMUL10 (256.0f / 10.0f)
load in color translation tables /** \brief Initializes the translucency tables used by the Software renderer.
*/ */
void R_InitTranslationTables(void) void R_InitTranslucencyTables(void)
{ {
// Load here the transparency lookup tables 'TINTTAB' // Load here the transparency lookup tables 'TINTTAB'
// NOTE: the TINTTAB resource MUST BE aligned on 64k for the asm // NOTE: the TINTTAB resource MUST BE aligned on 64k for the asm
@ -159,17 +160,94 @@ void R_InitTranslationTables(void)
W_ReadLump(W_GetNumForName("TRANS70"), transtables+0x60000); W_ReadLump(W_GetNumForName("TRANS70"), transtables+0x60000);
W_ReadLump(W_GetNumForName("TRANS80"), transtables+0x70000); W_ReadLump(W_GetNumForName("TRANS80"), transtables+0x70000);
W_ReadLump(W_GetNumForName("TRANS90"), transtables+0x80000); W_ReadLump(W_GetNumForName("TRANS90"), transtables+0x80000);
R_GenerateBlendTables();
} }
void R_GenerateBlendTables(void)
{
INT32 i;
/** \brief Generates a translation colormap. for (i = 0; i < NUMBLENDMAPS; i++)
{
if (i == blendtab_modulate)
continue;
blendtables[i] = Z_MallocAlign((NUMTRANSTABLES + 1) * 0x10000, PU_STATIC, NULL, 16);
}
\param dest_colormap colormap to populate for (i = 0; i <= 9; i++)
\param skinnum number of skin, TC_DEFAULT or TC_BOSS {
\param color translation color const size_t offs = (0x10000 * i);
const UINT8 alpha = TRANSTAB_AMTMUL10 * i;
\return void R_GenerateTranslucencyTable(blendtables[blendtab_add] + offs, AST_ADD, alpha);
*/ R_GenerateTranslucencyTable(blendtables[blendtab_subtract] + offs, AST_SUBTRACT, alpha);
R_GenerateTranslucencyTable(blendtables[blendtab_reversesubtract] + offs, AST_REVERSESUBTRACT, alpha);
}
// Modulation blending only requires a single table
blendtables[blendtab_modulate] = Z_MallocAlign(0x10000, PU_STATIC, NULL, 16);
R_GenerateTranslucencyTable(blendtables[blendtab_modulate], AST_MODULATE, 0);
}
static colorlookup_t transtab_lut;
void R_GenerateTranslucencyTable(UINT8 *table, int style, UINT8 blendamt)
{
INT16 bg, fg;
if (table == NULL)
I_Error("R_GenerateTranslucencyTable: input table was NULL!");
InitColorLUT(&transtab_lut, pMasterPalette, false);
for (bg = 0; bg < 0xFF; bg++)
{
for (fg = 0; fg < 0xFF; fg++)
{
RGBA_t backrgba = V_GetMasterColor(bg);
RGBA_t frontrgba = V_GetMasterColor(fg);
RGBA_t result;
result.rgba = ASTBlendPixel(backrgba, frontrgba, style, blendamt);
table[((bg * 0x100) + fg)] = GetColorLUT(&transtab_lut, result.s.red, result.s.green, result.s.blue);
}
}
}
#define ClipTransLevel(trans) max(min((trans), NUMTRANSMAPS-2), 0)
UINT8 *R_GetTranslucencyTable(INT32 alphalevel)
{
return transtables + (ClipTransLevel(alphalevel-1) << FF_TRANSSHIFT);
}
UINT8 *R_GetBlendTable(int style, INT32 alphalevel)
{
size_t offs = (ClipTransLevel(alphalevel) << FF_TRANSSHIFT);
// Lactozilla: Returns the equivalent to AST_TRANSLUCENT
// if no alpha style matches any of the blend tables.
switch (style)
{
case AST_ADD:
return blendtables[blendtab_add] + offs;
case AST_SUBTRACT:
return blendtables[blendtab_subtract] + offs;
case AST_REVERSESUBTRACT:
return blendtables[blendtab_reversesubtract] + offs;
case AST_MODULATE:
return blendtables[blendtab_modulate];
default:
break;
}
// Return a normal translucency table
if (--alphalevel >= 0)
return transtables + (ClipTransLevel(alphalevel) << FF_TRANSSHIFT);
else
return NULL;
}
// Define for getting accurate color brightness readings according to how the human eye sees them. // Define for getting accurate color brightness readings according to how the human eye sees them.
// https://en.wikipedia.org/wiki/Relative_luminance // https://en.wikipedia.org/wiki/Relative_luminance
@ -227,6 +305,14 @@ static void R_RainbowColormap(UINT8 *dest_colormap, UINT16 skincolor)
#undef SETBRIGHTNESS #undef SETBRIGHTNESS
/** \brief Generates a translation colormap.
\param dest_colormap colormap to populate
\param skinnum number of skin, TC_DEFAULT or TC_BOSS
\param color translation color
\return void
*/
static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, UINT16 color) static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, UINT16 color)
{ {
INT32 i, starttranscolor, skinramplength; INT32 i, starttranscolor, skinramplength;

View file

@ -37,7 +37,6 @@ extern UINT8 dc_hires;
extern UINT8 *dc_source; // first pixel in a column extern UINT8 *dc_source; // first pixel in a column
// translucency stuff here // translucency stuff here
extern UINT8 *transtables; // translucency tables, should be (*transtables)[5][256][256]
extern UINT8 *dc_transmap; extern UINT8 *dc_transmap;
// translation stuff here // translation stuff here
@ -56,9 +55,14 @@ extern INT32 dc_texheight;
extern INT32 ds_y, ds_x1, ds_x2; extern INT32 ds_y, ds_x1, ds_x2;
extern lighttable_t *ds_colormap; extern lighttable_t *ds_colormap;
extern lighttable_t *ds_translation;
extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
extern INT32 ds_waterofs, ds_bgofs;
extern UINT16 ds_flatwidth, ds_flatheight; extern UINT16 ds_flatwidth, ds_flatheight;
extern boolean ds_powersoftwo; extern boolean ds_powersoftwo;
extern UINT8 *ds_source; extern UINT8 *ds_source;
extern UINT8 *ds_transmap; extern UINT8 *ds_transmap;
@ -66,8 +70,8 @@ typedef struct {
float x, y, z; float x, y, z;
} floatv3_t; } floatv3_t;
extern pslope_t *ds_slope; // Current slope being used // Vectors for Software's tilted slope drawers
extern floatv3_t ds_su[MAXVIDHEIGHT], ds_sv[MAXVIDHEIGHT], ds_sz[MAXVIDHEIGHT]; // Vectors for... stuff? extern floatv3_t *ds_su, *ds_sv, *ds_sz;
extern floatv3_t *ds_sup, *ds_svp, *ds_szp; extern floatv3_t *ds_sup, *ds_svp, *ds_szp;
extern float focallengthf, zeroheight; extern float focallengthf, zeroheight;
@ -110,17 +114,36 @@ extern lumpnum_t viewborderlump[8];
#define TC_BLINK -6 // For item blinking, according to kart #define TC_BLINK -6 // For item blinking, according to kart
#define TC_DASHMODE -7 // For Metal Sonic's dashmode #define TC_DASHMODE -7 // For Metal Sonic's dashmode
// Custom player skin translation
// Initialize color translation tables, for player rendering etc. // Initialize color translation tables, for player rendering etc.
void R_InitTranslationTables(void);
UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags); UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags);
void R_FlushTranslationColormapCache(void); void R_FlushTranslationColormapCache(void);
UINT16 R_GetColorByName(const char *name); UINT16 R_GetColorByName(const char *name);
UINT16 R_GetSuperColorByName(const char *name); UINT16 R_GetSuperColorByName(const char *name);
extern UINT8 *transtables; // translucency tables, should be (*transtables)[5][256][256]
enum
{
blendtab_add,
blendtab_subtract,
blendtab_reversesubtract,
blendtab_modulate,
NUMBLENDMAPS
};
extern UINT8 *blendtables[NUMBLENDMAPS];
void R_InitTranslucencyTables(void);
void R_GenerateBlendTables(void);
void R_GenerateTranslucencyTable(UINT8 *table, int style, UINT8 blendamt);
UINT8 *R_GetTranslucencyTable(INT32 alphalevel);
UINT8 *R_GetBlendTable(int style, INT32 alphalevel);
// Color ramp modification should force a recache // Color ramp modification should force a recache
extern UINT8 skincolor_modified[]; extern UINT8 skincolor_modified[];
// Custom player skin translation
void R_InitViewBuffer(INT32 width, INT32 height); void R_InitViewBuffer(INT32 width, INT32 height);
void R_InitViewBorder(void); void R_InitViewBorder(void);
void R_VideoErase(size_t ofs, INT32 count); void R_VideoErase(size_t ofs, INT32 count);
@ -149,39 +172,47 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void);
void R_DrawFogColumn_8(void); void R_DrawFogColumn_8(void);
void R_DrawColumnShadowed_8(void); void R_DrawColumnShadowed_8(void);
#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan))
void R_DrawSpan_8(void); void R_DrawSpan_8(void);
void R_DrawSplat_8(void);
void R_DrawTranslucentSpan_8(void); void R_DrawTranslucentSpan_8(void);
void R_DrawTranslucentSplat_8(void);
void R_DrawTiltedSpan_8(void); void R_DrawTiltedSpan_8(void);
void R_DrawTiltedTranslucentSpan_8(void); void R_DrawTiltedTranslucentSpan_8(void);
#ifndef NOWATER
void R_DrawTiltedTranslucentWaterSpan_8(void); void R_DrawSplat_8(void);
#endif void R_DrawTranslucentSplat_8(void);
void R_DrawTiltedSplat_8(void); void R_DrawTiltedSplat_8(void);
void R_DrawFloorSprite_8(void);
void R_DrawTranslucentFloorSprite_8(void);
void R_DrawTiltedFloorSprite_8(void);
void R_DrawTiltedTranslucentFloorSprite_8(void);
void R_CalcTiltedLighting(fixed_t start, fixed_t end); void R_CalcTiltedLighting(fixed_t start, fixed_t end);
extern INT32 tiltlighting[MAXVIDWIDTH]; extern INT32 tiltlighting[MAXVIDWIDTH];
#ifndef NOWATER
void R_DrawTranslucentWaterSpan_8(void); void R_DrawTranslucentWaterSpan_8(void);
extern INT32 ds_bgofs; void R_DrawTiltedTranslucentWaterSpan_8(void);
extern INT32 ds_waterofs;
#endif
void R_DrawFogSpan_8(void); void R_DrawFogSpan_8(void);
// Lactozilla: Non-powers-of-two // Lactozilla: Non-powers-of-two
void R_DrawSpan_NPO2_8(void); void R_DrawSpan_NPO2_8(void);
void R_DrawTranslucentSpan_NPO2_8(void); void R_DrawTranslucentSpan_NPO2_8(void);
void R_DrawSplat_NPO2_8(void);
void R_DrawTranslucentSplat_NPO2_8(void);
void R_DrawTiltedSpan_NPO2_8(void); void R_DrawTiltedSpan_NPO2_8(void);
void R_DrawTiltedTranslucentSpan_NPO2_8(void); void R_DrawTiltedTranslucentSpan_NPO2_8(void);
#ifndef NOWATER
void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void); void R_DrawSplat_NPO2_8(void);
#endif void R_DrawTranslucentSplat_NPO2_8(void);
void R_DrawTiltedSplat_NPO2_8(void); void R_DrawTiltedSplat_NPO2_8(void);
#ifndef NOWATER
void R_DrawFloorSprite_NPO2_8(void);
void R_DrawTranslucentFloorSprite_NPO2_8(void);
void R_DrawTiltedFloorSprite_NPO2_8(void);
void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void);
void R_DrawTranslucentWaterSpan_NPO2_8(void); void R_DrawTranslucentWaterSpan_NPO2_8(void);
#endif void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void);
#ifdef USEASM #ifdef USEASM
void ASMCALL R_DrawColumn_8_ASM(void); void ASMCALL R_DrawColumn_8_ASM(void);

View file

@ -536,6 +536,9 @@ void R_DrawTranslatedColumn_8(void)
// SPANS // SPANS
// ========================================================================== // ==========================================================================
#define SPANSIZE 16
#define INVSPAN 0.0625f
/** \brief The R_DrawSpan_8 function /** \brief The R_DrawSpan_8 function
Draws the actual span. Draws the actual span.
*/ */
@ -643,8 +646,6 @@ void R_CalcTiltedLighting(fixed_t start, fixed_t end)
} }
} }
#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan))
/** \brief The R_DrawTiltedSpan_8 function /** \brief The R_DrawTiltedSpan_8 function
Draw slopes! Holy sheit! Draw slopes! Holy sheit!
*/ */
@ -704,9 +705,6 @@ void R_DrawTiltedSpan_8(void)
vz += ds_svp->x; vz += ds_svp->x;
} while (--width >= 0); } while (--width >= 0);
#else #else
#define SPANSIZE 16
#define INVSPAN 0.0625f
startz = 1.f/iz; startz = 1.f/iz;
startu = uz*startz; startu = uz*startz;
startv = vz*startz; startv = vz*startz;
@ -839,9 +837,6 @@ void R_DrawTiltedTranslucentSpan_8(void)
vz += ds_svp->x; vz += ds_svp->x;
} while (--width >= 0); } while (--width >= 0);
#else #else
#define SPANSIZE 16
#define INVSPAN 0.0625f
startz = 1.f/iz; startz = 1.f/iz;
startu = uz*startz; startu = uz*startz;
startv = vz*startz; startv = vz*startz;
@ -916,7 +911,6 @@ void R_DrawTiltedTranslucentSpan_8(void)
#endif #endif
} }
#ifndef NOWATER
/** \brief The R_DrawTiltedTranslucentWaterSpan_8 function /** \brief The R_DrawTiltedTranslucentWaterSpan_8 function
Like DrawTiltedTranslucentSpan, but for water Like DrawTiltedTranslucentSpan, but for water
*/ */
@ -977,9 +971,6 @@ void R_DrawTiltedTranslucentWaterSpan_8(void)
vz += ds_svp->x; vz += ds_svp->x;
} while (--width >= 0); } while (--width >= 0);
#else #else
#define SPANSIZE 16
#define INVSPAN 0.0625f
startz = 1.f/iz; startz = 1.f/iz;
startu = uz*startz; startu = uz*startz;
startv = vz*startz; startv = vz*startz;
@ -1053,7 +1044,6 @@ void R_DrawTiltedTranslucentWaterSpan_8(void)
} }
#endif #endif
} }
#endif // NOWATER
void R_DrawTiltedSplat_8(void) void R_DrawTiltedSplat_8(void)
{ {
@ -1116,9 +1106,6 @@ void R_DrawTiltedSplat_8(void)
vz += ds_svp->x; vz += ds_svp->x;
} while (--width >= 0); } while (--width >= 0);
#else #else
#define SPANSIZE 16
#define INVSPAN 0.0625f
startz = 1.f/iz; startz = 1.f/iz;
startu = uz*startz; startu = uz*startz;
startv = vz*startz; startv = vz*startz;
@ -1419,6 +1406,448 @@ void R_DrawTranslucentSplat_8 (void)
} }
} }
/** \brief The R_DrawFloorSprite_8 function
Just like R_DrawSplat_8, but for floor sprites.
*/
void R_DrawFloorSprite_8 (void)
{
fixed_t xposition;
fixed_t yposition;
fixed_t xstep, ystep;
UINT16 *source;
UINT8 *colormap;
UINT8 *translation;
UINT8 *dest;
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
size_t count = (ds_x2 - ds_x1 + 1);
UINT32 val;
xposition = ds_xfrac; yposition = ds_yfrac;
xstep = ds_xstep; ystep = ds_ystep;
// SoM: we only need 6 bits for the integer part (0 thru 63) so the rest
// can be used for the fraction part. This allows calculation of the memory address in the
// texture with two shifts, an OR and one AND. (see below)
// for texture sizes > 64 the amount of precision we can allow will decrease, but only by one
// bit per power of two (obviously)
// Ok, because I was able to eliminate the variable spot below, this function is now FASTER
// than the original span renderer. Whodathunkit?
xposition <<= nflatshiftup; yposition <<= nflatshiftup;
xstep <<= nflatshiftup; ystep <<= nflatshiftup;
source = (UINT16 *)ds_source;
colormap = ds_colormap;
translation = ds_translation;
dest = ylookup[ds_y] + columnofs[ds_x1];
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!
//
// <Callum> 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size)
val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
val &= 4194303;
val = source[val];
if (val & 0xFF00)
dest[0] = colormap[translation[val & 0xFF]];
xposition += xstep;
yposition += ystep;
val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
val &= 4194303;
val = source[val];
if (val & 0xFF00)
dest[1] = colormap[translation[val & 0xFF]];
xposition += xstep;
yposition += ystep;
val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
val &= 4194303;
val = source[val];
if (val & 0xFF00)
dest[2] = colormap[translation[val & 0xFF]];
xposition += xstep;
yposition += ystep;
val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
val &= 4194303;
val = source[val];
if (val & 0xFF00)
dest[3] = colormap[translation[val & 0xFF]];
xposition += xstep;
yposition += ystep;
val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
val &= 4194303;
val = source[val];
if (val & 0xFF00)
dest[4] = colormap[translation[val & 0xFF]];
xposition += xstep;
yposition += ystep;
val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
val &= 4194303;
val = source[val];
if (val & 0xFF00)
dest[5] = colormap[translation[val & 0xFF]];
xposition += xstep;
yposition += ystep;
val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
val &= 4194303;
val = source[val];
if (val & 0xFF00)
dest[6] = colormap[translation[val & 0xFF]];
xposition += xstep;
yposition += ystep;
val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
val &= 4194303;
val = source[val];
if (val & 0xFF00)
dest[7] = colormap[translation[val & 0xFF]];
xposition += xstep;
yposition += ystep;
dest += 8;
count -= 8;
}
while (count-- && dest <= deststop)
{
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
*dest = colormap[translation[val & 0xFF]];
dest++;
xposition += xstep;
yposition += ystep;
}
}
/** \brief The R_DrawTranslucentFloorSplat_8 function
Just like R_DrawFloorSprite_8, but is translucent!
*/
void R_DrawTranslucentFloorSprite_8 (void)
{
fixed_t xposition;
fixed_t yposition;
fixed_t xstep, ystep;
UINT16 *source;
UINT8 *colormap;
UINT8 *translation;
UINT8 *dest;
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
size_t count = (ds_x2 - ds_x1 + 1);
UINT32 val;
xposition = ds_xfrac; yposition = ds_yfrac;
xstep = ds_xstep; ystep = ds_ystep;
// SoM: we only need 6 bits for the integer part (0 thru 63) so the rest
// can be used for the fraction part. This allows calculation of the memory address in the
// texture with two shifts, an OR and one AND. (see below)
// for texture sizes > 64 the amount of precision we can allow will decrease, but only by one
// bit per power of two (obviously)
// Ok, because I was able to eliminate the variable spot below, this function is now FASTER
// than the original span renderer. Whodathunkit?
xposition <<= nflatshiftup; yposition <<= nflatshiftup;
xstep <<= nflatshiftup; ystep <<= nflatshiftup;
source = (UINT16 *)ds_source;
colormap = ds_colormap;
translation = ds_translation;
dest = ylookup[ds_y] + columnofs[ds_x1];
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!
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
dest[0] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[0]);
xposition += xstep;
yposition += ystep;
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
dest[1] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[1]);
xposition += xstep;
yposition += ystep;
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
dest[2] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[2]);
xposition += xstep;
yposition += ystep;
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
dest[3] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[3]);
xposition += xstep;
yposition += ystep;
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
dest[4] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[4]);
xposition += xstep;
yposition += ystep;
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
dest[5] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[5]);
xposition += xstep;
yposition += ystep;
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
dest[6] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[6]);
xposition += xstep;
yposition += ystep;
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
dest[7] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[7]);
xposition += xstep;
yposition += ystep;
dest += 8;
count -= 8;
}
while (count-- && dest <= deststop)
{
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
dest++;
xposition += xstep;
yposition += ystep;
}
}
/** \brief The R_DrawTiltedFloorSprite_8 function
Draws a tilted floor sprite.
*/
void R_DrawTiltedFloorSprite_8(void)
{
// x1, x2 = ds_x1, ds_x2
int width = ds_x2 - ds_x1;
double iz, uz, vz;
UINT32 u, v;
int i;
UINT16 *source;
UINT8 *colormap;
UINT8 *translation;
UINT8 *dest;
UINT16 val;
double startz, startu, startv;
double izstep, uzstep, vzstep;
double endz, endu, endv;
UINT32 stepu, stepv;
iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx);
uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx);
vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx);
dest = ylookup[ds_y] + columnofs[ds_x1];
source = (UINT16 *)ds_source;
colormap = ds_colormap;
translation = ds_translation;
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) + viewx;
v = (INT64)(startv) + viewy;
for (i = SPANSIZE-1; i >= 0; i--)
{
val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
if (val & 0xFF00)
*dest = colormap[translation[val & 0xFF]];
dest++;
u += stepu;
v += stepv;
}
startu = endu;
startv = endv;
width -= SPANSIZE;
}
if (width > 0)
{
if (width == 1)
{
u = (INT64)(startu);
v = (INT64)(startv);
val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
if (val & 0xFF00)
*dest = colormap[translation[val & 0xFF]];
}
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) + viewx;
v = (INT64)(startv) + viewy;
for (; width != 0; width--)
{
val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
if (val & 0xFF00)
*dest = colormap[translation[val & 0xFF]];
dest++;
u += stepu;
v += stepv;
}
}
}
}
/** \brief The R_DrawTiltedTranslucentFloorSprite_8 function
Draws a tilted, translucent, floor sprite.
*/
void R_DrawTiltedTranslucentFloorSprite_8(void)
{
// x1, x2 = ds_x1, ds_x2
int width = ds_x2 - ds_x1;
double iz, uz, vz;
UINT32 u, v;
int i;
UINT16 *source;
UINT8 *colormap;
UINT8 *translation;
UINT8 *dest;
UINT16 val;
double startz, startu, startv;
double izstep, uzstep, vzstep;
double endz, endu, endv;
UINT32 stepu, stepv;
iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx);
uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx);
vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx);
dest = ylookup[ds_y] + columnofs[ds_x1];
source = (UINT16 *)ds_source;
colormap = ds_colormap;
translation = ds_translation;
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) + viewx;
v = (INT64)(startv) + viewy;
for (i = SPANSIZE-1; i >= 0; i--)
{
val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
if (val & 0xFF00)
*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
dest++;
u += stepu;
v += stepv;
}
startu = endu;
startv = endv;
width -= SPANSIZE;
}
if (width > 0)
{
if (width == 1)
{
u = (INT64)(startu);
v = (INT64)(startv);
val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
if (val & 0xFF00)
*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
}
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) + viewx;
v = (INT64)(startv) + viewy;
for (; width != 0; width--)
{
val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
if (val & 0xFF00)
*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
dest++;
u += stepu;
v += stepv;
}
}
}
}
/** \brief The R_DrawTranslucentSpan_8 function /** \brief The R_DrawTranslucentSpan_8 function
Draws the actual span with translucency. Draws the actual span with translucency.
*/ */
@ -1503,7 +1932,6 @@ void R_DrawTranslucentSpan_8 (void)
} }
} }
#ifndef NOWATER
void R_DrawTranslucentWaterSpan_8(void) void R_DrawTranslucentWaterSpan_8(void)
{ {
UINT32 xposition; UINT32 xposition;
@ -1580,7 +2008,6 @@ void R_DrawTranslucentWaterSpan_8(void)
yposition += ystep; yposition += ystep;
} }
} }
#endif
/** \brief The R_DrawFogSpan_8 function /** \brief The R_DrawFogSpan_8 function
Draws the actual span with fogging. Draws the actual span with fogging.

View file

@ -15,6 +15,9 @@
// SPANS // SPANS
// ========================================================================== // ==========================================================================
#define SPANSIZE 16
#define INVSPAN 0.0625f
/** \brief The R_DrawSpan_NPO2_8 function /** \brief The R_DrawSpan_NPO2_8 function
Draws the actual span. Draws the actual span.
*/ */
@ -83,8 +86,6 @@ void R_DrawSpan_NPO2_8 (void)
} }
} }
#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan))
/** \brief The R_DrawTiltedSpan_NPO2_8 function /** \brief The R_DrawTiltedSpan_NPO2_8 function
Draw slopes! Holy sheit! Draw slopes! Holy sheit!
*/ */
@ -159,9 +160,6 @@ void R_DrawTiltedSpan_NPO2_8(void)
vz += ds_svp->x; vz += ds_svp->x;
} while (--width >= 0); } while (--width >= 0);
#else #else
#define SPANSIZE 16
#define INVSPAN 0.0625f
startz = 1.f/iz; startz = 1.f/iz;
startu = uz*startz; startu = uz*startz;
startv = vz*startz; startv = vz*startz;
@ -354,9 +352,6 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void)
vz += ds_svp->x; vz += ds_svp->x;
} while (--width >= 0); } while (--width >= 0);
#else #else
#define SPANSIZE 16
#define INVSPAN 0.0625f
startz = 1.f/iz; startz = 1.f/iz;
startu = uz*startz; startu = uz*startz;
startv = vz*startz; startv = vz*startz;
@ -553,9 +548,6 @@ void R_DrawTiltedSplat_NPO2_8(void)
vz += ds_svp->x; vz += ds_svp->x;
} while (--width >= 0); } while (--width >= 0);
#else #else
#define SPANSIZE 16
#define INVSPAN 0.0625f
startz = 1.f/iz; startz = 1.f/iz;
startu = uz*startz; startu = uz*startz;
startv = vz*startz; startv = vz*startz;
@ -818,6 +810,446 @@ void R_DrawTranslucentSplat_NPO2_8 (void)
} }
} }
/** \brief The R_DrawFloorSprite_NPO2_8 function
Just like R_DrawSplat_NPO2_8, but for floor sprites.
*/
void R_DrawFloorSprite_NPO2_8 (void)
{
fixed_t xposition;
fixed_t yposition;
fixed_t xstep, ystep;
fixed_t x, y;
fixed_t fixedwidth, fixedheight;
UINT16 *source;
UINT8 *translation;
UINT8 *colormap;
UINT8 *dest;
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
size_t count = (ds_x2 - ds_x1 + 1);
UINT32 val;
xposition = ds_xfrac; yposition = ds_yfrac;
xstep = ds_xstep; ystep = ds_ystep;
source = (UINT16 *)ds_source;
colormap = ds_colormap;
translation = ds_translation;
dest = ylookup[ds_y] + columnofs[ds_x1];
fixedwidth = ds_flatwidth << FRACBITS;
fixedheight = ds_flatheight << FRACBITS;
// Fix xposition and yposition if they are out of bounds.
if (xposition < 0)
xposition = fixedwidth - ((UINT32)(fixedwidth - xposition) % fixedwidth);
else if (xposition >= fixedwidth)
xposition %= fixedwidth;
if (yposition < 0)
yposition = fixedheight - ((UINT32)(fixedheight - yposition) % fixedheight);
else if (yposition >= fixedheight)
yposition %= fixedheight;
while (count-- && dest <= deststop)
{
// The loops here keep the texture coordinates within the texture.
// They will rarely iterate multiple times, and are cheaper than a modulo operation,
// even if using libdivide.
if (xstep < 0) // These if statements are hopefully hoisted by the compiler to above this loop
while (xposition < 0)
xposition += fixedwidth;
else
while (xposition >= fixedwidth)
xposition -= fixedwidth;
if (ystep < 0)
while (yposition < 0)
yposition += fixedheight;
else
while (yposition >= fixedheight)
yposition -= fixedheight;
x = (xposition >> FRACBITS);
y = (yposition >> FRACBITS);
val = source[((y * ds_flatwidth) + x)];
if (val & 0xFF00)
*dest = colormap[translation[val & 0xFF]];
dest++;
xposition += xstep;
yposition += ystep;
}
}
/** \brief The R_DrawTranslucentFloorSprite_NPO2_8 function
Just like R_DrawFloorSprite_NPO2_8, but is translucent!
*/
void R_DrawTranslucentFloorSprite_NPO2_8 (void)
{
fixed_t xposition;
fixed_t yposition;
fixed_t xstep, ystep;
fixed_t x, y;
fixed_t fixedwidth, fixedheight;
UINT16 *source;
UINT8 *translation;
UINT8 *colormap;
UINT8 *dest;
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
size_t count = (ds_x2 - ds_x1 + 1);
UINT32 val;
xposition = ds_xfrac; yposition = ds_yfrac;
xstep = ds_xstep; ystep = ds_ystep;
source = (UINT16 *)ds_source;
colormap = ds_colormap;
translation = ds_translation;
dest = ylookup[ds_y] + columnofs[ds_x1];
fixedwidth = ds_flatwidth << FRACBITS;
fixedheight = ds_flatheight << FRACBITS;
// Fix xposition and yposition if they are out of bounds.
if (xposition < 0)
xposition = fixedwidth - ((UINT32)(fixedwidth - xposition) % fixedwidth);
else if (xposition >= fixedwidth)
xposition %= fixedwidth;
if (yposition < 0)
yposition = fixedheight - ((UINT32)(fixedheight - yposition) % fixedheight);
else if (yposition >= fixedheight)
yposition %= fixedheight;
while (count-- && dest <= deststop)
{
// The loops here keep the texture coordinates within the texture.
// They will rarely iterate multiple times, and are cheaper than a modulo operation,
// even if using libdivide.
if (xstep < 0) // These if statements are hopefully hoisted by the compiler to above this loop
while (xposition < 0)
xposition += fixedwidth;
else
while (xposition >= fixedwidth)
xposition -= fixedwidth;
if (ystep < 0)
while (yposition < 0)
yposition += fixedheight;
else
while (yposition >= fixedheight)
yposition -= fixedheight;
x = (xposition >> FRACBITS);
y = (yposition >> FRACBITS);
val = source[((y * ds_flatwidth) + x)];
if (val & 0xFF00)
*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
dest++;
xposition += xstep;
yposition += ystep;
}
}
/** \brief The R_DrawTiltedFloorSprite_NPO2_8 function
Draws a tilted floor sprite.
*/
void R_DrawTiltedFloorSprite_NPO2_8(void)
{
// x1, x2 = ds_x1, ds_x2
int width = ds_x2 - ds_x1;
double iz, uz, vz;
UINT32 u, v;
int i;
UINT16 *source;
UINT8 *colormap;
UINT8 *translation;
UINT8 *dest;
UINT16 val;
double startz, startu, startv;
double izstep, uzstep, vzstep;
double endz, endu, endv;
UINT32 stepu, stepv;
iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx);
uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx);
vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx);
dest = ylookup[ds_y] + columnofs[ds_x1];
source = (UINT16 *)ds_source;
colormap = ds_colormap;
translation = ds_translation;
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) + viewx;
v = (INT64)(startv) + viewy;
for (i = SPANSIZE-1; i >= 0; i--)
{
// Lactozilla: Non-powers-of-two
fixed_t x = (((fixed_t)u-viewx) >> FRACBITS);
fixed_t y = (((fixed_t)v-viewy) >> FRACBITS);
// Carefully align all of my Friends.
if (x < 0)
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
if (y < 0)
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
x %= ds_flatwidth;
y %= ds_flatheight;
val = source[((y * ds_flatwidth) + x)];
if (val & 0xFF00)
*dest = colormap[translation[val & 0xFF]];
dest++;
u += stepu;
v += stepv;
}
startu = endu;
startv = endv;
width -= SPANSIZE;
}
if (width > 0)
{
if (width == 1)
{
u = (INT64)(startu);
v = (INT64)(startv);
// Lactozilla: Non-powers-of-two
{
fixed_t x = (((fixed_t)u-viewx) >> FRACBITS);
fixed_t y = (((fixed_t)v-viewy) >> FRACBITS);
// Carefully align all of my Friends.
if (x < 0)
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
if (y < 0)
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
x %= ds_flatwidth;
y %= ds_flatheight;
val = source[((y * ds_flatwidth) + x)];
if (val & 0xFF00)
*dest = colormap[translation[val & 0xFF]];
}
}
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) + viewx;
v = (INT64)(startv) + viewy;
for (; width != 0; width--)
{
// Lactozilla: Non-powers-of-two
fixed_t x = (((fixed_t)u-viewx) >> FRACBITS);
fixed_t y = (((fixed_t)v-viewy) >> FRACBITS);
// Carefully align all of my Friends.
if (x < 0)
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
if (y < 0)
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
x %= ds_flatwidth;
y %= ds_flatheight;
val = source[((y * ds_flatwidth) + x)];
if (val & 0xFF00)
*dest = colormap[translation[val & 0xFF]];
dest++;
u += stepu;
v += stepv;
}
}
}
}
/** \brief The R_DrawTiltedTranslucentFloorSprite_NPO2_8 function
Draws a tilted, translucent, floor sprite.
*/
void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void)
{
// x1, x2 = ds_x1, ds_x2
int width = ds_x2 - ds_x1;
double iz, uz, vz;
UINT32 u, v;
int i;
UINT16 *source;
UINT8 *colormap;
UINT8 *translation;
UINT8 *dest;
UINT16 val;
double startz, startu, startv;
double izstep, uzstep, vzstep;
double endz, endu, endv;
UINT32 stepu, stepv;
iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx);
uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx);
vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx);
dest = ylookup[ds_y] + columnofs[ds_x1];
source = (UINT16 *)ds_source;
colormap = ds_colormap;
translation = ds_translation;
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) + viewx;
v = (INT64)(startv) + viewy;
for (i = SPANSIZE-1; i >= 0; i--)
{
// Lactozilla: Non-powers-of-two
fixed_t x = (((fixed_t)u-viewx) >> FRACBITS);
fixed_t y = (((fixed_t)v-viewy) >> FRACBITS);
// Carefully align all of my Friends.
if (x < 0)
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
if (y < 0)
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
x %= ds_flatwidth;
y %= ds_flatheight;
val = source[((y * ds_flatwidth) + x)];
if (val & 0xFF00)
*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
dest++;
u += stepu;
v += stepv;
}
startu = endu;
startv = endv;
width -= SPANSIZE;
}
if (width > 0)
{
if (width == 1)
{
u = (INT64)(startu);
v = (INT64)(startv);
// Lactozilla: Non-powers-of-two
{
fixed_t x = (((fixed_t)u-viewx) >> FRACBITS);
fixed_t y = (((fixed_t)v-viewy) >> FRACBITS);
// Carefully align all of my Friends.
if (x < 0)
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
if (y < 0)
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
x %= ds_flatwidth;
y %= ds_flatheight;
val = source[((y * ds_flatwidth) + x)];
if (val & 0xFF00)
*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
}
}
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) + viewx;
v = (INT64)(startv) + viewy;
for (; width != 0; width--)
{
// Lactozilla: Non-powers-of-two
fixed_t x = (((fixed_t)u-viewx) >> FRACBITS);
fixed_t y = (((fixed_t)v-viewy) >> FRACBITS);
// Carefully align all of my Friends.
if (x < 0)
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
if (y < 0)
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
x %= ds_flatwidth;
y %= ds_flatheight;
val = source[((y * ds_flatwidth) + x)];
if (val & 0xFF00)
*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
dest++;
u += stepu;
v += stepv;
}
}
}
}
/** \brief The R_DrawTranslucentSpan_NPO2_8 function /** \brief The R_DrawTranslucentSpan_NPO2_8 function
Draws the actual span with translucency. Draws the actual span with translucency.
*/ */
@ -885,7 +1317,6 @@ void R_DrawTranslucentSpan_NPO2_8 (void)
} }
} }
#ifndef NOWATER
void R_DrawTranslucentWaterSpan_NPO2_8(void) void R_DrawTranslucentWaterSpan_NPO2_8(void)
{ {
fixed_t xposition; fixed_t xposition;
@ -1024,9 +1455,6 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void)
vz += ds_svp->x; vz += ds_svp->x;
} while (--width >= 0); } while (--width >= 0);
#else #else
#define SPANSIZE 16
#define INVSPAN 0.0625f
startz = 1.f/iz; startz = 1.f/iz;
startu = uz*startz; startu = uz*startz;
startv = vz*startz; startv = vz*startz;
@ -1145,4 +1573,3 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void)
} }
#endif #endif
} }
#endif // NOWATER

View file

@ -959,6 +959,16 @@ void R_ExecuteSetViewSize(void)
dy = FixedMul(abs(dy), fovtan); dy = FixedMul(abs(dy), fovtan);
yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy); yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy);
} }
if (ds_su)
Z_Free(ds_su);
if (ds_sv)
Z_Free(ds_sv);
if (ds_sz)
Z_Free(ds_sz);
ds_su = ds_sv = ds_sz = NULL;
ds_sup = ds_svp = ds_szp = NULL;
} }
memset(scalelight, 0xFF, sizeof(scalelight)); memset(scalelight, 0xFF, sizeof(scalelight));
@ -1011,8 +1021,8 @@ void R_Init(void)
//I_OutputMsg("\nR_InitLightTables"); //I_OutputMsg("\nR_InitLightTables");
R_InitLightTables(); R_InitLightTables();
//I_OutputMsg("\nR_InitTranslationTables\n"); //I_OutputMsg("\nR_InitTranslucencyTables\n");
R_InitTranslationTables(); R_InitTranslucencyTables();
R_InitDrawNodes(); R_InitDrawNodes();
@ -1473,9 +1483,6 @@ void R_RenderPlayerView(player_t *player)
} }
R_ClearDrawSegs(); R_ClearDrawSegs();
R_ClearSprites(); R_ClearSprites();
#ifdef FLOORSPLATS
R_ClearVisibleFloorSplats();
#endif
Portal_InitList(); Portal_InitList();
// check for new console commands. // check for new console commands.
@ -1558,9 +1565,6 @@ void R_RenderPlayerView(player_t *player)
ps_sw_planetime = I_GetTimeMicros(); ps_sw_planetime = I_GetTimeMicros();
R_DrawPlanes(); R_DrawPlanes();
#ifdef FLOORSPLATS
R_DrawVisibleFloorSplats();
#endif
ps_sw_planetime = I_GetTimeMicros() - ps_sw_planetime; ps_sw_planetime = I_GetTimeMicros() - ps_sw_planetime;
// draw mid texture and sprite // draw mid texture and sprite
@ -1572,24 +1576,6 @@ void R_RenderPlayerView(player_t *player)
free(masks); free(masks);
} }
#ifdef HWRENDER
void R_InitHardwareMode(void)
{
HWR_AddSessionCommands();
HWR_Switch();
HWR_LoadTextures(numtextures);
if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))
HWR_SetupLevel();
}
#endif
void R_ReloadHUDGraphics(void)
{
ST_LoadGraphics();
HU_LoadGraphics();
ST_ReloadSkinFaceGraphics();
}
// ========================================================================= // =========================================================================
// ENGINE COMMANDS & VARS // ENGINE COMMANDS & VARS
// ========================================================================= // =========================================================================

View file

@ -114,10 +114,6 @@ extern consvar_t cv_tailspickup;
// Called by startup code. // Called by startup code.
void R_Init(void); void R_Init(void);
#ifdef HWRENDER
void R_InitHardwareMode(void);
#endif
void R_ReloadHUDGraphics(void);
void R_CheckViewMorph(void); void R_CheckViewMorph(void);
void R_ApplyViewMorph(void); void R_ApplyViewMorph(void);

160
src/r_patch.c Normal file
View file

@ -0,0 +1,160 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by Jaime "Lactozilla" Passos.
//
// 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_patch.c
/// \brief Patch generation.
#include "doomdef.h"
#include "r_patch.h"
#include "r_picformats.h"
#include "r_defs.h"
#include "z_zone.h"
#ifdef HWRENDER
#include "hardware/hw_glob.h"
#endif
//
// Creates a patch.
// Assumes a PU_PATCH zone memory tag and no user, but can always be set later
//
patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest)
{
patch_t *patch = (dest == NULL) ? Z_Calloc(sizeof(patch_t), PU_PATCH, NULL) : (patch_t *)(dest);
if (source)
{
INT32 col, colsize;
size_t size = sizeof(INT32) * SHORT(source->width);
size_t offs = (sizeof(INT16) * 4) + size;
patch->width = SHORT(source->width);
patch->height = SHORT(source->height);
patch->leftoffset = SHORT(source->leftoffset);
patch->topoffset = SHORT(source->topoffset);
patch->columnofs = Z_Calloc(size, PU_PATCH_DATA, NULL);
for (col = 0; col < source->width; col++)
{
// This makes the column offsets relative to the column data itself,
// instead of the entire patch data
patch->columnofs[col] = LONG(source->columnofs[col]) - offs;
}
if (!srcsize)
I_Error("Patch_Create: no source size!");
colsize = (INT32)(srcsize) - (INT32)offs;
if (colsize <= 0)
I_Error("Patch_Create: no column data!");
patch->columns = Z_Calloc(colsize, PU_PATCH_DATA, NULL);
M_Memcpy(patch->columns, ((UINT8 *)source + LONG(source->columnofs[0])), colsize);
}
return patch;
}
//
// Frees a patch from memory.
//
static void Patch_FreeData(patch_t *patch)
{
INT32 i;
#ifdef HWRENDER
if (patch->hardware)
HWR_FreeTexture(patch);
#endif
for (i = 0; i < 4; i++)
{
if (patch->flats[i])
Z_Free(patch->flats[i]);
}
#ifdef ROTSPRITE
if (patch->rotated)
{
rotsprite_t *rotsprite = patch->rotated;
for (i = 0; i < rotsprite->angles; i++)
{
if (rotsprite->patches[i])
Patch_Free(rotsprite->patches[i]);
}
Z_Free(rotsprite->patches);
Z_Free(rotsprite);
}
#endif
if (patch->columnofs)
Z_Free(patch->columnofs);
if (patch->columns)
Z_Free(patch->columns);
}
void Patch_Free(patch_t *patch)
{
Patch_FreeData(patch);
Z_Free(patch);
}
//
// Frees patches with a tag range.
//
static boolean Patch_FreeTagsCallback(void *mem)
{
patch_t *patch = (patch_t *)mem;
Patch_FreeData(patch);
return true;
}
void Patch_FreeTags(INT32 lowtag, INT32 hightag)
{
Z_IterateTags(lowtag, hightag, Patch_FreeTagsCallback);
}
void Patch_GenerateFlat(patch_t *patch, pictureflags_t flags)
{
UINT8 flip = (flags & (PICFLAGS_XFLIP | PICFLAGS_YFLIP));
if (patch->flats[flip] == NULL)
patch->flats[flip] = Picture_Convert(PICFMT_PATCH, patch, PICFMT_FLAT16, 0, NULL, 0, 0, 0, 0, flags);
}
#ifdef HWRENDER
//
// Allocates a hardware patch.
//
void *Patch_AllocateHardwarePatch(patch_t *patch)
{
if (!patch->hardware)
{
GLPatch_t *grPatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, &patch->hardware);
grPatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, &grPatch->mipmap);
}
return (void *)(patch->hardware);
}
//
// Creates a hardware patch.
//
void *Patch_CreateGL(patch_t *patch)
{
GLPatch_t *grPatch = (GLPatch_t *)Patch_AllocateHardwarePatch(patch);
if (!grPatch->mipmap->data) // Run HWR_MakePatch in all cases, to recalculate some things
HWR_MakePatch(patch, grPatch, grPatch->mipmap, false);
return grPatch;
}
#endif // HWRENDER

44
src/r_patch.h Normal file
View file

@ -0,0 +1,44 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by Jaime "Lactozilla" Passos.
//
// 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_patch.h
/// \brief Patch generation.
#ifndef __R_PATCH__
#define __R_PATCH__
#include "r_defs.h"
#include "r_picformats.h"
#include "doomdef.h"
// Patch functions
patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest);
void Patch_Free(patch_t *patch);
#define Patch_FreeTag(tagnum) Patch_FreeTags(tagnum, tagnum)
void Patch_FreeTags(INT32 lowtag, INT32 hightag);
void Patch_GenerateFlat(patch_t *patch, pictureflags_t flags);
#ifdef HWRENDER
void *Patch_AllocateHardwarePatch(patch_t *patch);
void *Patch_CreateGL(patch_t *patch);
#endif
#ifdef ROTSPRITE
void Patch_Rotate(patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip);
patch_t *Patch_GetRotated(patch_t *patch, INT32 angle, boolean flip);
patch_t *Patch_GetRotatedSprite(
spriteframe_t *sprite,
size_t frame, size_t spriteangle,
boolean flip, boolean adjustfeet,
void *info, INT32 rotationangle);
INT32 R_GetRollAngle(angle_t rollangle);
#endif
#endif // __R_PATCH__

273
src/r_patchrotation.c Normal file
View file

@ -0,0 +1,273 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by Jaime "Lactozilla" Passos.
//
// 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_patchrotation.c
/// \brief Patch rotation.
#include "r_patchrotation.h"
#include "r_things.h" // FEETADJUST
#include "z_zone.h"
#include "w_wad.h"
#ifdef ROTSPRITE
fixed_t rollcosang[ROTANGLES];
fixed_t rollsinang[ROTANGLES];
INT32 R_GetRollAngle(angle_t rollangle)
{
INT32 ra = AngleFixed(rollangle)>>FRACBITS;
#if (ROTANGDIFF > 1)
ra += (ROTANGDIFF/2);
#endif
ra /= ROTANGDIFF;
ra %= ROTANGLES;
return ra;
}
patch_t *Patch_GetRotated(patch_t *patch, INT32 angle, boolean flip)
{
rotsprite_t *rotsprite = patch->rotated;
if (rotsprite == NULL || angle < 1 || angle >= ROTANGLES)
return NULL;
if (flip)
angle += rotsprite->angles;
return rotsprite->patches[angle];
}
patch_t *Patch_GetRotatedSprite(
spriteframe_t *sprite,
size_t frame, size_t spriteangle,
boolean flip, boolean adjustfeet,
void *info, INT32 rotationangle)
{
rotsprite_t *rotsprite;
spriteinfo_t *sprinfo = (spriteinfo_t *)info;
INT32 idx = rotationangle;
UINT8 type = (adjustfeet ? 1 : 0);
if (rotationangle < 1 || rotationangle >= ROTANGLES)
return NULL;
rotsprite = sprite->rotated[type][spriteangle];
if (rotsprite == NULL)
{
rotsprite = RotatedPatch_Create(ROTANGLES);
sprite->rotated[type][spriteangle] = rotsprite;
}
if (flip)
idx += rotsprite->angles;
if (rotsprite->patches[idx] == NULL)
{
patch_t *patch;
INT32 xpivot = 0, ypivot = 0;
lumpnum_t lump = sprite->lumppat[spriteangle];
if (lump == LUMPERROR)
return NULL;
patch = W_CachePatchNum(lump, PU_SPRITE);
if (sprinfo->available)
{
xpivot = sprinfo->pivot[frame].x;
ypivot = sprinfo->pivot[frame].y;
}
else
{
xpivot = patch->leftoffset;
ypivot = patch->height / 2;
}
RotatedPatch_DoRotation(rotsprite, patch, rotationangle, xpivot, ypivot, flip);
//BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer
if (adjustfeet)
((patch_t *)rotsprite->patches[idx])->topoffset += FEETADJUST>>FRACBITS;
}
return rotsprite->patches[idx];
}
void Patch_Rotate(patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip)
{
if (patch->rotated == NULL)
patch->rotated = RotatedPatch_Create(ROTANGLES);
RotatedPatch_DoRotation(patch->rotated, patch, angle, xpivot, ypivot, flip);
}
rotsprite_t *RotatedPatch_Create(INT32 numangles)
{
rotsprite_t *rotsprite = Z_Calloc(sizeof(rotsprite_t), PU_STATIC, NULL);
rotsprite->angles = numangles;
rotsprite->patches = Z_Calloc(rotsprite->angles * 2 * sizeof(void *), PU_STATIC, NULL);
return rotsprite;
}
static void RotatedPatch_CalculateDimensions(
INT32 width, INT32 height,
fixed_t ca, fixed_t sa,
INT32 *newwidth, INT32 *newheight)
{
fixed_t fixedwidth = (width * FRACUNIT);
fixed_t fixedheight = (height * FRACUNIT);
fixed_t w1 = abs(FixedMul(fixedwidth, ca) - FixedMul(fixedheight, sa));
fixed_t w2 = abs(FixedMul(-fixedwidth, ca) - FixedMul(fixedheight, sa));
fixed_t h1 = abs(FixedMul(fixedwidth, sa) + FixedMul(fixedheight, ca));
fixed_t h2 = abs(FixedMul(-fixedwidth, sa) + FixedMul(fixedheight, ca));
w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2)));
w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2)));
h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2)));
h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2)));
*newwidth = max(width, max(w1, w2));
*newheight = max(height, max(h1, h2));
}
void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip)
{
patch_t *rotated;
UINT16 *rawdst, *rawconv;
size_t size;
pictureflags_t bflip = (flip) ? PICFLAGS_XFLIP : 0;
INT32 width = patch->width;
INT32 height = patch->height;
INT32 leftoffset = patch->leftoffset;
INT32 newwidth, newheight;
fixed_t ca = rollcosang[angle];
fixed_t sa = rollsinang[angle];
fixed_t xcenter, ycenter;
INT32 idx = angle;
INT32 x, y;
INT32 sx, sy;
INT32 dx, dy;
INT32 ox, oy;
INT32 minx, miny, maxx, maxy;
// Don't cache angle = 0
if (angle < 1 || angle >= ROTANGLES)
return;
if (flip)
{
idx += rotsprite->angles;
xpivot = width - xpivot;
leftoffset = width - leftoffset;
}
if (rotsprite->patches[idx])
return;
// Find the dimensions of the rotated patch.
RotatedPatch_CalculateDimensions(width, height, ca, sa, &newwidth, &newheight);
xcenter = (xpivot * FRACUNIT);
ycenter = (ypivot * FRACUNIT);
if (xpivot != width / 2 || ypivot != height / 2)
{
newwidth *= 2;
newheight *= 2;
}
minx = newwidth;
miny = newheight;
maxx = 0;
maxy = 0;
// Draw the rotated sprite to a temporary buffer.
size = (newwidth * newheight);
if (!size)
size = (width * height);
rawdst = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL);
for (dy = 0; dy < newheight; dy++)
{
for (dx = 0; dx < newwidth; dx++)
{
x = (dx - (newwidth / 2)) * FRACUNIT;
y = (dy - (newheight / 2)) * FRACUNIT;
sx = FixedMul(x, ca) + FixedMul(y, sa) + xcenter;
sy = -FixedMul(x, sa) + FixedMul(y, ca) + ycenter;
sx >>= FRACBITS;
sy >>= FRACBITS;
if (sx >= 0 && sy >= 0 && sx < width && sy < height)
{
void *input = Picture_GetPatchPixel(patch, PICFMT_PATCH, sx, sy, bflip);
if (input != NULL)
{
rawdst[(dy * newwidth) + dx] = (0xFF00 | (*(UINT8 *)input));
if (dx < minx)
minx = dx;
if (dy < miny)
miny = dy;
if (dx > maxx)
maxx = dx;
if (dy > maxy)
maxy = dy;
}
}
}
}
ox = (newwidth / 2) + (leftoffset - xpivot);
oy = (newheight / 2) + (patch->topoffset - ypivot);
width = (maxx - minx);
height = (maxy - miny);
if ((unsigned)(width * height) != size)
{
UINT16 *src, *dest;
size = (width * height);
rawconv = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL);
src = &rawdst[(miny * newwidth) + minx];
dest = rawconv;
dy = height;
while (dy--)
{
M_Memcpy(dest, src, width * sizeof(UINT16));
dest += width;
src += newwidth;
}
ox -= minx;
oy -= miny;
Z_Free(rawdst);
}
else
{
rawconv = rawdst;
width = newwidth;
height = newheight;
}
// make patch
rotated = (patch_t *)Picture_Convert(PICFMT_FLAT16, rawconv, PICFMT_PATCH, 0, NULL, width, height, 0, 0, 0);
Z_ChangeTag(rotated, PU_PATCH_ROTATED);
Z_SetUser(rotated, (void **)(&rotsprite->patches[idx]));
Z_Free(rawconv);
rotated->leftoffset = ox;
rotated->topoffset = oy;
}
#endif

21
src/r_patchrotation.h Normal file
View file

@ -0,0 +1,21 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by Jaime "Lactozilla" Passos.
//
// 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_patchrotation.h
/// \brief Patch rotation.
#include "r_patch.h"
#include "r_picformats.h"
#ifdef ROTSPRITE
rotsprite_t *RotatedPatch_Create(INT32 numangles);
void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip);
extern fixed_t rollcosang[ROTANGLES];
extern fixed_t rollsinang[ROTANGLES];
#endif

View file

@ -16,10 +16,11 @@
#include "dehacked.h" #include "dehacked.h"
#include "i_video.h" #include "i_video.h"
#include "r_data.h" #include "r_data.h"
#include "r_textures.h" #include "r_patch.h"
#include "r_draw.h"
#include "r_picformats.h" #include "r_picformats.h"
#include "r_textures.h"
#include "r_things.h" #include "r_things.h"
#include "r_draw.h"
#include "v_video.h" #include "v_video.h"
#include "z_zone.h" #include "z_zone.h"
#include "w_wad.h" #include "w_wad.h"
@ -142,10 +143,21 @@ void *Picture_PatchConvert(
if (Picture_IsPatchFormat(informat)) if (Picture_IsPatchFormat(informat))
{ {
inpatch = (patch_t *)picture; inpatch = (patch_t *)picture;
inwidth = SHORT(inpatch->width); if (Picture_IsDoomPatchFormat(informat))
inheight = SHORT(inpatch->height); {
inleftoffset = SHORT(inpatch->leftoffset); softwarepatch_t *doompatch = (softwarepatch_t *)picture;
intopoffset = SHORT(inpatch->topoffset); inwidth = SHORT(doompatch->width);
inheight = SHORT(doompatch->height);
inleftoffset = SHORT(doompatch->leftoffset);
intopoffset = SHORT(doompatch->topoffset);
}
else
{
inwidth = inpatch->width;
inheight = inpatch->height;
inleftoffset = inpatch->leftoffset;
intopoffset = inpatch->topoffset;
}
} }
// Write image size and offset // Write image size and offset
@ -275,6 +287,7 @@ void *Picture_PatchConvert(
switch (outformat) switch (outformat)
{ {
case PICFMT_PATCH32: case PICFMT_PATCH32:
case PICFMT_DOOMPATCH32:
{ {
if (inbpp == PICDEPTH_32BPP) if (inbpp == PICDEPTH_32BPP)
{ {
@ -294,6 +307,7 @@ void *Picture_PatchConvert(
break; break;
} }
case PICFMT_PATCH16: case PICFMT_PATCH16:
case PICFMT_DOOMPATCH16:
if (inbpp == PICDEPTH_32BPP) if (inbpp == PICDEPTH_32BPP)
{ {
RGBA_t in = *(RGBA_t *)input; RGBA_t in = *(RGBA_t *)input;
@ -338,9 +352,26 @@ void *Picture_PatchConvert(
img = Z_Malloc(size, PU_STATIC, NULL); img = Z_Malloc(size, PU_STATIC, NULL);
memcpy(img, imgbuf, size); memcpy(img, imgbuf, size);
if (outsize != NULL) if (Picture_IsInternalPatchFormat(outformat))
*outsize = size; {
return img; patch_t *converted = Patch_Create((softwarepatch_t *)img, size, NULL);
#ifdef HWRENDER
Patch_CreateGL(converted);
#endif
Z_Free(img);
if (outsize != NULL)
*outsize = sizeof(patch_t);
return converted;
}
else
{
if (outsize != NULL)
*outsize = size;
return img;
}
} }
/** Converts a picture to a flat. /** Converts a picture to a flat.
@ -391,8 +422,17 @@ void *Picture_FlatConvert(
if (Picture_IsPatchFormat(informat)) if (Picture_IsPatchFormat(informat))
{ {
inpatch = (patch_t *)picture; inpatch = (patch_t *)picture;
inwidth = SHORT(inpatch->width); if (Picture_IsDoomPatchFormat(informat))
inheight = SHORT(inpatch->height); {
softwarepatch_t *doompatch = ((softwarepatch_t *)picture);
inwidth = SHORT(doompatch->width);
inheight = SHORT(doompatch->height);
}
else
{
inwidth = inpatch->width;
inheight = inpatch->height;
}
} }
size = (inwidth * inheight) * (outbpp / 8); size = (inwidth * inheight) * (outbpp / 8);
@ -503,22 +543,25 @@ void *Picture_GetPatchPixel(
UINT8 *s8 = NULL; UINT8 *s8 = NULL;
UINT16 *s16 = NULL; UINT16 *s16 = NULL;
UINT32 *s32 = NULL; UINT32 *s32 = NULL;
softwarepatch_t *doompatch = (softwarepatch_t *)patch;
INT16 width;
if (patch == NULL) if (patch == NULL)
I_Error("Picture_GetPatchPixel: patch == NULL"); I_Error("Picture_GetPatchPixel: patch == NULL");
if (x >= 0 && x < SHORT(patch->width)) width = (Picture_IsDoomPatchFormat(informat) ? patch->width : SHORT(patch->width));
{
INT32 topdelta, prevdelta = -1;
INT32 colofs = 0;
if (flags & PICFLAGS_XFLIP) if (x >= 0 && x < width)
colofs = LONG(patch->columnofs[(SHORT(patch->width)-1)-x]); {
else INT32 colx = (flags & PICFLAGS_XFLIP) ? (width-1)-x : x;
colofs = LONG(patch->columnofs[x]); INT32 topdelta, prevdelta = -1;
INT32 colofs = (Picture_IsDoomPatchFormat(informat) ? LONG(patch->columnofs[colx]) : patch->columnofs[colx]);
// Column offsets are pointers so no casting required // Column offsets are pointers so no casting required
column = (column_t *)((UINT8 *)patch + colofs); if (Picture_IsDoomPatchFormat(informat))
column = (column_t *)((UINT8 *)doompatch + colofs);
else
column = (column_t *)((UINT8 *)patch->columns + colofs);
while (column->topdelta != 0xff) while (column->topdelta != 0xff)
{ {
@ -527,25 +570,25 @@ void *Picture_GetPatchPixel(
topdelta += prevdelta; topdelta += prevdelta;
prevdelta = topdelta; prevdelta = topdelta;
s8 = (UINT8 *)(column) + 3; s8 = (UINT8 *)(column) + 3;
if (informat == PICFMT_PATCH32) if (Picture_FormatBPP(informat) == PICDEPTH_32BPP)
s32 = (UINT32 *)s8; s32 = (UINT32 *)s8;
else if (informat == PICFMT_PATCH16) else if (Picture_FormatBPP(informat) == PICDEPTH_16BPP)
s16 = (UINT16 *)s8; s16 = (UINT16 *)s8;
for (ofs = 0; ofs < column->length; ofs++) for (ofs = 0; ofs < column->length; ofs++)
{ {
if ((topdelta + ofs) == y) if ((topdelta + ofs) == y)
{ {
if (informat == PICFMT_PATCH32) if (Picture_FormatBPP(informat) == PICDEPTH_32BPP)
return &s32[ofs]; return &s32[ofs];
else if (informat == PICFMT_PATCH16) else if (Picture_FormatBPP(informat) == PICDEPTH_16BPP)
return &s16[ofs]; return &s16[ofs];
else // PICFMT_PATCH else // PICDEPTH_8BPP
return &s8[ofs]; return &s8[ofs];
} }
} }
if (informat == PICFMT_PATCH32) if (Picture_FormatBPP(informat) == PICDEPTH_32BPP)
column = (column_t *)((UINT32 *)column + column->length); column = (column_t *)((UINT32 *)column + column->length);
else if (informat == PICFMT_PATCH16) else if (Picture_FormatBPP(informat) == PICDEPTH_16BPP)
column = (column_t *)((UINT16 *)column + column->length); column = (column_t *)((UINT16 *)column + column->length);
else else
column = (column_t *)((UINT8 *)column + column->length); column = (column_t *)((UINT8 *)column + column->length);
@ -568,15 +611,18 @@ INT32 Picture_FormatBPP(pictureformat_t format)
{ {
case PICFMT_PATCH32: case PICFMT_PATCH32:
case PICFMT_FLAT32: case PICFMT_FLAT32:
case PICFMT_DOOMPATCH32:
case PICFMT_PNG: case PICFMT_PNG:
bpp = PICDEPTH_32BPP; bpp = PICDEPTH_32BPP;
break; break;
case PICFMT_PATCH16: case PICFMT_PATCH16:
case PICFMT_FLAT16: case PICFMT_FLAT16:
case PICFMT_DOOMPATCH16:
bpp = PICDEPTH_16BPP; bpp = PICDEPTH_16BPP;
break; break;
case PICFMT_PATCH: case PICFMT_PATCH:
case PICFMT_FLAT: case PICFMT_FLAT:
case PICFMT_DOOMPATCH:
bpp = PICDEPTH_8BPP; bpp = PICDEPTH_8BPP;
break; break;
default: default:
@ -592,7 +638,43 @@ INT32 Picture_FormatBPP(pictureformat_t format)
*/ */
boolean Picture_IsPatchFormat(pictureformat_t format) boolean Picture_IsPatchFormat(pictureformat_t format)
{ {
return (format == PICFMT_PATCH || format == PICFMT_PATCH16 || format == PICFMT_PATCH32); return (Picture_IsInternalPatchFormat(format) || Picture_IsDoomPatchFormat(format));
}
/** Checks if the specified picture format is an internal patch.
*
* \param format Input picture format.
* \return True if the picture format is an internal patch, false if not.
*/
boolean Picture_IsInternalPatchFormat(pictureformat_t format)
{
switch (format)
{
case PICFMT_PATCH:
case PICFMT_PATCH16:
case PICFMT_PATCH32:
return true;
default:
return false;
}
}
/** Checks if the specified picture format is a Doom patch.
*
* \param format Input picture format.
* \return True if the picture format is a Doom patch, false if not.
*/
boolean Picture_IsDoomPatchFormat(pictureformat_t format)
{
switch (format)
{
case PICFMT_DOOMPATCH:
case PICFMT_DOOMPATCH16:
case PICFMT_DOOMPATCH32:
return true;
default:
return false;
}
} }
/** Checks if the specified picture format is a flat. /** Checks if the specified picture format is a flat.
@ -605,14 +687,14 @@ boolean Picture_IsFlatFormat(pictureformat_t format)
return (format == PICFMT_FLAT || format == PICFMT_FLAT16 || format == PICFMT_FLAT32); return (format == PICFMT_FLAT || format == PICFMT_FLAT16 || format == PICFMT_FLAT32);
} }
/** Returns true if the lump is a valid patch. /** Returns true if the lump is a valid Doom patch.
* PICFMT_PATCH only, I think?? * PICFMT_DOOMPATCH only.
* *
* \param patch Input patch. * \param patch Input patch.
* \param picture Input patch size. * \param picture Input patch size.
* \return True if the input patch is valid. * \return True if the input patch is valid.
*/ */
boolean Picture_CheckIfPatch(patch_t *patch, size_t size) boolean Picture_CheckIfDoomPatch(softwarepatch_t *patch, size_t size)
{ {
INT16 width, height; INT16 width, height;
boolean result; boolean result;
@ -887,26 +969,45 @@ static png_bytep *PNG_Read(
// matches the color count of SRB2's palette: 256 colors. // matches the color count of SRB2's palette: 256 colors.
if (png_get_PLTE(png_ptr, png_info_ptr, &palette, &palette_size)) if (png_get_PLTE(png_ptr, png_info_ptr, &palette, &palette_size))
{ {
if (palette_size == 256) if (palette_size == 256 && pMasterPalette)
{
png_colorp pal = palette;
INT32 i;
usepal = true; usepal = true;
for (i = 0; i < 256; i++)
{
UINT32 rgb = R_PutRgbaRGBA(pal->red, pal->green, pal->blue, 0xFF);
if (rgb != pMasterPalette[i].rgba)
{
usepal = false;
break;
}
pal++;
}
}
} }
// If any of the tRNS colors have an alpha lower than 0xFF, and that // If any of the tRNS colors have an alpha lower than 0xFF, and that
// color is present on the image, the palette flag is disabled. // color is present on the image, the palette flag is disabled.
png_get_tRNS(png_ptr, png_info_ptr, &trans, &trans_num, &trans_values); if (usepal)
if (trans && trans_num == 256)
{ {
int i; png_get_tRNS(png_ptr, png_info_ptr, &trans, &trans_num, &trans_values);
for (i = 0; i < trans_num; i++)
if (trans && trans_num == 256)
{ {
// libpng will transform this image into RGB even if INT32 i;
// the transparent index does not exist in the image, for (i = 0; i < trans_num; i++)
// and there is no way around that.
if (trans[i] < 0xFF)
{ {
usepal = false; // libpng will transform this image into RGB even if
break; // the transparent index does not exist in the image,
// and there is no way around that.
if (trans[i] < 0xFF)
{
usepal = false;
break;
}
} }
} }
} }
@ -1446,11 +1547,6 @@ static void R_ParseSpriteInfo(boolean spr2)
info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL);
info->available = true; info->available = true;
#ifdef ROTSPRITE
if ((sprites != NULL) && (!spr2))
R_FreeSingleRotSprite(&sprites[sprnum]);
#endif
// Left Curly Brace // Left Curly Brace
sprinfoToken = M_GetToken(NULL); sprinfoToken = M_GetToken(NULL);
if (sprinfoToken == NULL) if (sprinfoToken == NULL)
@ -1511,9 +1607,6 @@ static void R_ParseSpriteInfo(boolean spr2)
size_t skinnum = skinnumbers[i]; size_t skinnum = skinnumbers[i];
skin_t *skin = &skins[skinnum]; skin_t *skin = &skins[skinnum];
spriteinfo_t *sprinfo = skin->sprinfo; spriteinfo_t *sprinfo = skin->sprinfo;
#ifdef ROTSPRITE
R_FreeSkinRotSprite(skinnum);
#endif
M_Memcpy(&sprinfo[spr2num], info, sizeof(spriteinfo_t)); M_Memcpy(&sprinfo[spr2num], info, sizeof(spriteinfo_t));
} }
} }
@ -1603,316 +1696,3 @@ void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps)
R_ParseSPRTINFOLump(wadnum, i); R_ParseSPRTINFOLump(wadnum, i);
} }
} }
#ifdef ROTSPRITE
//
// R_GetRollAngle
//
// Angles precalculated in R_InitSprites.
//
fixed_t rollcosang[ROTANGLES];
fixed_t rollsinang[ROTANGLES];
INT32 R_GetRollAngle(angle_t rollangle)
{
INT32 ra = AngleFixed(rollangle)>>FRACBITS;
#if (ROTANGDIFF > 1)
ra += (ROTANGDIFF/2);
#endif
ra /= ROTANGDIFF;
ra %= ROTANGLES;
return ra;
}
//
// R_CacheRotSprite
//
// Create a rotated sprite.
//
void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, UINT8 flip)
{
INT32 angle;
patch_t *patch;
patch_t *newpatch;
UINT16 *rawdst;
size_t size;
pictureflags_t bflip = (flip) ? PICFLAGS_XFLIP : 0;
#define SPRITE_XCENTER (leftoffset)
#define SPRITE_YCENTER (height / 2)
#define ROTSPRITE_XCENTER (newwidth / 2)
#define ROTSPRITE_YCENTER (newheight / 2)
if (!(sprframe->rotsprite.cached & (1<<rot)))
{
INT32 dx, dy;
INT32 px, py;
INT32 width, height, leftoffset;
fixed_t ca, sa;
lumpnum_t lump = sprframe->lumppat[rot];
#ifndef NO_PNG_LUMPS
size_t lumplength;
#endif
if (lump == LUMPERROR)
return;
patch = (patch_t *)W_CacheLumpNum(lump, PU_STATIC);
#ifndef NO_PNG_LUMPS
lumplength = W_LumpLength(lump);
if (Picture_IsLumpPNG((const UINT8 *)patch, lumplength))
patch = (patch_t *)Picture_PNGConvert((const UINT8 *)patch, PICFMT_PATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0);
else
#endif
// Because there's something wrong with SPR_DFLM, I guess
if (!Picture_CheckIfPatch(patch, lumplength))
return;
width = SHORT(patch->width);
height = SHORT(patch->height);
leftoffset = SHORT(patch->leftoffset);
// rotation pivot
px = SPRITE_XCENTER;
py = SPRITE_YCENTER;
// get correct sprite info for sprite
if (sprinfo == NULL)
sprinfo = &spriteinfo[sprnum];
if (sprinfo->available)
{
px = sprinfo->pivot[frame].x;
py = sprinfo->pivot[frame].y;
}
if (bflip)
{
px = width - px;
leftoffset = width - leftoffset;
}
// Don't cache angle = 0
for (angle = 1; angle < ROTANGLES; angle++)
{
INT32 newwidth, newheight;
ca = rollcosang[angle];
sa = rollsinang[angle];
// Find the dimensions of the rotated patch.
{
INT32 w1 = abs(FixedMul(width << FRACBITS, ca) - FixedMul(height << FRACBITS, sa));
INT32 w2 = abs(FixedMul(-(width << FRACBITS), ca) - FixedMul(height << FRACBITS, sa));
INT32 h1 = abs(FixedMul(width << FRACBITS, sa) + FixedMul(height << FRACBITS, ca));
INT32 h2 = abs(FixedMul(-(width << FRACBITS), sa) + FixedMul(height << FRACBITS, ca));
w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2)));
w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2)));
h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2)));
h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2)));
newwidth = max(width, max(w1, w2));
newheight = max(height, max(h1, h2));
}
// check boundaries
{
fixed_t top[2][2];
fixed_t bottom[2][2];
top[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS);
top[0][1] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS);
top[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS);
top[1][1] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS);
bottom[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS);
bottom[0][1] = -FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS);
bottom[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS);
bottom[1][1] = -FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS);
top[0][0] >>= FRACBITS;
top[0][1] >>= FRACBITS;
top[1][0] >>= FRACBITS;
top[1][1] >>= FRACBITS;
bottom[0][0] >>= FRACBITS;
bottom[0][1] >>= FRACBITS;
bottom[1][0] >>= FRACBITS;
bottom[1][1] >>= FRACBITS;
#define BOUNDARYWCHECK(b) (b[0] < 0 || b[0] >= width)
#define BOUNDARYHCHECK(b) (b[1] < 0 || b[1] >= height)
#define BOUNDARYADJUST(x) x *= 2
// top left/right
if (BOUNDARYWCHECK(top[0]) || BOUNDARYWCHECK(top[1]))
BOUNDARYADJUST(newwidth);
// bottom left/right
else if (BOUNDARYWCHECK(bottom[0]) || BOUNDARYWCHECK(bottom[1]))
BOUNDARYADJUST(newwidth);
// top left/right
if (BOUNDARYHCHECK(top[0]) || BOUNDARYHCHECK(top[1]))
BOUNDARYADJUST(newheight);
// bottom left/right
else if (BOUNDARYHCHECK(bottom[0]) || BOUNDARYHCHECK(bottom[1]))
BOUNDARYADJUST(newheight);
#undef BOUNDARYWCHECK
#undef BOUNDARYHCHECK
#undef BOUNDARYADJUST
}
// Draw the rotated sprite to a temporary buffer.
size = (newwidth * newheight);
if (!size)
size = (width * height);
rawdst = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL);
for (dy = 0; dy < newheight; dy++)
{
for (dx = 0; dx < newwidth; dx++)
{
INT32 x = (dx-ROTSPRITE_XCENTER) << FRACBITS;
INT32 y = (dy-ROTSPRITE_YCENTER) << FRACBITS;
INT32 sx = FixedMul(x, ca) + FixedMul(y, sa) + (px << FRACBITS);
INT32 sy = -FixedMul(x, sa) + FixedMul(y, ca) + (py << FRACBITS);
sx >>= FRACBITS;
sy >>= FRACBITS;
if (sx >= 0 && sy >= 0 && sx < width && sy < height)
{
void *input = Picture_GetPatchPixel(patch, PICFMT_PATCH, sx, sy, bflip);
if (input != NULL)
rawdst[(dy*newwidth)+dx] = (0xFF00 | (*(UINT8 *)input));
}
}
}
// make patch
newpatch = (patch_t *)Picture_Convert(PICFMT_FLAT16, rawdst, PICFMT_PATCH, 0, &size, newwidth, newheight, 0, 0, 0);
{
newpatch->leftoffset = (newpatch->width / 2) + (leftoffset - px);
newpatch->topoffset = (newpatch->height / 2) + (SHORT(patch->topoffset) - py);
}
//BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer
if (rendermode != render_none) // not for psprite
newpatch->topoffset += FEETADJUST>>FRACBITS;
// P_PrecacheLevel
if (devparm) spritememory += size;
// convert everything to little-endian, for big-endian support
newpatch->width = SHORT(newpatch->width);
newpatch->height = SHORT(newpatch->height);
newpatch->leftoffset = SHORT(newpatch->leftoffset);
newpatch->topoffset = SHORT(newpatch->topoffset);
#ifdef HWRENDER
if (rendermode == render_opengl)
{
GLPatch_t *grPatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL);
grPatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL);
grPatch->rawpatch = newpatch;
sprframe->rotsprite.patch[rot][angle] = (patch_t *)grPatch;
HWR_MakePatch(newpatch, grPatch, grPatch->mipmap, false);
}
else
#endif // HWRENDER
sprframe->rotsprite.patch[rot][angle] = newpatch;
// free rotated image data
Z_Free(rawdst);
}
// This rotation is cached now
sprframe->rotsprite.cached |= (1<<rot);
// free image data
Z_Free(patch);
}
#undef SPRITE_XCENTER
#undef SPRITE_YCENTER
#undef ROTSPRITE_XCENTER
#undef ROTSPRITE_YCENTER
}
//
// R_FreeSingleRotSprite
//
// Free sprite rotation data from memory, for a single spritedef.
//
void R_FreeSingleRotSprite(spritedef_t *spritedef)
{
UINT8 frame;
INT32 rot, ang;
for (frame = 0; frame < spritedef->numframes; frame++)
{
spriteframe_t *sprframe = &spritedef->spriteframes[frame];
for (rot = 0; rot < 16; rot++)
{
if (sprframe->rotsprite.cached & (1<<rot))
{
for (ang = 0; ang < ROTANGLES; ang++)
{
patch_t *rotsprite = sprframe->rotsprite.patch[rot][ang];
if (rotsprite)
{
#ifdef HWRENDER
if (rendermode == render_opengl)
{
GLPatch_t *grPatch = (GLPatch_t *)rotsprite;
if (grPatch->rawpatch)
{
Z_Free(grPatch->rawpatch);
grPatch->rawpatch = NULL;
}
if (grPatch->mipmap)
{
if (grPatch->mipmap->data)
{
Z_Free(grPatch->mipmap->data);
grPatch->mipmap->data = NULL;
}
Z_Free(grPatch->mipmap);
grPatch->mipmap = NULL;
}
}
#endif
Z_Free(rotsprite);
}
}
sprframe->rotsprite.cached &= ~(1<<rot);
}
}
}
}
//
// R_FreeSkinRotSprite
//
// Free sprite rotation data from memory, for a skin.
// Calls R_FreeSingleRotSprite.
//
void R_FreeSkinRotSprite(size_t skinnum)
{
size_t i;
skin_t *skin = &skins[skinnum];
spritedef_t *skinsprites = skin->sprites;
for (i = 0; i < NUMPLAYERSPRITES*2; i++)
{
R_FreeSingleRotSprite(skinsprites);
skinsprites++;
}
}
//
// R_FreeAllRotSprite
//
// Free ALL sprite rotation data from memory.
//
void R_FreeAllRotSprite(void)
{
INT32 i;
size_t s;
for (s = 0; s < numsprites; s++)
R_FreeSingleRotSprite(&sprites[s]);
for (i = 0; i < numskins; ++i)
R_FreeSkinRotSprite(i);
}
#endif

View file

@ -24,6 +24,7 @@ typedef enum
// Doom formats // Doom formats
PICFMT_PATCH, PICFMT_PATCH,
PICFMT_FLAT, PICFMT_FLAT,
PICFMT_DOOMPATCH,
// PNG // PNG
PICFMT_PNG, PICFMT_PNG,
@ -31,10 +32,12 @@ typedef enum
// 16bpp // 16bpp
PICFMT_PATCH16, PICFMT_PATCH16,
PICFMT_FLAT16, PICFMT_FLAT16,
PICFMT_DOOMPATCH16,
// 32bpp // 32bpp
PICFMT_PATCH32, PICFMT_PATCH32,
PICFMT_FLAT32 PICFMT_FLAT32,
PICFMT_DOOMPATCH32
} pictureformat_t; } pictureformat_t;
typedef enum typedef enum
@ -76,8 +79,10 @@ void *Picture_TextureToFlat(size_t trickytex);
INT32 Picture_FormatBPP(pictureformat_t format); INT32 Picture_FormatBPP(pictureformat_t format);
boolean Picture_IsPatchFormat(pictureformat_t format); boolean Picture_IsPatchFormat(pictureformat_t format);
boolean Picture_IsInternalPatchFormat(pictureformat_t format);
boolean Picture_IsDoomPatchFormat(pictureformat_t format);
boolean Picture_IsFlatFormat(pictureformat_t format); boolean Picture_IsFlatFormat(pictureformat_t format);
boolean Picture_CheckIfPatch(patch_t *patch, size_t size); boolean Picture_CheckIfDoomPatch(softwarepatch_t *patch, size_t size);
// Structs // Structs
typedef enum typedef enum
@ -120,15 +125,4 @@ extern spriteinfo_t spriteinfo[NUMSPRITES];
void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps); void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps);
void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum); void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum);
// Sprite rotation #endif // __R_PICFORMATS__
#ifdef ROTSPRITE
INT32 R_GetRollAngle(angle_t rollangle);
void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, UINT8 flip);
void R_FreeSingleRotSprite(spritedef_t *spritedef);
void R_FreeSkinRotSprite(size_t skinnum);
extern fixed_t rollcosang[ROTANGLES];
extern fixed_t rollsinang[ROTANGLES];
void R_FreeAllRotSprite(void);
#endif
#endif // __R_PATCH__

View file

@ -115,33 +115,40 @@ void R_InitPlanes(void)
} }
// //
// Water ripple effect!! // Water ripple effect
// Needs the height of the plane, and the vertical position of the span. // Needs the height of the plane, and the vertical position of the span.
// Sets ripple_xfrac and ripple_yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted. // Sets planeripple.xfrac and planeripple.yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted.
// //
#ifndef NOWATER struct
INT32 ds_bgofs; {
INT32 ds_waterofs; INT32 offset;
fixed_t xfrac, yfrac;
boolean active;
} planeripple;
static INT32 wtofs=0; static void R_CalculatePlaneRipple(visplane_t *plane, INT32 y, fixed_t plheight, boolean calcfrac)
static boolean itswater;
static fixed_t ripple_xfrac;
static fixed_t ripple_yfrac;
static void R_PlaneRipple(visplane_t *plane, INT32 y, fixed_t plheight)
{ {
fixed_t distance = FixedMul(plheight, yslope[y]); fixed_t distance = FixedMul(plheight, yslope[y]);
const INT32 yay = (wtofs + (distance>>9) ) & 8191; const INT32 yay = (planeripple.offset + (distance>>9)) & 8191;
// ripples da water texture // ripples da water texture
angle_t angle = (plane->viewangle + plane->plangle)>>ANGLETOFINESHIFT;
ds_bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; ds_bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS;
angle = (angle + 2048) & 8191; // 90 degrees if (calcfrac)
ripple_xfrac = FixedMul(FINECOSINE(angle), (ds_bgofs<<FRACBITS)); {
ripple_yfrac = FixedMul(FINESINE(angle), (ds_bgofs<<FRACBITS)); angle_t angle = (plane->viewangle + plane->plangle)>>ANGLETOFINESHIFT;
angle = (angle + 2048) & 8191; // 90 degrees
planeripple.xfrac = FixedMul(FINECOSINE(angle), (ds_bgofs<<FRACBITS));
planeripple.yfrac = FixedMul(FINESINE(angle), (ds_bgofs<<FRACBITS));
}
}
static void R_UpdatePlaneRipple(void)
{
ds_waterofs = (leveltime & 1)*16384;
planeripple.offset = (leveltime * 140);
} }
#endif
// //
// R_MapPlane // R_MapPlane
@ -159,7 +166,7 @@ static void R_PlaneRipple(visplane_t *plane, INT32 y, fixed_t plheight)
void R_MapPlane(INT32 y, INT32 x1, INT32 x2) void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
{ {
angle_t angle, planecos, planesin; angle_t angle, planecos, planesin;
fixed_t distance, span; fixed_t distance = 0, span;
size_t pindex; size_t pindex;
#ifdef RANGECHECK #ifdef RANGECHECK
@ -167,41 +174,51 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
I_Error("R_MapPlane: %d, %d at %d", x1, x2, y); I_Error("R_MapPlane: %d, %d at %d", x1, x2, y);
#endif #endif
// from r_splats's R_RenderFloorSplat if (x1 >= vid.width)
if (x1 >= vid.width) x1 = vid.width - 1; x1 = vid.width - 1;
angle = (currentplane->viewangle + currentplane->plangle)>>ANGLETOFINESHIFT; if (!currentplane->slope)
planecos = FINECOSINE(angle);
planesin = FINESINE(angle);
if (planeheight != cachedheight[y])
{ {
cachedheight[y] = planeheight; angle = (currentplane->viewangle + currentplane->plangle)>>ANGLETOFINESHIFT;
distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]); planecos = FINECOSINE(angle);
ds_xstep = cachedxstep[y] = FixedMul(distance, basexscale); planesin = FINESINE(angle);
ds_ystep = cachedystep[y] = FixedMul(distance, baseyscale);
if ((span = abs(centery-y))) if (planeheight != cachedheight[y])
{ {
ds_xstep = cachedxstep[y] = FixedMul(planesin, planeheight) / span; cachedheight[y] = planeheight;
ds_ystep = cachedystep[y] = FixedMul(planecos, planeheight) / span; cacheddistance[y] = distance = FixedMul(planeheight, yslope[y]);
span = abs(centery - y);
if (span) // don't divide by zero
{
ds_xstep = FixedMul(planesin, planeheight) / span;
ds_ystep = FixedMul(planecos, planeheight) / span;
}
else
{
ds_xstep = FixedMul(distance, basexscale);
ds_ystep = FixedMul(distance, baseyscale);
}
cachedxstep[y] = ds_xstep;
cachedystep[y] = ds_ystep;
} }
} else
else {
{ distance = cacheddistance[y];
distance = cacheddistance[y]; ds_xstep = cachedxstep[y];
ds_xstep = cachedxstep[y]; ds_ystep = cachedystep[y];
ds_ystep = cachedystep[y]; }
ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep;
ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep;
} }
ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep; // Water ripple effect
ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep; if (planeripple.active)
#ifndef NOWATER
if (itswater)
{ {
// Needed for ds_bgofs // Needed for ds_bgofs
R_PlaneRipple(currentplane, y, planeheight); R_CalculatePlaneRipple(currentplane, y, planeheight, (!currentplane->slope));
if (currentplane->slope) if (currentplane->slope)
{ {
@ -211,25 +228,25 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
} }
else else
{ {
ds_xfrac += ripple_xfrac; ds_xfrac += planeripple.xfrac;
ds_yfrac += ripple_yfrac; ds_yfrac += planeripple.yfrac;
} }
if (y+ds_bgofs>=viewheight) if ((y + ds_bgofs) >= viewheight)
ds_bgofs = viewheight-y-1; ds_bgofs = viewheight-y-1;
if (y+ds_bgofs<0) if ((y + ds_bgofs) < 0)
ds_bgofs = -y; ds_bgofs = -y;
} }
#endif
pindex = distance >> LIGHTZSHIFT;
if (pindex >= MAXLIGHTZ)
pindex = MAXLIGHTZ - 1;
if (currentplane->slope) if (currentplane->slope)
ds_colormap = colormaps; ds_colormap = colormaps;
else else
{
pindex = distance >> LIGHTZSHIFT;
if (pindex >= MAXLIGHTZ)
pindex = MAXLIGHTZ - 1;
ds_colormap = planezlight[pindex]; ds_colormap = planezlight[pindex];
}
if (currentplane->extra_colormap) if (currentplane->extra_colormap)
ds_colormap = currentplane->extra_colormap->colormap + (ds_colormap - colormaps); ds_colormap = currentplane->extra_colormap->colormap + (ds_colormap - colormaps);
@ -592,9 +609,7 @@ void R_DrawPlanes(void)
visplane_t *pl; visplane_t *pl;
INT32 i; INT32 i;
// Note: are these two lines really needed? R_UpdatePlaneRipple();
// R_DrawSinglePlane and R_DrawSkyPlane do span/column drawer resets themselves anyway
spanfunc = spanfuncs[BASEDRAWFUNC];
for (i = 0; i < MAXVISPLANES; i++, pl++) for (i = 0; i < MAXVISPLANES; i++, pl++)
{ {
@ -606,10 +621,6 @@ void R_DrawPlanes(void)
R_DrawSinglePlane(pl); R_DrawSinglePlane(pl);
} }
} }
#ifndef NOWATER
ds_waterofs = (leveltime & 1)*16384;
wtofs = leveltime * 140;
#endif
} }
// R_DrawSkyPlane // R_DrawSkyPlane
@ -655,46 +666,48 @@ static void R_DrawSkyPlane(visplane_t *pl)
} }
} }
static void R_SlopeVectors(visplane_t *pl, INT32 i, float fudge) // Potentially override other stuff for now cus we're mean. :< But draw a slope plane!
// I copied ZDoom's code and adapted it to SRB2... -Red
void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planeviewy, fixed_t planeviewz, fixed_t planexscale, fixed_t planeyscale, fixed_t planexoffset, fixed_t planeyoffset, angle_t planeviewangle, angle_t planeangle, float fudge)
{ {
// Potentially override other stuff for now cus we're mean. :< But draw a slope plane!
// I copied ZDoom's code and adapted it to SRB2... -Red
floatv3_t p, m, n; floatv3_t p, m, n;
float ang; float ang;
float vx, vy, vz; float vx, vy, vz;
float xscale = FIXED_TO_FLOAT(planexscale);
float yscale = FIXED_TO_FLOAT(planeyscale);
// compiler complains when P_GetSlopeZAt is used in FLOAT_TO_FIXED directly // compiler complains when P_GetSlopeZAt is used in FLOAT_TO_FIXED directly
// use this as a temp var to store P_GetSlopeZAt's return value each time // use this as a temp var to store P_GetSlopeZAt's return value each time
fixed_t temp; fixed_t temp;
vx = FIXED_TO_FLOAT(pl->viewx+xoffs); vx = FIXED_TO_FLOAT(planeviewx+planexoffset);
vy = FIXED_TO_FLOAT(pl->viewy-yoffs); vy = FIXED_TO_FLOAT(planeviewy-planeyoffset);
vz = FIXED_TO_FLOAT(pl->viewz); vz = FIXED_TO_FLOAT(planeviewz);
temp = P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy); temp = P_GetSlopeZAt(slope, planeviewx, planeviewy);
zeroheight = FIXED_TO_FLOAT(temp); zeroheight = FIXED_TO_FLOAT(temp);
// p is the texture origin in view space // p is the texture origin in view space
// Don't add in the offsets at this stage, because doing so can result in // Don't add in the offsets at this stage, because doing so can result in
// errors if the flat is rotated. // errors if the flat is rotated.
ang = ANG2RAD(ANGLE_270 - pl->viewangle); ang = ANG2RAD(ANGLE_270 - planeviewangle);
p.x = vx * cos(ang) - vy * sin(ang); p.x = vx * cos(ang) - vy * sin(ang);
p.z = vx * sin(ang) + vy * cos(ang); p.z = vx * sin(ang) + vy * cos(ang);
temp = P_GetSlopeZAt(pl->slope, -xoffs, yoffs); temp = P_GetSlopeZAt(slope, -planexoffset, planeyoffset);
p.y = FIXED_TO_FLOAT(temp) - vz; p.y = FIXED_TO_FLOAT(temp) - vz;
// m is the v direction vector in view space // m is the v direction vector in view space
ang = ANG2RAD(ANGLE_180 - (pl->viewangle + pl->plangle)); ang = ANG2RAD(ANGLE_180 - (planeviewangle + planeangle));
m.x = cos(ang); m.x = yscale * cos(ang);
m.z = sin(ang); m.z = yscale * sin(ang);
// n is the u direction vector in view space // n is the u direction vector in view space
n.x = sin(ang); n.x = xscale * sin(ang);
n.z = -cos(ang); n.z = -xscale * cos(ang);
ang = ANG2RAD(pl->plangle); ang = ANG2RAD(planeangle);
temp = P_GetSlopeZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(sin(ang)), pl->viewy + FLOAT_TO_FIXED(cos(ang))); temp = P_GetSlopeZAt(slope, planeviewx + yscale * FLOAT_TO_FIXED(sin(ang)), planeviewy + yscale * FLOAT_TO_FIXED(cos(ang)));
m.y = FIXED_TO_FLOAT(temp) - zeroheight; m.y = FIXED_TO_FLOAT(temp) - zeroheight;
temp = P_GetSlopeZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(cos(ang)), pl->viewy - FLOAT_TO_FIXED(sin(ang))); temp = P_GetSlopeZAt(slope, planeviewx + xscale * FLOAT_TO_FIXED(cos(ang)), planeviewy - xscale * FLOAT_TO_FIXED(sin(ang)));
n.y = FIXED_TO_FLOAT(temp) - zeroheight; n.y = FIXED_TO_FLOAT(temp) - zeroheight;
if (ds_powersoftwo) if (ds_powersoftwo)
@ -710,42 +723,62 @@ static void R_SlopeVectors(visplane_t *pl, INT32 i, float fudge)
// Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using. // Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using.
#define CROSS(d, v1, v2) \ #define CROSS(d, v1, v2) \
d.x = (v1.y * v2.z) - (v1.z * v2.y);\ d->x = (v1.y * v2.z) - (v1.z * v2.y);\
d.y = (v1.z * v2.x) - (v1.x * v2.z);\ d->y = (v1.z * v2.x) - (v1.x * v2.z);\
d.z = (v1.x * v2.y) - (v1.y * v2.x) d->z = (v1.x * v2.y) - (v1.y * v2.x)
CROSS(ds_su[i], p, m); CROSS(ds_sup, p, m);
CROSS(ds_sv[i], p, n); CROSS(ds_svp, p, n);
CROSS(ds_sz[i], m, n); CROSS(ds_szp, m, n);
#undef CROSS #undef CROSS
ds_su[i].z *= focallengthf; ds_sup->z *= focallengthf;
ds_sv[i].z *= focallengthf; ds_svp->z *= focallengthf;
ds_sz[i].z *= focallengthf; ds_szp->z *= focallengthf;
// Premultiply the texture vectors with the scale factors // Premultiply the texture vectors with the scale factors
#define SFMULT 65536.f #define SFMULT 65536.f
if (ds_powersoftwo) if (ds_powersoftwo)
{ {
ds_su[i].x *= (SFMULT * (1<<nflatshiftup)); ds_sup->x *= (SFMULT * (1<<nflatshiftup));
ds_su[i].y *= (SFMULT * (1<<nflatshiftup)); ds_sup->y *= (SFMULT * (1<<nflatshiftup));
ds_su[i].z *= (SFMULT * (1<<nflatshiftup)); ds_sup->z *= (SFMULT * (1<<nflatshiftup));
ds_sv[i].x *= (SFMULT * (1<<nflatshiftup)); ds_svp->x *= (SFMULT * (1<<nflatshiftup));
ds_sv[i].y *= (SFMULT * (1<<nflatshiftup)); ds_svp->y *= (SFMULT * (1<<nflatshiftup));
ds_sv[i].z *= (SFMULT * (1<<nflatshiftup)); ds_svp->z *= (SFMULT * (1<<nflatshiftup));
} }
else else
{ {
// Lactozilla: I'm essentially multiplying the vectors by FRACUNIT... // Lactozilla: I'm essentially multiplying the vectors by FRACUNIT...
ds_su[i].x *= SFMULT; ds_sup->x *= SFMULT;
ds_su[i].y *= SFMULT; ds_sup->y *= SFMULT;
ds_su[i].z *= SFMULT; ds_sup->z *= SFMULT;
ds_sv[i].x *= SFMULT; ds_svp->x *= SFMULT;
ds_sv[i].y *= SFMULT; ds_svp->y *= SFMULT;
ds_sv[i].z *= SFMULT; ds_svp->z *= SFMULT;
} }
#undef SFMULT #undef SFMULT
} }
void R_SetTiltedSpan(INT32 span)
{
if (ds_su == NULL)
ds_su = Z_Malloc(sizeof(*ds_su) * vid.height, PU_STATIC, NULL);
if (ds_sv == NULL)
ds_sv = Z_Malloc(sizeof(*ds_sv) * vid.height, PU_STATIC, NULL);
if (ds_sz == NULL)
ds_sz = Z_Malloc(sizeof(*ds_sz) * vid.height, PU_STATIC, NULL);
ds_sup = &ds_su[span];
ds_svp = &ds_sv[span];
ds_szp = &ds_sz[span];
}
static void R_SetSlopePlaneVectors(visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff, float fudge)
{
R_SetTiltedSpan(y);
R_CalculateSlopeVectors(pl->slope, pl->viewx, pl->viewy, pl->viewz, FRACUNIT, FRACUNIT, xoff, yoff, pl->viewangle, pl->plangle, fudge);
}
void R_DrawSinglePlane(visplane_t *pl) void R_DrawSinglePlane(visplane_t *pl)
{ {
levelflat_t *levelflat; levelflat_t *levelflat;
@ -755,6 +788,7 @@ void R_DrawSinglePlane(visplane_t *pl)
ffloor_t *rover; ffloor_t *rover;
int type; int type;
int spanfunctype = BASEDRAWFUNC; int spanfunctype = BASEDRAWFUNC;
angle_t viewang = viewangle;
if (!(pl->minx <= pl->maxx)) if (!(pl->minx <= pl->maxx))
return; return;
@ -766,9 +800,7 @@ void R_DrawSinglePlane(visplane_t *pl)
return; return;
} }
#ifndef NOWATER planeripple.active = false;
itswater = false;
#endif
spanfunc = spanfuncs[BASEDRAWFUNC]; spanfunc = spanfuncs[BASEDRAWFUNC];
if (pl->polyobj) if (pl->polyobj)
@ -779,7 +811,7 @@ void R_DrawSinglePlane(visplane_t *pl)
else if (pl->polyobj->translucency > 0) else if (pl->polyobj->translucency > 0)
{ {
spanfunctype = (pl->polyobj->flags & POF_SPLAT) ? SPANDRAWFUNC_TRANSSPLAT : SPANDRAWFUNC_TRANS; spanfunctype = (pl->polyobj->flags & POF_SPLAT) ? SPANDRAWFUNC_TRANSSPLAT : SPANDRAWFUNC_TRANS;
ds_transmap = transtables + ((pl->polyobj->translucency-1)<<FF_TRANSSHIFT); ds_transmap = R_GetTranslucencyTable(pl->polyobj->translucency);
} }
else if (pl->polyobj->flags & POF_SPLAT) // Opaque, but allow transparent flat pixels else if (pl->polyobj->flags & POF_SPLAT) // Opaque, but allow transparent flat pixels
spanfunctype = SPANDRAWFUNC_SPLAT; spanfunctype = SPANDRAWFUNC_SPLAT;
@ -818,23 +850,23 @@ void R_DrawSinglePlane(visplane_t *pl)
if (pl->ffloor->alpha < 12) if (pl->ffloor->alpha < 12)
return; // Don't even draw it return; // Don't even draw it
else if (pl->ffloor->alpha < 38) else if (pl->ffloor->alpha < 38)
ds_transmap = transtables + ((tr_trans90-1)<<FF_TRANSSHIFT); ds_transmap = R_GetTranslucencyTable(tr_trans90);
else if (pl->ffloor->alpha < 64) else if (pl->ffloor->alpha < 64)
ds_transmap = transtables + ((tr_trans80-1)<<FF_TRANSSHIFT); ds_transmap = R_GetTranslucencyTable(tr_trans80);
else if (pl->ffloor->alpha < 89) else if (pl->ffloor->alpha < 89)
ds_transmap = transtables + ((tr_trans70-1)<<FF_TRANSSHIFT); ds_transmap = R_GetTranslucencyTable(tr_trans70);
else if (pl->ffloor->alpha < 115) else if (pl->ffloor->alpha < 115)
ds_transmap = transtables + ((tr_trans60-1)<<FF_TRANSSHIFT); ds_transmap = R_GetTranslucencyTable(tr_trans60);
else if (pl->ffloor->alpha < 140) else if (pl->ffloor->alpha < 140)
ds_transmap = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT); ds_transmap = R_GetTranslucencyTable(tr_trans50);
else if (pl->ffloor->alpha < 166) else if (pl->ffloor->alpha < 166)
ds_transmap = transtables + ((tr_trans40-1)<<FF_TRANSSHIFT); ds_transmap = R_GetTranslucencyTable(tr_trans40);
else if (pl->ffloor->alpha < 192) else if (pl->ffloor->alpha < 192)
ds_transmap = transtables + ((tr_trans30-1)<<FF_TRANSSHIFT); ds_transmap = R_GetTranslucencyTable(tr_trans30);
else if (pl->ffloor->alpha < 217) else if (pl->ffloor->alpha < 217)
ds_transmap = transtables + ((tr_trans20-1)<<FF_TRANSSHIFT); ds_transmap = R_GetTranslucencyTable(tr_trans20);
else if (pl->ffloor->alpha < 243) else if (pl->ffloor->alpha < 243)
ds_transmap = transtables + ((tr_trans10-1)<<FF_TRANSSHIFT); ds_transmap = R_GetTranslucencyTable(tr_trans10);
else // Opaque, but allow transparent flat pixels else // Opaque, but allow transparent flat pixels
spanfunctype = SPANDRAWFUNC_SPLAT; spanfunctype = SPANDRAWFUNC_SPLAT;
@ -850,12 +882,12 @@ void R_DrawSinglePlane(visplane_t *pl)
} }
else light = (pl->lightlevel >> LIGHTSEGSHIFT); else light = (pl->lightlevel >> LIGHTSEGSHIFT);
#ifndef NOWATER
if (pl->ffloor->flags & FF_RIPPLE) if (pl->ffloor->flags & FF_RIPPLE)
{ {
INT32 top, bottom; INT32 top, bottom;
itswater = true; planeripple.active = true;
if (spanfunctype == SPANDRAWFUNC_TRANS) if (spanfunctype == SPANDRAWFUNC_TRANS)
{ {
spanfunctype = SPANDRAWFUNC_WATER; spanfunctype = SPANDRAWFUNC_WATER;
@ -875,26 +907,11 @@ void R_DrawSinglePlane(visplane_t *pl)
vid.width, vid.width); vid.width, vid.width);
} }
} }
#endif
} }
else else
light = (pl->lightlevel >> LIGHTSEGSHIFT); light = (pl->lightlevel >> LIGHTSEGSHIFT);
} }
if (!pl->slope // Don't mess with angle on slopes! We'll handle this ourselves later
&& viewangle != pl->viewangle+pl->plangle)
{
memset(cachedheight, 0, sizeof (cachedheight));
angle = (pl->viewangle+pl->plangle-ANGLE_90)>>ANGLETOFINESHIFT;
basexscale = FixedDiv(FINECOSINE(angle),centerxfrac);
baseyscale = -FixedDiv(FINESINE(angle),centerxfrac);
viewangle = pl->viewangle+pl->plangle;
}
xoffs = pl->xoffs;
yoffs = pl->yoffs;
planeheight = abs(pl->height - pl->viewz);
currentplane = pl; currentplane = pl;
levelflat = &levelflats[pl->picnum]; levelflat = &levelflats[pl->picnum];
@ -919,6 +936,20 @@ void R_DrawSinglePlane(visplane_t *pl)
R_CheckFlatLength(ds_flatwidth * ds_flatheight); R_CheckFlatLength(ds_flatwidth * ds_flatheight);
} }
if (!pl->slope // Don't mess with angle on slopes! We'll handle this ourselves later
&& viewangle != pl->viewangle+pl->plangle)
{
memset(cachedheight, 0, sizeof (cachedheight));
angle = (pl->viewangle+pl->plangle-ANGLE_90)>>ANGLETOFINESHIFT;
basexscale = FixedDiv(FINECOSINE(angle),centerxfrac);
baseyscale = -FixedDiv(FINESINE(angle),centerxfrac);
viewangle = pl->viewangle+pl->plangle;
}
xoffs = pl->xoffs;
yoffs = pl->yoffs;
planeheight = abs(pl->height - pl->viewz);
if (light >= LIGHTLEVELS) if (light >= LIGHTLEVELS)
light = LIGHTLEVELS-1; light = LIGHTLEVELS-1;
@ -978,50 +1009,41 @@ void R_DrawSinglePlane(visplane_t *pl)
xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1);
yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1);
} }
xoffs = (fixed_t)(xoffs*fudgecanyon); xoffs = (fixed_t)(xoffs*fudgecanyon);
yoffs = (fixed_t)(yoffs/fudgecanyon); yoffs = (fixed_t)(yoffs/fudgecanyon);
} }
ds_sup = &ds_su[0]; if (planeripple.active)
ds_svp = &ds_sv[0];
ds_szp = &ds_sz[0];
#ifndef NOWATER
if (itswater)
{ {
INT32 i;
fixed_t plheight = abs(P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy) - pl->viewz); fixed_t plheight = abs(P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy) - pl->viewz);
fixed_t rxoffs = xoffs;
fixed_t ryoffs = yoffs;
R_PlaneBounds(pl); R_PlaneBounds(pl);
for (i = pl->high; i < pl->low; i++) for (x = pl->high; x < pl->low; x++)
{ {
R_PlaneRipple(pl, i, plheight); R_CalculatePlaneRipple(pl, x, plheight, true);
xoffs = rxoffs + ripple_xfrac; R_SetSlopePlaneVectors(pl, x, (xoffs + planeripple.xfrac), (yoffs + planeripple.yfrac), fudgecanyon);
yoffs = ryoffs + ripple_yfrac;
R_SlopeVectors(pl, i, fudgecanyon);
} }
xoffs = rxoffs;
yoffs = ryoffs;
} }
else else
#endif R_SetSlopePlaneVectors(pl, 0, xoffs, yoffs, fudgecanyon);
R_SlopeVectors(pl, 0, fudgecanyon);
#ifndef NOWATER switch (spanfunctype)
if (itswater && (spanfunctype == SPANDRAWFUNC_WATER)) {
spanfunctype = SPANDRAWFUNC_TILTEDWATER; case SPANDRAWFUNC_WATER:
else spanfunctype = SPANDRAWFUNC_TILTEDWATER;
#endif break;
if (spanfunctype == SPANDRAWFUNC_TRANS) case SPANDRAWFUNC_TRANS:
spanfunctype = SPANDRAWFUNC_TILTEDTRANS; spanfunctype = SPANDRAWFUNC_TILTEDTRANS;
else if (spanfunctype == SPANDRAWFUNC_SPLAT) break;
spanfunctype = SPANDRAWFUNC_TILTEDSPLAT; case SPANDRAWFUNC_SPLAT:
else spanfunctype = SPANDRAWFUNC_TILTEDSPLAT;
spanfunctype = SPANDRAWFUNC_TILTED; break;
default:
spanfunctype = SPANDRAWFUNC_TILTED;
break;
}
planezlight = scalelight[light]; planezlight = scalelight[light];
} }
@ -1081,7 +1103,7 @@ using the palette colors.
if (spanfunc == spanfuncs[BASEDRAWFUNC]) if (spanfunc == spanfuncs[BASEDRAWFUNC])
{ {
INT32 i; INT32 i;
ds_transmap = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT); ds_transmap = R_GetTranslucencyTable(tr_trans50);
spanfunc = spanfuncs[SPANDRAWFUNC_TRANS]; spanfunc = spanfuncs[SPANDRAWFUNC_TRANS];
for (i=0; i<4; i++) for (i=0; i<4; i++)
{ {
@ -1131,6 +1153,8 @@ using the palette colors.
} }
} }
#endif #endif
viewangle = viewang;
} }
void R_PlaneBounds(visplane_t *plane) void R_PlaneBounds(visplane_t *plane)

View file

@ -87,11 +87,18 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop);
void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop); void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop);
void R_PlaneBounds(visplane_t *plane); void R_PlaneBounds(visplane_t *plane);
// Draws a single visplane.
void R_DrawSinglePlane(visplane_t *pl);
void R_CheckFlatLength(size_t size); void R_CheckFlatLength(size_t size);
boolean R_CheckPowersOfTwo(void); boolean R_CheckPowersOfTwo(void);
// Draws a single visplane.
void R_DrawSinglePlane(visplane_t *pl);
// Calculates the slope vectors needed for tilted span drawing.
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);
// Sets the slope vector pointers for the current tilted span.
void R_SetTiltedSpan(INT32 span);
typedef struct planemgr_s typedef struct planemgr_s
{ {
visplane_t *plane; visplane_t *plane;

View file

@ -25,6 +25,7 @@
#include "p_local.h" // Camera... #include "p_local.h" // Camera...
#include "p_slopes.h" #include "p_slopes.h"
#include "console.h" // con_clipviewtop #include "console.h" // con_clipviewtop
#include "taglist.h"
// OPTIMIZE: closed two sided lines as single sided // OPTIMIZE: closed two sided lines as single sided
@ -72,170 +73,6 @@ static lighttable_t **walllights;
static INT16 *maskedtexturecol; static INT16 *maskedtexturecol;
static fixed_t *maskedtextureheight = NULL; static fixed_t *maskedtextureheight = NULL;
// ==========================================================================
// R_Splats Wall Splats Drawer
// ==========================================================================
#ifdef WALLSPLATS
static INT16 last_ceilingclip[MAXVIDWIDTH];
static INT16 last_floorclip[MAXVIDWIDTH];
static void R_DrawSplatColumn(column_t *column)
{
INT32 topscreen, bottomscreen;
fixed_t basetexturemid;
INT32 topdelta, prevdelta = -1;
basetexturemid = dc_texturemid;
for (; column->topdelta != 0xff ;)
{
// calculate unclipped screen coordinates for post
topdelta = column->topdelta;
if (topdelta <= prevdelta)
topdelta += prevdelta;
prevdelta = topdelta;
topscreen = sprtopscreen + spryscale*topdelta;
bottomscreen = topscreen + spryscale*column->length;
dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS;
dc_yh = (bottomscreen-1)>>FRACBITS;
if (dc_yh >= last_floorclip[dc_x])
dc_yh = last_floorclip[dc_x] - 1;
if (dc_yl <= last_ceilingclip[dc_x])
dc_yl = last_ceilingclip[dc_x] + 1;
if (dc_yl <= dc_yh && dl_yh < vid.height && yh > 0)
{
dc_source = (UINT8 *)column + 3;
dc_texturemid = basetexturemid - (topdelta<<FRACBITS);
// Drawn by R_DrawColumn.
colfunc();
}
column = (column_t *)((UINT8 *)column + column->length + 4);
}
dc_texturemid = basetexturemid;
}
static void R_DrawWallSplats(void)
{
wallsplat_t *splat;
seg_t *seg;
angle_t angle, angle1, angle2;
INT32 x1, x2;
size_t pindex;
column_t *col;
patch_t *patch;
fixed_t texturecolumn;
splat = (wallsplat_t *)linedef->splats;
I_Assert(splat != NULL);
seg = ds_p->curline;
// draw all splats from the line that touches the range of the seg
for (; splat; splat = splat->next)
{
angle1 = R_PointToAngle(splat->v1.x, splat->v1.y);
angle2 = R_PointToAngle(splat->v2.x, splat->v2.y);
angle1 = (angle1 - viewangle + ANGLE_90)>>ANGLETOFINESHIFT;
angle2 = (angle2 - viewangle + ANGLE_90)>>ANGLETOFINESHIFT;
// out of the viewangletox lut
/// \todo clip it to the screen
if (angle1 > FINEANGLES/2 || angle2 > FINEANGLES/2)
continue;
x1 = viewangletox[angle1];
x2 = viewangletox[angle2];
if (x1 >= x2)
continue; // does not cross a pixel
// splat is not in this seg range
if (x2 < ds_p->x1 || x1 > ds_p->x2)
continue;
if (x1 < ds_p->x1)
x1 = ds_p->x1;
if (x2 > ds_p->x2)
x2 = ds_p->x2;
if (x2 <= x1)
continue;
// calculate incremental stepping values for texture edges
rw_scalestep = ds_p->scalestep;
spryscale = ds_p->scale1 + (x1 - ds_p->x1)*rw_scalestep;
mfloorclip = floorclip;
mceilingclip = ceilingclip;
patch = W_CachePatchNum(splat->patch, PU_PATCH);
dc_texturemid = splat->top + (SHORT(patch->height)<<(FRACBITS-1)) - viewz;
if (splat->yoffset)
dc_texturemid += *splat->yoffset;
sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
// set drawing mode
switch (splat->flags & SPLATDRAWMODE_MASK)
{
case SPLATDRAWMODE_OPAQUE:
colfunc = colfuncs[BASEDRAWFUNC];
break;
case SPLATDRAWMODE_TRANS:
if (!cv_translucency.value)
colfunc = colfuncs[BASEDRAWFUNC];
else
{
dc_transmap = transtables + ((tr_trans50 - 1)<<FF_TRANSSHIFT);
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
}
break;
case SPLATDRAWMODE_SHADE:
colfunc = colfuncs[COLDRAWFUNC_SHADE];
break;
}
dc_texheight = 0;
// draw the columns
for (dc_x = x1; dc_x <= x2; dc_x++, spryscale += rw_scalestep)
{
pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE - 1;
dc_colormap = walllights[pindex];
if (frontsector->extra_colormap)
dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
dc_iscale = 0xffffffffu / (unsigned)spryscale;
// find column of patch, from perspective
angle = (rw_centerangle + xtoviewangle[dc_x])>>ANGLETOFINESHIFT;
texturecolumn = rw_offset2 - splat->offset
- FixedMul(FINETANGENT(angle), rw_distance);
// FIXME!
texturecolumn >>= FRACBITS;
if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
continue;
// draw the texture
col = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
R_DrawSplatColumn(col);
}
} // next splat
colfunc = colfuncs[BASEDRAWFUNC];
}
#endif //WALLSPLATS
// ========================================================================== // ==========================================================================
// R_RenderMaskedSegRange // R_RenderMaskedSegRange
// ========================================================================== // ==========================================================================
@ -320,7 +157,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
if (ldef->alpha > 0 && ldef->alpha < FRACUNIT) if (ldef->alpha > 0 && ldef->alpha < FRACUNIT)
{ {
dc_transmap = transtables + ((R_GetLinedefTransTable(ldef->alpha) - 1) << FF_TRANSSHIFT); dc_transmap = R_GetTranslucencyTable(R_GetLinedefTransTable(ldef->alpha));
colfunc = colfuncs[COLDRAWFUNC_FUZZY]; colfunc = colfuncs[COLDRAWFUNC_FUZZY];
} }
@ -338,7 +175,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
if (curline->polyseg->translucency >= NUMTRANSMAPS) if (curline->polyseg->translucency >= NUMTRANSMAPS)
return; return;
dc_transmap = transtables + ((curline->polyseg->translucency-1)<<FF_TRANSSHIFT); dc_transmap = R_GetTranslucencyTable(curline->polyseg->translucency);
colfunc = colfuncs[COLDRAWFUNC_FUZZY]; colfunc = colfuncs[COLDRAWFUNC_FUZZY];
} }
@ -766,23 +603,23 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
if (pfloor->alpha < 12) if (pfloor->alpha < 12)
return; // Don't even draw it return; // Don't even draw it
else if (pfloor->alpha < 38) else if (pfloor->alpha < 38)
dc_transmap = transtables + ((tr_trans90-1)<<FF_TRANSSHIFT); dc_transmap = R_GetTranslucencyTable(tr_trans90);
else if (pfloor->alpha < 64) else if (pfloor->alpha < 64)
dc_transmap = transtables + ((tr_trans80-1)<<FF_TRANSSHIFT); dc_transmap = R_GetTranslucencyTable(tr_trans80);
else if (pfloor->alpha < 89) else if (pfloor->alpha < 89)
dc_transmap = transtables + ((tr_trans70-1)<<FF_TRANSSHIFT); dc_transmap = R_GetTranslucencyTable(tr_trans70);
else if (pfloor->alpha < 115) else if (pfloor->alpha < 115)
dc_transmap = transtables + ((tr_trans60-1)<<FF_TRANSSHIFT); dc_transmap = R_GetTranslucencyTable(tr_trans60);
else if (pfloor->alpha < 140) else if (pfloor->alpha < 140)
dc_transmap = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT); dc_transmap = R_GetTranslucencyTable(tr_trans50);
else if (pfloor->alpha < 166) else if (pfloor->alpha < 166)
dc_transmap = transtables + ((tr_trans40-1)<<FF_TRANSSHIFT); dc_transmap = R_GetTranslucencyTable(tr_trans40);
else if (pfloor->alpha < 192) else if (pfloor->alpha < 192)
dc_transmap = transtables + ((tr_trans30-1)<<FF_TRANSSHIFT); dc_transmap = R_GetTranslucencyTable(tr_trans30);
else if (pfloor->alpha < 217) else if (pfloor->alpha < 217)
dc_transmap = transtables + ((tr_trans20-1)<<FF_TRANSSHIFT); dc_transmap = R_GetTranslucencyTable(tr_trans20);
else if (pfloor->alpha < 243) else if (pfloor->alpha < 243)
dc_transmap = transtables + ((tr_trans10-1)<<FF_TRANSSHIFT); dc_transmap = R_GetTranslucencyTable(tr_trans10);
else else
fuzzy = false; // Opaque fuzzy = false; // Opaque
@ -2067,7 +1904,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|| backsector->floorlightsec != frontsector->floorlightsec || backsector->floorlightsec != frontsector->floorlightsec
//SoM: 4/3/2000: Check for colormaps //SoM: 4/3/2000: Check for colormaps
|| frontsector->extra_colormap != backsector->extra_colormap || frontsector->extra_colormap != backsector->extra_colormap
|| (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag)) || (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags)))
{ {
markfloor = true; markfloor = true;
} }
@ -2098,7 +1935,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|| backsector->ceilinglightsec != frontsector->ceilinglightsec || backsector->ceilinglightsec != frontsector->ceilinglightsec
//SoM: 4/3/2000: Check for colormaps //SoM: 4/3/2000: Check for colormaps
|| frontsector->extra_colormap != backsector->extra_colormap || frontsector->extra_colormap != backsector->extra_colormap
|| (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag)) || (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags)))
{ {
markceiling = true; markceiling = true;
} }
@ -2188,7 +2025,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
rw_bottomtexturemid += sidedef->rowoffset; rw_bottomtexturemid += sidedef->rowoffset;
// allocate space for masked texture tables // allocate space for masked texture tables
if (frontsector && backsector && frontsector->tag != backsector->tag && (backsector->ffloors || frontsector->ffloors)) if (frontsector && backsector && !Tag_Compare(&frontsector->tags, &backsector->tags) && (backsector->ffloors || frontsector->ffloors))
{ {
ffloor_t *rover; ffloor_t *rover;
ffloor_t *r2; ffloor_t *r2;
@ -2230,6 +2067,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
for (r2 = frontsector->ffloors; r2; r2 = r2->next) for (r2 = frontsector->ffloors; r2; r2 = r2->next)
{ {
if (r2->master == rover->master) // Skip if same control line.
break;
if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES)) if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES))
continue; continue;
@ -2285,6 +2125,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
for (r2 = backsector->ffloors; r2; r2 = r2->next) for (r2 = backsector->ffloors; r2; r2 = r2->next)
{ {
if (r2->master == rover->master) // Skip if same control line.
break;
if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES)) if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES))
continue; continue;
@ -2880,20 +2723,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
rw_tsilheight = &(ds_p->tsilheight); rw_tsilheight = &(ds_p->tsilheight);
rw_bsilheight = &(ds_p->bsilheight); rw_bsilheight = &(ds_p->bsilheight);
#ifdef WALLSPLATS R_RenderSegLoop();
if (linedef->splats && cv_splats.value)
{
// Isn't a bit wasteful to copy the ENTIRE array for every drawseg?
M_Memcpy(last_ceilingclip + ds_p->x1, ceilingclip + ds_p->x1,
sizeof (INT16) * (ds_p->x2 - ds_p->x1 + 1));
M_Memcpy(last_floorclip + ds_p->x1, floorclip + ds_p->x1,
sizeof (INT16) * (ds_p->x2 - ds_p->x1 + 1));
R_RenderSegLoop();
R_DrawWallSplats();
}
else
#endif
R_RenderSegLoop();
colfunc = colfuncs[BASEDRAWFUNC]; colfunc = colfuncs[BASEDRAWFUNC];
if (portalline) // if curline is a portal, set portalrender for drawseg if (portalline) // if curline is a portal, set portalrender for drawseg

View file

@ -17,6 +17,7 @@
#include "info.h" #include "info.h"
#include "sounds.h" #include "sounds.h"
#include "d_player.h" // skinflags #include "d_player.h" // skinflags
#include "r_patch.h"
#include "r_picformats.h" // spriteinfo_t #include "r_picformats.h" // spriteinfo_t
#include "r_defs.h" // spritedef_t #include "r_defs.h" // spritedef_t

File diff suppressed because it is too large Load diff

View file

@ -14,68 +14,35 @@
#define __R_SPLATS_H__ #define __R_SPLATS_H__
#include "r_defs.h" #include "r_defs.h"
#include "r_things.h"
//#define WALLSPLATS // comment this out to compile without splat effects
/*#ifdef USEASM
#define FLOORSPLATS
#endif*/
#define MAXLEVELSPLATS 1024
// splat flags
#define SPLATDRAWMODE_MASK 0x03 // mask to get drawmode from flags
#define SPLATDRAWMODE_OPAQUE 0x00
#define SPLATDRAWMODE_SHADE 0x01
#define SPLATDRAWMODE_TRANS 0x02
// ========================================================================== // ==========================================================================
// DEFINITIONS // DEFINITIONS
// ========================================================================== // ==========================================================================
// WALL SPLATS are patches drawn on top of wall segs struct rastery_s
typedef struct wallsplat_s
{ {
lumpnum_t patch; // lump id. fixed_t minx, maxx; // for each raster line starting at line 0
vertex_t v1, v2; // vertices along the linedef fixed_t tx1, ty1; // start points in texture at this line
fixed_t top; fixed_t tx2, ty2; // end points in texture at this line
fixed_t offset; // offset in columns<<FRACBITS from start of linedef to start of splat };
INT32 flags; extern struct rastery_s *prastertab; // for ASM code
fixed_t *yoffset;
line_t *line; // the parent line of the splat seg
struct wallsplat_s *next;
} wallsplat_t;
// FLOOR SPLATS are pic_t (raw horizontally stored) drawn on top of the floor or ceiling
typedef struct floorsplat_s typedef struct floorsplat_s
{ {
lumpnum_t pic; // a pic_t lump id UINT16 *pic;
INT32 flags; INT32 width, height;
INT32 size; // 64, 128, 256, etc. fixed_t scale, xscale, yscale;
vertex_t verts[4]; // (x,y) as viewn from above on map angle_t angle;
fixed_t z; // z (height) is constant for all the floorsplats boolean tilted; // Uses the tilted drawer
subsector_t *subsector; // the parent subsector pslope_t slope;
vector3_t verts[4]; // (x,y,z) as viewed from above on map
fixed_t x, y, z; // position
mobj_t *mobj; // Mobj it is tied to mobj_t *mobj; // Mobj it is tied to
struct floorsplat_s *next;
struct floorsplat_s *nextvis;
} floorsplat_t; } floorsplat_t;
// p_setup.c void R_DrawFloorSprite(vissprite_t *spr);
fixed_t P_SegLength(seg_t *seg); void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis);
// call at P_SetupLevel()
void R_ClearLevelSplats(void);
#ifdef WALLSPLATS
void R_AddWallSplat(line_t *wallline, INT16 sectorside, const char *patchname, fixed_t top,
fixed_t wallfrac, INT32 flags);
#endif
#ifdef FLOORSPLATS
void R_AddFloorSplat(subsector_t *subsec, mobj_t *mobj, const char *picname, fixed_t x, fixed_t y, fixed_t z,
INT32 flags);
#endif
void R_ClearVisibleFloorSplats(void);
void R_AddVisibleFloorSplats(subsector_t *subsec);
void R_DrawVisibleFloorSplats(void);
#endif /*__R_SPLATS_H__*/ #endif /*__R_SPLATS_H__*/

View file

@ -20,6 +20,7 @@
#include "m_misc.h" #include "m_misc.h"
#include "r_data.h" #include "r_data.h"
#include "r_textures.h" #include "r_textures.h"
#include "r_patch.h"
#include "r_picformats.h" #include "r_picformats.h"
#include "w_wad.h" #include "w_wad.h"
#include "z_zone.h" #include "z_zone.h"
@ -33,7 +34,7 @@
#endif #endif
#ifdef HWRENDER #ifdef HWRENDER
#include "hardware/hw_main.h" // HWR_LoadTextures #include "hardware/hw_glob.h" // HWR_LoadMapTextures
#endif #endif
#include <errno.h> #include <errno.h>
@ -266,7 +267,7 @@ UINT8 *R_GenerateTexture(size_t texnum)
UINT8 *blocktex; UINT8 *blocktex;
texture_t *texture; texture_t *texture;
texpatch_t *patch; texpatch_t *patch;
patch_t *realpatch; softwarepatch_t *realpatch;
UINT8 *pdata; UINT8 *pdata;
int x, x1, x2, i, width, height; int x, x1, x2, i, width, height;
size_t blocksize; size_t blocksize;
@ -296,7 +297,7 @@ UINT8 *R_GenerateTexture(size_t texnum)
lumpnum = patch->lump; lumpnum = patch->lump;
lumplength = W_LumpLengthPwad(wadnum, lumpnum); lumplength = W_LumpLengthPwad(wadnum, lumpnum);
pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
realpatch = (patch_t *)pdata; realpatch = (softwarepatch_t *)pdata;
#ifndef NO_PNG_LUMPS #ifndef NO_PNG_LUMPS
if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength)) if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength))
@ -392,17 +393,17 @@ UINT8 *R_GenerateTexture(size_t texnum)
lumpnum = patch->lump; lumpnum = patch->lump;
pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
lumplength = W_LumpLengthPwad(wadnum, lumpnum); lumplength = W_LumpLengthPwad(wadnum, lumpnum);
realpatch = (patch_t *)pdata; realpatch = (softwarepatch_t *)pdata;
dealloc = true; dealloc = true;
#ifndef NO_PNG_LUMPS #ifndef NO_PNG_LUMPS
if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength)) if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength))
realpatch = (patch_t *)Picture_PNGConvert((UINT8 *)realpatch, PICFMT_PATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0); realpatch = (softwarepatch_t *)Picture_PNGConvert((UINT8 *)realpatch, PICFMT_DOOMPATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0);
else else
#endif #endif
#ifdef WALLFLATS #ifdef WALLFLATS
if (texture->type == TEXTURETYPE_FLAT) if (texture->type == TEXTURETYPE_FLAT)
realpatch = (patch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_PATCH, 0, NULL, texture->width, texture->height, 0, 0, 0); realpatch = (softwarepatch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_DOOMPATCH, 0, NULL, texture->width, texture->height, 0, 0, 0);
else else
#endif #endif
{ {
@ -597,13 +598,13 @@ void *R_GetLevelFlat(levelflat_t *levelflat)
{ {
UINT8 *converted; UINT8 *converted;
size_t size; size_t size;
patch_t *patch = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE); softwarepatch_t *patch = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE);
levelflat->width = ds_flatwidth = SHORT(patch->width); levelflat->width = ds_flatwidth = SHORT(patch->width);
levelflat->height = ds_flatheight = SHORT(patch->height); levelflat->height = ds_flatheight = SHORT(patch->height);
levelflat->picture = Z_Malloc(levelflat->width * levelflat->height, PU_LEVEL, NULL); levelflat->picture = Z_Malloc(levelflat->width * levelflat->height, PU_LEVEL, NULL);
converted = Picture_FlatConvert(PICFMT_PATCH, patch, PICFMT_FLAT, 0, &size, levelflat->width, levelflat->height, patch->topoffset, patch->leftoffset, 0); converted = Picture_FlatConvert(PICFMT_DOOMPATCH, patch, PICFMT_FLAT, 0, &size, levelflat->width, levelflat->height, patch->topoffset, patch->leftoffset, 0);
M_Memcpy(levelflat->picture, converted, size); M_Memcpy(levelflat->picture, converted, size);
Z_Free(converted); Z_Free(converted);
} }
@ -839,7 +840,7 @@ Rloadtextures (INT32 i, INT32 w)
UINT16 j; UINT16 j;
UINT16 texstart, texend, texturesLumpPos; UINT16 texstart, texend, texturesLumpPos;
texture_t *texture; texture_t *texture;
patch_t *patchlump; softwarepatch_t *patchlump;
texpatch_t *patch; texpatch_t *patch;
// Get the lump numbers for the markers in the WAD, if they exist. // Get the lump numbers for the markers in the WAD, if they exist.
@ -1062,7 +1063,7 @@ void R_LoadTextures(void)
#ifdef HWRENDER #ifdef HWRENDER
if (rendermode == render_opengl) if (rendermode == render_opengl)
HWR_LoadTextures(numtextures); HWR_LoadMapTextures(numtextures);
#endif #endif
} }

File diff suppressed because it is too large Load diff

View file

@ -15,6 +15,7 @@
#define __R_THINGS__ #define __R_THINGS__
#include "r_plane.h" #include "r_plane.h"
#include "r_patch.h"
#include "r_picformats.h" #include "r_picformats.h"
#include "r_portal.h" #include "r_portal.h"
#include "r_defs.h" #include "r_defs.h"
@ -64,7 +65,6 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope);
void R_AddSprites(sector_t *sec, INT32 lightlevel); void R_AddSprites(sector_t *sec, INT32 lightlevel);
void R_InitSprites(void); void R_InitSprites(void);
void R_ClearSprites(void); void R_ClearSprites(void);
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal);
boolean R_ThingVisible (mobj_t *thing); boolean R_ThingVisible (mobj_t *thing);
@ -75,6 +75,15 @@ boolean R_ThingVisibleWithinDist (mobj_t *thing,
boolean R_PrecipThingVisible (precipmobj_t *precipthing, boolean R_PrecipThingVisible (precipmobj_t *precipthing,
fixed_t precip_draw_dist); fixed_t precip_draw_dist);
boolean R_ThingHorizontallyFlipped (mobj_t *thing);
boolean R_ThingVerticallyFlipped (mobj_t *thing);
boolean R_ThingIsPaperSprite (mobj_t *thing);
boolean R_ThingIsFloorSprite (mobj_t *thing);
boolean R_ThingIsFullBright (mobj_t *thing);
boolean R_ThingIsFullDark (mobj_t *thing);
// -------------- // --------------
// MASKED DRAWING // MASKED DRAWING
// -------------- // --------------
@ -107,19 +116,23 @@ void R_DrawMasked(maskcount_t* masks, UINT8 nummasks);
typedef enum typedef enum
{ {
// actual cuts // actual cuts
SC_NONE = 0, SC_NONE = 0,
SC_TOP = 1, SC_TOP = 1,
SC_BOTTOM = 1<<1, SC_BOTTOM = 1<<1,
// other flags // other flags
SC_PRECIP = 1<<2, SC_PRECIP = 1<<2,
SC_LINKDRAW = 1<<3, SC_LINKDRAW = 1<<3,
SC_FULLBRIGHT = 1<<4, SC_FULLBRIGHT = 1<<4,
SC_VFLIP = 1<<5, SC_FULLDARK = 1<<5,
SC_ISSCALED = 1<<6, SC_VFLIP = 1<<6,
SC_SHADOW = 1<<7, SC_ISSCALED = 1<<7,
SC_ISROTATED = 1<<8,
SC_SHADOW = 1<<9,
SC_SHEAR = 1<<10,
SC_SPLAT = 1<<11,
// masks // masks
SC_CUTMASK = SC_TOP|SC_BOTTOM, SC_CUTMASK = SC_TOP|SC_BOTTOM,
SC_FLAGMASK = ~SC_CUTMASK SC_FLAGMASK = ~SC_CUTMASK
} spritecut_e; } spritecut_e;
// A vissprite_t is a thing that will be drawn during a refresh, // A vissprite_t is a thing that will be drawn during a refresh,
@ -138,11 +151,12 @@ typedef struct vissprite_s
INT32 x1, x2; INT32 x1, x2;
fixed_t gx, gy; // for line side calculation fixed_t gx, gy; // for line side calculation
fixed_t gz, gzt; // global bottom/top for silhouette clipping fixed_t gz, gzt; // global bottom/top for silhouette clipping and sorting with 3D floors
fixed_t pz, pzt; // physical bottom/top for sorting with 3D floors
fixed_t startfrac; // horizontal position of x1 fixed_t startfrac; // horizontal position of x1
fixed_t scale, sortscale; // sortscale only differs from scale for paper sprites and MF2_LINKDRAW fixed_t scale;
fixed_t sortscale; // sortscale only differs from scale for paper sprites, floor sprites, and MF2_LINKDRAW
fixed_t sortsplat; // the sortscale from behind the floor sprite
fixed_t scalestep; // only for paper sprites, 0 otherwise fixed_t scalestep; // only for paper sprites, 0 otherwise
fixed_t paperoffset, paperdistance; // for paper sprites, offset/dist relative to the angle fixed_t paperoffset, paperdistance; // for paper sprites, offset/dist relative to the angle
fixed_t xiscale; // negative if flipped fixed_t xiscale; // negative if flipped
@ -171,11 +185,17 @@ typedef struct vissprite_s
fixed_t xscale; fixed_t xscale;
// Precalculated top and bottom screen coords for the sprite. // Precalculated top and bottom screen coords for the sprite.
fixed_t thingheight; // The actual height of the thing (for 3D floors)
sector_t *sector; // The sector containing the thing. sector_t *sector; // The sector containing the thing.
INT16 sz, szt; INT16 sz, szt;
spritecut_e cut; spritecut_e cut;
UINT32 renderflags;
UINT8 rotateflags;
fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset;
fixed_t shadowscale;
INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH]; INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH];
@ -184,6 +204,12 @@ typedef struct vissprite_s
extern UINT32 visspritecount; extern UINT32 visspritecount;
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal);
void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, portal_t* portal);
boolean R_SpriteIsFlashing(vissprite_t *vis);
UINT8 *R_GetSpriteTranslation(vissprite_t *vis);
// ---------- // ----------
// DRAW NODES // DRAW NODES
// ---------- // ----------

View file

@ -29,10 +29,7 @@
#include "fastcmp.h" #include "fastcmp.h"
#include "m_misc.h" // for tunes command #include "m_misc.h" // for tunes command
#include "m_cond.h" // for conditionsets #include "m_cond.h" // for conditionsets
#ifdef HAVE_LUA_MUSICPLUS
#include "lua_hook.h" // MusicChange hook #include "lua_hook.h" // MusicChange hook
#endif
#ifdef HW3SOUND #ifdef HW3SOUND
// 3D Sound Interface // 3D Sound Interface
@ -2272,10 +2269,8 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32
return; return;
strncpy(newmusic, mmusic, 7); strncpy(newmusic, mmusic, 7);
#ifdef HAVE_LUA_MUSICPLUS if (LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms))
if(LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms))
return; return;
#endif
newmusic[6] = 0; newmusic[6] = 0;
// No Music (empty string) // No Music (empty string)

View file

@ -28,6 +28,7 @@
#include "d_main.h" #include "d_main.h"
#include "d_clisrv.h" #include "d_clisrv.h"
#include "f_finale.h" #include "f_finale.h"
#include "y_inter.h" // usebuffer
#include "i_sound.h" // closed captions #include "i_sound.h" // closed captions
#include "s_sound.h" // ditto #include "s_sound.h" // ditto
#include "g_game.h" // ditto #include "g_game.h" // ditto
@ -63,14 +64,14 @@ consvar_t cv_scr_height = CVAR_INIT ("scr_height", "800", CV_SAVE, CV_Unsigned,
consvar_t cv_scr_depth = CVAR_INIT ("scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL); consvar_t cv_scr_depth = CVAR_INIT ("scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL);
consvar_t cv_renderview = CVAR_INIT ("renderview", "On", 0, CV_OnOff, NULL); consvar_t cv_renderview = CVAR_INIT ("renderview", "On", 0, CV_OnOff, NULL);
static void SCR_ActuallyChangeRenderer(void); CV_PossibleValue_t cv_renderer_t[] = {
static CV_PossibleValue_t cv_renderer_t[] = {
{1, "Software"}, {1, "Software"},
#ifdef HWRENDER #ifdef HWRENDER
{2, "OpenGL"}, {2, "OpenGL"},
#endif #endif
{0, NULL} {0, NULL}
}; };
consvar_t cv_renderer = CVAR_INIT ("renderer", "Software", CV_SAVE|CV_NOLUA|CV_CALL, cv_renderer_t, SCR_ChangeRenderer); consvar_t cv_renderer = CVAR_INIT ("renderer", "Software", CV_SAVE|CV_NOLUA|CV_CALL, cv_renderer_t, SCR_ChangeRenderer);
static void SCR_ChangeFullscreen(void); static void SCR_ChangeFullscreen(void);
@ -121,34 +122,34 @@ void SCR_SetDrawFuncs(void)
colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn_8; colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn_8;
spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_8; spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_8;
spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat_8;
spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_8;
spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan_8;
#ifndef NOWATER
spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_8;
#endif
spanfuncs[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_8; spanfuncs[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_8;
spanfuncs[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedTranslucentSpan_8; spanfuncs[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedTranslucentSpan_8;
#ifndef NOWATER spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat_8;
spanfuncs[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_8; spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_8;
#endif
spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_8; spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_8;
spanfuncs[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_8;
spanfuncs[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_8;
spanfuncs[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_8;
spanfuncs[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_8;
spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_8;
spanfuncs[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_8;
spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan_8;
// Lactozilla: Non-powers-of-two // Lactozilla: Non-powers-of-two
spanfuncs_npo2[BASEDRAWFUNC] = R_DrawSpan_NPO2_8; spanfuncs_npo2[BASEDRAWFUNC] = R_DrawSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_SPLAT] = R_DrawSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_FOG] = NULL; // Not needed
#ifndef NOWATER
spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_NPO2_8;
#endif
spanfuncs_npo2[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedTranslucentSpan_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedTranslucentSpan_NPO2_8;
#ifndef NOWATER spanfuncs_npo2[SPANDRAWFUNC_SPLAT] = R_DrawSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_NPO2_8;
#endif
spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_FOG] = NULL; // Not needed
#ifdef RUSEASM #ifdef RUSEASM
if (R_ASM) if (R_ASM)
@ -202,14 +203,19 @@ void SCR_SetMode(void)
// Lactozilla: Renderer switching // Lactozilla: Renderer switching
if (setrenderneeded) if (setrenderneeded)
{ {
Z_PreparePatchFlush(); // stop recording movies (APNG only)
needpatchflush = true; if (setrenderneeded && (moviemode == MM_APNG))
needpatchrecache = true; M_StopMovie();
VID_CheckRenderer();
// VID_SetMode will call VID_CheckRenderer itself,
// so no need to do this in here.
if (!setmodeneeded) if (!setmodeneeded)
VID_SetMode(vid.modenum); VID_CheckRenderer();
vid.recalc = 1;
} }
// Set the video mode in the video interface.
if (setmodeneeded) if (setmodeneeded)
VID_SetMode(--setmodeneeded); VID_SetMode(--setmodeneeded);
@ -279,34 +285,9 @@ void SCR_Startup(void)
vid.modenum = 0; vid.modenum = 0;
vid.dupx = vid.width / BASEVIDWIDTH;
vid.dupy = vid.height / BASEVIDHEIGHT;
vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT);
vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT);
#ifdef HWRENDER
if (rendermode != render_opengl && rendermode != render_none) // This was just placing it incorrectly at non aspect correct resolutions in opengl
#endif
vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy);
vid.meddupx = (UINT8)(vid.dupx >> 1) + 1;
vid.meddupy = (UINT8)(vid.dupy >> 1) + 1;
#ifdef HWRENDER
vid.fmeddupx = vid.meddupx*FRACUNIT;
vid.fmeddupy = vid.meddupy*FRACUNIT;
#endif
vid.smalldupx = (UINT8)(vid.dupx / 3) + 1;
vid.smalldupy = (UINT8)(vid.dupy / 3) + 1;
#ifdef HWRENDER
vid.fsmalldupx = vid.smalldupx*FRACUNIT;
vid.fsmalldupy = vid.smalldupy*FRACUNIT;
#endif
vid.baseratio = FRACUNIT;
V_Init(); V_Init();
V_Recalc();
CV_RegisterVar(&cv_ticrate); CV_RegisterVar(&cv_ticrate);
CV_RegisterVar(&cv_constextsize); CV_RegisterVar(&cv_constextsize);
@ -323,38 +304,7 @@ void SCR_Recalc(void)
// bytes per pixel quick access // bytes per pixel quick access
scr_bpp = vid.bpp; scr_bpp = vid.bpp;
// scale 1,2,3 times in x and y the patches for the menus and overlays... V_Recalc();
// calculated once and for all, used by routines in v_video.c
vid.dupx = vid.width / BASEVIDWIDTH;
vid.dupy = vid.height / BASEVIDHEIGHT;
vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT);
vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT);
#ifdef HWRENDER
//if (rendermode != render_opengl && rendermode != render_none) // This was just placing it incorrectly at non aspect correct resolutions in opengl
// 13/11/18:
// The above is no longer necessary, since we want OpenGL to be just like software now
// -- Monster Iestyn
#endif
vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy);
//vid.baseratio = FixedDiv(vid.height << FRACBITS, BASEVIDHEIGHT << FRACBITS);
vid.baseratio = FRACUNIT;
vid.meddupx = (UINT8)(vid.dupx >> 1) + 1;
vid.meddupy = (UINT8)(vid.dupy >> 1) + 1;
#ifdef HWRENDER
vid.fmeddupx = vid.meddupx*FRACUNIT;
vid.fmeddupy = vid.meddupy*FRACUNIT;
#endif
vid.smalldupx = (UINT8)(vid.dupx / 3) + 1;
vid.smalldupy = (UINT8)(vid.dupy / 3) + 1;
#ifdef HWRENDER
vid.fsmalldupx = vid.smalldupx*FRACUNIT;
vid.fsmalldupy = vid.smalldupy*FRACUNIT;
#endif
// toggle off (then back on) the automap because some screensize-dependent values will // toggle off (then back on) the automap because some screensize-dependent values will
// be calculated next time the automap is activated. // be calculated next time the automap is activated.
@ -374,6 +324,12 @@ void SCR_Recalc(void)
// vid.recalc lasts only for the next refresh... // vid.recalc lasts only for the next refresh...
con_recalc = true; con_recalc = true;
am_recalc = true; am_recalc = true;
#ifdef HWRENDER
// Shoot! The screen texture was flushed!
if ((rendermode == render_opengl) && (gamestate == GS_INTERMISSION))
usebuffer = false;
#endif
} }
// Check for screen cmd-line parms: to force a resolution. // Check for screen cmd-line parms: to force a resolution.
@ -411,7 +367,16 @@ void SCR_CheckDefaultMode(void)
setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1; setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1;
} }
SCR_ActuallyChangeRenderer(); if (cv_renderer.value != (signed)rendermode)
{
if (chosenrendermode == render_none) // nothing set at command line
SCR_ChangeRenderer();
else
{
// Set cv_renderer to the current render mode
CV_StealthSetValue(&cv_renderer, rendermode);
}
}
} }
// sets the modenum as the new default video mode to be saved in the config file // sets the modenum as the new default video mode to be saved in the config file
@ -441,64 +406,27 @@ void SCR_ChangeFullscreen(void)
#endif #endif
} }
static int target_renderer = 0; void SCR_ChangeRenderer(void)
void SCR_ActuallyChangeRenderer(void)
{ {
setrenderneeded = target_renderer; if (chosenrendermode != render_none
|| (signed)rendermode == cv_renderer.value)
return;
#ifdef HWRENDER #ifdef HWRENDER
// Well, it didn't even load anyway. // Check if OpenGL loaded successfully (or wasn't disabled) before switching to it.
if ((vid_opengl_state == -1) && (setrenderneeded == render_opengl)) if ((vid.glstate == VID_GL_LIBRARY_ERROR)
&& (cv_renderer.value == render_opengl))
{ {
if (M_CheckParm("-nogl")) if (M_CheckParm("-nogl"))
CONS_Alert(CONS_ERROR, "OpenGL rendering was disabled!\n"); CONS_Alert(CONS_ERROR, "OpenGL rendering was disabled!\n");
else else
CONS_Alert(CONS_ERROR, "OpenGL never loaded\n"); CONS_Alert(CONS_ERROR, "OpenGL never loaded\n");
setrenderneeded = 0;
return; return;
} }
#endif #endif
// setting the same renderer twice WILL crash your game, so let's not, please // Set the new render mode
if (rendermode == setrenderneeded) setrenderneeded = cv_renderer.value;
setrenderneeded = 0;
}
// Lactozilla: Renderer switching
void SCR_ChangeRenderer(void)
{
setrenderneeded = 0;
if (con_startup)
{
target_renderer = cv_renderer.value;
#ifdef HWRENDER
if (M_CheckParm("-opengl") && (vid_opengl_state == 1))
target_renderer = rendermode = render_opengl;
else
#endif
if (M_CheckParm("-software"))
target_renderer = rendermode = render_soft;
// set cv_renderer back
SCR_ChangeRendererCVars(rendermode);
return;
}
if (cv_renderer.value == 1)
target_renderer = render_soft;
else if (cv_renderer.value == 2)
target_renderer = render_opengl;
SCR_ActuallyChangeRenderer();
}
void SCR_ChangeRendererCVars(INT32 mode)
{
// set cv_renderer back
if (mode == render_soft)
CV_StealthSetValue(&cv_renderer, 1);
else if (mode == render_opengl)
CV_StealthSetValue(&cv_renderer, 2);
} }
boolean SCR_IsAspectCorrect(INT32 width, INT32 height) boolean SCR_IsAspectCorrect(INT32 width, INT32 height)

View file

@ -72,10 +72,16 @@ typedef struct viddef_s
#ifdef HWRENDER #ifdef HWRENDER
INT32/*fixed_t*/ fsmalldupx, fsmalldupy; INT32/*fixed_t*/ fsmalldupx, fsmalldupy;
INT32/*fixed_t*/ fmeddupx, fmeddupy; INT32/*fixed_t*/ fmeddupx, fmeddupy;
INT32 glstate;
#endif #endif
} viddef_t; } viddef_t;
#define VIDWIDTH vid.width
#define VIDHEIGHT vid.height enum
{
VID_GL_LIBRARY_NOTLOADED = 0,
VID_GL_LIBRARY_LOADED = 1,
VID_GL_LIBRARY_ERROR = -1,
};
// internal additional info for vesa modes only // internal additional info for vesa modes only
typedef struct typedef struct
@ -134,18 +140,22 @@ enum
{ {
SPANDRAWFUNC_BASE = BASEDRAWFUNC, SPANDRAWFUNC_BASE = BASEDRAWFUNC,
SPANDRAWFUNC_TRANS, SPANDRAWFUNC_TRANS,
SPANDRAWFUNC_SPLAT,
SPANDRAWFUNC_TRANSSPLAT,
SPANDRAWFUNC_FOG,
#ifndef NOWATER
SPANDRAWFUNC_WATER,
#endif
SPANDRAWFUNC_TILTED, SPANDRAWFUNC_TILTED,
SPANDRAWFUNC_TILTEDTRANS, SPANDRAWFUNC_TILTEDTRANS,
SPANDRAWFUNC_SPLAT,
SPANDRAWFUNC_TRANSSPLAT,
SPANDRAWFUNC_TILTEDSPLAT, SPANDRAWFUNC_TILTEDSPLAT,
#ifndef NOWATER
SPANDRAWFUNC_SPRITE,
SPANDRAWFUNC_TRANSSPRITE,
SPANDRAWFUNC_TILTEDSPRITE,
SPANDRAWFUNC_TILTEDTRANSSPRITE,
SPANDRAWFUNC_WATER,
SPANDRAWFUNC_TILTEDWATER, SPANDRAWFUNC_TILTEDWATER,
#endif
SPANDRAWFUNC_FOG,
SPANDRAWFUNC_MAX SPANDRAWFUNC_MAX
}; };
@ -170,10 +180,11 @@ extern boolean R_SSE2;
// ---------------- // ----------------
extern viddef_t vid; extern viddef_t vid;
extern INT32 setmodeneeded; // mode number to set if needed, or 0 extern INT32 setmodeneeded; // mode number to set if needed, or 0
extern UINT8 setrenderneeded;
void SCR_ChangeRenderer(void); void SCR_ChangeRenderer(void);
void SCR_ChangeRendererCVars(INT32 mode);
extern UINT8 setrenderneeded; extern CV_PossibleValue_t cv_renderer_t[];
extern INT32 scr_bpp; extern INT32 scr_bpp;
extern UINT8 *scr_borderpatch; // patch used to fill the view borders extern UINT8 *scr_borderpatch; // patch used to fill the view borders
@ -182,17 +193,23 @@ extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_re
// wait for page flipping to end or not // wait for page flipping to end or not
extern consvar_t cv_vidwait; extern consvar_t cv_vidwait;
// Initialize the screen
void SCR_Startup(void);
// Change video mode, only at the start of a refresh. // Change video mode, only at the start of a refresh.
void SCR_SetMode(void); void SCR_SetMode(void);
// Set drawer functions for Software
void SCR_SetDrawFuncs(void); void SCR_SetDrawFuncs(void);
// Recalc screen size dependent stuff // Recalc screen size dependent stuff
void SCR_Recalc(void); void SCR_Recalc(void);
// Check parms once at startup // Check parms once at startup
void SCR_CheckDefaultMode(void); void SCR_CheckDefaultMode(void);
// Set the mode number which is saved in the config
void SCR_SetDefaultMode (void);
void SCR_Startup (void); // Set the mode number which is saved in the config
void SCR_SetDefaultMode(void);
FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height); FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height);

View file

@ -196,6 +196,9 @@
<ClInclude Include="..\comptime.h" /> <ClInclude Include="..\comptime.h" />
<ClInclude Include="..\console.h" /> <ClInclude Include="..\console.h" />
<ClInclude Include="..\dehacked.h" /> <ClInclude Include="..\dehacked.h" />
<ClInclude Include="..\deh_soc.h" />
<ClInclude Include="..\deh_lua.h" />
<ClInclude Include="..\deh_tables.h" />
<ClInclude Include="..\doomdata.h" /> <ClInclude Include="..\doomdata.h" />
<ClInclude Include="..\doomdef.h" /> <ClInclude Include="..\doomdef.h" />
<ClInclude Include="..\doomstat.h" /> <ClInclude Include="..\doomstat.h" />
@ -283,6 +286,8 @@
<ClInclude Include="..\r_draw.h" /> <ClInclude Include="..\r_draw.h" />
<ClInclude Include="..\r_local.h" /> <ClInclude Include="..\r_local.h" />
<ClInclude Include="..\r_main.h" /> <ClInclude Include="..\r_main.h" />
<ClInclude Include="..\r_patch.h" />
<ClInclude Include="..\r_patchrotation.h" />
<ClInclude Include="..\r_picformats.h" /> <ClInclude Include="..\r_picformats.h" />
<ClInclude Include="..\r_plane.h" /> <ClInclude Include="..\r_plane.h" />
<ClInclude Include="..\r_portal.h" /> <ClInclude Include="..\r_portal.h" />
@ -361,6 +366,9 @@
<ClCompile Include="..\comptime.c" /> <ClCompile Include="..\comptime.c" />
<ClCompile Include="..\console.c" /> <ClCompile Include="..\console.c" />
<ClCompile Include="..\dehacked.c" /> <ClCompile Include="..\dehacked.c" />
<ClCompile Include="..\deh_soc.c" />
<ClCompile Include="..\deh_lua.c" />
<ClCompile Include="..\deh_tables.c" />
<ClCompile Include="..\d_clisrv.c" /> <ClCompile Include="..\d_clisrv.c" />
<ClCompile Include="..\d_main.c" /> <ClCompile Include="..\d_main.c" />
<ClCompile Include="..\d_net.c" /> <ClCompile Include="..\d_net.c" />
@ -452,6 +460,8 @@
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\r_main.c" /> <ClCompile Include="..\r_main.c" />
<ClCompile Include="..\r_patch.c" />
<ClCompile Include="..\r_patchrotation.c" />
<ClCompile Include="..\r_picformats.c" /> <ClCompile Include="..\r_picformats.c" />
<ClCompile Include="..\r_plane.c" /> <ClCompile Include="..\r_plane.c" />
<ClCompile Include="..\r_portal.c" /> <ClCompile Include="..\r_portal.c" />

Some files were not shown because too many files have changed in this diff Show more