Merge branch SRB2:next into tsourdt3rdport3

This commit is contained in:
Alam Ed Arias 2025-01-10 03:51:04 +00:00
commit e355cf832e
181 changed files with 5051 additions and 3320 deletions

View file

@ -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"

View file

@ -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.

View file

@ -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 <gcfreak_ag20@hotmail.com>
Copyright (C) 2010-2018 by Sonic Team Junior <stjr@srb2.org>
Copyright (C) 2010-2024 by Sonic Team Junior <stjr@srb2.org>
and is licensed under the GPL version 2,
see "/usr/share/common-licenses/GPL-2".

View file

@ -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 <gcfreak_ag20@hotmail.com>
Copyright (C) 2010-2018 by Sonic Team Junior <stjr@srb2.org>
Copyright (C) 2010-2024 by Sonic Team Junior <stjr@srb2.org>
and is licensed under the GPL version 2,
see "/usr/share/common-licenses/GPL-2".

View file

@ -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 = <float>; // X offset for lower texture. Default = 0.0.
offsety_bottom = <float>; // Y offset for lower texture. Default = 0.0.
light = <integer>; // Light level, relative to 'sector' light level. Default = 0.
lightabsolute = <bool>; // true = 'light' is an absolute value, ignoring 'sector' light level.
comment = <string>; // A comment. Implementors should attach no special
// semantic meaning to this field.
}

View file

@ -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;

View file

@ -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;

View file

@ -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()

View file

@ -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 \

71
src/Makefile.d/haiku.mk Normal file
View file

@ -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))

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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.

View file

@ -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)

View file

@ -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 <stdio.h>
#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

View file

@ -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.

View file

@ -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.

View file

@ -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;
}

View file

@ -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.

View file

@ -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

View file

@ -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; i<tty_con.cursor; i++)
{
tty_Back();
write(STDOUT_FILENO, " ", 1);
}
write(STDOUT_FILENO, "\r", 1);
}
}
// clear the display of the line currently edited
// bring cursor back to beginning of line
static inline void tty_Hide(void)
{
//I_Assert(consolevent);
if (ttycon_hide)
{
ttycon_hide++;
return;
}
tty_Clear();
ttycon_hide++;
}
// show the current line
// FIXME TTimo need to position the cursor if needed??
static inline void tty_Show(void)
{
size_t i;
ssize_t d;
//I_Assert(consolevent);
I_Assert(ttycon_hide>0);
ttycon_hide--;
if (ttycon_hide == 0 && tty_con.cursor)
{
for (i=0; i<tty_con.cursor; i++)
{
d = write(STDOUT_FILENO, tty_con.buffer+i, 1);
}
}
(void)d;
}
// never exit without calling this, or your terminal will be left in a pretty bad state
@ -900,6 +867,11 @@ static void I_GetConsoleEvents(void)
tty_con.cursor = 0;
ev.key = KEY_ENTER;
}
else if (key == 0x4) // ^D, aka EOF
{
// shut down, most unix programs behave this way
I_Quit();
}
else continue;
}
else if (tty_con.cursor < sizeof(tty_con.buffer))
@ -999,20 +971,8 @@ static void I_GetConsoleEvents(void)
static void I_StartupConsole(void)
{
HANDLE ci, co;
const INT32 ded = M_CheckParm("-dedicated");
BOOL gotConsole = FALSE;
if (M_CheckParm("-console") || ded)
gotConsole = AllocConsole();
#ifdef _DEBUG
else if (M_CheckParm("-noconsole") && !ded)
#else
else if (!M_CheckParm("-console") && !ded)
#endif
{
FreeConsole();
gotConsole = FALSE;
}
BOOL gotConsole = AllocConsole();
consolevent = !M_CheckParm("-noconsole");
if (gotConsole)
{
SetConsoleTitleA("SRB2 Console");
@ -1040,12 +1000,7 @@ static inline void I_ShutdownConsole(void){}
static void I_GetConsoleEvents(void){}
static inline void I_StartupConsole(void)
{
#ifdef _DEBUG
consolevent = !M_CheckParm("-noconsole");
#else
consolevent = M_CheckParm("-console");
#endif
framebuffer = M_CheckParm("-framebuffer");
if (framebuffer)
@ -1063,6 +1018,9 @@ void I_OutputMsg(const char *fmt, ...)
va_start(argptr,fmt);
len = vsnprintf(NULL, 0, fmt, argptr);
va_end(argptr);
if (len == 0)
return;
txt = malloc(len+1);
va_start(argptr,fmt);
vsprintf(txt, fmt, argptr);
@ -1152,18 +1110,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
@ -1390,8 +1350,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)
@ -1416,7 +1376,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__
@ -1433,13 +1395,13 @@ static const char *locateWad(void)
#ifndef NOHOME
// find in $HOME
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
@ -1468,8 +1430,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

View file

@ -157,7 +157,7 @@ void I_wake_all_cond(I_cond *anchor)
pthread_mutex_lock(&thread_lock);
if (*anchor == NULL)
{
*anchor = malloc(sizeof(pthread_t));
*anchor = malloc(sizeof(pthread_cond_t));
pthread_cond_init(*anchor, NULL);
}
pthread_mutex_unlock(&thread_lock);

View file

@ -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.
@ -28,6 +28,12 @@ static inline int lib_freeslot(lua_State *L)
if (!lua_lumploading)
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
if (!deh_loaded)
{
initfreeslots();
deh_loaded = true;
}
while (n-- > 0)
{
s = Z_StrDup(luaL_checkstring(L,1));

View file

@ -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.

View file

@ -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.
};

View file

@ -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.

View file

@ -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);
}

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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;

