diff --git a/.gitlab/ci/templates/srb2ci.yml b/.gitlab/ci/templates/srb2ci.yml index 3716d9df9..bdf8a3ed6 100644 --- a/.gitlab/ci/templates/srb2ci.yml +++ b/.gitlab/ci/templates/srb2ci.yml @@ -61,7 +61,7 @@ - - | # apt_update echo -e "\e[0Ksection_start:`date +%s`:apt_update[collapsed=true]\r\e[0KUpdating APT listing" - - apt-get update + - timeout 2m apt-get update || timeout 2m apt-get update - | # apt_update echo -e "\e[0Ksection_end:`date +%s`:apt_update\r\e[0K" diff --git a/assets/README.txt b/assets/README.txt index e384333ed..2c522966e 100644 --- a/assets/README.txt +++ b/assets/README.txt @@ -39,7 +39,7 @@ https://facebook.com/SonicRoboBlast2 COPYRIGHT AND DISCLAIMER -Design and content in Sonic Robo Blast 2 is copyright 1998-2023 by Sonic Team Jr. +Design and content in Sonic Robo Blast 2 is copyright 1998-2024 by Sonic Team Jr. All original material in this game is copyrighted by their respective owners, and no copyright infringement is intended. Sonic Team Jr. is in no way affiliated with SEGA or Sonic Team, and we do not claim ownership of any of SEGA's intellectual property used in SRB2. diff --git a/assets/debian-template/copyright b/assets/debian-template/copyright index cc47c453b..649e796fb 100644 --- a/assets/debian-template/copyright +++ b/assets/debian-template/copyright @@ -12,7 +12,7 @@ Upstream Author(s): Copyright: - Copyright (C) 1998-2018 by Sonic Team Junior + Copyright (C) 1998-2024 by Sonic Team Junior License: @@ -21,7 +21,7 @@ License: The Debian packaging is: Copyright (C) 2010 Callum Dickinson - Copyright (C) 2010-2018 by Sonic Team Junior + Copyright (C) 2010-2024 by Sonic Team Junior and is licensed under the GPL version 2, see "/usr/share/common-licenses/GPL-2". diff --git a/debian-template/copyright b/debian-template/copyright index cc47c453b..649e796fb 100644 --- a/debian-template/copyright +++ b/debian-template/copyright @@ -12,7 +12,7 @@ Upstream Author(s): Copyright: - Copyright (C) 1998-2018 by Sonic Team Junior + Copyright (C) 1998-2024 by Sonic Team Junior License: @@ -21,7 +21,7 @@ License: The Debian packaging is: Copyright (C) 2010 Callum Dickinson - Copyright (C) 2010-2018 by Sonic Team Junior + Copyright (C) 2010-2024 by Sonic Team Junior and is licensed under the GPL version 2, see "/usr/share/common-licenses/GPL-2". diff --git a/doc/specs/udmf_srb2.txt b/doc/specs/udmf_srb2.txt index d6d71a0d5..eaa3a8a97 100644 --- a/doc/specs/udmf_srb2.txt +++ b/doc/specs/udmf_srb2.txt @@ -1,5 +1,5 @@ =============================================================================== -Universal Doom Map Format Sonic Robo Blast 2 extensions v1.0 19.02.2024 +Universal Doom Map Format Sonic Robo Blast 2 extensions v1.0 19.06.2024 Copyright (c) 2024 Sonic Team Junior uses Universal Doom Map Format Specification v1.1 as a template, @@ -143,6 +143,9 @@ Sonic Robo Blast 2 defines the following standardized fields: offsetx_bottom = ; // X offset for lower texture. Default = 0.0. offsety_bottom = ; // Y offset for lower texture. Default = 0.0. + light = ; // Light level, relative to 'sector' light level. Default = 0. + lightabsolute = ; // true = 'light' is an absolute value, ignoring 'sector' light level. + comment = ; // A comment. Implementors should attach no special // semantic meaning to this field. } diff --git a/extras/conf/udb/Includes/SRB222_common.cfg b/extras/conf/udb/Includes/SRB222_common.cfg index 90c85cdea..e5cafead4 100644 --- a/extras/conf/udb/Includes/SRB222_common.cfg +++ b/extras/conf/udb/Includes/SRB222_common.cfg @@ -115,7 +115,7 @@ mapformat_udmf // Enables setting distinct brightness for floor, ceiling, and walls distinctfloorandceilingbrightness = true; - distinctwallbrightness = false; + distinctwallbrightness = true; // Enables setting distinct brightness for upper, middle, and lower sidedef parts distinctsidedefpartbrightness = false; diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 37b01d7dd..c37c29ce0 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -280,18 +280,18 @@ universalfields default = ""; } - //light - //{ - // type = 0; - // default = 0; - //} - // - //lightabsolute - //{ - // type = 3; - // default = false; - //} - // + light + { + type = 0; + default = 0; + } + + lightabsolute + { + type = 3; + default = false; + } + //light_top //{ // type = 0; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 20caecf7b..fbd29cddd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -172,6 +172,11 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") endif() endif() +if("${CMAKE_SYSTEM_NAME}" MATCHES "Haiku") + target_compile_definitions(SRB2SDL2 PRIVATE -DNOEXECINFO) + target_link_libraries(SRB2SDL2 PRIVATE network) +endif() + if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") target_compile_definitions(SRB2SDL2 PRIVATE -DMACOSX) endif() diff --git a/src/Makefile.d/detect.mk b/src/Makefile.d/detect.mk index 9e2736946..853ad3d6d 100644 --- a/src/Makefile.d/detect.mk +++ b/src/Makefile.d/detect.mk @@ -4,7 +4,6 @@ # Previously featured:\ PANDORA\ - HAIKU\ DUMMY\ DJGPPDOS\ SOLARIS\ @@ -17,6 +16,7 @@ all_systems:=\ UNIX\ LINUX\ FREEBSD\ + HAIKU\ # check for user specified system ifeq (,$(filter $(all_systems),$(.VARIABLES))) @@ -35,6 +35,8 @@ system:=$(shell uname -s) ifeq ($(system),Linux) new_system:=LINUX +else ifeq ($(system),Haiku) +new_system:=HAIKU else $(error \ diff --git a/src/Makefile.d/haiku.mk b/src/Makefile.d/haiku.mk new file mode 100644 index 000000000..6742ec75b --- /dev/null +++ b/src/Makefile.d/haiku.mk @@ -0,0 +1,71 @@ +# +# Makefile options for Haiku +# + +opts+=-DUNIXCOMMON -DLUA_USE_POSIX + +ifndef DEDICATED +ifndef DUMMY +SDL?=1 +DEDICATED?=0 +endif +endif + +NOEXECINFO=1 + +ifeq (${SDL},1) +EXENAME?=srb2haiku +else ifeq (${DEDICATED},1) +EXENAME?=srb2haikud +endif + +ifndef NONET +libs+=-lnetwork +endif + +define _set = +$(1)_CFLAGS?=$($(1)_opts) +$(1)_LDFLAGS?=$($(1)_libs) +endef + +lib:=../libs/gme +LIBGME_opts:=-I$(lib)/include +LIBGME_libs:=-l:libgme.so.0 +$(eval $(call _set,LIBGME)) + +lib:=../libs/libopenmpt +LIBOPENMPT_opts:=-I$(lib)/inc +LIBOPENMPT_libs:=-l:libopenmpt.so.0 +$(eval $(call _set,LIBOPENMPT)) + +ifdef SDL +lib:=../libs/SDL2_mixer +mixer_opts:=-I$(lib)/include +mixer_libs:=-l:libSDL2_mixer-2.0.so.0 + +lib:=../libs/SDL2 +SDL_opts:=-I$(lib)/include $(mixer_opts) +SDL_libs:=$(mixer_libs) -l:libSDL2-2.0.so.0 +$(eval $(call _set,SDL)) +endif + +lib:=../libs/zlib +ZLIB_opts:=-I$(lib) +ZLIB_libs:=-l:libz.so.1 +$(eval $(call _set,ZLIB)) + +ifndef PNG_CONFIG +PNG_opts:= +PNG_libs:=-l:libpng16.so.16 +$(eval $(call _set,PNG)) +endif + +lib:=../libs/curl +CURL_opts:=-I$(lib)/include +CURL_libs:=-l:libcurl.so.4 +$(eval $(call _set,CURL)) + +lib:=../libs/miniupnpc +MINIUPNPC_opts:=-I$(lib)/include +MINIUPNPC_libs:=-l:libminiupnpc.so.17 +$(eval $(call _set,MINIUPNPC)) diff --git a/src/Makefile.d/platform.mk b/src/Makefile.d/platform.mk index d9a2954f6..d5423a397 100644 --- a/src/Makefile.d/platform.mk +++ b/src/Makefile.d/platform.mk @@ -35,6 +35,10 @@ endif else ifdef FREEBSD UNIX=1 platform=freebsd +else ifdef HAIKU +# Give Haiku its own configuration, since it +# isn't actually UNIX. +include Makefile.d/haiku.mk else ifdef SOLARIS # FIXME: UNTESTED UNIX=1 platform=solaris diff --git a/src/Makefile.d/sdl.mk b/src/Makefile.d/sdl.mk index a1bfa3303..d5e83989c 100644 --- a/src/Makefile.d/sdl.mk +++ b/src/Makefile.d/sdl.mk @@ -33,11 +33,13 @@ else opts+=-DHAVE_MIXER sources+=sdl/mixer_sound.c - ifdef HAVE_MIXERX - opts+=-DHAVE_MIXERX - libs+=-lSDL2_mixer_ext - else - libs+=-lSDL2_mixer + ifndef HAIKU # Haiku has a special import path + ifdef HAVE_MIXERX + opts+=-DHAVE_MIXERX + libs+=-lSDL2_mixer_ext + else + libs+=-lSDL2_mixer + endif endif endif diff --git a/src/b_bot.c b/src/b_bot.c index 6229cb1d6..97dcd1078 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2007-2016 by John "JTE" Muniz. -// Copyright (C) 2011-2023 by Sonic Team Junior. +// Copyright (C) 2011-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/byteptr.h b/src/byteptr.h index 4377fae57..61cefd350 100644 --- a/src/byteptr.h +++ b/src/byteptr.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/command.c b/src/command.c index e0156274e..8f9166361 100644 --- a/src/command.c +++ b/src/command.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1722,8 +1722,7 @@ badinput: static boolean serverloading = false; -static consvar_t * -ReadNetVar (UINT8 **p, char **return_value, boolean *return_stealth) +static consvar_t *ReadNetVar(save_t *p, char **return_value, boolean *return_stealth) { UINT16 netid; char *val; @@ -1731,10 +1730,10 @@ ReadNetVar (UINT8 **p, char **return_value, boolean *return_stealth) consvar_t *cvar; - netid = READUINT16 (*p); - val = (char *)*p; - SKIPSTRING (*p); - stealth = READUINT8 (*p); + netid = P_ReadUINT16(p); + val = (char *)&p->buf[p->pos]; + P_SkipString(p); + stealth = P_ReadUINT8(p); cvar = CV_FindNetVar(netid); @@ -1752,8 +1751,7 @@ ReadNetVar (UINT8 **p, char **return_value, boolean *return_stealth) } #ifdef OLD22DEMOCOMPAT -static consvar_t * -ReadOldDemoVar (UINT8 **p, char **return_value, boolean *return_stealth) +static consvar_t *ReadOldDemoVar(save_t *p, char **return_value, boolean *return_stealth) { UINT16 id; char *val; @@ -1761,10 +1759,10 @@ ReadOldDemoVar (UINT8 **p, char **return_value, boolean *return_stealth) old_demo_var_t *demovar; - id = READUINT16 (*p); - val = (char *)*p; - SKIPSTRING (*p); - stealth = READUINT8 (*p); + id = P_ReadUINT16(p); + val = (char *)&p->buf[p->pos]; + P_SkipString(p); + stealth = P_ReadUINT8(p); demovar = CV_FindOldDemoVar(id); @@ -1783,8 +1781,7 @@ ReadOldDemoVar (UINT8 **p, char **return_value, boolean *return_stealth) } #endif/*OLD22DEMOCOMPAT*/ -static consvar_t * -ReadDemoVar (UINT8 **p, char **return_value, boolean *return_stealth) +static consvar_t *ReadDemoVar(save_t *p, char **return_value, boolean *return_stealth) { char *name; char *val; @@ -1792,11 +1789,11 @@ ReadDemoVar (UINT8 **p, char **return_value, boolean *return_stealth) consvar_t *cvar; - name = (char *)*p; - SKIPSTRING (*p); - val = (char *)*p; - SKIPSTRING (*p); - stealth = READUINT8 (*p); + name = (char *)&p->buf[p->pos]; + P_SkipString(p); + val = (char *)&p->buf[p->pos]; + P_SkipString(p); + stealth = P_ReadUINT8(p); cvar = CV_FindVar(name); @@ -1826,41 +1823,46 @@ static void Got_NetVar(UINT8 **p, INT32 playernum) return; } - cvar = ReadNetVar(p, &svalue, &stealth); + save_t save_p; + save_p.buf = *p; + save_p.size = MAXTEXTCMD; + save_p.pos = 0; + cvar = ReadNetVar(&save_p, &svalue, &stealth); + *p = &save_p.buf[save_p.pos]; if (cvar) Setvalue(cvar, svalue, stealth); } -void CV_SaveVars(UINT8 **p, boolean in_demo) +void CV_SaveVars(save_t *p, boolean in_demo) { consvar_t *cvar; - UINT8 *count_p = *p; + UINT8 *count_p = &p->buf[p->pos]; UINT16 count = 0; // send only changed cvars ... // the client will reset all netvars to default before loading - WRITEUINT16(*p, 0x0000); + P_WriteUINT16(p, 0x0000); for (cvar = consvar_vars; cvar; cvar = cvar->next) if ((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar)) { if (in_demo) { - WRITESTRING(*p, cvar->name); + P_WriteString(p, cvar->name); } else { - WRITEUINT16(*p, cvar->netid); + P_WriteUINT16(p, cvar->netid); } - WRITESTRING(*p, cvar->string); - WRITEUINT8(*p, false); + P_WriteString(p, cvar->string); + P_WriteUINT8(p, false); ++count; } WRITEUINT16(count_p, count); } -static void CV_LoadVars(UINT8 **p, - consvar_t *(*got)(UINT8 **p, char **ret_value, boolean *ret_stealth)) +static void CV_LoadVars(save_t *p, + consvar_t *(*got)(save_t *p, char **ret_value, boolean *ret_stealth)) { const boolean store = (client || demoplayback); @@ -1888,7 +1890,7 @@ static void CV_LoadVars(UINT8 **p, } } - count = READUINT16(*p); + count = P_ReadUINT16(p); while (count--) { cvar = (*got)(p, &val, &stealth); @@ -1921,19 +1923,19 @@ void CV_RevertNetVars(void) } } -void CV_LoadNetVars(UINT8 **p) +void CV_LoadNetVars(save_t *p) { CV_LoadVars(p, ReadNetVar); } #ifdef OLD22DEMOCOMPAT -void CV_LoadOldDemoVars(UINT8 **p) +void CV_LoadOldDemoVars(save_t *p) { CV_LoadVars(p, ReadOldDemoVar); } #endif -void CV_LoadDemoVars(UINT8 **p) +void CV_LoadDemoVars(save_t *p) { CV_LoadVars(p, ReadDemoVar); } @@ -1986,7 +1988,7 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth) if (!var->string) I_Error("CV_Set: %s no string set!\n", var->name); #endif - if (!var || !var->string || !value || !stricmp(var->string, value)) + if (!var || !var->string || !value || (var->can_change == NULL && !stricmp(var->string, value))) return; // no changes if (var->flags & CV_NETVAR) diff --git a/src/command.h b/src/command.h index f0dc62418..c1ac7d486 100644 --- a/src/command.h +++ b/src/command.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -15,6 +15,7 @@ #include #include "doomdef.h" +#include "p_saveg.h" //=================================== // Command buffer & command execution @@ -218,19 +219,19 @@ void CV_AddValue(consvar_t *var, INT32 increment); void CV_SaveVariables(FILE *f); // load/save gamesate (load and save option and for network join in game) -void CV_SaveVars(UINT8 **p, boolean in_demo); +void CV_SaveVars(save_t *p, boolean in_demo); #define CV_SaveNetVars(p) CV_SaveVars(p, false) -void CV_LoadNetVars(UINT8 **p); +void CV_LoadNetVars(save_t *p); // then revert after leaving a netgame void CV_RevertNetVars(void); #define CV_SaveDemoVars(p) CV_SaveVars(p, true) -void CV_LoadDemoVars(UINT8 **p); +void CV_LoadDemoVars(save_t *p); #ifdef OLD22DEMOCOMPAT -void CV_LoadOldDemoVars(UINT8 **p); +void CV_LoadOldDemoVars(save_t *p); #endif // reset cheat netvars after cheats is deactivated diff --git a/src/console.c b/src/console.c index 0c3eac4f7..50ecfec9c 100644 --- a/src/console.c +++ b/src/console.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/console.h b/src/console.h index 6ad1dba1e..2af01f1a3 100644 --- a/src/console.h +++ b/src/console.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_main.c b/src/d_main.c index 3a3a0b26a..a6a9385d2 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -679,13 +679,13 @@ static void D_Display(void) s[sizeof s - 1] = '\0'; snprintf(s, sizeof s - 1, "get %d b/s", getbps); - V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-40, V_YELLOWMAP, s); + V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-40, V_YELLOWMAP, s); snprintf(s, sizeof s - 1, "send %d b/s", sendbps); - V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-30, V_YELLOWMAP, s); + V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-30, V_YELLOWMAP, s); snprintf(s, sizeof s - 1, "GameMiss %.2f%%", gamelostpercent); - V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-20, V_YELLOWMAP, s); + V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-20, V_YELLOWMAP, s); snprintf(s, sizeof s - 1, "SysMiss %.2f%%", lostpercent); - V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s); + V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-10, V_YELLOWMAP, s); } if (cv_perfstats.value) @@ -1250,7 +1250,7 @@ void D_SRB2Main(void) // Print GPL notice for our console users (Linux) CONS_Printf( "\n\nSonic Robo Blast 2\n" - "Copyright (C) 1998-2023 by Sonic Team Junior\n\n" + "Copyright (C) 1998-2024 by Sonic Team Junior\n\n" "This program comes with ABSOLUTELY NO WARRANTY.\n\n" "This is free software, and you are welcome to redistribute it\n" "and/or modify it under the terms of the GNU General Public License\n" @@ -1535,7 +1535,7 @@ void D_SRB2Main(void) I_Error("Cannot find a map remotely named '%s'\n", word); else { - if (!M_CheckParm("-server")) + if (!(M_CheckParm("-server") || dedicated)) G_SetUsedCheats(true); autostart = true; } diff --git a/src/d_player.h b/src/d_player.h index 95d2f609d..5f5bf53d6 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_think.h b/src/d_think.h index 589124587..76c1bb5b8 100644 --- a/src/d_think.h +++ b/src/d_think.h @@ -51,6 +51,8 @@ typedef struct thinker_s // killough 11/98: count of how many other objects reference // this one using pointers. Used for garbage collection. INT32 references; + + boolean removing; boolean cachable; #ifdef PARANOIA diff --git a/src/dedicated/i_system.c b/src/dedicated/i_system.c index 82dd51be0..22d3d1200 100644 --- a/src/dedicated/i_system.c +++ b/src/dedicated/i_system.c @@ -3,7 +3,7 @@ // // Copyright (C) 1993-1996 by id Software, Inc. // Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2014-2023 by Sonic Team Junior. +// Copyright (C) 2014-2024 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -705,10 +705,9 @@ typedef struct static feild_t tty_con; -// when printing general stuff to stdout stderr (Sys_Printf) -// we need to disable the tty console stuff -// this increments so we can recursively disable -static INT32 ttycon_hide = 0; +// lock to prevent clearing partial lines, since not everything +// printed ends on a newline. +static boolean ttycon_ateol = true; // some key codes that the terminal may be using // TTimo NOTE: I'm not sure how relevant this is static INT32 tty_erase; @@ -736,63 +735,31 @@ static inline void tty_FlushIn(void) // TTimo NOTE: it seems on some terminals just sending '\b' is not enough // so for now, in any case we send "\b \b" .. yeah well .. // (there may be a way to find out if '\b' alone would work though) +// Hanicef NOTE: using \b this way is unreliable because of terminal state, +// it's better to use \r to reset the cursor to the beginning of the +// line and clear from there. static void tty_Back(void) { - char key; - ssize_t d; - key = '\b'; - d = write(STDOUT_FILENO, &key, 1); - key = ' '; - d = write(STDOUT_FILENO, &key, 1); - key = '\b'; - d = write(STDOUT_FILENO, &key, 1); - (void)d; + write(STDOUT_FILENO, "\r", 1); + if (tty_con.cursor>0) + { + write(STDOUT_FILENO, tty_con.buffer, tty_con.cursor); + } + write(STDOUT_FILENO, " \b", 2); } static void tty_Clear(void) { size_t i; + write(STDOUT_FILENO, "\r", 1); if (tty_con.cursor>0) { for (i=0; i0); - ttycon_hide--; - if (ttycon_hide == 0 && tty_con.cursor) - { - for (i=0; i 0) { s = Z_StrDup(luaL_checkstring(L,1)); diff --git a/src/deh_soc.c b/src/deh_soc.c index 3759cc9c7..c0e646f60 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/deh_tables.c b/src/deh_tables.c index f113f6b19..91163b206 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -4483,6 +4483,8 @@ const char *const PLAYERFLAG_LIST[] = { "CANCARRY", // Can carry? "FINISHED", + "SHIELDDOWN", // Shield has been pressed. + NULL // stop loop here. }; diff --git a/src/deh_tables.h b/src/deh_tables.h index b6986adff..94af2fa52 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/dehacked.c b/src/dehacked.c index 2050a117f..63656753d 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -192,7 +192,10 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) INT32 i; if (!deh_loaded) + { initfreeslots(); + deh_loaded = true; + } deh_num_warning = 0; @@ -605,14 +608,10 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) if (deh_num_warning) { CONS_Printf(M_GetText("%d warning%s in the SOC lump\n"), deh_num_warning, deh_num_warning == 1 ? "" : "s"); - if (devparm) { + if (devparm) I_Error("%s%s",va(M_GetText("%d warning%s in the SOC lump\n"), deh_num_warning, deh_num_warning == 1 ? "" : "s"), M_GetText("See log.txt for details.\n")); - //while (!I_GetKey()) - //I_OsPolling(); - } } - deh_loaded = true; Z_Free(s); } diff --git a/src/doomdef.h b/src/doomdef.h index 1b0e76314..c92e6dc37 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/doomstat.h b/src/doomstat.h index bde2bacc7..5246349de 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/doomtype.h b/src/doomtype.h index fa8616793..415669ac4 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/f_finale.c b/src/f_finale.c index 810af4e82..a992a0dfd 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1065,12 +1065,12 @@ static const char *credits[] = { "Julio \"Chaos Zero 64\" Guir", "\"Hanicef\"", "\"Hannu_Hanhi\"", // For many OpenGL performance improvements! + "\"hazepastel\"", "Kepa \"Nev3r\" Iceta", "Thomas \"Shadow Hog\" Igoe", "Iestyn \"Monster Iestyn\" Jealous", "\"Kaito Sinclaire\"", "\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog - "\"katsy\"", "Ronald \"Furyhunter\" Kinard", // The SDL2 port "\"Lat'\"", // SRB2-CHAT, the chat window from Kart "\"LZA\"", @@ -3435,7 +3435,7 @@ void F_TitleScreenTicker(boolean run) { for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; diff --git a/src/f_finale.h b/src/f_finale.h index 4b777eb11..e12a81cc6 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/filesrch.c b/src/filesrch.c index ea19e00cd..67a2e8976 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -444,12 +444,11 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name); #if defined(__linux__) || defined(__FreeBSD__) - if (dent->d_type == DT_UNKNOWN) - if (lstat(searchpath,&fsstat) == 0 && S_ISDIR(fsstat.st_mode)) + if (dent->d_type == DT_UNKNOWN || dent->d_type == DT_LNK) + if (stat(searchpath,&fsstat) == 0 && S_ISDIR(fsstat.st_mode)) dent->d_type = DT_DIR; // Linux and FreeBSD has a special field for file type on dirent, so use that to speed up lookups. - // FIXME: should we also follow symlinks? if (dent->d_type == DT_DIR && depthleft) #else if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat diff --git a/src/g_demo.c b/src/g_demo.c index cfa34fc7e..8315e716b 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -614,7 +614,7 @@ void G_ConsGhostTic(void) mobj = NULL; for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mobj = (mobj_t *)th; if (mobj->type == (mobjtype_t)type && mobj->x == x && mobj->y == y && mobj->z == z) @@ -1454,6 +1454,7 @@ void G_BeginRecording(void) char *filename; UINT16 totalfiles; UINT8 *m; + save_t savebuffer; if (demo_p) return; @@ -1603,7 +1604,11 @@ void G_BeginRecording(void) } // Save netvar data - CV_SaveDemoVars(&demo_p); + savebuffer.buf = demo_p; + savebuffer.size = demoend - demo_p; + savebuffer.pos = 0; + CV_SaveDemoVars(&savebuffer); + demo_p = &savebuffer.buf[savebuffer.pos]; memset(&oldcmd,0,sizeof(oldcmd)); memset(&oldghost,0,sizeof(oldghost)); @@ -2236,10 +2241,24 @@ void G_DoPlayDemo(char *defdemoname) // net var data #ifdef OLD22DEMOCOMPAT if (demoversion < 0x000d) - CV_LoadOldDemoVars(&demo_p); + { + save_t savebuffer; + savebuffer.buf = demo_p; + savebuffer.size = demoend - demo_p; + savebuffer.pos = 0; + CV_LoadOldDemoVars(&savebuffer); + demo_p = &savebuffer.buf[savebuffer.pos]; + } else #endif - CV_LoadDemoVars(&demo_p); + { + save_t savebuffer; + savebuffer.buf = demo_p; + savebuffer.size = demoend - demo_p; + savebuffer.pos = 0; + CV_LoadDemoVars(&savebuffer); + demo_p = &savebuffer.buf[savebuffer.pos]; + } // Sigh ... it's an empty demo. if (*demo_p == DEMOMARKER) @@ -2677,7 +2696,7 @@ void G_DoPlayMetal(void) // find metal sonic for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo = (mobj_t *)th; diff --git a/src/g_demo.h b/src/g_demo.h index 67f61f54d..d7c682871 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/g_game.c b/src/g_game.c index bf369d111..894063585 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -256,8 +256,6 @@ boolean precache = true; // if true, load all graphics at start INT16 prevmap, nextmap; -static UINT8 *savebuffer; - // Analog Control static void UserAnalog_OnChange(void); static void UserAnalog2_OnChange(void); @@ -1386,7 +1384,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (PLAYERINPUTDOWN(ssplayer, GC_SPIN) || (usejoystick && axis > 0)) cmd->buttons |= BT_SPIN; - if (gamestate != GS_LEVEL) // not in a level, don't build anything else + if (gamestate == GS_INTRO) // prevent crash in intro { cmd->angleturn = ticcmd_oldangleturn[forplayer]; cmd->aiming = G_ClipAimingPitch(myaiming); @@ -1724,7 +1722,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // 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 (addedtogame) + if (addedtogame && gamestate == GS_LEVEL) { INT16 extra = ticcmd_oldangleturn[forplayer] - player->oldrelangleturn; INT16 origangle = cmd->angleturn; @@ -1936,6 +1934,8 @@ void G_DoLoadLevel(boolean resetplayer) // void G_StartTitleCard(void) { + ST_stopTitleCard(); + // The title card has been disabled for this map. // Oh well. if (!G_IsTitleCardAvailable()) @@ -2624,6 +2624,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) boolean spectator; boolean outofcoop; boolean removing; + boolean muted; INT16 bot; SINT8 pity; INT16 rings; @@ -2641,6 +2642,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) spectator = players[player].spectator; outofcoop = players[player].outofcoop; removing = players[player].removing; + muted = players[player].muted; pflags = (players[player].pflags & (PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE|PF_TAGIT|PF_GAMETYPEOVER)); playerangleturn = players[player].angleturn; oldrelangleturn = players[player].oldrelangleturn; @@ -2718,6 +2720,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->spectator = spectator; p->outofcoop = outofcoop; p->removing = removing; + p->muted = muted; p->angleturn = playerangleturn; p->oldrelangleturn = oldrelangleturn; @@ -3069,7 +3072,7 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo) // scan all thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -3352,7 +3355,7 @@ void G_AddPlayer(INT32 playernum) p->playerstate = PST_REBORN; - p->height = mobjinfo[MT_PLAYER].height; + p->height = skins[p->skin]->height; if (G_GametypeUsesLives() || ((netgame || multiplayer) && (gametyperules & GTR_FRIENDLY))) p->lives = cv_startinglives.value; @@ -4396,7 +4399,7 @@ void G_LoadGameSettings(void) // Loads the main data file, which stores information such as emblems found, etc. void G_LoadGameData(gamedata_t *data) { - size_t length; + save_t savebuffer; INT32 i, j; UINT32 versionID; @@ -4438,18 +4441,18 @@ void G_LoadGameData(gamedata_t *data) return; } - length = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &savebuffer); - if (!length) + savebuffer.size = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &savebuffer.buf); + if (!savebuffer.size) { // No gamedata. We can save a new one. data->loaded = true; return; } - save_p = savebuffer; + savebuffer.pos = 0; // Version check - versionID = READUINT32(save_p); + versionID = P_ReadUINT32(&savebuffer); if (versionID != GAMEDATA_ID #ifdef COMPAT_GAMEDATA_ID // backwards compat behavior && versionID != COMPAT_GAMEDATA_ID @@ -4460,8 +4463,7 @@ void G_LoadGameData(gamedata_t *data) if (strcmp(srb2home,".")) gdfolder = srb2home; - Z_Free(savebuffer); - save_p = NULL; + Z_Free(savebuffer.buf); I_Error("Game data is from another version of SRB2.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder); } @@ -4473,14 +4475,14 @@ void G_LoadGameData(gamedata_t *data) } #endif - data->totalplaytime = READUINT32(save_p); + data->totalplaytime = P_ReadUINT32(&savebuffer); #ifdef COMPAT_GAMEDATA_ID if (versionID == COMPAT_GAMEDATA_ID) { // We'll temporarily use the old condition when loading an older file. // The proper mod-specific hash will get saved in afterwards. - boolean modded = READUINT8(save_p); + boolean modded = P_ReadUINT8(&savebuffer); if (modded && !savemoddata) { @@ -4500,13 +4502,13 @@ void G_LoadGameData(gamedata_t *data) strcpy(currentfilename, gamedatafilename); STRBUFCPY(backupfilename, strcat(currentfilename, bak)); - FIL_WriteFile(va(pandf, srb2home, backupfilename), savebuffer, length); + FIL_WriteFile(va(pandf, srb2home, backupfilename), &savebuffer.buf, savebuffer.size); } else #endif { // Quick & dirty hash for what mod this save file is for. - UINT32 modID = READUINT32(save_p); + UINT32 modID = P_ReadUINT32(&savebuffer); UINT32 expectedID = quickncasehash(timeattackfolder, sizeof timeattackfolder); if (modID != expectedID) @@ -4518,50 +4520,50 @@ void G_LoadGameData(gamedata_t *data) // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) - if ((data->mapvisited[i] = READUINT8(save_p)) > MV_MAX) + if ((data->mapvisited[i] = P_ReadUINT8(&savebuffer)) > MV_MAX) goto datacorrupt; // To save space, use one bit per collected/achieved/unlocked flag for (i = 0; i < max_emblems;) { - rtemp = READUINT8(save_p); + rtemp = P_ReadUINT8(&savebuffer); for (j = 0; j < 8 && j+i < max_emblems; ++j) data->collected[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < max_extraemblems;) { - rtemp = READUINT8(save_p); + rtemp = P_ReadUINT8(&savebuffer); for (j = 0; j < 8 && j+i < max_extraemblems; ++j) data->extraCollected[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < max_unlockables;) { - rtemp = READUINT8(save_p); + rtemp = P_ReadUINT8(&savebuffer); for (j = 0; j < 8 && j+i < max_unlockables; ++j) data->unlocked[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < max_conditionsets;) { - rtemp = READUINT8(save_p); + rtemp = P_ReadUINT8(&savebuffer); for (j = 0; j < 8 && j+i < max_conditionsets; ++j) data->achieved[j+i] = ((rtemp >> j) & 1); i += j; } - data->timesBeaten = READUINT32(save_p); - data->timesBeatenWithEmeralds = READUINT32(save_p); - data->timesBeatenUltimate = READUINT32(save_p); + data->timesBeaten = P_ReadUINT32(&savebuffer); + data->timesBeatenWithEmeralds = P_ReadUINT32(&savebuffer); + data->timesBeatenUltimate = P_ReadUINT32(&savebuffer); // Main records for (i = 0; i < NUMMAPS; ++i) { - recscore = READUINT32(save_p); - rectime = (tic_t)READUINT32(save_p); - recrings = READUINT16(save_p); - save_p++; // compat + recscore = P_ReadUINT32(&savebuffer); + rectime = (tic_t)P_ReadUINT32(&savebuffer); + recrings = P_ReadUINT16(&savebuffer); + P_ReadUINT8(&savebuffer); // compat if (recrings > 10000 || recscore > MAXSCORE) goto datacorrupt; @@ -4578,16 +4580,16 @@ void G_LoadGameData(gamedata_t *data) // Nights records for (i = 0; i < NUMMAPS; ++i) { - if ((recmares = READUINT8(save_p)) == 0) + if ((recmares = P_ReadUINT8(&savebuffer)) == 0) continue; G_AllocNightsRecordData((INT16)i, data); for (curmare = 0; curmare < (recmares+1); ++curmare) { - data->nightsrecords[i]->score[curmare] = READUINT32(save_p); - data->nightsrecords[i]->grade[curmare] = READUINT8(save_p); - data->nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p); + data->nightsrecords[i]->score[curmare] = P_ReadUINT32(&savebuffer); + data->nightsrecords[i]->grade[curmare] = P_ReadUINT8(&savebuffer); + data->nightsrecords[i]->time[curmare] = (tic_t)P_ReadUINT32(&savebuffer); if (data->nightsrecords[i]->grade[curmare] > GRADE_S) { @@ -4599,8 +4601,7 @@ void G_LoadGameData(gamedata_t *data) } // done - Z_Free(savebuffer); - save_p = NULL; + Z_Free(savebuffer.buf); // Don't consider loaded until it's a success! // It used to do this much earlier, but this would cause the gamedata to @@ -4621,8 +4622,7 @@ void G_LoadGameData(gamedata_t *data) if (strcmp(srb2home,".")) gdfolder = srb2home; - Z_Free(savebuffer); - save_p = NULL; + Z_Free(savebuffer.buf); I_Error("Corrupt game data file.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder); } @@ -4632,9 +4632,8 @@ void G_LoadGameData(gamedata_t *data) // Saves the main data file, which stores information such as emblems found, etc. void G_SaveGameData(gamedata_t *data) { - UINT8 *data_p; + save_t savebuffer; - size_t length; INT32 i, j; UINT8 btemp; @@ -4646,30 +4645,31 @@ void G_SaveGameData(gamedata_t *data) if (!data->loaded) return; // If never loaded (-nodata), don't save - data_p = savebuffer = (UINT8 *)malloc(GAMEDATASIZE); - if (!data_p) + savebuffer.size = GAMEDATASIZE; + savebuffer.buf = (UINT8 *)malloc(savebuffer.size); + if (!savebuffer.buf) { CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n")); return; } + savebuffer.pos = 0; if (usedCheats) { - free(savebuffer); - savebuffer = NULL; + free(savebuffer.buf); return; } // Version test - WRITEUINT32(data_p, GAMEDATA_ID); + P_WriteUINT32(&savebuffer, GAMEDATA_ID); - WRITEUINT32(data_p, data->totalplaytime); + P_WriteUINT32(&savebuffer, data->totalplaytime); - WRITEUINT32(data_p, quickncasehash(timeattackfolder, sizeof timeattackfolder)); + P_WriteUINT32(&savebuffer, quickncasehash(timeattackfolder, sizeof timeattackfolder)); // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) - WRITEUINT8(data_p, (data->mapvisited[i] & MV_MAX)); + P_WriteUINT8(&savebuffer, (data->mapvisited[i] & MV_MAX)); // To save space, use one bit per collected/achieved/unlocked flag for (i = 0; i < MAXEMBLEMS;) @@ -4677,7 +4677,7 @@ void G_SaveGameData(gamedata_t *data) btemp = 0; for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) btemp |= (data->collected[j+i] << j); - WRITEUINT8(data_p, btemp); + P_WriteUINT8(&savebuffer, btemp); i += j; } for (i = 0; i < MAXEXTRAEMBLEMS;) @@ -4685,7 +4685,7 @@ void G_SaveGameData(gamedata_t *data) btemp = 0; for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) btemp |= (data->extraCollected[j+i] << j); - WRITEUINT8(data_p, btemp); + P_WriteUINT8(&savebuffer, btemp); i += j; } for (i = 0; i < MAXUNLOCKABLES;) @@ -4693,7 +4693,7 @@ void G_SaveGameData(gamedata_t *data) btemp = 0; for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) btemp |= (data->unlocked[j+i] << j); - WRITEUINT8(data_p, btemp); + P_WriteUINT8(&savebuffer, btemp); i += j; } for (i = 0; i < MAXCONDITIONSETS;) @@ -4701,30 +4701,30 @@ void G_SaveGameData(gamedata_t *data) btemp = 0; for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) btemp |= (data->achieved[j+i] << j); - WRITEUINT8(data_p, btemp); + P_WriteUINT8(&savebuffer, btemp); i += j; } - WRITEUINT32(data_p, data->timesBeaten); - WRITEUINT32(data_p, data->timesBeatenWithEmeralds); - WRITEUINT32(data_p, data->timesBeatenUltimate); + P_WriteUINT32(&savebuffer, data->timesBeaten); + P_WriteUINT32(&savebuffer, data->timesBeatenWithEmeralds); + P_WriteUINT32(&savebuffer, data->timesBeatenUltimate); // Main records for (i = 0; i < NUMMAPS; i++) { if (data->mainrecords[i]) { - WRITEUINT32(data_p, data->mainrecords[i]->score); - WRITEUINT32(data_p, data->mainrecords[i]->time); - WRITEUINT16(data_p, data->mainrecords[i]->rings); + P_WriteUINT32(&savebuffer, data->mainrecords[i]->score); + P_WriteUINT32(&savebuffer, data->mainrecords[i]->time); + P_WriteUINT16(&savebuffer, data->mainrecords[i]->rings); } else { - WRITEUINT32(data_p, 0); - WRITEUINT32(data_p, 0); - WRITEUINT16(data_p, 0); + P_WriteUINT32(&savebuffer, 0); + P_WriteUINT32(&savebuffer, 0); + P_WriteUINT16(&savebuffer, 0); } - WRITEUINT8(data_p, 0); // compat + P_WriteUINT8(&savebuffer, 0); // compat } // NiGHTS records @@ -4732,25 +4732,22 @@ void G_SaveGameData(gamedata_t *data) { if (!data->nightsrecords[i] || !data->nightsrecords[i]->nummares) { - WRITEUINT8(data_p, 0); + P_WriteUINT8(&savebuffer, 0); continue; } - WRITEUINT8(data_p, data->nightsrecords[i]->nummares); + P_WriteUINT8(&savebuffer, data->nightsrecords[i]->nummares); for (curmare = 0; curmare < (data->nightsrecords[i]->nummares + 1); ++curmare) { - WRITEUINT32(data_p, data->nightsrecords[i]->score[curmare]); - WRITEUINT8(data_p, data->nightsrecords[i]->grade[curmare]); - WRITEUINT32(data_p, data->nightsrecords[i]->time[curmare]); + P_WriteUINT32(&savebuffer, data->nightsrecords[i]->score[curmare]); + P_WriteUINT8(&savebuffer, data->nightsrecords[i]->grade[curmare]); + P_WriteUINT32(&savebuffer, data->nightsrecords[i]->time[curmare]); } } - length = data_p - savebuffer; - - FIL_WriteFile(va(pandf, srb2home, gamedatafilename), savebuffer, length); - free(savebuffer); - savebuffer = NULL; + FIL_WriteFile(va(pandf, srb2home, gamedatafilename), savebuffer.buf, savebuffer.pos); + free(savebuffer.buf); } #define VERSIONSIZE 16 @@ -4761,7 +4758,7 @@ void G_SaveGameData(gamedata_t *data) // void G_LoadGame(UINT32 slot, INT16 mapoverride) { - size_t length; + save_t savebuffer; char vcheck[VERSIONSIZE]; char savename[255]; @@ -4778,18 +4775,18 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) else sprintf(savename, savegamename, slot); - length = FIL_ReadFile(savename, &savebuffer); - if (!length) + savebuffer.size = FIL_ReadFile(savename, &savebuffer.buf); + if (!savebuffer.size) { CONS_Printf(M_GetText("Couldn't read file %s\n"), savename); return; } - save_p = savebuffer; + savebuffer.pos = 0; memset(vcheck, 0, sizeof (vcheck)); sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION); - if (strcmp((const char *)save_p, (const char *)vcheck)) + if (strcmp((const char *)&savebuffer.buf[savebuffer.pos], (const char *)vcheck)) { #ifdef SAVEGAME_OTHERVERSIONS M_StartMessage(M_GetText("Save game from different version.\nYou can load this savegame, but\nsaving afterwards will be disabled.\n\nDo you want to continue anyway?\n\n(Press 'Y' to confirm)\n"), @@ -4799,15 +4796,14 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) M_ClearMenus(true); // so ESC backs out to title M_StartMessage(M_GetText("Save game from different version\n\nPress ESC\n"), NULL, MM_NOTHING); Command_ExitGame_f(); - Z_Free(savebuffer); - save_p = savebuffer = NULL; + Z_Free(savebuffer.buf); // no cheating! memset(&savedata, 0, sizeof(savedata)); #endif return; // bad version } - save_p += VERSIONSIZE; + savebuffer.pos += VERSIONSIZE; // if (demoplayback) // reset game engine // G_StopDemo(); @@ -4816,13 +4812,12 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) // automapactive = false; // dearchive all the modifications - if (!P_LoadGame(mapoverride)) + if (!P_LoadGame(&savebuffer, mapoverride)) { M_ClearMenus(true); // so ESC backs out to title M_StartMessage(M_GetText("Savegame file corrupted\n\nPress ESC\n"), NULL, MM_NOTHING); Command_ExitGame_f(); - Z_Free(savebuffer); - save_p = savebuffer = NULL; + Z_Free(savebuffer.buf); // no cheating! memset(&savedata, 0, sizeof(savedata)); @@ -4830,13 +4825,12 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) } if (marathonmode) { - marathontime = READUINT32(save_p); - marathonmode |= READUINT8(save_p); + marathontime = P_ReadUINT32(&savebuffer); + marathonmode |= P_ReadUINT8(&savebuffer); } // done - Z_Free(savebuffer); - save_p = savebuffer = NULL; + Z_Free(savebuffer.buf); displayplayer = consoleplayer; multiplayer = splitscreen = false; @@ -4854,6 +4848,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) // void G_SaveGame(UINT32 slot, INT16 mapnum) { + save_t savebuffer; boolean saved; char savename[256] = ""; const char *backup; @@ -4867,33 +4862,32 @@ void G_SaveGame(UINT32 slot, INT16 mapnum) gameaction = ga_nothing; { char name[VERSIONSIZE]; - size_t length; - save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); - if (!save_p) + savebuffer.size = SAVEGAMESIZE; + savebuffer.buf = (UINT8 *)malloc(savebuffer.size); + if (!savebuffer.buf) { CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n")); return; } + savebuffer.pos = 0; memset(name, 0, sizeof (name)); sprintf(name, (marathonmode ? "back-up %d" : "version %d"), VERSION); - WRITEMEM(save_p, name, VERSIONSIZE); + P_WriteMem(&savebuffer, name, VERSIONSIZE); - P_SaveGame(mapnum); + P_SaveGame(&savebuffer, mapnum); if (marathonmode) { UINT32 writetime = marathontime; if (!(marathonmode & MA_INGAME)) writetime += TICRATE*5; // live event backup penalty because we don't know how long it takes to get to the next map - WRITEUINT32(save_p, writetime); - WRITEUINT8(save_p, (marathonmode & ~MA_INIT)); + P_WriteUINT32(&savebuffer, writetime); + P_WriteUINT8(&savebuffer, (marathonmode & ~MA_INIT)); } - length = save_p - savebuffer; - saved = FIL_WriteFile(backup, savebuffer, length); - free(savebuffer); - save_p = savebuffer = NULL; + saved = FIL_WriteFile(backup, savebuffer.buf, savebuffer.pos); + free(savebuffer.buf); } gameaction = ga_nothing; @@ -4905,11 +4899,10 @@ void G_SaveGame(UINT32 slot, INT16 mapnum) } #define BADSAVE goto cleanup; -#define CHECKPOS if (save_p >= end_p) BADSAVE void G_SaveGameOver(UINT32 slot, boolean modifylives) { + save_t savebuffer; boolean saved = false; - size_t length; char vcheck[VERSIONSIZE]; char savename[255]; const char *backup; @@ -4920,42 +4913,38 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) sprintf(savename, savegamename, slot); backup = va("%s",savename); - length = FIL_ReadFile(savename, &savebuffer); - if (!length) + savebuffer.size = FIL_ReadFile(savename, &savebuffer.buf); + if (!savebuffer.size) { CONS_Printf(M_GetText("Couldn't read file %s\n"), savename); return; } + savebuffer.pos = 0; + { char temp[sizeof(timeattackfolder)]; - UINT8 *end_p = savebuffer + length; UINT8 *lives_p; SINT8 pllives; #ifdef NEWSKINSAVES INT16 backwardsCompat = 0; #endif - save_p = savebuffer; // Version check memset(vcheck, 0, sizeof (vcheck)); sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION); - if (strcmp((const char *)save_p, (const char *)vcheck)) BADSAVE - save_p += VERSIONSIZE; + if (strcmp((const char *)&savebuffer.buf[savebuffer.pos], (const char *)vcheck)) BADSAVE + savebuffer.pos += VERSIONSIZE; // P_UnArchiveMisc() - (void)READINT16(save_p); - CHECKPOS - (void)READUINT16(save_p); // emeralds - CHECKPOS - READSTRINGN(save_p, temp, sizeof(temp)); // mod it belongs to + (void)P_ReadINT16(&savebuffer); + (void)P_ReadUINT16(&savebuffer); // emeralds + P_ReadStringN(&savebuffer, temp, sizeof(temp)); // mod it belongs to if (strcmp(temp, timeattackfolder)) BADSAVE // P_UnArchivePlayer() - CHECKPOS #ifdef NEWSKINSAVES - backwardsCompat = READUINT16(save_p); - CHECKPOS + backwardsCompat = P_ReadUINT16(&savebuffer); if (backwardsCompat == NEWSKINSAVES) // New save, read skin names #endif @@ -4963,47 +4952,37 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) char ourSkinName[SKINNAMESIZE+1]; char botSkinName[SKINNAMESIZE+1]; - READSTRINGN(save_p, ourSkinName, SKINNAMESIZE); - CHECKPOS + P_ReadStringN(&savebuffer, ourSkinName, SKINNAMESIZE); - READSTRINGN(save_p, botSkinName, SKINNAMESIZE); - CHECKPOS + P_ReadStringN(&savebuffer, botSkinName, SKINNAMESIZE); } - WRITEUINT8(save_p, numgameovers); - CHECKPOS + P_WriteUINT8(&savebuffer, numgameovers); - lives_p = save_p; - pllives = READSINT8(save_p); // lives - CHECKPOS + lives_p = &savebuffer.buf[savebuffer.pos]; + pllives = P_ReadSINT8(&savebuffer); // lives if (modifylives && pllives < startinglivesbalance[numgameovers]) { - pllives = startinglivesbalance[numgameovers]; - WRITESINT8(lives_p, pllives); + *lives_p = startinglivesbalance[numgameovers]; } - (void)READINT32(save_p); // Score - CHECKPOS - (void)READINT32(save_p); // continues + (void)P_ReadINT32(&savebuffer); // Score + (void)P_ReadINT32(&savebuffer); // continues // File end marker check - CHECKPOS - switch (READUINT8(save_p)) + switch (P_ReadUINT8(&savebuffer)) { case 0xb7: { UINT8 i, banksinuse; - CHECKPOS - banksinuse = READUINT8(save_p); - CHECKPOS + banksinuse = P_ReadUINT8(&savebuffer); if (banksinuse > NUM_LUABANKS) BADSAVE for (i = 0; i < banksinuse; i++) { - (void)READINT32(save_p); - CHECKPOS + (void)P_ReadINT32(&savebuffer); } - if (READUINT8(save_p) != 0x1d) + if (P_ReadUINT8(&savebuffer) != 0x1d) BADSAVE } case 0x1d: @@ -5013,7 +4992,7 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) } // done - saved = FIL_WriteFile(backup, savebuffer, length); + saved = FIL_WriteFile(backup, savebuffer.buf, savebuffer.size); } cleanup: @@ -5021,11 +5000,9 @@ cleanup: CONS_Printf(M_GetText("Game saved.\n")); else if (!saved) CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, (marathonmode ? liveeventbackup : savegamename)); - Z_Free(savebuffer); - save_p = savebuffer = NULL; + Z_Free(savebuffer.buf); } -#undef CHECKPOS #undef BADSAVE // diff --git a/src/g_game.h b/src/g_game.h index 0d5fc7e37..2680fa973 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/g_input.c b/src/g_input.c index 4a9692e88..3ba709978 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index b9ab2592d..5d1af10e2 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by Sonic Team Junior. +// Copyright (C) 2020-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -114,7 +114,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt polygonArray[polygonArraySize].numVerts = iNumPts; polygonArray[polygonArraySize].polyFlags = PolyFlags; polygonArray[polygonArraySize].texture = current_texture; - polygonArray[polygonArraySize].shader = (shader_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target; + polygonArray[polygonArraySize].shader = (shader_target != SHADER_NONE) ? HWR_GetShaderFromTarget(shader_target) : shader_target; polygonArray[polygonArraySize].horizonSpecial = horizonSpecial; // default to polygonArraySize so we don't lose order on horizon lines // (yes, it's supposed to be negative, since we're sorting in that direction) @@ -311,7 +311,6 @@ void HWR_RenderBatches(void) int nextIndex = polygonIndexArray[polygonReadPos]; if (polygonArray[index].hash != polygonArray[nextIndex].hash) { - changeState = true; nextShader = polygonArray[nextIndex].shader; nextTexture = polygonArray[nextIndex].texture; nextPolyFlags = polygonArray[nextIndex].polyFlags; @@ -320,14 +319,17 @@ void HWR_RenderBatches(void) nextTexture = 0; if (currentShader != nextShader && cv_glshaders.value && gl_shadersavailable) { + changeState = true; changeShader = true; } if (currentTexture != nextTexture) { + changeState = true; changeTexture = true; } if (currentPolyFlags != nextPolyFlags) { + changeState = true; changePolyFlags = true; } if (cv_glshaders.value && gl_shadersavailable) @@ -339,6 +341,7 @@ void HWR_RenderBatches(void) currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end) { + changeState = true; changeSurfaceInfo = true; } } @@ -346,6 +349,7 @@ void HWR_RenderBatches(void) { if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba) { + changeState = true; changeSurfaceInfo = true; } } diff --git a/src/hardware/hw_batching.h b/src/hardware/hw_batching.h index df1a4c38b..4214ca410 100644 --- a/src/hardware/hw_batching.h +++ b/src/hardware/hw_batching.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by Sonic Team Junior. +// Copyright (C) 2020-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 56f5416cf..b71bf7007 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -450,15 +450,10 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex, GLMipmap_t texture = textures[texnum]; - mipmap->flags = TF_WRAPXY; - mipmap->width = (UINT16)texture->width; - mipmap->height = (UINT16)texture->height; - mipmap->format = textureformat; - blockwidth = texture->width; blockheight = texture->height; - blocksize = (blockwidth * blockheight); - block = MakeBlock(&grtex->mipmap); + blocksize = blockwidth * blockheight; + block = MakeBlock(mipmap); // Composite the columns together. for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) @@ -488,7 +483,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex, GLMipmap_t realpatch = W_CachePatchNumPwad(wadnum, lumpnum, PU_PATCH); } - HWR_DrawTexturePatchInCache(&grtex->mipmap, blockwidth, blockheight, texture, patch, realpatch); + HWR_DrawTexturePatchInCache(mipmap, blockwidth, blockheight, texture, patch, realpatch); if (free_patch) Patch_Free(realpatch); @@ -680,25 +675,24 @@ void HWR_InitMapTextures(void) gl_maptexturesloaded = false; } -static void DeleteTextureMipmap(GLMipmap_t *grMipmap) +static void DeleteTextureMipmap(GLMipmap_t *grMipmap, boolean delete_mipmap) { HWD.pfnDeleteTexture(grMipmap); - // Chroma-keyed textures do not own their texture data, so do not free it - if (!(grMipmap->flags & TF_CHROMAKEYED)) + if (delete_mipmap) Z_Free(grMipmap->data); } -static void FreeMapTexture(GLMapTexture_t *tex) +static void FreeMapTexture(GLMapTexture_t *tex, boolean delete_chromakeys) { if (tex->mipmap.nextcolormap) { - DeleteTextureMipmap(tex->mipmap.nextcolormap); + DeleteTextureMipmap(tex->mipmap.nextcolormap, delete_chromakeys); free(tex->mipmap.nextcolormap); tex->mipmap.nextcolormap = NULL; } - DeleteTextureMipmap(&tex->mipmap); + DeleteTextureMipmap(&tex->mipmap, true); } void HWR_FreeMapTextures(void) @@ -707,8 +701,8 @@ void HWR_FreeMapTextures(void) for (i = 0; i < gl_numtextures; i++) { - FreeMapTexture(&gl_textures[i]); - FreeMapTexture(&gl_flats[i]); + FreeMapTexture(&gl_textures[i], true); + FreeMapTexture(&gl_flats[i], false); } // now the heap don't have any 'user' pointing to our @@ -741,22 +735,7 @@ void HWR_LoadMapTextures(size_t pnumtextures) // -------------------------------------------------------------------------- // Make sure texture is downloaded and set it as the source // -------------------------------------------------------------------------- -static void GetMapTexture(INT32 tex, GLMapTexture_t *grtex, GLMipmap_t *mipmap) -{ - // Generate texture if missing from the cache - if (!mipmap->data && !mipmap->downloaded) - HWR_GenerateTexture(tex, grtex, mipmap); - - // If hardware does not have the texture, then call pfnSetTexture to upload it - if (!mipmap->downloaded) - HWD.pfnSetTexture(mipmap); - HWR_SetCurrentTexture(mipmap); - - // The system-memory data can be purged now. - Z_ChangeTag(mipmap->data, PU_HWRCACHE_UNLOCKED); -} - -GLMapTexture_t *HWR_GetTexture(INT32 tex) +GLMapTexture_t *HWR_GetTexture(INT32 tex, boolean chromakeyed) { if (tex < 0 || tex >= (signed)gl_numtextures) { @@ -769,7 +748,46 @@ GLMapTexture_t *HWR_GetTexture(INT32 tex) GLMapTexture_t *grtex = &gl_textures[tex]; - GetMapTexture(tex, grtex, &grtex->mipmap); + GLMipmap_t *grMipmap = &grtex->mipmap; + GLMipmap_t *originalMipmap = grMipmap; + + if (!originalMipmap->downloaded) + { + originalMipmap->flags = TF_WRAPXY; + originalMipmap->width = (UINT16)textures[tex]->width; + originalMipmap->height = (UINT16)textures[tex]->height; + originalMipmap->format = textureformat; + } + + // If chroma-keyed, create or use a different mipmap for the variant + if (chromakeyed && !textures[tex]->transparency) + { + // Allocate it if it wasn't already + if (!originalMipmap->nextcolormap) + { + GLMipmap_t *newMipmap = calloc(1, sizeof (*grMipmap)); + if (newMipmap == NULL) + I_Error("%s: Out of memory", "HWR_GetTexture"); + + newMipmap->flags = originalMipmap->flags | TF_CHROMAKEYED; + newMipmap->width = originalMipmap->width; + newMipmap->height = originalMipmap->height; + newMipmap->format = originalMipmap->format; + originalMipmap->nextcolormap = newMipmap; + } + + // Generate, upload and bind the variant texture instead of the original one + grMipmap = originalMipmap->nextcolormap; + } + + if (!grMipmap->data) + HWR_GenerateTexture(tex, grtex, grMipmap); + + if (!grMipmap->downloaded) + HWD.pfnSetTexture(grMipmap); + HWR_SetCurrentTexture(grMipmap); + + Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED); return grtex; } @@ -1240,20 +1258,29 @@ void HWR_SetMapPalette(void) // Creates a hardware lighttable from the supplied lighttable. // Returns the id of the hw lighttable, usable in FSurfaceInfo. -UINT32 HWR_CreateLightTable(UINT8 *lighttable) +UINT32 HWR_CreateLightTable(UINT8 *lighttable, RGBA_t *hw_lighttable) { - UINT32 i, id; + UINT32 i; RGBA_t *palette = HWR_GetTexturePalette(); - RGBA_t *hw_lighttable = Z_Malloc(256 * 32 * sizeof(RGBA_t), PU_STATIC, NULL); // To make the palette index -> RGBA mapping easier for the shader, // the hardware lighttable is composed of RGBA colors instead of palette indices. for (i = 0; i < 256 * 32; i++) hw_lighttable[i] = palette[lighttable[i]]; - id = HWD.pfnCreateLightTable(hw_lighttable); - Z_Free(hw_lighttable); - return id; + return HWD.pfnCreateLightTable(hw_lighttable); +} + +// Updates a hardware lighttable of a given id from the supplied lighttable. +void HWR_UpdateLightTable(UINT32 id, UINT8 *lighttable, RGBA_t *hw_lighttable) +{ + UINT32 i; + RGBA_t *palette = HWR_GetTexturePalette(); + + for (i = 0; i < 256 * 32; i++) + hw_lighttable[i] = palette[lighttable[i]]; + + HWD.pfnUpdateLightTable(id, hw_lighttable); } // get hwr lighttable id for colormap, create it if it doesn't already exist @@ -1267,25 +1294,41 @@ UINT32 HWR_GetLightTableID(extracolormap_t *colormap) default_colormap = true; } - // create hw lighttable if there isn't one - if (!colormap->gl_lighttable_id) - { - UINT8 *colormap_pointer; + UINT8 *colormap_pointer; - if (default_colormap) - colormap_pointer = colormaps; // don't actually use the data from the "default colormap" - else - colormap_pointer = colormap->colormap; - colormap->gl_lighttable_id = HWR_CreateLightTable(colormap_pointer); + if (default_colormap) + colormap_pointer = colormaps; // don't actually use the data from the "default colormap" + else + colormap_pointer = colormap->colormap; + + // create hw lighttable if there isn't one + if (colormap->gl_lighttable.data == NULL) + { + Z_Malloc(256 * 32 * sizeof(RGBA_t), PU_HWRLIGHTTABLEDATA, &colormap->gl_lighttable.data); } - return colormap->gl_lighttable_id; + // Generate the texture for this light table + if (!colormap->gl_lighttable.id) + { + colormap->gl_lighttable.id = HWR_CreateLightTable(colormap_pointer, colormap->gl_lighttable.data); + } + // Update the texture if it was directly changed by a script + else if (colormap->gl_lighttable.needs_update) + { + HWR_UpdateLightTable(colormap->gl_lighttable.id, colormap_pointer, colormap->gl_lighttable.data); + } + + colormap->gl_lighttable.needs_update = false; + + return colormap->gl_lighttable.id; } // Note: all hardware lighttable ids assigned before this // call become invalid and must not be used. void HWR_ClearLightTables(void) { + Z_FreeTag(PU_HWRLIGHTTABLEDATA); + if (vid.glstate == VID_GL_LIBRARY_LOADED) HWD.pfnClearLightTables(); } diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 7d06ceb60..77d7133b6 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index ddce7d988..369f59ac2 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 45ee2933a..a5fdc00a4 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -71,6 +71,7 @@ EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value); EXPORT void HWRAPI(SetPaletteLookup)(UINT8 *lut); EXPORT UINT32 HWRAPI(CreateLightTable)(RGBA_t *hw_lighttable); +EXPORT void HWRAPI(UpdateLightTable)(UINT32 id, RGBA_t *hw_lighttable); EXPORT void HWRAPI(ClearLightTables)(void); EXPORT void HWRAPI(SetScreenPalette)(RGBA_t *palette); @@ -125,6 +126,7 @@ struct hwdriver_s SetPaletteLookup pfnSetPaletteLookup; CreateLightTable pfnCreateLightTable; + UpdateLightTable pfnUpdateLightTable; ClearLightTables pfnClearLightTables; SetScreenPalette pfnSetScreenPalette; }; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 807c70989..bf9f7da3b 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -120,7 +120,7 @@ void HWR_GetPatch(patch_t *patch); void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap); void HWR_GetFadeMask(lumpnum_t fademasklumpnum); -GLMapTexture_t *HWR_GetTexture(INT32 tex); +GLMapTexture_t *HWR_GetTexture(INT32 tex, boolean chromakeyed); void HWR_GetLevelFlat(levelflat_t *levelflat, boolean chromakeyed); void HWR_GetRawFlat(lumpnum_t flatlumpnum); @@ -133,7 +133,8 @@ void HWR_UnlockCachedPatch(GLPatch_t *gpatch); void HWR_SetPalette(RGBA_t *palette); void HWR_SetMapPalette(void); -UINT32 HWR_CreateLightTable(UINT8 *lighttable); +UINT32 HWR_CreateLightTable(UINT8 *lighttable, RGBA_t *hw_lighttable); +void HWR_UpdateLightTable(UINT32 id, UINT8 *lighttable, RGBA_t *hw_lighttable); UINT32 HWR_GetLightTableID(extracolormap_t *colormap); void HWR_ClearLightTables(void); diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index e7769edbd..1d2772dc4 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 831c8d7c4..da8965454 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -309,6 +309,43 @@ static FUINT HWR_CalcSlopeLight(FUINT lightnum, angle_t dir, fixed_t delta) return (FUINT)finallight; } +static UINT8 HWR_SideLightLevel(side_t *side, INT16 base_lightlevel) +{ + return max(0, min(255, side->light + + ((side->lightabsolute) ? 0 : base_lightlevel))); +} + +/* TODO: implement per-texture lighting +static UINT8 HWR_TopLightLevel(side_t *side, INT16 base_lightlevel) +{ + return max(0, min(255, side->light_top + + ((side->lightabsolute_top) ? 0 : HWR_SideLightLevel(side, base_lightlevel)))); +} + +static UINT8 HWR_MidLightLevel(side_t *side, INT16 base_lightlevel) +{ + return max(0, min(255, side->light_mid + + ((side->lightabsolute_mid) ? 0 : HWR_SideLightLevel(side, base_lightlevel)))); +} + +static UINT8 HWR_BottomLightLevel(side_t *side, INT16 base_lightlevel) +{ + return max(0, min(255, side->light_bottom + + ((side->lightabsolute_bottom) ? 0 : HWR_SideLightLevel(side, base_lightlevel)))); +} +*/ + +static UINT8 HWR_FloorLightLevel(sector_t *sector, INT16 base_lightlevel) +{ + return max(0, min(255, sector->floorlightlevel + + ((sector->floorlightabsolute) ? 0 : base_lightlevel))); +} + +static UINT8 HWR_CeilingLightLevel(sector_t *sector, INT16 base_lightlevel) +{ + return max(0, min(255, sector->ceilinglightlevel + + ((sector->ceilinglightabsolute) ? 0 : base_lightlevel))); +} // ========================================================================== // FLOOR/CEILING GENERATION FROM SUBSECTORS // ========================================================================== @@ -705,8 +742,9 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, fixed_t v2x = FloatToFixed(wallVerts[1].x); fixed_t v2y = FloatToFixed(wallVerts[1].z); + FUINT lightnum = HWR_SideLightLevel(gl_sidedef, sector->lightlevel); const UINT8 alpha = Surf->PolyColor.s.alpha; - FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y); + lightnum = HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y); extracolormap_t *colormap = NULL; if (!r_renderwalls) @@ -750,13 +788,13 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, { if (pfloor && (pfloor->fofflags & FOF_FOG)) { - lightnum = pfloor->master->frontsector->lightlevel; + lightnum = HWR_SideLightLevel(gl_sidedef, pfloor->master->frontsector->lightlevel); colormap = pfloor->master->frontsector->extra_colormap; lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y); } else { - lightnum = *list[i].lightlevel; + lightnum = HWR_SideLightLevel(gl_sidedef, *list[i].lightlevel); colormap = *list[i].extra_colormap; lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y); } @@ -916,6 +954,7 @@ static boolean HWR_BlendMidtextureSurface(FSurfaceInfo *pSurf) static void HWR_RenderMidtexture(INT32 gl_midtexture, float cliplow, float cliphigh, fixed_t worldtop, fixed_t worldbottom, fixed_t worldhigh, fixed_t worldlow, fixed_t worldtopslope, fixed_t worldbottomslope, fixed_t worldhighslope, fixed_t worldlowslope, UINT32 lightnum, FOutVector *inWallVerts) { + sector_t *front, *back; FOutVector wallVerts[4]; FSurfaceInfo Surf; @@ -925,6 +964,16 @@ static void HWR_RenderMidtexture(INT32 gl_midtexture, float cliplow, float cliph if (!HWR_BlendMidtextureSurface(&Surf)) return; + if (gl_linedef->frontsector->heightsec != -1) + front = §ors[gl_linedef->frontsector->heightsec]; + else + front = gl_linedef->frontsector; + + if (gl_linedef->backsector->heightsec != -1) + back = §ors[gl_linedef->backsector->heightsec]; + else + back = gl_linedef->backsector; + fixed_t texheight = FixedDiv(textureheight[gl_midtexture], abs(gl_sidedef->scaley_mid)); INT32 repeats; @@ -934,15 +983,15 @@ static void HWR_RenderMidtexture(INT32 gl_midtexture, float cliplow, float cliph { fixed_t high, low; - if (gl_frontsector->ceilingheight > gl_backsector->ceilingheight) - high = gl_backsector->ceilingheight; + if (front->ceilingheight > back->ceilingheight) + high = back->ceilingheight; else - high = gl_frontsector->ceilingheight; + high = front->ceilingheight; - if (gl_frontsector->floorheight > gl_backsector->floorheight) - low = gl_frontsector->floorheight; + if (front->floorheight > back->floorheight) + low = front->floorheight; else - low = gl_backsector->floorheight; + low = back->floorheight; repeats = (high - low) / texheight; if ((high - low) % texheight) @@ -951,7 +1000,7 @@ static void HWR_RenderMidtexture(INT32 gl_midtexture, float cliplow, float cliph else repeats = 1; - GLMapTexture_t *grTex = HWR_GetTexture(gl_midtexture); + GLMapTexture_t *grTex = HWR_GetTexture(gl_midtexture, true); float xscale = FixedToFloat(gl_sidedef->scalex_mid); float yscale = FixedToFloat(gl_sidedef->scaley_mid); @@ -969,8 +1018,8 @@ static void HWR_RenderMidtexture(INT32 gl_midtexture, float cliplow, float cliph if (gl_curline->polyseg) { // Change this when polyobjects support slopes - popentop = popentopslope = gl_curline->backsector->ceilingheight; - popenbottom = popenbottomslope = gl_curline->backsector->floorheight; + popentop = popentopslope = back->ceilingheight; + popenbottom = popenbottomslope = back->floorheight; } else { @@ -1167,7 +1216,7 @@ static void HWR_ProcessSeg(void) float cliplow = (float)gl_curline->offset; float cliphigh = cliplow + (gl_curline->flength * FRACUNIT); - FUINT lightnum = gl_frontsector->lightlevel; + FUINT lightnum = HWR_SideLightLevel(gl_sidedef, gl_frontsector->lightlevel); extracolormap_t *colormap = gl_frontsector->extra_colormap; lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y); @@ -1210,7 +1259,7 @@ static void HWR_ProcessSeg(void) // check TOP TEXTURE if ((worldhighslope < worldtopslope || worldhigh < worldtop) && gl_toptexture) { - grTex = HWR_GetTexture(gl_toptexture); + grTex = HWR_GetTexture(gl_toptexture, false); xscale = FixedToFloat(abs(gl_sidedef->scalex_top)); yscale = FixedToFloat(abs(gl_sidedef->scaley_top)); @@ -1300,7 +1349,7 @@ static void HWR_ProcessSeg(void) // check BOTTOM TEXTURE if ((worldlowslope > worldbottomslope || worldlow > worldbottom) && gl_bottomtexture) { - grTex = HWR_GetTexture(gl_bottomtexture); + grTex = HWR_GetTexture(gl_bottomtexture, false); xscale = FixedToFloat(abs(gl_sidedef->scalex_bottom)); yscale = FixedToFloat(abs(gl_sidedef->scaley_bottom)); @@ -1414,7 +1463,7 @@ static void HWR_ProcessSeg(void) // Single sided line... Deal only with the middletexture (if one exists) if (gl_midtexture && gl_linedef->special != SPECIAL_HORIZON_LINE) // (Ignore horizon line for OGL) { - grTex = HWR_GetTexture(gl_midtexture); + grTex = HWR_GetTexture(gl_midtexture, false); xscale = FixedToFloat(gl_sidedef->scalex_mid); yscale = FixedToFloat(gl_sidedef->scaley_mid); @@ -1588,7 +1637,7 @@ static void HWR_ProcessSeg(void) // -- Monster Iestyn 26/06/18 fixed_t texturevpeg = side->rowoffset + side->offsety_mid; - grTex = HWR_GetTexture(texnum); + grTex = HWR_GetTexture(texnum, true); xscale = FixedToFloat(side->scalex_mid); yscale = FixedToFloat(side->scaley_mid); @@ -1628,11 +1677,11 @@ static void HWR_ProcessSeg(void) { blendmode = PF_Fog|PF_NoTexture; - lightnum = rover->master->frontsector->lightlevel; + lightnum = HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel); colormap = rover->master->frontsector->extra_colormap; lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y); - Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap); + Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel), rover->master->frontsector->extra_colormap); if (gl_frontsector->numlights) HWR_SplitWall(gl_frontsector, wallVerts, 0, &Surf, rover->fofflags, rover, blendmode); @@ -1643,7 +1692,7 @@ static void HWR_ProcessSeg(void) { blendmode = PF_Masked; - if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) + if ((rover->fofflags & FOF_TRANSLUCENT && !((rover->fofflags & FOF_SPLAT) && rover->alpha >= 255)) || rover->blend) { blendmode = rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent; Surf.PolyColor.s.alpha = max(0, min(rover->alpha, 255)); @@ -1745,7 +1794,7 @@ static void HWR_ProcessSeg(void) // -- Monster Iestyn 26/06/18 fixed_t texturevpeg = side->rowoffset + side->offsety_mid; - grTex = HWR_GetTexture(texnum); + grTex = HWR_GetTexture(texnum, true); xscale = FixedToFloat(side->scalex_mid); yscale = FixedToFloat(side->scaley_mid); @@ -1785,7 +1834,7 @@ static void HWR_ProcessSeg(void) { blendmode = PF_Fog|PF_NoTexture; - lightnum = rover->master->frontsector->lightlevel; + lightnum = HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel); colormap = rover->master->frontsector->extra_colormap; lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y); @@ -1800,7 +1849,7 @@ static void HWR_ProcessSeg(void) { blendmode = PF_Masked; - if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) + if ((rover->fofflags & FOF_TRANSLUCENT && !((rover->fofflags & FOF_SPLAT) && rover->alpha >= 255)) || rover->blend) { blendmode = rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent; Surf.PolyColor.s.alpha = max(0, min(rover->alpha, 255)); @@ -2442,7 +2491,7 @@ static void HWR_Subsector(size_t num) rover; rover = rover->next) { fixed_t bottomCullHeight, topCullHeight, centerHeight; - + if (!(rover->fofflags & FOF_EXISTS) || !(rover->fofflags & FOF_RENDERPLANES)) continue; if (sub->validcount == validcount) @@ -2454,7 +2503,7 @@ static void HWR_Subsector(size_t num) if (gl_frontsector->cullheight) { - if (HWR_DoCulling(gl_frontsector->cullheight, viewsector->cullheight, gl_viewz, FIXED_TO_FLOAT(bottomCullHeight), FIXED_TO_FLOAT(topCullHeight))) + if (HWR_DoCulling(gl_frontsector->cullheight, viewsector->cullheight, gl_viewz, FIXED_TO_FLOAT(*rover->bottomheight), FIXED_TO_FLOAT(*rover->topheight))) continue; } @@ -2471,17 +2520,17 @@ static void HWR_Subsector(size_t num) UINT8 alpha; light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < bottomCullHeight ? true : false); - alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); + alpha = HWR_FogBlockAlpha(HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), rover->master->frontsector->extra_colormap); HWR_AddTransparentFloor(0, &extrasubsectors[num], false, *rover->bottomheight, - *gl_frontsector->lightlist[light].lightlevel, + HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, true, false, rover->master->frontsector->extra_colormap); } - else if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) // SoM: Flags are more efficient + else if ((rover->fofflags & FOF_TRANSLUCENT && !((rover->fofflags & FOF_SPLAT) && rover->alpha >= 255)) || rover->blend) // SoM: Flags are more efficient { light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < bottomCullHeight ? true : false); @@ -2489,7 +2538,7 @@ static void HWR_Subsector(size_t num) &extrasubsectors[num], false, *rover->bottomheight, - *gl_frontsector->lightlist[light].lightlevel, + HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), max(0, min(rover->alpha, 255)), rover->master->frontsector, HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent), false, rover->fofflags & FOF_SPLAT, *gl_frontsector->lightlist[light].extra_colormap); @@ -2498,8 +2547,9 @@ static void HWR_Subsector(size_t num) { HWR_GetLevelFlat(&levelflats[*rover->bottompic], rover->fofflags & FOF_SPLAT); light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < bottomCullHeight ? true : false); - HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic], - rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); + HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, + HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), + &levelflats[*rover->bottompic], rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); } } @@ -2516,17 +2566,17 @@ static void HWR_Subsector(size_t num) UINT8 alpha; light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < topCullHeight ? true : false); - alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); + alpha = HWR_FogBlockAlpha(HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), rover->master->frontsector->extra_colormap); HWR_AddTransparentFloor(0, &extrasubsectors[num], true, *rover->topheight, - *gl_frontsector->lightlist[light].lightlevel, + HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, true, false, rover->master->frontsector->extra_colormap); } - else if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) + else if ((rover->fofflags & FOF_TRANSLUCENT && !((rover->fofflags & FOF_SPLAT) && rover->alpha >= 255)) || rover->blend) { light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < topCullHeight ? true : false); @@ -2534,7 +2584,7 @@ static void HWR_Subsector(size_t num) &extrasubsectors[num], true, *rover->topheight, - *gl_frontsector->lightlist[light].lightlevel, + HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), max(0, min(rover->alpha, 255)), rover->master->frontsector, HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent), false, rover->fofflags & FOF_SPLAT, *gl_frontsector->lightlist[light].extra_colormap); @@ -2543,8 +2593,9 @@ static void HWR_Subsector(size_t num) { HWR_GetLevelFlat(&levelflats[*rover->toppic], rover->fofflags & FOF_SPLAT); light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < topCullHeight ? true : false); - HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic], - rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); + HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, + HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), + &levelflats[*rover->toppic], rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); } } } @@ -2880,7 +2931,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) } HWR_Lighting(&sSurf, 0, colormap); - sSurf.PolyColor.s.alpha = alpha; + sSurf.PolyColor.s.alpha = FixedMul(thing->alpha, alpha); if (HWR_UseShader()) { @@ -3054,11 +3105,16 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) // baseWallVerts is used to know the final shape to easily get the vertex // co-ordinates memcpy(wallVerts, baseWallVerts, sizeof(baseWallVerts)); + + fixed_t newalpha = spr->mobj->alpha; // if sprite has linkdraw, then dont write to z-buffer (by not using PF_Occlude) // this will result in sprites drawn afterwards to be drawn on top like intended when using linkdraw. if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer) + { + newalpha = spr->mobj->tracer->alpha; occlusion = 0; + } else occlusion = PF_Occlude; @@ -3094,6 +3150,8 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) blend = HWR_GetBlendModeFlag(blendmode)|occlusion; if (!occlusion) use_linkdraw_hack = true; } + + Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha); if (HWR_UseShader()) { @@ -3543,11 +3601,15 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) FBITFIELD blend = 0; FBITFIELD occlusion; boolean use_linkdraw_hack = false; + fixed_t newalpha = spr->mobj->alpha; // if sprite has linkdraw, then dont write to z-buffer (by not using PF_Occlude) // this will result in sprites drawn afterwards to be drawn on top like intended when using linkdraw. if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer) + { occlusion = 0; + newalpha = spr->mobj->tracer->alpha; + } else occlusion = PF_Occlude; @@ -3583,6 +3645,8 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) blend = HWR_GetBlendModeFlag(blendmode)|occlusion; if (!occlusion) use_linkdraw_hack = true; } + + Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha); if (spr->renderflags & RF_SHADOWEFFECTS) { @@ -3893,7 +3957,7 @@ void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boo planeinfo[numplanes].isceiling = isceiling; planeinfo[numplanes].fixedheight = fixedheight; - planeinfo[numplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? 255 : lightlevel; + planeinfo[numplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? lightlevel : 255; // TODO: 2.3: Make transparent FOF planes always use light level planeinfo[numplanes].levelflat = levelflat; planeinfo[numplanes].xsub = xsub; planeinfo[numplanes].alpha = alpha; @@ -3925,7 +3989,7 @@ void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polyse polyplaneinfo[numpolyplanes].isceiling = isceiling; polyplaneinfo[numpolyplanes].fixedheight = fixedheight; - polyplaneinfo[numpolyplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? 255 : lightlevel; + polyplaneinfo[numpolyplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? lightlevel : 255; // TODO: 2.3: Make transparent polyobject planes always use light level polyplaneinfo[numpolyplanes].levelflat = levelflat; polyplaneinfo[numpolyplanes].polysector = polysector; polyplaneinfo[numpolyplanes].alpha = alpha; @@ -4086,7 +4150,7 @@ static void HWR_CreateDrawNodes(void) else if (sortnode[sortindex[i]].wall) { if (!(sortnode[sortindex[i]].wall->blend & PF_NoTexture)) - HWR_GetTexture(sortnode[sortindex[i]].wall->texnum); + HWR_GetTexture(sortnode[sortindex[i]].wall->texnum, true); HWR_RenderWall(sortnode[sortindex[i]].wall->wallVerts, &sortnode[sortindex[i]].wall->Surf, sortnode[sortindex[i]].wall->blend, sortnode[sortindex[i]].wall->fogwall, sortnode[sortindex[i]].wall->lightlevel, sortnode[sortindex[i]].wall->wallcolormap); } @@ -5066,6 +5130,8 @@ static void HWR_DrawSkyBackground(player_t *player) HWD.pfnSetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated); + HWR_GetTexture(texturetranslation[skytexture], false); + if (cv_glskydome.value) { FTransform dometransform; @@ -5081,8 +5147,6 @@ static void HWR_DrawSkyBackground(player_t *player) HWR_SetTransformAiming(&dometransform, player, false); dometransform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); - HWR_GetTexture(texturetranslation[skytexture]); - if (gl_sky.texture != texturetranslation[skytexture]) { HWR_ClearSkyDome(); @@ -5102,7 +5166,6 @@ static void HWR_DrawSkyBackground(player_t *player) float aspectratio; float angleturn; - HWR_GetTexture(texturetranslation[skytexture]); aspectratio = (float)vid.width/(float)vid.height; //Hurdler: the sky is the only texture who need 4.0f instead of 1.0 @@ -5542,7 +5605,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) // Can't have palette rendering if shaders are disabled. boolean HWR_ShouldUsePaletteRendering(void) { - return (cv_glpaletterendering.value && HWR_UseShader()); + return (pMasterPalette != NULL && cv_glpaletterendering.value && HWR_UseShader()); } // enable or disable palette rendering state depending on settings and availability @@ -5659,7 +5722,7 @@ consvar_t cv_glbatching = CVAR_INIT ("gr_batching", "On", 0, CV_OnOff, NULL); static CV_PossibleValue_t glpalettedepth_cons_t[] = {{16, "16 bits"}, {24, "24 bits"}, {0, NULL}}; -consvar_t cv_glpaletterendering = CVAR_INIT ("gr_paletterendering", "Off", CV_SAVE|CV_CALL, CV_OnOff, CV_glpaletterendering_OnChange); +consvar_t cv_glpaletterendering = CVAR_INIT ("gr_paletterendering", "On", CV_SAVE|CV_CALL, CV_OnOff, CV_glpaletterendering_OnChange); consvar_t cv_glpalettedepth = CVAR_INIT ("gr_palettedepth", "16 bits", CV_SAVE|CV_CALL, glpalettedepth_cons_t, CV_glpalettedepth_OnChange); #define ONLY_IF_GL_LOADED if (vid.glstate != VID_GL_LIBRARY_LOADED) return; diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index ea610a48b..2277c32f3 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index a1fbdaa14..426c014d2 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1289,6 +1289,11 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) // Apparently people don't like jump frames like that, so back it goes //if (tics > durs) //durs = tics; + + // Make linkdraw objects use their tracer's alpha value + fixed_t newalpha = spr->mobj->alpha; + if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer) + newalpha = spr->mobj->tracer->alpha; INT32 blendmode; if (spr->mobj->frame & FF_BLENDMASK) @@ -1303,6 +1308,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) Surf.PolyColor.s.alpha = (spr->mobj->flags2 & MF2_SHADOW) ? 0x40 : 0xff; Surf.PolyFlags = HWR_GetBlendModeFlag(blendmode); } + + Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha); // don't forget to enable the depth test because we can't do this // like before: model polygons are not sorted diff --git a/src/hardware/hw_shaders.c b/src/hardware/hw_shaders.c index 36cbb5db9..fde67375f 100644 --- a/src/hardware/hw_shaders.c +++ b/src/hardware/hw_shaders.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021 by Sonic Team Junior. +// Copyright (C) 2021-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -448,6 +448,101 @@ void HWR_LoadAllCustomShaders(void) HWR_LoadCustomShadersFromFile(i, W_FileHasFolders(wadfiles[i])); } +static const char version_directives[][14] = { + "#version 330\n", + "#version 150\n", + "#version 140\n", + "#version 130\n", + "#version 120\n", + "#version 110\n", +}; + +static boolean HWR_VersionDirectiveExists(const char* source) +{ + return strncmp(source, "#version", 8) == 0; +} + +static char* HWR_PrependVersionDirective(const char* source, UINT32 version_index) +{ + const UINT32 version_len = sizeof(version_directives[version_index]) - 1; + const UINT32 source_len = strlen(source); + + char* result = Z_Malloc(source_len + version_len + 1, PU_STATIC, NULL); + strcpy(result, version_directives[version_index]); + strcpy(result + version_len, source); + + return result; +} + +static void HWR_ReplaceVersionInplace(char* shader, UINT32 version_index) +{ + shader[9] = version_directives[version_index][9]; + shader[10] = version_directives[version_index][10]; + shader[11] = version_directives[version_index][11]; +} + +static boolean HWR_CheckVersionDirectives(const char* vert, const char* frag) +{ + return HWR_VersionDirectiveExists(vert) && HWR_VersionDirectiveExists(frag); +} + +static void HWR_TryToCompileShaderWithImplicitVersion(INT32 shader_index, INT32 shaderxlat_id) +{ + char* vert_shader = gl_shaders[shader_index].vertex; + char* frag_shader = gl_shaders[shader_index].fragment; + + boolean vert_shader_version_exists = HWR_VersionDirectiveExists(vert_shader); + boolean frag_shader_version_exists = HWR_VersionDirectiveExists(frag_shader); + + if(!vert_shader_version_exists) { + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: vertex shader '%s' is missing a #version directive\n", HWR_GetShaderName(shaderxlat_id)); + } + + if(!frag_shader_version_exists) { + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: fragment shader '%s' is missing a #version directive\n", HWR_GetShaderName(shaderxlat_id)); + } + + // try to compile as is + HWR_CompileShader(shader_index); + if (gl_shaders[shader_index].compiled) + return; + + // try each version directive + for(UINT32 i = 0; i < sizeof(version_directives) / sizeof(version_directives[0]); ++i) { + CONS_Alert(CONS_NOTICE, "HWR_TryToCompileShaderWithImplicitVersion: Trying %s\n", version_directives[i]); + + if(!vert_shader_version_exists) { + // first time reallocation would have to be made + + if(i == 0) { + void* old = (void*)gl_shaders[shader_index].vertex; + vert_shader = gl_shaders[shader_index].vertex = HWR_PrependVersionDirective(vert_shader, i); + Z_Free(old); + } else { + HWR_ReplaceVersionInplace(vert_shader, i); + } + } + + if(!frag_shader_version_exists) { + if(i == 0) { + void* old = (void*)gl_shaders[shader_index].fragment; + frag_shader = gl_shaders[shader_index].fragment = HWR_PrependVersionDirective(frag_shader, i); + Z_Free(old); + } else { + HWR_ReplaceVersionInplace(frag_shader, i); + } + } + + HWR_CompileShader(shader_index); + if (gl_shaders[shader_index].compiled) { + CONS_Alert(CONS_NOTICE, "HWR_TryToCompileShaderWithImplicitVersion: Compiled with %s\n", + version_directives[i]); + CONS_Alert(CONS_WARNING, "Implicit GLSL version is used. Correct behavior is not guaranteed\n"); + return; + } + } +} + void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3) { UINT16 lump; @@ -610,7 +705,13 @@ skip_field: gl_shaders[shader_index].fragment = Z_StrDup(gl_shadersources[i].fragment); if (!gl_shaders[shader_index].vertex) gl_shaders[shader_index].vertex = Z_StrDup(gl_shadersources[i].vertex); - HWR_CompileShader(shader_index); + + if(!HWR_CheckVersionDirectives(gl_shaders[shader_index].vertex, gl_shaders[shader_index].fragment)) { + HWR_TryToCompileShaderWithImplicitVersion(shader_index, i); + } else { + HWR_CompileShader(shader_index); + } + if (!gl_shaders[shader_index].compiled) CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: A compilation error occured for the %s shader in file %s. See the console messages above for more information.\n", shaderxlat[i].type, wadfiles[wadnum]->filename); } diff --git a/src/hardware/hw_shaders.h b/src/hardware/hw_shaders.h index bb0e6a232..38a2d9911 100644 --- a/src/hardware/hw_shaders.h +++ b/src/hardware/hw_shaders.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021 by Sonic Team Junior. +// Copyright (C) 2021-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/r_opengl/ogl_win.c b/src/hardware/r_opengl/ogl_win.c index c9bf60144..ec8fc9bdb 100644 --- a/src/hardware/r_opengl/ogl_win.c +++ b/src/hardware/r_opengl/ogl_win.c @@ -117,7 +117,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, // handle to DLL module #define pwglDeleteContext wglDeleteContext; #define pwglMakeCurrent wglMakeCurrent; #else -static HMODULE OGL32, GLU32; +static HMODULE OGL32; typedef void *(WINAPI *PFNwglGetProcAddress) (const char *); static PFNwglGetProcAddress pwglGetProcAddress; typedef HGLRC (WINAPI *PFNwglCreateContext) (HDC hdc); @@ -132,13 +132,6 @@ static PFNwglMakeCurrent pwglMakeCurrent; void *GetGLFunc(const char *proc) { void *func = NULL; - if (strncmp(proc, "glu", 3) == 0) - { - if (GLU32) - func = GetProcAddress(GLU32, proc); - else - return NULL; - } if (pwglGetProcAddress) func = pwglGetProcAddress(proc); if (!func) @@ -155,8 +148,6 @@ boolean LoadGL(void) if (!OGL32) return 0; - GLU32 = LoadLibrary("GLU32.DLL"); - pwglGetProcAddress = GetGLFunc("wglGetProcAddress"); pwglCreateContext = GetGLFunc("wglCreateContext"); pwglDeleteContext = GetGLFunc("wglDeleteContext"); @@ -528,7 +519,6 @@ EXPORT void HWRAPI(Shutdown) (void) ReleaseDC(hWnd, hDC); hDC = NULL; } - FreeLibrary(GLU32); FreeLibrary(OGL32); GL_DBG_Printf ("HWRAPI Shutdown(DONE)\n"); } diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 75a92c2fb..e11dd4f16 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -96,6 +96,7 @@ static GLint min_filter = GL_LINEAR; static GLint mag_filter = GL_LINEAR; static GLint anisotropic_filter = 0; static boolean model_lighting = false; +boolean supportMipMap = false; const GLubyte *gl_version = NULL; const GLubyte *gl_renderer = NULL; @@ -417,9 +418,6 @@ static PFNglCopyTexImage2D pglCopyTexImage2D; typedef void (APIENTRY * PFNglCopyTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); static PFNglCopyTexSubImage2D pglCopyTexSubImage2D; #endif -/* GLU functions */ -typedef GLint (APIENTRY * PFNgluBuild2DMipmaps) (GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *data); -static PFNgluBuild2DMipmaps pgluBuild2DMipmaps; /* 1.2 functions for 3D textures */ typedef void (APIENTRY * PFNglTexImage3D) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); @@ -708,9 +706,6 @@ void SetupGLFunc4(void) pglUniform3fv = GetGLFunc("glUniform3fv"); pglGetUniformLocation = GetGLFunc("glGetUniformLocation"); #endif - - // GLU - pgluBuild2DMipmaps = GetGLFunc("gluBuild2DMipmaps"); } EXPORT boolean HWRAPI(InitShaders) (void) @@ -1617,7 +1612,8 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); if (MipMap) { - pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); if (pTexInfo->flags & TF_TRANSPARENT) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff @@ -1638,7 +1634,8 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); if (MipMap) { - pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); if (pTexInfo->flags & TF_TRANSPARENT) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff @@ -1658,7 +1655,8 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) { if (MipMap) { - pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); // Control the mipmap level of detail pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higer the detail if (pTexInfo->flags & TF_TRANSPARENT) @@ -2241,7 +2239,7 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) mag_filter = GL_LINEAR; min_filter = GL_NEAREST; } - if (!pgluBuild2DMipmaps) + if (!supportMipMap) { MipMap = GL_FALSE; min_filter = GL_LINEAR; @@ -3257,6 +3255,24 @@ EXPORT UINT32 HWRAPI(CreateLightTable)(RGBA_t *hw_lighttable) return item->id; } +EXPORT void HWRAPI(UpdateLightTable)(UINT32 id, RGBA_t *hw_lighttable) +{ + LTListItem *item = LightTablesHead; + while (item && item->id != id) + item = item->next; + + if (item) + { + pglBindTexture(GL_TEXTURE_2D, item->id); + + // Just update it + pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 32, GL_RGBA, GL_UNSIGNED_BYTE, hw_lighttable); + + // restore previously bound texture + pglBindTexture(GL_TEXTURE_2D, tex_downloaded); + } +} + // Delete light table textures, ids given before become invalid and must not be used. EXPORT void HWRAPI(ClearLightTables)(void) { diff --git a/src/hardware/r_opengl/r_opengl.h b/src/hardware/r_opengl/r_opengl.h index f7e33c46a..197f75ea8 100644 --- a/src/hardware/r_opengl/r_opengl.h +++ b/src/hardware/r_opengl/r_opengl.h @@ -35,7 +35,6 @@ #else #include -#include #ifdef STATIC_OPENGL // Because of the 1.3 functions, you'll need GLext to compile it if static #define GL_GLEXT_PROTOTYPES @@ -127,6 +126,7 @@ extern GLint screen_width; extern GLint screen_height; extern GLbyte screen_depth; extern GLint maximumAnisotropy; +extern boolean supportMipMap; /** \brief OpenGL flags for video driver */ diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 8489e4058..9333a61d2 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -29,7 +29,7 @@ #include "i_video.h" #include "i_system.h" -#include "st_stuff.h" // ST_HEIGHT +#include "st_stuff.h" #include "r_local.h" #include "keys.h" @@ -204,7 +204,7 @@ void HU_LoadGraphics(void) HU_SetFontProperties(&hu_font, 0, 4, 8, 12); HU_SetFontProperties(&tny_font, 0, 2, 4, 12); HU_SetFontProperties(&cred_font, 0, 16, 16, 16); - HU_SetFontProperties(<_font, 0, 16, 20, 20); + HU_SetFontProperties(<_font, 0, 16, 20, 16); HU_SetFontProperties(&ntb_font, 2, 4, 20, 21); HU_SetFontProperties(&nto_font, 0, 4, 20, 21); @@ -587,8 +587,8 @@ static void Command_CSay_f(void) DoSayCommand(0, 1, HU_CSAY); } -static tic_t spam_tokens[MAXPLAYERS] = { 1 }; // fill the buffer with 1 so the motd can be sent. -static tic_t spam_tics[MAXPLAYERS]; +UINT8 spam_tokens[MAXPLAYERS] = { 1 }; // fill the buffer with 1 so the motd can be sent. +tic_t spam_tics[MAXPLAYERS]; /** Receives a message, processing an ::XD_SAY command. * \sa DoSayCommand @@ -649,14 +649,12 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) else spam_tokens[playernum] -= 1; - // run the lua hook even if we were supposed to eat the msg, netgame consistency goes first. + if (spam_eatmsg) + return; // don't proceed if we were supposed to eat the message. if (LUA_HookPlayerMsg(playernum, target, flags, msg)) return; - if (spam_eatmsg) - return; // don't proceed if we were supposed to eat the message. - // If it's a CSAY, just CECHO and be done with it. if (flags & HU_CSAY) { @@ -1218,27 +1216,36 @@ static void HU_drawMiniChat(void) INT32 charwidth = 4, charheight = 6; INT32 boxw = cv_chatwidth.value; INT32 dx = 0, dy = 0; + boolean prev_linereturn = false; if (!chat_nummsg_min) return; // needless to say it's useless to do anything if we don't have anything to draw. for (size_t i = chat_nummsg_min; i > 0; i--) { - char *msg = V_ChatWordWrap(chatx, boxw-charwidth, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]); + char *msg = V_ChatWordWrap(0, boxw-charwidth-2, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE|V_MONOSPACE, chat_mini[i-1]); for(size_t j = 0; msg[j]; j++) // iterate through msg { if (msg[j] == '\n') // get back down. { - chatheight += charheight; - dx = 0; + if (!prev_linereturn) + { + chatheight += charheight; + dx = 0; + } + prev_linereturn = true; } else if (msg[j] >= FONTSTART) { + prev_linereturn = false; + dx += charwidth; - if (dx >= boxw) + + if (dx >= boxw-charwidth-2) { dx = 0; chatheight += charheight; + prev_linereturn = true; } } } @@ -1250,35 +1257,43 @@ static void HU_drawMiniChat(void) } y = chaty - (chatheight + charheight); + prev_linereturn = false; for (size_t i = 0; i < chat_nummsg_min; i++) // iterate through our hot messages { INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below... INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one. - char *msg = V_ChatWordWrap(chatx, boxw-charwidth, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it. + char *msg = V_ChatWordWrap(0, boxw-charwidth-2, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE|V_MONOSPACE, chat_mini[i]); // get the current message, and word wrap it. UINT8 *colormap = NULL; for(size_t j = 0; msg[j]; j++) // iterate through msg { if (msg[j] == '\n') // get back down. { - dy += charheight; - dx = 0; + if (!prev_linereturn) + { + dy += charheight; + dx = 0; + } + prev_linereturn = true; } else if (msg[j] & 0x80) // get colormap colormap = V_GetStringColormap(((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK); else if (msg[j] >= FONTSTART) { + prev_linereturn = false; + if (cv_chatbacktint.value) // on request of wolfy V_DrawFillConsoleMap(x + dx + 2, y+dy, charwidth, charheight, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); - V_DrawChatCharacter(x + dx + 2, y+dy, msg[j] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|transflag, true, colormap); - + V_DrawChatCharacter(x + dx + 2, y+dy, msg[j] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_MONOSPACE|transflag, true, colormap); dx += charwidth; - if (dx >= boxw) + + if (dx >= boxw-charwidth-2) { dx = 0; dy += charheight; + prev_linereturn = true; } } } @@ -1303,6 +1318,7 @@ static void HU_drawChatLog(INT32 offset) UINT32 i = 0; INT32 chat_topy, chat_bottomy; boolean atbottom = false; + boolean prev_linereturn = false; // make sure that our scroll position isn't "illegal"; if (chat_scroll > chat_maxscroll) @@ -1335,27 +1351,38 @@ static void HU_drawChatLog(INT32 offset) for (i=0; i= FONTSTART) + else { - if ((y+dy+2 >= chat_topy) && (y+dy < (chat_bottomy))) - V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, true, colormap); + prev_linereturn = false; - dx += charwidth; - if (dx >= boxw-charwidth-2 && i= FONTSTART) + { + if ((y+dy+2 >= chat_topy) && (y+dy < (chat_bottomy))) + V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_MONOSPACE, true, colormap); + + dx += charwidth; + } + + if (dx >= boxw-charwidth-2 && i < chat_nummsg_log) // end of message shouldn't count, nor should invisible characters!!!! { dx = 0; dy += charheight; + prev_linereturn = true; } } } diff --git a/src/hu_stuff.h b/src/hu_stuff.h index ca77ed930..2618d873b 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -79,6 +79,9 @@ void HU_AddChatText(const char *text, boolean playsound); // set true when entering a chat message extern boolean chat_on; +extern UINT8 spam_tokens[MAXPLAYERS]; +extern tic_t spam_tics[MAXPLAYERS]; + extern patch_t *emeraldpics[3][8]; extern patch_t *rflagico; extern patch_t *bflagico; diff --git a/src/i_system.h b/src/i_system.h index f4d169113..5348caf4d 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_video.h b/src/i_video.h index 4b459e25b..f3bbc90b9 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/info.c b/src/info.c index d66c24af8..715fe5d53 100644 --- a/src/info.c +++ b/src/info.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1784,8 +1784,8 @@ state_t states[NUMSTATES] = {SPR_RING, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 23, 1, S_RING, 0}, // S_RING // Blue Sphere for special stages - {SPR_SPHR, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BLUESPHERE - {SPR_SPHR, FF_FULLBRIGHT + {SPR_SPHR, FF_SEMIBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BLUESPHERE + {SPR_SPHR, FF_SEMIBRIGHT #ifdef MANIASPHERES |FF_ANIMATE|FF_RANDOMANIM #endif @@ -1794,13 +1794,13 @@ state_t states[NUMSTATES] = // Bomb Sphere {SPR_SPHR, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_BOMBSPHERE2, 0}, // S_BOMBSPHERE1 - {SPR_SPHR, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE3, 0}, // S_BOMBSPHERE2 - {SPR_SPHR, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_BOMBSPHERE4, 0}, // S_BOMBSPHERE3 - {SPR_SPHR, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE1, 0}, // S_BOMBSPHERE4 + {SPR_SPHR, FF_SEMIBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE3, 0}, // S_BOMBSPHERE2 + {SPR_SPHR, FF_SEMIBRIGHT|5, 2, {NULL}, 0, 0, S_BOMBSPHERE4, 0}, // S_BOMBSPHERE3 + {SPR_SPHR, FF_SEMIBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE1, 0}, // S_BOMBSPHERE4 // NiGHTS Chip - {SPR_NCHP, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 15, 2, S_NULL, 0}, // S_NIGHTSCHIP - {SPR_NCHP, FF_FULLBRIGHT|FF_ANIMATE|16, -1, {NULL}, 15, 2, S_NULL, 0}, // S_NIGHTSCHIPBONUS + {SPR_NCHP, FF_SEMIBRIGHT|FF_ANIMATE, -1, {NULL}, 15, 2, S_NULL, 0}, // S_NIGHTSCHIP + {SPR_NCHP, FF_SEMIBRIGHT|FF_ANIMATE|16, -1, {NULL}, 15, 2, S_NULL, 0}, // S_NIGHTSCHIPBONUS // NiGHTS Star {SPR_NSTR, FF_ANIMATE, -1, {NULL}, 14, 2, S_NULL, 0}, // S_NIGHTSSTAR @@ -1858,9 +1858,9 @@ state_t states[NUMSTATES] = {SPR_CEMG, FF_FULLBRIGHT|6, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CEMG7 // Emerald hunt shards - {SPR_SHRD, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SHRD1 - {SPR_SHRD, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SHRD2 - {SPR_SHRD, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SHRD3 + {SPR_SHRD, FF_SEMIBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SHRD1 + {SPR_SHRD, FF_SEMIBRIGHT|1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SHRD2 + {SPR_SHRD, FF_SEMIBRIGHT|2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SHRD3 // Bubble Source {SPR_BBLS, 0, 8, {A_BubbleSpawn}, 2048, 0, S_BUBBLES2, 0}, // S_BUBBLES1 diff --git a/src/info.h b/src/info.h index f58aee07d..ddbfc31b7 100644 --- a/src/info.h +++ b/src/info.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 6d2c8661e..18ae53405 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -3181,17 +3181,25 @@ static int lib_rTextureNumForName(lua_State *L) static int lib_rCheckTextureNameForNum(lua_State *L) { + char s[9]; INT32 num = (INT32)luaL_checkinteger(L, 1); //HUDSAFE - lua_pushstring(L, R_CheckTextureNameForNum(num)); + + M_Memcpy(s, R_CheckTextureNameForNum(num), 8); + s[8] = '\0'; + lua_pushstring(L, s); return 1; } static int lib_rTextureNameForNum(lua_State *L) { + char s[9]; INT32 num = (INT32)luaL_checkinteger(L, 1); //HUDSAFE - lua_pushstring(L, R_TextureNameForNum(num)); + + M_Memcpy(s, R_TextureNameForNum(num), 8); + s[8] = '\0'; + lua_pushstring(L, s); return 1; } @@ -3878,7 +3886,7 @@ static int lib_gAddPlayer(lua_State *L) player_t *newplayer; SINT8 skinnum = 0, bot; - for (i = 0; i < MAXPLAYERS; i++) + for (i = 1; i < MAXPLAYERS; i++) { if (!playeringame[i]) break; diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c index c29eadecc..f570c229b 100644 --- a/src/lua_blockmaplib.c +++ b/src/lua_blockmaplib.c @@ -254,11 +254,10 @@ static int lib_searchBlockmap(lua_State *L) } else // mobj and function only - search around mobj's radius by default { - fixed_t radius = mobj->radius + MAXRADIUS; - x1 = mobj->x - radius; - x2 = mobj->x + radius; - y1 = mobj->y - radius; - y2 = mobj->y + radius; + x1 = mobj->x - mobj->radius; + x2 = mobj->x + mobj->radius; + y1 = mobj->y - mobj->radius; + y2 = mobj->y + mobj->radius; } lua_settop(L, 2); // pop everything except function, mobj diff --git a/src/lua_colorlib.c b/src/lua_colorlib.c index 3fab589b2..2743635ed 100644 --- a/src/lua_colorlib.c +++ b/src/lua_colorlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021-2022 by "Lactozilla". -// Copyright (C) 2014-2023 by Sonic Team Junior. +// Copyright (C) 2021-2024 by Lactozilla. +// Copyright (C) 2014-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -593,7 +593,7 @@ static int extracolormap_set(lua_State *L) || exc->fadergba != old_fade_rgba || exc->fadestart != old_fade_start || exc->fadeend != old_fade_end) - R_GenerateLightTable(exc, true); + R_UpdateLightTable(exc, true); return 0; } diff --git a/src/lua_hook.h b/src/lua_hook.h index 17e0e99a0..ce79cd1cb 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -72,6 +72,7 @@ automatically. X (MusicChange),\ X (PlayerHeight),/* override player height */\ X (PlayerCanEnterSpinGaps),\ + X (AddonLoaded),\ X (KeyDown),\ X (KeyUp),\ diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 54381e4ae..1bf3caf65 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -498,7 +498,25 @@ static int call_string_hooks(Hook_State *hook) static int call_mobj_type_hooks(Hook_State *hook, mobjtype_t mobj_type) { - return call_mapped(hook, &mobjHookIds[mobj_type][hook->hook_type]); + int numCalls = call_mapped(hook, &mobjHookIds[mobj_type][hook->hook_type]); + + if (numCalls > 0 && mobj_type == MT_NULL && ( + hook->hook_type == MOBJ_HOOK(MobjThinker ) + || hook->hook_type == MOBJ_HOOK(MobjCollide ) + || hook->hook_type == MOBJ_HOOK(MobjLineCollide) + || hook->hook_type == MOBJ_HOOK(MobjMoveCollide) + || hook->hook_type == MOBJ_HOOK(MobjFuse ) + || hook->hook_type == MOBJ_HOOK(MobjThinker ) + || hook->hook_type == MOBJ_HOOK(BossThinker ) + || hook->hook_type == MOBJ_HOOK(MobjMoveBlocked) + || hook->hook_type == MOBJ_HOOK(FollowMobj ) + )) + LUA_UsageWarning(L, va( + "%s hooks not attached to a specific mobj type are deprecated and will be removed.", + mobjHookNames[hook->hook_type]) + ); + + return numCalls; } static void call_hud_hooks @@ -751,7 +769,7 @@ static void hook_think_frame(int type) PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src); else if (type == 6) PS_SetPostThinkFrameHookInfo(hook_index, time_taken, ar.short_src); - + hook_index++; } } diff --git a/src/lua_hud.h b/src/lua_hud.h index 36ce230ed..ae938e28a 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2023 by Sonic Team Junior. +// Copyright (C) 2014-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index d6771f108..d2b3d9679 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2023 by Sonic Team Junior. +// Copyright (C) 2014-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_hudlib_drawlist.c b/src/lua_hudlib_drawlist.c index cb58e628e..358d615cf 100644 --- a/src/lua_hudlib_drawlist.c +++ b/src/lua_hudlib_drawlist.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2023 by Sonic Team Junior. +// Copyright (C) 2014-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 511c20031..a65ee23eb 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_libs.h b/src/lua_libs.h index 90c7bba7c..e1585f488 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 6b489f22b..c946b10ce 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -213,6 +213,14 @@ enum side_e { side_sector, side_special, side_repeatcnt, + side_light, + side_light_top, + side_light_mid, + side_light_bottom, + side_lightabsolute, + side_lightabsolute_top, + side_lightabsolute_mid, + side_lightabsolute_bottom, side_text }; @@ -241,6 +249,14 @@ static const char *const side_opt[] = { "sector", "special", "repeatcnt", + "light", + "light_top", + "light_mid", + "light_bottom", + "lightabsolute", + "lightabsolute_top", + "lightabsolute_mid", + "lightabsolute_bottom", "text", NULL}; @@ -1311,6 +1327,30 @@ static int side_get(lua_State *L) case side_repeatcnt: lua_pushinteger(L, side->repeatcnt); return 1; + case side_light: + lua_pushinteger(L, side->light); + return 1; + case side_light_top: + lua_pushinteger(L, side->light_top); + return 1; + case side_light_mid: + lua_pushinteger(L, side->light_mid); + return 1; + case side_light_bottom: + lua_pushinteger(L, side->light_bottom); + return 1; + case side_lightabsolute: + lua_pushboolean(L, side->lightabsolute); + return 1; + case side_lightabsolute_top: + lua_pushboolean(L, side->lightabsolute_top); + return 1; + case side_lightabsolute_mid: + lua_pushboolean(L, side->lightabsolute_mid); + return 1; + case side_lightabsolute_bottom: + lua_pushboolean(L, side->lightabsolute_bottom); + return 1; // TODO: 2.3: Delete case side_text: { @@ -1413,6 +1453,30 @@ static int side_set(lua_State *L) case side_repeatcnt: side->repeatcnt = luaL_checkinteger(L, 3); break; + case side_light: + side->light = luaL_checkinteger(L, 3); + break; + case side_light_top: + side->light_top = luaL_checkinteger(L, 3); + break; + case side_light_mid: + side->light_mid = luaL_checkinteger(L, 3); + break; + case side_light_bottom: + side->light_bottom = luaL_checkinteger(L, 3); + break; + case side_lightabsolute: + side->lightabsolute = luaL_checkboolean(L, 3); + break; + case side_lightabsolute_top: + side->lightabsolute_top = luaL_checkboolean(L, 3); + break; + case side_lightabsolute_mid: + side->lightabsolute_mid = luaL_checkboolean(L, 3); + break; + case side_lightabsolute_bottom: + side->lightabsolute_bottom = luaL_checkboolean(L, 3); + break; } return 0; } diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index de7065790..6bdebf774 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -69,6 +69,7 @@ enum mobj_e { mobj_color, mobj_translation, mobj_blendmode, + mobj_alpha, mobj_bnext, mobj_bprev, mobj_hnext, @@ -150,6 +151,7 @@ static const char *const mobj_opt[] = { "color", "translation", "blendmode", + "alpha", "bnext", "bprev", "hnext", @@ -196,12 +198,12 @@ static int mobj_get(lua_State *L) enum mobj_e field = Lua_optoption(L, 2, -1, mobj_fields_ref); lua_settop(L, 2); - if (!mo || !ISINLEVEL) { + if (P_MobjWasRemoved(mo) || !ISINLEVEL) { if (field == mobj_valid) { lua_pushboolean(L, 0); return 1; } - if (!mo) { + if (P_MobjWasRemoved(mo)) { return LUA_ErrInvalid(L, "mobj_t"); } else return luaL_error(L, "Do not access an mobj_t field outside a level!"); @@ -354,6 +356,9 @@ static int mobj_get(lua_State *L) case mobj_blendmode: lua_pushinteger(L, mo->blendmode); break; + case mobj_alpha: + lua_pushfixed(L, mo->alpha); + break; case mobj_bnext: if (mo->blocknode && mo->blocknode->bnext) { LUA_PushUserdata(L, mo->blocknode->bnext->mobj, META_MOBJ); @@ -733,6 +738,16 @@ static int mobj_set(lua_State *L) mo->blendmode = blendmode; break; } + case mobj_alpha: + { + fixed_t alpha = luaL_checkfixed(L, 3); + if (alpha < 0) + alpha = 0; + else if (alpha > FRACUNIT) + alpha = FRACUNIT; + mo->alpha = alpha; + break; + } case mobj_bnext: return NOSETPOS; case mobj_bprev: diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 744a56f7f..37b42fde5 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_script.c b/src/lua_script.c index 057899555..686555a16 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1098,7 +1098,7 @@ static UINT8 GetUserdataArchType(int index) return ARCH_NULL; } -static UINT8 ArchiveValue(int TABLESINDEX, int myindex) +static UINT8 ArchiveValue(save_t *save_p, int TABLESINDEX, int myindex) { if (myindex < 0) myindex = lua_gettop(gL)+1+myindex; @@ -1106,34 +1106,34 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { case LUA_TNONE: case LUA_TNIL: - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); break; // This might be a problem. D: case LUA_TLIGHTUSERDATA: case LUA_TTHREAD: case LUA_TFUNCTION: - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); return 2; case LUA_TBOOLEAN: - WRITEUINT8(save_p, lua_toboolean(gL, myindex) ? ARCH_TRUE : ARCH_FALSE); + P_WriteUINT8(save_p, lua_toboolean(gL, myindex) ? ARCH_TRUE : ARCH_FALSE); break; case LUA_TNUMBER: { lua_Integer number = lua_tointeger(gL, myindex); if (number >= INT8_MIN && number <= INT8_MAX) { - WRITEUINT8(save_p, ARCH_INT8); - WRITESINT8(save_p, number); + P_WriteUINT8(save_p, ARCH_INT8); + P_WriteSINT8(save_p, number); } else if (number >= INT16_MIN && number <= INT16_MAX) { - WRITEUINT8(save_p, ARCH_INT16); - WRITEINT16(save_p, number); + P_WriteUINT8(save_p, ARCH_INT16); + P_WriteINT16(save_p, number); } else { - WRITEUINT8(save_p, ARCH_INT32); - WRITEFIXED(save_p, number); + P_WriteUINT8(save_p, ARCH_INT32); + P_WriteFixed(save_p, number); } break; } @@ -1144,23 +1144,23 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) UINT32 i = 0; // if you're wondering why we're writing a string to save_p this way, // it turns out that Lua can have embedded zeros ('\0') in the strings, - // so we can't use WRITESTRING as that cuts off when it finds a '\0'. + // so we can't use P_WriteString as that cuts off when it finds a '\0'. // Saving the size of the string also allows us to get the size of the string on the other end, // fixing the awful crashes previously encountered for reading strings longer than 1024 // (yes I know that's kind of a stupid thing to care about, but it'd be evil to trim or ignore them?) // -- Monster Iestyn 05/08/18 if (len < 255) { - WRITEUINT8(save_p, ARCH_SMALLSTRING); - WRITEUINT8(save_p, len); // save size of string + P_WriteUINT8(save_p, ARCH_SMALLSTRING); + P_WriteUINT8(save_p, len); // save size of string } else { - WRITEUINT8(save_p, ARCH_LARGESTRING); - WRITEUINT32(save_p, len); // save size of string + P_WriteUINT8(save_p, ARCH_LARGESTRING); + P_WriteUINT32(save_p, len); // save size of string } while (i < len) - WRITECHAR(save_p, s[i++]); // write chars individually, including the embedded zeros + P_WriteChar(save_p, s[i++]); // write chars individually, including the embedded zeros break; } case LUA_TTABLE: @@ -1186,13 +1186,13 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) if (t == 0) { CONS_Alert(CONS_ERROR, "Too many tables to archive!\n"); - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); return 0; } } - WRITEUINT8(save_p, ARCH_TABLE); - WRITEUINT16(save_p, t); + P_WriteUINT8(save_p, ARCH_TABLE); + P_WriteUINT16(save_p, t); if (!found) { @@ -1208,25 +1208,25 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) case ARCH_MOBJINFO: { mobjinfo_t *info = *((mobjinfo_t **)lua_touserdata(gL, myindex)); - WRITEUINT8(save_p, ARCH_MOBJINFO); - WRITEUINT16(save_p, info - mobjinfo); + P_WriteUINT8(save_p, ARCH_MOBJINFO); + P_WriteUINT16(save_p, info - mobjinfo); break; } case ARCH_STATE: { state_t *state = *((state_t **)lua_touserdata(gL, myindex)); - WRITEUINT8(save_p, ARCH_STATE); - WRITEUINT16(save_p, state - states); + P_WriteUINT8(save_p, ARCH_STATE); + P_WriteUINT16(save_p, state - states); break; } case ARCH_MOBJ: { mobj_t *mobj = *((mobj_t **)lua_touserdata(gL, myindex)); if (!mobj) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_MOBJ); - WRITEUINT32(save_p, mobj->mobjnum); + P_WriteUINT8(save_p, ARCH_MOBJ); + P_WriteUINT32(save_p, mobj->mobjnum); } break; } @@ -1234,10 +1234,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { player_t *player = *((player_t **)lua_touserdata(gL, myindex)); if (!player) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_PLAYER); - WRITEUINT8(save_p, player - players); + P_WriteUINT8(save_p, ARCH_PLAYER); + P_WriteUINT8(save_p, player - players); } break; } @@ -1245,10 +1245,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { mapthing_t *mapthing = *((mapthing_t **)lua_touserdata(gL, myindex)); if (!mapthing) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_MAPTHING); - WRITEUINT16(save_p, mapthing - mapthings); + P_WriteUINT8(save_p, ARCH_MAPTHING); + P_WriteUINT16(save_p, mapthing - mapthings); } break; } @@ -1256,10 +1256,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { vertex_t *vertex = *((vertex_t **)lua_touserdata(gL, myindex)); if (!vertex) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_VERTEX); - WRITEUINT16(save_p, vertex - vertexes); + P_WriteUINT8(save_p, ARCH_VERTEX); + P_WriteUINT16(save_p, vertex - vertexes); } break; } @@ -1267,10 +1267,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { line_t *line = *((line_t **)lua_touserdata(gL, myindex)); if (!line) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_LINE); - WRITEUINT16(save_p, line - lines); + P_WriteUINT8(save_p, ARCH_LINE); + P_WriteUINT16(save_p, line - lines); } break; } @@ -1278,10 +1278,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { side_t *side = *((side_t **)lua_touserdata(gL, myindex)); if (!side) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_SIDE); - WRITEUINT16(save_p, side - sides); + P_WriteUINT8(save_p, ARCH_SIDE); + P_WriteUINT16(save_p, side - sides); } break; } @@ -1289,10 +1289,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { subsector_t *subsector = *((subsector_t **)lua_touserdata(gL, myindex)); if (!subsector) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_SUBSECTOR); - WRITEUINT16(save_p, subsector - subsectors); + P_WriteUINT8(save_p, ARCH_SUBSECTOR); + P_WriteUINT16(save_p, subsector - subsectors); } break; } @@ -1300,10 +1300,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { sector_t *sector = *((sector_t **)lua_touserdata(gL, myindex)); if (!sector) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_SECTOR); - WRITEUINT16(save_p, sector - sectors); + P_WriteUINT8(save_p, ARCH_SECTOR); + P_WriteUINT16(save_p, sector - sectors); } break; } @@ -1312,10 +1312,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { seg_t *seg = *((seg_t **)lua_touserdata(gL, myindex)); if (!seg) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_SEG); - WRITEUINT16(save_p, seg - segs); + P_WriteUINT8(save_p, ARCH_SEG); + P_WriteUINT16(save_p, seg - segs); } break; } @@ -1323,10 +1323,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { node_t *node = *((node_t **)lua_touserdata(gL, myindex)); if (!node) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_NODE); - WRITEUINT16(save_p, node - nodes); + P_WriteUINT8(save_p, ARCH_NODE); + P_WriteUINT16(save_p, node - nodes); } break; } @@ -1335,16 +1335,16 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { ffloor_t *rover = *((ffloor_t **)lua_touserdata(gL, myindex)); if (!rover) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { UINT16 i = P_GetFFloorID(rover); if (i == UINT16_MAX) // invalid ID - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_FFLOOR); - WRITEUINT16(save_p, rover->target - sectors); - WRITEUINT16(save_p, i); + P_WriteUINT8(save_p, ARCH_FFLOOR); + P_WriteUINT16(save_p, rover->target - sectors); + P_WriteUINT16(save_p, i); } } break; @@ -1353,10 +1353,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { polyobj_t *polyobj = *((polyobj_t **)lua_touserdata(gL, myindex)); if (!polyobj) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_POLYOBJ); - WRITEUINT16(save_p, polyobj-PolyObjects); + P_WriteUINT8(save_p, ARCH_POLYOBJ); + P_WriteUINT16(save_p, polyobj-PolyObjects); } break; } @@ -1364,10 +1364,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { pslope_t *slope = *((pslope_t **)lua_touserdata(gL, myindex)); if (!slope) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_SLOPE); - WRITEUINT16(save_p, slope->id); + P_WriteUINT8(save_p, ARCH_SLOPE); + P_WriteUINT16(save_p, slope->id); } break; } @@ -1375,36 +1375,36 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex)); if (!header) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_MAPHEADER); - WRITEUINT16(save_p, header - *mapheaderinfo); + P_WriteUINT8(save_p, ARCH_MAPHEADER); + P_WriteUINT16(save_p, header - *mapheaderinfo); } break; } case ARCH_SKINCOLOR: { skincolor_t *info = *((skincolor_t **)lua_touserdata(gL, myindex)); - WRITEUINT8(save_p, ARCH_SKINCOLOR); - WRITEUINT16(save_p, info - skincolors); + P_WriteUINT8(save_p, ARCH_SKINCOLOR); + P_WriteUINT16(save_p, info - skincolors); break; } case ARCH_MOUSE: { mouse_t *m = *((mouse_t **)lua_touserdata(gL, myindex)); - WRITEUINT8(save_p, ARCH_MOUSE); - WRITEUINT8(save_p, m == &mouse ? 1 : 2); + P_WriteUINT8(save_p, ARCH_MOUSE); + P_WriteUINT8(save_p, m == &mouse ? 1 : 2); break; } case ARCH_SKIN: { skin_t *skin = *((skin_t **)lua_touserdata(gL, myindex)); - WRITEUINT8(save_p, ARCH_SKIN); - WRITEUINT8(save_p, skin->skinnum); // UINT8 because MAXSKINS must be <= 256 + P_WriteUINT8(save_p, ARCH_SKIN); + P_WriteUINT8(save_p, skin->skinnum); // UINT8 because MAXSKINS must be <= 256 break; } default: - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); return 2; } break; @@ -1412,14 +1412,14 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) return 0; } -static void ArchiveExtVars(void *pointer, const char *ptype) +static void ArchiveExtVars(save_t *save_p, void *pointer, const char *ptype) { int TABLESINDEX; UINT16 i; if (!gL) { if (fastcmp(ptype,"player")) // players must always be included, even if no vars - WRITEUINT16(save_p, 0); + P_WriteUINT16(save_p, 0); return; } @@ -1435,7 +1435,7 @@ static void ArchiveExtVars(void *pointer, const char *ptype) { // no extra values table lua_pop(gL, 1); if (fastcmp(ptype,"player")) // players must always be included, even if no vars - WRITEUINT16(save_p, 0); + P_WriteUINT16(save_p, 0); return; } @@ -1447,20 +1447,20 @@ static void ArchiveExtVars(void *pointer, const char *ptype) if (i == 0) { if (fastcmp(ptype,"player")) // always include players even if they have no extra variables - WRITEUINT16(save_p, 0); + P_WriteUINT16(save_p, 0); lua_pop(gL, 1); return; } if (fastcmp(ptype,"mobj")) // mobjs must write their mobjnum as a header - WRITEUINT32(save_p, ((mobj_t *)pointer)->mobjnum); - WRITEUINT16(save_p, i); + P_WriteUINT32(save_p, ((mobj_t *)pointer)->mobjnum); + P_WriteUINT16(save_p, i); lua_pushnil(gL); while (lua_next(gL, -2)) { I_Assert(lua_type(gL, -2) == LUA_TSTRING); - WRITESTRING(save_p, lua_tostring(gL, -2)); - if (ArchiveValue(TABLESINDEX, -1) == 2) + P_WriteString(save_p, lua_tostring(gL, -2)); + if (ArchiveValue(save_p, TABLESINDEX, -1) == 2) CONS_Alert(CONS_ERROR, "Type of value for %s entry '%s' (%s) could not be archived!\n", ptype, lua_tostring(gL, -2), luaL_typename(gL, -1)); lua_pop(gL, 1); } @@ -1468,16 +1468,19 @@ static void ArchiveExtVars(void *pointer, const char *ptype) lua_pop(gL, 1); } +// FIXME: remove and pass as local variable +static save_t *lua_save_p; + static int NetArchive(lua_State *L) { int TABLESINDEX = lua_upvalueindex(1); int i, n = lua_gettop(L); for (i = 1; i <= n; i++) - ArchiveValue(TABLESINDEX, i); + ArchiveValue(lua_save_p, TABLESINDEX, i); return n; } -static void ArchiveTables(void) +static void ArchiveTables(save_t *save_p) { int TABLESINDEX; UINT16 i, n; @@ -1496,14 +1499,14 @@ static void ArchiveTables(void) while (lua_next(gL, -2)) { // Write key - e = ArchiveValue(TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this. + e = ArchiveValue(save_p, TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this. if (e == 1) n++; // the table contained a new table we'll have to archive. :( else if (e == 2) // invalid key type (function, thread, lightuserdata, or anything we don't recognise) CONS_Alert(CONS_ERROR, "Index '%s' (%s) of table %d could not be archived!\n", lua_tostring(gL, -2), luaL_typename(gL, -2), i); // Write value - e = ArchiveValue(TABLESINDEX, -1); + e = ArchiveValue(save_p, TABLESINDEX, -1); if (e == 1) n++; // the table contained a new table we'll have to archive. :( else if (e == 2) // invalid value type @@ -1511,7 +1514,7 @@ static void ArchiveTables(void) lua_pop(gL, 1); } - WRITEUINT8(save_p, ARCH_TEND); + P_WriteUINT8(save_p, ARCH_TEND); // Write metatable ID if (lua_getmetatable(gL, -1)) @@ -1520,19 +1523,19 @@ static void ArchiveTables(void) 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)); + P_WriteUINT16(save_p, lua_isnil(gL, -1) ? 0 : lua_tointeger(gL, -1)); lua_pop(gL, 3); } else - WRITEUINT16(save_p, 0); + P_WriteUINT16(save_p, 0); lua_pop(gL, 1); } } -static UINT8 UnArchiveValue(int TABLESINDEX) +static UINT8 UnArchiveValue(save_t *save_p, int TABLESINDEX) { - UINT8 type = READUINT8(save_p); + UINT8 type = P_ReadUINT8(save_p); switch (type) { case ARCH_NULL: @@ -1545,13 +1548,13 @@ static UINT8 UnArchiveValue(int TABLESINDEX) lua_pushboolean(gL, false); break; case ARCH_INT8: - lua_pushinteger(gL, READSINT8(save_p)); + lua_pushinteger(gL, P_ReadSINT8(save_p)); break; case ARCH_INT16: - lua_pushinteger(gL, READINT16(save_p)); + lua_pushinteger(gL, P_ReadINT16(save_p)); break; case ARCH_INT32: - lua_pushinteger(gL, READFIXED(save_p)); + lua_pushinteger(gL, P_ReadFixed(save_p)); break; case ARCH_SMALLSTRING: case ARCH_LARGESTRING: @@ -1562,23 +1565,23 @@ static UINT8 UnArchiveValue(int TABLESINDEX) // See my comments in the ArchiveValue function; // it's much the same for reading strings as writing them! - // (i.e. we can't use READSTRING either) + // (i.e. we can't use P_ReadString either) // -- Monster Iestyn 05/08/18 if (type == ARCH_SMALLSTRING) - len = READUINT8(save_p); // length of string, including embedded zeros + len = P_ReadUINT8(save_p); // length of string, including embedded zeros else - len = READUINT32(save_p); // length of string, including embedded zeros + len = P_ReadUINT32(save_p); // length of string, including embedded zeros value = malloc(len); // make temp buffer of size len // now read the actual string while (i < len) - value[i++] = READCHAR(save_p); // read chars individually, including the embedded zeros + value[i++] = P_ReadChar(save_p); // read chars individually, including the embedded zeros lua_pushlstring(gL, value, len); // push the string (note: this function supports embedded zeros) free(value); // free the buffer break; } case ARCH_TABLE: { - UINT16 tid = READUINT16(save_p); + UINT16 tid = P_ReadUINT16(save_p); lua_rawgeti(gL, TABLESINDEX, tid); if (lua_isnil(gL, -1)) { @@ -1591,69 +1594,69 @@ static UINT8 UnArchiveValue(int TABLESINDEX) break; } case ARCH_MOBJINFO: - LUA_PushUserdata(gL, &mobjinfo[READUINT16(save_p)], META_MOBJINFO); + LUA_PushUserdata(gL, &mobjinfo[P_ReadUINT16(save_p)], META_MOBJINFO); break; case ARCH_STATE: - LUA_PushUserdata(gL, &states[READUINT16(save_p)], META_STATE); + LUA_PushUserdata(gL, &states[P_ReadUINT16(save_p)], META_STATE); break; case ARCH_MOBJ: - LUA_PushUserdata(gL, P_FindNewPosition(READUINT32(save_p)), META_MOBJ); + LUA_PushUserdata(gL, P_FindNewPosition(P_ReadUINT32(save_p)), META_MOBJ); break; case ARCH_PLAYER: - LUA_PushUserdata(gL, &players[READUINT8(save_p)], META_PLAYER); + LUA_PushUserdata(gL, &players[P_ReadUINT8(save_p)], META_PLAYER); break; case ARCH_MAPTHING: - LUA_PushUserdata(gL, &mapthings[READUINT16(save_p)], META_MAPTHING); + LUA_PushUserdata(gL, &mapthings[P_ReadUINT16(save_p)], META_MAPTHING); break; case ARCH_VERTEX: - LUA_PushUserdata(gL, &vertexes[READUINT16(save_p)], META_VERTEX); + LUA_PushUserdata(gL, &vertexes[P_ReadUINT16(save_p)], META_VERTEX); break; case ARCH_LINE: - LUA_PushUserdata(gL, &lines[READUINT16(save_p)], META_LINE); + LUA_PushUserdata(gL, &lines[P_ReadUINT16(save_p)], META_LINE); break; case ARCH_SIDE: - LUA_PushUserdata(gL, &sides[READUINT16(save_p)], META_SIDE); + LUA_PushUserdata(gL, &sides[P_ReadUINT16(save_p)], META_SIDE); break; case ARCH_SUBSECTOR: - LUA_PushUserdata(gL, &subsectors[READUINT16(save_p)], META_SUBSECTOR); + LUA_PushUserdata(gL, &subsectors[P_ReadUINT16(save_p)], META_SUBSECTOR); break; case ARCH_SECTOR: - LUA_PushUserdata(gL, §ors[READUINT16(save_p)], META_SECTOR); + LUA_PushUserdata(gL, §ors[P_ReadUINT16(save_p)], META_SECTOR); break; #ifdef HAVE_LUA_SEGS case ARCH_SEG: - LUA_PushUserdata(gL, &segs[READUINT16(save_p)], META_SEG); + LUA_PushUserdata(gL, &segs[P_ReadUINT16(save_p)], META_SEG); break; case ARCH_NODE: - LUA_PushUserdata(gL, &nodes[READUINT16(save_p)], META_NODE); + LUA_PushUserdata(gL, &nodes[P_ReadUINT16(save_p)], META_NODE); break; #endif case ARCH_FFLOOR: { - sector_t *sector = §ors[READUINT16(save_p)]; - UINT16 id = READUINT16(save_p); + sector_t *sector = §ors[P_ReadUINT16(save_p)]; + UINT16 id = P_ReadUINT16(save_p); ffloor_t *rover = P_GetFFloorByID(sector, id); if (rover) LUA_PushUserdata(gL, rover, META_FFLOOR); break; } case ARCH_POLYOBJ: - LUA_PushUserdata(gL, &PolyObjects[READUINT16(save_p)], META_POLYOBJ); + LUA_PushUserdata(gL, &PolyObjects[P_ReadUINT16(save_p)], META_POLYOBJ); break; case ARCH_SLOPE: - LUA_PushUserdata(gL, P_SlopeById(READUINT16(save_p)), META_SLOPE); + LUA_PushUserdata(gL, P_SlopeById(P_ReadUINT16(save_p)), META_SLOPE); break; case ARCH_MAPHEADER: - LUA_PushUserdata(gL, mapheaderinfo[READUINT16(save_p)], META_MAPHEADER); + LUA_PushUserdata(gL, mapheaderinfo[P_ReadUINT16(save_p)], META_MAPHEADER); break; case ARCH_SKINCOLOR: - LUA_PushUserdata(gL, &skincolors[READUINT16(save_p)], META_SKINCOLOR); + LUA_PushUserdata(gL, &skincolors[P_ReadUINT16(save_p)], META_SKINCOLOR); break; case ARCH_MOUSE: - LUA_PushUserdata(gL, READUINT16(save_p) == 1 ? &mouse : &mouse2, META_MOUSE); + LUA_PushUserdata(gL, P_ReadUINT16(save_p) == 1 ? &mouse : &mouse2, META_MOUSE); break; case ARCH_SKIN: - LUA_PushUserdata(gL, skins[READUINT8(save_p)], META_SKIN); + LUA_PushUserdata(gL, skins[P_ReadUINT8(save_p)], META_SKIN); break; case ARCH_TEND: return 1; @@ -1661,10 +1664,10 @@ static UINT8 UnArchiveValue(int TABLESINDEX) return 0; } -static void UnArchiveExtVars(void *pointer) +static void UnArchiveExtVars(save_t *save_p, void *pointer) { int TABLESINDEX; - UINT16 field_count = READUINT16(save_p); + UINT16 field_count = P_ReadUINT16(save_p); UINT16 i; char field[1024]; @@ -1677,8 +1680,8 @@ static void UnArchiveExtVars(void *pointer) for (i = 0; i < field_count; i++) { - READSTRING(save_p, field); - UnArchiveValue(TABLESINDEX); + P_ReadString(save_p, field); + UnArchiveValue(save_p, TABLESINDEX); lua_setfield(gL, -2, field); } @@ -1695,11 +1698,11 @@ static int NetUnArchive(lua_State *L) int TABLESINDEX = lua_upvalueindex(1); int i, n = lua_gettop(L); for (i = 1; i <= n; i++) - UnArchiveValue(TABLESINDEX); + UnArchiveValue(lua_save_p, TABLESINDEX); return n; } -static void UnArchiveTables(void) +static void UnArchiveTables(save_t *save_p) { int TABLESINDEX; UINT16 i, n; @@ -1716,13 +1719,13 @@ static void UnArchiveTables(void) lua_rawgeti(gL, TABLESINDEX, i); while (true) { - UINT8 e = UnArchiveValue(TABLESINDEX); // read key + UINT8 e = UnArchiveValue(save_p, TABLESINDEX); // read key if (e == 1) // End of table break; else if (e == 2) // Key contains a new table n++; - if (UnArchiveValue(TABLESINDEX) == 2) // read value + if (UnArchiveValue(save_p, TABLESINDEX) == 2) // read value n++; if (lua_isnil(gL, -2)) // if key is nil (if a function etc was accidentally saved) @@ -1734,7 +1737,7 @@ static void UnArchiveTables(void) lua_rawset(gL, -3); } - metatableid = READUINT16(save_p); + metatableid = P_ReadUINT16(save_p); if (metatableid) { // setmetatable(table, registry.metatables[metatableid]) @@ -1758,7 +1761,7 @@ void LUA_Step(void) lua_gc(gL, LUA_GCSTEP, 1); } -void LUA_Archive(void) +void LUA_Archive(save_t *save_p) { INT32 i; thinker_t *th; @@ -1771,29 +1774,30 @@ void LUA_Archive(void) if (!playeringame[i] && i > 0) // dedicated servers... continue; // all players in game will be archived, even if they just add a 0. - ArchiveExtVars(&players[i], "player"); + ArchiveExtVars(save_p, &players[i], "player"); } for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; // archive function will determine when to skip mobjs, // and write mobjnum in otherwise. - ArchiveExtVars(th, "mobj"); + ArchiveExtVars(save_p, th, "mobj"); } - WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. + P_WriteUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. + lua_save_p = save_p; LUA_HookNetArchive(NetArchive); // call the NetArchive hook in archive mode - ArchiveTables(); + ArchiveTables(save_p); if (gL) lua_pop(gL, 1); // pop tables } -void LUA_UnArchive(void) +void LUA_UnArchive(save_t *save_p) { UINT32 mobjnum; INT32 i; @@ -1806,23 +1810,24 @@ void LUA_UnArchive(void) { if (!playeringame[i] && i > 0) // dedicated servers... continue; - UnArchiveExtVars(&players[i]); + UnArchiveExtVars(save_p, &players[i]); } do { - mobjnum = READUINT32(save_p); // read a mobjnum + mobjnum = P_ReadUINT32(save_p); // read a mobjnum for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; if (((mobj_t *)th)->mobjnum != mobjnum) // find matching mobj continue; - UnArchiveExtVars(th); // apply variables + UnArchiveExtVars(save_p, th); // apply variables } } while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker. + lua_save_p = save_p; LUA_HookNetArchive(NetUnArchive); // call the NetArchive hook in unarchive mode - UnArchiveTables(); + UnArchiveTables(save_p); if (gL) lua_pop(gL, 1); // pop tables diff --git a/src/lua_script.h b/src/lua_script.h index 45d2a37ff..c5a5069ef 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -13,6 +13,7 @@ #ifndef LUA_SCRIPT_H #define LUA_SCRIPT_H +#include "p_saveg.h" #include "m_fixed.h" #include "doomtype.h" #include "d_player.h" @@ -52,8 +53,8 @@ void LUA_DumpFile(const char *filename); #endif fixed_t LUA_EvalMath(const char *word); void LUA_Step(void); -void LUA_Archive(void); -void LUA_UnArchive(void); +void LUA_Archive(save_t *save_p); +void LUA_UnArchive(save_t *save_p); int LUA_PushGlobals(lua_State *L, const char *word); int LUA_CheckGlobals(lua_State *L, const char *word); void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index 26f4011d3..0e8860804 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2023 by Sonic Team Junior. +// Copyright (C) 2014-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_anigif.c b/src/m_anigif.c index 6e6ec68aa..5ebc4892c 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 2013-2016 by Matthew "Kaito Sinclaire" Walsh. // Copyright (C) 2013 by "Ninji". -// Copyright (C) 2013-2023 by Sonic Team Junior. +// Copyright (C) 2013-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_cheat.c b/src/m_cheat.c index 07f100717..4be071bb2 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -562,7 +562,7 @@ void Command_Teleport_f(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -1072,7 +1072,7 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo = (mobj_t *)th; diff --git a/src/m_cheat.h b/src/m_cheat.h index 564c6da77..6bd1546f8 100644 --- a/src/m_cheat.h +++ b/src/m_cheat.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_cond.c b/src/m_cond.c index 5a5913297..418b2ff2b 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -494,6 +494,12 @@ UINT8 M_MapLocked(INT32 mapnum, gamedata_t *data) UINT8 M_CampaignWarpIsCheat(INT32 gt, INT32 mapnum, gamedata_t *data) { + if (dedicated) + { + // See M_MapLocked; don't make dedicated servers annoying. + return false; + } + if (M_MapLocked(mapnum, data) == true) { // Warping to locked maps is definitely always a cheat diff --git a/src/m_easing.c b/src/m_easing.c index 48fe1efbc..60ca6e9b6 100644 --- a/src/m_easing.c +++ b/src/m_easing.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2023 by Lactozilla. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_easing.h b/src/m_easing.h index eaa5d6773..6884833af 100644 --- a/src/m_easing.h +++ b/src/m_easing.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2023 by Lactozilla. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_fixed.c b/src/m_fixed.c index 19c1e8091..ace05fd3b 100644 --- a/src/m_fixed.c +++ b/src/m_fixed.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // Copyright (C) 2009 by Stephen McGranahan. // // This program is free software distributed under the diff --git a/src/m_fixed.h b/src/m_fixed.h index f40c7b308..504b53a6e 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_menu.c b/src/m_menu.c index 38165472e..afc45fcf0 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2011-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -140,6 +140,7 @@ static char *char_notes = NULL; boolean menuactive = false; boolean fromlevelselect = false; +tic_t shieldprompt_timer = 0; // Show a prompt about the new Shield button for old configs // TODO: 2.3: Remove typedef enum { @@ -3161,6 +3162,7 @@ static void Command_Manual_f(void) if (modeattacking) return; M_StartControlPanel(); + if (shieldprompt_timer) return; // TODO: 2.3: Delete this line currentMenu = &MISC_HelpDef; itemOn = 0; } @@ -3316,7 +3318,7 @@ boolean M_Responder(event_t *ev) if (ch == -1) return false; - else if (ch == gamecontrol[GC_SYSTEMMENU][0] || ch == gamecontrol[GC_SYSTEMMENU][1]) // allow remappable ESC key + else if (ev->type != ev_text && (ch == gamecontrol[GC_SYSTEMMENU][0] || ch == gamecontrol[GC_SYSTEMMENU][1])) // allow remappable ESC key ch = KEY_ESCAPE; // F-Keys @@ -3340,6 +3342,7 @@ boolean M_Responder(event_t *ev) if (modeattacking) return true; M_StartControlPanel(); + if (shieldprompt_timer) return true; // TODO: 2.3: Delete this line M_Options(0); // Uncomment the below if you want the menu to reset to the top each time like before. M_SetupNextMenu will fix it automatically. //OP_SoundOptionsDef.lastOn = 0; @@ -3350,6 +3353,7 @@ boolean M_Responder(event_t *ev) if (modeattacking) return true; M_StartControlPanel(); + if (shieldprompt_timer) return true; // TODO: 2.3: Delete this line M_Options(0); M_VideoModeMenu(0); return true; @@ -3361,6 +3365,7 @@ boolean M_Responder(event_t *ev) if (modeattacking) return true; M_StartControlPanel(); + if (shieldprompt_timer) return true; // TODO: 2.3: Delete this line M_Options(0); M_SetupNextMenu(&OP_MainDef); return true; @@ -3394,9 +3399,16 @@ boolean M_Responder(event_t *ev) // Handle menuitems which need a specific key handling if (routine && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_KEYHANDLER) { + // block text input if ctrl is held, to allow using ctrl+c ctrl+v and ctrl+x + if (ctrldown) + { + routine(ch); + return true; + } + // ignore ev_keydown events if the key maps to a character, since // the ev_text event will follow immediately after in that case. - if (ev->type == ev_keydown && ch >= 32 && ch <= 127) + if (ev->type == ev_keydown && ((ch >= 32 && ch <= 127) || (ch >= KEY_KEYPAD7 && ch <= KEY_KPADDEL))) return true; routine(ch); @@ -3424,7 +3436,7 @@ boolean M_Responder(event_t *ev) { // dirty hack: for customising controls, I want only buttons/keys, not moves if (ev->type == ev_mouse || ev->type == ev_mouse2 || ev->type == ev_joystick - || ev->type == ev_joystick2) + || ev->type == ev_joystick2 || ev->type == ev_text) return true; if (routine) { @@ -3631,6 +3643,230 @@ void M_Drawer(void) } } +// Handle the "Do you want to assign Shield Ability now?" pop-up for old configs // TODO: 2.3: Remove this line... +static UINT8 shieldprompt_currentchoice = 0; // ...and this line... + +static void M_ShieldPromptUseDefaults(void) // ...and this function +{ + // With a default config from v2.2.10 to v2.2.13, the B button will be set to Custom 1, + // and Controls per Key defaults to "One", so it will override the default Shield button. + // A default config from v2.2.0 to v2.2.9 has Next Weapon on B, so it suffers from this too. + + // So for "Use default Shield Ability buttons", we should update old configs to mitigate gamepad conflicts + // (even with "Several" Controls per Key!), and show a message with the default bindings + + for (setupcontrols = gamecontrol; true; setupcontrols = gamecontrolbis) // Do stuff for both P1 and P2 + { + INT32 JOY1 = (setupcontrols == gamecontrol) ? KEY_JOY1 : KEY_2JOY1; // Is this for P1 or for P2? + + if ((setupcontrols[GC_CUSTOM1][0] == JOY1+1 || setupcontrols[GC_CUSTOM1][1] == JOY1+1) + && (setupcontrols[GC_CUSTOM2][0] == JOY1+3 || setupcontrols[GC_CUSTOM2][1] == JOY1+3) + && (setupcontrols[GC_CUSTOM3][0] == JOY1+8 || setupcontrols[GC_CUSTOM3][1] == JOY1+8)) + { + // If the player has v2.2.13's default gamepad Custom 1/2/3 buttons, + // shuffle Custom 1/2/3 around to make room for Shield Ability on B + UINT8 shield_slot = (setupcontrols[GC_SHIELD ][0] == KEY_NULL ) ? 0 : 1; + UINT8 custom1_slot = (setupcontrols[GC_CUSTOM1][0] == JOY1+1) ? 0 : 1; + UINT8 custom2_slot = (setupcontrols[GC_CUSTOM2][0] == JOY1+3) ? 0 : 1; + UINT8 custom3_slot = (setupcontrols[GC_CUSTOM3][0] == JOY1+8) ? 0 : 1; + + setupcontrols[GC_SHIELD ][shield_slot ] = JOY1+1; // Assign Shield Ability to B + setupcontrols[GC_CUSTOM1][custom1_slot] = JOY1+3; // Move Custom 1 from B to Y + setupcontrols[GC_CUSTOM2][custom2_slot] = JOY1+8; // Move Custom 2 from Y to LS + setupcontrols[GC_CUSTOM3][custom3_slot] = KEY_NULL; // Unassign Custom 3 from LS... + // (The alternative would be to check and update the ENTIRE gamepad layout. + // That'd be nice, but it would mess with people that are used to the old defaults.) + } + else if ((setupcontrols[GC_WEAPONNEXT][0] == JOY1+1 || setupcontrols[GC_WEAPONNEXT][1] == JOY1+1) + && (setupcontrols[GC_WEAPONPREV][0] == JOY1+2 || setupcontrols[GC_WEAPONPREV][1] == JOY1+2)) + { + // Or if the user has a default config from v2.2.0 to v2.2.9, + // the B button will be Next Weapon, and X will be Previous Weapon. + // It's "safe" to discard one of them, you just have to press X multiple times to select in the other direction + UINT8 shield_slot = (setupcontrols[GC_SHIELD ][0] == KEY_NULL ) ? 0 : 1; + UINT8 nweapon_slot = (setupcontrols[GC_WEAPONNEXT][0] == JOY1+1) ? 0 : 1; + UINT8 pweapon_slot = (setupcontrols[GC_WEAPONPREV][0] == JOY1+2) ? 0 : 1; + + setupcontrols[GC_SHIELD ][shield_slot ] = JOY1+1; // Assign Shield Ability to B + setupcontrols[GC_WEAPONNEXT][nweapon_slot] = JOY1+3; // Move Next Weapon from B to X + setupcontrols[GC_WEAPONPREV][pweapon_slot] = KEY_NULL; // Unassign Previous Weapon from X + } + + if (setupcontrols == gamecontrolbis) // If we've already updated both players, break out + break; + } + + + // Now, show a message about the default Shield Ability bindings + if ((gamecontrol[GC_SHIELD][0] == KEY_LALT && gamecontrol[GC_SHIELD][1] == KEY_JOY1+1) + || (gamecontrol[GC_SHIELD][0] == KEY_JOY1+1 && gamecontrol[GC_SHIELD][1] == KEY_LALT)) + { + // Left Alt and the B button are both assigned + M_StartMessage(M_GetText("Shield Ability defaults to\nthe \x82""Left Alt\x80"" key on keyboard,\nand the \x85""B button\x80"" on gamepads." + "\n\nYou can always reassign it\nin the Options menu later." + "\n\n\nPress 'Enter' to continue\n"), + NULL, MM_NOTHING); + MessageDef.x = 43; // Change the pop-up message's background position/width + MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 27; + } + else if (gamecontrol[GC_SHIELD][0] == KEY_LALT || gamecontrol[GC_SHIELD][1] == KEY_LALT) + { + // Left Alt is assigned, but the B button isn't. + M_StartMessage(M_GetText("Shield Ability defaults to\nthe \x82""Left Alt\x80"" key on keyboard.\nThe \x85""B button\x80"" on gamepads was taken." + "\n\nYou can always reassign it\nin the Options menu later." + "\n\n\nPress 'Enter' to continue\n"), + NULL, MM_NOTHING); + MessageDef.x = 24; // Change the pop-up message's background position/width + MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 32; + } + else if (gamecontrol[GC_SHIELD][0] == KEY_JOY1+1 || gamecontrol[GC_SHIELD][1] == KEY_JOY1+1) + { + // The B button is assigned, but Left Alt isn't + M_StartMessage(M_GetText("Shield Ability defaults to\nthe \x85""B button\x80"" on gamepads.\nThe \x82""Left Alt\x80"" key on keyboard was taken." + "\n\nYou can always reassign it\nin the Options menu later." + "\n\n\nPress 'Enter' to continue\n"), + NULL, MM_NOTHING); + MessageDef.x = 8; // Change the pop-up message's background position/width + MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 36; + } + else if (gamecontrol[GC_SHIELD][0] == KEY_NULL && gamecontrol[GC_SHIELD][1] == KEY_NULL) + { + // Neither Left Alt nor the B button are assigned + M_StartMessage(M_GetText("Shield Ability is unassigned!\nThe \x82""Left Alt\x80"" key on keyboard and\nthe \x85""B button\x80"" on gamepads were taken." + "\n\nYou should assign Shield Ability\nin the Options menu later." + "\n\n\nPress 'Enter' to continue\n"), + NULL, MM_NOTHING); + MessageDef.x = 19; // Change the pop-up message's background position/width + MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 33; + } + else + { + // Neither Left Alt nor the B button are assigned... but something else is??? + // (This can technically happen if you edit your config or use setcontrol in the console before opening the menu) + char keystr[16+16+2+7+1]; // Two 16-char keys + two colour codes + "' and '" + null + + if (gamecontrol[GC_SHIELD][0] != KEY_NULL && gamecontrol[GC_SHIELD][1] != KEY_NULL) + STRBUFCPY(keystr, va("%s\x80""' and '\x82""%s", + G_KeyNumToName(gamecontrol[GC_SHIELD][0]), + G_KeyNumToName(gamecontrol[GC_SHIELD][1]))); + else if (gamecontrol[GC_SHIELD][0] != KEY_NULL) + STRBUFCPY(keystr, G_KeyNumToName(gamecontrol[GC_SHIELD][0])); + else //if (gamecontrol[GC_SHIELD][1] != KEY_NULL) + STRBUFCPY(keystr, G_KeyNumToName(gamecontrol[GC_SHIELD][1])); + + M_StartMessage(va("Shield Ability is assigned to\n'\x82""%s\x80""'." + "\n\nYou can always reassign it\nin the Options menu later." + "\n\n\nPress 'Enter' to continue\n", + keystr), NULL, MM_NOTHING); + MessageDef.x = 23; // Change the pop-up message's background position/width + MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 32; + } +} + +static void M_HandleShieldPromptMenu(INT32 choice) // TODO: 2.3: Remove +{ + switch (choice) + { + case KEY_ESCAPE: + if (I_GetTime() <= shieldprompt_timer) // Don't mash past the pop-up by accident! + break; + + S_StartSound(NULL, sfx_menu1); + noFurtherInput = true; + shieldprompt_timer = 0; + M_ShieldPromptUseDefaults(); + break; + + case KEY_ENTER: + if (I_GetTime() <= shieldprompt_timer) // Don't mash past the pop-up by accident! + break; + + S_StartSound(NULL, sfx_menu1); + noFurtherInput = true; + shieldprompt_timer = 0; + + if (shieldprompt_currentchoice == 0) + { + OP_ChangeControlsDef.lastOn = 8; // Highlight Shield Ability in the controls menu + M_Setup1PControlsMenu(0); // Set up P1's controls menu and call M_SetupNextMenu + } + else if (shieldprompt_currentchoice == 1) // Copy the Spin buttons to the Shield buttons + { + CV_SetValue(&cv_controlperkey, 2); // Make sure that Controls per Key is "Several" + + gamecontrol [GC_SHIELD][0] = gamecontrol [GC_SPIN][0]; + gamecontrol [GC_SHIELD][1] = gamecontrol [GC_SPIN][1]; + gamecontrolbis[GC_SHIELD][0] = gamecontrolbis[GC_SPIN][0]; + gamecontrolbis[GC_SHIELD][1] = gamecontrolbis[GC_SPIN][1]; + CV_SetValue(&cv_shieldaxis, cv_spinaxis.value); + CV_SetValue(&cv_shieldaxis2, cv_spinaxis2.value); + + M_StartMessage(M_GetText("Spin and Shield Ability are now\nthe same button." + "\n\nYou can always reassign them\nin the Options menu later." + "\n\n\nPress 'Enter' to continue\n"), + NULL, MM_NOTHING); + MessageDef.x = 36; // Change the pop-up message's background position/width + MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 29; + } + else + M_ShieldPromptUseDefaults(); + break; + + case KEY_UPARROW: + S_StartSound(NULL, sfx_menu1); + shieldprompt_currentchoice = (shieldprompt_currentchoice+2)%3; + break; + + case KEY_DOWNARROW: + S_StartSound(NULL, sfx_menu1); + shieldprompt_currentchoice = (shieldprompt_currentchoice+1)%3; + break; + } + + MessageDef.prevMenu = &MainDef; +} + +static void M_DrawShieldPromptMenu(void) // TODO: 2.3: Remove +{ + INT16 cursorx = (BASEVIDWIDTH/2) - 24; + + V_DrawFill(10-3, 68-3, 300+6, 40+6, 159); + // V_DrawCenteredString doesn't centre newlines, so we have to draw each line separately + V_DrawCenteredString(BASEVIDWIDTH/2, 68, V_ALLOWLOWERCASE, "Welcome back! Since you last played,"); + V_DrawCenteredString(BASEVIDWIDTH/2, 76, V_ALLOWLOWERCASE, "Spin has been split into separate"); + V_DrawCenteredString(BASEVIDWIDTH/2, 84, V_ALLOWLOWERCASE, "\"Spin\" and \"Shield Ability\" controls."); + + V_DrawCenteredString(BASEVIDWIDTH/2, 98, V_ALLOWLOWERCASE, "Do you want to assign Shield Ability now?"); + + + V_DrawCenteredString(BASEVIDWIDTH/2, 164, + (shieldprompt_currentchoice == 0) ? V_YELLOWMAP : 0, "Open Control Setup"); + V_DrawCenteredString(BASEVIDWIDTH/2, 172, + (shieldprompt_currentchoice == 1) ? V_YELLOWMAP : 0, "Keep the old behaviour"); + V_DrawCenteredString(BASEVIDWIDTH/2, 180, + (shieldprompt_currentchoice == 2) ? V_YELLOWMAP : 0, "Use default Shield Ability buttons"); + + switch (shieldprompt_currentchoice) + { + case 0: cursorx -= V_StringWidth("Open Control Setup", 0)/2; break; + case 1: cursorx -= V_StringWidth("Keep the old behaviour", 0)/2; break; + default: cursorx -= V_StringWidth("Use default Shield Ability buttons", 0)/2; break; + } + V_DrawScaledPatch(cursorx, 164 + (shieldprompt_currentchoice*8), 0, W_CachePatchName("M_CURSOR", PU_PATCH)); +} + +static menuitem_t OP_ShieldPromptMenu[] = {{IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleShieldPromptMenu, 0}}; // TODO: 2.3: Remove + +menu_t OP_ShieldPromptDef = { // TODO: 2.3: Remove + MN_SPECIAL, + NULL, + 1, + &MainDef, + OP_ShieldPromptMenu, + M_DrawShieldPromptMenu, + 0, 0, 0, NULL +}; + // // M_StartControlPanel // @@ -3662,6 +3898,15 @@ void M_StartControlPanel(void) currentMenu = &MainDef; itemOn = singleplr; M_UpdateItemOn(); + + if (shieldprompt_timer) // For old configs, show a pop-up about the new Shield button // TODO: 2.3: Remove + { + S_StartSound(NULL, sfx_strpst); + noFurtherInput = true; + shieldprompt_timer = I_GetTime() + TICRATE; // Don't mash past the pop-up by accident! + + M_SetupNextMenu(&OP_ShieldPromptDef); + } } else if (modeattacking) { @@ -8273,6 +8518,7 @@ static void M_StartTutorial(INT32 choice) gamecomplete = 0; cursaveslot = 0; maplistoption = 0; + CV_StealthSet(&cv_skin, DEFAULTSKIN); // tutorial accounts for sonic only G_DeferedInitNew(false, G_BuildMapName(tutorialmap), 0, false, false); } @@ -8372,7 +8618,7 @@ static void M_DrawLoadGameData(void) if (savegameinfo[savetodraw].lives == -42) col = 26; else if (savegameinfo[savetodraw].botskin == 3) // & knuckles - col = 105; + col = 106; else if (savegameinfo[savetodraw].botskin) // tailsbot or custom col = 134; else @@ -8432,7 +8678,17 @@ static void M_DrawLoadGameData(void) if (savegameinfo[savetodraw].lives == -42) V_DrawRightAlignedThinString(x + 79, y, V_GRAYMAP, "NEW GAME"); else if (savegameinfo[savetodraw].lives == -666) - V_DrawRightAlignedThinString(x + 79, y, V_REDMAP, "CAN'T LOAD!"); + { + if (savegameinfo[savetodraw].continuescore == -62) + { + V_DrawRightAlignedThinString(x + 79, y, V_REDMAP, "ADDON NOT LOADED"); + V_DrawRightAlignedThinString(x + 79, y-10, V_REDMAP, savegameinfo[savetodraw].skinname); + } + else + { + V_DrawRightAlignedThinString(x + 79, y, V_REDMAP, "CAN'T LOAD!"); + } + } else if (savegameinfo[savetodraw].gamemap & 8192) V_DrawRightAlignedThinString(x + 79, y, V_GREENMAP, "CLEAR!"); else @@ -8665,6 +8921,7 @@ static void M_LoadSelect(INT32 choice) } #define VERSIONSIZE 16 +#define MISSING { savegameinfo[slot].continuescore = -62; savegameinfo[slot].lives = -666; Z_Free(savebuffer); return; } #define BADSAVE { savegameinfo[slot].lives = -666; Z_Free(savebuffer); return; } #define CHECKPOS if (sav_p >= end_p) BADSAVE // Reads the save file to list lives, level, player, etc. @@ -8761,10 +9018,11 @@ static void M_ReadSavegameInfo(UINT32 slot) CHECKPOS READSTRINGN(sav_p, ourSkinName, SKINNAMESIZE); savegameinfo[slot].skinnum = R_SkinAvailable(ourSkinName); + STRBUFCPY(savegameinfo[slot].skinname, ourSkinName); if (savegameinfo[slot].skinnum >= numskins || !R_SkinUsable(-1, savegameinfo[slot].skinnum)) - BADSAVE + MISSING CHECKPOS READSTRINGN(sav_p, botSkinName, SKINNAMESIZE); @@ -8772,7 +9030,7 @@ static void M_ReadSavegameInfo(UINT32 slot) if (savegameinfo[slot].botskin-1 >= numskins || !R_SkinUsable(-1, savegameinfo[slot].botskin-1)) - BADSAVE + MISSING } CHECKPOS @@ -8817,6 +9075,7 @@ static void M_ReadSavegameInfo(UINT32 slot) } #undef CHECKPOS #undef BADSAVE +#undef MISSING // // M_ReadSaveStrings @@ -11864,8 +12123,7 @@ static void M_HandleConnectIP(INT32 choice) if ( ctrldown ) { switch (choice) { - case 'v': - case 'V': // ctrl+v, pasting + case 'v': // ctrl+v, pasting { const char *paste = I_ClipboardPaste(); @@ -11878,8 +12136,7 @@ static void M_HandleConnectIP(INT32 choice) break; } case KEY_INS: - case 'c': - case 'C': // ctrl+c, ctrl+insert, copying + case 'c': // ctrl+c, ctrl+insert, copying if (l != 0) // Don't replace the clipboard without any text { I_ClipboardCopy(setupm_ip, l); @@ -11887,8 +12144,7 @@ static void M_HandleConnectIP(INT32 choice) } break; - case 'x': - case 'X': // ctrl+x, cutting + case 'x': // ctrl+x, cutting if (l != 0) // Don't replace the clipboard without any text { I_ClipboardCopy(setupm_ip, l); @@ -11944,15 +12200,6 @@ static void M_HandleConnectIP(INT32 choice) setupm_ip[l] = (char)choice; setupm_ip[l+1] = 0; } - else if (choice >= 199 && choice <= 211 && choice != 202 && choice != 206) //numpad too! - { - char keypad_translation[] = {'7','8','9','-','4','5','6','+','1','2','3','0','.'}; - choice = keypad_translation[choice - 199]; - S_StartSound(NULL,sfx_menu1); // Tails - setupm_ip[l] = (char)choice; - setupm_ip[l+1] = 0; - } - break; } diff --git a/src/m_menu.h b/src/m_menu.h index 99a5b6de4..cfe811d0b 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2011-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -176,6 +176,7 @@ typedef struct extern menupres_t menupres[NUMMENUTYPES]; extern UINT32 prevMenuId; extern UINT32 activeMenuId; +extern tic_t shieldprompt_timer; // Show a prompt about the new Shield button for old configs // TODO: 2.3: Remove void M_InitMenuPresTables(void); UINT8 M_GetYoungestChildMenu(void); @@ -421,6 +422,7 @@ typedef struct { char levelname[32]; UINT8 skinnum; + char skinname [SKINNAMESIZE+1]; UINT8 botskin; UINT8 numemeralds; UINT8 numgameovers; diff --git a/src/m_misc.c b/src/m_misc.c index a60bbea98..dda3ffc86 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -560,6 +560,11 @@ void M_FirstLoadConfig(void) COM_BufInsertText(va("exec \"%s\"\n", configfile)); // no COM_BufExecute() needed; that does it right away + // For configs loaded at startup only, check for pre-Shield-button configs // TODO: 2.3: Remove + if (GETMAJOREXECVERSION(cv_execversion.value) < 55 // Pre-v2.2.14 configs + && cv_execversion.value != 25) // Make sure that the config exists, too + shieldprompt_timer = 1; + // don't filter anymore vars and don't let this convsvar be changed COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, EXECVERSION)); CV_ToggleExecVersion(false); diff --git a/src/m_misc.h b/src/m_misc.h index 04ac66ca6..636810944 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_perfstats.c b/src/m_perfstats.c index b9948bdc0..33a774acf 100644 --- a/src/m_perfstats.c +++ b/src/m_perfstats.c @@ -453,7 +453,7 @@ static int PS_DrawPerfRows(int x, int y, int color, perfstatrow_t *rows) return draw_y; } -static void PS_UpdateMetricHistory(ps_metric_t *metric, boolean time_metric, boolean frame_metric, boolean set_user) +static void PS_UpdateMetricHistory(ps_metric_t *metric, boolean time_metric, boolean frame_metric) { int index = frame_metric ? ps_frame_index : ps_tick_index; @@ -461,7 +461,7 @@ static void PS_UpdateMetricHistory(ps_metric_t *metric, boolean time_metric, boo { // allocate history table int value_size = time_metric ? sizeof(precise_t) : sizeof(INT32); - void** memory_user = set_user ? &metric->history : NULL; + void** memory_user = &metric->history; metric->history = Z_Calloc(value_size * cv_ps_samplesize.value, PU_PERFSTATS, memory_user); @@ -491,7 +491,7 @@ static void PS_UpdateRowHistories(perfstatrow_t *rows, boolean frame_metric) for (row = rows; row->lores_label; row++) { if (PS_IsRowValid(row)) - PS_UpdateMetricHistory(row->metric, !!(row->flags & PS_TIME), frame_metric, true); + PS_UpdateMetricHistory(row->metric, !!(row->flags & PS_TIME), frame_metric); } } @@ -584,7 +584,7 @@ static void PS_CountThinkers(void) for (thinker = thlist[i].next; thinker != &thlist[i]; thinker = thinker->next) { ps_thinkercount.value.i++; - if (thinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (thinker->removing) ps_removecount.value.i++; else if (i == THINK_POLYOBJ) ps_polythcount.value.i++; @@ -649,17 +649,17 @@ void PS_UpdateTickStats(void) if (cv_perfstats.value == 3) { for (i = 0; i < thinkframe_hooks_length; i++) - PS_UpdateMetricHistory(&thinkframe_hooks[i].time_taken, true, false, false); + PS_UpdateMetricHistory(&thinkframe_hooks[i].time_taken, true, false); } else if (cv_perfstats.value == 4) { for (i = 0; i < prethinkframe_hooks_length; i++) - PS_UpdateMetricHistory(&prethinkframe_hooks[i].time_taken, true, false, false); + PS_UpdateMetricHistory(&prethinkframe_hooks[i].time_taken, true, false); } else if (cv_perfstats.value == 5) { for (i = 0; i < postthinkframe_hooks_length; i++) - PS_UpdateMetricHistory(&postthinkframe_hooks[i].time_taken, true, false, false); + PS_UpdateMetricHistory(&postthinkframe_hooks[i].time_taken, true, false); } } if (cv_perfstats.value) diff --git a/src/m_tokenizer.c b/src/m_tokenizer.c index 8bb094cae..09f8915a5 100644 --- a/src/m_tokenizer.c +++ b/src/m_tokenizer.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2013-2023 by Sonic Team Junior. +// Copyright (C) 2013-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_tokenizer.h b/src/m_tokenizer.h index 7ee856b3c..4f03563a2 100644 --- a/src/m_tokenizer.h +++ b/src/m_tokenizer.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2013-2023 by Sonic Team Junior. +// Copyright (C) 2013-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c index 917e32b59..c740d53a6 100644 --- a/src/netcode/client_connection.c +++ b/src/netcode/client_connection.c @@ -546,6 +546,7 @@ static void AbortConnection(void) { Snake_Free(&snake); + CURLAbortFile(); D_QuitNetGame(); CL_Reset(); D_StartTitle(); @@ -1062,10 +1063,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic } } - // Rusty TODO: multithread - if (filedownload.http_running) - CURLGetFile(); - if (waitmore) break; // exit the case diff --git a/src/netcode/commands.c b/src/netcode/commands.c index f3bbc8a86..8d6dab06b 100644 --- a/src/netcode/commands.c +++ b/src/netcode/commands.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 2bf9d2dde..591923571 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -114,6 +114,7 @@ static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_cons_t, NULL); consvar_t cv_idletime = CVAR_INIT ("idletime", "0", CV_SAVE, CV_Unsigned, NULL); +consvar_t cv_idlespectate = CVAR_INIT ("idlespectate", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_dedicatedidletime = CVAR_INIT ("dedicatedidletime", "10", CV_SAVE, CV_Unsigned, NULL); consvar_t cv_httpsource = CVAR_INIT ("http_source", "", CV_SAVE, NULL, NULL); @@ -1360,19 +1361,33 @@ static void IdleUpdate(void) if (!server || !netgame) return; - for (i = 1; i < MAXPLAYERS; i++) + for (i = 0; i < MAXPLAYERS; i++) { - if (cv_idletime.value && playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && !players[i].bot && !IsPlayerAdmin(i) && i != serverplayer && gamestate == GS_LEVEL) + if (playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && !players[i].bot && gamestate == GS_LEVEL) { if (players[i].cmd.forwardmove || players[i].cmd.sidemove || players[i].cmd.buttons) players[i].lastinputtime = 0; else players[i].lastinputtime++; - if (players[i].lastinputtime > (tic_t)cv_idletime.value * TICRATE * 60) + if (cv_idletime.value && !IsPlayerAdmin(i) && i != serverplayer && !(players[i].pflags & PF_FINISHED) && players[i].lastinputtime > (tic_t)cv_idletime.value * TICRATE * 60) { players[i].lastinputtime = 0; - SendKick(i, KICK_MSG_IDLE | KICK_MSG_KEEP_BODY); + if (cv_idlespectate.value && G_GametypeHasSpectators()) + { + changeteam_union NetPacket; + UINT16 usvalue; + NetPacket.value.l = NetPacket.value.b = 0; + NetPacket.packet.newteam = 0; + NetPacket.packet.playernum = i; + NetPacket.packet.verification = true; // This signals that it's a server change + usvalue = SHORT(NetPacket.value.l|NetPacket.value.b); + SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue)); + } + else + { + SendKick(i, KICK_MSG_IDLE | KICK_MSG_KEEP_BODY); + } } } else @@ -1399,6 +1414,83 @@ static void IdleUpdate(void) } } +static void DedicatedIdleUpdate(INT32 *realtics) +{ + const tic_t dedicatedidletime = cv_dedicatedidletime.value * TICRATE; + static tic_t dedicatedidletimeprev = 0; + static tic_t dedicatedidle = 0; + + if (!server || !dedicated || gamestate != GS_LEVEL) + return; + + if (dedicatedidletime > 0) + { + INT32 i; + + boolean empty = true; + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i]) + { + empty = false; + break; + } + + if (empty) + { + if (leveltime == 2) + { + // On next tick... + dedicatedidle = dedicatedidletime - 1; + } + else if (dedicatedidle >= dedicatedidletime) + { + if (D_GetExistingTextcmd(gametic, 0) || D_GetExistingTextcmd(gametic + 1, 0)) + { + CONS_Printf("DEDICATED: Awakening from idle (Netxcmd detected...)\n"); + dedicatedidle = 0; + } + else + { + (*realtics) = 0; + } + } + else + { + dedicatedidle += (*realtics); + + if (dedicatedidle >= dedicatedidletime) + { + const char *idlereason = "at round start"; + if (leveltime > 3) + idlereason = va("for %d seconds", dedicatedidle / TICRATE); + + CONS_Printf("DEDICATED: No players %s, idling...\n", idlereason); + (*realtics) = 0; + dedicatedidle = dedicatedidletime; + } + } + } + else + { + if (dedicatedidle >= dedicatedidletime) + { + CONS_Printf("DEDICATED: Awakening from idle (Player detected...)\n"); + } + dedicatedidle = 0; + } + } + else + { + if (dedicatedidletimeprev > 0 && dedicatedidle >= dedicatedidletimeprev) + { + CONS_Printf("DEDICATED: Awakening from idle (Idle disabled...)\n"); + } + dedicatedidle = 0; + } + + dedicatedidletimeprev = dedicatedidletime; +} + // Handle timeouts to prevent definitive freezes from happenning static void HandleNodeTimeouts(void) { @@ -1475,69 +1567,7 @@ void NetUpdate(void) realtics = 5; } - if (server && dedicated && gamestate == GS_LEVEL) - { - const tic_t dedicatedidletime = cv_dedicatedidletime.value * TICRATE; - static tic_t dedicatedidletimeprev = 0; - static tic_t dedicatedidle = 0; - - if (dedicatedidletime > 0) - { - INT32 i; - - for (i = 1; i < MAXNETNODES; ++i) - if (netnodes[i].ingame) - { - if (dedicatedidle >= dedicatedidletime) - { - CONS_Printf("DEDICATED: Awakening from idle (Node %d detected...)\n", i); - dedicatedidle = 0; - } - break; - } - - if (i == MAXNETNODES) - { - if (leveltime == 2) - { - // On next tick... - dedicatedidle = dedicatedidletime-1; - } - else if (dedicatedidle >= dedicatedidletime) - { - if (D_GetExistingTextcmd(gametic, 0) || D_GetExistingTextcmd(gametic+1, 0)) - { - CONS_Printf("DEDICATED: Awakening from idle (Netxcmd detected...)\n"); - dedicatedidle = 0; - } - else - { - realtics = 0; - } - } - else if ((dedicatedidle += realtics) >= dedicatedidletime) - { - const char *idlereason = "at round start"; - if (leveltime > 3) - idlereason = va("for %d seconds", dedicatedidle/TICRATE); - - CONS_Printf("DEDICATED: No nodes %s, idling...\n", idlereason); - realtics = 0; - dedicatedidle = dedicatedidletime; - } - } - } - else - { - if (dedicatedidletimeprev > 0 && dedicatedidle >= dedicatedidletimeprev) - { - CONS_Printf("DEDICATED: Awakening from idle (Idle disabled...)\n"); - } - dedicatedidle = 0; - } - - dedicatedidletimeprev = dedicatedidletime; - } + DedicatedIdleUpdate(&realtics); gametime = nowtime; @@ -1784,7 +1814,7 @@ INT16 Consistancy(void) { for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo = (mobj_t *)th; diff --git a/src/netcode/d_clisrv.h b/src/netcode/d_clisrv.h index 5aac4693d..342173dff 100644 --- a/src/netcode/d_clisrv.h +++ b/src/netcode/d_clisrv.h @@ -73,7 +73,7 @@ extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; extern tic_t servermaxping; -extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed, cv_idletime, cv_dedicatedidletime; +extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed, cv_idletime, cv_idlespectate, cv_dedicatedidletime; extern consvar_t cv_httpsource; // Used in d_net, the only dependence diff --git a/src/netcode/d_net.c b/src/netcode/d_net.c index b24409db1..4860d8688 100644 --- a/src/netcode/d_net.c +++ b/src/netcode/d_net.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -62,16 +62,11 @@ static doomdata_t reboundstore[MAXREBOUND]; static INT16 reboundsize[MAXREBOUND]; static INT32 rebound_head, rebound_tail; -/// \brief bandwith of netgame -INT32 net_bandwidth; - /// \brief max length per packet INT16 hardware_MAXPACKETLENGTH; boolean (*I_NetGet)(void) = NULL; void (*I_NetSend)(void) = NULL; -boolean (*I_NetCanSend)(void) = NULL; -boolean (*I_NetCanGet)(void) = NULL; void (*I_NetCloseSocket)(void) = NULL; void (*I_NetFreeNodenum)(INT32 nodenum) = NULL; SINT8 (*I_NetMakeNodewPort)(const char *address, const char* port) = NULL; @@ -996,15 +991,7 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen netbuffer->ackreturn = 0; if (reliable) { - if (I_NetCanSend && !I_NetCanSend()) - { - if (netbuffer->packettype < PT_CANFAIL) - GetFreeAcknum(&netbuffer->ack, true); - - DEBFILE("HSendPacket: Out of bandwidth\n"); - return false; - } - else if (!GetFreeAcknum(&netbuffer->ack, false)) + if (!GetFreeAcknum(&netbuffer->ack, false)) return false; } else @@ -1156,7 +1143,7 @@ static void Internal_FreeNodenum(INT32 nodenum) char *I_NetSplitAddress(char *host, char **port) { - boolean v4 = (strchr(host, '.') != NULL); + boolean v4 = (host[0] != '['); host = strtok(host, v4 ? ":" : "[]"); @@ -1189,10 +1176,7 @@ void D_SetDoomcom(void) { if (doomcom) return; doomcom = Z_Calloc(sizeof (doomcom_t), PU_STATIC, NULL); - doomcom->id = DOOMCOM_ID; doomcom->numslots = doomcom->numnodes = 1; - doomcom->gametype = 0; - doomcom->consoleplayer = 0; doomcom->extratics = 0; } @@ -1211,13 +1195,11 @@ boolean D_CheckNetGame(void) I_NetGet = Internal_Get; I_NetSend = Internal_Send; - I_NetCanSend = NULL; I_NetCloseSocket = NULL; I_NetFreeNodenum = Internal_FreeNodenum; I_NetMakeNodewPort = NULL; hardware_MAXPACKETLENGTH = MAXPACKETLENGTH; - net_bandwidth = 30000; // I_InitNetwork sets doomcom and netgame // check and initialize the network driver multiplayer = false; @@ -1237,7 +1219,6 @@ boolean D_CheckNetGame(void) server = true; // WTF? server always true??? // no! The deault mode is server. Client is set elsewhere // when the client executes connect command. - doomcom->ticdup = 1; if (M_CheckParm("-extratic")) { @@ -1248,21 +1229,6 @@ boolean D_CheckNetGame(void) CONS_Printf(M_GetText("Set extratics to %d\n"), doomcom->extratics); } - if (M_CheckParm("-bandwidth")) - { - if (M_IsNextParm()) - { - net_bandwidth = atoi(M_GetNextParm()); - if (net_bandwidth < 1000) - net_bandwidth = 1000; - if (net_bandwidth > 100000) - hardware_MAXPACKETLENGTH = MAXPACKETLENGTH; - CONS_Printf(M_GetText("Network bandwidth set to %d\n"), net_bandwidth); - } - else - I_Error("usage: -bandwidth "); - } - software_MAXPACKETLENGTH = hardware_MAXPACKETLENGTH; if (M_CheckParm("-packetsize")) { @@ -1282,8 +1248,6 @@ boolean D_CheckNetGame(void) if (netgame) multiplayer = true; - if (doomcom->id != DOOMCOM_ID) - I_Error("Doomcom buffer invalid!"); if (doomcom->numnodes > MAXNETNODES) I_Error("Too many nodes (%d), max:%d", doomcom->numnodes, MAXNETNODES); @@ -1293,7 +1257,7 @@ boolean D_CheckNetGame(void) if (M_CheckParm("-debugfile")) { char filename[21]; - INT32 k = doomcom->consoleplayer - 1; + INT32 k = consoleplayer - 1; if (M_IsNextParm()) k = atoi(M_GetNextParm()) - 1; while (!debugfile && k < MAXPLAYERS) @@ -1400,7 +1364,6 @@ void D_CloseConnection(void) I_NetGet = Internal_Get; I_NetSend = Internal_Send; - I_NetCanSend = NULL; I_NetCloseSocket = NULL; I_NetFreeNodenum = Internal_FreeNodenum; I_NetMakeNodewPort = NULL; diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index f7b98c4db..8376f26b9 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -391,7 +391,7 @@ static CV_PossibleValue_t perfstats_cons_t[] = { consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", CV_CALL, perfstats_cons_t, PS_PerfStats_OnChange); static CV_PossibleValue_t ps_samplesize_cons_t[] = { {1, "MIN"}, {1000, "MAX"}, {0, NULL}}; -consvar_t cv_ps_samplesize = CVAR_INIT ("ps_samplesize", "1", CV_CALL, ps_samplesize_cons_t, PS_SampleSize_OnChange); +consvar_t cv_ps_samplesize = CVAR_INIT ("ps_samplesize", "175", CV_CALL, ps_samplesize_cons_t, PS_SampleSize_OnChange); static CV_PossibleValue_t ps_descriptor_cons_t[] = { {1, "Average"}, {2, "SD"}, {3, "Minimum"}, {4, "Maximum"}, {0, NULL}}; consvar_t cv_ps_descriptor = CVAR_INIT ("ps_descriptor", "Average", 0, ps_descriptor_cons_t, NULL); @@ -620,6 +620,7 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_blamecfail); CV_RegisterVar(&cv_dedicatedidletime); CV_RegisterVar(&cv_idletime); + CV_RegisterVar(&cv_idlespectate); CV_RegisterVar(&cv_httpsource); COM_AddCommand("ping", Command_Ping_f, COM_LUA); @@ -2510,11 +2511,11 @@ static void MutePlayer(boolean mute) if (COM_Argc() < 2) { - CONS_Printf(M_GetText("muteplayer : mute a player\n")); + CONS_Printf(M_GetText("muteplayer : mute a player\n")); return; } - data[0] = atoi(COM_Argv(1)); + data[0] = nametonum(COM_Argv(1)); if (data[0] >= MAXPLAYERS || !playeringame[data[0]]) { CONS_Alert(CONS_NOTICE, M_GetText("There is no player %u!\n"), (unsigned int)data[0]); @@ -2603,11 +2604,11 @@ static void Command_ServerTeamChange_f(void) if (COM_Argc() < 3) { if (G_TagGametype()) - CONS_Printf(M_GetText("serverchangeteam : switch player to a new team (%s)\n"), "it, notit, playing, or spectator"); + CONS_Printf(M_GetText("serverchangeteam : switch player to a new team (%s)\n"), "it, notit, playing, or spectator"); else if (G_GametypeHasTeams()) - CONS_Printf(M_GetText("serverchangeteam : switch player to a new team (%s)\n"), "red, blue or spectator"); + CONS_Printf(M_GetText("serverchangeteam : switch player to a new team (%s)\n"), "red, blue or spectator"); else if (G_GametypeHasSpectators()) - CONS_Printf(M_GetText("serverchangeteam : switch player to a new team (%s)\n"), "spectator or playing"); + CONS_Printf(M_GetText("serverchangeteam : switch player to a new team (%s)\n"), "spectator or playing"); else CONS_Alert(CONS_NOTICE, M_GetText("This command cannot be used in this gametype.\n")); return; @@ -2655,19 +2656,19 @@ static void Command_ServerTeamChange_f(void) if (error) { if (G_TagGametype()) - CONS_Printf(M_GetText("serverchangeteam : switch player to a new team (%s)\n"), "it, notit, playing, or spectator"); + CONS_Printf(M_GetText("serverchangeteam : switch player to a new team (%s)\n"), "it, notit, playing, or spectator"); else if (G_GametypeHasTeams()) - CONS_Printf(M_GetText("serverchangeteam : switch player to a new team (%s)\n"), "red, blue or spectator"); + CONS_Printf(M_GetText("serverchangeteam : switch player to a new team (%s)\n"), "red, blue or spectator"); else if (G_GametypeHasSpectators()) - CONS_Printf(M_GetText("serverchangeteam : switch player to a new team (%s)\n"), "spectator or playing"); + CONS_Printf(M_GetText("serverchangeteam : switch player to a new team (%s)\n"), "spectator or playing"); return; } - NetPacket.packet.playernum = atoi(COM_Argv(1)); + NetPacket.packet.playernum = nametonum(COM_Argv(1)); - if (!playeringame[NetPacket.packet.playernum]) + if (NetPacket.packet.playernum == -1 || !playeringame[NetPacket.packet.playernum]) { - CONS_Alert(CONS_NOTICE, M_GetText("There is no player %d!\n"), NetPacket.packet.playernum); + CONS_Alert(CONS_NOTICE, M_GetText("There is no player %s!\n"), COM_Argv(1)); return; } @@ -3106,13 +3107,16 @@ static void Command_Verify_f(void) if (COM_Argc() != 2) { - CONS_Printf(M_GetText("promote : give admin privileges to a player\n")); + CONS_Printf(M_GetText("promote : give admin privileges to a player\n")); return; } - strlcpy(buf, COM_Argv(1), sizeof (buf)); - - playernum = atoi(buf); + playernum = nametonum(COM_Argv(1)); + if (playernum == -1) + { + CONS_Alert(CONS_NOTICE, M_GetText("There is no player %s!\n"), COM_Argv(1)); + return; + } temp = buf; @@ -3156,13 +3160,16 @@ static void Command_RemoveAdmin_f(void) if (COM_Argc() != 2) { - CONS_Printf(M_GetText("demote : remove admin privileges from a player\n")); + CONS_Printf(M_GetText("demote : remove admin privileges from a player\n")); return; } - strlcpy(buf, COM_Argv(1), sizeof(buf)); - - playernum = atoi(buf); + playernum = nametonum(COM_Argv(1)); + if (playernum == -1) + { + CONS_Alert(CONS_NOTICE, M_GetText("There is no player %s!\n"), COM_Argv(1)); + return; + } temp = buf; @@ -4792,12 +4799,11 @@ static void Command_Togglemodified_f(void) modifiedgame = !modifiedgame; } -extern UINT8 *save_p; static void Command_Archivetest_f(void) { - UINT8 *buf; UINT32 i, wrote; thinker_t *th; + save_t savebuffer; if (gamestate != GS_LEVEL) { CONS_Printf("This command only works in-game, you dummy.\n"); @@ -4811,28 +4817,29 @@ static void Command_Archivetest_f(void) ((mobj_t *)th)->mobjnum = i++; // allocate buffer - buf = save_p = ZZ_Alloc(1024); + savebuffer.size = 1024; + savebuffer.buf = malloc(savebuffer.size); + savebuffer.pos = 0; // test archive CONS_Printf("LUA_Archive...\n"); - LUA_Archive(); - WRITEUINT8(save_p, 0x7F); - wrote = (UINT32)(save_p-buf); + LUA_Archive(&savebuffer); + P_WriteUINT8(&savebuffer, 0x7F); + wrote = savebuffer.pos; // clear Lua state, so we can really see what happens! CONS_Printf("Clearing state!\n"); LUA_ClearExtVars(); // test unarchive - save_p = buf; CONS_Printf("LUA_UnArchive...\n"); - LUA_UnArchive(); - i = READUINT8(save_p); - if (i != 0x7F || wrote != (UINT32)(save_p-buf)) - CONS_Printf("Savegame corrupted. (write %u, read %u)\n", wrote, (UINT32)(save_p-buf)); + LUA_UnArchive(&savebuffer); + i = P_ReadUINT8(&savebuffer); + if (i != 0x7F || wrote != (UINT32)(savebuffer.pos)) + CONS_Printf("Savegame corrupted. (write %u, read %u)\n", wrote, (UINT32)(savebuffer.pos)); // free buffer - Z_Free(buf); + free(savebuffer.buf); CONS_Printf("Done. No crash.\n"); } #endif @@ -4903,11 +4910,13 @@ static void Name2_OnChange(void) static boolean Skin_CanChange(const char *valstr) { - (void)valstr; - if (!Playing()) return true; // do whatever you want + // You already are that skin. + if (stricmp(skins[players[consoleplayer].skin]->name, valstr) == 0) + return false; + if (!(multiplayer || netgame)) // In single player. return true; @@ -4922,11 +4931,13 @@ static boolean Skin_CanChange(const char *valstr) static boolean Skin2_CanChange(const char *valstr) { - (void)valstr; - if (!Playing() || !splitscreen) return true; // do whatever you want + // You already are that skin. + if (stricmp(skins[players[secondarydisplayplayer].skin]->name, valstr) == 0) + return false; + if (CanChangeSkin(secondarydisplayplayer) && !P_PlayerMoving(secondarydisplayplayer)) return true; else diff --git a/src/netcode/d_netcmd.h b/src/netcode/d_netcmd.h index f92878a4e..c11575575 100644 --- a/src/netcode/d_netcmd.h +++ b/src/netcode/d_netcmd.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/netcode/d_netfil.c b/src/netcode/d_netfil.c index a8a10d475..313905f43 100644 --- a/src/netcode/d_netfil.c +++ b/src/netcode/d_netfil.c @@ -95,6 +95,7 @@ static filetran_t transfer[MAXNETNODES]; INT32 fileneedednum; // Number of files needed to join the server fileneeded_t *fileneeded; // List of needed files static tic_t lasttimeackpacketsent = 0; +static I_mutex downloadmutex; char downloaddir[512] = "DOWNLOAD"; // For resuming failed downloads @@ -606,7 +607,7 @@ void AddLuaFileTransfer(const char *filename, const char *mode) prevnext = &((*prevnext)->next); // Allocate file transfer information and append it to the transfer list - filetransfer = malloc(sizeof(luafiletransfer_t)); + filetransfer = calloc(1, sizeof(luafiletransfer_t)); if (!filetransfer) I_Error("AddLuaFileTransfer: Out of memory\n"); *prevnext = filetransfer; @@ -1033,7 +1034,6 @@ void FileSendTicker(void) netbuffer->packettype = PT_FILEFRAGMENT; - // (((sendbytes-nowsentbyte)*TICRATE)/(I_GetTime()-starttime)<(UINT32)net_bandwidth) while (packetsent-- && filestosend != 0) { for (i = currentnode, j = 0; j < MAXNETNODES; @@ -1610,11 +1610,13 @@ boolean CURLPrepareFile(const char* url, int dfilenum) I_Error("Attempted to download files in -nodownload mode"); #endif - curl_global_init(CURL_GLOBAL_ALL); + if (!multi_handle) + { + curl_global_init(CURL_GLOBAL_ALL); + multi_handle = curl_multi_init(); + } http_handle = curl_easy_init(); - multi_handle = curl_multi_init(); - if (http_handle && multi_handle) { I_mkdir(downloaddir, 0755); @@ -1673,6 +1675,8 @@ boolean CURLPrepareFile(const char* url, int dfilenum) filedownload.current = dfilenum; filedownload.http_running = true; + I_spawn_thread("http-download", (I_thread_fn)CURLGetFile, NULL); + return true; } @@ -1681,103 +1685,119 @@ boolean CURLPrepareFile(const char* url, int dfilenum) return false; } +void CURLAbortFile(void) +{ + filedownload.http_running = false; + + // lock and unlock to wait for the download thread to exit + I_lock_mutex(&downloadmutex); + I_unlock_mutex(downloadmutex); +} + void CURLGetFile(void) { + I_lock_mutex(&downloadmutex); CURLMcode mc; /* return code used by curl_multi_wait() */ CURLcode easyres; /* Return from easy interface */ - int numfds; CURLMsg *m; /* for picking up messages with the transfer status */ CURL *e; int msgs_left; /* how many messages are left */ const char *easy_handle_error; + boolean running = true; - if (curl_runninghandles) + while (running && filedownload.http_running) { - curl_multi_perform(multi_handle, &curl_runninghandles); - - /* wait for activity, timeout or "nothing" */ - mc = curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds); - - if (mc != CURLM_OK) + if (curl_runninghandles) { - CONS_Alert(CONS_WARNING, "curl_multi_wait() failed, code %d.\n", mc); - return; - } - curl_curfile->currentsize = curl_dlnow; - curl_curfile->totalsize = curl_dltotal; - } + curl_multi_perform(multi_handle, &curl_runninghandles); - /* See how the transfers went */ - while ((m = curl_multi_info_read(multi_handle, &msgs_left))) - { - if (m && (m->msg == CURLMSG_DONE)) - { - e = m->easy_handle; - easyres = m->data.result; + /* wait for activity, timeout or "nothing" */ + mc = curl_multi_wait(multi_handle, NULL, 0, 1000, NULL); - char *filename = Z_StrDup(curl_realname); - nameonly(filename); - - if (easyres != CURLE_OK) + if (mc != CURLM_OK) { - long response_code = 0; - - if (easyres == CURLE_HTTP_RETURNED_ERROR) - curl_easy_getinfo(e, CURLINFO_RESPONSE_CODE, &response_code); - - if (response_code == 404) - curl_curfile->failed = FDOWNLOAD_FAIL_NOTFOUND; - else - curl_curfile->failed = FDOWNLOAD_FAIL_OTHER; - - easy_handle_error = (response_code) ? va("HTTP response code %ld", response_code) : curl_easy_strerror(easyres); - curl_curfile->status = FS_FALLBACK; - curl_curfile->currentsize = curl_origfilesize; - curl_curfile->totalsize = curl_origtotalfilesize; - filedownload.http_failed = true; - fclose(curl_curfile->file); - remove(curl_curfile->filename); - CONS_Alert(CONS_ERROR, M_GetText("Failed to download addon \"%s\" (%s)\n"), filename, easy_handle_error); + CONS_Alert(CONS_WARNING, "curl_multi_wait() failed, code %d.\n", mc); + continue; } - else + curl_curfile->currentsize = curl_dlnow; + curl_curfile->totalsize = curl_dltotal; + } + + /* See how the transfers went */ + while ((m = curl_multi_info_read(multi_handle, &msgs_left))) + { + if (m && (m->msg == CURLMSG_DONE)) { - fclose(curl_curfile->file); + running = false; + e = m->easy_handle; + easyres = m->data.result; - CONS_Printf(M_GetText("Finished download of \"%s\"\n"), filename); + char *filename = Z_StrDup(curl_realname); + nameonly(filename); - if (checkfilemd5(curl_curfile->filename, curl_curfile->md5sum) == FS_MD5SUMBAD) + if (easyres != CURLE_OK) { - CONS_Alert(CONS_WARNING, M_GetText("File \"%s\" does not match the version used by the server\n"), filename); + long response_code = 0; + + if (easyres == CURLE_HTTP_RETURNED_ERROR) + curl_easy_getinfo(e, CURLINFO_RESPONSE_CODE, &response_code); + + if (response_code == 404) + curl_curfile->failed = FDOWNLOAD_FAIL_NOTFOUND; + else + curl_curfile->failed = FDOWNLOAD_FAIL_OTHER; + + easy_handle_error = (response_code) ? va("HTTP response code %ld", response_code) : curl_easy_strerror(easyres); curl_curfile->status = FS_FALLBACK; - curl_curfile->failed = FDOWNLOAD_FAIL_MD5SUMBAD; + curl_curfile->currentsize = curl_origfilesize; + curl_curfile->totalsize = curl_origtotalfilesize; filedownload.http_failed = true; + fclose(curl_curfile->file); + remove(curl_curfile->filename); + CONS_Alert(CONS_ERROR, M_GetText("Failed to download addon \"%s\" (%s)\n"), filename, easy_handle_error); } else { - filedownload.completednum++; - filedownload.completedsize += curl_curfile->totalsize; - curl_curfile->status = FS_FOUND; + fclose(curl_curfile->file); + + CONS_Printf(M_GetText("Finished download of \"%s\"\n"), filename); + + if (checkfilemd5(curl_curfile->filename, curl_curfile->md5sum) == FS_MD5SUMBAD) + { + CONS_Alert(CONS_WARNING, M_GetText("File \"%s\" does not match the version used by the server\n"), filename); + curl_curfile->status = FS_FALLBACK; + curl_curfile->failed = FDOWNLOAD_FAIL_MD5SUMBAD; + filedownload.http_failed = true; + } + else + { + filedownload.completednum++; + filedownload.completedsize += curl_curfile->totalsize; + curl_curfile->status = FS_FOUND; + } } + + Z_Free(filename); + + curl_curfile->file = NULL; + filedownload.remaining--; + curl_multi_remove_handle(multi_handle, e); + curl_easy_cleanup(e); + + if (!filedownload.remaining) + break; } - - Z_Free(filename); - - curl_curfile->file = NULL; - filedownload.http_running = false; - filedownload.remaining--; - curl_multi_remove_handle(multi_handle, e); - curl_easy_cleanup(e); - - if (!filedownload.remaining) - break; } } - if (!filedownload.remaining) + if (!filedownload.remaining || !filedownload.http_running) { curl_multi_cleanup(multi_handle); curl_global_cleanup(); + multi_handle = NULL; } + filedownload.http_running = false; + I_unlock_mutex(downloadmutex); } HTTP_login * diff --git a/src/netcode/d_netfil.h b/src/netcode/d_netfil.h index 4039b5e2d..9f29d18bb 100644 --- a/src/netcode/d_netfil.h +++ b/src/netcode/d_netfil.h @@ -140,6 +140,7 @@ boolean CL_SendFileRequest(void); void PT_RequestFile(SINT8 node); boolean CURLPrepareFile(const char* url, int dfilenum); +void CURLAbortFile(void); void CURLGetFile(void); HTTP_login * CURLGetLogin (const char *url, HTTP_login ***return_prev_next); diff --git a/src/netcode/gamestate.c b/src/netcode/gamestate.c index f36347c6d..967e23650 100644 --- a/src/netcode/gamestate.c +++ b/src/netcode/gamestate.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -54,30 +54,25 @@ boolean SV_ResendingSavegameToAnyone(void) void SV_SendSaveGame(INT32 node, boolean resending) { size_t length, compressedlen; - UINT8 *savebuffer; + save_t savebuffer; UINT8 *compressedsave; UINT8 *buffertosend; // first save it in a malloced buffer - savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); - if (!savebuffer) + savebuffer.size = SAVEGAMESIZE; + savebuffer.buf = (UINT8 *)malloc(savebuffer.size); + if (!savebuffer.buf) { CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); return; } // Leave room for the uncompressed length. - save_p = savebuffer + sizeof(UINT32); + savebuffer.pos = sizeof(UINT32); - P_SaveNetGame(resending); + P_SaveNetGame(&savebuffer, resending); - length = save_p - savebuffer; - if (length > SAVEGAMESIZE) - { - free(savebuffer); - save_p = NULL; - I_Error("Savegame buffer overrun"); - } + length = savebuffer.pos; // Allocate space for compressed save: one byte fewer than for the // uncompressed data to ensure that the compression is worthwhile. @@ -85,15 +80,16 @@ void SV_SendSaveGame(INT32 node, boolean resending) if (!compressedsave) { CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); + free(savebuffer.buf); return; } // Attempt to compress it. - if((compressedlen = lzf_compress(savebuffer + sizeof(UINT32), length - sizeof(UINT32), compressedsave + sizeof(UINT32), length - sizeof(UINT32) - 1))) + if((compressedlen = lzf_compress(savebuffer.buf + sizeof(UINT32), length - sizeof(UINT32), compressedsave + sizeof(UINT32), length - sizeof(UINT32) - 1))) { // Compressing succeeded; send compressed data - free(savebuffer); + free(savebuffer.buf); // State that we're compressed. buffertosend = compressedsave; @@ -107,12 +103,12 @@ void SV_SendSaveGame(INT32 node, boolean resending) free(compressedsave); // State that we're not compressed - buffertosend = savebuffer; - WRITEUINT32(savebuffer, 0); + buffertosend = savebuffer.buf; + savebuffer.pos = 0; + P_WriteUINT32(&savebuffer, 0); } AddRamToSendQueue(node, buffertosend, length, SF_RAM, 0); - save_p = NULL; // Remember when we started sending the savegame so we can handle timeouts netnodes[node].sendingsavegame = true; @@ -125,8 +121,7 @@ static consvar_t cv_dumpconsistency = CVAR_INIT ("dumpconsistency", "Off", CV_SA void SV_SavedGame(void) { - size_t length; - UINT8 *savebuffer; + save_t savebuffer; char tmpsave[256]; if (!cv_dumpconsistency.value) @@ -135,29 +130,22 @@ void SV_SavedGame(void) sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); // first save it in a malloced buffer - save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); - if (!save_p) + savebuffer.size = SAVEGAMESIZE; + savebuffer.buf = (UINT8 *)malloc(savebuffer.size); + if (!savebuffer.buf) { CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); return; } + savebuffer.pos = 0; - P_SaveNetGame(false); - - length = save_p - savebuffer; - if (length > SAVEGAMESIZE) - { - free(savebuffer); - save_p = NULL; - I_Error("Savegame buffer overrun"); - } + P_SaveNetGame(&savebuffer, false); // then save it! - if (!FIL_WriteFile(tmpsave, savebuffer, length)) + if (!FIL_WriteFile(tmpsave, savebuffer.buf, savebuffer.pos)) CONS_Printf(M_GetText("Didn't save %s for netgame"), tmpsave); - free(savebuffer); - save_p = NULL; + free(savebuffer.pos); } #undef TMPSAVENAME @@ -167,33 +155,34 @@ void SV_SavedGame(void) void CL_LoadReceivedSavegame(boolean reloading) { - UINT8 *savebuffer = NULL; - size_t length, decompressedlen; + save_t savebuffer; + size_t decompressedlen; char tmpsave[256]; FreeFileNeeded(); sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); - length = FIL_ReadFile(tmpsave, &savebuffer); + savebuffer.size = FIL_ReadFile(tmpsave, &savebuffer.buf); + savebuffer.pos = 0; - CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(length)); - if (!length) + CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(savebuffer.size)); + if (!savebuffer.size) { I_Error("Can't read savegame sent"); return; } - save_p = savebuffer; - // Decompress saved game if necessary. - decompressedlen = READUINT32(save_p); + decompressedlen = P_ReadUINT32(&savebuffer); if(decompressedlen > 0) { UINT8 *decompressedbuffer = Z_Malloc(decompressedlen, PU_STATIC, NULL); - lzf_decompress(save_p, length - sizeof(UINT32), decompressedbuffer, decompressedlen); - Z_Free(savebuffer); - save_p = savebuffer = decompressedbuffer; + lzf_decompress(savebuffer.buf + sizeof(UINT32), savebuffer.size - sizeof(UINT32), decompressedbuffer, decompressedlen); + Z_Free(savebuffer.buf); + savebuffer.buf = decompressedbuffer; + savebuffer.size = decompressedlen; + savebuffer.pos = 0; } paused = false; @@ -203,7 +192,7 @@ void CL_LoadReceivedSavegame(boolean reloading) automapactive = false; // load a base level - if (P_LoadNetGame(reloading)) + if (P_LoadNetGame(&savebuffer, reloading)) { const UINT8 actnum = mapheaderinfo[gamemap-1]->actnum; CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)); @@ -219,8 +208,7 @@ void CL_LoadReceivedSavegame(boolean reloading) } // done - Z_Free(savebuffer); - save_p = NULL; + Z_Free(savebuffer.buf); if (unlink(tmpsave) == -1) CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave); consistancy[gametic%BACKUPTICS] = Consistancy(); diff --git a/src/netcode/i_net.h b/src/netcode/i_net.h index 09b842296..a2039bd19 100644 --- a/src/netcode/i_net.h +++ b/src/netcode/i_net.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -32,7 +32,6 @@ #define INETPACKETLENGTH 1024 extern INT16 hardware_MAXPACKETLENGTH; -extern INT32 net_bandwidth; // in byte/s #if defined(_MSC_VER) #pragma pack(1) @@ -40,36 +39,17 @@ extern INT32 net_bandwidth; // in byte/s typedef struct { - /// Supposed to be DOOMCOM_ID - INT32 id; - - /// SRB2 executes an INT32 to execute commands. - INT16 intnum; - /// Communication between SRB2 and the driver. - /// Is CMD_SEND or CMD_GET. - INT16 command; /// Is dest for send, set by get (-1 = no packet). INT16 remotenode; - /// Number of bytes in doomdata to be sent INT16 datalength; /// Info common to all nodes. /// Console is always node 0. INT16 numnodes; - /// Flag: 1 = no duplication, 2-5 = dup for slow nets. - INT16 ticdup; /// Flag: 1 = send a backup tic in every packet. INT16 extratics; - /// kind of game - INT16 gametype; - /// Flag: -1 = new game, 0-5 = load savegame - INT16 savegame; - /// currect map - INT16 map; - /// Info specific to this node. - INT16 consoleplayer; /// Number of "slots": the highest player number in use plus one. INT16 numslots; @@ -87,18 +67,10 @@ extern doomcom_t *doomcom; */ extern boolean (*I_NetGet)(void); -/** \brief ask to driver if there is data waiting -*/ -extern boolean (*I_NetCanGet)(void); - /** \brief send packet within doomcom struct */ extern void (*I_NetSend)(void); -/** \brief ask to driver if all is ok to send data now -*/ -extern boolean (*I_NetCanSend)(void); - /** \brief close a connection \param nodenum node to be closed diff --git a/src/netcode/i_tcp.c b/src/netcode/i_tcp.c index 6a50f440b..256d9992e 100644 --- a/src/netcode/i_tcp.c +++ b/src/netcode/i_tcp.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -37,6 +37,7 @@ #endif #include "../doomdef.h" +#include "../z_zone.h" #ifdef USE_WINSOCK1 #include @@ -87,6 +88,10 @@ #undef EHOSTUNREACH #endif #define EHOSTUNREACH WSAEHOSTUNREACH + #ifdef ENETUNREACH + #undef ENETUNREACH + #endif + #define ENETUNREACH WSAENETUNREACH #ifndef IOC_VENDOR #define IOC_VENDOR 0x18000000 #endif @@ -120,8 +125,6 @@ typedef union static boolean UPNP_support = true; #endif // HAVE_MINIUPNC -#define MAXBANS 100 - #include "../i_system.h" #include "i_net.h" #include "d_net.h" @@ -140,7 +143,6 @@ typedef union #endif #include "i_addrinfo.h" -#define SELECTTEST #define DEFAULTPORT "5029" #ifdef USE_WINSOCK @@ -169,8 +171,8 @@ static mysockaddr_t clientaddress[MAXNETNODES+1]; static mysockaddr_t broadcastaddress[MAXNETNODES+1]; static size_t broadcastaddresses = 0; static boolean nodeconnected[MAXNETNODES+1]; -static mysockaddr_t banned[MAXBANS]; -static UINT8 bannedmask[MAXBANS]; +static mysockaddr_t *banned; +static UINT8 *bannedmask; static size_t numbans = 0; static boolean SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1? @@ -317,7 +319,11 @@ init_upnpc_once(struct upnpdata *upnpuserdata) I_OutputMsg(M_GetText("Found UPnP device:\n desc: %s\n st: %s\n"), dev->descURL, dev->st); +#if (MINIUPNPC_API_VERSION >= 18) + UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), NULL, 0); +#else UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); +#endif I_OutputMsg(M_GetText("Local LAN IP address: %s\n"), lanaddr); descXML = miniwget(dev->descURL, &descXMLsize, scope_id, &status_code); if (descXML) @@ -624,56 +630,6 @@ static boolean SOCK_Get(void) return false; } -// check if we can send (do not go over the buffer) - -static fd_set masterset; - -#ifdef SELECTTEST -static boolean FD_CPY(fd_set *src, fd_set *dst, SOCKET_TYPE *fd, size_t len) -{ - boolean testset = false; - FD_ZERO(dst); - for (size_t i = 0; i < len;i++) - { - if(fd[i] != (SOCKET_TYPE)ERRSOCKET && - FD_ISSET(fd[i], src) && !FD_ISSET(fd[i], dst)) // no checking for dups - { - FD_SET(fd[i], dst); - testset = true; - } - } - return testset; -} - -static boolean SOCK_CanSend(void) -{ - struct timeval timeval_for_select = {0, 0}; - fd_set tset; - int wselect; - - if(!FD_CPY(&masterset, &tset, mysockets, mysocketses)) - return false; - wselect = select(255, NULL, &tset, NULL, &timeval_for_select); - if (wselect >= 1) - return true; - return false; -} - -static boolean SOCK_CanGet(void) -{ - struct timeval timeval_for_select = {0, 0}; - fd_set tset; - int rselect; - - if(!FD_CPY(&masterset, &tset, mysockets, mysocketses)) - return false; - rselect = select(255, &tset, NULL, NULL, &timeval_for_select); - if (rselect >= 1) - return true; - return false; -} -#endif - static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr) { socklen_t d4 = (socklen_t)sizeof(struct sockaddr_in); @@ -681,7 +637,6 @@ static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr socklen_t d6 = (socklen_t)sizeof(struct sockaddr_in6); #endif socklen_t d, da = (socklen_t)sizeof(mysockaddr_t); - ssize_t status; switch (sockaddr->any.sa_family) { @@ -692,14 +647,11 @@ static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr default: d = da; break; } - status = sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d); - if (status == -1) - { - CONS_Alert(CONS_WARNING, "Unable to send packet to %s: %s\n", SOCK_AddrToStr(sockaddr), strerror(errno)); - } - return status; + return sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d); } +#define ALLOWEDERROR(x) ((x) == ECONNREFUSED || (x) == EWOULDBLOCK || (x) == EHOSTUNREACH || (x) == ENETUNREACH) + static void SOCK_Send(void) { ssize_t c = ERRSOCKET; @@ -714,19 +666,25 @@ static void SOCK_Send(void) for (size_t j = 0; j < broadcastaddresses; j++) { if (myfamily[i] == broadcastaddress[j].any.sa_family) - SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]); + { + c = SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]); + if (c == ERRSOCKET && !ALLOWEDERROR(errno)) + break; + } } } - return; } else if (nodesocket[doomcom->remotenode] == (SOCKET_TYPE)ERRSOCKET) { for (size_t i = 0; i < mysocketses; i++) { if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family) - SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]); + { + c = SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]); + if (c == ERRSOCKET && !ALLOWEDERROR(errno)) + break; + } } - return; } else { @@ -736,12 +694,14 @@ static void SOCK_Send(void) if (c == ERRSOCKET) { int e = errno; // save error code so it can't be modified later - if (e != ECONNREFUSED && e != EWOULDBLOCK && e != EHOSTUNREACH) + if (!ALLOWEDERROR(e)) I_Error("SOCK_Send, error sending to node %d (%s) #%u: %s", doomcom->remotenode, SOCK_GetNodeAddress(doomcom->remotenode), e, strerror(e)); } } +#undef ALLOWEDERROR + static void SOCK_FreeNodenum(INT32 numnode) { // can't disconnect from self :) @@ -911,7 +871,6 @@ static boolean UDP_Socket(void) mysockets[s] = ERRSOCKET; for (s = 0; s < MAXNETNODES+1; s++) nodesocket[s] = ERRSOCKET; - FD_ZERO(&masterset); s = 0; memset(&hints, 0x00, sizeof (hints)); @@ -938,7 +897,6 @@ static boolean UDP_Socket(void) mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen); if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET) { - FD_SET(mysockets[s], &masterset); myfamily[s] = hints.ai_family; s++; } @@ -959,7 +917,6 @@ static boolean UDP_Socket(void) mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen); if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET) { - FD_SET(mysockets[s], &masterset); myfamily[s] = hints.ai_family; s++; #ifdef HAVE_MINIUPNPC @@ -992,7 +949,6 @@ static boolean UDP_Socket(void) mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen); if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET) { - FD_SET(mysockets[s], &masterset); myfamily[s] = hints.ai_family; s++; } @@ -1013,7 +969,6 @@ static boolean UDP_Socket(void) mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen); if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET) { - FD_SET(mysockets[s], &masterset); myfamily[s] = hints.ai_family; s++; } @@ -1139,16 +1094,13 @@ boolean I_InitTcpDriver(void) static void SOCK_CloseSocket(void) { - for (size_t i=0; i < MAXNETNODES+1; i++) + for (size_t i=0; i < mysocketses; i++) { - if (mysockets[i] != (SOCKET_TYPE)ERRSOCKET - && FD_ISSET(mysockets[i], &masterset)) - { - FD_CLR(mysockets[i], &masterset); + if (mysockets[i] != (SOCKET_TYPE)ERRSOCKET) close(mysockets[i]); - } mysockets[i] = ERRSOCKET; } + mysocketses = 0; } void I_ShutdownTcpDriver(void) @@ -1200,11 +1152,7 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) // test ip address of server for (i = 0; i < mysocketses; ++i) { - /* sendto tests that there is a network to this - address */ - if (runp->ai_addr->sa_family == myfamily[i] && - sendto(mysockets[i], NULL, 0, 0, - runp->ai_addr, runp->ai_addrlen) == 0) + if (runp->ai_addr->sa_family == myfamily[i]) { memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen); break; @@ -1234,12 +1182,6 @@ static boolean SOCK_OpenSocket(void) I_NetFreeNodenum = SOCK_FreeNodenum; I_NetMakeNodewPort = SOCK_NetMakeNodewPort; -#ifdef SELECTTEST - // seem like not work with libsocket : ( - I_NetCanSend = SOCK_CanSend; - I_NetCanGet = SOCK_CanGet; -#endif - // build the socket but close it first SOCK_CloseSocket(); return UDP_Socket(); @@ -1249,9 +1191,9 @@ static boolean SOCK_Ban(INT32 node) { if (node > MAXNETNODES) return false; - if (numbans == MAXBANS) - return false; + banned = Z_Realloc(banned, sizeof(*banned) * (numbans+1), PU_STATIC, NULL); + bannedmask = Z_Realloc(bannedmask, sizeof(*bannedmask) * (numbans+1), PU_STATIC, NULL); M_Memcpy(&banned[numbans], &clientaddress[node], sizeof (mysockaddr_t)); if (banned[numbans].any.sa_family == AF_INET) { @@ -1262,7 +1204,7 @@ static boolean SOCK_Ban(INT32 node) else if (banned[numbans].any.sa_family == AF_INET6) { banned[numbans].ip6.sin6_port = 0; - bannedmask[numbans] = 128; + bannedmask[numbans] = 64; } #endif numbans++; @@ -1274,7 +1216,7 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask) struct my_addrinfo *ai, *runp, hints; int gaie; - if (numbans == MAXBANS || !address) + if (!address) return false; memset(&hints, 0x00, sizeof(hints)); @@ -1289,15 +1231,17 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask) runp = ai; - while(runp != NULL && numbans != MAXBANS) + while(runp != NULL) { + banned = Z_Realloc(banned, sizeof(*banned) * (numbans+1), PU_STATIC, NULL); + bannedmask = Z_Realloc(bannedmask, sizeof(*bannedmask) * (numbans+1), PU_STATIC, NULL); memcpy(&banned[numbans], runp->ai_addr, runp->ai_addrlen); if (mask) bannedmask[numbans] = (UINT8)atoi(mask); #ifdef HAVE_IPV6 else if (runp->ai_family == AF_INET6) - bannedmask[numbans] = 128; + bannedmask[numbans] = 64; #endif else bannedmask[numbans] = 32; @@ -1306,7 +1250,7 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask) bannedmask[numbans] = 32; #ifdef HAVE_IPV6 else if (bannedmask[numbans] > 128 && runp->ai_family == AF_INET6) - bannedmask[numbans] = 128; + bannedmask[numbans] = 64; #endif numbans++; runp = runp->ai_next; @@ -1320,6 +1264,10 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask) static void SOCK_ClearBans(void) { numbans = 0; + Z_Free(banned); + banned = NULL; + Z_Free(bannedmask); + bannedmask = NULL; } boolean I_InitTcpNetwork(void) @@ -1374,7 +1322,6 @@ boolean I_InitTcpNetwork(void) // FIXME: // ??? and now ? // server on a big modem ??? 4*isdn - net_bandwidth = 16000; hardware_MAXPACKETLENGTH = INETPACKETLENGTH; ret = true; @@ -1403,7 +1350,6 @@ boolean I_InitTcpNetwork(void) // so we're on a LAN COM_BufAddText("connect any\n"); - net_bandwidth = 800000; hardware_MAXPACKETLENGTH = MAXPACKETLENGTH; } } diff --git a/src/netcode/mserv.c b/src/netcode/mserv.c index 74ee120f9..78a395344 100644 --- a/src/netcode/mserv.c +++ b/src/netcode/mserv.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // Copyright (C) 2020-2023 by James R. // // This program is free software distributed under the diff --git a/src/p_enemy.c b/src/p_enemy.c index e1b21e295..60cffebfc 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -3744,7 +3744,7 @@ static void P_DoBossVictory(mobj_t *mo) // scan the remaining thinkers to see if all bosses are dead for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -6449,7 +6449,7 @@ void A_RingExplode(mobj_t *actor) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -8756,7 +8756,7 @@ void A_FindTarget(mobj_t *actor) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -8820,7 +8820,7 @@ void A_FindTracer(mobj_t *actor) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -9498,7 +9498,7 @@ void A_RemoteAction(mobj_t *actor) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -9761,7 +9761,7 @@ void A_SetObjectTypeState(mobj_t *actor) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -10391,7 +10391,7 @@ void A_CheckThingCount(mobj_t *actor) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -14395,7 +14395,7 @@ void A_LavafallLava(mobj_t *actor) if (LUA_CallAction(A_LAVAFALLLAVA, actor)) return; - if ((40 - actor->fuse) % (2*(actor->scale >> FRACBITS))) + if ((40 - actor->fuse) % max(2*(actor->scale >> FRACBITS), 1)) // avoid crashes if actor->scale < FRACUNIT return; // Don't spawn lava unless a player is nearby. diff --git a/src/p_inter.c b/src/p_inter.c index e73cd1fce..0e63fea1b 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -101,7 +101,7 @@ void P_ClearStarPost(INT32 postnum) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -130,7 +130,7 @@ void P_ResetStarposts(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; post = (mobj_t *)th; @@ -836,7 +836,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) { clientGamedata->collected[special->health-1] = true; M_UpdateUnlockablesAndExtraEmblems(clientGamedata); - G_SaveGameData(clientGamedata); + if (!prevCollected) // don't thrash the disk and wreak performance. + G_SaveGameData(clientGamedata); } if (netgame) @@ -1002,7 +1003,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // scan the thinkers to find the corresponding anchorpoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -1096,7 +1097,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // scan the remaining thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -1146,7 +1147,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // in from the paraloop. Isn't this just so efficient? for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -1521,7 +1522,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // scan the remaining thinkers to find koopa for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -2019,7 +2020,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -2869,7 +2870,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget // scan the thinkers to make sure all the old pinch dummies are gone on death for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo = (mobj_t *)th; @@ -3786,6 +3787,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (player->powers[pw_carry] == CR_NIGHTSMODE) // NiGHTS damage handling { + if (player->powers[pw_flashing]) + return false; if (!force) { if (source == target) @@ -3803,6 +3806,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (G_IsSpecialStage(gamemap) && !(damagetype & DMG_DEATHMASK)) { + if (player->powers[pw_flashing]) + return false; + if (LUA_HookMobjDamage(target, inflictor, source, damage, damagetype)) + return true; P_SpecialStageDamage(player, inflictor, source); return true; } diff --git a/src/p_local.h b/src/p_local.h index 249c3cd4b..3253ef0b6 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -39,11 +39,6 @@ // Convenience macro to fix issue with collision along bottom/left edges of blockmap -Red #define BMBOUNDFIX(xl, xh, yl, yh) {if (xl > xh) xl = 0; if (yl > yh) yl = 0;} -// MAXRADIUS is for precalculated sector block boxes -// the spider demon is larger, -// but we do not have any moving sectors nearby -#define MAXRADIUS (32*FRACUNIT) - // max Z move up or down without jumping // above this, a height difference is considered as a 'dropoff' #define MAXSTEPMOVE (24*FRACUNIT) diff --git a/src/p_map.c b/src/p_map.c index 668a8ab64..fce17f8c4 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -36,6 +36,9 @@ #include "m_perfstats.h" // ps_checkposition_calls +// Formerly called MAXRADIUS +#define MAXTRYMOVE (32*FRACUNIT) + fixed_t tmbbox[4]; mobj_t *tmthing; static INT32 tmflags; @@ -1258,8 +1261,9 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) if (tmthing->type != MT_SHELL && tmthing->target && tmthing->target->type == thing->type) { - // Don't hit same species as originator. - if (thing == tmthing->target) + // Don't hit yourself, and if a player, don't hit bots + if (thing == tmthing->target + || (thing->player && tmthing->target->player && (thing->player->bot == BOT_2PAI || thing->player->bot == BOT_2PHUMAN))) return CHECKTHING_IGNORE; if (thing->type != MT_PLAYER) @@ -1464,13 +1468,13 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) } // check for special pickup - if (thing->flags & MF_SPECIAL) + if (thing->flags & MF_SPECIAL && (tmthing->player || (tmthing->flags & MF_PUSHABLE))) // MF_PUSHABLE added for steam jets { P_TouchSpecialThing(thing, tmthing, true); // can remove thing return CHECKTHING_COLLIDE; } // check again for special pickup - if (tmthing->flags & MF_SPECIAL) + if (tmthing->flags & MF_SPECIAL && (thing->player || (thing->flags & MF_PUSHABLE))) // MF_PUSHABLE added for steam jets { P_TouchSpecialThing(tmthing, thing, true); // can remove thing return CHECKTHING_COLLIDE; @@ -2164,15 +2168,10 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) } } - // The bounding box is extended by MAXRADIUS - // because mobj_ts are grouped into mapblocks - // based on their origin point, and can overlap - // into adjacent blocks by up to MAXRADIUS units. - - xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; - xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; - yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; - yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); @@ -2392,11 +2391,6 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) } } - // The bounding box is extended by MAXRADIUS - // because mobj_ts are grouped into mapblocks - // based on their origin point, and can overlap - // into adjacent blocks by up to MAXRADIUS units. - xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; @@ -2501,6 +2495,9 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) floatok = false; + if (dedicated) // this crashes so don't even try it + return false; + if (twodlevel || (thiscam == &camera && players[displayplayer].mo && (players[displayplayer].mo->flags2 & MF2_TWOD)) || (thiscam == &camera2 && players[secondarydisplayplayer].mo && (players[secondarydisplayplayer].mo->flags2 & MF2_TWOD))) @@ -2524,16 +2521,16 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) } do { - if (x-tryx > MAXRADIUS) - tryx += MAXRADIUS; - else if (x-tryx < -MAXRADIUS) - tryx -= MAXRADIUS; + if (x-tryx > MAXTRYMOVE) + tryx += MAXTRYMOVE; + else if (x-tryx < -MAXTRYMOVE) + tryx -= MAXTRYMOVE; else tryx = x; - if (y-tryy > MAXRADIUS) - tryy += MAXRADIUS; - else if (y-tryy < -MAXRADIUS) - tryy -= MAXRADIUS; + if (y-tryy > MAXTRYMOVE) + tryy += MAXTRYMOVE; + else if (y-tryy < -MAXTRYMOVE) + tryy -= MAXTRYMOVE; else tryy = y; @@ -2679,7 +2676,7 @@ increment_move floatok = false; // This makes sure that there are no freezes from computing extremely small movements. - // Originally was MAXRADIUS/2, but that can cause some bad inconsistencies for small players. + // Originally was MAXTRYMOVE/2, but that can cause some bad inconsistencies for small players. radius = max(radius, thing->scale); // And we also have to prevent Big Large (tm) movements, as those can skip too far @@ -2868,10 +2865,10 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) { INT32 xl, xh, yl, yh; - yh = (unsigned)(thing->y + MAXRADIUS - bmaporgy)>>MAPBLOCKSHIFT; - yl = (unsigned)(thing->y - MAXRADIUS - bmaporgy)>>MAPBLOCKSHIFT; - xh = (unsigned)(thing->x + MAXRADIUS - bmaporgx)>>MAPBLOCKSHIFT; - xl = (unsigned)(thing->x - MAXRADIUS - bmaporgx)>>MAPBLOCKSHIFT; + yh = (unsigned)(thing->y + thing->radius - bmaporgy)>>MAPBLOCKSHIFT; + yl = (unsigned)(thing->y - thing->radius - bmaporgy)>>MAPBLOCKSHIFT; + xh = (unsigned)(thing->x + thing->radius - bmaporgx)>>MAPBLOCKSHIFT; + xl = (unsigned)(thing->x - thing->radius - bmaporgx)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); @@ -2943,16 +2940,16 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y) tryx = thing->x; tryy = thing->y; do { - if (x-tryx > MAXRADIUS) - tryx += MAXRADIUS; - else if (x-tryx < -MAXRADIUS) - tryx -= MAXRADIUS; + if (x-tryx > MAXTRYMOVE) + tryx += MAXTRYMOVE; + else if (x-tryx < -MAXTRYMOVE) + tryx -= MAXTRYMOVE; else tryx = x; - if (y-tryy > MAXRADIUS) - tryy += MAXRADIUS; - else if (y-tryy < -MAXRADIUS) - tryy -= MAXRADIUS; + if (y-tryy > MAXTRYMOVE) + tryy += MAXTRYMOVE; + else if (y-tryy < -MAXTRYMOVE) + tryy -= MAXTRYMOVE; else tryy = y; @@ -3960,23 +3957,25 @@ papercollision: mo->momy = tmymove; } + const fixed_t tmradius = mo->radius > 8 ? mo->radius : 8; + do { - if (tmxmove > mo->radius) { - newx = mo->x + mo->radius; - tmxmove -= mo->radius; - } else if (tmxmove < -mo->radius) { - newx = mo->x - mo->radius; - tmxmove += mo->radius; + if (tmxmove > tmradius) { + newx = mo->x + tmradius; + tmxmove -= tmradius; + } else if (tmxmove < -tmradius) { + newx = mo->x - tmradius; + tmxmove += tmradius; } else { newx = mo->x + tmxmove; tmxmove = 0; } - if (tmymove > mo->radius) { - newy = mo->y + mo->radius; - tmymove -= mo->radius; - } else if (tmymove < -mo->radius) { - newy = mo->y - mo->radius; - tmymove += mo->radius; + if (tmymove > tmradius) { + newy = mo->y + tmradius; + tmymove -= tmradius; + } else if (tmymove < -tmradius) { + newy = mo->y - tmradius; + tmymove += tmradius; } else { newy = mo->y + tmymove; tmymove = 0; @@ -4209,7 +4208,8 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 dama INT32 xl, xh, yl, yh; fixed_t dist; - dist = FixedMul(damagedist, spot->scale) + MAXRADIUS; + dist = FixedMul(damagedist, spot->scale); + yh = (unsigned)(spot->y + dist - bmaporgy)>>MAPBLOCKSHIFT; yl = (unsigned)(spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT; xh = (unsigned)(spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT; @@ -4379,15 +4379,15 @@ static boolean P_CheckSectorPolyObjects(sector_t *sector, boolean realcrush, boo { mobj_t *mo; blocknode_t *block; + blocknode_t *next = NULL; if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) continue; - block = blocklinks[y * bmapwidth + x]; - - for (; block; block = block->mnext) + for (block = blocklinks[y * bmapwidth + x]; block != NULL; block = next) { mo = block->mobj; + next = block->mnext; // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect if (!P_MobjInsidePolyobj(po, mo)) diff --git a/src/p_maputl.c b/src/p_maputl.c index 200b89cff..5398fd7a4 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1052,35 +1052,23 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *)) // boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *)) { - mobj_t *bnext = NULL; blocknode_t *block, *next = NULL; if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) return true; // Check interaction with the objects in the blockmap. - for (block = blocklinks[y*bmapwidth + x]; block; block = next) + for (block = blocklinks[y*bmapwidth + x]; block != NULL; block = next) { - next = block->mnext; - if (next) - P_SetTarget(&bnext, next->mobj); // We want to note our reference to bnext here in case it is MF_NOTHINK and gets removed! + next = block->mnext; // We want to note our reference to mnext here! if (!func(block->mobj)) - { - P_SetTarget(&bnext, NULL); return false; - } - if (P_MobjWasRemoved(tmthing) // func just popped our tmthing, cannot continue. - || (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue. - { - P_SetTarget(&bnext, NULL); + if (P_MobjWasRemoved(tmthing)) // func just popped our tmthing, cannot continue. return true; - } } - P_SetTarget(&bnext, NULL); - return true; } diff --git a/src/p_maputl.h b/src/p_maputl.h index e894c08a2..67f7fd086 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_mobj.c b/src/p_mobj.c index 3ca609390..dcebd334f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -90,7 +90,7 @@ static void P_SetupStateAnimation(mobj_t *mobj, state_t *st) if (mobj->sprite == SPR_PLAY && mobj->skin) { spritedef_t *spritedef = P_GetSkinSpritedef(mobj->skin, mobj->sprite2); - animlength = (INT32)(spritedef->numframes); + animlength = (INT32)(spritedef->numframes) - 1; } else animlength = st->var1; @@ -765,7 +765,7 @@ void P_EmeraldManager(void) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (think->removing) continue; mo = (mobj_t *)think; @@ -2246,7 +2246,7 @@ boolean P_ZMovement(mobj_t *mo) else if (!onground) P_SlopeLaunch(mo); } - + if (!mo->player && P_CheckDeathPitCollide(mo) && mo->health && !(mo->flags & MF_NOCLIPHEIGHT) && !(mo->flags2 & MF2_BOSSDEAD)) { @@ -2939,7 +2939,7 @@ boolean P_SceneryZMovement(mobj_t *mo) mo->eflags &= ~MFE_APPLYPMOMZ; } mo->z += mo->momz; - + if (!mo->player && P_CheckDeathPitCollide(mo) && mo->health && !(mo->flags & MF_NOCLIPHEIGHT) && !(mo->flags2 & MF2_BOSSDEAD)) { @@ -3455,7 +3455,7 @@ void P_DestroyRobots(void) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (think->removing) continue; mo = (mobj_t *)think; @@ -3782,7 +3782,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj) // always do the gravity bit now, that's simpler // BUT CheckPosition only if wasn't done before. - if (!(mobj->eflags & MFE_ONGROUND) || mobj->momz + if (mobj->momz || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z + mobj->height != mobj->ceilingz) || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z != mobj->floorz) || P_IsObjectInGoop(mobj)) @@ -3795,17 +3795,6 @@ static void P_PlayerMobjThinker(mobj_t *mobj) } else { -#if 0 // i don't know why this is here, it's causing a few undesired state glitches, and disabling it doesn't appear to negatively affect the game, but i don't want it gone permanently just in case some obscure bug crops up - if (!(mobj->player->powers[pw_carry] == CR_NIGHTSMODE)) // used for drilling - mobj->player->pflags &= ~PF_STARTJUMP; - mobj->player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); - if (mobj->player->secondjump || mobj->player->powers[pw_tailsfly]) - { - mobj->player->secondjump = 0; - mobj->player->powers[pw_tailsfly] = 0; - P_SetMobjState(mobj, S_PLAY_WALK); - } -#endif mobj->eflags &= ~MFE_JUSTHITFLOOR; } @@ -4265,7 +4254,7 @@ static void P_Boss3Thinker(mobj_t *mobj) // this can happen if the boss was hurt earlier than expected for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -5354,7 +5343,7 @@ static void P_Boss9Thinker(mobj_t *mobj) // Build a hoop linked list of 'em! for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -6056,7 +6045,7 @@ mobj_t *P_GetClosestAxis(mobj_t *source) // scan the thinkers to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -9348,10 +9337,10 @@ static void P_PointPushThink(mobj_t *mobj) radius = mobj->spawnpoint->args[0] << FRACBITS; pushmobj = mobj; - xl = (unsigned)(mobj->x - radius - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; - xh = (unsigned)(mobj->x + radius - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; - yl = (unsigned)(mobj->y - radius - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; - yh = (unsigned)(mobj->y + radius - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + xl = (unsigned)(mobj->x - radius - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(mobj->x + radius - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(mobj->y - radius - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(mobj->y + radius - bmaporgy)>>MAPBLOCKSHIFT; P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushThing); } @@ -10355,6 +10344,7 @@ void P_MobjThinker(mobj_t *mobj) case MT_GRENADEPICKUP: if (mobj->health == 0) // Fading tile { + // TODO: Maybe use mobj->alpha instead of messing with frame flags INT32 value = mobj->info->damage/10; value = mobj->fuse/value; value = 10-value; @@ -10700,6 +10690,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) // Sprite rendering mobj->blendmode = AST_TRANSLUCENT; + mobj->alpha = FRACUNIT; mobj->spritexscale = mobj->spriteyscale = mobj->scale; mobj->spritexoffset = mobj->spriteyoffset = 0; mobj->floorspriteslope = NULL; @@ -10744,7 +10735,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) // Set shadowscale here, before spawn hook so that Lua can change it mobj->shadowscale = P_DefaultMobjShadowScale(mobj); - + // A monitor can't respawn if we're not in multiplayer, // or if we're in co-op and it's score or a 1up if (mobj->flags & MF_MONITOR && (!(netgame || multiplayer) @@ -11192,17 +11183,16 @@ tic_t itemrespawntime[ITEMQUESIZE]; size_t iquehead, iquetail; #ifdef PARANOIA -#define SCRAMBLE_REMOVED // Force debug build to crash when Removed mobj is accessed +#define SCRAMBLE_REMOVED // Force debug build to crash when a removed mobj is accessed #endif void P_RemoveMobj(mobj_t *mobj) { I_Assert(mobj != NULL); - if (P_MobjWasRemoved(mobj)) - return; // something already removing this mobj. + if (P_MobjWasRemoved(mobj) || mobj->thinker.removing) + return; // Something already removed or is removing this mobj. - mobj->thinker.function.acp1 = (actionf_p1)P_RemoveThinkerDelayed; // shh. no recursing. + mobj->thinker.removing = true; // Set earlier to avoid recursion. LUA_HookMobj(mobj, MOBJ_HOOK(MobjRemoved)); - mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; // needed for P_UnsetThingPosition, etc. to work. // Rings only, please! if (mobj->spawnpoint && @@ -12872,7 +12862,7 @@ static boolean P_MapAlreadyHasStarPost(mobj_t *mobj) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; diff --git a/src/p_mobj.h b/src/p_mobj.h index 2f013a2f3..4a8427669 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -313,6 +313,7 @@ typedef struct mobj_s UINT32 renderflags; // render flags INT32 blendmode; // blend mode + fixed_t alpha; // alpha fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2; @@ -456,6 +457,7 @@ typedef struct precipmobj_s UINT32 renderflags; // render flags INT32 blendmode; // blend mode + fixed_t alpha; // alpha fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2; @@ -537,6 +539,8 @@ boolean P_SceneryZMovement(mobj_t *mo); void P_PlayerZMovement(mobj_t *mo); void P_EmeraldManager(void); +mobj_t *P_FindNewPosition(UINT32 oldposition); + extern INT32 modulothing; #define MAXHUNTEMERALDS 64 diff --git a/src/p_polyobj.c b/src/p_polyobj.c index e779956e8..3d1a38d36 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by James Haley -// Copyright (C) 2006-2023 by Sonic Team Junior. +// Copyright (C) 2006-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -878,15 +878,15 @@ static void Polyobj_carryThings(polyobj_t *po, fixed_t dx, fixed_t dy) { mobj_t *mo; blocknode_t *block; + blocknode_t *next = NULL; if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) continue; - block = blocklinks[y * bmapwidth + x]; - - for (; block; block = block->mnext) + for (block = blocklinks[y * bmapwidth + x]; block != NULL; block = next) { mo = block->mobj; + next = block->mnext; if (mo->lastlook == pomovecount) continue; @@ -927,11 +927,11 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line) if (!(po->flags & POF_SOLID)) return hitflags; - // adjust linedef bounding box to blockmap, extend by MAXRADIUS - linebox[BOXLEFT] = (unsigned)(line->bbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; - linebox[BOXRIGHT] = (unsigned)(line->bbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; - linebox[BOXBOTTOM] = (unsigned)(line->bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; - linebox[BOXTOP] = (unsigned)(line->bbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + // adjust linedef bounding box to blockmap + linebox[BOXLEFT] = (unsigned)(line->bbox[BOXLEFT] - bmaporgx) >> MAPBLOCKSHIFT; + linebox[BOXRIGHT] = (unsigned)(line->bbox[BOXRIGHT] - bmaporgx) >> MAPBLOCKSHIFT; + linebox[BOXBOTTOM] = (unsigned)(line->bbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT; + linebox[BOXTOP] = (unsigned)(line->bbox[BOXTOP] - bmaporgy) >> MAPBLOCKSHIFT; // check all mobj blockmap cells the line contacts for (y = linebox[BOXBOTTOM]; y <= linebox[BOXTOP]; ++y) @@ -942,9 +942,11 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line) { mobj_t *mo = NULL; blocknode_t *block = blocklinks[y * bmapwidth + x]; + blocknode_t *next = NULL; - for (; block; block = block->mnext) + for (; block != NULL; block = next) { + next = block->mnext; mo = block->mobj; // Don't scroll objects that aren't affected by gravity @@ -1115,15 +1117,15 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta, { mobj_t *mo; blocknode_t *block; + blocknode_t *next = NULL; if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) continue; - block = blocklinks[y * bmapwidth + x]; - - for (; block; block = block->mnext) + for (block = blocklinks[y * bmapwidth + x]; block != NULL; block = next) { mo = block->mobj; + next = block->mnext; if (mo->lastlook == pomovecount) continue; @@ -1316,7 +1318,7 @@ void Polyobj_InitLevel(void) // the mobj_t pointers on a queue for use below. for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo = (mobj_t *)th; diff --git a/src/p_pspr.h b/src/p_pspr.h index 6510190f1..5e1c1e05e 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_saveg.c b/src/p_saveg.c index 5e4d6d076..650622f59 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -35,9 +35,249 @@ #include "p_polyobj.h" #include "lua_script.h" #include "p_slopes.h" +#include "hu_stuff.h" savedata_t savedata; -UINT8 *save_p; + +#define ALLOC_SIZE(p, z) \ + if ((p)->pos + (z) > (p)->size) \ + { \ + while ((p)->pos + (z) > (p)->size) \ + (p)->size <<= 1; \ + (p)->buf = realloc((p)->buf, (p)->size); \ + } + +void P_WriteUINT8(save_t *p, UINT8 v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteSINT8(save_t *p, SINT8 v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteUINT16(save_t *p, UINT16 v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteINT16(save_t *p, INT16 v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteUINT32(save_t *p, UINT32 v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteINT32(save_t *p, INT32 v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteChar(save_t *p, char v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteFixed(save_t *p, fixed_t v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteAngle(save_t *p, angle_t v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteStringN(save_t *p, char const *s, size_t n) +{ + size_t i; + + for (i = 0; i < n && s[i] != '\0'; i++) + P_WriteChar(p, s[i]); + + if (i < n) + P_WriteChar(p, '\0'); +} + +void P_WriteStringL(save_t *p, char const *s, size_t n) +{ + size_t i; + + for (i = 0; i < n - 1 && s[i] != '\0'; i++) + P_WriteChar(p, s[i]); + + P_WriteChar(p, '\0'); +} + +void P_WriteString(save_t *p, char const *s) +{ + size_t i; + + for (i = 0; s[i] != '\0'; i++) + P_WriteChar(p, s[i]); + + P_WriteChar(p, '\0'); +} + +void P_WriteMem(save_t *p, void const *s, size_t n) +{ + ALLOC_SIZE(p, n); + memcpy(&p->buf[p->pos], s, n); + p->pos += n; +} + +void P_SkipStringN(save_t *p, size_t n) +{ + size_t i; + for (i = 0; p->pos < p->size && i < n && P_ReadChar(p) != '\0'; i++); +} + +void P_SkipStringL(save_t *p, size_t n) +{ + P_SkipStringN(p, n); +} + +void P_SkipString(save_t *p) +{ + P_SkipStringN(p, SIZE_MAX); +} + +UINT8 P_ReadUINT8(save_t *p) +{ + UINT8 v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +SINT8 P_ReadSINT8(save_t *p) +{ + SINT8 v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +UINT16 P_ReadUINT16(save_t *p) +{ + UINT16 v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +INT16 P_ReadINT16(save_t *p) +{ + INT16 v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +UINT32 P_ReadUINT32(save_t *p) +{ + UINT32 v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +INT32 P_ReadINT32(save_t *p) +{ + INT32 v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +char P_ReadChar(save_t *p) +{ + char v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +fixed_t P_ReadFixed(save_t *p) +{ + fixed_t v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +angle_t P_ReadAngle(save_t *p) +{ + angle_t v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +void P_ReadStringN(save_t *p, char *s, size_t n) +{ + size_t i; + for (i = 0; p->pos < p->size && i < n && (s[i] = P_ReadChar(p)) != '\0'; i++); + s[i] = '\0'; +} + +void P_ReadStringL(save_t *p, char *s, size_t n) +{ + P_ReadStringN(p, s, n - 1); +} + +void P_ReadString(save_t *p, char *s) +{ + P_ReadStringN(p, s, SIZE_MAX); +} + +void P_ReadMem(save_t *p, void *s, size_t n) +{ + if (p->pos + n > p->size) + return; + memcpy(s, &p->buf[p->pos], n); + p->pos += n; +} // Block UINT32s to attempt to ensure that the correct data is // being sent and received @@ -62,7 +302,7 @@ typedef enum DRONE = 0x80, } player_saveflags; -static inline void P_ArchivePlayer(void) +static inline void P_ArchivePlayer(save_t *save_p) { const player_t *player = &players[consoleplayer]; SINT8 pllives = player->lives; @@ -72,32 +312,32 @@ static inline void P_ArchivePlayer(void) #ifdef NEWSKINSAVES // Write a specific value into the old skininfo location. // If we read something other than this, it's an older save file that used skin numbers. - WRITEUINT16(save_p, NEWSKINSAVES); + P_WriteUINT16(save_p, NEWSKINSAVES); #endif // Write skin names, so that loading skins in different orders // doesn't change who the save file is for! - WRITESTRINGN(save_p, skins[player->skin]->name, SKINNAMESIZE); + P_WriteStringN(save_p, skins[player->skin]->name, SKINNAMESIZE); if (botskin != 0) { - WRITESTRINGN(save_p, skins[botskin-1]->name, SKINNAMESIZE); + P_WriteStringN(save_p, skins[botskin-1]->name, SKINNAMESIZE); } else { - WRITESTRINGN(save_p, "\0", SKINNAMESIZE); + P_WriteStringN(save_p, "\0", SKINNAMESIZE); } - WRITEUINT8(save_p, numgameovers); - WRITESINT8(save_p, pllives); - WRITEUINT32(save_p, player->score); - WRITEINT32(save_p, player->continues); + P_WriteUINT8(save_p, numgameovers); + P_WriteSINT8(save_p, pllives); + P_WriteUINT32(save_p, player->score); + P_WriteINT32(save_p, player->continues); } -static inline void P_UnArchivePlayer(void) +static inline void P_UnArchivePlayer(save_t *save_p) { #ifdef NEWSKINSAVES - INT16 backwardsCompat = READUINT16(save_p); + INT16 backwardsCompat = P_ReadUINT16(save_p); if (backwardsCompat != NEWSKINSAVES) { @@ -111,30 +351,30 @@ static inline void P_UnArchivePlayer(void) char ourSkinName[SKINNAMESIZE+1]; char botSkinName[SKINNAMESIZE+1]; - READSTRINGN(save_p, ourSkinName, SKINNAMESIZE); + P_ReadStringN(save_p, ourSkinName, SKINNAMESIZE); savedata.skin = R_SkinAvailable(ourSkinName); - READSTRINGN(save_p, botSkinName, SKINNAMESIZE); + P_ReadStringN(save_p, botSkinName, SKINNAMESIZE); savedata.botskin = R_SkinAvailable(botSkinName) + 1; } - savedata.numgameovers = READUINT8(save_p); - savedata.lives = READSINT8(save_p); - savedata.score = READUINT32(save_p); - savedata.continues = READINT32(save_p); + savedata.numgameovers = P_ReadUINT8(save_p); + savedata.lives = P_ReadSINT8(save_p); + savedata.score = P_ReadUINT32(save_p); + savedata.continues = P_ReadINT32(save_p); } -static void P_NetArchivePlayers(void) +static void P_NetArchivePlayers(save_t *save_p) { INT32 i, j; UINT16 flags; // size_t q; - WRITEUINT32(save_p, ARCHIVEBLOCK_PLAYERS); + P_WriteUINT32(save_p, ARCHIVEBLOCK_PLAYERS); for (i = 0; i < MAXPLAYERS; i++) { - WRITESINT8(save_p, (SINT8)adminplayers[i]); + P_WriteSINT8(save_p, (SINT8)adminplayers[i]); if (!playeringame[i]) continue; @@ -143,142 +383,142 @@ static void P_NetArchivePlayers(void) // no longer send ticcmds - WRITESTRINGN(save_p, player_names[i], MAXPLAYERNAME); - WRITEINT16(save_p, players[i].angleturn); - WRITEINT16(save_p, players[i].oldrelangleturn); - WRITEANGLE(save_p, players[i].aiming); - WRITEANGLE(save_p, players[i].drawangle); - WRITEANGLE(save_p, players[i].viewrollangle); - WRITEANGLE(save_p, players[i].awayviewaiming); - WRITEINT32(save_p, players[i].awayviewtics); - WRITEINT16(save_p, players[i].rings); - WRITEINT16(save_p, players[i].spheres); + P_WriteStringN(save_p, player_names[i], MAXPLAYERNAME); + P_WriteINT16(save_p, players[i].angleturn); + P_WriteINT16(save_p, players[i].oldrelangleturn); + P_WriteAngle(save_p, players[i].aiming); + P_WriteAngle(save_p, players[i].drawangle); + P_WriteAngle(save_p, players[i].viewrollangle); + P_WriteAngle(save_p, players[i].awayviewaiming); + P_WriteINT32(save_p, players[i].awayviewtics); + P_WriteINT16(save_p, players[i].rings); + P_WriteINT16(save_p, players[i].spheres); - WRITESINT8(save_p, players[i].pity); - WRITEINT32(save_p, players[i].currentweapon); - WRITEINT32(save_p, players[i].ringweapons); + P_WriteSINT8(save_p, players[i].pity); + P_WriteINT32(save_p, players[i].currentweapon); + P_WriteINT32(save_p, players[i].ringweapons); - WRITEUINT16(save_p, players[i].ammoremoval); - WRITEUINT32(save_p, players[i].ammoremovaltimer); - WRITEINT32(save_p, players[i].ammoremovaltimer); + P_WriteUINT16(save_p, players[i].ammoremoval); + P_WriteUINT32(save_p, players[i].ammoremovaltimer); + P_WriteINT32(save_p, players[i].ammoremovaltimer); for (j = 0; j < NUMPOWERS; j++) - WRITEUINT16(save_p, players[i].powers[j]); + P_WriteUINT16(save_p, players[i].powers[j]); - WRITEUINT8(save_p, players[i].playerstate); - WRITEUINT32(save_p, players[i].pflags); - WRITEUINT8(save_p, players[i].panim); - WRITEUINT8(save_p, players[i].stronganim); - WRITEUINT8(save_p, players[i].spectator); - WRITEUINT8(save_p, players[i].muted); + P_WriteUINT8(save_p, players[i].playerstate); + P_WriteUINT32(save_p, players[i].pflags); + P_WriteUINT8(save_p, players[i].panim); + P_WriteUINT8(save_p, players[i].stronganim); + P_WriteUINT8(save_p, players[i].spectator); + P_WriteUINT8(save_p, players[i].muted); - WRITEUINT16(save_p, players[i].flashpal); - WRITEUINT16(save_p, players[i].flashcount); + P_WriteUINT16(save_p, players[i].flashpal); + P_WriteUINT16(save_p, players[i].flashcount); - WRITEUINT16(save_p, players[i].skincolor); - WRITEINT32(save_p, players[i].skin); - WRITEUINT32(save_p, players[i].availabilities); - WRITEUINT32(save_p, players[i].score); - WRITEUINT32(save_p, players[i].recordscore); - WRITEFIXED(save_p, players[i].dashspeed); - WRITESINT8(save_p, players[i].lives); - WRITESINT8(save_p, players[i].continues); - WRITESINT8(save_p, players[i].xtralife); - WRITEUINT8(save_p, players[i].gotcontinue); - WRITEFIXED(save_p, players[i].speed); - WRITEUINT8(save_p, players[i].secondjump); - WRITEUINT8(save_p, players[i].fly1); - WRITEUINT8(save_p, players[i].scoreadd); - WRITEUINT32(save_p, players[i].glidetime); - WRITEUINT8(save_p, players[i].climbing); - WRITEINT32(save_p, players[i].deadtimer); - WRITEUINT32(save_p, players[i].exiting); - WRITEUINT8(save_p, players[i].homing); - WRITEUINT32(save_p, players[i].dashmode); - WRITEUINT32(save_p, players[i].skidtime); + P_WriteUINT16(save_p, players[i].skincolor); + P_WriteINT32(save_p, players[i].skin); + P_WriteUINT32(save_p, players[i].availabilities); + P_WriteUINT32(save_p, players[i].score); + P_WriteUINT32(save_p, players[i].recordscore); + P_WriteFixed(save_p, players[i].dashspeed); + P_WriteSINT8(save_p, players[i].lives); + P_WriteSINT8(save_p, players[i].continues); + P_WriteSINT8(save_p, players[i].xtralife); + P_WriteUINT8(save_p, players[i].gotcontinue); + P_WriteFixed(save_p, players[i].speed); + P_WriteUINT8(save_p, players[i].secondjump); + P_WriteUINT8(save_p, players[i].fly1); + P_WriteUINT8(save_p, players[i].scoreadd); + P_WriteUINT32(save_p, players[i].glidetime); + P_WriteUINT8(save_p, players[i].climbing); + P_WriteINT32(save_p, players[i].deadtimer); + P_WriteUINT32(save_p, players[i].exiting); + P_WriteUINT8(save_p, players[i].homing); + P_WriteUINT32(save_p, players[i].dashmode); + P_WriteUINT32(save_p, players[i].skidtime); ////////// // Bots // ////////// - WRITEUINT8(save_p, players[i].bot); - WRITEUINT8(save_p, players[i].botmem.lastForward); - WRITEUINT8(save_p, players[i].botmem.lastBlocked); - WRITEUINT8(save_p, players[i].botmem.catchup_tics); - WRITEUINT8(save_p, players[i].botmem.thinkstate); - WRITEUINT8(save_p, players[i].removing); + P_WriteUINT8(save_p, players[i].bot); + P_WriteUINT8(save_p, players[i].botmem.lastForward); + P_WriteUINT8(save_p, players[i].botmem.lastBlocked); + P_WriteUINT8(save_p, players[i].botmem.catchup_tics); + P_WriteUINT8(save_p, players[i].botmem.thinkstate); + P_WriteUINT8(save_p, players[i].removing); - WRITEUINT8(save_p, players[i].blocked); - WRITEUINT16(save_p, players[i].lastbuttons); + P_WriteUINT8(save_p, players[i].blocked); + P_WriteUINT16(save_p, players[i].lastbuttons); //////////////////////////// // Conveyor Belt Movement // //////////////////////////// - WRITEFIXED(save_p, players[i].cmomx); // Conveyor momx - WRITEFIXED(save_p, players[i].cmomy); // Conveyor momy - WRITEFIXED(save_p, players[i].rmomx); // "Real" momx (momx - cmomx) - WRITEFIXED(save_p, players[i].rmomy); // "Real" momy (momy - cmomy) + P_WriteFixed(save_p, players[i].cmomx); // Conveyor momx + P_WriteFixed(save_p, players[i].cmomy); // Conveyor momy + P_WriteFixed(save_p, players[i].rmomx); // "Real" momx (momx - cmomx) + P_WriteFixed(save_p, players[i].rmomy); // "Real" momy (momy - cmomy) ///////////////////// // Race Mode Stuff // ///////////////////// - WRITEINT16(save_p, players[i].numboxes); - WRITEINT16(save_p, players[i].totalring); - WRITEUINT32(save_p, players[i].realtime); - WRITEUINT8(save_p, players[i].laps); + P_WriteINT16(save_p, players[i].numboxes); + P_WriteINT16(save_p, players[i].totalring); + P_WriteUINT32(save_p, players[i].realtime); + P_WriteUINT8(save_p, players[i].laps); //////////////////// // CTF Mode Stuff // //////////////////// - WRITEINT32(save_p, players[i].ctfteam); - WRITEUINT16(save_p, players[i].gotflag); + P_WriteINT32(save_p, players[i].ctfteam); + P_WriteUINT16(save_p, players[i].gotflag); - WRITEINT32(save_p, players[i].weapondelay); - WRITEINT32(save_p, players[i].tossdelay); + P_WriteINT32(save_p, players[i].weapondelay); + P_WriteINT32(save_p, players[i].tossdelay); - WRITEUINT32(save_p, players[i].starposttime); - WRITEINT16(save_p, players[i].starpostx); - WRITEINT16(save_p, players[i].starposty); - WRITEINT16(save_p, players[i].starpostz); - WRITEINT32(save_p, players[i].starpostnum); - WRITEANGLE(save_p, players[i].starpostangle); - WRITEFIXED(save_p, players[i].starpostscale); + P_WriteUINT32(save_p, players[i].starposttime); + P_WriteINT16(save_p, players[i].starpostx); + P_WriteINT16(save_p, players[i].starposty); + P_WriteINT16(save_p, players[i].starpostz); + P_WriteINT32(save_p, players[i].starpostnum); + P_WriteAngle(save_p, players[i].starpostangle); + P_WriteFixed(save_p, players[i].starpostscale); - WRITEANGLE(save_p, players[i].angle_pos); - WRITEANGLE(save_p, players[i].old_angle_pos); + P_WriteAngle(save_p, players[i].angle_pos); + P_WriteAngle(save_p, players[i].old_angle_pos); - WRITEINT32(save_p, players[i].flyangle); - WRITEUINT32(save_p, players[i].drilltimer); - WRITEINT32(save_p, players[i].linkcount); - WRITEUINT32(save_p, players[i].linktimer); - WRITEINT32(save_p, players[i].anotherflyangle); - WRITEUINT32(save_p, players[i].nightstime); - WRITEUINT32(save_p, players[i].bumpertime); - WRITEINT32(save_p, players[i].drillmeter); - WRITEUINT8(save_p, players[i].drilldelay); - WRITEUINT8(save_p, players[i].bonustime); - WRITEFIXED(save_p, players[i].oldscale); - WRITEUINT8(save_p, players[i].mare); - WRITEUINT8(save_p, players[i].marelap); - WRITEUINT8(save_p, players[i].marebonuslap); - WRITEUINT32(save_p, players[i].marebegunat); - WRITEUINT32(save_p, players[i].lastmaretime); - WRITEUINT32(save_p, players[i].startedtime); - WRITEUINT32(save_p, players[i].finishedtime); - WRITEUINT32(save_p, players[i].lapbegunat); - WRITEUINT32(save_p, players[i].lapstartedtime); - WRITEINT16(save_p, players[i].finishedspheres); - WRITEINT16(save_p, players[i].finishedrings); - WRITEUINT32(save_p, players[i].marescore); - WRITEUINT32(save_p, players[i].lastmarescore); - WRITEUINT32(save_p, players[i].totalmarescore); - WRITEUINT8(save_p, players[i].lastmare); - WRITEUINT8(save_p, players[i].lastmarelap); - WRITEUINT8(save_p, players[i].lastmarebonuslap); - WRITEUINT8(save_p, players[i].totalmarelap); - WRITEUINT8(save_p, players[i].totalmarebonuslap); - WRITEINT32(save_p, players[i].maxlink); - WRITEUINT8(save_p, players[i].texttimer); - WRITEUINT8(save_p, players[i].textvar); + P_WriteINT32(save_p, players[i].flyangle); + P_WriteUINT32(save_p, players[i].drilltimer); + P_WriteINT32(save_p, players[i].linkcount); + P_WriteUINT32(save_p, players[i].linktimer); + P_WriteINT32(save_p, players[i].anotherflyangle); + P_WriteUINT32(save_p, players[i].nightstime); + P_WriteUINT32(save_p, players[i].bumpertime); + P_WriteINT32(save_p, players[i].drillmeter); + P_WriteUINT8(save_p, players[i].drilldelay); + P_WriteUINT8(save_p, players[i].bonustime); + P_WriteFixed(save_p, players[i].oldscale); + P_WriteUINT8(save_p, players[i].mare); + P_WriteUINT8(save_p, players[i].marelap); + P_WriteUINT8(save_p, players[i].marebonuslap); + P_WriteUINT32(save_p, players[i].marebegunat); + P_WriteUINT32(save_p, players[i].lastmaretime); + P_WriteUINT32(save_p, players[i].startedtime); + P_WriteUINT32(save_p, players[i].finishedtime); + P_WriteUINT32(save_p, players[i].lapbegunat); + P_WriteUINT32(save_p, players[i].lapstartedtime); + P_WriteINT16(save_p, players[i].finishedspheres); + P_WriteINT16(save_p, players[i].finishedrings); + P_WriteUINT32(save_p, players[i].marescore); + P_WriteUINT32(save_p, players[i].lastmarescore); + P_WriteUINT32(save_p, players[i].totalmarescore); + P_WriteUINT8(save_p, players[i].lastmare); + P_WriteUINT8(save_p, players[i].lastmarelap); + P_WriteUINT8(save_p, players[i].lastmarebonuslap); + P_WriteUINT8(save_p, players[i].totalmarelap); + P_WriteUINT8(save_p, players[i].totalmarebonuslap); + P_WriteINT32(save_p, players[i].maxlink); + P_WriteUINT8(save_p, players[i].texttimer); + P_WriteUINT8(save_p, players[i].textvar); if (players[i].capsule) flags |= CAPSULE; @@ -298,73 +538,73 @@ static void P_NetArchivePlayers(void) if (players[i].drone) flags |= DRONE; - WRITEINT16(save_p, players[i].lastsidehit); - WRITEINT16(save_p, players[i].lastlinehit); + P_WriteINT16(save_p, players[i].lastsidehit); + P_WriteINT16(save_p, players[i].lastlinehit); - WRITEUINT32(save_p, players[i].losstime); + P_WriteUINT32(save_p, players[i].losstime); - WRITEUINT8(save_p, players[i].timeshit); + P_WriteUINT8(save_p, players[i].timeshit); - WRITEINT32(save_p, players[i].onconveyor); + P_WriteINT32(save_p, players[i].onconveyor); - WRITEUINT32(save_p, players[i].jointime); - WRITEUINT32(save_p, players[i].quittime); + P_WriteUINT32(save_p, players[i].jointime); + P_WriteUINT32(save_p, players[i].quittime); - WRITEUINT16(save_p, flags); + P_WriteUINT16(save_p, flags); if (flags & CAPSULE) - WRITEUINT32(save_p, players[i].capsule->mobjnum); + P_WriteUINT32(save_p, players[i].capsule->mobjnum); if (flags & FIRSTAXIS) - WRITEUINT32(save_p, players[i].axis1->mobjnum); + P_WriteUINT32(save_p, players[i].axis1->mobjnum); if (flags & SECONDAXIS) - WRITEUINT32(save_p, players[i].axis2->mobjnum); + P_WriteUINT32(save_p, players[i].axis2->mobjnum); if (flags & AWAYVIEW) - WRITEUINT32(save_p, players[i].awayviewmobj->mobjnum); + P_WriteUINT32(save_p, players[i].awayviewmobj->mobjnum); if (flags & FOLLOW) - WRITEUINT32(save_p, players[i].followmobj->mobjnum); + P_WriteUINT32(save_p, players[i].followmobj->mobjnum); if (flags & DRONE) - WRITEUINT32(save_p, players[i].drone->mobjnum); + P_WriteUINT32(save_p, players[i].drone->mobjnum); - WRITEFIXED(save_p, players[i].camerascale); - WRITEFIXED(save_p, players[i].shieldscale); + P_WriteFixed(save_p, players[i].camerascale); + P_WriteFixed(save_p, players[i].shieldscale); - WRITEUINT8(save_p, players[i].charability); - WRITEUINT8(save_p, players[i].charability2); - WRITEUINT32(save_p, players[i].charflags); - WRITEUINT32(save_p, (UINT32)players[i].thokitem); - WRITEUINT32(save_p, (UINT32)players[i].spinitem); - WRITEUINT32(save_p, (UINT32)players[i].revitem); - WRITEUINT32(save_p, (UINT32)players[i].followitem); - WRITEFIXED(save_p, players[i].actionspd); - WRITEFIXED(save_p, players[i].mindash); - WRITEFIXED(save_p, players[i].maxdash); - WRITEFIXED(save_p, players[i].normalspeed); - WRITEFIXED(save_p, players[i].runspeed); - WRITEUINT8(save_p, players[i].thrustfactor); - WRITEUINT8(save_p, players[i].accelstart); - WRITEUINT8(save_p, players[i].acceleration); - WRITEFIXED(save_p, players[i].jumpfactor); - WRITEFIXED(save_p, players[i].height); - WRITEFIXED(save_p, players[i].spinheight); + P_WriteUINT8(save_p, players[i].charability); + P_WriteUINT8(save_p, players[i].charability2); + P_WriteUINT32(save_p, players[i].charflags); + P_WriteUINT32(save_p, (UINT32)players[i].thokitem); + P_WriteUINT32(save_p, (UINT32)players[i].spinitem); + P_WriteUINT32(save_p, (UINT32)players[i].revitem); + P_WriteUINT32(save_p, (UINT32)players[i].followitem); + P_WriteFixed(save_p, players[i].actionspd); + P_WriteFixed(save_p, players[i].mindash); + P_WriteFixed(save_p, players[i].maxdash); + P_WriteFixed(save_p, players[i].normalspeed); + P_WriteFixed(save_p, players[i].runspeed); + P_WriteUINT8(save_p, players[i].thrustfactor); + P_WriteUINT8(save_p, players[i].accelstart); + P_WriteUINT8(save_p, players[i].acceleration); + P_WriteFixed(save_p, players[i].jumpfactor); + P_WriteFixed(save_p, players[i].height); + P_WriteFixed(save_p, players[i].spinheight); } } -static void P_NetUnArchivePlayers(void) +static void P_NetUnArchivePlayers(save_t *save_p) { INT32 i, j; UINT16 flags; - if (READUINT32(save_p) != ARCHIVEBLOCK_PLAYERS) + if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_PLAYERS) I_Error("Bad $$$.sav at archive block Players"); for (i = 0; i < MAXPLAYERS; i++) { - adminplayers[i] = (INT32)READSINT8(save_p); + adminplayers[i] = (INT32)P_ReadSINT8(save_p); // Do NOT memset player struct to 0 // other areas may initialize data elsewhere @@ -374,198 +614,198 @@ static void P_NetUnArchivePlayers(void) // NOTE: sending tics should (hopefully) no longer be necessary - READSTRINGN(save_p, player_names[i], MAXPLAYERNAME); - players[i].angleturn = READINT16(save_p); - players[i].oldrelangleturn = READINT16(save_p); - players[i].aiming = READANGLE(save_p); - players[i].drawangle = READANGLE(save_p); - players[i].viewrollangle = READANGLE(save_p); - players[i].awayviewaiming = READANGLE(save_p); - players[i].awayviewtics = READINT32(save_p); - players[i].rings = READINT16(save_p); - players[i].spheres = READINT16(save_p); + P_ReadStringN(save_p, player_names[i], MAXPLAYERNAME); + players[i].angleturn = P_ReadINT16(save_p); + players[i].oldrelangleturn = P_ReadINT16(save_p); + players[i].aiming = P_ReadAngle(save_p); + players[i].drawangle = P_ReadAngle(save_p); + players[i].viewrollangle = P_ReadAngle(save_p); + players[i].awayviewaiming = P_ReadAngle(save_p); + players[i].awayviewtics = P_ReadINT32(save_p); + players[i].rings = P_ReadINT16(save_p); + players[i].spheres = P_ReadINT16(save_p); - players[i].pity = READSINT8(save_p); - players[i].currentweapon = READINT32(save_p); - players[i].ringweapons = READINT32(save_p); + players[i].pity = P_ReadSINT8(save_p); + players[i].currentweapon = P_ReadINT32(save_p); + players[i].ringweapons = P_ReadINT32(save_p); - players[i].ammoremoval = READUINT16(save_p); - players[i].ammoremovaltimer = READUINT32(save_p); - players[i].ammoremovalweapon = READINT32(save_p); + players[i].ammoremoval = P_ReadUINT16(save_p); + players[i].ammoremovaltimer = P_ReadUINT32(save_p); + players[i].ammoremovalweapon = P_ReadINT32(save_p); for (j = 0; j < NUMPOWERS; j++) - players[i].powers[j] = READUINT16(save_p); + players[i].powers[j] = P_ReadUINT16(save_p); - players[i].playerstate = READUINT8(save_p); - players[i].pflags = READUINT32(save_p); - players[i].panim = READUINT8(save_p); - players[i].stronganim = READUINT8(save_p); - players[i].spectator = READUINT8(save_p); - players[i].muted = READUINT8(save_p); + players[i].playerstate = P_ReadUINT8(save_p); + players[i].pflags = P_ReadUINT32(save_p); + players[i].panim = P_ReadUINT8(save_p); + players[i].stronganim = P_ReadUINT8(save_p); + players[i].spectator = P_ReadUINT8(save_p); + players[i].muted = P_ReadUINT8(save_p); - players[i].flashpal = READUINT16(save_p); - players[i].flashcount = READUINT16(save_p); + players[i].flashpal = P_ReadUINT16(save_p); + players[i].flashcount = P_ReadUINT16(save_p); - players[i].skincolor = READUINT16(save_p); - players[i].skin = READINT32(save_p); - players[i].availabilities = READUINT32(save_p); - players[i].score = READUINT32(save_p); - players[i].recordscore = READUINT32(save_p); - players[i].dashspeed = READFIXED(save_p); // dashing speed - players[i].lives = READSINT8(save_p); - players[i].continues = READSINT8(save_p); // continues that player has acquired - players[i].xtralife = READSINT8(save_p); // Ring Extra Life counter - players[i].gotcontinue = READUINT8(save_p); // got continue from stage - players[i].speed = READFIXED(save_p); // Player's speed (distance formula of MOMX and MOMY values) - players[i].secondjump = READUINT8(save_p); - players[i].fly1 = READUINT8(save_p); // Tails flying - players[i].scoreadd = READUINT8(save_p); // Used for multiple enemy attack bonus - players[i].glidetime = READUINT32(save_p); // Glide counter for thrust - players[i].climbing = READUINT8(save_p); // Climbing on the wall - players[i].deadtimer = READINT32(save_p); // End game if game over lasts too long - players[i].exiting = READUINT32(save_p); // Exitlevel timer - players[i].homing = READUINT8(save_p); // Are you homing? - players[i].dashmode = READUINT32(save_p); // counter for dashmode ability - players[i].skidtime = READUINT32(save_p); // Skid timer + players[i].skincolor = P_ReadUINT16(save_p); + players[i].skin = P_ReadINT32(save_p); + players[i].availabilities = P_ReadUINT32(save_p); + players[i].score = P_ReadUINT32(save_p); + players[i].recordscore = P_ReadUINT32(save_p); + players[i].dashspeed = P_ReadFixed(save_p); // dashing speed + players[i].lives = P_ReadSINT8(save_p); + players[i].continues = P_ReadSINT8(save_p); // continues that player has acquired + players[i].xtralife = P_ReadSINT8(save_p); // Ring Extra Life counter + players[i].gotcontinue = P_ReadUINT8(save_p); // got continue from stage + players[i].speed = P_ReadFixed(save_p); // Player's speed (distance formula of MOMX and MOMY values) + players[i].secondjump = P_ReadUINT8(save_p); + players[i].fly1 = P_ReadUINT8(save_p); // Tails flying + players[i].scoreadd = P_ReadUINT8(save_p); // Used for multiple enemy attack bonus + players[i].glidetime = P_ReadUINT32(save_p); // Glide counter for thrust + players[i].climbing = P_ReadUINT8(save_p); // Climbing on the wall + players[i].deadtimer = P_ReadINT32(save_p); // End game if game over lasts too long + players[i].exiting = P_ReadUINT32(save_p); // Exitlevel timer + players[i].homing = P_ReadUINT8(save_p); // Are you homing? + players[i].dashmode = P_ReadUINT32(save_p); // counter for dashmode ability + players[i].skidtime = P_ReadUINT32(save_p); // Skid timer ////////// // Bots // ////////// - players[i].bot = READUINT8(save_p); + players[i].bot = P_ReadUINT8(save_p); - players[i].botmem.lastForward = READUINT8(save_p); - players[i].botmem.lastBlocked = READUINT8(save_p); - players[i].botmem.catchup_tics = READUINT8(save_p); - players[i].botmem.thinkstate = READUINT8(save_p); - players[i].removing = READUINT8(save_p); + players[i].botmem.lastForward = P_ReadUINT8(save_p); + players[i].botmem.lastBlocked = P_ReadUINT8(save_p); + players[i].botmem.catchup_tics = P_ReadUINT8(save_p); + players[i].botmem.thinkstate = P_ReadUINT8(save_p); + players[i].removing = P_ReadUINT8(save_p); - players[i].blocked = READUINT8(save_p); - players[i].lastbuttons = READUINT16(save_p); + players[i].blocked = P_ReadUINT8(save_p); + players[i].lastbuttons = P_ReadUINT16(save_p); //////////////////////////// // Conveyor Belt Movement // //////////////////////////// - players[i].cmomx = READFIXED(save_p); // Conveyor momx - players[i].cmomy = READFIXED(save_p); // Conveyor momy - players[i].rmomx = READFIXED(save_p); // "Real" momx (momx - cmomx) - players[i].rmomy = READFIXED(save_p); // "Real" momy (momy - cmomy) + players[i].cmomx = P_ReadFixed(save_p); // Conveyor momx + players[i].cmomy = P_ReadFixed(save_p); // Conveyor momy + players[i].rmomx = P_ReadFixed(save_p); // "Real" momx (momx - cmomx) + players[i].rmomy = P_ReadFixed(save_p); // "Real" momy (momy - cmomy) ///////////////////// // Race Mode Stuff // ///////////////////// - players[i].numboxes = READINT16(save_p); // Number of item boxes obtained for Race Mode - players[i].totalring = READINT16(save_p); // Total number of rings obtained for Race Mode - players[i].realtime = READUINT32(save_p); // integer replacement for leveltime - players[i].laps = READUINT8(save_p); // Number of laps (optional) + players[i].numboxes = P_ReadINT16(save_p); // Number of item boxes obtained for Race Mode + players[i].totalring = P_ReadINT16(save_p); // Total number of rings obtained for Race Mode + players[i].realtime = P_ReadUINT32(save_p); // integer replacement for leveltime + players[i].laps = P_ReadUINT8(save_p); // Number of laps (optional) //////////////////// // CTF Mode Stuff // //////////////////// - players[i].ctfteam = READINT32(save_p); // 1 == Red, 2 == Blue - players[i].gotflag = READUINT16(save_p); // 1 == Red, 2 == Blue Do you have the flag? + players[i].ctfteam = P_ReadINT32(save_p); // 1 == Red, 2 == Blue + players[i].gotflag = P_ReadUINT16(save_p); // 1 == Red, 2 == Blue Do you have the flag? - players[i].weapondelay = READINT32(save_p); - players[i].tossdelay = READINT32(save_p); + players[i].weapondelay = P_ReadINT32(save_p); + players[i].tossdelay = P_ReadINT32(save_p); - players[i].starposttime = READUINT32(save_p); - players[i].starpostx = READINT16(save_p); - players[i].starposty = READINT16(save_p); - players[i].starpostz = READINT16(save_p); - players[i].starpostnum = READINT32(save_p); - players[i].starpostangle = READANGLE(save_p); - players[i].starpostscale = READFIXED(save_p); + players[i].starposttime = P_ReadUINT32(save_p); + players[i].starpostx = P_ReadINT16(save_p); + players[i].starposty = P_ReadINT16(save_p); + players[i].starpostz = P_ReadINT16(save_p); + players[i].starpostnum = P_ReadINT32(save_p); + players[i].starpostangle = P_ReadAngle(save_p); + players[i].starpostscale = P_ReadFixed(save_p); - players[i].angle_pos = READANGLE(save_p); - players[i].old_angle_pos = READANGLE(save_p); + players[i].angle_pos = P_ReadAngle(save_p); + players[i].old_angle_pos = P_ReadAngle(save_p); - players[i].flyangle = READINT32(save_p); - players[i].drilltimer = READUINT32(save_p); - players[i].linkcount = READINT32(save_p); - players[i].linktimer = READUINT32(save_p); - players[i].anotherflyangle = READINT32(save_p); - players[i].nightstime = READUINT32(save_p); - players[i].bumpertime = READUINT32(save_p); - players[i].drillmeter = READINT32(save_p); - players[i].drilldelay = READUINT8(save_p); - players[i].bonustime = (boolean)READUINT8(save_p); - players[i].oldscale = READFIXED(save_p); - players[i].mare = READUINT8(save_p); - players[i].marelap = READUINT8(save_p); - players[i].marebonuslap = READUINT8(save_p); - players[i].marebegunat = READUINT32(save_p); - players[i].lastmaretime = READUINT32(save_p); - players[i].startedtime = READUINT32(save_p); - players[i].finishedtime = READUINT32(save_p); - players[i].lapbegunat = READUINT32(save_p); - players[i].lapstartedtime = READUINT32(save_p); - players[i].finishedspheres = READINT16(save_p); - players[i].finishedrings = READINT16(save_p); - players[i].marescore = READUINT32(save_p); - players[i].lastmarescore = READUINT32(save_p); - players[i].totalmarescore = READUINT32(save_p); - players[i].lastmare = READUINT8(save_p); - players[i].lastmarelap = READUINT8(save_p); - players[i].lastmarebonuslap = READUINT8(save_p); - players[i].totalmarelap = READUINT8(save_p); - players[i].totalmarebonuslap = READUINT8(save_p); - players[i].maxlink = READINT32(save_p); - players[i].texttimer = READUINT8(save_p); - players[i].textvar = READUINT8(save_p); + players[i].flyangle = P_ReadINT32(save_p); + players[i].drilltimer = P_ReadUINT32(save_p); + players[i].linkcount = P_ReadINT32(save_p); + players[i].linktimer = P_ReadUINT32(save_p); + players[i].anotherflyangle = P_ReadINT32(save_p); + players[i].nightstime = P_ReadUINT32(save_p); + players[i].bumpertime = P_ReadUINT32(save_p); + players[i].drillmeter = P_ReadINT32(save_p); + players[i].drilldelay = P_ReadUINT8(save_p); + players[i].bonustime = (boolean)P_ReadUINT8(save_p); + players[i].oldscale = P_ReadFixed(save_p); + players[i].mare = P_ReadUINT8(save_p); + players[i].marelap = P_ReadUINT8(save_p); + players[i].marebonuslap = P_ReadUINT8(save_p); + players[i].marebegunat = P_ReadUINT32(save_p); + players[i].lastmaretime = P_ReadUINT32(save_p); + players[i].startedtime = P_ReadUINT32(save_p); + players[i].finishedtime = P_ReadUINT32(save_p); + players[i].lapbegunat = P_ReadUINT32(save_p); + players[i].lapstartedtime = P_ReadUINT32(save_p); + players[i].finishedspheres = P_ReadINT16(save_p); + players[i].finishedrings = P_ReadINT16(save_p); + players[i].marescore = P_ReadUINT32(save_p); + players[i].lastmarescore = P_ReadUINT32(save_p); + players[i].totalmarescore = P_ReadUINT32(save_p); + players[i].lastmare = P_ReadUINT8(save_p); + players[i].lastmarelap = P_ReadUINT8(save_p); + players[i].lastmarebonuslap = P_ReadUINT8(save_p); + players[i].totalmarelap = P_ReadUINT8(save_p); + players[i].totalmarebonuslap = P_ReadUINT8(save_p); + players[i].maxlink = P_ReadINT32(save_p); + players[i].texttimer = P_ReadUINT8(save_p); + players[i].textvar = P_ReadUINT8(save_p); - players[i].lastsidehit = READINT16(save_p); - players[i].lastlinehit = READINT16(save_p); + players[i].lastsidehit = P_ReadINT16(save_p); + players[i].lastlinehit = P_ReadINT16(save_p); - players[i].losstime = READUINT32(save_p); + players[i].losstime = P_ReadUINT32(save_p); - players[i].timeshit = READUINT8(save_p); + players[i].timeshit = P_ReadUINT8(save_p); - players[i].onconveyor = READINT32(save_p); + players[i].onconveyor = P_ReadINT32(save_p); - players[i].jointime = READUINT32(save_p); - players[i].quittime = READUINT32(save_p); + players[i].jointime = P_ReadUINT32(save_p); + players[i].quittime = P_ReadUINT32(save_p); - flags = READUINT16(save_p); + flags = P_ReadUINT16(save_p); if (flags & CAPSULE) - players[i].capsule = (mobj_t *)(size_t)READUINT32(save_p); + players[i].capsule = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (flags & FIRSTAXIS) - players[i].axis1 = (mobj_t *)(size_t)READUINT32(save_p); + players[i].axis1 = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (flags & SECONDAXIS) - players[i].axis2 = (mobj_t *)(size_t)READUINT32(save_p); + players[i].axis2 = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (flags & AWAYVIEW) - players[i].awayviewmobj = (mobj_t *)(size_t)READUINT32(save_p); + players[i].awayviewmobj = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (flags & FOLLOW) - players[i].followmobj = (mobj_t *)(size_t)READUINT32(save_p); + players[i].followmobj = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (flags & DRONE) - players[i].drone = (mobj_t *)(size_t)READUINT32(save_p); + players[i].drone = (mobj_t *)(size_t)P_ReadUINT32(save_p); - players[i].camerascale = READFIXED(save_p); - players[i].shieldscale = READFIXED(save_p); + players[i].camerascale = P_ReadFixed(save_p); + players[i].shieldscale = P_ReadFixed(save_p); //SetPlayerSkinByNum(i, players[i].skin); - players[i].charability = READUINT8(save_p); - players[i].charability2 = READUINT8(save_p); - players[i].charflags = READUINT32(save_p); - players[i].thokitem = (mobjtype_t)READUINT32(save_p); - players[i].spinitem = (mobjtype_t)READUINT32(save_p); - players[i].revitem = (mobjtype_t)READUINT32(save_p); - players[i].followitem = (mobjtype_t)READUINT32(save_p); - players[i].actionspd = READFIXED(save_p); - players[i].mindash = READFIXED(save_p); - players[i].maxdash = READFIXED(save_p); - players[i].normalspeed = READFIXED(save_p); - players[i].runspeed = READFIXED(save_p); - players[i].thrustfactor = READUINT8(save_p); - players[i].accelstart = READUINT8(save_p); - players[i].acceleration = READUINT8(save_p); - players[i].jumpfactor = READFIXED(save_p); - players[i].height = READFIXED(save_p); - players[i].spinheight = READFIXED(save_p); + players[i].charability = P_ReadUINT8(save_p); + players[i].charability2 = P_ReadUINT8(save_p); + players[i].charflags = P_ReadUINT32(save_p); + players[i].thokitem = P_ReadUINT32(save_p); + players[i].spinitem = P_ReadUINT32(save_p); + players[i].revitem = P_ReadUINT32(save_p); + players[i].followitem = P_ReadUINT32(save_p); + players[i].actionspd = P_ReadFixed(save_p); + players[i].mindash = P_ReadFixed(save_p); + players[i].maxdash = P_ReadFixed(save_p); + players[i].normalspeed = P_ReadFixed(save_p); + players[i].runspeed = P_ReadFixed(save_p); + players[i].thrustfactor = P_ReadUINT8(save_p); + players[i].accelstart = P_ReadUINT8(save_p); + players[i].acceleration = P_ReadUINT8(save_p); + players[i].jumpfactor = P_ReadFixed(save_p); + players[i].height = P_ReadFixed(save_p); + players[i].spinheight = P_ReadFixed(save_p); players[i].viewheight = 41*players[i].height/48; // scale cannot be factored in at this point } @@ -668,12 +908,12 @@ static void ClearNetColormaps(void) net_colormaps = NULL; } -static void P_NetArchiveColormaps(void) +static void P_NetArchiveColormaps(save_t *save_p) { // We save and then we clean up our colormap mess extracolormap_t *exc, *exc_next; UINT32 i = 0; - WRITEUINT32(save_p, num_net_colormaps); // save for safety + P_WriteUINT32(save_p, num_net_colormaps); // save for safety for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next) { @@ -682,15 +922,15 @@ static void P_NetArchiveColormaps(void) if (!exc) exc = R_CreateDefaultColormap(false); - WRITEUINT8(save_p, exc->fadestart); - WRITEUINT8(save_p, exc->fadeend); - WRITEUINT8(save_p, exc->flags); + P_WriteUINT8(save_p, exc->fadestart); + P_WriteUINT8(save_p, exc->fadeend); + P_WriteUINT8(save_p, exc->flags); - WRITEINT32(save_p, exc->rgba); - WRITEINT32(save_p, exc->fadergba); + P_WriteINT32(save_p, exc->rgba); + P_WriteINT32(save_p, exc->fadergba); #ifdef EXTRACOLORMAPLUMPS - WRITESTRINGN(save_p, exc->lumpname, 9); + P_WriteStringN(save_p, exc->lumpname, 9); #endif exc_next = exc->next; @@ -702,7 +942,7 @@ static void P_NetArchiveColormaps(void) net_colormaps = NULL; } -static void P_NetUnArchiveColormaps(void) +static void P_NetUnArchiveColormaps(save_t *save_p) { // When we reach this point, we already populated our list with // dummy colormaps. Now that we are loading the color data, @@ -710,7 +950,7 @@ static void P_NetUnArchiveColormaps(void) extracolormap_t *exc, *existing_exc, *exc_next = NULL; UINT32 i = 0; - num_net_colormaps = READUINT32(save_p); + num_net_colormaps = P_ReadUINT32(save_p); for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next) { @@ -720,15 +960,15 @@ static void P_NetUnArchiveColormaps(void) char lumpname[9]; #endif - fadestart = READUINT8(save_p); - fadeend = READUINT8(save_p); - flags = READUINT8(save_p); + fadestart = P_ReadUINT8(save_p); + fadeend = P_ReadUINT8(save_p); + flags = P_ReadUINT8(save_p); - rgba = READINT32(save_p); - fadergba = READINT32(save_p); + rgba = P_ReadINT32(save_p); + fadergba = P_ReadINT32(save_p); #ifdef EXTRACOLORMAPLUMPS - READSTRINGN(save_p, lumpname, 9); + P_ReadStringN(save_p, lumpname, 9); if (lumpname[0]) { @@ -804,29 +1044,29 @@ static void P_NetUnArchiveColormaps(void) net_colormaps = NULL; } -static void P_NetArchiveWaypoints(void) +static void P_NetArchiveWaypoints(save_t *save_p) { INT32 i, j; for (i = 0; i < NUMWAYPOINTSEQUENCES; i++) { - WRITEUINT16(save_p, numwaypoints[i]); + P_WriteUINT16(save_p, numwaypoints[i]); for (j = 0; j < numwaypoints[i]; j++) - WRITEUINT32(save_p, waypoints[i][j] ? waypoints[i][j]->mobjnum : 0); + P_WriteUINT32(save_p, waypoints[i][j] ? waypoints[i][j]->mobjnum : 0); } } -static void P_NetUnArchiveWaypoints(void) +static void P_NetUnArchiveWaypoints(save_t *save_p) { INT32 i, j; UINT32 mobjnum; for (i = 0; i < NUMWAYPOINTSEQUENCES; i++) { - numwaypoints[i] = READUINT16(save_p); + numwaypoints[i] = P_ReadUINT16(save_p); for (j = 0; j < numwaypoints[i]; j++) { - mobjnum = READUINT32(save_p); + mobjnum = P_ReadUINT32(save_p); waypoints[i][j] = (mobjnum == 0) ? NULL : P_FindNewPosition(mobjnum); } } @@ -919,7 +1159,11 @@ enum LD_SDMIDLIGHT = 1<<19, LD_SDBOTLIGHT = 1<<20, LD_SDREPEATCNT = 1<<21, - LD_SDFLAGS = 1<<22 + LD_SDFLAGS = 1<<22, + LD_SDLIGHTABS = 1<<23, + LD_SDTOPLIGHTABS = 1<<24, + LD_SDMIDLIGHTABS = 1<<25, + LD_SDBOTLIGHTABS = 1<<26 }; static boolean P_AreArgsEqual(const line_t *li, const line_t *spawnli) @@ -969,7 +1213,7 @@ static boolean CheckFFloorDiff(const sector_t *ss) // Special case: save the stats of all modified ffloors along with their ffloor "number"s // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed -static void ArchiveFFloors(const sector_t *ss) +static void ArchiveFFloors(save_t *save_p, const sector_t *ss) { size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc ffloor_t *rover; @@ -984,19 +1228,19 @@ static void ArchiveFFloors(const sector_t *ss) if (fflr_diff) { - WRITEUINT16(save_p, j); // save ffloor "number" - WRITEUINT8(save_p, fflr_diff); + P_WriteUINT16(save_p, j); // save ffloor "number" + P_WriteUINT8(save_p, fflr_diff); if (fflr_diff & FD_FLAGS) - WRITEUINT32(save_p, rover->fofflags); + P_WriteUINT32(save_p, rover->fofflags); if (fflr_diff & FD_ALPHA) - WRITEINT16(save_p, rover->alpha); + P_WriteINT16(save_p, rover->alpha); } j++; } - WRITEUINT16(save_p, 0xffff); + P_WriteUINT16(save_p, 0xffff); } -static void UnArchiveFFloors(const sector_t *ss) +static void UnArchiveFFloors(save_t *save_p, const sector_t *ss) { UINT16 j = 0; // number of current ffloor in loop UINT16 fflr_i; // saved ffloor "number" of next modified ffloor @@ -1007,7 +1251,7 @@ static void UnArchiveFFloors(const sector_t *ss) if (!rover) // it is assumed sectors[i].ffloors actually exists, but just in case... I_Error("Sector does not have any ffloors!"); - fflr_i = READUINT16(save_p); // get first modified ffloor's number ready + fflr_i = P_ReadUINT16(save_p); // get first modified ffloor's number ready for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here? { if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already @@ -1022,21 +1266,21 @@ static void UnArchiveFFloors(const sector_t *ss) continue; } - fflr_diff = READUINT8(save_p); + fflr_diff = P_ReadUINT8(save_p); if (fflr_diff & FD_FLAGS) - rover->fofflags = READUINT32(save_p); + rover->fofflags = P_ReadUINT32(save_p); if (fflr_diff & FD_ALPHA) - rover->alpha = READINT16(save_p); + rover->alpha = P_ReadINT16(save_p); - fflr_i = READUINT16(save_p); // get next ffloor "number" ready + fflr_i = P_ReadUINT16(save_p); // get next ffloor "number" ready j++; rover = rover->next; } } -static void ArchiveSectors(void) +static void ArchiveSectors(save_t *save_p) { size_t i, j; const sector_t *ss = sectors; @@ -1130,102 +1374,102 @@ static void ArchiveSectors(void) if (diff) { - WRITEUINT32(save_p, i); - WRITEUINT8(save_p, diff); + P_WriteUINT32(save_p, i); + P_WriteUINT8(save_p, diff); if (diff & SD_DIFF2) - WRITEUINT8(save_p, diff2); + P_WriteUINT8(save_p, diff2); if (diff2 & SD_DIFF3) - WRITEUINT8(save_p, diff3); + P_WriteUINT8(save_p, diff3); if (diff3 & SD_DIFF4) - WRITEUINT8(save_p, diff4); + P_WriteUINT8(save_p, diff4); if (diff4 & SD_DIFF5) - WRITEUINT8(save_p, diff5); + P_WriteUINT8(save_p, diff5); if (diff & SD_FLOORHT) - WRITEFIXED(save_p, ss->floorheight); + P_WriteFixed(save_p, ss->floorheight); if (diff & SD_CEILHT) - WRITEFIXED(save_p, ss->ceilingheight); + P_WriteFixed(save_p, ss->ceilingheight); if (diff & SD_FLOORPIC) - WRITEMEM(save_p, levelflats[ss->floorpic].name, 8); + P_WriteMem(save_p, levelflats[ss->floorpic].name, 8); if (diff & SD_CEILPIC) - WRITEMEM(save_p, levelflats[ss->ceilingpic].name, 8); + P_WriteMem(save_p, levelflats[ss->ceilingpic].name, 8); if (diff & SD_LIGHT) - WRITEINT16(save_p, ss->lightlevel); + P_WriteINT16(save_p, ss->lightlevel); if (diff & SD_SPECIAL) - WRITEINT16(save_p, ss->special); + P_WriteINT16(save_p, ss->special); if (diff2 & SD_FXOFFS) - WRITEFIXED(save_p, ss->floorxoffset); + P_WriteFixed(save_p, ss->floorxoffset); if (diff2 & SD_FYOFFS) - WRITEFIXED(save_p, ss->flooryoffset); + P_WriteFixed(save_p, ss->flooryoffset); if (diff2 & SD_CXOFFS) - WRITEFIXED(save_p, ss->ceilingxoffset); + P_WriteFixed(save_p, ss->ceilingxoffset); if (diff2 & SD_CYOFFS) - WRITEFIXED(save_p, ss->ceilingyoffset); + P_WriteFixed(save_p, ss->ceilingyoffset); if (diff2 & SD_FLOORANG) - WRITEANGLE(save_p, ss->floorangle); + P_WriteAngle(save_p, ss->floorangle); if (diff2 & SD_CEILANG) - WRITEANGLE(save_p, ss->ceilingangle); + P_WriteAngle(save_p, ss->ceilingangle); if (diff2 & SD_TAG) { - WRITEUINT32(save_p, ss->tags.count); + P_WriteUINT32(save_p, ss->tags.count); for (j = 0; j < ss->tags.count; j++) - WRITEINT16(save_p, ss->tags.tags[j]); + P_WriteINT16(save_p, ss->tags.tags[j]); } if (diff3 & SD_COLORMAP) - WRITEUINT32(save_p, CheckAddNetColormapToList(ss->extra_colormap)); + P_WriteUINT32(save_p, CheckAddNetColormapToList(ss->extra_colormap)); // returns existing index if already added, or appends to net_colormaps and returns new index if (diff3 & SD_CRUMBLESTATE) - WRITEINT32(save_p, ss->crumblestate); + P_WriteINT32(save_p, ss->crumblestate); if (diff3 & SD_FLOORLIGHT) { - WRITEINT16(save_p, ss->floorlightlevel); - WRITEUINT8(save_p, ss->floorlightabsolute); + P_WriteINT16(save_p, ss->floorlightlevel); + P_WriteUINT8(save_p, ss->floorlightabsolute); } if (diff3 & SD_CEILLIGHT) { - WRITEINT16(save_p, ss->ceilinglightlevel); - WRITEUINT8(save_p, ss->ceilinglightabsolute); + P_WriteINT16(save_p, ss->ceilinglightlevel); + P_WriteUINT8(save_p, ss->ceilinglightabsolute); } if (diff3 & SD_FLAG) - WRITEUINT32(save_p, ss->flags); + P_WriteUINT32(save_p, ss->flags); if (diff3 & SD_SPECIALFLAG) - WRITEUINT32(save_p, ss->specialflags); + P_WriteUINT32(save_p, ss->specialflags); if (diff4 & SD_DAMAGETYPE) - WRITEUINT8(save_p, ss->damagetype); + P_WriteUINT8(save_p, ss->damagetype); if (diff4 & SD_TRIGGERTAG) - WRITEINT16(save_p, ss->triggertag); + P_WriteINT16(save_p, ss->triggertag); if (diff4 & SD_TRIGGERER) - WRITEUINT8(save_p, ss->triggerer); + P_WriteUINT8(save_p, ss->triggerer); if (diff4 & SD_FXSCALE) - WRITEFIXED(save_p, ss->floorxscale); + P_WriteFixed(save_p, ss->floorxscale); if (diff4 & SD_FYSCALE) - WRITEFIXED(save_p, ss->flooryscale); + P_WriteFixed(save_p, ss->flooryscale); if (diff4 & SD_CXSCALE) - WRITEFIXED(save_p, ss->ceilingxscale); + P_WriteFixed(save_p, ss->ceilingxscale); if (diff4 & SD_CYSCALE) - WRITEFIXED(save_p, ss->ceilingyscale); + P_WriteFixed(save_p, ss->ceilingyscale); if (diff5 & SD_GRAVITY) - WRITEFIXED(save_p, ss->gravity); + P_WriteFixed(save_p, ss->gravity); if (diff5 & SD_FLOORPORTAL) - WRITEUINT32(save_p, ss->portal_floor); + P_WriteUINT32(save_p, ss->portal_floor); if (diff5 & SD_CEILPORTAL) - WRITEUINT32(save_p, ss->portal_ceiling); + P_WriteUINT32(save_p, ss->portal_ceiling); if (diff & SD_FFLOORS) - ArchiveFFloors(ss); + ArchiveFFloors(save_p, ss); } } - WRITEUINT32(save_p, 0xffffffff); + P_WriteUINT32(save_p, 0xffffffff); } -static void UnArchiveSectors(void) +static void UnArchiveSectors(save_t *save_p) { UINT32 i; UINT16 j; UINT8 diff, diff2, diff3, diff4, diff5; for (;;) { - i = READUINT32(save_p); + i = P_ReadUINT32(save_p); if (i == 0xffffffff) break; @@ -1233,58 +1477,58 @@ static void UnArchiveSectors(void) if (i > numsectors) I_Error("Invalid sector number %u from server (expected end at %s)", i, sizeu1(numsectors)); - diff = READUINT8(save_p); + diff = P_ReadUINT8(save_p); if (diff & SD_DIFF2) - diff2 = READUINT8(save_p); + diff2 = P_ReadUINT8(save_p); else diff2 = 0; if (diff2 & SD_DIFF3) - diff3 = READUINT8(save_p); + diff3 = P_ReadUINT8(save_p); else diff3 = 0; if (diff3 & SD_DIFF4) - diff4 = READUINT8(save_p); + diff4 = P_ReadUINT8(save_p); else diff4 = 0; if (diff4 & SD_DIFF5) - diff5 = READUINT8(save_p); + diff5 = P_ReadUINT8(save_p); else diff5 = 0; if (diff & SD_FLOORHT) - sectors[i].floorheight = READFIXED(save_p); + sectors[i].floorheight = P_ReadFixed(save_p); if (diff & SD_CEILHT) - sectors[i].ceilingheight = READFIXED(save_p); + sectors[i].ceilingheight = P_ReadFixed(save_p); if (diff & SD_FLOORPIC) { - sectors[i].floorpic = P_AddLevelFlatRuntime((char *)save_p); - save_p += 8; + sectors[i].floorpic = P_AddLevelFlatRuntime((char *)&save_p->buf[save_p->pos]); + save_p->pos += 8; } if (diff & SD_CEILPIC) { - sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)save_p); - save_p += 8; + sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)&save_p->buf[save_p->pos]); + save_p->pos += 8; } if (diff & SD_LIGHT) - sectors[i].lightlevel = READINT16(save_p); + sectors[i].lightlevel = P_ReadINT16(save_p); if (diff & SD_SPECIAL) - sectors[i].special = READINT16(save_p); + sectors[i].special = P_ReadINT16(save_p); if (diff2 & SD_FXOFFS) - sectors[i].floorxoffset = READFIXED(save_p); + sectors[i].floorxoffset = P_ReadFixed(save_p); if (diff2 & SD_FYOFFS) - sectors[i].flooryoffset = READFIXED(save_p); + sectors[i].flooryoffset = P_ReadFixed(save_p); if (diff2 & SD_CXOFFS) - sectors[i].ceilingxoffset = READFIXED(save_p); + sectors[i].ceilingxoffset = P_ReadFixed(save_p); if (diff2 & SD_CYOFFS) - sectors[i].ceilingyoffset = READFIXED(save_p); + sectors[i].ceilingyoffset = P_ReadFixed(save_p); if (diff2 & SD_FLOORANG) - sectors[i].floorangle = READANGLE(save_p); + sectors[i].floorangle = P_ReadAngle(save_p); if (diff2 & SD_CEILANG) - sectors[i].ceilingangle = READANGLE(save_p); + sectors[i].ceilingangle = P_ReadAngle(save_p); if (diff2 & SD_TAG) { - size_t ncount = READUINT32(save_p); + size_t ncount = P_ReadUINT32(save_p); // Remove entries from global lists. for (j = 0; j < sectors[i].tags.count; j++) @@ -1298,7 +1542,7 @@ static void UnArchiveSectors(void) } for (j = 0; j < ncount; j++) - sectors[i].tags.tags[j] = READINT16(save_p); + sectors[i].tags.tags[j] = P_ReadINT16(save_p); // Add new entries. for (j = 0; j < sectors[i].tags.count; j++) @@ -1307,49 +1551,49 @@ static void UnArchiveSectors(void) if (diff3 & SD_COLORMAP) - sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p)); + sectors[i].extra_colormap = GetNetColormapFromList(P_ReadUINT32(save_p)); if (diff3 & SD_CRUMBLESTATE) - sectors[i].crumblestate = READINT32(save_p); + sectors[i].crumblestate = P_ReadINT32(save_p); if (diff3 & SD_FLOORLIGHT) { - sectors[i].floorlightlevel = READINT16(save_p); - sectors[i].floorlightabsolute = READUINT8(save_p); + sectors[i].floorlightlevel = P_ReadINT16(save_p); + sectors[i].floorlightabsolute = P_ReadUINT8(save_p); } if (diff3 & SD_CEILLIGHT) { - sectors[i].ceilinglightlevel = READINT16(save_p); - sectors[i].ceilinglightabsolute = READUINT8(save_p); + sectors[i].ceilinglightlevel = P_ReadINT16(save_p); + sectors[i].ceilinglightabsolute = P_ReadUINT8(save_p); } if (diff3 & SD_FLAG) { - sectors[i].flags = READUINT32(save_p); + sectors[i].flags = P_ReadUINT32(save_p); CheckForReverseGravity |= (sectors[i].flags & MSF_GRAVITYFLIP); } if (diff3 & SD_SPECIALFLAG) - sectors[i].specialflags = READUINT32(save_p); + sectors[i].specialflags = P_ReadUINT32(save_p); if (diff4 & SD_DAMAGETYPE) - sectors[i].damagetype = READUINT8(save_p); + sectors[i].damagetype = P_ReadUINT8(save_p); if (diff4 & SD_TRIGGERTAG) - sectors[i].triggertag = READINT16(save_p); + sectors[i].triggertag = P_ReadINT16(save_p); if (diff4 & SD_TRIGGERER) - sectors[i].triggerer = READUINT8(save_p); + sectors[i].triggerer = P_ReadUINT8(save_p); if (diff4 & SD_FXSCALE) - sectors[i].floorxscale = READFIXED(save_p); + sectors[i].floorxscale = P_ReadFixed(save_p); if (diff4 & SD_FYSCALE) - sectors[i].flooryscale = READFIXED(save_p); + sectors[i].flooryscale = P_ReadFixed(save_p); if (diff4 & SD_CXSCALE) - sectors[i].ceilingxscale = READFIXED(save_p); + sectors[i].ceilingxscale = P_ReadFixed(save_p); if (diff4 & SD_CYSCALE) - sectors[i].ceilingyscale = READFIXED(save_p); + sectors[i].ceilingyscale = P_ReadFixed(save_p); if (diff5 & SD_GRAVITY) - sectors[i].gravity = READFIXED(save_p); + sectors[i].gravity = P_ReadFixed(save_p); if (diff5 & SD_FLOORPORTAL) - sectors[i].portal_floor = READUINT32(save_p); + sectors[i].portal_floor = P_ReadUINT32(save_p); if (diff5 & SD_CEILPORTAL) - sectors[i].portal_ceiling = READUINT32(save_p); + sectors[i].portal_ceiling = P_ReadUINT32(save_p); if (diff & SD_FFLOORS) - UnArchiveFFloors(§ors[i]); + UnArchiveFFloors(save_p, §ors[i]); } } @@ -1393,52 +1637,84 @@ static UINT32 GetSideDiff(const side_t *si, const side_t *spawnsi) diff |= LD_SDBOTSCALEY; if (si->repeatcnt != spawnsi->repeatcnt) diff |= LD_SDREPEATCNT; + if (si->light != spawnsi->light) + diff |= LD_SDLIGHT; + if (si->light_top != spawnsi->light_top) + diff |= LD_SDTOPLIGHT; + if (si->light_mid != spawnsi->light_mid) + diff |= LD_SDMIDLIGHT; + if (si->light_bottom != spawnsi->light_bottom) + diff |= LD_SDBOTLIGHT; + if (si->lightabsolute != spawnsi->lightabsolute) + diff |= LD_SDLIGHTABS; + if (si->lightabsolute_top != spawnsi->lightabsolute_top) + diff |= LD_SDTOPLIGHTABS; + if (si->lightabsolute_mid != spawnsi->lightabsolute_mid) + diff |= LD_SDMIDLIGHTABS; + if (si->lightabsolute_bottom != spawnsi->lightabsolute_bottom) + diff |= LD_SDBOTLIGHTABS; return diff; } -static void ArchiveSide(const side_t *si, UINT32 diff) +static void ArchiveSide(save_t *save_p, const side_t *si, UINT32 diff) { - WRITEUINT32(save_p, diff); + P_WriteUINT32(save_p, diff); if (diff & LD_SDTEXOFFX) - WRITEFIXED(save_p, si->textureoffset); + P_WriteFixed(save_p, si->textureoffset); if (diff & LD_SDTEXOFFY) - WRITEFIXED(save_p, si->rowoffset); + P_WriteFixed(save_p, si->rowoffset); if (diff & LD_SDTOPTEX) - WRITEINT32(save_p, si->toptexture); + P_WriteINT32(save_p, si->toptexture); if (diff & LD_SDBOTTEX) - WRITEINT32(save_p, si->bottomtexture); + P_WriteINT32(save_p, si->bottomtexture); if (diff & LD_SDMIDTEX) - WRITEINT32(save_p, si->midtexture); + P_WriteINT32(save_p, si->midtexture); if (diff & LD_SDTOPOFFX) - WRITEFIXED(save_p, si->offsetx_top); + P_WriteFixed(save_p, si->offsetx_top); if (diff & LD_SDMIDOFFX) - WRITEFIXED(save_p, si->offsetx_mid); + P_WriteFixed(save_p, si->offsetx_mid); if (diff & LD_SDBOTOFFX) - WRITEFIXED(save_p, si->offsetx_bottom); + P_WriteFixed(save_p, si->offsetx_bottom); if (diff & LD_SDTOPOFFY) - WRITEFIXED(save_p, si->offsety_top); + P_WriteFixed(save_p, si->offsety_top); if (diff & LD_SDMIDOFFY) - WRITEFIXED(save_p, si->offsety_mid); + P_WriteFixed(save_p, si->offsety_mid); if (diff & LD_SDBOTOFFY) - WRITEFIXED(save_p, si->offsety_bottom); + P_WriteFixed(save_p, si->offsety_bottom); if (diff & LD_SDTOPSCALEX) - WRITEFIXED(save_p, si->scalex_top); + P_WriteFixed(save_p, si->scalex_top); if (diff & LD_SDMIDSCALEX) - WRITEFIXED(save_p, si->scalex_mid); + P_WriteFixed(save_p, si->scalex_mid); if (diff & LD_SDBOTSCALEX) - WRITEFIXED(save_p, si->scalex_bottom); + P_WriteFixed(save_p, si->scalex_bottom); if (diff & LD_SDTOPSCALEY) - WRITEFIXED(save_p, si->scaley_top); + P_WriteFixed(save_p, si->scaley_top); if (diff & LD_SDMIDSCALEY) - WRITEFIXED(save_p, si->scaley_mid); + P_WriteFixed(save_p, si->scaley_mid); if (diff & LD_SDBOTSCALEY) - WRITEFIXED(save_p, si->scaley_bottom); + P_WriteFixed(save_p, si->scaley_bottom); if (diff & LD_SDREPEATCNT) - WRITEINT16(save_p, si->repeatcnt); + P_WriteINT16(save_p, si->repeatcnt); + if (diff & LD_SDLIGHT) + P_WriteINT16(save_p, si->light); + if (diff & LD_SDTOPLIGHT) + P_WriteINT16(save_p, si->light_top); + if (diff & LD_SDMIDLIGHT) + P_WriteINT16(save_p, si->light_mid); + if (diff & LD_SDBOTLIGHT) + P_WriteINT16(save_p, si->light_bottom); + if (diff & LD_SDLIGHTABS) + P_WriteUINT8(save_p, si->lightabsolute); + if (diff & LD_SDTOPLIGHTABS) + P_WriteUINT8(save_p, si->lightabsolute_top); + if (diff & LD_SDMIDLIGHTABS) + P_WriteUINT8(save_p, si->lightabsolute_mid); + if (diff & LD_SDBOTLIGHTABS) + P_WriteUINT8(save_p, si->lightabsolute_bottom); } -static void ArchiveLines(void) +static void ArchiveLines(save_t *save_p) { size_t i; const line_t *li = lines; @@ -1488,21 +1764,21 @@ static void ArchiveLines(void) if (diff) { - WRITEUINT32(save_p, i); - WRITEUINT8(save_p, diff); + P_WriteUINT32(save_p, i); + P_WriteUINT8(save_p, diff); if (diff & LD_DIFF2) - WRITEUINT8(save_p, diff2); + P_WriteUINT8(save_p, diff2); if (diff & LD_FLAG) - WRITEINT16(save_p, li->flags); + P_WriteINT16(save_p, li->flags); if (diff & LD_SPECIAL) - WRITEINT16(save_p, li->special); + P_WriteINT16(save_p, li->special); if (diff & LD_CLLCOUNT) - WRITEINT16(save_p, li->callcount); + P_WriteINT16(save_p, li->callcount); if (diff & LD_ARGS) { UINT8 j; for (j = 0; j < NUMLINEARGS; j++) - WRITEINT32(save_p, li->args[j]); + P_WriteINT32(save_p, li->args[j]); } if (diff & LD_STRINGARGS) { @@ -1513,72 +1789,88 @@ static void ArchiveLines(void) if (!li->stringargs[j]) { - WRITEINT32(save_p, 0); + P_WriteINT32(save_p, 0); continue; } len = strlen(li->stringargs[j]); - WRITEINT32(save_p, len); + P_WriteINT32(save_p, len); for (k = 0; k < len; k++) - WRITECHAR(save_p, li->stringargs[j][k]); + P_WriteChar(save_p, li->stringargs[j][k]); } } if (diff & LD_SIDE1) - ArchiveSide(&sides[li->sidenum[0]], side1diff); + ArchiveSide(save_p, &sides[li->sidenum[0]], side1diff); if (diff & LD_SIDE2) - ArchiveSide(&sides[li->sidenum[1]], side2diff); + ArchiveSide(save_p, &sides[li->sidenum[1]], side2diff); if (diff2 & LD_EXECUTORDELAY) - WRITEINT32(save_p, li->executordelay); + P_WriteINT32(save_p, li->executordelay); if (diff2 & LD_TRANSFPORTAL) - WRITEUINT32(save_p, li->secportal); + P_WriteUINT32(save_p, li->secportal); } } - WRITEUINT32(save_p, 0xffffffff); + P_WriteUINT32(save_p, 0xffffffff); } -static void UnArchiveSide(side_t *si) +static void UnArchiveSide(save_t *save_p, side_t *si) { - UINT32 diff = READUINT32(save_p); + UINT32 diff = P_ReadUINT32(save_p); if (diff & LD_SDTEXOFFX) - si->textureoffset = READFIXED(save_p); + si->textureoffset = P_ReadFixed(save_p); if (diff & LD_SDTEXOFFY) - si->rowoffset = READFIXED(save_p); + si->rowoffset = P_ReadFixed(save_p); if (diff & LD_SDTOPTEX) - si->toptexture = READINT32(save_p); + si->toptexture = P_ReadINT32(save_p); if (diff & LD_SDBOTTEX) - si->bottomtexture = READINT32(save_p); + si->bottomtexture = P_ReadINT32(save_p); if (diff & LD_SDMIDTEX) - si->midtexture = READINT32(save_p); + si->midtexture = P_ReadINT32(save_p); if (diff & LD_SDTOPOFFX) - si->offsetx_top = READFIXED(save_p); + si->offsetx_top = P_ReadFixed(save_p); if (diff & LD_SDMIDOFFX) - si->offsetx_mid = READFIXED(save_p); + si->offsetx_mid = P_ReadFixed(save_p); if (diff & LD_SDBOTOFFX) - si->offsetx_bottom = READFIXED(save_p); + si->offsetx_bottom = P_ReadFixed(save_p); if (diff & LD_SDTOPOFFY) - si->offsety_top = READFIXED(save_p); + si->offsety_top = P_ReadFixed(save_p); if (diff & LD_SDMIDOFFY) - si->offsety_mid = READFIXED(save_p); + si->offsety_mid = P_ReadFixed(save_p); if (diff & LD_SDBOTOFFY) - si->offsety_bottom = READFIXED(save_p); + si->offsety_bottom = P_ReadFixed(save_p); if (diff & LD_SDTOPSCALEX) - si->scalex_top = READFIXED(save_p); + si->scalex_top = P_ReadFixed(save_p); if (diff & LD_SDMIDSCALEX) - si->scalex_mid = READFIXED(save_p); + si->scalex_mid = P_ReadFixed(save_p); if (diff & LD_SDBOTSCALEX) - si->scalex_bottom = READFIXED(save_p); + si->scalex_bottom = P_ReadFixed(save_p); if (diff & LD_SDTOPSCALEY) - si->scaley_top = READFIXED(save_p); + si->scaley_top = P_ReadFixed(save_p); if (diff & LD_SDMIDSCALEY) - si->scaley_mid = READFIXED(save_p); + si->scaley_mid = P_ReadFixed(save_p); if (diff & LD_SDBOTSCALEY) - si->scaley_bottom = READFIXED(save_p); + si->scaley_bottom = P_ReadFixed(save_p); if (diff & LD_SDREPEATCNT) - si->repeatcnt = READINT16(save_p); + si->repeatcnt = P_ReadINT16(save_p); + if (diff & LD_SDLIGHT) + si->light = P_ReadINT16(save_p); + if (diff & LD_SDTOPLIGHT) + si->light_top = P_ReadINT16(save_p); + if (diff & LD_SDMIDLIGHT) + si->light_mid = P_ReadINT16(save_p); + if (diff & LD_SDBOTLIGHT) + si->light_bottom = P_ReadINT16(save_p); + if (diff & LD_SDLIGHTABS) + si->lightabsolute = P_ReadUINT8(save_p); + if (diff & LD_SDTOPLIGHTABS) + si->lightabsolute_top = P_ReadUINT8(save_p); + if (diff & LD_SDMIDLIGHTABS) + si->lightabsolute_mid = P_ReadUINT8(save_p); + if (diff & LD_SDBOTLIGHTABS) + si->lightabsolute_bottom = P_ReadUINT8(save_p); } -static void UnArchiveLines(void) +static void UnArchiveLines(save_t *save_p) { UINT32 i; line_t *li; @@ -1586,38 +1878,38 @@ static void UnArchiveLines(void) for (;;) { - i = READUINT32(save_p); + i = P_ReadUINT32(save_p); if (i == 0xffffffff) break; if (i > numlines) I_Error("Invalid line number %u from server", i); - diff = READUINT8(save_p); + diff = P_ReadUINT8(save_p); if (diff & LD_DIFF2) - diff2 = READUINT8(save_p); + diff2 = P_ReadUINT8(save_p); else diff2 = 0; li = &lines[i]; if (diff & LD_FLAG) - li->flags = READINT16(save_p); + li->flags = P_ReadINT16(save_p); if (diff & LD_SPECIAL) - li->special = READINT16(save_p); + li->special = P_ReadINT16(save_p); if (diff & LD_CLLCOUNT) - li->callcount = READINT16(save_p); + li->callcount = P_ReadINT16(save_p); if (diff & LD_ARGS) { UINT8 j; for (j = 0; j < NUMLINEARGS; j++) - li->args[j] = READINT32(save_p); + li->args[j] = P_ReadINT32(save_p); } if (diff & LD_STRINGARGS) { UINT8 j; for (j = 0; j < NUMLINESTRINGARGS; j++) { - size_t len = READINT32(save_p); + size_t len = P_ReadINT32(save_p); size_t k; if (!len) @@ -1629,38 +1921,38 @@ static void UnArchiveLines(void) li->stringargs[j] = Z_Realloc(li->stringargs[j], len + 1, PU_LEVEL, NULL); for (k = 0; k < len; k++) - li->stringargs[j][k] = READCHAR(save_p); + li->stringargs[j][k] = P_ReadChar(save_p); li->stringargs[j][len] = '\0'; } } if (diff & LD_SIDE1) - UnArchiveSide(&sides[li->sidenum[0]]); + UnArchiveSide(save_p, &sides[li->sidenum[0]]); if (diff & LD_SIDE2) - UnArchiveSide(&sides[li->sidenum[1]]); + UnArchiveSide(save_p, &sides[li->sidenum[1]]); if (diff2 & LD_EXECUTORDELAY) - li->executordelay = READINT32(save_p); + li->executordelay = P_ReadINT32(save_p); if (diff2 & LD_TRANSFPORTAL) - li->secportal = READUINT32(save_p); + li->secportal = P_ReadUINT32(save_p); } } -static void P_NetArchiveWorld(void) +static void P_NetArchiveWorld(save_t *save_p) { // initialize colormap vars because paranoia ClearNetColormaps(); - WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); + P_WriteUINT32(save_p, ARCHIVEBLOCK_WORLD); - ArchiveSectors(); - ArchiveLines(); + ArchiveSectors(save_p); + ArchiveLines(save_p); R_ClearTextureNumCache(false); } -static void P_NetUnArchiveWorld(void) +static void P_NetUnArchiveWorld(save_t *save_p) { UINT16 i; - if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD) + if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_WORLD) I_Error("Bad $$$.sav at archive block World"); // initialize colormap vars because paranoia @@ -1674,8 +1966,8 @@ static void P_NetUnArchiveWorld(void) num_ffloors++; } - UnArchiveSectors(); - UnArchiveLines(); + UnArchiveSectors(save_p); + UnArchiveLines(save_p); } // @@ -1746,7 +2038,8 @@ typedef enum MD2_DISPOFFSET = 1<<23, MD2_DRAWONLYFORPLAYER = 1<<24, MD2_DONTDRAWFORVIEWMOBJ = 1<<25, - MD2_TRANSLATION = 1<<26 + MD2_TRANSLATION = 1<<26, + MD2_ALPHA = 1<<27 } mobj_diff2_t; typedef enum @@ -1825,7 +2118,7 @@ static UINT32 SaveSlope(const pslope_t *slope) return 0xFFFFFFFF; } -static void SaveMobjThinker(const thinker_t *th, const UINT8 type) +static void SaveMobjThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const mobj_t *mobj = (const mobj_t *)th; UINT32 diff; @@ -1989,6 +2282,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_DONTDRAWFORVIEWMOBJ; if (mobj->dispoffset != mobj->info->dispoffset) diff2 |= MD2_DISPOFFSET; + if (mobj->alpha != FRACUNIT) + diff2 |= MD2_ALPHA; if (diff2 != 0) diff |= MD_MORE; @@ -1997,28 +2292,28 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) if (mobj->type == MT_HOOPCENTER) diff = MD_SPAWNPOINT; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, diff); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, diff); if (diff & MD_MORE) - WRITEUINT32(save_p, diff2); + P_WriteUINT32(save_p, diff2); // save pointer, at load time we will search this pointer to reinitilize pointers - WRITEUINT32(save_p, (size_t)mobj); + P_WriteUINT32(save_p, (size_t)mobj); - WRITEFIXED(save_p, mobj->z); // Force this so 3dfloor problems don't arise. - WRITEFIXED(save_p, mobj->floorz); - WRITEFIXED(save_p, mobj->ceilingz); + P_WriteFixed(save_p, mobj->z); // Force this so 3dfloor problems don't arise. + P_WriteFixed(save_p, mobj->floorz); + P_WriteFixed(save_p, mobj->ceilingz); if (diff2 & MD2_FLOORROVER) { - WRITEUINT32(save_p, SaveSector(mobj->floorrover->target)); - WRITEUINT16(save_p, P_GetFFloorID(mobj->floorrover)); + P_WriteUINT32(save_p, SaveSector(mobj->floorrover->target)); + P_WriteUINT16(save_p, P_GetFFloorID(mobj->floorrover)); } if (diff2 & MD2_CEILINGROVER) { - WRITEUINT32(save_p, SaveSector(mobj->ceilingrover->target)); - WRITEUINT16(save_p, P_GetFFloorID(mobj->ceilingrover)); + P_WriteUINT32(save_p, SaveSector(mobj->ceilingrover->target)); + P_WriteUINT16(save_p, P_GetFFloorID(mobj->ceilingrover)); } if (diff & MD_SPAWNPOINT) @@ -2027,647 +2322,649 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) for (z = 0; z < nummapthings; z++) if (&mapthings[z] == mobj->spawnpoint) - WRITEUINT16(save_p, z); + P_WriteUINT16(save_p, z); if (mobj->type == MT_HOOPCENTER) return; } if (diff & MD_TYPE) - WRITEUINT32(save_p, mobj->type); + P_WriteUINT32(save_p, mobj->type); if (diff & MD_POS) { - WRITEFIXED(save_p, mobj->x); - WRITEFIXED(save_p, mobj->y); - WRITEANGLE(save_p, mobj->angle); - WRITEANGLE(save_p, mobj->pitch); - WRITEANGLE(save_p, mobj->roll); + P_WriteFixed(save_p, mobj->x); + P_WriteFixed(save_p, mobj->y); + P_WriteAngle(save_p, mobj->angle); + P_WriteAngle(save_p, mobj->pitch); + P_WriteAngle(save_p, mobj->roll); } if (diff & MD_MOM) { - WRITEFIXED(save_p, mobj->momx); - WRITEFIXED(save_p, mobj->momy); - WRITEFIXED(save_p, mobj->momz); - WRITEFIXED(save_p, mobj->pmomz); + P_WriteFixed(save_p, mobj->momx); + P_WriteFixed(save_p, mobj->momy); + P_WriteFixed(save_p, mobj->momz); + P_WriteFixed(save_p, mobj->pmomz); } if (diff & MD_RADIUS) - WRITEFIXED(save_p, mobj->radius); + P_WriteFixed(save_p, mobj->radius); if (diff & MD_HEIGHT) - WRITEFIXED(save_p, mobj->height); + P_WriteFixed(save_p, mobj->height); if (diff & MD_FLAGS) - WRITEUINT32(save_p, mobj->flags); + P_WriteUINT32(save_p, mobj->flags); if (diff & MD_FLAGS2) - WRITEUINT32(save_p, mobj->flags2); + P_WriteUINT32(save_p, mobj->flags2); if (diff & MD_HEALTH) - WRITEINT32(save_p, mobj->health); + P_WriteINT32(save_p, mobj->health); if (diff & MD_RTIME) - WRITEINT32(save_p, mobj->reactiontime); + P_WriteINT32(save_p, mobj->reactiontime); if (diff & MD_STATE) - WRITEUINT16(save_p, mobj->state-states); + P_WriteUINT16(save_p, mobj->state-states); if (diff & MD_TICS) - WRITEINT32(save_p, mobj->tics); + P_WriteINT32(save_p, mobj->tics); if (diff & MD_SPRITE) { - WRITEUINT16(save_p, mobj->sprite); + P_WriteUINT16(save_p, mobj->sprite); if (mobj->sprite == SPR_PLAY) - WRITEUINT16(save_p, mobj->sprite2); + P_WriteUINT16(save_p, mobj->sprite2); } if (diff & MD_FRAME) { - WRITEUINT32(save_p, mobj->frame); - WRITEUINT16(save_p, mobj->anim_duration); + P_WriteUINT32(save_p, mobj->frame); + P_WriteUINT16(save_p, mobj->anim_duration); } if (diff & MD_EFLAGS) - WRITEUINT16(save_p, mobj->eflags); + P_WriteUINT16(save_p, mobj->eflags); if (diff & MD_PLAYER) - WRITEUINT8(save_p, mobj->player-players); + P_WriteUINT8(save_p, mobj->player-players); if (diff & MD_MOVEDIR) - WRITEANGLE(save_p, mobj->movedir); + P_WriteAngle(save_p, mobj->movedir); if (diff & MD_MOVECOUNT) - WRITEINT32(save_p, mobj->movecount); + P_WriteINT32(save_p, mobj->movecount); if (diff & MD_THRESHOLD) - WRITEINT32(save_p, mobj->threshold); + P_WriteINT32(save_p, mobj->threshold); if (diff & MD_LASTLOOK) - WRITEINT32(save_p, mobj->lastlook); + P_WriteINT32(save_p, mobj->lastlook); if (diff & MD_TARGET) - WRITEUINT32(save_p, mobj->target->mobjnum); + P_WriteUINT32(save_p, mobj->target->mobjnum); if (diff & MD_TRACER) - WRITEUINT32(save_p, mobj->tracer->mobjnum); + P_WriteUINT32(save_p, mobj->tracer->mobjnum); if (diff & MD_FRICTION) - WRITEFIXED(save_p, mobj->friction); + P_WriteFixed(save_p, mobj->friction); if (diff & MD_MOVEFACTOR) - WRITEFIXED(save_p, mobj->movefactor); + P_WriteFixed(save_p, mobj->movefactor); if (diff & MD_FUSE) - WRITEINT32(save_p, mobj->fuse); + P_WriteINT32(save_p, mobj->fuse); if (diff & MD_WATERTOP) - WRITEFIXED(save_p, mobj->watertop); + P_WriteFixed(save_p, mobj->watertop); if (diff & MD_WATERBOTTOM) - WRITEFIXED(save_p, mobj->waterbottom); + P_WriteFixed(save_p, mobj->waterbottom); if (diff & MD_SCALE) - WRITEFIXED(save_p, mobj->scale); + P_WriteFixed(save_p, mobj->scale); if (diff & MD_DSCALE) - WRITEFIXED(save_p, mobj->destscale); + P_WriteFixed(save_p, mobj->destscale); if (diff2 & MD2_SCALESPEED) - WRITEFIXED(save_p, mobj->scalespeed); + P_WriteFixed(save_p, mobj->scalespeed); if (diff2 & MD2_CUSVAL) - WRITEINT32(save_p, mobj->cusval); + P_WriteINT32(save_p, mobj->cusval); if (diff2 & MD2_CVMEM) - WRITEINT32(save_p, mobj->cvmem); + P_WriteINT32(save_p, mobj->cvmem); if (diff2 & MD2_SKIN) - WRITEUINT8(save_p, (UINT8)(((skin_t *)mobj->skin)->skinnum)); + P_WriteUINT8(save_p, (UINT8)(((skin_t *)mobj->skin)->skinnum)); if (diff2 & MD2_COLOR) - WRITEUINT16(save_p, mobj->color); + P_WriteUINT16(save_p, mobj->color); if (diff2 & MD2_EXTVAL1) - WRITEINT32(save_p, mobj->extravalue1); + P_WriteINT32(save_p, mobj->extravalue1); if (diff2 & MD2_EXTVAL2) - WRITEINT32(save_p, mobj->extravalue2); + P_WriteINT32(save_p, mobj->extravalue2); if (diff2 & MD2_HNEXT) - WRITEUINT32(save_p, mobj->hnext->mobjnum); + P_WriteUINT32(save_p, mobj->hnext->mobjnum); if (diff2 & MD2_HPREV) - WRITEUINT32(save_p, mobj->hprev->mobjnum); + P_WriteUINT32(save_p, mobj->hprev->mobjnum); if (diff2 & MD2_SLOPE) - WRITEUINT16(save_p, mobj->standingslope->id); + P_WriteUINT16(save_p, mobj->standingslope->id); if (diff2 & MD2_COLORIZED) - WRITEUINT8(save_p, mobj->colorized); + P_WriteUINT8(save_p, mobj->colorized); if (diff2 & MD2_MIRRORED) - WRITEUINT8(save_p, mobj->mirrored); + P_WriteUINT8(save_p, mobj->mirrored); if (diff2 & MD2_SPRITEROLL) - WRITEANGLE(save_p, mobj->spriteroll); + P_WriteAngle(save_p, mobj->spriteroll); if (diff2 & MD2_SHADOWSCALE) - WRITEFIXED(save_p, mobj->shadowscale); + P_WriteFixed(save_p, mobj->shadowscale); if (diff2 & MD2_RENDERFLAGS) - WRITEUINT32(save_p, mobj->renderflags); + P_WriteUINT32(save_p, mobj->renderflags); if (diff2 & MD2_BLENDMODE) - WRITEINT32(save_p, mobj->blendmode); + P_WriteINT32(save_p, mobj->blendmode); if (diff2 & MD2_SPRITEXSCALE) - WRITEFIXED(save_p, mobj->spritexscale); + P_WriteFixed(save_p, mobj->spritexscale); if (diff2 & MD2_SPRITEYSCALE) - WRITEFIXED(save_p, mobj->spriteyscale); + P_WriteFixed(save_p, mobj->spriteyscale); if (diff2 & MD2_SPRITEXOFFSET) - WRITEFIXED(save_p, mobj->spritexoffset); + P_WriteFixed(save_p, mobj->spritexoffset); if (diff2 & MD2_SPRITEYOFFSET) - WRITEFIXED(save_p, mobj->spriteyoffset); + P_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); + P_WriteFixed(save_p, slope->zdelta); + P_WriteAngle(save_p, slope->zangle); + P_WriteAngle(save_p, slope->xydirection); - WRITEFIXED(save_p, slope->o.x); - WRITEFIXED(save_p, slope->o.y); - WRITEFIXED(save_p, slope->o.z); + P_WriteFixed(save_p, slope->o.x); + P_WriteFixed(save_p, slope->o.y); + P_WriteFixed(save_p, slope->o.z); - WRITEFIXED(save_p, slope->d.x); - WRITEFIXED(save_p, slope->d.y); + P_WriteFixed(save_p, slope->d.x); + P_WriteFixed(save_p, slope->d.y); - WRITEFIXED(save_p, slope->normal.x); - WRITEFIXED(save_p, slope->normal.y); - WRITEFIXED(save_p, slope->normal.z); + P_WriteFixed(save_p, slope->normal.x); + P_WriteFixed(save_p, slope->normal.y); + P_WriteFixed(save_p, slope->normal.z); } if (diff2 & MD2_DRAWONLYFORPLAYER) - WRITEUINT8(save_p, mobj->drawonlyforplayer-players); + P_WriteUINT8(save_p, mobj->drawonlyforplayer-players); if (diff2 & MD2_DONTDRAWFORVIEWMOBJ) - WRITEUINT32(save_p, mobj->dontdrawforviewmobj->mobjnum); + P_WriteUINT32(save_p, mobj->dontdrawforviewmobj->mobjnum); if (diff2 & MD2_DISPOFFSET) - WRITEINT32(save_p, mobj->dispoffset); + P_WriteINT32(save_p, mobj->dispoffset); if (diff2 & MD2_TRANSLATION) - WRITEUINT16(save_p, mobj->translation); + P_WriteUINT16(save_p, mobj->translation); + if (diff2 & MD2_ALPHA) + P_WriteFixed(save_p, mobj->alpha); - WRITEUINT32(save_p, mobj->mobjnum); + P_WriteUINT32(save_p, mobj->mobjnum); } -static void SaveNoEnemiesThinker(const thinker_t *th, const UINT8 type) +static void SaveNoEnemiesThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const noenemies_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); } -static void SaveBounceCheeseThinker(const thinker_t *th, const UINT8 type) +static void SaveBounceCheeseThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const bouncecheese_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEFIXED(save_p, ht->speed); - WRITEFIXED(save_p, ht->distance); - WRITEFIXED(save_p, ht->floorwasheight); - WRITEFIXED(save_p, ht->ceilingwasheight); - WRITECHAR(save_p, ht->low); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteFixed(save_p, ht->speed); + P_WriteFixed(save_p, ht->distance); + P_WriteFixed(save_p, ht->floorwasheight); + P_WriteFixed(save_p, ht->ceilingwasheight); + P_WriteChar(save_p, ht->low); } -static void SaveContinuousFallThinker(const thinker_t *th, const UINT8 type) +static void SaveContinuousFallThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const continuousfall_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEFIXED(save_p, ht->speed); - WRITEINT32(save_p, ht->direction); - WRITEFIXED(save_p, ht->floorstartheight); - WRITEFIXED(save_p, ht->ceilingstartheight); - WRITEFIXED(save_p, ht->destheight); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteFixed(save_p, ht->speed); + P_WriteINT32(save_p, ht->direction); + P_WriteFixed(save_p, ht->floorstartheight); + P_WriteFixed(save_p, ht->ceilingstartheight); + P_WriteFixed(save_p, ht->destheight); } -static void SaveMarioBlockThinker(const thinker_t *th, const UINT8 type) +static void SaveMarioBlockThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const mariothink_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEFIXED(save_p, ht->speed); - WRITEINT32(save_p, ht->direction); - WRITEFIXED(save_p, ht->floorstartheight); - WRITEFIXED(save_p, ht->ceilingstartheight); - WRITEINT16(save_p, ht->tag); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteFixed(save_p, ht->speed); + P_WriteINT32(save_p, ht->direction); + P_WriteFixed(save_p, ht->floorstartheight); + P_WriteFixed(save_p, ht->ceilingstartheight); + P_WriteINT16(save_p, ht->tag); } -static void SaveMarioCheckThinker(const thinker_t *th, const UINT8 type) +static void SaveMarioCheckThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const mariocheck_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); - WRITEUINT32(save_p, SaveSector(ht->sector)); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT32(save_p, SaveSector(ht->sector)); } -static void SaveThwompThinker(const thinker_t *th, const UINT8 type) +static void SaveThwompThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const thwomp_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEFIXED(save_p, ht->crushspeed); - WRITEFIXED(save_p, ht->retractspeed); - WRITEINT32(save_p, ht->direction); - WRITEFIXED(save_p, ht->floorstartheight); - WRITEFIXED(save_p, ht->ceilingstartheight); - WRITEINT32(save_p, ht->delay); - WRITEINT16(save_p, ht->tag); - WRITEUINT16(save_p, ht->sound); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteFixed(save_p, ht->crushspeed); + P_WriteFixed(save_p, ht->retractspeed); + P_WriteINT32(save_p, ht->direction); + P_WriteFixed(save_p, ht->floorstartheight); + P_WriteFixed(save_p, ht->ceilingstartheight); + P_WriteINT32(save_p, ht->delay); + P_WriteINT16(save_p, ht->tag); + P_WriteUINT16(save_p, ht->sound); } -static void SaveFloatThinker(const thinker_t *th, const UINT8 type) +static void SaveFloatThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const floatthink_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT16(save_p, ht->tag); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteINT16(save_p, ht->tag); } -static void SaveEachTimeThinker(const thinker_t *th, const UINT8 type) +static void SaveEachTimeThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const eachtime_t *ht = (const void *)th; size_t i; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); for (i = 0; i < MAXPLAYERS; i++) { - WRITECHAR(save_p, ht->playersInArea[i]); + P_WriteChar(save_p, ht->playersInArea[i]); } - WRITECHAR(save_p, ht->triggerOnExit); + P_WriteChar(save_p, ht->triggerOnExit); } -static void SaveRaiseThinker(const thinker_t *th, const UINT8 type) +static void SaveRaiseThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const raise_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT16(save_p, ht->tag); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEFIXED(save_p, ht->ceilingbottom); - WRITEFIXED(save_p, ht->ceilingtop); - WRITEFIXED(save_p, ht->basespeed); - WRITEFIXED(save_p, ht->extraspeed); - WRITEUINT8(save_p, ht->shaketimer); - WRITEUINT8(save_p, ht->flags); + P_WriteUINT8(save_p, type); + P_WriteINT16(save_p, ht->tag); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteFixed(save_p, ht->ceilingbottom); + P_WriteFixed(save_p, ht->ceilingtop); + P_WriteFixed(save_p, ht->basespeed); + P_WriteFixed(save_p, ht->extraspeed); + P_WriteUINT8(save_p, ht->shaketimer); + P_WriteUINT8(save_p, ht->flags); } -static void SaveCeilingThinker(const thinker_t *th, const UINT8 type) +static void SaveCeilingThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const ceiling_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT8(save_p, ht->type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEFIXED(save_p, ht->bottomheight); - WRITEFIXED(save_p, ht->topheight); - WRITEFIXED(save_p, ht->speed); - WRITEFIXED(save_p, ht->delay); - WRITEFIXED(save_p, ht->delaytimer); - WRITEUINT8(save_p, ht->crush); - WRITEINT32(save_p, ht->texture); - WRITEINT32(save_p, ht->direction); - WRITEINT16(save_p, ht->tag); - WRITEFIXED(save_p, ht->origspeed); - WRITEFIXED(save_p, ht->sourceline); + P_WriteUINT8(save_p, type); + P_WriteUINT8(save_p, ht->type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteFixed(save_p, ht->bottomheight); + P_WriteFixed(save_p, ht->topheight); + P_WriteFixed(save_p, ht->speed); + P_WriteFixed(save_p, ht->delay); + P_WriteFixed(save_p, ht->delaytimer); + P_WriteUINT8(save_p, ht->crush); + P_WriteINT32(save_p, ht->texture); + P_WriteINT32(save_p, ht->direction); + P_WriteINT16(save_p, ht->tag); + P_WriteFixed(save_p, ht->origspeed); + P_WriteFixed(save_p, ht->sourceline); } -static void SaveFloormoveThinker(const thinker_t *th, const UINT8 type) +static void SaveFloormoveThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const floormove_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT8(save_p, ht->type); - WRITEUINT8(save_p, ht->crush); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT32(save_p, ht->direction); - WRITEINT32(save_p, ht->texture); - WRITEFIXED(save_p, ht->floordestheight); - WRITEFIXED(save_p, ht->speed); - WRITEFIXED(save_p, ht->origspeed); - WRITEFIXED(save_p, ht->delay); - WRITEFIXED(save_p, ht->delaytimer); - WRITEINT16(save_p, ht->tag); - WRITEFIXED(save_p, ht->sourceline); + P_WriteUINT8(save_p, type); + P_WriteUINT8(save_p, ht->type); + P_WriteUINT8(save_p, ht->crush); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteINT32(save_p, ht->direction); + P_WriteINT32(save_p, ht->texture); + P_WriteFixed(save_p, ht->floordestheight); + P_WriteFixed(save_p, ht->speed); + P_WriteFixed(save_p, ht->origspeed); + P_WriteFixed(save_p, ht->delay); + P_WriteFixed(save_p, ht->delaytimer); + P_WriteINT16(save_p, ht->tag); + P_WriteFixed(save_p, ht->sourceline); } -static void SaveLightflashThinker(const thinker_t *th, const UINT8 type) +static void SaveLightflashThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const lightflash_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT32(save_p, ht->maxlight); - WRITEINT32(save_p, ht->minlight); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteINT32(save_p, ht->maxlight); + P_WriteINT32(save_p, ht->minlight); } -static void SaveStrobeThinker(const thinker_t *th, const UINT8 type) +static void SaveStrobeThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const strobe_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT32(save_p, ht->count); - WRITEINT16(save_p, ht->minlight); - WRITEINT16(save_p, ht->maxlight); - WRITEINT32(save_p, ht->darktime); - WRITEINT32(save_p, ht->brighttime); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteINT32(save_p, ht->count); + P_WriteINT16(save_p, ht->minlight); + P_WriteINT16(save_p, ht->maxlight); + P_WriteINT32(save_p, ht->darktime); + P_WriteINT32(save_p, ht->brighttime); } -static void SaveGlowThinker(const thinker_t *th, const UINT8 type) +static void SaveGlowThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const glow_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT16(save_p, ht->minlight); - WRITEINT16(save_p, ht->maxlight); - WRITEINT16(save_p, ht->direction); - WRITEINT16(save_p, ht->speed); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteINT16(save_p, ht->minlight); + P_WriteINT16(save_p, ht->maxlight); + P_WriteINT16(save_p, ht->direction); + P_WriteINT16(save_p, ht->speed); } -static inline void SaveFireflickerThinker(const thinker_t *th, const UINT8 type) +static inline void SaveFireflickerThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const fireflicker_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT32(save_p, ht->count); - WRITEINT32(save_p, ht->resetcount); - WRITEINT16(save_p, ht->maxlight); - WRITEINT16(save_p, ht->minlight); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteINT32(save_p, ht->count); + P_WriteINT32(save_p, ht->resetcount); + P_WriteINT16(save_p, ht->maxlight); + P_WriteINT16(save_p, ht->minlight); } -static void SaveElevatorThinker(const thinker_t *th, const UINT8 type) +static void SaveElevatorThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const elevator_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT8(save_p, ht->type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEUINT32(save_p, SaveSector(ht->actionsector)); - WRITEINT32(save_p, ht->direction); - WRITEFIXED(save_p, ht->floordestheight); - WRITEFIXED(save_p, ht->ceilingdestheight); - WRITEFIXED(save_p, ht->speed); - WRITEFIXED(save_p, ht->origspeed); - WRITEFIXED(save_p, ht->low); - WRITEFIXED(save_p, ht->high); - WRITEFIXED(save_p, ht->distance); - WRITEFIXED(save_p, ht->delay); - WRITEFIXED(save_p, ht->delaytimer); - WRITEFIXED(save_p, ht->floorwasheight); - WRITEFIXED(save_p, ht->ceilingwasheight); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT8(save_p, type); + P_WriteUINT8(save_p, ht->type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteUINT32(save_p, SaveSector(ht->actionsector)); + P_WriteINT32(save_p, ht->direction); + P_WriteFixed(save_p, ht->floordestheight); + P_WriteFixed(save_p, ht->ceilingdestheight); + P_WriteFixed(save_p, ht->speed); + P_WriteFixed(save_p, ht->origspeed); + P_WriteFixed(save_p, ht->low); + P_WriteFixed(save_p, ht->high); + P_WriteFixed(save_p, ht->distance); + P_WriteFixed(save_p, ht->delay); + P_WriteFixed(save_p, ht->delaytimer); + P_WriteFixed(save_p, ht->floorwasheight); + P_WriteFixed(save_p, ht->ceilingwasheight); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); } -static void SaveCrumbleThinker(const thinker_t *th, const UINT8 type) +static void SaveCrumbleThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const crumble_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEUINT32(save_p, SaveSector(ht->actionsector)); - WRITEUINT32(save_p, SavePlayer(ht->player)); // was dummy - WRITEINT32(save_p, ht->direction); - WRITEINT32(save_p, ht->origalpha); - WRITEINT32(save_p, ht->timer); - WRITEFIXED(save_p, ht->speed); - WRITEFIXED(save_p, ht->floorwasheight); - WRITEFIXED(save_p, ht->ceilingwasheight); - WRITEUINT8(save_p, ht->flags); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteUINT32(save_p, SaveSector(ht->actionsector)); + P_WriteUINT32(save_p, SavePlayer(ht->player)); // was dummy + P_WriteINT32(save_p, ht->direction); + P_WriteINT32(save_p, ht->origalpha); + P_WriteINT32(save_p, ht->timer); + P_WriteFixed(save_p, ht->speed); + P_WriteFixed(save_p, ht->floorwasheight); + P_WriteFixed(save_p, ht->ceilingwasheight); + P_WriteUINT8(save_p, ht->flags); } -static inline void SaveScrollThinker(const thinker_t *th, const UINT8 type) +static inline void SaveScrollThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const scroll_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEFIXED(save_p, ht->dx); - WRITEFIXED(save_p, ht->dy); - WRITEINT32(save_p, ht->affectee); - WRITEINT32(save_p, ht->control); - WRITEFIXED(save_p, ht->last_height); - WRITEFIXED(save_p, ht->vdx); - WRITEFIXED(save_p, ht->vdy); - WRITEINT32(save_p, ht->accel); - WRITEINT32(save_p, ht->exclusive); - WRITEUINT8(save_p, ht->type); + P_WriteUINT8(save_p, type); + P_WriteFixed(save_p, ht->dx); + P_WriteFixed(save_p, ht->dy); + P_WriteINT32(save_p, ht->affectee); + P_WriteINT32(save_p, ht->control); + P_WriteFixed(save_p, ht->last_height); + P_WriteFixed(save_p, ht->vdx); + P_WriteFixed(save_p, ht->vdy); + P_WriteINT32(save_p, ht->accel); + P_WriteINT32(save_p, ht->exclusive); + P_WriteUINT8(save_p, ht->type); } -static inline void SaveFrictionThinker(const thinker_t *th, const UINT8 type) +static inline void SaveFrictionThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const friction_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->friction); - WRITEINT32(save_p, ht->movefactor); - WRITEINT32(save_p, ht->affectee); - WRITEINT32(save_p, ht->referrer); - WRITEUINT8(save_p, ht->roverfriction); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->friction); + P_WriteINT32(save_p, ht->movefactor); + P_WriteINT32(save_p, ht->affectee); + P_WriteINT32(save_p, ht->referrer); + P_WriteUINT8(save_p, ht->roverfriction); } -static inline void SavePusherThinker(const thinker_t *th, const UINT8 type) +static inline void SavePusherThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const pusher_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT8(save_p, ht->type); - WRITEFIXED(save_p, ht->x_mag); - WRITEFIXED(save_p, ht->y_mag); - WRITEFIXED(save_p, ht->z_mag); - WRITEINT32(save_p, ht->affectee); - WRITEUINT8(save_p, ht->roverpusher); - WRITEINT32(save_p, ht->referrer); - WRITEINT32(save_p, ht->exclusive); - WRITEINT32(save_p, ht->slider); + P_WriteUINT8(save_p, type); + P_WriteUINT8(save_p, ht->type); + P_WriteFixed(save_p, ht->x_mag); + P_WriteFixed(save_p, ht->y_mag); + P_WriteFixed(save_p, ht->z_mag); + P_WriteINT32(save_p, ht->affectee); + P_WriteUINT8(save_p, ht->roverpusher); + P_WriteINT32(save_p, ht->referrer); + P_WriteINT32(save_p, ht->exclusive); + P_WriteINT32(save_p, ht->slider); } -static void SaveLaserThinker(const thinker_t *th, const UINT8 type) +static void SaveLaserThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const laserthink_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT16(save_p, ht->tag); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); - WRITEUINT8(save_p, ht->nobosses); + P_WriteUINT8(save_p, type); + P_WriteINT16(save_p, ht->tag); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT8(save_p, ht->nobosses); } -static void SaveLightlevelThinker(const thinker_t *th, const UINT8 type) +static void SaveLightlevelThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const lightlevel_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT16(save_p, ht->sourcelevel); - WRITEINT16(save_p, ht->destlevel); - WRITEFIXED(save_p, ht->fixedcurlevel); - WRITEFIXED(save_p, ht->fixedpertic); - WRITEINT32(save_p, ht->timer); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteINT16(save_p, ht->sourcelevel); + P_WriteINT16(save_p, ht->destlevel); + P_WriteFixed(save_p, ht->fixedcurlevel); + P_WriteFixed(save_p, ht->fixedpertic); + P_WriteINT32(save_p, ht->timer); } -static void SaveExecutorThinker(const thinker_t *th, const UINT8 type) +static void SaveExecutorThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const executor_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveLine(ht->line)); - WRITEUINT32(save_p, SaveMobjnum(ht->caller)); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT32(save_p, ht->timer); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveLine(ht->line)); + P_WriteUINT32(save_p, SaveMobjnum(ht->caller)); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteINT32(save_p, ht->timer); } -static void SaveDisappearThinker(const thinker_t *th, const UINT8 type) +static void SaveDisappearThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const disappear_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, ht->appeartime); - WRITEUINT32(save_p, ht->disappeartime); - WRITEUINT32(save_p, ht->offset); - WRITEUINT32(save_p, ht->timer); - WRITEINT32(save_p, ht->affectee); - WRITEINT32(save_p, ht->sourceline); - WRITEINT32(save_p, ht->exists); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, ht->appeartime); + P_WriteUINT32(save_p, ht->disappeartime); + P_WriteUINT32(save_p, ht->offset); + P_WriteUINT32(save_p, ht->timer); + P_WriteINT32(save_p, ht->affectee); + P_WriteINT32(save_p, ht->sourceline); + P_WriteINT32(save_p, ht->exists); } -static void SaveFadeThinker(const thinker_t *th, const UINT8 type) +static void SaveFadeThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const fade_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc)); - WRITEUINT32(save_p, ht->sectornum); - WRITEUINT32(save_p, ht->ffloornum); - WRITEINT32(save_p, ht->alpha); - WRITEINT16(save_p, ht->sourcevalue); - WRITEINT16(save_p, ht->destvalue); - WRITEINT16(save_p, ht->destlightlevel); - WRITEINT16(save_p, ht->speed); - WRITEUINT8(save_p, (UINT8)ht->ticbased); - WRITEINT32(save_p, ht->timer); - WRITEUINT8(save_p, ht->doexists); - WRITEUINT8(save_p, ht->dotranslucent); - WRITEUINT8(save_p, ht->dolighting); - WRITEUINT8(save_p, ht->docolormap); - WRITEUINT8(save_p, ht->docollision); - WRITEUINT8(save_p, ht->doghostfade); - WRITEUINT8(save_p, ht->exactalpha); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc)); + P_WriteUINT32(save_p, ht->sectornum); + P_WriteUINT32(save_p, ht->ffloornum); + P_WriteINT32(save_p, ht->alpha); + P_WriteINT16(save_p, ht->sourcevalue); + P_WriteINT16(save_p, ht->destvalue); + P_WriteINT16(save_p, ht->destlightlevel); + P_WriteINT16(save_p, ht->speed); + P_WriteUINT8(save_p, (UINT8)ht->ticbased); + P_WriteINT32(save_p, ht->timer); + P_WriteUINT8(save_p, ht->doexists); + P_WriteUINT8(save_p, ht->dotranslucent); + P_WriteUINT8(save_p, ht->dolighting); + P_WriteUINT8(save_p, ht->docolormap); + P_WriteUINT8(save_p, ht->docollision); + P_WriteUINT8(save_p, ht->doghostfade); + P_WriteUINT8(save_p, ht->exactalpha); } -static void SaveFadeColormapThinker(const thinker_t *th, const UINT8 type) +static void SaveFadeColormapThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const fadecolormap_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEUINT32(save_p, CheckAddNetColormapToList(ht->source_exc)); - WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc)); - WRITEUINT8(save_p, (UINT8)ht->ticbased); - WRITEINT32(save_p, ht->duration); - WRITEINT32(save_p, ht->timer); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteUINT32(save_p, CheckAddNetColormapToList(ht->source_exc)); + P_WriteUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc)); + P_WriteUINT8(save_p, (UINT8)ht->ticbased); + P_WriteINT32(save_p, ht->duration); + P_WriteINT32(save_p, ht->timer); } -static void SavePlaneDisplaceThinker(const thinker_t *th, const UINT8 type) +static void SavePlaneDisplaceThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const planedisplace_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->affectee); - WRITEINT32(save_p, ht->control); - WRITEFIXED(save_p, ht->last_height); - WRITEFIXED(save_p, ht->speed); - WRITEUINT8(save_p, ht->type); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->affectee); + P_WriteINT32(save_p, ht->control); + P_WriteFixed(save_p, ht->last_height); + P_WriteFixed(save_p, ht->speed); + P_WriteUINT8(save_p, ht->type); } -static inline void SaveDynamicLineSlopeThinker(const thinker_t *th, const UINT8 type) +static inline void SaveDynamicLineSlopeThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const dynlineplanethink_t* ht = (const void*)th; - WRITEUINT8(save_p, type); - WRITEUINT8(save_p, ht->type); - WRITEUINT32(save_p, SaveSlope(ht->slope)); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); - WRITEFIXED(save_p, ht->extent); + P_WriteUINT8(save_p, type); + P_WriteUINT8(save_p, ht->type); + P_WriteUINT32(save_p, SaveSlope(ht->slope)); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteFixed(save_p, ht->extent); } -static inline void SaveDynamicVertexSlopeThinker(const thinker_t *th, const UINT8 type) +static inline void SaveDynamicVertexSlopeThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { size_t i; const dynvertexplanethink_t* ht = (const void*)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSlope(ht->slope)); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSlope(ht->slope)); for (i = 0; i < 3; i++) - WRITEUINT32(save_p, SaveSector(ht->secs[i])); - WRITEMEM(save_p, ht->vex, sizeof(ht->vex)); - WRITEMEM(save_p, ht->origsecheights, sizeof(ht->origsecheights)); - WRITEMEM(save_p, ht->origvecheights, sizeof(ht->origvecheights)); - WRITEUINT8(save_p, ht->relative); + P_WriteUINT32(save_p, SaveSector(ht->secs[i])); + P_WriteMem(save_p, ht->vex, sizeof(ht->vex)); + P_WriteMem(save_p, ht->origsecheights, sizeof(ht->origsecheights)); + P_WriteMem(save_p, ht->origvecheights, sizeof(ht->origvecheights)); + P_WriteUINT8(save_p, ht->relative); } -static inline void SavePolyrotatetThinker(const thinker_t *th, const UINT8 type) +static inline void SavePolyrotatetThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const polyrotate_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->polyObjNum); - WRITEINT32(save_p, ht->speed); - WRITEINT32(save_p, ht->distance); - WRITEUINT8(save_p, ht->turnobjs); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->polyObjNum); + P_WriteINT32(save_p, ht->speed); + P_WriteINT32(save_p, ht->distance); + P_WriteUINT8(save_p, ht->turnobjs); } -static void SavePolymoveThinker(const thinker_t *th, const UINT8 type) +static void SavePolymoveThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const polymove_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->polyObjNum); - WRITEINT32(save_p, ht->speed); - WRITEFIXED(save_p, ht->momx); - WRITEFIXED(save_p, ht->momy); - WRITEINT32(save_p, ht->distance); - WRITEANGLE(save_p, ht->angle); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->polyObjNum); + P_WriteINT32(save_p, ht->speed); + P_WriteFixed(save_p, ht->momx); + P_WriteFixed(save_p, ht->momy); + P_WriteINT32(save_p, ht->distance); + P_WriteAngle(save_p, ht->angle); } -static void SavePolywaypointThinker(const thinker_t *th, UINT8 type) +static void SavePolywaypointThinker(save_t *save_p, const thinker_t *th, UINT8 type) { const polywaypoint_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->polyObjNum); - WRITEINT32(save_p, ht->speed); - WRITEINT32(save_p, ht->sequence); - WRITEINT32(save_p, ht->pointnum); - WRITEINT32(save_p, ht->direction); - WRITEUINT8(save_p, ht->returnbehavior); - WRITEUINT8(save_p, ht->continuous); - WRITEUINT8(save_p, ht->stophere); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->polyObjNum); + P_WriteINT32(save_p, ht->speed); + P_WriteINT32(save_p, ht->sequence); + P_WriteINT32(save_p, ht->pointnum); + P_WriteINT32(save_p, ht->direction); + P_WriteUINT8(save_p, ht->returnbehavior); + P_WriteUINT8(save_p, ht->continuous); + P_WriteUINT8(save_p, ht->stophere); } -static void SavePolyslidedoorThinker(const thinker_t *th, const UINT8 type) +static void SavePolyslidedoorThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const polyslidedoor_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->polyObjNum); - WRITEINT32(save_p, ht->delay); - WRITEINT32(save_p, ht->delayCount); - WRITEINT32(save_p, ht->initSpeed); - WRITEINT32(save_p, ht->speed); - WRITEINT32(save_p, ht->initDistance); - WRITEINT32(save_p, ht->distance); - WRITEUINT32(save_p, ht->initAngle); - WRITEUINT32(save_p, ht->angle); - WRITEUINT32(save_p, ht->revAngle); - WRITEFIXED(save_p, ht->momx); - WRITEFIXED(save_p, ht->momy); - WRITEUINT8(save_p, ht->closing); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->polyObjNum); + P_WriteINT32(save_p, ht->delay); + P_WriteINT32(save_p, ht->delayCount); + P_WriteINT32(save_p, ht->initSpeed); + P_WriteINT32(save_p, ht->speed); + P_WriteINT32(save_p, ht->initDistance); + P_WriteINT32(save_p, ht->distance); + P_WriteUINT32(save_p, ht->initAngle); + P_WriteUINT32(save_p, ht->angle); + P_WriteUINT32(save_p, ht->revAngle); + P_WriteFixed(save_p, ht->momx); + P_WriteFixed(save_p, ht->momy); + P_WriteUINT8(save_p, ht->closing); } -static void SavePolyswingdoorThinker(const thinker_t *th, const UINT8 type) +static void SavePolyswingdoorThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const polyswingdoor_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->polyObjNum); - WRITEINT32(save_p, ht->delay); - WRITEINT32(save_p, ht->delayCount); - WRITEINT32(save_p, ht->initSpeed); - WRITEINT32(save_p, ht->speed); - WRITEINT32(save_p, ht->initDistance); - WRITEINT32(save_p, ht->distance); - WRITEUINT8(save_p, ht->closing); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->polyObjNum); + P_WriteINT32(save_p, ht->delay); + P_WriteINT32(save_p, ht->delayCount); + P_WriteINT32(save_p, ht->initSpeed); + P_WriteINT32(save_p, ht->speed); + P_WriteINT32(save_p, ht->initDistance); + P_WriteINT32(save_p, ht->distance); + P_WriteUINT8(save_p, ht->closing); } -static void SavePolydisplaceThinker(const thinker_t *th, const UINT8 type) +static void SavePolydisplaceThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const polydisplace_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->polyObjNum); - WRITEUINT32(save_p, SaveSector(ht->controlSector)); - WRITEFIXED(save_p, ht->dx); - WRITEFIXED(save_p, ht->dy); - WRITEFIXED(save_p, ht->oldHeights); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->polyObjNum); + P_WriteUINT32(save_p, SaveSector(ht->controlSector)); + P_WriteFixed(save_p, ht->dx); + P_WriteFixed(save_p, ht->dy); + P_WriteFixed(save_p, ht->oldHeights); } -static void SavePolyrotdisplaceThinker(const thinker_t *th, const UINT8 type) +static void SavePolyrotdisplaceThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const polyrotdisplace_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->polyObjNum); - WRITEUINT32(save_p, SaveSector(ht->controlSector)); - WRITEFIXED(save_p, ht->rotscale); - WRITEUINT8(save_p, ht->turnobjs); - WRITEFIXED(save_p, ht->oldHeights); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->polyObjNum); + P_WriteUINT32(save_p, SaveSector(ht->controlSector)); + P_WriteFixed(save_p, ht->rotscale); + P_WriteUINT8(save_p, ht->turnobjs); + P_WriteFixed(save_p, ht->oldHeights); } -static void SavePolyfadeThinker(const thinker_t *th, const UINT8 type) +static void SavePolyfadeThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const polyfade_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->polyObjNum); - WRITEINT32(save_p, ht->sourcevalue); - WRITEINT32(save_p, ht->destvalue); - WRITEUINT8(save_p, (UINT8)ht->docollision); - WRITEUINT8(save_p, (UINT8)ht->doghostfade); - WRITEUINT8(save_p, (UINT8)ht->ticbased); - WRITEINT32(save_p, ht->duration); - WRITEINT32(save_p, ht->timer); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->polyObjNum); + P_WriteINT32(save_p, ht->sourcevalue); + P_WriteINT32(save_p, ht->destvalue); + P_WriteUINT8(save_p, (UINT8)ht->docollision); + P_WriteUINT8(save_p, (UINT8)ht->doghostfade); + P_WriteUINT8(save_p, (UINT8)ht->ticbased); + P_WriteINT32(save_p, ht->duration); + P_WriteINT32(save_p, ht->timer); } -static void P_NetArchiveThinkers(void) +static void P_NetArchiveThinkers(save_t *save_p) { const thinker_t *th; UINT32 i; - WRITEUINT32(save_p, ARCHIVEBLOCK_THINKERS); + P_WriteUINT32(save_p, ARCHIVEBLOCK_THINKERS); for (i = 0; i < NUM_THINKERLISTS; i++) { @@ -2675,13 +2972,12 @@ static void P_NetArchiveThinkers(void) // save off the current thinkers for (th = thlist[i].next; th != &thlist[i]; th = th->next) { - if (!(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed - || th->function.acp1 == (actionf_p1)P_NullPrecipThinker)) + if (!(th->removing || th->function.acp1 == (actionf_p1)P_NullPrecipThinker)) numsaved++; if (th->function.acp1 == (actionf_p1)P_MobjThinker) { - SaveMobjThinker(th, tc_mobj); + SaveMobjThinker(save_p, th, tc_mobj); continue; } #ifdef PARANOIA @@ -2689,213 +2985,213 @@ static void P_NetArchiveThinkers(void) #endif else if (th->function.acp1 == (actionf_p1)T_MoveCeiling) { - SaveCeilingThinker(th, tc_ceiling); + SaveCeilingThinker(save_p, th, tc_ceiling); continue; } else if (th->function.acp1 == (actionf_p1)T_CrushCeiling) { - SaveCeilingThinker(th, tc_crushceiling); + SaveCeilingThinker(save_p, th, tc_crushceiling); continue; } else if (th->function.acp1 == (actionf_p1)T_MoveFloor) { - SaveFloormoveThinker(th, tc_floor); + SaveFloormoveThinker(save_p, th, tc_floor); continue; } else if (th->function.acp1 == (actionf_p1)T_LightningFlash) { - SaveLightflashThinker(th, tc_flash); + SaveLightflashThinker(save_p, th, tc_flash); continue; } else if (th->function.acp1 == (actionf_p1)T_StrobeFlash) { - SaveStrobeThinker(th, tc_strobe); + SaveStrobeThinker(save_p, th, tc_strobe); continue; } else if (th->function.acp1 == (actionf_p1)T_Glow) { - SaveGlowThinker(th, tc_glow); + SaveGlowThinker(save_p, th, tc_glow); continue; } else if (th->function.acp1 == (actionf_p1)T_FireFlicker) { - SaveFireflickerThinker(th, tc_fireflicker); + SaveFireflickerThinker(save_p, th, tc_fireflicker); continue; } else if (th->function.acp1 == (actionf_p1)T_MoveElevator) { - SaveElevatorThinker(th, tc_elevator); + SaveElevatorThinker(save_p, th, tc_elevator); continue; } else if (th->function.acp1 == (actionf_p1)T_ContinuousFalling) { - SaveContinuousFallThinker(th, tc_continuousfalling); + SaveContinuousFallThinker(save_p, th, tc_continuousfalling); continue; } else if (th->function.acp1 == (actionf_p1)T_ThwompSector) { - SaveThwompThinker(th, tc_thwomp); + SaveThwompThinker(save_p, th, tc_thwomp); continue; } else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector) { - SaveNoEnemiesThinker(th, tc_noenemies); + SaveNoEnemiesThinker(save_p, th, tc_noenemies); continue; } else if (th->function.acp1 == (actionf_p1)T_EachTimeThinker) { - SaveEachTimeThinker(th, tc_eachtime); + SaveEachTimeThinker(save_p, th, tc_eachtime); continue; } else if (th->function.acp1 == (actionf_p1)T_RaiseSector) { - SaveRaiseThinker(th, tc_raisesector); + SaveRaiseThinker(save_p, th, tc_raisesector); continue; } else if (th->function.acp1 == (actionf_p1)T_CameraScanner) { - SaveElevatorThinker(th, tc_camerascanner); + SaveElevatorThinker(save_p, th, tc_camerascanner); continue; } else if (th->function.acp1 == (actionf_p1)T_Scroll) { - SaveScrollThinker(th, tc_scroll); + SaveScrollThinker(save_p, th, tc_scroll); continue; } else if (th->function.acp1 == (actionf_p1)T_Friction) { - SaveFrictionThinker(th, tc_friction); + SaveFrictionThinker(save_p, th, tc_friction); continue; } else if (th->function.acp1 == (actionf_p1)T_Pusher) { - SavePusherThinker(th, tc_pusher); + SavePusherThinker(save_p, th, tc_pusher); continue; } else if (th->function.acp1 == (actionf_p1)T_BounceCheese) { - SaveBounceCheeseThinker(th, tc_bouncecheese); + SaveBounceCheeseThinker(save_p, th, tc_bouncecheese); continue; } else if (th->function.acp1 == (actionf_p1)T_StartCrumble) { - SaveCrumbleThinker(th, tc_startcrumble); + SaveCrumbleThinker(save_p, th, tc_startcrumble); continue; } else if (th->function.acp1 == (actionf_p1)T_MarioBlock) { - SaveMarioBlockThinker(th, tc_marioblock); + SaveMarioBlockThinker(save_p, th, tc_marioblock); continue; } else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker) { - SaveMarioCheckThinker(th, tc_marioblockchecker); + SaveMarioCheckThinker(save_p, th, tc_marioblockchecker); continue; } else if (th->function.acp1 == (actionf_p1)T_FloatSector) { - SaveFloatThinker(th, tc_floatsector); + SaveFloatThinker(save_p, th, tc_floatsector); continue; } else if (th->function.acp1 == (actionf_p1)T_LaserFlash) { - SaveLaserThinker(th, tc_laserflash); + SaveLaserThinker(save_p, th, tc_laserflash); continue; } else if (th->function.acp1 == (actionf_p1)T_LightFade) { - SaveLightlevelThinker(th, tc_lightfade); + SaveLightlevelThinker(save_p, th, tc_lightfade); continue; } else if (th->function.acp1 == (actionf_p1)T_ExecutorDelay) { - SaveExecutorThinker(th, tc_executor); + SaveExecutorThinker(save_p, th, tc_executor); continue; } else if (th->function.acp1 == (actionf_p1)T_Disappear) { - SaveDisappearThinker(th, tc_disappear); + SaveDisappearThinker(save_p, th, tc_disappear); continue; } else if (th->function.acp1 == (actionf_p1)T_Fade) { - SaveFadeThinker(th, tc_fade); + SaveFadeThinker(save_p, th, tc_fade); continue; } else if (th->function.acp1 == (actionf_p1)T_FadeColormap) { - SaveFadeColormapThinker(th, tc_fadecolormap); + SaveFadeColormapThinker(save_p, th, tc_fadecolormap); continue; } else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace) { - SavePlaneDisplaceThinker(th, tc_planedisplace); + SavePlaneDisplaceThinker(save_p, th, tc_planedisplace); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate) { - SavePolyrotatetThinker(th, tc_polyrotate); + SavePolyrotatetThinker(save_p, th, tc_polyrotate); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyObjMove) { - SavePolymoveThinker(th, tc_polymove); + SavePolymoveThinker(save_p, th, tc_polymove); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyObjWaypoint) { - SavePolywaypointThinker(th, tc_polywaypoint); + SavePolywaypointThinker(save_p, th, tc_polywaypoint); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyDoorSlide) { - SavePolyslidedoorThinker(th, tc_polyslidedoor); + SavePolyslidedoorThinker(save_p, th, tc_polyslidedoor); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyDoorSwing) { - SavePolyswingdoorThinker(th, tc_polyswingdoor); + SavePolyswingdoorThinker(save_p, th, tc_polyswingdoor); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyObjFlag) { - SavePolymoveThinker(th, tc_polyflag); + SavePolymoveThinker(save_p, th, tc_polyflag); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyObjDisplace) { - SavePolydisplaceThinker(th, tc_polydisplace); + SavePolydisplaceThinker(save_p, th, tc_polydisplace); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyObjRotDisplace) { - SavePolyrotdisplaceThinker(th, tc_polyrotdisplace); + SavePolyrotdisplaceThinker(save_p, th, tc_polyrotdisplace); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyObjFade) { - SavePolyfadeThinker(th, tc_polyfade); + SavePolyfadeThinker(save_p, th, tc_polyfade); continue; } else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeLine) { - SaveDynamicLineSlopeThinker(th, tc_dynslopeline); + SaveDynamicLineSlopeThinker(save_p, th, tc_dynslopeline); continue; } else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeVert) { - SaveDynamicVertexSlopeThinker(th, tc_dynslopevert); + SaveDynamicVertexSlopeThinker(save_p, th, tc_dynslopevert); continue; } #ifdef PARANOIA else - I_Assert(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed); // wait garbage collection + I_Assert(th->removing); // wait garbage collection #endif } CONS_Debug(DBG_NETPLAY, "%u thinkers saved in list %d\n", numsaved, i); - WRITEUINT8(save_p, tc_end); + P_WriteUINT8(save_p, tc_end); } } @@ -2910,7 +3206,7 @@ mobj_t *P_FindNewPosition(UINT32 oldposition) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mobj = (mobj_t *)th; @@ -2959,7 +3255,7 @@ static inline pslope_t *LoadSlope(UINT32 slopeid) return NULL; } -static thinker_t* LoadMobjThinker(actionf_p1 thinker) +static thinker_t* LoadMobjThinker(save_t *save_p, actionf_p1 thinker) { thinker_t *next; mobj_t *mobj; @@ -2969,35 +3265,35 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) fixed_t z, floorz, ceilingz; ffloor_t *floorrover = NULL, *ceilingrover = NULL; - diff = READUINT32(save_p); + diff = P_ReadUINT32(save_p); if (diff & MD_MORE) - diff2 = READUINT32(save_p); + diff2 = P_ReadUINT32(save_p); else diff2 = 0; - next = (void *)(size_t)READUINT32(save_p); + next = (void *)(size_t)P_ReadUINT32(save_p); - z = READFIXED(save_p); // Force this so 3dfloor problems don't arise. - floorz = READFIXED(save_p); - ceilingz = READFIXED(save_p); + z = P_ReadFixed(save_p); // Force this so 3dfloor problems don't arise. + floorz = P_ReadFixed(save_p); + ceilingz = P_ReadFixed(save_p); if (diff2 & MD2_FLOORROVER) { - sector_t *sec = LoadSector(READUINT32(save_p)); - UINT16 id = READUINT16(save_p); + sector_t *sec = LoadSector(P_ReadUINT32(save_p)); + UINT16 id = P_ReadUINT16(save_p); floorrover = P_GetFFloorByID(sec, id); } if (diff2 & MD2_CEILINGROVER) { - sector_t *sec = LoadSector(READUINT32(save_p)); - UINT16 id = READUINT16(save_p); + sector_t *sec = LoadSector(P_ReadUINT32(save_p)); + UINT16 id = P_ReadUINT16(save_p); ceilingrover = P_GetFFloorByID(sec, id); } if (diff & MD_SPAWNPOINT) { - UINT16 spawnpointnum = READUINT16(save_p); + UINT16 spawnpointnum = P_ReadUINT16(save_p); if (mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case { @@ -3023,7 +3319,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->ceilingrover = ceilingrover; if (diff & MD_TYPE) - mobj->type = READUINT32(save_p); + mobj->type = P_ReadUINT32(save_p); else { for (i = 0; i < NUMMOBJTYPES; i++) @@ -3042,11 +3338,11 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->info = &mobjinfo[mobj->type]; if (diff & MD_POS) { - mobj->x = READFIXED(save_p); - mobj->y = READFIXED(save_p); - mobj->angle = READANGLE(save_p); - mobj->pitch = READANGLE(save_p); - mobj->roll = READANGLE(save_p); + mobj->x = P_ReadFixed(save_p); + mobj->y = P_ReadFixed(save_p); + mobj->angle = P_ReadAngle(save_p); + mobj->pitch = P_ReadAngle(save_p); + mobj->roll = P_ReadAngle(save_p); } else { @@ -3058,47 +3354,47 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) } if (diff & MD_MOM) { - mobj->momx = READFIXED(save_p); - mobj->momy = READFIXED(save_p); - mobj->momz = READFIXED(save_p); - mobj->pmomz = READFIXED(save_p); + mobj->momx = P_ReadFixed(save_p); + mobj->momy = P_ReadFixed(save_p); + mobj->momz = P_ReadFixed(save_p); + mobj->pmomz = P_ReadFixed(save_p); } // otherwise they're zero, and the memset took care of it if (diff & MD_RADIUS) - mobj->radius = READFIXED(save_p); + mobj->radius = P_ReadFixed(save_p); else mobj->radius = mobj->info->radius; if (diff & MD_HEIGHT) - mobj->height = READFIXED(save_p); + mobj->height = P_ReadFixed(save_p); else mobj->height = mobj->info->height; if (diff & MD_FLAGS) - mobj->flags = READUINT32(save_p); + mobj->flags = P_ReadUINT32(save_p); else mobj->flags = mobj->info->flags; if (diff & MD_FLAGS2) - mobj->flags2 = READUINT32(save_p); + mobj->flags2 = P_ReadUINT32(save_p); if (diff & MD_HEALTH) - mobj->health = READINT32(save_p); + mobj->health = P_ReadINT32(save_p); else mobj->health = mobj->info->spawnhealth; if (diff & MD_RTIME) - mobj->reactiontime = READINT32(save_p); + mobj->reactiontime = P_ReadINT32(save_p); else mobj->reactiontime = mobj->info->reactiontime; if (diff & MD_STATE) - mobj->state = &states[READUINT16(save_p)]; + mobj->state = &states[P_ReadUINT16(save_p)]; else mobj->state = &states[mobj->info->spawnstate]; if (diff & MD_TICS) - mobj->tics = READINT32(save_p); + mobj->tics = P_ReadINT32(save_p); else mobj->tics = mobj->state->tics; if (diff & MD_SPRITE) { - mobj->sprite = READUINT16(save_p); + mobj->sprite = P_ReadUINT16(save_p); if (mobj->sprite == SPR_PLAY) - mobj->sprite2 = READUINT16(save_p); + mobj->sprite2 = P_ReadUINT16(save_p); } else { mobj->sprite = mobj->state->sprite; @@ -3107,8 +3403,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) } if (diff & MD_FRAME) { - mobj->frame = READUINT32(save_p); - mobj->anim_duration = READUINT16(save_p); + mobj->frame = P_ReadUINT32(save_p); + mobj->anim_duration = P_ReadUINT16(save_p); } else { @@ -3116,128 +3412,132 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->anim_duration = (UINT16)mobj->state->var2; } if (diff & MD_EFLAGS) - mobj->eflags = READUINT16(save_p); + mobj->eflags = P_ReadUINT16(save_p); if (diff & MD_PLAYER) { - i = READUINT8(save_p); + i = P_ReadUINT8(save_p); mobj->player = &players[i]; mobj->player->mo = mobj; } if (diff & MD_MOVEDIR) - mobj->movedir = READANGLE(save_p); + mobj->movedir = P_ReadAngle(save_p); if (diff & MD_MOVECOUNT) - mobj->movecount = READINT32(save_p); + mobj->movecount = P_ReadINT32(save_p); if (diff & MD_THRESHOLD) - mobj->threshold = READINT32(save_p); + mobj->threshold = P_ReadINT32(save_p); if (diff & MD_LASTLOOK) - mobj->lastlook = READINT32(save_p); + mobj->lastlook = P_ReadINT32(save_p); else mobj->lastlook = -1; if (diff & MD_TARGET) - mobj->target = (mobj_t *)(size_t)READUINT32(save_p); + mobj->target = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (diff & MD_TRACER) - mobj->tracer = (mobj_t *)(size_t)READUINT32(save_p); + mobj->tracer = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (diff & MD_FRICTION) - mobj->friction = READFIXED(save_p); + mobj->friction = P_ReadFixed(save_p); else mobj->friction = ORIG_FRICTION; if (diff & MD_MOVEFACTOR) - mobj->movefactor = READFIXED(save_p); + mobj->movefactor = P_ReadFixed(save_p); else mobj->movefactor = FRACUNIT; if (diff & MD_FUSE) - mobj->fuse = READINT32(save_p); + mobj->fuse = P_ReadINT32(save_p); if (diff & MD_WATERTOP) - mobj->watertop = READFIXED(save_p); + mobj->watertop = P_ReadFixed(save_p); if (diff & MD_WATERBOTTOM) - mobj->waterbottom = READFIXED(save_p); + mobj->waterbottom = P_ReadFixed(save_p); if (diff & MD_SCALE) - mobj->scale = READFIXED(save_p); + mobj->scale = P_ReadFixed(save_p); else mobj->scale = FRACUNIT; if (diff & MD_DSCALE) - mobj->destscale = READFIXED(save_p); + mobj->destscale = P_ReadFixed(save_p); else mobj->destscale = mobj->scale; if (diff2 & MD2_SCALESPEED) - mobj->scalespeed = READFIXED(save_p); + mobj->scalespeed = P_ReadFixed(save_p); else mobj->scalespeed = FRACUNIT/12; if (diff2 & MD2_CUSVAL) - mobj->cusval = READINT32(save_p); + mobj->cusval = P_ReadINT32(save_p); if (diff2 & MD2_CVMEM) - mobj->cvmem = READINT32(save_p); + mobj->cvmem = P_ReadINT32(save_p); if (diff2 & MD2_SKIN) - mobj->skin = skins[READUINT8(save_p)]; + mobj->skin = skins[P_ReadUINT8(save_p)]; if (diff2 & MD2_COLOR) - mobj->color = READUINT16(save_p); + mobj->color = P_ReadUINT16(save_p); if (diff2 & MD2_EXTVAL1) - mobj->extravalue1 = READINT32(save_p); + mobj->extravalue1 = P_ReadINT32(save_p); if (diff2 & MD2_EXTVAL2) - mobj->extravalue2 = READINT32(save_p); + mobj->extravalue2 = P_ReadINT32(save_p); if (diff2 & MD2_HNEXT) - mobj->hnext = (mobj_t *)(size_t)READUINT32(save_p); + mobj->hnext = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (diff2 & MD2_HPREV) - mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p); + mobj->hprev = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (diff2 & MD2_SLOPE) - mobj->standingslope = P_SlopeById(READUINT16(save_p)); + mobj->standingslope = P_SlopeById(P_ReadUINT16(save_p)); if (diff2 & MD2_COLORIZED) - mobj->colorized = READUINT8(save_p); + mobj->colorized = P_ReadUINT8(save_p); if (diff2 & MD2_MIRRORED) - mobj->mirrored = READUINT8(save_p); + mobj->mirrored = P_ReadUINT8(save_p); if (diff2 & MD2_SPRITEROLL) - mobj->spriteroll = READANGLE(save_p); + mobj->spriteroll = P_ReadAngle(save_p); if (diff2 & MD2_SHADOWSCALE) - mobj->shadowscale = READFIXED(save_p); + mobj->shadowscale = P_ReadFixed(save_p); if (diff2 & MD2_RENDERFLAGS) - mobj->renderflags = READUINT32(save_p); + mobj->renderflags = P_ReadUINT32(save_p); if (diff2 & MD2_BLENDMODE) - mobj->blendmode = READINT32(save_p); + mobj->blendmode = P_ReadINT32(save_p); else mobj->blendmode = AST_TRANSLUCENT; if (diff2 & MD2_SPRITEXSCALE) - mobj->spritexscale = READFIXED(save_p); + mobj->spritexscale = P_ReadFixed(save_p); else mobj->spritexscale = FRACUNIT; if (diff2 & MD2_SPRITEYSCALE) - mobj->spriteyscale = READFIXED(save_p); + mobj->spriteyscale = P_ReadFixed(save_p); else mobj->spriteyscale = FRACUNIT; if (diff2 & MD2_SPRITEXOFFSET) - mobj->spritexoffset = READFIXED(save_p); + mobj->spritexoffset = P_ReadFixed(save_p); if (diff2 & MD2_SPRITEYOFFSET) - mobj->spriteyoffset = READFIXED(save_p); + mobj->spriteyoffset = P_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->zdelta = P_ReadFixed(save_p); + slope->zangle = P_ReadAngle(save_p); + slope->xydirection = P_ReadAngle(save_p); - slope->o.x = READFIXED(save_p); - slope->o.y = READFIXED(save_p); - slope->o.z = READFIXED(save_p); + slope->o.x = P_ReadFixed(save_p); + slope->o.y = P_ReadFixed(save_p); + slope->o.z = P_ReadFixed(save_p); - slope->d.x = READFIXED(save_p); - slope->d.y = READFIXED(save_p); + slope->d.x = P_ReadFixed(save_p); + slope->d.y = P_ReadFixed(save_p); - slope->normal.x = READFIXED(save_p); - slope->normal.y = READFIXED(save_p); - slope->normal.z = READFIXED(save_p); + slope->normal.x = P_ReadFixed(save_p); + slope->normal.y = P_ReadFixed(save_p); + slope->normal.z = P_ReadFixed(save_p); slope->moved = true; } if (diff2 & MD2_DRAWONLYFORPLAYER) - mobj->drawonlyforplayer = &players[READUINT8(save_p)]; + mobj->drawonlyforplayer = &players[P_ReadUINT8(save_p)]; if (diff2 & MD2_DONTDRAWFORVIEWMOBJ) - mobj->dontdrawforviewmobj = (mobj_t *)(size_t)READUINT32(save_p); + mobj->dontdrawforviewmobj = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (diff2 & MD2_DISPOFFSET) - mobj->dispoffset = READINT32(save_p); + mobj->dispoffset = P_ReadINT32(save_p); else mobj->dispoffset = mobj->info->dispoffset; if (diff2 & MD2_TRANSLATION) - mobj->translation = READUINT16(save_p); + mobj->translation = P_ReadUINT16(save_p); + if (diff2 & MD2_ALPHA) + mobj->alpha = P_ReadFixed(save_p); + else + mobj->alpha = FRACUNIT; if (diff & MD_REDFLAG) { @@ -3253,7 +3553,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) // set sprev, snext, bprev, bnext, subsector P_SetThingPosition(mobj); - mobj->mobjnum = READUINT32(save_p); + mobj->mobjnum = P_ReadUINT32(save_p); if (mobj->player) { @@ -3282,25 +3582,25 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) return &mobj->thinker; } -static thinker_t* LoadNoEnemiesThinker(actionf_p1 thinker) +static thinker_t* LoadNoEnemiesThinker(save_t *save_p, actionf_p1 thinker) { noenemies_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save_p)); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); return &ht->thinker; } -static thinker_t* LoadBounceCheeseThinker(actionf_p1 thinker) +static thinker_t* LoadBounceCheeseThinker(save_t *save_p, actionf_p1 thinker) { bouncecheese_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save_p)); - ht->sector = LoadSector(READUINT32(save_p)); - ht->speed = READFIXED(save_p); - ht->distance = READFIXED(save_p); - ht->floorwasheight = READFIXED(save_p); - ht->ceilingwasheight = READFIXED(save_p); - ht->low = READCHAR(save_p); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->speed = P_ReadFixed(save_p); + ht->distance = P_ReadFixed(save_p); + ht->floorwasheight = P_ReadFixed(save_p); + ht->ceilingwasheight = P_ReadFixed(save_p); + ht->low = P_ReadChar(save_p); if (ht->sector) ht->sector->ceilingdata = ht; @@ -3308,16 +3608,16 @@ static thinker_t* LoadBounceCheeseThinker(actionf_p1 thinker) return &ht->thinker; } -static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker) +static thinker_t* LoadContinuousFallThinker(save_t *save_p, actionf_p1 thinker) { continuousfall_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->speed = READFIXED(save_p); - ht->direction = READINT32(save_p); - ht->floorstartheight = READFIXED(save_p); - ht->ceilingstartheight = READFIXED(save_p); - ht->destheight = READFIXED(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->speed = P_ReadFixed(save_p); + ht->direction = P_ReadINT32(save_p); + ht->floorstartheight = P_ReadFixed(save_p); + ht->ceilingstartheight = P_ReadFixed(save_p); + ht->destheight = P_ReadFixed(save_p); if (ht->sector) { @@ -3328,16 +3628,16 @@ static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker) return &ht->thinker; } -static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker) +static thinker_t* LoadMarioBlockThinker(save_t *save_p, actionf_p1 thinker) { mariothink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->speed = READFIXED(save_p); - ht->direction = READINT32(save_p); - ht->floorstartheight = READFIXED(save_p); - ht->ceilingstartheight = READFIXED(save_p); - ht->tag = READINT16(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->speed = P_ReadFixed(save_p); + ht->direction = P_ReadINT32(save_p); + ht->floorstartheight = P_ReadFixed(save_p); + ht->ceilingstartheight = P_ReadFixed(save_p); + ht->tag = P_ReadINT16(save_p); if (ht->sector) { @@ -3348,29 +3648,29 @@ static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker) return &ht->thinker; } -static thinker_t* LoadMarioCheckThinker(actionf_p1 thinker) +static thinker_t* LoadMarioCheckThinker(save_t *save_p, actionf_p1 thinker) { mariocheck_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save_p)); - ht->sector = LoadSector(READUINT32(save_p)); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); + ht->sector = LoadSector(P_ReadUINT32(save_p)); return &ht->thinker; } -static thinker_t* LoadThwompThinker(actionf_p1 thinker) +static thinker_t* LoadThwompThinker(save_t *save_p, actionf_p1 thinker) { thwomp_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save_p)); - ht->sector = LoadSector(READUINT32(save_p)); - ht->crushspeed = READFIXED(save_p); - ht->retractspeed = READFIXED(save_p); - ht->direction = READINT32(save_p); - ht->floorstartheight = READFIXED(save_p); - ht->ceilingstartheight = READFIXED(save_p); - ht->delay = READINT32(save_p); - ht->tag = READINT16(save_p); - ht->sound = READUINT16(save_p); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->crushspeed = P_ReadFixed(save_p); + ht->retractspeed = P_ReadFixed(save_p); + ht->direction = P_ReadINT32(save_p); + ht->floorstartheight = P_ReadFixed(save_p); + ht->ceilingstartheight = P_ReadFixed(save_p); + ht->delay = P_ReadINT32(save_p); + ht->tag = P_ReadINT16(save_p); + ht->sound = P_ReadUINT16(save_p); if (ht->sector) { @@ -3381,163 +3681,163 @@ static thinker_t* LoadThwompThinker(actionf_p1 thinker) return &ht->thinker; } -static thinker_t* LoadFloatThinker(actionf_p1 thinker) +static thinker_t* LoadFloatThinker(save_t *save_p, actionf_p1 thinker) { floatthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save_p)); - ht->sector = LoadSector(READUINT32(save_p)); - ht->tag = READINT16(save_p); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->tag = P_ReadINT16(save_p); return &ht->thinker; } -static thinker_t* LoadEachTimeThinker(actionf_p1 thinker) +static thinker_t* LoadEachTimeThinker(save_t *save_p, actionf_p1 thinker) { size_t i; eachtime_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save_p)); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); for (i = 0; i < MAXPLAYERS; i++) { - ht->playersInArea[i] = READCHAR(save_p); + ht->playersInArea[i] = P_ReadChar(save_p); } - ht->triggerOnExit = READCHAR(save_p); + ht->triggerOnExit = P_ReadChar(save_p); return &ht->thinker; } -static thinker_t* LoadRaiseThinker(actionf_p1 thinker) +static thinker_t* LoadRaiseThinker(save_t *save_p, actionf_p1 thinker) { raise_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->tag = READINT16(save_p); - ht->sector = LoadSector(READUINT32(save_p)); - ht->ceilingbottom = READFIXED(save_p); - ht->ceilingtop = READFIXED(save_p); - ht->basespeed = READFIXED(save_p); - ht->extraspeed = READFIXED(save_p); - ht->shaketimer = READUINT8(save_p); - ht->flags = READUINT8(save_p); + ht->tag = P_ReadINT16(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->ceilingbottom = P_ReadFixed(save_p); + ht->ceilingtop = P_ReadFixed(save_p); + ht->basespeed = P_ReadFixed(save_p); + ht->extraspeed = P_ReadFixed(save_p); + ht->shaketimer = P_ReadUINT8(save_p); + ht->flags = P_ReadUINT8(save_p); return &ht->thinker; } -static thinker_t* LoadCeilingThinker(actionf_p1 thinker) +static thinker_t* LoadCeilingThinker(save_t *save_p, actionf_p1 thinker) { ceiling_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->type = READUINT8(save_p); - ht->sector = LoadSector(READUINT32(save_p)); - ht->bottomheight = READFIXED(save_p); - ht->topheight = READFIXED(save_p); - ht->speed = READFIXED(save_p); - ht->delay = READFIXED(save_p); - ht->delaytimer = READFIXED(save_p); - ht->crush = READUINT8(save_p); - ht->texture = READINT32(save_p); - ht->direction = READINT32(save_p); - ht->tag = READINT16(save_p); - ht->origspeed = READFIXED(save_p); - ht->sourceline = READFIXED(save_p); + ht->type = P_ReadUINT8(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->bottomheight = P_ReadFixed(save_p); + ht->topheight = P_ReadFixed(save_p); + ht->speed = P_ReadFixed(save_p); + ht->delay = P_ReadFixed(save_p); + ht->delaytimer = P_ReadFixed(save_p); + ht->crush = P_ReadUINT8(save_p); + ht->texture = P_ReadINT32(save_p); + ht->direction = P_ReadINT32(save_p); + ht->tag = P_ReadINT16(save_p); + ht->origspeed = P_ReadFixed(save_p); + ht->sourceline = P_ReadFixed(save_p); if (ht->sector) ht->sector->ceilingdata = ht; return &ht->thinker; } -static thinker_t* LoadFloormoveThinker(actionf_p1 thinker) +static thinker_t* LoadFloormoveThinker(save_t *save_p, actionf_p1 thinker) { floormove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->type = READUINT8(save_p); - ht->crush = READUINT8(save_p); - ht->sector = LoadSector(READUINT32(save_p)); - ht->direction = READINT32(save_p); - ht->texture = READINT32(save_p); - ht->floordestheight = READFIXED(save_p); - ht->speed = READFIXED(save_p); - ht->origspeed = READFIXED(save_p); - ht->delay = READFIXED(save_p); - ht->delaytimer = READFIXED(save_p); - ht->tag = READINT16(save_p); - ht->sourceline = READFIXED(save_p); + ht->type = P_ReadUINT8(save_p); + ht->crush = P_ReadUINT8(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->direction = P_ReadINT32(save_p); + ht->texture = P_ReadINT32(save_p); + ht->floordestheight = P_ReadFixed(save_p); + ht->speed = P_ReadFixed(save_p); + ht->origspeed = P_ReadFixed(save_p); + ht->delay = P_ReadFixed(save_p); + ht->delaytimer = P_ReadFixed(save_p); + ht->tag = P_ReadINT16(save_p); + ht->sourceline = P_ReadFixed(save_p); if (ht->sector) ht->sector->floordata = ht; return &ht->thinker; } -static thinker_t* LoadLightflashThinker(actionf_p1 thinker) +static thinker_t* LoadLightflashThinker(save_t *save_p, actionf_p1 thinker) { lightflash_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->maxlight = READINT32(save_p); - ht->minlight = READINT32(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->maxlight = P_ReadINT32(save_p); + ht->minlight = P_ReadINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; return &ht->thinker; } -static thinker_t* LoadStrobeThinker(actionf_p1 thinker) +static thinker_t* LoadStrobeThinker(save_t *save_p, actionf_p1 thinker) { strobe_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->count = READINT32(save_p); - ht->minlight = READINT16(save_p); - ht->maxlight = READINT16(save_p); - ht->darktime = READINT32(save_p); - ht->brighttime = READINT32(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->count = P_ReadINT32(save_p); + ht->minlight = P_ReadINT16(save_p); + ht->maxlight = P_ReadINT16(save_p); + ht->darktime = P_ReadINT32(save_p); + ht->brighttime = P_ReadINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; return &ht->thinker; } -static thinker_t* LoadGlowThinker(actionf_p1 thinker) +static thinker_t* LoadGlowThinker(save_t *save_p, actionf_p1 thinker) { glow_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->minlight = READINT16(save_p); - ht->maxlight = READINT16(save_p); - ht->direction = READINT16(save_p); - ht->speed = READINT16(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->minlight = P_ReadINT16(save_p); + ht->maxlight = P_ReadINT16(save_p); + ht->direction = P_ReadINT16(save_p); + ht->speed = P_ReadINT16(save_p); if (ht->sector) ht->sector->lightingdata = ht; return &ht->thinker; } -static thinker_t* LoadFireflickerThinker(actionf_p1 thinker) +static thinker_t* LoadFireflickerThinker(save_t *save_p, actionf_p1 thinker) { fireflicker_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->count = READINT32(save_p); - ht->resetcount = READINT32(save_p); - ht->maxlight = READINT16(save_p); - ht->minlight = READINT16(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->count = P_ReadINT32(save_p); + ht->resetcount = P_ReadINT32(save_p); + ht->maxlight = P_ReadINT16(save_p); + ht->minlight = P_ReadINT16(save_p); if (ht->sector) ht->sector->lightingdata = ht; return &ht->thinker; } -static thinker_t* LoadElevatorThinker(actionf_p1 thinker, boolean setplanedata) +static thinker_t* LoadElevatorThinker(save_t *save_p, actionf_p1 thinker, boolean setplanedata) { elevator_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->type = READUINT8(save_p); - ht->sector = LoadSector(READUINT32(save_p)); - ht->actionsector = LoadSector(READUINT32(save_p)); - ht->direction = READINT32(save_p); - ht->floordestheight = READFIXED(save_p); - ht->ceilingdestheight = READFIXED(save_p); - ht->speed = READFIXED(save_p); - ht->origspeed = READFIXED(save_p); - ht->low = READFIXED(save_p); - ht->high = READFIXED(save_p); - ht->distance = READFIXED(save_p); - ht->delay = READFIXED(save_p); - ht->delaytimer = READFIXED(save_p); - ht->floorwasheight = READFIXED(save_p); - ht->ceilingwasheight = READFIXED(save_p); - ht->sourceline = LoadLine(READUINT32(save_p)); + ht->type = P_ReadUINT8(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->actionsector = LoadSector(P_ReadUINT32(save_p)); + ht->direction = P_ReadINT32(save_p); + ht->floordestheight = P_ReadFixed(save_p); + ht->ceilingdestheight = P_ReadFixed(save_p); + ht->speed = P_ReadFixed(save_p); + ht->origspeed = P_ReadFixed(save_p); + ht->low = P_ReadFixed(save_p); + ht->high = P_ReadFixed(save_p); + ht->distance = P_ReadFixed(save_p); + ht->delay = P_ReadFixed(save_p); + ht->delaytimer = P_ReadFixed(save_p); + ht->floorwasheight = P_ReadFixed(save_p); + ht->ceilingwasheight = P_ReadFixed(save_p); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); if (ht->sector && setplanedata) { @@ -3548,21 +3848,21 @@ static thinker_t* LoadElevatorThinker(actionf_p1 thinker, boolean setplanedata) return &ht->thinker; } -static thinker_t* LoadCrumbleThinker(actionf_p1 thinker) +static thinker_t* LoadCrumbleThinker(save_t *save_p, actionf_p1 thinker) { crumble_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save_p)); - ht->sector = LoadSector(READUINT32(save_p)); - ht->actionsector = LoadSector(READUINT32(save_p)); - ht->player = LoadPlayer(READUINT32(save_p)); - ht->direction = READINT32(save_p); - ht->origalpha = READINT32(save_p); - ht->timer = READINT32(save_p); - ht->speed = READFIXED(save_p); - ht->floorwasheight = READFIXED(save_p); - ht->ceilingwasheight = READFIXED(save_p); - ht->flags = READUINT8(save_p); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->actionsector = LoadSector(P_ReadUINT32(save_p)); + ht->player = LoadPlayer(P_ReadUINT32(save_p)); + ht->direction = P_ReadINT32(save_p); + ht->origalpha = P_ReadINT32(save_p); + ht->timer = P_ReadINT32(save_p); + ht->speed = P_ReadFixed(save_p); + ht->floorwasheight = P_ReadFixed(save_p); + ht->ceilingwasheight = P_ReadFixed(save_p); + ht->flags = P_ReadUINT8(save_p); if (ht->sector) ht->sector->floordata = ht; @@ -3570,123 +3870,123 @@ static thinker_t* LoadCrumbleThinker(actionf_p1 thinker) return &ht->thinker; } -static thinker_t* LoadScrollThinker(actionf_p1 thinker) +static thinker_t* LoadScrollThinker(save_t *save_p, actionf_p1 thinker) { scroll_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->dx = READFIXED(save_p); - ht->dy = READFIXED(save_p); - ht->affectee = READINT32(save_p); - ht->control = READINT32(save_p); - ht->last_height = READFIXED(save_p); - ht->vdx = READFIXED(save_p); - ht->vdy = READFIXED(save_p); - ht->accel = READINT32(save_p); - ht->exclusive = READINT32(save_p); - ht->type = READUINT8(save_p); + ht->dx = P_ReadFixed(save_p); + ht->dy = P_ReadFixed(save_p); + ht->affectee = P_ReadINT32(save_p); + ht->control = P_ReadINT32(save_p); + ht->last_height = P_ReadFixed(save_p); + ht->vdx = P_ReadFixed(save_p); + ht->vdy = P_ReadFixed(save_p); + ht->accel = P_ReadINT32(save_p); + ht->exclusive = P_ReadINT32(save_p); + ht->type = P_ReadUINT8(save_p); return &ht->thinker; } -static inline thinker_t* LoadFrictionThinker(actionf_p1 thinker) +static inline thinker_t* LoadFrictionThinker(save_t *save_p, actionf_p1 thinker) { friction_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->friction = READINT32(save_p); - ht->movefactor = READINT32(save_p); - ht->affectee = READINT32(save_p); - ht->referrer = READINT32(save_p); - ht->roverfriction = READUINT8(save_p); + ht->friction = P_ReadINT32(save_p); + ht->movefactor = P_ReadINT32(save_p); + ht->affectee = P_ReadINT32(save_p); + ht->referrer = P_ReadINT32(save_p); + ht->roverfriction = P_ReadUINT8(save_p); return &ht->thinker; } -static thinker_t* LoadPusherThinker(actionf_p1 thinker) +static thinker_t* LoadPusherThinker(save_t *save_p, actionf_p1 thinker) { pusher_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->type = READUINT8(save_p); - ht->x_mag = READFIXED(save_p); - ht->y_mag = READFIXED(save_p); - ht->z_mag = READFIXED(save_p); - ht->affectee = READINT32(save_p); - ht->roverpusher = READUINT8(save_p); - ht->referrer = READINT32(save_p); - ht->exclusive = READINT32(save_p); - ht->slider = READINT32(save_p); + ht->type = P_ReadUINT8(save_p); + ht->x_mag = P_ReadFixed(save_p); + ht->y_mag = P_ReadFixed(save_p); + ht->z_mag = P_ReadFixed(save_p); + ht->affectee = P_ReadINT32(save_p); + ht->roverpusher = P_ReadUINT8(save_p); + ht->referrer = P_ReadINT32(save_p); + ht->exclusive = P_ReadINT32(save_p); + ht->slider = P_ReadINT32(save_p); return &ht->thinker; } -static inline thinker_t* LoadLaserThinker(actionf_p1 thinker) +static inline thinker_t* LoadLaserThinker(save_t *save_p, actionf_p1 thinker) { laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->tag = READINT16(save_p); - ht->sourceline = LoadLine(READUINT32(save_p)); - ht->nobosses = READUINT8(save_p); + ht->tag = P_ReadINT16(save_p); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); + ht->nobosses = P_ReadUINT8(save_p); return &ht->thinker; } -static inline thinker_t* LoadLightlevelThinker(actionf_p1 thinker) +static inline thinker_t* LoadLightlevelThinker(save_t *save_p, actionf_p1 thinker) { lightlevel_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->sourcelevel = READINT16(save_p); - ht->destlevel = READINT16(save_p); - ht->fixedcurlevel = READFIXED(save_p); - ht->fixedpertic = READFIXED(save_p); - ht->timer = READINT32(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->sourcelevel = P_ReadINT16(save_p); + ht->destlevel = P_ReadINT16(save_p); + ht->fixedcurlevel = P_ReadFixed(save_p); + ht->fixedpertic = P_ReadFixed(save_p); + ht->timer = P_ReadINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; return &ht->thinker; } -static inline thinker_t* LoadExecutorThinker(actionf_p1 thinker) +static inline thinker_t* LoadExecutorThinker(save_t *save_p, actionf_p1 thinker) { executor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->line = LoadLine(READUINT32(save_p)); - ht->caller = LoadMobj(READUINT32(save_p)); - ht->sector = LoadSector(READUINT32(save_p)); - ht->timer = READINT32(save_p); + ht->line = LoadLine(P_ReadUINT32(save_p)); + ht->caller = LoadMobj(P_ReadUINT32(save_p)); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->timer = P_ReadINT32(save_p); return &ht->thinker; } -static inline thinker_t* LoadDisappearThinker(actionf_p1 thinker) +static inline thinker_t* LoadDisappearThinker(save_t *save_p, actionf_p1 thinker) { disappear_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->appeartime = READUINT32(save_p); - ht->disappeartime = READUINT32(save_p); - ht->offset = READUINT32(save_p); - ht->timer = READUINT32(save_p); - ht->affectee = READINT32(save_p); - ht->sourceline = READINT32(save_p); - ht->exists = READINT32(save_p); + ht->appeartime = P_ReadUINT32(save_p); + ht->disappeartime = P_ReadUINT32(save_p); + ht->offset = P_ReadUINT32(save_p); + ht->timer = P_ReadUINT32(save_p); + ht->affectee = P_ReadINT32(save_p); + ht->sourceline = P_ReadINT32(save_p); + ht->exists = P_ReadINT32(save_p); return &ht->thinker; } -static inline thinker_t* LoadFadeThinker(actionf_p1 thinker) +static inline thinker_t* LoadFadeThinker(save_t *save_p, actionf_p1 thinker) { sector_t *ss; fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->dest_exc = GetNetColormapFromList(READUINT32(save_p)); - ht->sectornum = READUINT32(save_p); - ht->ffloornum = READUINT32(save_p); - ht->alpha = READINT32(save_p); - ht->sourcevalue = READINT16(save_p); - ht->destvalue = READINT16(save_p); - ht->destlightlevel = READINT16(save_p); - ht->speed = READINT16(save_p); - ht->ticbased = (boolean)READUINT8(save_p); - ht->timer = READINT32(save_p); - ht->doexists = READUINT8(save_p); - ht->dotranslucent = READUINT8(save_p); - ht->dolighting = READUINT8(save_p); - ht->docolormap = READUINT8(save_p); - ht->docollision = READUINT8(save_p); - ht->doghostfade = READUINT8(save_p); - ht->exactalpha = READUINT8(save_p); + ht->dest_exc = GetNetColormapFromList(P_ReadUINT32(save_p)); + ht->sectornum = P_ReadUINT32(save_p); + ht->ffloornum = P_ReadUINT32(save_p); + ht->alpha = P_ReadINT32(save_p); + ht->sourcevalue = P_ReadINT16(save_p); + ht->destvalue = P_ReadINT16(save_p); + ht->destlightlevel = P_ReadINT16(save_p); + ht->speed = P_ReadINT16(save_p); + ht->ticbased = (boolean)P_ReadUINT8(save_p); + ht->timer = P_ReadINT32(save_p); + ht->doexists = P_ReadUINT8(save_p); + ht->dotranslucent = P_ReadUINT8(save_p); + ht->dolighting = P_ReadUINT8(save_p); + ht->docolormap = P_ReadUINT8(save_p); + ht->docollision = P_ReadUINT8(save_p); + ht->doghostfade = P_ReadUINT8(save_p); + ht->exactalpha = P_ReadUINT8(save_p); ss = LoadSector(ht->sectornum); if (ss) @@ -3707,176 +4007,176 @@ static inline thinker_t* LoadFadeThinker(actionf_p1 thinker) return &ht->thinker; } -static inline thinker_t* LoadFadeColormapThinker(actionf_p1 thinker) +static inline thinker_t* LoadFadeColormapThinker(save_t *save_p, actionf_p1 thinker) { fadecolormap_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->source_exc = GetNetColormapFromList(READUINT32(save_p)); - ht->dest_exc = GetNetColormapFromList(READUINT32(save_p)); - ht->ticbased = (boolean)READUINT8(save_p); - ht->duration = READINT32(save_p); - ht->timer = READINT32(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->source_exc = GetNetColormapFromList(P_ReadUINT32(save_p)); + ht->dest_exc = GetNetColormapFromList(P_ReadUINT32(save_p)); + ht->ticbased = (boolean)P_ReadUINT8(save_p); + ht->duration = P_ReadINT32(save_p); + ht->timer = P_ReadINT32(save_p); if (ht->sector) ht->sector->fadecolormapdata = ht; return &ht->thinker; } -static inline thinker_t* LoadPlaneDisplaceThinker(actionf_p1 thinker) +static inline thinker_t* LoadPlaneDisplaceThinker(save_t *save_p, actionf_p1 thinker) { planedisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->affectee = READINT32(save_p); - ht->control = READINT32(save_p); - ht->last_height = READFIXED(save_p); - ht->speed = READFIXED(save_p); - ht->type = READUINT8(save_p); + ht->affectee = P_ReadINT32(save_p); + ht->control = P_ReadINT32(save_p); + ht->last_height = P_ReadFixed(save_p); + ht->speed = P_ReadFixed(save_p); + ht->type = P_ReadUINT8(save_p); return &ht->thinker; } -static inline thinker_t* LoadDynamicLineSlopeThinker(actionf_p1 thinker) +static inline thinker_t* LoadDynamicLineSlopeThinker(save_t *save_p, actionf_p1 thinker) { dynlineplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->type = READUINT8(save_p); - ht->slope = LoadSlope(READUINT32(save_p)); - ht->sourceline = LoadLine(READUINT32(save_p)); - ht->extent = READFIXED(save_p); + ht->type = P_ReadUINT8(save_p); + ht->slope = LoadSlope(P_ReadUINT32(save_p)); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); + ht->extent = P_ReadFixed(save_p); return &ht->thinker; } -static inline thinker_t* LoadDynamicVertexSlopeThinker(actionf_p1 thinker) +static inline thinker_t* LoadDynamicVertexSlopeThinker(save_t *save_p, actionf_p1 thinker) { size_t i; dynvertexplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->slope = LoadSlope(READUINT32(save_p)); + ht->slope = LoadSlope(P_ReadUINT32(save_p)); for (i = 0; i < 3; i++) - ht->secs[i] = LoadSector(READUINT32(save_p)); - READMEM(save_p, ht->vex, sizeof(ht->vex)); - READMEM(save_p, ht->origsecheights, sizeof(ht->origsecheights)); - READMEM(save_p, ht->origvecheights, sizeof(ht->origvecheights)); - ht->relative = READUINT8(save_p); + ht->secs[i] = LoadSector(P_ReadUINT32(save_p)); + P_ReadMem(save_p, ht->vex, sizeof(ht->vex)); + P_ReadMem(save_p, ht->origsecheights, sizeof(ht->origsecheights)); + P_ReadMem(save_p, ht->origvecheights, sizeof(ht->origvecheights)); + ht->relative = P_ReadUINT8(save_p); return &ht->thinker; } -static inline thinker_t* LoadPolyrotatetThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolyrotatetThinker(save_t *save_p, actionf_p1 thinker) { polyrotate_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save_p); - ht->speed = READINT32(save_p); - ht->distance = READINT32(save_p); - ht->turnobjs = READUINT8(save_p); + ht->polyObjNum = P_ReadINT32(save_p); + ht->speed = P_ReadINT32(save_p); + ht->distance = P_ReadINT32(save_p); + ht->turnobjs = P_ReadUINT8(save_p); return &ht->thinker; } -static thinker_t* LoadPolymoveThinker(actionf_p1 thinker) +static thinker_t* LoadPolymoveThinker(save_t *save_p, actionf_p1 thinker) { polymove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save_p); - ht->speed = READINT32(save_p); - ht->momx = READFIXED(save_p); - ht->momy = READFIXED(save_p); - ht->distance = READINT32(save_p); - ht->angle = READANGLE(save_p); + ht->polyObjNum = P_ReadINT32(save_p); + ht->speed = P_ReadINT32(save_p); + ht->momx = P_ReadFixed(save_p); + ht->momy = P_ReadFixed(save_p); + ht->distance = P_ReadINT32(save_p); + ht->angle = P_ReadAngle(save_p); return &ht->thinker; } -static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolywaypointThinker(save_t *save_p, actionf_p1 thinker) { polywaypoint_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save_p); - ht->speed = READINT32(save_p); - ht->sequence = READINT32(save_p); - ht->pointnum = READINT32(save_p); - ht->direction = READINT32(save_p); - ht->returnbehavior = READUINT8(save_p); - ht->continuous = READUINT8(save_p); - ht->stophere = READUINT8(save_p); + ht->polyObjNum = P_ReadINT32(save_p); + ht->speed = P_ReadINT32(save_p); + ht->sequence = P_ReadINT32(save_p); + ht->pointnum = P_ReadINT32(save_p); + ht->direction = P_ReadINT32(save_p); + ht->returnbehavior = P_ReadUINT8(save_p); + ht->continuous = P_ReadUINT8(save_p); + ht->stophere = P_ReadUINT8(save_p); return &ht->thinker; } -static inline thinker_t* LoadPolyslidedoorThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolyslidedoorThinker(save_t *save_p, actionf_p1 thinker) { polyslidedoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save_p); - ht->delay = READINT32(save_p); - ht->delayCount = READINT32(save_p); - ht->initSpeed = READINT32(save_p); - ht->speed = READINT32(save_p); - ht->initDistance = READINT32(save_p); - ht->distance = READINT32(save_p); - ht->initAngle = READUINT32(save_p); - ht->angle = READUINT32(save_p); - ht->revAngle = READUINT32(save_p); - ht->momx = READFIXED(save_p); - ht->momy = READFIXED(save_p); - ht->closing = READUINT8(save_p); + ht->polyObjNum = P_ReadINT32(save_p); + ht->delay = P_ReadINT32(save_p); + ht->delayCount = P_ReadINT32(save_p); + ht->initSpeed = P_ReadINT32(save_p); + ht->speed = P_ReadINT32(save_p); + ht->initDistance = P_ReadINT32(save_p); + ht->distance = P_ReadINT32(save_p); + ht->initAngle = P_ReadUINT32(save_p); + ht->angle = P_ReadUINT32(save_p); + ht->revAngle = P_ReadUINT32(save_p); + ht->momx = P_ReadFixed(save_p); + ht->momy = P_ReadFixed(save_p); + ht->closing = P_ReadUINT8(save_p); return &ht->thinker; } -static inline thinker_t* LoadPolyswingdoorThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolyswingdoorThinker(save_t *save_p, actionf_p1 thinker) { polyswingdoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save_p); - ht->delay = READINT32(save_p); - ht->delayCount = READINT32(save_p); - ht->initSpeed = READINT32(save_p); - ht->speed = READINT32(save_p); - ht->initDistance = READINT32(save_p); - ht->distance = READINT32(save_p); - ht->closing = READUINT8(save_p); + ht->polyObjNum = P_ReadINT32(save_p); + ht->delay = P_ReadINT32(save_p); + ht->delayCount = P_ReadINT32(save_p); + ht->initSpeed = P_ReadINT32(save_p); + ht->speed = P_ReadINT32(save_p); + ht->initDistance = P_ReadINT32(save_p); + ht->distance = P_ReadINT32(save_p); + ht->closing = P_ReadUINT8(save_p); return &ht->thinker; } -static inline thinker_t* LoadPolydisplaceThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolydisplaceThinker(save_t *save_p, actionf_p1 thinker) { polydisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save_p); - ht->controlSector = LoadSector(READUINT32(save_p)); - ht->dx = READFIXED(save_p); - ht->dy = READFIXED(save_p); - ht->oldHeights = READFIXED(save_p); + ht->polyObjNum = P_ReadINT32(save_p); + ht->controlSector = LoadSector(P_ReadUINT32(save_p)); + ht->dx = P_ReadFixed(save_p); + ht->dy = P_ReadFixed(save_p); + ht->oldHeights = P_ReadFixed(save_p); return &ht->thinker; } -static inline thinker_t* LoadPolyrotdisplaceThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolyrotdisplaceThinker(save_t *save_p, actionf_p1 thinker) { polyrotdisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save_p); - ht->controlSector = LoadSector(READUINT32(save_p)); - ht->rotscale = READFIXED(save_p); - ht->turnobjs = READUINT8(save_p); - ht->oldHeights = READFIXED(save_p); + ht->polyObjNum = P_ReadINT32(save_p); + ht->controlSector = LoadSector(P_ReadUINT32(save_p)); + ht->rotscale = P_ReadFixed(save_p); + ht->turnobjs = P_ReadUINT8(save_p); + ht->oldHeights = P_ReadFixed(save_p); return &ht->thinker; } -static thinker_t* LoadPolyfadeThinker(actionf_p1 thinker) +static thinker_t* LoadPolyfadeThinker(save_t *save_p, actionf_p1 thinker) { polyfade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save_p); - ht->sourcevalue = READINT32(save_p); - ht->destvalue = READINT32(save_p); - ht->docollision = (boolean)READUINT8(save_p); - ht->doghostfade = (boolean)READUINT8(save_p); - ht->ticbased = (boolean)READUINT8(save_p); - ht->duration = READINT32(save_p); - ht->timer = READINT32(save_p); + ht->polyObjNum = P_ReadINT32(save_p); + ht->sourcevalue = P_ReadINT32(save_p); + ht->destvalue = P_ReadINT32(save_p); + ht->docollision = (boolean)P_ReadUINT8(save_p); + ht->doghostfade = (boolean)P_ReadUINT8(save_p); + ht->ticbased = (boolean)P_ReadUINT8(save_p); + ht->duration = P_ReadINT32(save_p); + ht->timer = P_ReadINT32(save_p); return &ht->thinker; } -static void P_NetUnArchiveThinkers(void) +static void P_NetUnArchiveThinkers(save_t *save_p) { thinker_t *currentthinker; thinker_t *next; @@ -3885,7 +4185,7 @@ static void P_NetUnArchiveThinkers(void) UINT32 i; UINT32 numloaded = 0; - if (READUINT32(save_p) != ARCHIVEBLOCK_THINKERS) + if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_THINKERS) I_Error("Bad $$$.sav at archive block Thinkers"); // remove all the current thinkers @@ -3923,7 +4223,7 @@ static void P_NetUnArchiveThinkers(void) for (;;) { thinker_t* th = NULL; - tclass = READUINT8(save_p); + tclass = P_ReadUINT8(save_p); if (tclass == tc_end) break; // leave the saved thinker reading loop @@ -3932,167 +4232,167 @@ static void P_NetUnArchiveThinkers(void) switch (tclass) { case tc_mobj: - th = LoadMobjThinker((actionf_p1)P_MobjThinker); + th = LoadMobjThinker(save_p, (actionf_p1)P_MobjThinker); break; case tc_ceiling: - th = LoadCeilingThinker((actionf_p1)T_MoveCeiling); + th = LoadCeilingThinker(save_p, (actionf_p1)T_MoveCeiling); break; case tc_crushceiling: - th = LoadCeilingThinker((actionf_p1)T_CrushCeiling); + th = LoadCeilingThinker(save_p, (actionf_p1)T_CrushCeiling); break; case tc_floor: - th = LoadFloormoveThinker((actionf_p1)T_MoveFloor); + th = LoadFloormoveThinker(save_p, (actionf_p1)T_MoveFloor); break; case tc_flash: - th = LoadLightflashThinker((actionf_p1)T_LightningFlash); + th = LoadLightflashThinker(save_p, (actionf_p1)T_LightningFlash); break; case tc_strobe: - th = LoadStrobeThinker((actionf_p1)T_StrobeFlash); + th = LoadStrobeThinker(save_p, (actionf_p1)T_StrobeFlash); break; case tc_glow: - th = LoadGlowThinker((actionf_p1)T_Glow); + th = LoadGlowThinker(save_p, (actionf_p1)T_Glow); break; case tc_fireflicker: - th = LoadFireflickerThinker((actionf_p1)T_FireFlicker); + th = LoadFireflickerThinker(save_p, (actionf_p1)T_FireFlicker); break; case tc_elevator: - th = LoadElevatorThinker((actionf_p1)T_MoveElevator, true); + th = LoadElevatorThinker(save_p, (actionf_p1)T_MoveElevator, true); break; case tc_continuousfalling: - th = LoadContinuousFallThinker((actionf_p1)T_ContinuousFalling); + th = LoadContinuousFallThinker(save_p, (actionf_p1)T_ContinuousFalling); break; case tc_thwomp: - th = LoadThwompThinker((actionf_p1)T_ThwompSector); + th = LoadThwompThinker(save_p, (actionf_p1)T_ThwompSector); break; case tc_noenemies: - th = LoadNoEnemiesThinker((actionf_p1)T_NoEnemiesSector); + th = LoadNoEnemiesThinker(save_p, (actionf_p1)T_NoEnemiesSector); break; case tc_eachtime: - th = LoadEachTimeThinker((actionf_p1)T_EachTimeThinker); + th = LoadEachTimeThinker(save_p, (actionf_p1)T_EachTimeThinker); break; case tc_raisesector: - th = LoadRaiseThinker((actionf_p1)T_RaiseSector); + th = LoadRaiseThinker(save_p, (actionf_p1)T_RaiseSector); break; case tc_camerascanner: - th = LoadElevatorThinker((actionf_p1)T_CameraScanner, false); + th = LoadElevatorThinker(save_p, (actionf_p1)T_CameraScanner, false); break; case tc_bouncecheese: - th = LoadBounceCheeseThinker((actionf_p1)T_BounceCheese); + th = LoadBounceCheeseThinker(save_p, (actionf_p1)T_BounceCheese); break; case tc_startcrumble: - th = LoadCrumbleThinker((actionf_p1)T_StartCrumble); + th = LoadCrumbleThinker(save_p, (actionf_p1)T_StartCrumble); break; case tc_marioblock: - th = LoadMarioBlockThinker((actionf_p1)T_MarioBlock); + th = LoadMarioBlockThinker(save_p, (actionf_p1)T_MarioBlock); break; case tc_marioblockchecker: - th = LoadMarioCheckThinker((actionf_p1)T_MarioBlockChecker); + th = LoadMarioCheckThinker(save_p, (actionf_p1)T_MarioBlockChecker); break; case tc_floatsector: - th = LoadFloatThinker((actionf_p1)T_FloatSector); + th = LoadFloatThinker(save_p, (actionf_p1)T_FloatSector); break; case tc_laserflash: - th = LoadLaserThinker((actionf_p1)T_LaserFlash); + th = LoadLaserThinker(save_p, (actionf_p1)T_LaserFlash); break; case tc_lightfade: - th = LoadLightlevelThinker((actionf_p1)T_LightFade); + th = LoadLightlevelThinker(save_p, (actionf_p1)T_LightFade); break; case tc_executor: - th = LoadExecutorThinker((actionf_p1)T_ExecutorDelay); + th = LoadExecutorThinker(save_p, (actionf_p1)T_ExecutorDelay); restoreNum = true; break; case tc_disappear: - th = LoadDisappearThinker((actionf_p1)T_Disappear); + th = LoadDisappearThinker(save_p, (actionf_p1)T_Disappear); break; case tc_fade: - th = LoadFadeThinker((actionf_p1)T_Fade); + th = LoadFadeThinker(save_p, (actionf_p1)T_Fade); break; case tc_fadecolormap: - th = LoadFadeColormapThinker((actionf_p1)T_FadeColormap); + th = LoadFadeColormapThinker(save_p, (actionf_p1)T_FadeColormap); break; case tc_planedisplace: - th = LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace); + th = LoadPlaneDisplaceThinker(save_p, (actionf_p1)T_PlaneDisplace); break; case tc_polyrotate: - th = LoadPolyrotatetThinker((actionf_p1)T_PolyObjRotate); + th = LoadPolyrotatetThinker(save_p, (actionf_p1)T_PolyObjRotate); break; case tc_polymove: - th = LoadPolymoveThinker((actionf_p1)T_PolyObjMove); + th = LoadPolymoveThinker(save_p, (actionf_p1)T_PolyObjMove); break; case tc_polywaypoint: - th = LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint); + th = LoadPolywaypointThinker(save_p, (actionf_p1)T_PolyObjWaypoint); break; case tc_polyslidedoor: - th = LoadPolyslidedoorThinker((actionf_p1)T_PolyDoorSlide); + th = LoadPolyslidedoorThinker(save_p, (actionf_p1)T_PolyDoorSlide); break; case tc_polyswingdoor: - th = LoadPolyswingdoorThinker((actionf_p1)T_PolyDoorSwing); + th = LoadPolyswingdoorThinker(save_p, (actionf_p1)T_PolyDoorSwing); break; case tc_polyflag: - th = LoadPolymoveThinker((actionf_p1)T_PolyObjFlag); + th = LoadPolymoveThinker(save_p, (actionf_p1)T_PolyObjFlag); break; case tc_polydisplace: - th = LoadPolydisplaceThinker((actionf_p1)T_PolyObjDisplace); + th = LoadPolydisplaceThinker(save_p, (actionf_p1)T_PolyObjDisplace); break; case tc_polyrotdisplace: - th = LoadPolyrotdisplaceThinker((actionf_p1)T_PolyObjRotDisplace); + th = LoadPolyrotdisplaceThinker(save_p, (actionf_p1)T_PolyObjRotDisplace); break; case tc_polyfade: - th = LoadPolyfadeThinker((actionf_p1)T_PolyObjFade); + th = LoadPolyfadeThinker(save_p, (actionf_p1)T_PolyObjFade); break; case tc_dynslopeline: - th = LoadDynamicLineSlopeThinker((actionf_p1)T_DynamicSlopeLine); + th = LoadDynamicLineSlopeThinker(save_p, (actionf_p1)T_DynamicSlopeLine); break; case tc_dynslopevert: - th = LoadDynamicVertexSlopeThinker((actionf_p1)T_DynamicSlopeVert); + th = LoadDynamicVertexSlopeThinker(save_p, (actionf_p1)T_DynamicSlopeVert); break; case tc_scroll: - th = LoadScrollThinker((actionf_p1)T_Scroll); + th = LoadScrollThinker(save_p, (actionf_p1)T_Scroll); break; case tc_friction: - th = LoadFrictionThinker((actionf_p1)T_Friction); + th = LoadFrictionThinker(save_p, (actionf_p1)T_Friction); break; case tc_pusher: - th = LoadPusherThinker((actionf_p1)T_Pusher); + th = LoadPusherThinker(save_p, (actionf_p1)T_Pusher); break; default: @@ -4132,29 +4432,29 @@ static void P_NetUnArchiveThinkers(void) #define PD_FLAGS 0x01 #define PD_TRANS 0x02 -static inline void P_ArchivePolyObj(polyobj_t *po) +static inline void P_ArchivePolyObj(save_t *save_p, polyobj_t *po) { UINT8 diff = 0; - WRITEINT32(save_p, po->id); - WRITEANGLE(save_p, po->angle); + P_WriteINT32(save_p, po->id); + P_WriteAngle(save_p, po->angle); - WRITEFIXED(save_p, po->spawnSpot.x); - WRITEFIXED(save_p, po->spawnSpot.y); + P_WriteFixed(save_p, po->spawnSpot.x); + P_WriteFixed(save_p, po->spawnSpot.y); if (po->flags != po->spawnflags) diff |= PD_FLAGS; if (po->translucency != po->spawntrans) diff |= PD_TRANS; - WRITEUINT8(save_p, diff); + P_WriteUINT8(save_p, diff); if (diff & PD_FLAGS) - WRITEINT32(save_p, po->flags); + P_WriteINT32(save_p, po->flags); if (diff & PD_TRANS) - WRITEINT32(save_p, po->translucency); + P_WriteINT32(save_p, po->translucency); } -static inline void P_UnArchivePolyObj(polyobj_t *po) +static inline void P_UnArchivePolyObj(save_t *save_p, polyobj_t *po) { INT32 id; UINT32 angle; @@ -4166,19 +4466,19 @@ static inline void P_UnArchivePolyObj(polyobj_t *po) // when they first start to run. po->thinker = NULL; - id = READINT32(save_p); + id = P_ReadINT32(save_p); - angle = READANGLE(save_p); + angle = P_ReadAngle(save_p); - x = READFIXED(save_p); - y = READFIXED(save_p); + x = P_ReadFixed(save_p); + y = P_ReadFixed(save_p); - diff = READUINT8(save_p); + diff = P_ReadUINT8(save_p); if (diff & PD_FLAGS) - po->flags = READINT32(save_p); + po->flags = P_ReadINT32(save_p); if (diff & PD_TRANS) - po->translucency = READINT32(save_p); + po->translucency = P_ReadINT32(save_p); // if the object is bad or isn't in the id hash, we can do nothing more // with it, so return now @@ -4189,33 +4489,33 @@ static inline void P_UnArchivePolyObj(polyobj_t *po) Polyobj_MoveOnLoad(po, angle, x, y); } -static inline void P_ArchivePolyObjects(void) +static inline void P_ArchivePolyObjects(save_t *save_p) { INT32 i; - WRITEUINT32(save_p, ARCHIVEBLOCK_POBJS); + P_WriteUINT32(save_p, ARCHIVEBLOCK_POBJS); // save number of polyobjects - WRITEINT32(save_p, numPolyObjects); + P_WriteINT32(save_p, numPolyObjects); for (i = 0; i < numPolyObjects; ++i) - P_ArchivePolyObj(&PolyObjects[i]); + P_ArchivePolyObj(save_p, &PolyObjects[i]); } -static inline void P_UnArchivePolyObjects(void) +static inline void P_UnArchivePolyObjects(save_t *save_p) { INT32 i, numSavedPolys; - if (READUINT32(save_p) != ARCHIVEBLOCK_POBJS) + if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_POBJS) I_Error("Bad $$$.sav at archive block Pobjs"); - numSavedPolys = READINT32(save_p); + numSavedPolys = P_ReadINT32(save_p); if (numSavedPolys != numPolyObjects) I_Error("P_UnArchivePolyObjects: polyobj count inconsistency\n"); for (i = 0; i < numSavedPolys; ++i) - P_UnArchivePolyObj(&PolyObjects[i]); + P_UnArchivePolyObj(save_p, &PolyObjects[i]); } static inline void P_FinishMobjs(void) @@ -4227,7 +4527,7 @@ static inline void P_FinishMobjs(void) for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; currentthinker = currentthinker->next) { - if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (currentthinker->removing) continue; mobj = (mobj_t *)currentthinker; @@ -4245,7 +4545,7 @@ static void P_RelinkPointers(void) for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; currentthinker = currentthinker->next) { - if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (currentthinker->removing) continue; mobj = (mobj_t *)currentthinker; @@ -4333,11 +4633,11 @@ static void P_RelinkPointers(void) } } -static inline void P_NetArchiveSpecials(void) +static inline void P_NetArchiveSpecials(save_t *save_p) { size_t i, z; - WRITEUINT32(save_p, ARCHIVEBLOCK_SPECIALS); + P_WriteUINT32(save_p, ARCHIVEBLOCK_SPECIALS); // itemrespawn queue for deathmatch i = iquetail; @@ -4347,53 +4647,54 @@ static inline void P_NetArchiveSpecials(void) { if (&mapthings[z] == itemrespawnque[i]) { - WRITEUINT32(save_p, z); + P_WriteUINT32(save_p, z); break; } } - WRITEUINT32(save_p, itemrespawntime[i]); + P_WriteUINT32(save_p, itemrespawntime[i]); i = (i + 1) & (ITEMQUESIZE-1); } // end delimiter - WRITEUINT32(save_p, 0xffffffff); + P_WriteUINT32(save_p, 0xffffffff); // Sky number - WRITEINT32(save_p, globallevelskynum); + P_WriteINT32(save_p, globallevelskynum); // Current global weather type - WRITEUINT8(save_p, globalweather); + P_WriteUINT8(save_p, globalweather); if (metalplayback) // Is metal sonic running? { - WRITEUINT8(save_p, 0x01); - G_SaveMetal(&save_p); + UINT8 *p = &save_p->buf[save_p->pos+1]; + P_WriteUINT8(save_p, 0x01); + G_SaveMetal(&p); } else - WRITEUINT8(save_p, 0x00); + P_WriteUINT8(save_p, 0x00); } -static void P_NetUnArchiveSpecials(void) +static void P_NetUnArchiveSpecials(save_t *save_p) { size_t i; INT32 j; - if (READUINT32(save_p) != ARCHIVEBLOCK_SPECIALS) + if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_SPECIALS) I_Error("Bad $$$.sav at archive block Specials"); // BP: added save itemrespawn queue for deathmatch iquetail = iquehead = 0; - while ((i = READUINT32(save_p)) != 0xffffffff) + while ((i = P_ReadUINT32(save_p)) != 0xffffffff) { itemrespawnque[iquehead] = &mapthings[i]; - itemrespawntime[iquehead++] = READINT32(save_p); + itemrespawntime[iquehead++] = P_ReadINT32(save_p); } - j = READINT32(save_p); + j = P_ReadINT32(save_p); if (j != globallevelskynum) P_SetupLevelSky(j, true); - globalweather = READUINT8(save_p); + globalweather = P_ReadUINT8(save_p); if (globalweather) { @@ -4408,14 +4709,17 @@ static void P_NetUnArchiveSpecials(void) P_SwitchWeather(globalweather); } - if (READUINT8(save_p) == 0x01) // metal sonic - G_LoadMetal(&save_p); + if (P_ReadUINT8(save_p) == 0x01) // metal sonic + { + UINT8 *p = &save_p->buf[save_p->pos]; + G_LoadMetal(&p); + } } // ======================================================================= // Misc // ======================================================================= -static inline void P_ArchiveMisc(INT16 mapnum) +static inline void P_ArchiveMisc(save_t *save_p, INT16 mapnum) { //lastmapsaved = mapnum; lastmaploaded = mapnum; @@ -4423,16 +4727,16 @@ static inline void P_ArchiveMisc(INT16 mapnum) if (gamecomplete) mapnum |= 8192; - WRITEINT16(save_p, mapnum); - WRITEUINT16(save_p, emeralds+357); - WRITESTRINGN(save_p, timeattackfolder, sizeof(timeattackfolder)); + P_WriteINT16(save_p, mapnum); + P_WriteUINT16(save_p, emeralds+357); + P_WriteStringN(save_p, timeattackfolder, sizeof(timeattackfolder)); } -static inline void P_UnArchiveSPGame(INT16 mapoverride) +static inline void P_UnArchiveSPGame(save_t *save_p, INT16 mapoverride) { char testname[sizeof(timeattackfolder)]; - gamemap = READINT16(save_p); + gamemap = P_ReadINT16(save_p); if (mapoverride != 0) { @@ -4453,9 +4757,9 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride) tokenlist = 0; token = 0; - savedata.emeralds = READUINT16(save_p)-357; + savedata.emeralds = P_ReadUINT16(save_p)-357; - READSTRINGN(save_p, testname, sizeof(testname)); + P_ReadStringN(save_p, testname, sizeof(testname)); if (strcmp(testname, timeattackfolder)) { @@ -4469,100 +4773,106 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride) playeringame[consoleplayer] = true; } -static void P_NetArchiveMisc(boolean resending) +static void P_NetArchiveMisc(save_t *save_p, boolean resending) { INT32 i; - WRITEUINT32(save_p, ARCHIVEBLOCK_MISC); + P_WriteUINT32(save_p, ARCHIVEBLOCK_MISC); if (resending) - WRITEUINT32(save_p, gametic); - WRITEINT16(save_p, gamemap); + P_WriteUINT32(save_p, gametic); + P_WriteINT16(save_p, gamemap); if (gamestate != GS_LEVEL) - WRITEINT16(save_p, GS_WAITINGPLAYERS); // nice hack to put people back into waitingplayers + P_WriteINT16(save_p, GS_WAITINGPLAYERS); // nice hack to put people back into waitingplayers else - WRITEINT16(save_p, gamestate); - WRITEINT16(save_p, gametype); + P_WriteINT16(save_p, gamestate); + P_WriteINT16(save_p, gametype); { UINT32 pig = 0; for (i = 0; i < MAXPLAYERS; i++) pig |= (playeringame[i] != 0)<totalplaytime); + P_WriteUINT32(save_p, data->totalplaytime); // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) - WRITEUINT8(save_p, (data->mapvisited[i] & MV_MAX)); + P_WriteUINT8(save_p, (data->mapvisited[i] & MV_MAX)); // To save space, use one bit per collected/achieved/unlocked flag for (i = 0; i < MAXEMBLEMS;) @@ -4681,7 +4997,7 @@ static inline void P_NetArchiveEmblems(void) btemp = 0; for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) btemp |= (data->collected[j+i] << j); - WRITEUINT8(save_p, btemp); + P_WriteUINT8(save_p, btemp); i += j; } for (i = 0; i < MAXEXTRAEMBLEMS;) @@ -4689,7 +5005,7 @@ static inline void P_NetArchiveEmblems(void) btemp = 0; for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) btemp |= (data->extraCollected[j+i] << j); - WRITEUINT8(save_p, btemp); + P_WriteUINT8(save_p, btemp); i += j; } for (i = 0; i < MAXUNLOCKABLES;) @@ -4697,7 +5013,7 @@ static inline void P_NetArchiveEmblems(void) btemp = 0; for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) btemp |= (data->unlocked[j+i] << j); - WRITEUINT8(save_p, btemp); + P_WriteUINT8(save_p, btemp); i += j; } for (i = 0; i < MAXCONDITIONSETS;) @@ -4705,28 +5021,28 @@ static inline void P_NetArchiveEmblems(void) btemp = 0; for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) btemp |= (data->achieved[j+i] << j); - WRITEUINT8(save_p, btemp); + P_WriteUINT8(save_p, btemp); i += j; } - WRITEUINT32(save_p, data->timesBeaten); - WRITEUINT32(save_p, data->timesBeatenWithEmeralds); - WRITEUINT32(save_p, data->timesBeatenUltimate); + P_WriteUINT32(save_p, data->timesBeaten); + P_WriteUINT32(save_p, data->timesBeatenWithEmeralds); + P_WriteUINT32(save_p, data->timesBeatenUltimate); // Main records for (i = 0; i < NUMMAPS; i++) { if (data->mainrecords[i]) { - WRITEUINT32(save_p, data->mainrecords[i]->score); - WRITEUINT32(save_p, data->mainrecords[i]->time); - WRITEUINT16(save_p, data->mainrecords[i]->rings); + P_WriteUINT32(save_p, data->mainrecords[i]->score); + P_WriteUINT32(save_p, data->mainrecords[i]->time); + P_WriteUINT16(save_p, data->mainrecords[i]->rings); } else { - WRITEUINT32(save_p, 0); - WRITEUINT32(save_p, 0); - WRITEUINT16(save_p, 0); + P_WriteUINT32(save_p, 0); + P_WriteUINT32(save_p, 0); + P_WriteUINT16(save_p, 0); } } @@ -4735,43 +5051,43 @@ static inline void P_NetArchiveEmblems(void) { if (!data->nightsrecords[i] || !data->nightsrecords[i]->nummares) { - WRITEUINT8(save_p, 0); + P_WriteUINT8(save_p, 0); continue; } - WRITEUINT8(save_p, data->nightsrecords[i]->nummares); + P_WriteUINT8(save_p, data->nightsrecords[i]->nummares); for (curmare = 0; curmare < (data->nightsrecords[i]->nummares + 1); ++curmare) { - WRITEUINT32(save_p, data->nightsrecords[i]->score[curmare]); - WRITEUINT8(save_p, data->nightsrecords[i]->grade[curmare]); - WRITEUINT32(save_p, data->nightsrecords[i]->time[curmare]); + P_WriteUINT32(save_p, data->nightsrecords[i]->score[curmare]); + P_WriteUINT8(save_p, data->nightsrecords[i]->grade[curmare]); + P_WriteUINT32(save_p, data->nightsrecords[i]->time[curmare]); } } // Mid-map stuff - WRITEUINT32(save_p, unlocktriggers); + P_WriteUINT32(save_p, unlocktriggers); for (i = 0; i < MAXPLAYERS; i++) { if (!ntemprecords[i].nummares) { - WRITEUINT8(save_p, 0); + P_WriteUINT8(save_p, 0); continue; } - WRITEUINT8(save_p, ntemprecords[i].nummares); + P_WriteUINT8(save_p, ntemprecords[i].nummares); for (curmare = 0; curmare < (ntemprecords[i].nummares + 1); ++curmare) { - WRITEUINT32(save_p, ntemprecords[i].score[curmare]); - WRITEUINT8(save_p, ntemprecords[i].grade[curmare]); - WRITEUINT32(save_p, ntemprecords[i].time[curmare]); + P_WriteUINT32(save_p, ntemprecords[i].score[curmare]); + P_WriteUINT8(save_p, ntemprecords[i].grade[curmare]); + P_WriteUINT32(save_p, ntemprecords[i].time[curmare]); } } } -static inline void P_NetUnArchiveEmblems(void) +static inline void P_NetUnArchiveEmblems(save_t *save_p) { gamedata_t *data = serverGamedata; INT32 i, j; @@ -4782,14 +5098,14 @@ static inline void P_NetUnArchiveEmblems(void) UINT8 recmares; INT32 curmare; - if (READUINT32(save_p) != ARCHIVEBLOCK_EMBLEMS) + if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_EMBLEMS) I_Error("Bad $$$.sav at archive block Emblems"); - savemoddata = (boolean)READUINT8(save_p); // this one is actually necessary because savemoddata stays false otherwise for some reason. + savemoddata = (boolean)P_ReadUINT8(save_p); // this one is actually necessary because savemoddata stays false otherwise for some reason. - if (numemblems != READINT32(save_p)) + if (numemblems != P_ReadINT32(save_p)) I_Error("Bad $$$.sav dearchiving Emblems (numemblems mismatch)"); - if (numextraemblems != READINT32(save_p)) + if (numextraemblems != P_ReadINT32(save_p)) I_Error("Bad $$$.sav dearchiving Emblems (numextraemblems mismatch)"); // This shouldn't happen, but if something really fucked up happens and you transfer @@ -4804,53 +5120,53 @@ static inline void P_NetUnArchiveEmblems(void) // TODO: Optimize this to only read information about emblems, unlocks, etc. which actually exist // There is no need to go all the way up to MAXEMBLEMS when wads are guaranteed to be the same. - data->totalplaytime = READUINT32(save_p); + data->totalplaytime = P_ReadUINT32(save_p); // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) - if ((data->mapvisited[i] = READUINT8(save_p)) > MV_MAX) + if ((data->mapvisited[i] = P_ReadUINT8(save_p)) > MV_MAX) I_Error("Bad $$$.sav dearchiving Emblems (invalid visit flags)"); // To save space, use one bit per collected/achieved/unlocked flag for (i = 0; i < MAXEMBLEMS;) { - rtemp = READUINT8(save_p); + rtemp = P_ReadUINT8(save_p); for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) data->collected[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < MAXEXTRAEMBLEMS;) { - rtemp = READUINT8(save_p); + rtemp = P_ReadUINT8(save_p); for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) data->extraCollected[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < MAXUNLOCKABLES;) { - rtemp = READUINT8(save_p); + rtemp = P_ReadUINT8(save_p); for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) data->unlocked[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < MAXCONDITIONSETS;) { - rtemp = READUINT8(save_p); + rtemp = P_ReadUINT8(save_p); for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) data->achieved[j+i] = ((rtemp >> j) & 1); i += j; } - data->timesBeaten = READUINT32(save_p); - data->timesBeatenWithEmeralds = READUINT32(save_p); - data->timesBeatenUltimate = READUINT32(save_p); + data->timesBeaten = P_ReadUINT32(save_p); + data->timesBeatenWithEmeralds = P_ReadUINT32(save_p); + data->timesBeatenUltimate = P_ReadUINT32(save_p); // Main records for (i = 0; i < NUMMAPS; ++i) { - recscore = READUINT32(save_p); - rectime = (tic_t)READUINT32(save_p); - recrings = READUINT16(save_p); + recscore = P_ReadUINT32(save_p); + rectime = (tic_t)P_ReadUINT32(save_p); + recrings = P_ReadUINT16(save_p); if (recrings > 10000 || recscore > MAXSCORE) I_Error("Bad $$$.sav dearchiving Emblems (invalid score)"); @@ -4867,16 +5183,16 @@ static inline void P_NetUnArchiveEmblems(void) // Nights records for (i = 0; i < NUMMAPS; ++i) { - if ((recmares = READUINT8(save_p)) == 0) + if ((recmares = P_ReadUINT8(save_p)) == 0) continue; G_AllocNightsRecordData((INT16)i, data); for (curmare = 0; curmare < (recmares+1); ++curmare) { - data->nightsrecords[i]->score[curmare] = READUINT32(save_p); - data->nightsrecords[i]->grade[curmare] = READUINT8(save_p); - data->nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p); + data->nightsrecords[i]->score[curmare] = P_ReadUINT32(save_p); + data->nightsrecords[i]->grade[curmare] = P_ReadUINT8(save_p); + data->nightsrecords[i]->time[curmare] = (tic_t)P_ReadUINT32(save_p); if (data->nightsrecords[i]->grade[curmare] > GRADE_S) { @@ -4888,18 +5204,18 @@ static inline void P_NetUnArchiveEmblems(void) } // Mid-map stuff - unlocktriggers = READUINT32(save_p); + unlocktriggers = P_ReadUINT32(save_p); for (i = 0; i < MAXPLAYERS; ++i) { - if ((recmares = READUINT8(save_p)) == 0) + if ((recmares = P_ReadUINT8(save_p)) == 0) continue; for (curmare = 0; curmare < (recmares+1); ++curmare) { - ntemprecords[i].score[curmare] = READUINT32(save_p); - ntemprecords[i].grade[curmare] = READUINT8(save_p); - ntemprecords[i].time[curmare] = (tic_t)READUINT32(save_p); + ntemprecords[i].score[curmare] = P_ReadUINT32(save_p); + ntemprecords[i].grade[curmare] = P_ReadUINT8(save_p); + ntemprecords[i].time[curmare] = (tic_t)P_ReadUINT32(save_p); if (ntemprecords[i].grade[curmare] > GRADE_S) { @@ -4911,37 +5227,37 @@ static inline void P_NetUnArchiveEmblems(void) } } -static void P_NetArchiveSectorPortals(void) +static void P_NetArchiveSectorPortals(save_t *save_p) { - WRITEUINT32(save_p, ARCHIVEBLOCK_SECPORTALS); + P_WriteUINT32(save_p, ARCHIVEBLOCK_SECPORTALS); - WRITEUINT32(save_p, secportalcount); + P_WriteUINT32(save_p, secportalcount); for (size_t i = 0; i < secportalcount; i++) { UINT8 type = secportals[i].type; - WRITEUINT8(save_p, type); - WRITEFIXED(save_p, secportals[i].origin.x); - WRITEFIXED(save_p, secportals[i].origin.y); + P_WriteUINT8(save_p, type); + P_WriteUINT8(save_p, secportals[i].ceiling ? 1 : 0); + P_WriteUINT32(save_p, SaveSector(secportals[i].target)); switch (type) { case SECPORTAL_LINE: - WRITEUINT32(save_p, SaveLine(secportals[i].line.start)); - WRITEUINT32(save_p, SaveLine(secportals[i].line.dest)); + P_WriteUINT32(save_p, SaveLine(secportals[i].line.start)); + P_WriteUINT32(save_p, SaveLine(secportals[i].line.dest)); break; case SECPORTAL_PLANE: case SECPORTAL_HORIZON: case SECPORTAL_FLOOR: case SECPORTAL_CEILING: - WRITEUINT32(save_p, SaveSector(secportals[i].sector)); + P_WriteUINT32(save_p, SaveSector(secportals[i].sector)); break; case SECPORTAL_OBJECT: - if (secportals[i].mobj && !P_MobjWasRemoved(secportals[i].mobj)) - SaveMobjnum(secportals[i].mobj); + if (!P_MobjWasRemoved(secportals[i].mobj)) + P_WriteUINT32(save_p, SaveMobjnum(secportals[i].mobj)); else - WRITEUINT32(save_p, 0); + P_WriteUINT32(save_p, 0); break; default: break; @@ -4949,15 +5265,15 @@ static void P_NetArchiveSectorPortals(void) } } -static void P_NetUnArchiveSectorPortals(void) +static void P_NetUnArchiveSectorPortals(save_t *save_p) { - if (READUINT32(save_p) != ARCHIVEBLOCK_SECPORTALS) + if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_SECPORTALS) I_Error("Bad $$$.sav at archive block Secportals"); Z_Free(secportals); P_InitSectorPortals(); - UINT32 count = READUINT32(save_p); + UINT32 count = P_ReadUINT32(save_p); for (UINT32 i = 0; i < count; i++) { @@ -4965,24 +5281,24 @@ static void P_NetUnArchiveSectorPortals(void) sectorportal_t *secportal = &secportals[id]; - secportal->type = READUINT8(save_p); - secportal->origin.x = READFIXED(save_p); - secportal->origin.y = READFIXED(save_p); + secportal->type = P_ReadUINT8(save_p); + secportal->ceiling = (P_ReadUINT8(save_p) != 0) ? true : false; + secportal->target = LoadSector(P_ReadUINT32(save_p)); switch (secportal->type) { case SECPORTAL_LINE: - secportal->line.start = LoadLine(READUINT32(save_p)); - secportal->line.dest = LoadLine(READUINT32(save_p)); + secportal->line.start = LoadLine(P_ReadUINT32(save_p)); + secportal->line.dest = LoadLine(P_ReadUINT32(save_p)); break; case SECPORTAL_PLANE: case SECPORTAL_HORIZON: case SECPORTAL_FLOOR: case SECPORTAL_CEILING: - secportal->sector = LoadSector(READUINT32(save_p)); + secportal->sector = LoadSector(P_ReadUINT32(save_p)); break; case SECPORTAL_OBJECT: - id = READUINT32(save_p); + id = P_ReadUINT32(save_p); secportal->mobj = (id == 0) ? NULL : P_FindNewPosition(id); break; default: @@ -4991,7 +5307,7 @@ static void P_NetUnArchiveSectorPortals(void) } } -static inline void P_ArchiveLuabanksAndConsistency(void) +static inline void P_ArchiveLuabanksAndConsistency(save_t *save_p) { UINT8 i, banksinuse = NUM_LUABANKS; @@ -5000,30 +5316,30 @@ static inline void P_ArchiveLuabanksAndConsistency(void) if (banksinuse) { - WRITEUINT8(save_p, 0xb7); // luabanks marker - WRITEUINT8(save_p, banksinuse); + P_WriteUINT8(save_p, 0xb7); // luabanks marker + P_WriteUINT8(save_p, banksinuse); for (i = 0; i < banksinuse; i++) - WRITEINT32(save_p, luabanks[i]); + P_WriteINT32(save_p, luabanks[i]); } - WRITEUINT8(save_p, 0x1d); // consistency marker + P_WriteUINT8(save_p, 0x1d); // consistency marker } -static inline boolean P_UnArchiveLuabanksAndConsistency(void) +static inline boolean P_UnArchiveLuabanksAndConsistency(save_t *save_p) { - switch (READUINT8(save_p)) + switch (P_ReadUINT8(save_p)) { case 0xb7: // luabanks marker { - UINT8 i, banksinuse = READUINT8(save_p); + UINT8 i, banksinuse = P_ReadUINT8(save_p); if (banksinuse > NUM_LUABANKS) { CONS_Alert(CONS_ERROR, M_GetText("Corrupt Luabanks! (Too many banks in use)\n")); return false; } for (i = 0; i < banksinuse; i++) - luabanks[i] = READINT32(save_p); - if (READUINT8(save_p) != 0x1d) // consistency marker + luabanks[i] = P_ReadINT32(save_p); + if (P_ReadUINT8(save_p) != 0x1d) // consistency marker { CONS_Alert(CONS_ERROR, M_GetText("Corrupt Luabanks! (Failed consistency check)\n")); return false; @@ -5039,27 +5355,27 @@ static inline boolean P_UnArchiveLuabanksAndConsistency(void) return true; } -void P_SaveGame(INT16 mapnum) +void P_SaveGame(save_t *save_p, INT16 mapnum) { - P_ArchiveMisc(mapnum); - P_ArchivePlayer(); - P_ArchiveLuabanksAndConsistency(); + P_ArchiveMisc(save_p, mapnum); + P_ArchivePlayer(save_p); + P_ArchiveLuabanksAndConsistency(save_p); } -void P_SaveNetGame(boolean resending) +void P_SaveNetGame(save_t *save_p, boolean resending) { thinker_t *th; mobj_t *mobj; INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise - CV_SaveNetVars(&save_p); - P_NetArchiveMisc(resending); - P_NetArchiveEmblems(); + CV_SaveNetVars(save_p); + P_NetArchiveMisc(save_p, resending); + P_NetArchiveEmblems(save_p); // Assign the mobjnumber for pointer tracking for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mobj = (mobj_t *)th; @@ -5068,32 +5384,32 @@ void P_SaveNetGame(boolean resending) mobj->mobjnum = i++; } - P_NetArchivePlayers(); + P_NetArchivePlayers(save_p); if (gamestate == GS_LEVEL) { - P_NetArchiveWorld(); - P_ArchivePolyObjects(); - P_NetArchiveThinkers(); - P_NetArchiveSpecials(); - P_NetArchiveColormaps(); - P_NetArchiveWaypoints(); - P_NetArchiveSectorPortals(); + P_NetArchiveWorld(save_p); + P_ArchivePolyObjects(save_p); + P_NetArchiveThinkers(save_p); + P_NetArchiveSpecials(save_p); + P_NetArchiveColormaps(save_p); + P_NetArchiveWaypoints(save_p); + P_NetArchiveSectorPortals(save_p); } - LUA_Archive(); + LUA_Archive(save_p); - P_ArchiveLuabanksAndConsistency(); + P_ArchiveLuabanksAndConsistency(save_p); } -boolean P_LoadGame(INT16 mapoverride) +boolean P_LoadGame(save_t *save_p, INT16 mapoverride) { if (gamestate == GS_INTERMISSION) Y_EndIntermission(); G_SetGamestate(GS_NULL); // should be changed in P_UnArchiveMisc - P_UnArchiveSPGame(mapoverride); - P_UnArchivePlayer(); + P_UnArchiveSPGame(save_p, mapoverride); + P_UnArchivePlayer(save_p); - if (!P_UnArchiveLuabanksAndConsistency()) + if (!P_UnArchiveLuabanksAndConsistency(save_p)) return false; // Only do this after confirming savegame is ok @@ -5103,26 +5419,26 @@ boolean P_LoadGame(INT16 mapoverride) return true; } -boolean P_LoadNetGame(boolean reloading) +boolean P_LoadNetGame(save_t *save_p, boolean reloading) { - CV_LoadNetVars(&save_p); - if (!P_NetUnArchiveMisc(reloading)) + CV_LoadNetVars(save_p); + if (!P_NetUnArchiveMisc(save_p, reloading)) return false; - P_NetUnArchiveEmblems(); - P_NetUnArchivePlayers(); + P_NetUnArchiveEmblems(save_p); + P_NetUnArchivePlayers(save_p); if (gamestate == GS_LEVEL) { - P_NetUnArchiveWorld(); - P_UnArchivePolyObjects(); - P_NetUnArchiveThinkers(); - P_NetUnArchiveSpecials(); - P_NetUnArchiveColormaps(); - P_NetUnArchiveWaypoints(); - P_NetUnArchiveSectorPortals(); + P_NetUnArchiveWorld(save_p); + P_UnArchivePolyObjects(save_p); + P_NetUnArchiveThinkers(save_p); + P_NetUnArchiveSpecials(save_p); + P_NetUnArchiveColormaps(save_p); + P_NetUnArchiveWaypoints(save_p); + P_NetUnArchiveSectorPortals(save_p); P_RelinkPointers(); P_FinishMobjs(); } - LUA_UnArchive(); + LUA_UnArchive(save_p); // This is stupid and hacky, but maybe it'll work! P_SetRandSeed(P_GetInitSeed()); @@ -5133,5 +5449,5 @@ boolean P_LoadNetGame(boolean reloading) // precipitation when loading a netgame save. Instead, precip has to be spawned here. // This is done in P_NetUnArchiveSpecials now. - return P_UnArchiveLuabanksAndConsistency(); + return P_UnArchiveLuabanksAndConsistency(save_p); } diff --git a/src/p_saveg.h b/src/p_saveg.h index 545008e7e..05e82190a 100644 --- a/src/p_saveg.h +++ b/src/p_saveg.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -18,17 +18,24 @@ #pragma interface #endif +#include "tables.h" + #define NEWSKINSAVES (INT16_MAX) // TODO: 2.3: Delete (Purely for backwards compatibility) // Persistent storage/archiving. // These are the load / save game routines. -void P_SaveGame(INT16 mapnum); -void P_SaveNetGame(boolean resending); -boolean P_LoadGame(INT16 mapoverride); -boolean P_LoadNetGame(boolean reloading); +typedef struct +{ + unsigned char *buf; + size_t size; + size_t pos; +} save_t; -mobj_t *P_FindNewPosition(UINT32 oldposition); +void P_SaveGame(save_t *save_p, INT16 mapnum); +void P_SaveNetGame(save_t *save_p, boolean resending); +boolean P_LoadGame(save_t *save_p, INT16 mapoverride); +boolean P_LoadNetGame(save_t *save_p, boolean reloading); typedef struct { @@ -42,6 +49,37 @@ typedef struct } savedata_t; extern savedata_t savedata; -extern UINT8 *save_p; + +void P_WriteUINT8(save_t *p, UINT8 v); +void P_WriteSINT8(save_t *p, SINT8 v); +void P_WriteUINT16(save_t *p, UINT16 v); +void P_WriteINT16(save_t *p, INT16 v); +void P_WriteUINT32(save_t *p, UINT32 v); +void P_WriteINT32(save_t *p, INT32 v); +void P_WriteChar(save_t *p, char v); +void P_WriteFixed(save_t *p, fixed_t v); +void P_WriteAngle(save_t *p, angle_t v); +void P_WriteStringN(save_t *p, char const *s, size_t n); +void P_WriteStringL(save_t *p, char const *s, size_t n); +void P_WriteString(save_t *p, char const *s); +void P_WriteMem(save_t *p, void const *s, size_t n); + +void P_SkipStringN(save_t *p, size_t n); +void P_SkipStringL(save_t *p, size_t n); +void P_SkipString(save_t *p); + +UINT8 P_ReadUINT8(save_t *p); +SINT8 P_ReadSINT8(save_t *p); +UINT16 P_ReadUINT16(save_t *p); +INT16 P_ReadINT16(save_t *p); +UINT32 P_ReadUINT32(save_t *p); +INT32 P_ReadINT32(save_t *p); +char P_ReadChar(save_t *p); +fixed_t P_ReadFixed(save_t *p); +angle_t P_ReadAngle(save_t *p); +void P_ReadStringN(save_t *p, char *s, size_t n); +void P_ReadStringL(save_t *p, char *s, size_t n); +void P_ReadString(save_t *p, char *s); +void P_ReadMem(save_t *p, void *s, size_t n); #endif diff --git a/src/p_setup.c b/src/p_setup.c index e9bd69dc5..a62e287ac 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -530,7 +530,7 @@ UINT32 P_GetScoreForGradeOverall(INT16 map, UINT8 grade) void P_AddNiGHTSTimes(INT16 i, char *gtext) { char *spos = gtext; - + for (UINT8 n = 0; n < 8; n++) { if (spos != NULL) @@ -692,7 +692,7 @@ void P_ReloadRings(void) // scan the thinkers to find rings/spheres/hoops to unset for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo = (mobj_t *)th; @@ -750,7 +750,7 @@ void P_SwitchSpheresBonusMode(boolean bonustime) // scan the thinkers to find spheres to switch for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo = (mobj_t *)th; @@ -1367,6 +1367,9 @@ static void P_LoadSidedefs(UINT8 *data) sd->scalex_top = sd->scalex_mid = sd->scalex_bottom = FRACUNIT; sd->scaley_top = sd->scaley_mid = sd->scaley_bottom = FRACUNIT; + sd->light = sd->light_top = sd->light_mid = sd->light_bottom = 0; + sd->lightabsolute = sd->lightabsolute_top = sd->lightabsolute_mid = sd->lightabsolute_bottom = false; + P_SetSidedefSector(i, (UINT16)SHORT(msd->sector)); // Special info stored in texture fields! @@ -1977,6 +1980,22 @@ static void ParseTextmapSidedefParameter(UINT32 i, const char *param, const char P_SetSidedefSector(i, atol(val)); else if (fastcmp(param, "repeatcnt")) sides[i].repeatcnt = atol(val); + else if (fastcmp(param, "light")) + sides[i].light = atol(val); + else if (fastcmp(param, "light_top")) + sides[i].light_top = atol(val); + else if (fastcmp(param, "light_mid")) + sides[i].light_mid = atol(val); + else if (fastcmp(param, "light_bottom")) + sides[i].light_bottom = atol(val); + else if (fastcmp(param, "lightabsolute") && fastcmp("true", val)) + sides[i].lightabsolute = true; + else if (fastcmp(param, "lightabsolute_top") && fastcmp("true", val)) + sides[i].lightabsolute_top = true; + else if (fastcmp(param, "lightabsolute_mid") && fastcmp("true", val)) + sides[i].lightabsolute_mid = true; + else if (fastcmp(param, "lightabsolute_bottom") && fastcmp("true", val)) + sides[i].lightabsolute_bottom = true; } static void ParseTextmapLinedefParameter(UINT32 i, const char *param, const char *val) @@ -2704,6 +2723,22 @@ static void P_WriteTextmap(void) fprintf(f, "texturemiddle = \"%.*s\";\n", 8, textures[wsides[i].midtexture]->name); if (wsides[i].repeatcnt != 0) fprintf(f, "repeatcnt = %d;\n", wsides[i].repeatcnt); + if (wsides[i].light != 0) + fprintf(f, "light = %d;\n", wsides[i].light); + if (wsides[i].light_top != 0) + fprintf(f, "light_top = %d;\n", wsides[i].light_top); + if (wsides[i].light_mid != 0) + fprintf(f, "light_mid = %d;\n", wsides[i].light_mid); + if (wsides[i].light_bottom != 0) + fprintf(f, "light_bottom = %d;\n", wsides[i].light_bottom); + if (wsides[i].lightabsolute) + fprintf(f, "lightabsolute = true;\n"); + if (wsides[i].lightabsolute_top) + fprintf(f, "lightabsolute_top = true;\n"); + if (wsides[i].lightabsolute_mid) + fprintf(f, "lightabsolute_mid = true;\n"); + if (wsides[i].lightabsolute_bottom) + fprintf(f, "lightabsolute_bottom = true;\n"); fprintf(f, "}\n"); fprintf(f, "\n"); } @@ -2960,7 +2995,7 @@ static void P_LoadTextmap(void) side_t *sd; mapthing_t *mt; - CONS_Alert(CONS_NOTICE, "UDMF support is still a work-in-progress; its specs and features are prone to change until it is fully implemented.\n"); + //CONS_Alert(CONS_NOTICE, "UDMF support is still a work-in-progress; its specs and features are prone to change until it is fully implemented.\n"); /// Given the UDMF specs, some fields are given a default value. /// If an element's field has a default value set, it is omitted @@ -3040,7 +3075,7 @@ static void P_LoadTextmap(void) // TODO: remove this limitation in a backwards-compatible way (UDMF versioning?) UINT8 lightalpha = (textmap_colormap.lightalpha * 102) / 10; UINT8 fadealpha = (textmap_colormap.fadealpha * 102) / 10; - + INT32 rgba = P_ColorToRGBA(textmap_colormap.lightcolor, lightalpha); INT32 fadergba = P_ColorToRGBA(textmap_colormap.fadecolor, fadealpha); sc->extra_colormap = sc->spawn_extra_colormap = R_CreateColormap(rgba, fadergba, textmap_colormap.fadestart, textmap_colormap.fadeend, textmap_colormap.flags); @@ -3106,6 +3141,8 @@ static void P_LoadTextmap(void) sd->bottomtexture = R_TextureNumForName("-"); sd->sector = NULL; sd->repeatcnt = 0; + sd->light = sd->light_top = sd->light_mid = sd->light_bottom = 0; + sd->lightabsolute = sd->lightabsolute_top = sd->lightabsolute_mid = sd->lightabsolute_bottom = false; TextmapParse(sidedefBlocks.pos[i], i, ParseTextmapSidedefParameter); @@ -7296,7 +7333,7 @@ void P_RespawnThings(void) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (think->removing) continue; P_RemoveMobj((mobj_t *)think); } @@ -7608,20 +7645,20 @@ static void P_InitCamera(void) CV_SetValue(&cv_analog[1], 0); displayplayer = consoleplayer; // Start with your OWN view, please! - } - if (twodlevel) - { - CV_SetValue(&cv_analog[0], false); - CV_SetValue(&cv_analog[1], false); - } - else - { - if (cv_useranalog[0].value) - CV_SetValue(&cv_analog[0], true); + if (twodlevel) + { + CV_SetValue(&cv_analog[0], false); + CV_SetValue(&cv_analog[1], false); + } + else + { + if (cv_useranalog[0].value) + CV_SetValue(&cv_analog[0], true); - if ((splitscreen && cv_useranalog[1].value) || botingame) - CV_SetValue(&cv_analog[1], true); + if ((splitscreen && cv_useranalog[1].value) || botingame) + CV_SetValue(&cv_analog[1], true); + } } } @@ -7816,6 +7853,10 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) maptol = mapheaderinfo[gamemap-1]->typeoflevel; gametyperules = gametypedefaultrules[gametype]; + // clear the target on map change, since the object will be invalidated + P_SetTarget(&ticcmd_ztargetfocus[0], NULL); + P_SetTarget(&ticcmd_ztargetfocus[1], NULL); + CON_Drawer(); // let the user know what we are going to do I_FinishUpdate(); // page flip or blit buffer @@ -7965,6 +8006,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) // Free GPU textures before freeing patches. if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) HWR_ClearAllTextures(); + + // Delete light table textures + HWR_ClearLightTables(); #endif Patch_FreeTag(PU_PATCH_LOWPRIORITY); diff --git a/src/p_setup.h b/src/p_setup.h index da38d4c08..6b0218854 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_slopes.c b/src/p_slopes.c index c2bacad9e..7f070e2a1 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2009 by Stephen McGranahan. -// Copyright (C) 2015-2023 by Sonic Team Junior. +// Copyright (C) 2015-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -181,8 +181,8 @@ void T_DynamicSlopeLine (dynlineplanethink_t* th) { pslope_t* slope = th->slope; line_t* srcline = th->sourceline; - - fixed_t zdelta; + + fixed_t zdelta, oldoz = slope->o.z; switch(th->type) { case DP_FRONTFLOOR: @@ -209,7 +209,7 @@ void T_DynamicSlopeLine (dynlineplanethink_t* th) return; } - if (slope->zdelta != FixedDiv(zdelta, th->extent)) { + if (slope->zdelta != FixedDiv(zdelta, th->extent) || oldoz != slope->o.z) { slope->zdelta = FixedDiv(zdelta, th->extent); slope->zangle = R_PointToAngle2(0, 0, th->extent, -zdelta); slope->moved = true; diff --git a/src/p_slopes.h b/src/p_slopes.h index fdc07f67e..39b7ba56d 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2009 by Stephen McGranahan. -// Copyright (C) 2015-2023 by Sonic Team Junior. +// Copyright (C) 2015-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_spec.c b/src/p_spec.c index 78cf46063..d375d3e2f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -2405,18 +2405,15 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) y = line->args[3] << FRACBITS; z = line->args[4] << FRACBITS; - P_UnsetThingPosition(mo); - mo->x += x; - mo->y += y; - mo->z += z; - P_SetThingPosition(mo); - + P_SetOrigin(mo, mo->x + x, mo->y + y, mo->z + z); + if (mo->player) { if (bot) // This might put poor Tails in a wall if he's too far behind! D: But okay, whatever! >:3 P_SetOrigin(bot, bot->x + x, bot->y + y, bot->z + z); if (splitscreen && mo->player == &players[secondarydisplayplayer] && camera2.chase) { + camera2.reset = true; camera2.x += x; camera2.y += y; camera2.z += z; @@ -2424,6 +2421,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } else if (camera.chase && mo->player == &players[displayplayer]) { + camera.reset = true; camera.x += x; camera.y += y; camera.z += z; @@ -3644,7 +3642,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (mo2->type != MT_EGGTRAP) continue; - if (mo2->thinker.function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (mo2->thinker.removing) continue; P_KillMobj(mo2, NULL, mo, 0); @@ -3856,7 +3854,7 @@ void P_SetupSignExit(player_t *player) // spin all signposts in the level then. for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (think->removing) continue; thing = (mobj_t *)think; @@ -3894,7 +3892,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (think->removing) continue; mo = (mobj_t *)think; @@ -4397,7 +4395,7 @@ static void P_ProcessEggCapsule(player_t *player, sector_t *sector) // The chimps are my friends.. heeheeheheehehee..... - LouisJM for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; if (mo2->type != MT_EGGTRAP) @@ -6238,7 +6236,7 @@ static void P_DoPortalCopyFromLine(sector_t *dest_sector, int plane_type, int ta } } -static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num, UINT32 *result) +static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num, UINT32 *result, boolean ceiling) { sectorportal_t *secportal = NULL; @@ -6246,8 +6244,8 @@ static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num, { *num = P_NewSectorPortal(); secportal = &secportals[*num]; - secportal->origin.x = sector->soundorg.x; - secportal->origin.y = sector->soundorg.y; + secportal->target = sector; + secportal->ceiling = ceiling; *result = *num; } else @@ -6261,12 +6259,12 @@ static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num, static sectorportal_t *P_SectorGetFloorPortalOrCreate(sector_t *sector, UINT32 *result) { - return P_SectorGetPortalOrCreate(sector, §or->portal_floor, result); + return P_SectorGetPortalOrCreate(sector, §or->portal_floor, result, false); } static sectorportal_t *P_SectorGetCeilingPortalOrCreate(sector_t *sector, UINT32 *result) { - return P_SectorGetPortalOrCreate(sector, §or->portal_ceiling, result); + return P_SectorGetPortalOrCreate(sector, §or->portal_ceiling, result, true); } static void P_CopySectorPortalToLines(UINT32 portal_num, int sector_tag) diff --git a/src/p_spec.h b/src/p_spec.h index b9c3a2ca3..ba08781b6 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_tick.c b/src/p_tick.c index 56e0fd897..db8688484 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -162,7 +162,7 @@ void Command_CountMobjs_f(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; if (((mobj_t *)th)->type == i) @@ -182,7 +182,7 @@ void Command_CountMobjs_f(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; if (((mobj_t *)th)->type == i) @@ -348,6 +348,7 @@ void P_RemoveThinkerDelayed(thinker_t *thinker) void P_RemoveThinker(thinker_t *thinker) { LUA_InvalidateUserdata(thinker); + thinker->removing = true; thinker->function.acp1 = (actionf_p1)P_RemoveThinkerDelayed; } diff --git a/src/p_user.c b/src/p_user.c index 7ad5bccbb..3301987a2 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -435,7 +435,7 @@ UINT8 P_FindLowestMare(void) // to find the egg capsule with the lowest mare for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -488,7 +488,7 @@ boolean P_TransferToNextMare(player_t *player) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -539,7 +539,7 @@ static mobj_t *P_FindAxis(INT32 mare, INT32 axisnum) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -574,7 +574,7 @@ static mobj_t *P_FindAxisTransfer(INT32 mare, INT32 axisnum, mobjtype_t type) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -615,7 +615,7 @@ void P_TransferToAxis(player_t *player, INT32 axisnum) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -716,7 +716,7 @@ static void P_DeNightserizePlayer(player_t *player) // Check to see if the player should be killed. for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -976,6 +976,9 @@ pflags_t P_GetJumpFlags(player_t *player) // boolean P_PlayerInPain(player_t *player) { + if (P_MobjWasRemoved(player->mo)) + return false; + // no silly, sliding isn't pain if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing]) return true; @@ -1896,7 +1899,7 @@ void P_SpawnShieldOrb(player_t *player) // blaze through the thinkers to see if an orb already exists! for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; shieldobj = (mobj_t *)th; @@ -2078,6 +2081,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->renderflags = mobj->renderflags; ghost->blendmode = mobj->blendmode; + ghost->alpha = mobj->alpha; ghost->spritexscale = mobj->spritexscale; ghost->spriteyscale = mobj->spriteyscale; @@ -5108,7 +5112,7 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -6475,7 +6479,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad // Find next waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -6511,7 +6515,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad { for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -6540,7 +6544,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad { for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -7272,7 +7276,7 @@ static void P_NiGHTSMovement(player_t *player) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -8172,7 +8176,7 @@ void P_MovePlayer(player_t *player) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -8825,6 +8829,8 @@ void P_MovePlayer(player_t *player) player->mo->height = P_GetPlayerSpinHeight(player); atspinheight = true; } + else if (player->powers[pw_carry] == CR_PLAYER || player->powers[pw_carry] == CR_PTERABYTE) // You're slightly shorter while being carried + player->mo->height = FixedDiv(P_GetPlayerHeight(player), FixedDiv(14*FRACUNIT,10*FRACUNIT)); else player->mo->height = P_GetPlayerHeight(player); @@ -9155,7 +9161,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (think->removing) continue; mo = (mobj_t *)think; @@ -9253,7 +9259,7 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction, for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (think->removing) continue; mo = (mobj_t *)think; @@ -9372,7 +9378,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (think->removing) continue; mo = (mobj_t *)think; @@ -9518,7 +9524,7 @@ void P_FindEmerald(void) // to find all emeralds for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -10919,7 +10925,7 @@ static mobj_t *P_GetAxis(INT32 num) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mobj = (mobj_t *)th; @@ -12001,7 +12007,7 @@ void P_PlayerThink(player_t *player) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -12846,9 +12852,9 @@ void P_PlayerAfterThink(player_t *player) else { if (tails->player) - P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*FRACUNIT), true); + P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*tails->scale), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*tails->scale), true); else - P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->angle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->angle, 4*FRACUNIT), true); + P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->angle, 4*tails->scale), tails->y + P_ReturnThrustY(tails, tails->angle, 4*tails->scale), true); player->mo->momx = tails->momx; player->mo->momy = tails->momy; player->mo->momz = tails->momz; @@ -12862,7 +12868,7 @@ void P_PlayerAfterThink(player_t *player) P_SetPlayerAngle(player, player->mo->angle); } - if (P_AproxDistance(player->mo->x - tails->x, player->mo->y - tails->y) > player->mo->radius) + if (P_AproxDistance(player->mo->x - tails->x, player->mo->y - tails->y) > tails->radius) player->powers[pw_carry] = CR_NONE; if (player->powers[pw_carry] == CR_PLAYER) @@ -13083,7 +13089,7 @@ void P_PlayerAfterThink(player_t *player) player->mo->momy = ptera->momy; player->mo->momz = ptera->momz; - if (P_AproxDistance(player->mo->x - ptera->x - ptera->watertop, player->mo->y - ptera->y - ptera->waterbottom) > player->mo->radius) + if (P_AproxDistance(player->mo->x - ptera->x - ptera->watertop, player->mo->y - ptera->y - ptera->waterbottom) > ptera->radius) goto dropoff; ptera->watertop >>= 1; diff --git a/src/r_bsp.c b/src/r_bsp.c index d606d7a27..ad27b9bf8 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -230,6 +230,18 @@ static INT32 R_DoorClosed(void) && (backsector->floorheight <= frontsector->floorheight || curline->sidedef->bottomtexture); } +static UINT8 R_FloorLightLevel(sector_t *sector, INT16 base_lightlevel) +{ + return max(0, min(255, sector->floorlightlevel + + ((sector->floorlightabsolute) ? 0 : base_lightlevel))); +} + +static UINT8 R_CeilingLightLevel(sector_t *sector, INT16 base_lightlevel) +{ + return max(0, min(255, sector->ceilinglightlevel + + ((sector->ceilinglightabsolute) ? 0 : base_lightlevel))); +} + // // If player's view height is underneath fake floor, lower the // drawn ceiling to be just under the floor height, and replace @@ -312,11 +324,11 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->lightlevel = s->lightlevel; if (floorlightlevel) - *floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel))) + *floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel))) : sectors[s->floorlightsec].lightlevel; if (ceilinglightlevel) - *ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel))) + *ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel))) : sectors[s->ceilinglightsec].lightlevel; } else if (heightsec != -1 && viewz >= sectors[heightsec].ceilingheight @@ -356,11 +368,11 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->lightlevel = s->lightlevel; if (floorlightlevel) - *floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel))) + *floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel))) : sectors[s->floorlightsec].lightlevel; if (ceilinglightlevel) - *ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel))) + *ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel))) : sectors[s->ceilinglightsec].lightlevel; } sec = tempsec; @@ -968,11 +980,10 @@ static void R_Subsector(size_t num) && ((viewz < heightcheck && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES))) || (viewz > heightcheck && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES)))) { - light = R_GetPlaneLight(frontsector, planecenterz, - viewz < heightcheck); + light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck); ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->bottomheight, *rover->bottompic, - *frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, *rover->bottomyoffs, + R_FloorLightLevel(rover->master->frontsector, *frontsector->lightlist[light].lightlevel), *rover->bottomxoffs, *rover->bottomyoffs, *rover->bottomxscale, *rover->bottomyscale, *rover->bottomangle, *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope, NULL); @@ -1002,7 +1013,7 @@ static void R_Subsector(size_t num) light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck); ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->topheight, *rover->toppic, - *frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, + R_CeilingLightLevel(rover->master->frontsector, *frontsector->lightlist[light].lightlevel), *rover->topxoffs, *rover->topyoffs, *rover->topxscale, *rover->topyscale, *rover->topangle, *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->t_slope, NULL); diff --git a/src/r_data.c b/src/r_data.c index 75ec0556d..32faa07a8 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -426,9 +426,6 @@ void R_ClearColormaps(void) { // Purged by PU_LEVEL, just overwrite the pointer extra_colormaps = R_CreateDefaultColormap(true); -#ifdef HWRENDER - HWR_ClearLightTables(); -#endif } // @@ -849,6 +846,15 @@ void R_GenerateLightTable(extracolormap_t *extra_colormap, boolean uselookup) } } +void R_UpdateLightTable(extracolormap_t *extra_colormap, boolean uselookup) +{ + R_GenerateLightTable(extra_colormap, uselookup); + +#ifdef HWRENDER + extra_colormap->gl_lighttable.needs_update = true; +#endif +} + extracolormap_t *R_CreateColormapFromLinedef(char *p1, char *p2, char *p3) { // default values diff --git a/src/r_data.h b/src/r_data.h index 9340ed284..64abf6d83 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -90,6 +90,7 @@ typedef enum } textmapcolormapflags_t; void R_GenerateLightTable(extracolormap_t *extra_colormap, boolean uselookup); +void R_UpdateLightTable(extracolormap_t *extra_colormap, boolean uselookup); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); extracolormap_t * R_CreateColormapFromLinedef(char *p1, char *p2, char *p3); extracolormap_t* R_CreateColormap(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags); diff --git a/src/r_defs.h b/src/r_defs.h index 54d43e824..eac3e2d1f 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -60,6 +60,8 @@ typedef UINT8 lighttable_t; #define CMF_FADEFULLBRIGHTSPRITES 1 #define CMF_FOG 4 +#define TEXTURE_255_IS_TRANSPARENT + // ExtraColormap type. Use for extra_colormaps from now on. typedef struct extracolormap_s { @@ -74,8 +76,11 @@ typedef struct extracolormap_s lighttable_t *colormap; #ifdef HWRENDER - // The id of the hardware lighttable. Zero means it does not exist yet. - UINT32 gl_lighttable_id; + struct { + UINT32 id; // The id of the hardware lighttable. Zero means it does not exist yet. + RGBA_t *data; // The texture data of the hardware lighttable. + boolean needs_update; // If the colormap changed recently or not. + } gl_lighttable; #endif #ifdef EXTRACOLORMAPLUMPS @@ -240,9 +245,8 @@ typedef struct sectorportal_s struct sector_s *sector; struct mobj_s *mobj; }; - struct { - fixed_t x, y; - } origin; + struct sector_s *target; + boolean ceiling; } sectorportal_t; typedef struct ffloor_s @@ -631,6 +635,11 @@ typedef struct fixed_t scalex_top, scalex_mid, scalex_bottom; fixed_t scaley_top, scaley_mid, scaley_bottom; + // per-wall lighting for UDMF + // TODO: implement per-texture lighting + INT16 light, light_top, light_mid, light_bottom; + boolean lightabsolute, lightabsolute_top, lightabsolute_mid, lightabsolute_bottom; + // Texture indices. // We do not maintain names here. INT32 toptexture, bottomtexture, midtexture; diff --git a/src/r_draw.c b/src/r_draw.c index feb4693bb..906398ec4 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -19,7 +19,6 @@ #include "doomstat.h" #include "r_local.h" #include "r_translation.h" -#include "st_stuff.h" // need ST_HEIGHT #include "i_video.h" #include "v_video.h" #include "m_misc.h" diff --git a/src/r_draw.h b/src/r_draw.h index 77588d7de..d5c5b4e25 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -154,9 +154,11 @@ void R_VideoErase(size_t ofs, INT32 count); void R_DrawColumn_8(void); void R_DrawColumnClamped_8(void); +void R_Draw2sMultiPatchColumn_8(void); void R_DrawShadeColumn_8(void); void R_DrawTranslucentColumn_8(void); void R_DrawTranslucentColumnClamped_8(void); +void R_Draw2sMultiPatchTranslucentColumn_8(void); void R_DrawDropShadowColumn_8(void); void R_DrawTranslatedColumn_8(void); void R_DrawTranslatedTranslucentColumn_8(void); @@ -171,6 +173,7 @@ void R_DrawTiltedTranslucentSpan_8(void); void R_DrawSplat_8(void); void R_DrawTranslucentSplat_8(void); void R_DrawTiltedSplat_8(void); +void R_DrawTiltedTranslucentSplat_8(void); void R_DrawFloorSprite_8(void); void R_DrawTranslucentFloorSprite_8(void); @@ -192,6 +195,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void); void R_DrawSplat_NPO2_8(void); void R_DrawTranslucentSplat_NPO2_8(void); void R_DrawTiltedSplat_NPO2_8(void); +void R_DrawTiltedTranslucentSplat_NPO2_8(void); void R_DrawFloorSprite_NPO2_8(void); void R_DrawTranslucentFloorSprite_NPO2_8(void); diff --git a/src/r_draw8.c b/src/r_draw8.c index 735127f88..c720f454e 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -192,6 +192,189 @@ void R_DrawColumnClamped_8(void) } } +void R_Draw2sMultiPatchColumn_8(void) +{ + INT32 count; + register UINT8 *dest; + register fixed_t frac; + fixed_t fracstep; + + count = dc_yh - dc_yl; + + if (count < 0) // Zero length, column does not exceed a pixel. + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + return; +#endif + + // Framebuffer destination address. + dest = &topleft[dc_yl*vid.width + dc_x]; + + count++; + + // Determine scaling, which is the only mapping to be done. + fracstep = dc_iscale; + frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep); + + // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. + // This is as fast as it gets. + { + register const UINT8 *source = dc_source; + register const lighttable_t *colormap = dc_colormap; + register INT32 heightmask = dc_texheight-1; + register UINT8 val; + if (dc_texheight & heightmask) // not a power of 2 -- killough + { + heightmask++; + heightmask <<= FRACBITS; + + if (frac < 0) + while ((frac += heightmask) < 0); + else + while (frac >= heightmask) + frac -= heightmask; + + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + // heightmask is the Tutti-Frutti fix + val = source[frac>>FRACBITS]; + + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + + dest += vid.width; + + // Avoid overflow. + if (fracstep > 0x7FFFFFFF - frac) + frac += fracstep - heightmask; + else + frac += fracstep; + + while (frac >= heightmask) + frac -= heightmask; + } while (--count); + } + else + { + while ((count -= 2) >= 0) // texture height is a power of 2 + { + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + dest += vid.width; + frac += fracstep; + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + dest += vid.width; + frac += fracstep; + } + if (count & 1) + { + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + } + } + } +} + +void R_Draw2sMultiPatchTranslucentColumn_8(void) +{ + INT32 count; + register UINT8 *dest; + register fixed_t frac; + fixed_t fracstep; + + count = dc_yh - dc_yl; + + if (count < 0) // Zero length, column does not exceed a pixel. + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + return; +#endif + + // Framebuffer destination address. + dest = &topleft[dc_yl*vid.width + dc_x]; + + count++; + + // Determine scaling, which is the only mapping to be done. + fracstep = dc_iscale; + frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep); + + // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. + // This is as fast as it gets. + { + register const UINT8 *source = dc_source; + register const UINT8 *transmap = dc_transmap; + register const lighttable_t *colormap = dc_colormap; + register INT32 heightmask = dc_texheight-1; + register UINT8 val; + if (dc_texheight & heightmask) // not a power of 2 -- killough + { + heightmask++; + heightmask <<= FRACBITS; + + if (frac < 0) + while ((frac += heightmask) < 0); + else + while (frac >= heightmask) + frac -= heightmask; + + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + // heightmask is the Tutti-Frutti fix + val = source[frac>>FRACBITS]; + + if (val != TRANSPARENTPIXEL) + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + + dest += vid.width; + + // Avoid overflow. + if (fracstep > 0x7FFFFFFF - frac) + frac += fracstep - heightmask; + else + frac += fracstep; + + while (frac >= heightmask) + frac -= heightmask; + } while (--count); + } + else + { + while ((count -= 2) >= 0) // texture height is a power of 2 + { + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + dest += vid.width; + frac += fracstep; + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + dest += vid.width; + frac += fracstep; + } + if (count & 1) + { + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + } + } + } +} + /** \brief The R_DrawShadeColumn_8 function Experiment to make software go faster. Taken from the Boom source */ @@ -1118,6 +1301,136 @@ void R_DrawTiltedSplat_8(void) #endif } +void R_DrawTiltedTranslucentSplat_8(void) +{ + // x1, x2 = ds_x1, ds_x2 + int width = ds_x2 - ds_x1; + double iz, uz, vz; + UINT32 u, v; + int i; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + + UINT8 val; + + double startz, startu, startv; + double izstep, uzstep, vzstep; + double endz, endu, endv; + UINT32 stepu, stepv; + + iz = ds_sz.z + ds_sz.y*(centery-ds_y) + ds_sz.x*(ds_x1-centerx); + uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx); + vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx); + + R_CalcSlopeLight(); + + dest = &topleft[ds_y*vid.width + ds_x1]; + source = ds_source; + //colormap = ds_colormap; + +#if 0 // The "perfect" reference version of this routine. Pretty slow. + // Use it only to see how things are supposed to look. + i = 0; + do + { + double z = 1.f/iz; + u = (INT64)(uz*z); + v = (INT64)(vz*z); + + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + + dest++; + iz += ds_sz.x; + uz += ds_su.x; + vz += ds_sv.x; + } while (--width >= 0); +#else + startz = 1.f/iz; + startu = uz*startz; + startv = vz*startz; + + izstep = ds_sz.x * SPANSIZE; + uzstep = ds_su.x * SPANSIZE; + vzstep = ds_sv.x * SPANSIZE; + //x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + stepu = (INT64)((endu - startu) * INVSPAN); + stepv = (INT64)((endv - startv) * INVSPAN); + u = (INT64)(startu); + v = (INT64)(startv); + + for (i = SPANSIZE-1; i >= 0; i--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 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); + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + } + else + { + double left = width; + iz += ds_sz.x * left; + uz += ds_su.x * left; + vz += ds_sv.x * left; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + left = 1.f/left; + stepu = (INT64)((endu - startu) * left); + stepv = (INT64)((endv - startv) * left); + u = (INT64)(startu); + v = (INT64)(startv); + + for (; width != 0; width--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + u += stepu; + v += stepv; + } + } + } +#endif +} + /** \brief The R_DrawSplat_8 function Just like R_DrawSpan_8, but skips transparent pixels. */ diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index 1ed3a8fa4..7fbb40d84 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -666,6 +666,204 @@ void R_DrawTiltedSplat_NPO2_8(void) #endif } +void R_DrawTiltedTranslucentSplat_NPO2_8(void) +{ + // x1, x2 = ds_x1, ds_x2 + int width = ds_x2 - ds_x1; + double iz, uz, vz; + UINT32 u, v; + int i; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + + UINT8 val; + + double startz, startu, startv; + double izstep, uzstep, vzstep; + double endz, endu, endv; + UINT32 stepu, stepv; + + struct libdivide_u32_t x_divider = libdivide_u32_gen(ds_flatwidth); + struct libdivide_u32_t y_divider = libdivide_u32_gen(ds_flatheight); + + iz = ds_sz.z + ds_sz.y*(centery-ds_y) + ds_sz.x*(ds_x1-centerx); + uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx); + vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx); + + R_CalcSlopeLight(); + + dest = &topleft[ds_y*vid.width + ds_x1]; + source = ds_source; + //colormap = ds_colormap; + +#if 0 // The "perfect" reference version of this routine. Pretty slow. + // Use it only to see how things are supposed to look. + i = 0; + do + { + double z = 1.f/iz; + u = (INT64)(uz*z); + v = (INT64)(vz*z); + + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; + if (y < 0) + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + + dest++; + iz += ds_sz.x; + uz += ds_su.x; + vz += ds_sv.x; + } while (--width >= 0); +#else + startz = 1.f/iz; + startu = uz*startz; + startv = vz*startz; + + izstep = ds_sz.x * SPANSIZE; + uzstep = ds_su.x * SPANSIZE; + vzstep = ds_sv.x * SPANSIZE; + //x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + stepu = (INT64)((endu - startu) * INVSPAN); + stepv = (INT64)((endv - startv) * INVSPAN); + u = (INT64)(startu); + v = (INT64)(startv); + + for (i = SPANSIZE-1; i >= 0; i--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; + if (y < 0) + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 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); + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; + if (y < 0) + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + } + else + { + double left = width; + iz += ds_sz.x * left; + uz += ds_su.x * left; + vz += ds_sv.x * left; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + left = 1.f/left; + stepu = (INT64)((endu - startu) * left); + stepv = (INT64)((endv - startv) * left); + u = (INT64)(startu); + v = (INT64)(startv); + + for (; width != 0; width--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; + if (y < 0) + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + u += stepu; + v += stepv; + } + } + } +#endif +} + /** \brief The R_DrawSplat_NPO2_8 function Just like R_DrawSpan_NPO2_8, but skips transparent pixels. */ diff --git a/src/r_fps.c b/src/r_fps.c index 7f1f2bb30..71f6e59a7 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze, Andrey Budko (prboom) -// Copyright (C) 1999-2019 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_fps.h b/src/r_fps.h index 33224a83a..ce64d19be 100644 --- a/src/r_fps.h +++ b/src/r_fps.h @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze, Andrey Budko (prboom) -// Copyright (C) 1999-2019 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_main.c b/src/r_main.c index 067b8abdb..ee05876da 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1152,8 +1152,14 @@ void R_SetupFrame(player_t *player) if (quake.epicenter) { // Calculate 3D distance from epicenter, using the camera. - fixed_t xydist = R_PointToDist2(thiscam->x, thiscam->y, quake.epicenter->x, quake.epicenter->y); - fixed_t dist = R_PointToDist2(0, thiscam->z, xydist, quake.epicenter->z); + fixed_t xydist, dist; + if (P_MobjWasRemoved(r_viewmobj)) { + xydist = R_PointToDist2(thiscam->x, thiscam->y, quake.epicenter->x, quake.epicenter->y); + dist = R_PointToDist2(0, thiscam->z, xydist, quake.epicenter->z); + } else { + xydist = R_PointToDist2(r_viewmobj->x, r_viewmobj->y, quake.epicenter->x, quake.epicenter->y); + dist = R_PointToDist2(0, r_viewmobj->z, xydist, quake.epicenter->z); + } // More effect closer to epicenter, outside of radius = no effect if (!quake.radius || dist > quake.radius) @@ -1428,6 +1434,9 @@ static void R_PortalFrame(portal_t *portal) viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); + if (!P_MobjWasRemoved(portal->viewmobj)) + r_viewmobj = portal->viewmobj; + portalclipstart = portal->start; portalclipend = portal->end; diff --git a/src/r_main.h b/src/r_main.h index 64a69fffe..af7086e83 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patch.c b/src/r_patch.c index a6a9dc2eb..19e66404f 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2023 by Lactozilla. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patch.h b/src/r_patch.h index f1a018c03..ff76254e8 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2024 by Lactozilla. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index b91069849..989665d74 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2023 by Lactozilla. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patchrotation.h b/src/r_patchrotation.h index a239ac5fa..184d7ac13 100644 --- a/src/r_patchrotation.h +++ b/src/r_patchrotation.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2023 by Lactozilla. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_picformats.c b/src/r_picformats.c index d71657021..a45c143b0 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -2,8 +2,8 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 2005-2009 by Andrey "entryway" Budko. -// Copyright (C) 2018-2023 by Jaime "Lactozilla" Passos. -// Copyright (C) 2019-2023 by Sonic Team Junior. +// Copyright (C) 2018-2024 by Lactozilla. +// Copyright (C) 2019-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_picformats.h b/src/r_picformats.h index 098f927a5..123dda976 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 2018-2023 by Jaime "Lactozilla" Passos. -// Copyright (C) 2019-2023 by Sonic Team Junior. +// Copyright (C) 2018-2024 by Lactozilla. +// Copyright (C) 2019-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_plane.c b/src/r_plane.c index 33e3aac13..a0de048ea 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -83,7 +83,7 @@ static fixed_t planeheight; fixed_t yslopetab[MAXVIDHEIGHT*16]; fixed_t *yslope; -static fixed_t xoffs, yoffs; +static INT64 xoffs, yoffs; static dvector3_t slope_origin, slope_u, slope_v; static dvector3_t slope_lightu, slope_lightv; @@ -376,19 +376,25 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li visplane_t *check; unsigned hash; + float offset_xd = FixedToFloat(xoff) / FixedToFloat(xscale ? xscale : 1); + float offset_yd = FixedToFloat(yoff) / FixedToFloat(yscale ? yscale : 1); + + INT64 offset_x = offset_xd * FRACUNIT; + INT64 offset_y = offset_yd * FRACUNIT; + if (!slope) // Don't mess with this right now if a slope is involved { - xoff += FixedMul(viewx, xscale); - yoff -= FixedMul(viewy, yscale); + offset_x += viewx; + offset_y -= viewy; if (plangle != 0) { // Add the view offset, rotated by the plane angle. float ang = ANG2RAD(plangle); - float x = FixedToFloat(xoff); - float y = FixedToFloat(yoff); - xoff = FloatToFixed(x * cos(ang) + y * sin(ang)); - yoff = FloatToFixed(-x * sin(ang) + y * cos(ang)); + float x = offset_x / (float)FRACUNIT; + float y = offset_y / (float)FRACUNIT; + offset_x = (x * cos(ang) + y * sin(ang)) * FRACUNIT; + offset_y = (-x * sin(ang) + y * cos(ang)) * FRACUNIT; } } @@ -399,16 +405,19 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li float ang = ANG2RAD(polyobj->angle); float x = FixedToFloat(polyobj->centerPt.x); float y = FixedToFloat(polyobj->centerPt.y); - xoff -= FloatToFixed(x * cos(ang) + y * sin(ang)); - yoff -= FloatToFixed(x * sin(ang) - y * cos(ang)); + offset_x -= (x * cos(ang) + y * sin(ang)) * FRACUNIT; + offset_y -= (x * sin(ang) - y * cos(ang)) * FRACUNIT; } else { - xoff -= polyobj->centerPt.x; - yoff += polyobj->centerPt.y; + offset_x -= polyobj->centerPt.x; + offset_y += polyobj->centerPt.y; } } + offset_x = ((INT64)offset_x * xscale) / FRACUNIT; + offset_y = ((INT64)offset_y * yscale) / FRACUNIT; + // This appears to fix the Nimbus Ruins sky bug. if (picnum == skyflatnum && pfloor) { @@ -423,7 +432,7 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li { if (height == check->height && picnum == check->picnum && lightlevel == check->lightlevel - && xoff == check->xoffs && yoff == check->yoffs + && offset_x == check->xoffs && offset_y == check->yoffs && xscale == check->xscale && yscale == check->yscale && planecolormap == check->extra_colormap && check->viewx == viewx && check->viewy == viewy && check->viewz == viewz @@ -449,8 +458,8 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li check->lightlevel = lightlevel; check->minx = vid.width; check->maxx = -1; - check->xoffs = xoff; - check->yoffs = yoff; + check->xoffs = offset_x; + check->yoffs = offset_y; check->xscale = xscale; check->yscale = yscale; check->extra_colormap = planecolormap; @@ -658,13 +667,13 @@ static void R_DrawSkyPlane(visplane_t *pl) } // Returns the height of the sloped plane at (x, y) as a double -static double R_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y) +static double R_GetSlopeZAt(const pslope_t *slope, INT64 x, INT64 y) { // If you want to reimplement this using just the equation constants, use this instead: // (d + a*x + b*y) * -(1.0 / c) - double px = FixedToDouble(x) - slope->dorigin.x; - double py = FixedToDouble(y) - slope->dorigin.y; + double px = (x / (double)FRACUNIT) - slope->dorigin.x; + double py = (y / (double)FRACUNIT) - slope->dorigin.y; double dist = (px * slope->dnormdir.x) + (py * slope->dnormdir.y); @@ -672,10 +681,10 @@ static double R_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y) } // Sets the texture origin vector of the sloped plane. -static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, fixed_t angle) +static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, INT64 xoff, INT64 yoff, fixed_t angle) { - INT64 vx = (INT64)xpos + (INT64)xoff; - INT64 vy = (INT64)ypos - (INT64)yoff; + INT64 vx = (INT64)xpos + xoff; + INT64 vy = (INT64)ypos - yoff; float vxf = vx / (float)FRACUNIT; float vyf = vy / (float)FRACUNIT; @@ -702,7 +711,7 @@ void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, slope->moved = false; } - R_SetSlopePlaneOrigin(slope, xpos, ypos, zpos, xoff, yoff, angle); + R_SetSlopePlaneOrigin(slope, xpos, ypos, zpos, (INT64)xoff, (INT64)yoff, angle); height = R_GetSlopeZAt(slope, xpos, ypos); zeroheight = height - FixedToDouble(zpos); @@ -735,7 +744,7 @@ void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, } // This function calculates all of the vectors necessary for drawing a sloped and scaled plane. -void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle) +void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, INT64 xoff, INT64 yoff, angle_t angle, angle_t plangle) { double height, z_at_xy; float ang; @@ -836,9 +845,11 @@ static void CalcSlopePlaneVectors(visplane_t *pl, fixed_t xoff, fixed_t yoff) { if (!ds_fog && (pl->xscale != FRACUNIT || pl->yscale != FRACUNIT)) { + float offset_x = FixedToFloat(xoff) / FixedToFloat(pl->xscale ? pl->xscale : 1); + float offset_y = FixedToFloat(yoff) / FixedToFloat(pl->yscale ? pl->yscale : 1); R_SetScaledSlopePlane(pl->slope, pl->viewx, pl->viewy, pl->viewz, FixedDiv(FRACUNIT, pl->xscale), FixedDiv(FRACUNIT, pl->yscale), - FixedDiv(xoff, pl->xscale), FixedDiv(yoff, pl->yscale), pl->viewangle, pl->plangle); + (INT64)(offset_x * FRACUNIT), (INT64)(offset_y * FRACUNIT), pl->viewangle, pl->plangle); } else R_SetSlopePlane(pl->slope, pl->viewx, pl->viewy, pl->viewz, xoff, yoff, pl->viewangle, pl->plangle); @@ -910,7 +921,7 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->polyobj->translucency == 0 || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG))) light = (pl->lightlevel >> LIGHTSEGSHIFT); - else + else // TODO: 2.3: Make transparent polyobject planes always use light level light = LIGHTLEVELS-1; } else @@ -952,7 +963,7 @@ void R_DrawSinglePlane(visplane_t *pl) if ((spanfunctype == SPANDRAWFUNC_SPLAT) || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG))) light = (pl->lightlevel >> LIGHTSEGSHIFT); - else + else // TODO: 2.3: Make transparent FOF planes use light level instead of always being fullbright light = LIGHTLEVELS-1; } else if (pl->ffloor->fofflags & FOF_FOG) @@ -1079,6 +1090,9 @@ void R_DrawSinglePlane(visplane_t *pl) case SPANDRAWFUNC_SPLAT: spanfunctype = SPANDRAWFUNC_TILTEDSPLAT; break; + case SPANDRAWFUNC_TRANSSPLAT: + spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPLAT; + break; case SPANDRAWFUNC_SOLID: spanfunctype = SPANDRAWFUNC_TILTEDSOLID; break; diff --git a/src/r_plane.h b/src/r_plane.h index 69620f25e..cd9477501 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -48,7 +48,7 @@ typedef struct visplane_s UINT16 padbottomstart, bottom[MAXVIDWIDTH], padbottomend; INT32 high, low; // R_PlaneBounds should set these. - fixed_t xoffs, yoffs; // Scrolling flats. + INT64 xoffs, yoffs; // Scrolling flats. fixed_t xscale, yscale; sector_t *sector; @@ -85,7 +85,7 @@ void R_DrawSinglePlane(visplane_t *pl); // Calculates the slope vectors needed for tilted span drawing. void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle); -void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle); +void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, INT64 xoff, INT64 yoff, angle_t angle, angle_t plangle); typedef struct planemgr_s { diff --git a/src/r_portal.c b/src/r_portal.c index 4d042cae3..957d574b2 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -101,7 +101,7 @@ void Portal_ClipApply (const portal_t* portal) static portal_t* Portal_Add (const INT16 x1, const INT16 x2) { - portal_t *portal = Z_Malloc(sizeof(portal_t), PU_LEVEL, NULL); + portal_t *portal = Z_Calloc(sizeof(portal_t), PU_LEVEL, NULL); INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL); INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL); fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1 + 1), PU_LEVEL, NULL); @@ -117,7 +117,7 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2) portal_cap->next = portal; portal_cap = portal; } - portal->next = NULL; + portal->clipline = -1; // Store clipping values so they can be restored once the portal is rendered. portal->ceilingclip = ceilingclipsave; @@ -142,11 +142,9 @@ void Portal_Remove (portal_t* portal) Z_Free(portal); } -static void Portal_GetViewpointForLine(portal_t *portal, line_t *start, line_t *dest) +static void Portal_GetViewpointForLine(portal_t *portal, line_t *start, line_t *dest, angle_t dangle) { // Offset the portal view by the linedef centers - angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0); - fixed_t disttopoint; angle_t angtopoint; @@ -168,7 +166,6 @@ static void Portal_GetViewpointForLine(portal_t *portal, line_t *start, line_t * portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); - portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight; portal->viewangle = viewangle + dangle; } @@ -189,12 +186,13 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con line_t* start = &lines[line1]; line_t* dest = &lines[line2]; - Portal_GetViewpointForLine(portal, start, dest); + angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0); + + Portal_GetViewpointForLine(portal, start, dest, dangle); + + portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight; portal->clipline = line2; - portal->is_skybox = false; - portal->is_horizon = false; - portal->horizon_sector = NULL; Portal_ClipRange(portal); @@ -317,10 +315,7 @@ static boolean Portal_AddSkybox (const visplane_t* plane) Portal_ClipVisplane(plane, portal); - portal->clipline = -1; portal->is_skybox = true; - portal->is_horizon = false; - portal->horizon_sector = NULL; Portal_GetViewpointForSkybox(portal); @@ -332,14 +327,28 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se fixed_t x, y, z; angle_t angle; + sector_t *target = secportal->target; + + fixed_t target_x = target->soundorg.x; + fixed_t target_y = target->soundorg.y; + fixed_t target_z; + + if (secportal->ceiling) + target_z = P_GetSectorCeilingZAt(target, target_x, target_y); + else + target_z = P_GetSectorFloorZAt(target, target_x, target_y); + switch (secportal->type) { case SECPORTAL_LINE: - Portal_GetViewpointForLine(portal, secportal->line.start, secportal->line.dest); + angle = secportal->line.dest->angle - secportal->line.start->angle; + Portal_GetViewpointForLine(portal, secportal->line.start, secportal->line.dest, angle); + portal->viewz = viewz; // Apparently it just works like that. Not going to question it. return; case SECPORTAL_OBJECT: - if (!secportal->mobj || P_MobjWasRemoved(secportal->mobj)) + if (P_MobjWasRemoved(secportal->mobj)) return; + portal->viewmobj = secportal->mobj; x = secportal->mobj->x; y = secportal->mobj->y; z = secportal->mobj->z; @@ -373,8 +382,9 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se return; } - fixed_t refx = secportal->origin.x - viewx; - fixed_t refy = secportal->origin.y - viewy; + fixed_t refx = target_x - viewx; + fixed_t refy = target_y - viewy; + fixed_t refz = target_z - viewz; // Rotate the X/Y to match the target angle if (angle != 0) @@ -387,7 +397,7 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se portal->viewx = x - refx; portal->viewy = y - refy; - portal->viewz = z + viewz; + portal->viewz = z - refz; portal->viewangle = angle + viewangle; } @@ -413,11 +423,6 @@ static boolean Portal_AddSectorPortal (const visplane_t* plane) Portal_ClipVisplane(plane, portal); - portal->clipline = -1; - portal->is_horizon = false; - portal->is_skybox = false; - portal->horizon_sector = NULL; - Portal_GetViewpointForSecPortal(portal, secportal); return true; @@ -425,7 +430,7 @@ static boolean Portal_AddSectorPortal (const visplane_t* plane) /** Creates a transferred sector portal. */ -void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2) +void Portal_AddTransferred (const UINT32 secportalnum, const INT32 x1, const INT32 x2) { if (secportalnum >= secportalcount) return; @@ -435,9 +440,6 @@ void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2) return; portal_t* portal = Portal_Add(x1, x2); - portal->is_skybox = false; - portal->is_horizon = false; - portal->horizon_sector = NULL; if (secportal->type == SECPORTAL_SKYBOX) Portal_GetViewpointForSkybox(portal); diff --git a/src/r_portal.h b/src/r_portal.h index 2485e45a7..5190885b7 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -36,6 +36,8 @@ typedef struct portal_s boolean is_skybox; + mobj_t *viewmobj; + UINT8 pass; /**< Keeps track of the portal's recursion depth. */ INT32 clipline; /**< Optional clipline for line-based portals. */ @@ -58,7 +60,7 @@ extern INT32 portalclipstart, portalclipend; void Portal_InitList (void); void Portal_Remove (portal_t* portal); void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2); -void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2); +void Portal_AddTransferred (const UINT32 secportalnum, const INT32 x1, const INT32 x2); void Portal_ClipRange (portal_t* portal); void Portal_ClipApply (const portal_t* portal); diff --git a/src/r_segs.c b/src/r_segs.c index 75c95aa93..4939d1fc8 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -94,6 +94,124 @@ transnum_t R_GetLinedefTransTable(fixed_t alpha) return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1); } +static UINT8 R_SideLightLevel(side_t *side, INT16 base_lightlevel) +{ + return max(0, min(255, side->light + + ((side->lightabsolute) ? 0 : base_lightlevel))); +} + +/* TODO: implement per-texture lighting +static UINT8 R_TopLightLevel(side_t *side, INT16 base_lightlevel) +{ + return max(0, min(255, side->light_top + + ((side->lightabsolute_top) ? 0 : R_SideLightLevel(side, base_lightlevel)))); +} + +static UINT8 R_MidLightLevel(side_t *side, INT16 base_lightlevel) +{ + return max(0, min(255, side->light_mid + + ((side->lightabsolute_mid) ? 0 : R_SideLightLevel(side, base_lightlevel)))); +} + +static UINT8 R_BottomLightLevel(side_t *side, INT16 base_lightlevel) +{ + return max(0, min(255, side->light_bottom + + ((side->lightabsolute_bottom) ? 0 : R_SideLightLevel(side, base_lightlevel)))); +} +*/ + +// If we have a multi-patch texture on a 2sided wall (rare) then we draw +// it using R_DrawColumn, else we draw it using R_DrawMaskedColumn, this +// way we don't have to store extra post_t info with each column for +// multi-patch textures. They are not normally needed as multi-patch +// textures don't have holes in it. At least not for now. +static void R_Render2sidedMultiPatchColumn(column_t *column, unsigned lengthcol) +{ + INT32 topscreen, bottomscreen; + + post_t *post = &column->posts[0]; + if (!post->length) + return; + + topscreen = sprtopscreen; + bottomscreen = topscreen + spryscale * lengthcol; + + dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS; + dc_yh = (bottomscreen-1)>>FRACBITS; + + if (windowtop != INT32_MAX && windowbottom != INT32_MAX) + { + dc_yl = ((windowtop + FRACUNIT)>>FRACBITS); + dc_yh = (windowbottom - 1)>>FRACBITS; + } + + if (dc_yh >= mfloorclip[dc_x]) + dc_yh = mfloorclip[dc_x] - 1; + if (dc_yl <= mceilingclip[dc_x]) + dc_yl = mceilingclip[dc_x] + 1; + + if (dc_yl >= vid.height || dc_yh < 0) + return; + + if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0) + { + dc_source = column->pixels + post->data_offset; + dc_postlength = post->length; + + if (colfunc == colfuncs[BASEDRAWFUNC]) + (colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])(); + else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) + (colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS])(); + else + colfunc(); + } +} + +static void R_RenderFlipped2sidedMultiPatchColumn(column_t *column, unsigned lengthcol) +{ + INT32 topscreen, bottomscreen; + + void (*localcolfunc)(void); + + post_t *post = &column->posts[0]; + if (!post->length) + return; + + topscreen = sprtopscreen; + bottomscreen = topscreen + spryscale * lengthcol; + + dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS; + dc_yh = (bottomscreen-1)>>FRACBITS; + + if (windowtop != INT32_MAX && windowbottom != INT32_MAX) + { + dc_yl = ((windowtop + FRACUNIT)>>FRACBITS); + dc_yh = (windowbottom - 1)>>FRACBITS; + } + + if (dc_yh >= mfloorclip[dc_x]) + dc_yh = mfloorclip[dc_x] - 1; + if (dc_yl <= mceilingclip[dc_x]) + dc_yl = mceilingclip[dc_x] + 1; + + if (dc_yl >= vid.height || dc_yh < 0) + return; + + if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0) + { + dc_postlength = post->length; + + if (colfunc == colfuncs[BASEDRAWFUNC]) + localcolfunc = colfuncs[COLDRAWFUNC_TWOSMULTIPATCH]; + else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) + localcolfunc = colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS]; + else + localcolfunc = colfunc; + + R_DrawFlippedPost(column->pixels + post->data_offset, post->length, localcolfunc); + } +} + void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { size_t pindex; @@ -181,7 +299,16 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // Texture must be cached R_CheckTextureCache(texnum); - if (vertflip) // vertically flipped? + // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures + // are not stored per-column with post info in SRB2 + if (!textures[texnum]->transparency) + { + if (vertflip) // vertically flipped? + colfunc_2s = R_RenderFlipped2sidedMultiPatchColumn; + else + colfunc_2s = R_Render2sidedMultiPatchColumn; + } + else if (vertflip) // vertically flipped? colfunc_2s = R_DrawFlippedMaskedColumn; else colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture @@ -223,7 +350,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) || (rlight->flags & FOF_FOG) || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG))) - lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); + lightnum = R_SideLightLevel(curline->sidedef, rlight->lightlevel) >> LIGHTSEGSHIFT; else lightnum = LIGHTLEVELS - 1; @@ -241,7 +368,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); + lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT; else lightnum = LIGHTLEVELS - 1; @@ -697,9 +824,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // Check if the current light effects the colormap/lightlevel if (pfloor->fofflags & FOF_FOG) - rlight->lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); + rlight->lightnum = R_SideLightLevel(curline->sidedef, pfloor->master->frontsector->lightlevel) >> LIGHTSEGSHIFT; else - rlight->lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); + rlight->lightnum = R_SideLightLevel(curline->sidedef, rlight->lightlevel) >> LIGHTSEGSHIFT; if (pfloor->fofflags & FOF_FOG || rlight->flags & FOF_FOG || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG))) ; @@ -717,18 +844,17 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { // Get correct light level! if ((frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); + lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT; else if (fog) - lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); + lightnum = R_SideLightLevel(curline->sidedef, pfloor->master->frontsector->lightlevel) >> LIGHTSEGSHIFT; else if (fuzzy) lightnum = LIGHTLEVELS-1; else - lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false) - ->lightlevel >> LIGHTSEGSHIFT; + lightnum = R_SideLightLevel(curline->sidedef, R_FakeFlat(frontsector, &tempsec, &templight, &templight, false)->lightlevel) >> LIGHTSEGSHIFT; if (pfloor->fofflags & FOF_FOG || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))); else if (curline->v1->y == curline->v2->y) - lightnum--; + lightnum--; else if (curline->v1->x == curline->v2->x) lightnum++; @@ -811,7 +937,16 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // Texture must be cached R_CheckTextureCache(texnum); - if (vertflip) // vertically flipped? + // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures + // are not stored per-column with post info in SRB2 + if (!textures[texnum]->transparency) + { + if (vertflip) // vertically flipped? + colfunc_2s = R_RenderFlipped2sidedMultiPatchColumn; + else + colfunc_2s = R_Render2sidedMultiPatchColumn; + } + else if (vertflip) // vertically flipped? colfunc_2s = R_DrawRepeatFlippedMaskedColumn; else colfunc_2s = R_DrawRepeatMaskedColumn; @@ -906,9 +1041,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { // Otherwise use column drawers with extra checks if (fuzzy) - colfunc = R_DrawTranslucentColumnClamped_8; + colfunc = colfuncs[COLDRAWFUNC_CLAMPEDTRANS]; else - colfunc = R_DrawColumnClamped_8; + colfunc = colfuncs[COLDRAWFUNC_CLAMPED]; } } @@ -1353,7 +1488,7 @@ static void R_RenderSegLoop (void) for (i = 0; i < dc_numlights; i++) { INT32 lightnum; - lightnum = (dc_lightlist[i].lightlevel >> LIGHTSEGSHIFT); + lightnum = R_SideLightLevel(curline->sidedef, dc_lightlist[i].lightlevel) >> LIGHTSEGSHIFT; if (dc_lightlist[i].extra_colormap) ; @@ -2540,7 +2675,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) // use different light tables // for horizontal / vertical / diagonal // OPTIMIZE: get rid of LIGHTSEGSHIFT globally - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); + lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT; if (curline->v1->y == curline->v2->y) lightnum--; diff --git a/src/r_skins.c b/src/r_skins.c index a341ee80f..f364273e8 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_skins.h b/src/r_skins.h index 5122b53a6..645fea540 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_sky.c b/src/r_sky.c index 1b2c43d12..ad7262c6e 100644 --- a/src/r_sky.c +++ b/src/r_sky.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_splats.c b/src/r_splats.c index 027ccd720..ce35a35b4 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -381,7 +381,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr if (pSplat->slope) { - R_SetScaledSlopePlane(pSplat->slope, vis->viewpoint.x, vis->viewpoint.y, vis->viewpoint.z, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewpoint.angle, pSplat->angle); + R_SetScaledSlopePlane(pSplat->slope, vis->viewpoint.x, vis->viewpoint.y, vis->viewpoint.z, (INT64)pSplat->xscale, (INT64)pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewpoint.angle, pSplat->angle); } else if (!ds_solidcolor) { diff --git a/src/r_textures.c b/src/r_textures.c index 5d3fe24db..bd22a2df1 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -147,9 +147,9 @@ static void R_DrawFlippedColumnInCache(column_t *column, UINT8 *cache, texpatch_ if (count > 0) { - for (; dest < cache + position + count; --source, is_opaque++) + for (; dest < cache + position + count; --source, dest++, is_opaque++) { - *dest++ = *source; + *dest = *source; *is_opaque = true; } } @@ -295,7 +295,6 @@ UINT8 *R_GenerateTexture(size_t texnum) UINT16 lumpnum = patch->lump; UINT8 *pdata; softwarepatch_t *realpatch; - boolean holey = false; #ifndef NO_PNG_LUMPS UINT8 header[PNG_HEADER_SIZE]; @@ -310,9 +309,11 @@ UINT8 *R_GenerateTexture(size_t texnum) pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); realpatch = (softwarepatch_t *)pdata; + texture->transparency = false; + // Check the patch for holes. if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height)) - holey = true; + texture->transparency = true; else { UINT8 *colofs = (UINT8 *)realpatch->columnofs; @@ -332,12 +333,12 @@ UINT8 *R_GenerateTexture(size_t texnum) col = (doompost_t *)((UINT8 *)col + col->length + 4); } if (y < texture->height) - holey = true; // this texture is HOLEy! D: + texture->transparency = true; // this texture is HOLEy! D: } } // If the patch uses transparency, we have to save it this way. - if (holey) + if (texture->transparency) { texture->flip = patch->flip; @@ -378,6 +379,15 @@ UINT8 *R_GenerateTexture(size_t texnum) temp_columns = Z_Calloc(sizeof(column_t) * texture->width, PU_STATIC, NULL); temp_block = Z_Calloc(total_pixels, PU_STATIC, NULL); +#ifdef TEXTURE_255_IS_TRANSPARENT + texture->transparency = false; + + // Transparency hack + memset(temp_block, TRANSPARENTPIXEL, total_pixels); +#else + texture->transparency = true; +#endif + for (x = 0; x < texture->width; x++) { column_t *column = &temp_columns[x]; @@ -474,13 +484,27 @@ UINT8 *R_GenerateTexture(size_t texnum) // Now write the columns column_posts = Z_Calloc(sizeof(unsigned) * texture->width, PU_STATIC, NULL); +#ifdef TEXTURE_255_IS_TRANSPARENT + total_posts = texture->width; + temp_posts = Z_Realloc(temp_posts, sizeof(post_t) * total_posts, PU_CACHE, NULL); +#endif + for (x = 0; x < texture->width; x++) { post_t *post = NULL; - boolean was_opaque = false; column_t *column = &temp_columns[x]; +#ifdef TEXTURE_255_IS_TRANSPARENT + post = &temp_posts[x]; + post->topdelta = 0; + post->length = texture->height; + post->data_offset = 0; + column_posts[x] = x; + column->num_posts = 1; +#else + boolean was_opaque = false; + column_posts[x] = (unsigned)-1; for (INT32 y = 0; y < texture->height; y++) @@ -510,6 +534,7 @@ UINT8 *R_GenerateTexture(size_t texnum) post->length++; } +#endif } blocksize = (sizeof(column_t) * texture->width) + (sizeof(post_t) * total_posts) + (sizeof(UINT8) * total_pixels); @@ -1154,7 +1179,7 @@ static lumpnum_t W_GetTexPatchLumpNum(const char *name) if (lump == LUMPERROR) { // Use whatever else you can find. - return W_GetNumForName(name); + return W_CheckNumForPatchName(name); } return lump; diff --git a/src/r_textures.h b/src/r_textures.h index eb68ec09f..35db40d42 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -54,6 +54,7 @@ typedef struct char name[8]; UINT32 hash; UINT8 type; // TEXTURETYPE_* + boolean transparency; INT16 width, height; UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both void *flat; // The texture, as a flat. diff --git a/src/r_things.c b/src/r_things.c index dc9cab997..50855e2fc 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -279,6 +279,14 @@ static boolean GetFramesAndRotationsFromShortLumpName( *ret_rotation2 = R_Char2Rotation(name[7]); if (*ret_frame2 >= 64 || *ret_rotation2 == 255) return false; + + // TRNSLATE is a valid but extremely unlikely sprite name: + // * The sprite name is "TRNS" + // * The frame is L, rotation A; mirrored to frame T, rotation E + // In the very unfortunate event that TRNSLATE is found between sprite lumps, + // this name check prevents it from being added as a sprite, when it actually isn't. + if (memcmp(name, "TRNSLATE", 8) == 0) + return false; } else { @@ -367,7 +375,7 @@ static void MirrorMissingRotations(void) { spriteframe_t *frame = &sprtemp[framenum]; - if (frame->rotate == SRF_NONE || !(frame->rotate & SRF_3DMASK)) + if (frame->rotate == SRF_NONE || !(frame->rotate & (SRF_3DMASK | SRF_2D))) continue; UINT8 numrotations = frame->rotate == SRF_3D ? 8 : 16; @@ -379,7 +387,7 @@ static void MirrorMissingRotations(void) UINT8 baserotation = GetOppositeRotation(rotation, frame->rotate); UINT32 lumpnum = frame->lumppat[baserotation - 1]; - R_InstallSpriteLump(WADFILENUM(lumpnum), LUMPNUM(lumpnum), frame->lumpid[baserotation], framenum, rotation, 1); + R_InstallSpriteLump(WADFILENUM(lumpnum), LUMPNUM(lumpnum), frame->lumpid[baserotation - 1], framenum, rotation, 1); } } } @@ -996,6 +1004,12 @@ UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 trans return NULL; } +// Based off of R_GetLinedefTransTable +transnum_t R_GetThingTransTable(fixed_t alpha, transnum_t transmap) +{ + return (20*(FRACUNIT - ((alpha * (10 - transmap))/10) - 1) + FRACUNIT) >> (FRACBITS+1); +} + // // R_DrawVisSprite // mfloorclip and mceilingclip should also be set. @@ -1501,6 +1515,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, floordiff = abs((isflipped ? interp.height : 0) + interp.z - groundz); trans = floordiff / (100*FRACUNIT) + 3; + trans = R_GetThingTransTable(thing->alpha, trans); if (trans >= 9) return; scalemul = FixedMul(FRACUNIT - floordiff/640, scale); @@ -2192,6 +2207,11 @@ static void R_ProjectSprite(mobj_t *thing) else trans = 0; + if ((oldthing->flags2 & MF2_LINKDRAW) && oldthing->tracer) + trans = R_GetThingTransTable(oldthing->tracer->alpha, trans); + else + trans = R_GetThingTransTable(oldthing->alpha, trans); + // Check if this sprite needs to be rendered like a shadow shadowdraw = (!!(thing->renderflags & RF_SHADOWDRAW) && !(papersprite || splat)); shadoweffects = (thing->renderflags & RF_SHADOWEFFECTS); @@ -3652,6 +3672,7 @@ boolean R_ThingVisible (mobj_t *thing) (thing->sprite == SPR_NULL) || // Don't draw null-sprites (thing->flags2 & MF2_DONTDRAW) || // Don't draw MF2_LINKDRAW objects (thing->drawonlyforplayer && thing->drawonlyforplayer != viewplayer) || // Don't draw other players' personal objects + (!R_BlendLevelVisible(thing->blendmode, R_GetThingTransTable(thing->alpha, 0))) || (!P_MobjWasRemoved(r_viewmobj) && ( (r_viewmobj == thing) || // Don't draw first-person players or awayviewmobj objects (r_viewmobj->player && r_viewmobj->player->followmobj == thing) || // Don't draw first-person players' followmobj diff --git a/src/r_things.h b/src/r_things.h index 3daf55c42..ae21d2404 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -93,6 +93,7 @@ boolean R_ThingIsFullDark (mobj_t *thing); boolean R_ThingIsFlashing (mobj_t *thing); UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 translation); +transnum_t R_GetThingTransTable(fixed_t alpha, transnum_t transmap); void R_ThingOffsetOverlay (mobj_t *thing, fixed_t *outx, fixed_t *outy); diff --git a/src/r_translation.c b/src/r_translation.c index a53b30e9f..53bb0e6a0 100644 --- a/src/r_translation.c +++ b/src/r_translation.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2006 by Randy Heit. -// Copyright (C) 2023 by Sonic Team Junior. +// Copyright (C) 2023-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_translation.h b/src/r_translation.h index 1eb40233d..9cae1a647 100644 --- a/src/r_translation.h +++ b/src/r_translation.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2006 by Randy Heit. -// Copyright (C) 2023 by Sonic Team Junior. +// Copyright (C) 2023-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/s_sound.c b/src/s_sound.c index 32353a59c..0329c289e 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/s_sound.h b/src/s_sound.h index d64778fc3..589060c8c 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/screen.c b/src/screen.c index 9a82a1561..781d22335 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -112,6 +112,10 @@ void SCR_SetDrawFuncs(void) colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8; colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed_8; colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn_8; + colfuncs[COLDRAWFUNC_CLAMPED] = R_DrawColumnClamped_8; + colfuncs[COLDRAWFUNC_CLAMPEDTRANS] = R_DrawTranslucentColumnClamped_8; + colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8; + colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn_8; colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn_8; spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_8; @@ -120,6 +124,7 @@ void SCR_SetDrawFuncs(void) spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat_8; spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_8; spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_8; + spanfuncs[SPANDRAWFUNC_TILTEDTRANSSPLAT] = R_DrawTiltedTranslucentSplat_8; spanfuncs[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_8; spanfuncs[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_8; spanfuncs[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_8; @@ -142,6 +147,7 @@ void SCR_SetDrawFuncs(void) spanfuncs_npo2[SPANDRAWFUNC_SPLAT] = R_DrawSplat_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_NPO2_8; + spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANSSPLAT] = R_DrawTiltedTranslucentSplat_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; diff --git a/src/screen.h b/src/screen.h index 8b952e553..3ce593a52 100644 --- a/src/screen.h +++ b/src/screen.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -30,10 +30,6 @@ #define NUMSCREENS 5 #endif -// Size of statusbar. -#define ST_HEIGHT 32 -#define ST_WIDTH 320 - // used now as a maximum video mode size for extra vesa modes. // we try to re-allocate a minimum of buffers for stability of the memory, @@ -97,6 +93,10 @@ enum COLDRAWFUNC_SHADE, COLDRAWFUNC_SHADOWED, COLDRAWFUNC_TRANSTRANS, + COLDRAWFUNC_CLAMPED, + COLDRAWFUNC_CLAMPEDTRANS, + COLDRAWFUNC_TWOSMULTIPATCH, + COLDRAWFUNC_TWOSMULTIPATCHTRANS, COLDRAWFUNC_FOG, COLDRAWFUNC_MAX @@ -115,6 +115,7 @@ enum SPANDRAWFUNC_SPLAT, SPANDRAWFUNC_TRANSSPLAT, SPANDRAWFUNC_TILTEDSPLAT, + SPANDRAWFUNC_TILTEDTRANSSPLAT, SPANDRAWFUNC_SPRITE, SPANDRAWFUNC_TRANSSPRITE, diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index ca87fcc79..f56126601 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -112,6 +112,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(SetPaletteLookup); GETFUNC(CreateLightTable); + GETFUNC(UpdateLightTable); GETFUNC(ClearLightTables); GETFUNC(SetScreenPalette); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index e28fbd34a..7c2e6b69d 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -477,10 +477,9 @@ typedef struct feild_t tty_con; -// when printing general stuff to stdout stderr (Sys_Printf) -// we need to disable the tty console stuff -// this increments so we can recursively disable -static INT32 ttycon_hide = 0; +// lock to prevent clearing partial lines, since not everything +// printed ends on a newline. +static boolean ttycon_ateol = true; // some key codes that the terminal may be using // TTimo NOTE: I'm not sure how relevant this is static INT32 tty_erase; @@ -508,63 +507,31 @@ static inline void tty_FlushIn(void) // TTimo NOTE: it seems on some terminals just sending '\b' is not enough // so for now, in any case we send "\b \b" .. yeah well .. // (there may be a way to find out if '\b' alone would work though) +// Hanicef NOTE: using \b this way is unreliable because of terminal state, +// it's better to use \r to reset the cursor to the beginning of the +// line and clear from there. static void tty_Back(void) { - char key; - ssize_t d; - key = '\b'; - d = write(STDOUT_FILENO, &key, 1); - key = ' '; - d = write(STDOUT_FILENO, &key, 1); - key = '\b'; - d = write(STDOUT_FILENO, &key, 1); - (void)d; + write(STDOUT_FILENO, "\r", 1); + if (tty_con.cursor>0) + { + write(STDOUT_FILENO, tty_con.buffer, tty_con.cursor); + } + write(STDOUT_FILENO, " \b", 2); } static void tty_Clear(void) { size_t i; + write(STDOUT_FILENO, "\r", 1); if (tty_con.cursor>0) { for (i=0; i0); - ttycon_hide--; - if (ttycon_hide == 0 && tty_con.cursor) - { - for (i=0; i 0) { LPVOID blank = malloc(oldLength); - if (!blank) return; + if (!blank) + { + free(txt); + return; + } memset(blank, ' ', oldLength); // Blank out. oldLines = malloc(oldLength*sizeof(TCHAR)); if (!oldLines) { + free(txt); free(blank); return; } @@ -970,18 +957,20 @@ void I_OutputMsg(const char *fmt, ...) } #else #ifdef HAVE_TERMIOS - if (consolevent) + if (consolevent && ttycon_ateol) { - tty_Hide(); + tty_Clear(); + ttycon_ateol = false; } #endif if (!framebuffer) fprintf(stderr, "%s", txt); #ifdef HAVE_TERMIOS - if (consolevent) + if (consolevent && txt[len-1] == '\n') { - tty_Show(); + write(STDOUT_FILENO, tty_con.buffer, tty_con.cursor); + ttycon_ateol = true; } #endif @@ -990,6 +979,7 @@ void I_OutputMsg(const char *fmt, ...) fflush(stderr); #endif + free(txt); } // @@ -2307,7 +2297,7 @@ void I_Sleep(UINT32 ms) void I_SleepDuration(precise_t duration) { -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__HAIKU__) UINT64 precision = I_GetPrecisePrecision(); struct timespec ts = { .tv_sec = duration / precision, @@ -3003,8 +2993,8 @@ static const char *searchWad(const char *searchDir) #define CHECKWADPATH(ret) \ do { \ - I_OutputMsg(",%s", returnWadPath); \ - if (isWadPathOk(returnWadPath)) \ + I_OutputMsg(",%s", ret); \ + if (isWadPathOk(ret)) \ return ret; \ } while (0) @@ -3033,7 +3023,9 @@ static const char *locateWad(void) #ifndef NOCWD // examine current dir strcpy(returnWadPath, "."); - CHECKWADPATH(NULL); + I_OutputMsg(",%s", returnWadPath); + if (isWadPathOk(returnWadPath)) + return NULL; #endif #ifdef __APPLE__ @@ -3053,10 +3045,11 @@ static const char *locateWad(void) I_OutputMsg(",HOME/" DEFAULTDIR); if ((envstr = I_GetEnv("HOME")) != NULL) { - char *tmp = malloc(strlen(envstr) + sizeof(DEFAULTDIR)); + char *tmp = malloc(strlen(envstr) + 1 + sizeof(DEFAULTDIR)); strcpy(tmp, envstr); + strcat(tmp, "/"); strcat(tmp, DEFAULTDIR); - SEARCHWAD(envstr); + CHECKWADPATH(tmp); free(tmp); } #endif @@ -3084,8 +3077,10 @@ const char *I_LocateWad(void) { // change to the directory where we found srb2.pk3 #if defined (_WIN32) + waddir = _fullpath(NULL, waddir, MAX_PATH); SetCurrentDirectoryA(waddir); #else + waddir = realpath(waddir, NULL); if (chdir(waddir) == -1) I_OutputMsg("Couldn't change working directory\n"); #endif diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 10c866a1e..82583ccb4 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -87,7 +87,7 @@ #endif // maximum number of windowed modes (see windowedModes[][]) -#define MAXWINMODES (18) +#define MAXWINMODES (21) /** \brief */ @@ -157,7 +157,9 @@ static INT32 windowedModes[MAXWINMODES][2] = {1920,1080}, // 1.66 {1680,1050}, // 1.60,5.25 {1600,1200}, // 1.33 + {1600,1000}, // 1.60,5.00 {1600, 900}, // 1.66 + {1536, 864}, // 1.66,4.80 {1366, 768}, // 1.66 {1440, 900}, // 1.60,4.50 {1280,1024}, // 1.33? @@ -166,6 +168,7 @@ static INT32 windowedModes[MAXWINMODES][2] = {1280, 720}, // 1.66 {1152, 864}, // 1.33,3.60 {1024, 768}, // 1.33,3.20 + { 960, 600}, // 1.60,3.00 { 800, 600}, // 1.33,2.50 { 640, 480}, // 1.33,2.00 { 640, 400}, // 1.60,2.00 @@ -1901,6 +1904,7 @@ void VID_StartupOpenGL(void) HWD.pfnSetPaletteLookup = hwSym("SetPaletteLookup",NULL); HWD.pfnCreateLightTable = hwSym("CreateLightTable",NULL); + HWD.pfnUpdateLightTable = hwSym("UpdateLightTable",NULL); HWD.pfnClearLightTables = hwSym("ClearLightTables",NULL); HWD.pfnSetScreenPalette = hwSym("SetScreenPalette",NULL); @@ -1945,8 +1949,6 @@ void I_ShutdownGraphics(void) I_OutputMsg("shut down\n"); #ifdef HWRENDER - if (GLUhandle) - hwClose(GLUhandle); if (sdlglcontext) { SDL_GL_DeleteContext(sdlglcontext); diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index e7347547e..c78b43ec4 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -70,18 +70,10 @@ PFNglGetString pglGetString; /** \brief SDL video display surface */ INT32 oglflags = 0; -void *GLUhandle = NULL; SDL_GLContext sdlglcontext = 0; void *GetGLFunc(const char *proc) { - if (strncmp(proc, "glu", 3) == 0) - { - if (GLUhandle) - return hwSym(proc, GLUhandle); - else - return NULL; - } return SDL_GL_GetProcAddress(proc); } @@ -89,7 +81,6 @@ boolean LoadGL(void) { #ifndef STATIC_OPENGL const char *OGLLibname = NULL; - const char *GLULibname = NULL; if (M_CheckParm("-OGLlib") && M_IsNextParm()) OGLLibname = M_GetNextParm(); @@ -102,43 +93,6 @@ boolean LoadGL(void) CONS_Printf("If you know what is the OpenGL library's name, use -OGLlib\n"); return 0; } - -#if 0 - GLULibname = "/proc/self/exe"; -#elif defined (_WIN32) - GLULibname = "GLU32.DLL"; -#elif defined (__MACH__) - GLULibname = "/System/Library/Frameworks/OpenGL.framework/Libraries/libGLU.dylib"; -#elif defined (macintos) - GLULibname = "OpenGLLibrary"; -#elif defined (__unix__) - GLULibname = "libGLU.so.1"; -#elif defined (__HAIKU__) - GLULibname = "libGLU.so"; -#else - GLULibname = NULL; -#endif - - if (M_CheckParm("-GLUlib") && M_IsNextParm()) - GLULibname = M_GetNextParm(); - - if (GLULibname) - { - GLUhandle = hwOpen(GLULibname); - if (GLUhandle) - return SetupGLfunc(); - else - { - CONS_Alert(CONS_ERROR, "Could not load GLU Library: %s\n", GLULibname); - if (!M_CheckParm ("-GLUlib")) - CONS_Alert(CONS_ERROR, "If you know what is the GLU library's name, use -GLUlib\n"); - } - } - else - { - CONS_Alert(CONS_ERROR, "Could not load GLU Library\n"); - CONS_Alert(CONS_ERROR, "If you know what is the GLU library's name, use -GLUlib\n"); - } #endif return SetupGLfunc(); } @@ -155,6 +109,7 @@ boolean OglSdlSurface(INT32 w, INT32 h) { INT32 cbpp = cv_scr_depth.value < 16 ? 16 : cv_scr_depth.value; static boolean first_init = false; + static int majorGL = 0, minorGL = 0; oglflags = 0; @@ -189,6 +144,12 @@ boolean OglSdlSurface(INT32 w, INT32 h) else maximumAnisotropy = 1; + if (sscanf((const char*)gl_version, "%d.%d", &majorGL, &minorGL) + && (!(majorGL == 1 && minorGL <= 3))) + supportMipMap = true; + else + supportMipMap = false; + SetupGLFunc4(); glanisotropicmode_cons_t[1].value = maximumAnisotropy; diff --git a/src/sdl/ogl_sdl.h b/src/sdl/ogl_sdl.h index bd1d699ff..87df5e5e6 100644 --- a/src/sdl/ogl_sdl.h +++ b/src/sdl/ogl_sdl.h @@ -19,8 +19,6 @@ #include "../v_video.h" -extern void *GLUhandle; - boolean OglSdlSurface(INT32 w, INT32 h); void OglSdlFinishUpdate(boolean vidwait); diff --git a/src/snake.c b/src/snake.c index 2349d5fdb..4219d5b8f 100644 --- a/src/snake.c +++ b/src/snake.c @@ -582,7 +582,7 @@ boolean Snake_JoyGrabber(void *opaque, event_t *ev) { snake_t *snake = opaque; - if (ev->type == ev_joystick && ev->key == 0) + if (snake != NULL && ev->type == ev_joystick && ev->key == 0) { snake->joyevents[snake->joyeventcount] = ev; snake->joyeventcount++; diff --git a/src/st_stuff.c b/src/st_stuff.c index e088a448c..5bb3aa98c 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1042,6 +1042,9 @@ static void ST_drawInput(void) INT32 x = hudinfo[HUD_INPUT].x, y = hudinfo[HUD_INPUT].y; + if (hu_showscores) + return; + if (stplyr->powers[pw_carry] == CR_NIGHTSMODE) y += 8; else if (modeattacking || !LUA_HudEnabled(hud_lives)) @@ -1255,6 +1258,8 @@ static void ST_drawInput(void) V_DrawThinString(x, y, hudinfo[HUD_INPUT].f|((leveltime & 4) ? V_YELLOWMAP : V_REDMAP), "BAD DEMO!!"); } +static boolean lt_active = false; + static patch_t *lt_patches[3]; static INT32 lt_scroll = 0; static INT32 lt_mom = 0; @@ -1303,6 +1308,7 @@ void ST_startTitleCard(void) ST_cacheLevelTitle(); // initialize HUD variables + lt_active = true; lt_ticker = lt_exitticker = lt_lasttic = 0; lt_endtime = 2*TICRATE + (10*NEWTICRATERATIO); lt_scroll = BASEVIDWIDTH * FRACUNIT; @@ -1311,21 +1317,11 @@ void ST_startTitleCard(void) } // -// What happens before drawing the title card. -// Which is just setting the HUD translucency. +// Stops the title card. // -void ST_preDrawTitleCard(void) +void ST_stopTitleCard(void) { - if (!G_IsTitleCardAvailable()) - return; - - if (lt_ticker >= (lt_endtime + TICRATE)) - return; - - if (!lt_exitticker) - st_translucency = 0; - else - st_translucency = max(0, min((INT32)lt_exitticker-4, cv_translucenthud.value)); + lt_active = false; } // @@ -1334,47 +1330,43 @@ void ST_preDrawTitleCard(void) // void ST_runTitleCard(void) { - boolean run = !(paused || P_AutoPause()); - - if (!G_IsTitleCardAvailable()) + if (!lt_active || ((paused || P_AutoPause()) && lt_ticker >= PRELEVELTIME)) return; - if (lt_ticker >= (lt_endtime + TICRATE)) - return; - - if (run || (lt_ticker < PRELEVELTIME)) + if (!lt_exitticker) { - // tick - lt_ticker++; - if (lt_ticker >= lt_endtime) - lt_exitticker++; - - // scroll to screen (level title) - if (!lt_exitticker) - { - if (abs(lt_scroll) > FRACUNIT) - lt_scroll -= (lt_scroll>>2); - else - lt_scroll = 0; - } - // scroll away from screen (level title) + if (abs(lt_scroll) > FRACUNIT) + lt_scroll -= (lt_scroll>>2); else + lt_scroll = 0; + + if (abs(lt_zigzag) > FRACUNIT) + lt_zigzag -= (lt_zigzag>>2); + else + lt_zigzag = 0; + } + else + { + lt_mom -= FRACUNIT*6; + + if (lt_scroll > -BASEVIDWIDTH * FRACUNIT * 2) { - lt_mom -= FRACUNIT*6; lt_scroll += lt_mom; } - // scroll to screen (zigzag) - if (!lt_exitticker) + if (lt_zigzag > -(lt_patches[1]->width)*FRACUNIT) { - if (abs(lt_zigzag) > FRACUNIT) - lt_zigzag -= (lt_zigzag>>2); - else - lt_zigzag = 0; - } - // scroll away from screen (zigzag) - else lt_zigzag += lt_mom; + } + } + + lt_ticker++; + lt_exitticker = max((signed)lt_ticker - (signed)lt_endtime, 0); + + if (lt_ticker >= (lt_endtime + TICRATE)) + { + lt_active = false; + return; } } @@ -1401,9 +1393,6 @@ void ST_drawTitleCard(void) colormap = R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE); - if (!G_IsTitleCardAvailable()) - return; - if (!LUA_HudEnabled(hud_stagetitle)) goto luahook; @@ -1484,13 +1473,14 @@ void ST_preLevelTitleCardDrawer(void) // void ST_drawWipeTitleCard(void) { + if (!lt_active) + return; + stplyr = &players[consoleplayer]; - ST_preDrawTitleCard(); ST_drawTitleCard(); if (splitscreen) { stplyr = &players[secondarydisplayplayer]; - ST_preDrawTitleCard(); ST_drawTitleCard(); } } @@ -2665,7 +2655,7 @@ static boolean ST_doItemFinderIconsAndSound(void) // Scan thinkers to find emblem mobj with these ids for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -2701,24 +2691,14 @@ static boolean ST_doItemFinderIconsAndSound(void) return true; } +static boolean drawstagetitle = false; + // // Draw the status bar overlay, customisable: the user chooses which // kind of information to overlay // static void ST_overlayDrawer(void) { - // Decide whether to draw the stage title or not - boolean stagetitle = false; - - // Check for a valid level title - // If the HUD is enabled - // And, if Lua is running, if the HUD library has the stage title enabled - if (G_IsTitleCardAvailable() && *mapheaderinfo[gamemap-1]->lvlttl != '\0' && !(hu_showscores && (netgame || multiplayer))) - { - stagetitle = true; - ST_preDrawTitleCard(); - } - // hu_showscores = auto hide score/time/rings when tab rankings are shown if (!(hu_showscores && (netgame || multiplayer))) { @@ -2858,7 +2838,7 @@ static void ST_overlayDrawer(void) } // draw level title Tails - if (stagetitle && (!WipeInAction) && (!WipeStageTitle)) + if (drawstagetitle && !WipeInAction && !WipeStageTitle) ST_drawTitleCard(); if (!hu_showscores && (netgame || multiplayer) && LUA_HudEnabled(hud_textspectator)) @@ -2929,7 +2909,22 @@ void ST_Drawer(void) } } - st_translucency = cv_translucenthud.value; + // Decide whether to draw the stage title or not + if (lt_active) + { + drawstagetitle = !(hu_showscores && (netgame || multiplayer)); + + if (!lt_exitticker) + st_translucency = 0; + else + st_translucency = max(0, min((INT32)lt_exitticker-4, cv_translucenthud.value)); + } + else + { + st_translucency = cv_translucenthud.value; + + drawstagetitle = false; + } if (st_overlay) { diff --git a/src/st_stuff.h b/src/st_stuff.h index 6f6bac1fa..a2fb8a0ed 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -49,9 +49,9 @@ void ST_doPaletteStuff(void); // title card void ST_startTitleCard(void); +void ST_stopTitleCard(void); void ST_runTitleCard(void); void ST_drawTitleCard(void); -void ST_preDrawTitleCard(void); void ST_preLevelTitleCardDrawer(void); void ST_drawWipeTitleCard(void); diff --git a/src/string.c b/src/string.c index b24e12e6e..c5d95b224 100644 --- a/src/string.c +++ b/src/string.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by Graue. -// Copyright (C) 2006-2023 by Sonic Team Junior. +// Copyright (C) 2006-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/tables.c b/src/tables.c index d0fb428ba..8e9075be2 100644 --- a/src/tables.c +++ b/src/tables.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // Copyright (C) 2009 by Stephen McGranahan. // // This program is free software distributed under the diff --git a/src/tables.h b/src/tables.h index 65d7f7243..3c0dd2a81 100644 --- a/src/tables.h +++ b/src/tables.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/v_video.c b/src/v_video.c index 3beb435b5..42a4aaa00 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/v_video.h b/src/v_video.h index d37762466..bdab23e8a 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/w_wad.c b/src/w_wad.c index cc7cdc201..50ba622a9 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -65,6 +65,7 @@ #include "i_video.h" // rendermode #include "md5.h" #include "lua_script.h" +#include "lua_hook.h" #ifdef SCANTHINGS #include "p_setup.h" // P_ScanThings #endif @@ -307,12 +308,10 @@ static void W_LoadDehackedLumps(UINT16 wadnum, boolean mainfile) * \param resblock resulting MD5 checksum * \return 0 if MD5 checksum was made, and is at resblock, 1 if error was found */ + +#ifndef NOMD5 static INT32 W_MakeFileMD5(const char *filename, void *resblock) { -#ifdef NOMD5 - (void)filename; - memset(resblock, 0x00, 16); -#else FILE *fhandle; if ((fhandle = fopen(filename, "rb")) != NULL) @@ -329,9 +328,9 @@ static INT32 W_MakeFileMD5(const char *filename, void *resblock) fclose(fhandle); return 0; } -#endif return 1; } +#endif // Invalidates the cache of lump numbers. Call this whenever a wad is added. static void W_InvalidateLumpnumCache(void) @@ -1011,6 +1010,10 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) break; } + lua_lumploading++; + LUA_HookVoid(HOOK(AddonLoaded)); + lua_lumploading--; + W_InvalidateLumpnumCache(); return wadfile->numlumps; } @@ -1171,6 +1174,11 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup) W_ReadFileShaders(wadfile); W_LoadTrnslateLumps(numwadfiles - 1); W_LoadDehackedLumpsPK3(numwadfiles - 1, mainfile); + + lua_lumploading++; + LUA_HookVoid(HOOK(AddonLoaded)); + lua_lumploading--; + W_InvalidateLumpnumCache(); return wadfile->numlumps; @@ -1329,10 +1337,10 @@ UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlum /* SLADE is special and puts a single directory entry. Skip that. */ if (strlen(lump_p->fullname) == name_length) i++; - break; + return i; } } - return i; + return INT16_MAX; } // In a PK3 type of resource file, it looks for the next lumpinfo entry that doesn't share the specified pathfile. @@ -1692,7 +1700,7 @@ lumpnum_t W_GetNumForLongName(const char *name) // static UINT16 W_CheckNumForPatchNamePwad(const char *name, UINT16 wad, boolean longname) { - UINT16 i, start, end; + UINT16 i, start = INT16_MAX, end = INT16_MAX; static char uname[8 + 1] = { 0 }; UINT32 hash = 0; lumpinfo_t *lump_p; @@ -1716,6 +1724,13 @@ static UINT16 W_CheckNumForPatchNamePwad(const char *name, UINT16 wad, boolean l { start = W_CheckNumForFolderStartPK3("Flats/", wad, 0); end = W_CheckNumForFolderEndPK3("Flats/", wad, start); + + // if the start and end is the same, the folder is empty + if (end <= start) + { + start = INT16_MAX; + end = INT16_MAX; + } } else { @@ -2643,7 +2658,8 @@ static lumpchecklist_t folderblacklist[] = { {"Lua/", 4}, {"SOC/", 4}, - {"Sprites/", 8}, + {"Sprites/", 8}, + {"LongSprites/", 12}, {"Textures/", 9}, {"Patches/", 8}, {"Flats/", 6}, diff --git a/src/w_wad.h b/src/w_wad.h index 3dcb9b6e8..84aafa3a4 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/win32/Srb2win.rc b/src/win32/Srb2win.rc index 46114f871..bbe61cb17 100644 --- a/src/win32/Srb2win.rc +++ b/src/win32/Srb2win.rc @@ -98,7 +98,7 @@ BEGIN VALUE "FileDescription", "Sonic Robo Blast 2\0" VALUE "FileVersion", VERSIONSTRING_RC VALUE "InternalName", "srb2\0" - VALUE "LegalCopyright", "Copyright 1998-2023 by Sonic Team Junior\0" + VALUE "LegalCopyright", "Copyright 1998-2024 by Sonic Team Junior\0" VALUE "LegalTrademarks", "Sonic the Hedgehog and related characters are trademarks of Sega.\0" VALUE "OriginalFilename", "srb2win.exe\0" VALUE "PrivateBuild", "\0" diff --git a/src/y_inter.c b/src/y_inter.c index 2add8645b..95a08a387 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2004-2023 by Sonic Team Junior. +// Copyright (C) 2004-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/z_zone.c b/src/z_zone.c index 5750f8ae0..0852fabae 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -671,6 +671,7 @@ static void Command_Memfree_f(void) CONS_Printf(M_GetText("Cached textures : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRCACHE)>>10)); CONS_Printf(M_GetText("Texture colormaps : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHCOLMIPMAP)>>10)); CONS_Printf(M_GetText("Model textures : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRMODELTEXTURE)>>10)); + CONS_Printf(M_GetText("Light table textures : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRLIGHTTABLEDATA)>>10)); CONS_Printf(M_GetText("Plane polygons : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPLANE)>>10)); CONS_Printf(M_GetText("All GPU textures : %7d KB\n"), HWR_GetTextureUsed()>>10); } diff --git a/src/z_zone.h b/src/z_zone.h index ce7af4a15..56c540c3b 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -55,6 +55,7 @@ enum PU_HWRPATCHINFO = 21, // Hardware GLPatch_t struct for OpenGL texture cache PU_HWRPATCHCOLMIPMAP = 22, // Hardware GLMipmap_t struct colormap variation of patch PU_HWRMODELTEXTURE = 23, // Hardware model texture + PU_HWRLIGHTTABLEDATA = 24, // Hardware light table data PU_HWRCACHE = 48, // static until unlocked PU_CACHE = 49, // static until unlocked