View file

@ -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.

View file

@ -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

View file

@ -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;

View file

@ -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.

View file

@ -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
//

View file

@ -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.

View file

@ -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.

View file

@ -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;
}
}

View file

@ -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.

View file

@ -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();
}

View file

@ -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.

View file

@ -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.

View file

@ -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;
};

View file

@ -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);

View file

@ -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.

View file

@ -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 = &sectors[gl_linedef->frontsector->heightsec];
else
front = gl_linedef->frontsector;
if (gl_linedef->backsector->heightsec != -1)
back = &sectors[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;

View file

@ -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.

View file

@ -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

View file

@ -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);
}

View file

@ -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.

View file

@ -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");
}

View file

@ -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)
{

View file

@ -35,7 +35,6 @@
#else
#include <GL/gl.h>
#include <GL/glu.h>
#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
*/

View file

@ -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(&lt_font, 0, 16, 20, 20);
HU_SetFontProperties(&lt_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<chat_nummsg_log; i++) // iterate through our chatlog
{
char *msg = V_ChatWordWrap(chatx, boxw-charwidth, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[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_log[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)
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<chat_nummsg_log) // end of message shouldn't count, nor should invisible characters!!!!
if (msg[j] >= 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;
}
}
}

View file

@ -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;

View file

@ -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.

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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;

View file

@ -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

View file

@ -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;
}

View file

@ -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),\

View file

@ -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++;
}
}

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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;
}

View file

@ -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:

View file

@ -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.

View file

@ -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, &sectors[READUINT16(save_p)], META_SECTOR);
LUA_PushUserdata(gL, &sectors[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 = &sectors[READUINT16(save_p)];
UINT16 id = READUINT16(save_p);
sector_t *sector = &sectors[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

View file

@ -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

View file

@ -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.

View file

@ -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.

View file

@ -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;

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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.

View file

@ -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)

View file

@ -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.

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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;

View file

@ -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

View file

@ -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 <byte_per_sec>");
}
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;

View file

@ -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 <playernum>: mute a player\n"));
CONS_Printf(M_GetText("muteplayer <playername/playernum>: 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 <playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator");
CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator");
else if (G_GametypeHasTeams())
CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator");
CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator");
else if (G_GametypeHasSpectators())
CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing");
CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: 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 <playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator");
CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator");
else if (G_GametypeHasTeams())
CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator");
CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator");
else if (G_GametypeHasSpectators())
CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing");
CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: 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 <playernum>: give admin privileges to a player\n"));
CONS_Printf(M_GetText("promote <playername/playernum>: 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 <playernum>: remove admin privileges from a player\n"));
CONS_Printf(M_GetText("demote <playername/playernum>: 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

View file

@ -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.

View file

@ -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 *

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