Merge branch 'next' into jimita-unfuck-awayview

This commit is contained in:
Steel Titanium 2019-05-25 19:47:45 -04:00
commit 34ce368895
46 changed files with 1821 additions and 356 deletions

View File

@ -3,7 +3,7 @@ jobs:
build:
working_directory: /root/SRB2
docker:
- image: debian:jessie
- image: debian:stretch
environment:
CC: ccache gcc -m32
PKG_CONFIG_LIBDIR: /usr/lib/i386-linux-gnu/pkgconfig
@ -36,17 +36,20 @@ jobs:
- v1-SRB2-APT
- run:
name: Install SDK
command: apt-get -qq -y --no-install-recommends install git build-essential nasm libpng12-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 gettext ccache wget gcc-multilib upx openssh-client
command: apt-get -qq -y --no-install-recommends install git build-essential nasm libpng-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 gettext ccache wget gcc-multilib upx openssh-client
- save_cache:
key: v1-SRB2-APT
paths:
- /var/cache/apt/archives
- checkout
- run:
name: Compile without network support
command: make -C src LINUX=1 ERRORMODE=1 -k NONET=1
name: Compile without network support and BLUA
command: make -C src LINUX=1 ERRORMODE=1 -k NONET=1 NO_LUA=1
- run:
name: Clean build
name: wipe build
command: make -C src LINUX=1 cleandep
- run:
name: rebuild depend
command: make -C src LINUX=1 clean
- restore_cache:
keys:

View File

@ -15,6 +15,7 @@ matrix:
- p7zip-full
- gcc-4.4
compiler: gcc-4.4
env: GCC44=1
#gcc-4.4 (Ubuntu/Linaro 4.4.7-8ubuntu1) 4.4.7
- os: linux
addons:
@ -27,6 +28,7 @@ matrix:
- p7zip-full
- gcc-4.6
compiler: gcc-4.6
env: GCC46=1
#gcc-4.6 (Ubuntu/Linaro 4.6.4-6ubuntu2) 4.6.4
- os: linux
addons:
@ -39,9 +41,11 @@ matrix:
- p7zip-full
- gcc-4.7
compiler: gcc-4.7
env: GCC47=1
#gcc-4.7
- os: linux
compiler: gcc
env: GCC48=1
#gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
- os: linux
addons:
@ -56,6 +60,7 @@ matrix:
- p7zip-full
- gcc-4.8
compiler: gcc-4.8
env: GCC48=1
#gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
- os: linux
addons:
@ -70,7 +75,7 @@ matrix:
- p7zip-full
- gcc-7
compiler: gcc-7
env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough"
env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough" GCC72=1
#gcc-7 (Ubuntu 7.2.0-1ubuntu1~14.04) 7.2.0 20170802
- os: linux
addons:
@ -85,7 +90,7 @@ matrix:
- p7zip-full
- gcc-8
compiler: gcc-8
env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough -Wno-error=format-overflow"
env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough -Wno-error=format-overflow" GCC81=1
#gcc-8 (Ubuntu 7.2.0-1ubuntu1~14.04) 8.1.0
- os: linux
compiler: clang
@ -216,9 +221,11 @@ matrix:
# - os: osx
# osx_image: xcode7.2
# #Apple LLVM version 7.0.2 (clang-700.1.81)
# - os: osx
# osx_image: xcode7.3
# #Apple LLVM version 7.3.0 (clang-703.0.31)
- os: osx
osx_image: xcode7.3
#Apple LLVM version 7.3.0 (clang-703.0.31)
#Default: macOS 10.13 and Xcode 9.4.1
allow_failures:
- compiler: clang-3.5
- compiler: clang-3.6
@ -242,6 +249,16 @@ addons:
- libgl1-mesa-dev
- libgme-dev
- p7zip-full
homebrew:
taps:
- mazmazz/srb2
packages:
- sdl2_mixer
- game-music-emu
- p7zip
- cmake
update: true
before_script:
- wget --verbose --server-response -c http://rosenthalcastle.org/srb2/SRB2-v2115-assets-2.7z -O $HOME/srb2_cache/SRB2-v2115-assets-2.7z
@ -253,9 +270,6 @@ before_script:
- cmake .. -DCMAKE_BUILD_TYPE=Release
before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install sdl2 sdl2_mixer game-music-emu p7zip; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install cmake||true; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then curl -O -L https://www.libsdl.org/release/SDL2-2.0.6.dmg; hdiutil attach SDL2-2.0.6.dmg; sudo cp -a /Volumes/SDL2/SDL2.framework /Library/Frameworks/; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then curl -O -L https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.1.dmg; hdiutil attach SDL2_mixer-2.0.1.dmg; sudo cp -a /Volumes/SDL2_mixer/SDL2_mixer.framework /Library/Frameworks/; fi
- mkdir -p $HOME/srb2_cache

View File

@ -54,13 +54,19 @@ macro(copy_files_to_build_dir target dlllist_var)
endif()
endmacro()
# 64-bit check
if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
# bitness check
set(SRB2_SYSTEM_BITS 0)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
message(STATUS "Target is 64-bit")
set(SRB2_SYSTEM_BITS 64)
else()
endif()
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
message(STATUS "Target is 32-bit")
set(SRB2_SYSTEM_BITS 32)
endif()
if(${SRB2_SYSTEM_BITS} EQUAL 0)
message(STATUS "Target bitness is unknown")
endif()
# OS macros
if (UNIX)

View File

@ -7,6 +7,10 @@
# and other things
#
ifdef GCC81
GCC80=1
endif
ifdef GCC80
GCC72=1
endif

View File

@ -96,6 +96,37 @@ boolean I_SetSongSpeed(float speed)
return false;
}
/// ------------------------
// MUSIC SEEKING
/// ------------------------
UINT32 I_GetSongLength(void)
{
return 0;
}
boolean I_SetSongLoopPoint(UINT32 looppoint)
{
(void)looppoint;
return false;
}
UINT32 I_GetSongLoopPoint(void)
{
return 0;
}
boolean I_SetSongPosition(UINT32 position)
{
(void)position;
return false;
}
UINT32 I_GetSongPosition(void)
{
return 0;
}
/// ------------------------
// MUSIC PLAYBACK
/// ------------------------
@ -140,3 +171,44 @@ void I_SetMusicVolume(INT32 volume)
{
(void)volume;
}
/// ------------------------
// MUSIC FADING
/// ------------------------
void I_SetInternalMusicVolume(UINT8 volume)
{
(void)volume;
}
void I_StopFadingSong(void)
{
}
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
{
(void)target_volume;
(void)source_volume;
(void)ms;
return false;
}
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
{
(void)target_volume;
(void)ms;
return false;
}
boolean I_FadeOutStopSong(UINT32 ms)
{
(void)ms;
return false;
}
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
{
(void)ms;
(void)looping;
return false;
}

View File

@ -148,6 +148,20 @@ void COM_BufInsertText(const char *ptext)
}
}
/** Progress the wait timer and flush waiting console commands when ready.
*/
void
COM_BufTicker(void)
{
if (com_wait)
{
com_wait--;
return;
}
COM_BufExecute();
}
/** Flushes (executes) console commands in the buffer.
*/
void COM_BufExecute(void)
@ -157,12 +171,6 @@ void COM_BufExecute(void)
char line[1024] = "";
INT32 quotes;
if (com_wait)
{
com_wait--;
return;
}
while (com_text.cursize)
{
// find a '\n' or; line break
@ -514,7 +522,6 @@ static void COM_ExecuteString(char *ptext)
{
if (!stricmp(com_argv[0], cmd->name)) //case insensitive now that we have lower and uppercase!
{
recursion = 0;
cmd->function();
return;
}
@ -526,19 +533,17 @@ static void COM_ExecuteString(char *ptext)
if (!stricmp(com_argv[0], a->name))
{
if (recursion > MAX_ALIAS_RECURSION)
{
CONS_Alert(CONS_WARNING, M_GetText("Alias recursion cycle detected!\n"));
recursion = 0;
return;
else
{ // Monster Iestyn: keep track of how many levels of recursion we're in
recursion++;
COM_BufInsertText(a->value);
recursion--;
}
recursion++;
COM_BufInsertText(a->value);
return;
}
}
recursion = 0;
// check cvars
// Hurdler: added at Ebola's request ;)
// (don't flood the console in software mode with bad gr_xxx command)

View File

@ -45,6 +45,9 @@ void COM_ImmedExecute(const char *ptext);
// Execute commands in buffer, flush them
void COM_BufExecute(void);
// As above; and progress the wait timer.
void COM_BufTicker(void);
// setup command buffer, at game tartup
void COM_Init(void);

View File

@ -96,6 +96,7 @@ static size_t input_len; // length of current line, used to bound cursor and suc
// protos.
static void CON_InputInit(void);
static void CON_RecalcSize(void);
static void CON_ChangeHeight(void);
static void CONS_hudlines_Change(void);
static void CONS_backcolor_Change(void);
@ -447,6 +448,12 @@ static void CON_RecalcSize(void)
con_destlines = vid.height;
}
if (con_destlines > 0) // Resize console if already open
{
CON_ChangeHeight();
con_curlines = con_destlines;
}
// check for change of video width
if (conw == con_width)
return; // didn't change
@ -496,6 +503,20 @@ static void CON_RecalcSize(void)
Z_Free(tmp_buffer);
}
static void CON_ChangeHeight(void)
{
INT32 minheight = 20 * con_scalefactor; // 20 = 8+8+4
// toggle console in
con_destlines = (cons_height.value*vid.height)/100;
if (con_destlines < minheight)
con_destlines = minheight;
else if (con_destlines > vid.height)
con_destlines = vid.height;
con_destlines &= ~0x3; // multiple of text row height
}
// Handles Console moves in/out of screen (per frame)
//
static void CON_MoveConsole(void)
@ -584,16 +605,7 @@ void CON_Ticker(void)
CON_ClearHUD();
}
else
{
// toggle console in
con_destlines = (cons_height.value*vid.height)/100;
if (con_destlines < minheight)
con_destlines = minheight;
else if (con_destlines > vid.height)
con_destlines = vid.height;
con_destlines &= ~0x3; // multiple of text row height
}
CON_ChangeHeight();
}
// console movement
@ -1051,16 +1063,6 @@ boolean CON_Responder(event_t *ev)
else if (key == KEY_KPADSLASH)
key = '/';
// capslock
if (key == KEY_CAPSLOCK) // it's a toggle.
{
if (capslock)
capslock = false;
else
capslock = true;
return true;
}
if (key >= 'a' && key <= 'z')
{
if (capslock ^ shiftdown)
@ -1106,6 +1108,7 @@ static void CON_Print(char *msg)
{
size_t l;
INT32 controlchars = 0; // for color changing
char color = '\x80'; // keep color across lines
if (msg == NULL)
return;
@ -1131,7 +1134,7 @@ static void CON_Print(char *msg)
{
if (*msg & 0x80)
{
con_line[con_cx++] = *(msg++);
color = con_line[con_cx++] = *(msg++);
controlchars++;
continue;
}
@ -1139,12 +1142,14 @@ static void CON_Print(char *msg)
{
con_cy--;
CON_Linefeed();
color = '\x80';
controlchars = 0;
}
else if (*msg == '\n') // linefeed
{
CON_Linefeed();
controlchars = 0;
con_line[con_cx++] = color;
controlchars = 1;
}
else if (*msg == ' ') // space
{
@ -1152,7 +1157,8 @@ static void CON_Print(char *msg)
if (con_cx - controlchars >= con_width-11)
{
CON_Linefeed();
controlchars = 0;
con_line[con_cx++] = color;
controlchars = 1;
}
}
else if (*msg == '\t')
@ -1167,7 +1173,8 @@ static void CON_Print(char *msg)
if (con_cx - controlchars >= con_width-11)
{
CON_Linefeed();
controlchars = 0;
con_line[con_cx++] = color;
controlchars = 1;
}
}
msg++;
@ -1184,7 +1191,8 @@ static void CON_Print(char *msg)
if ((con_cx - controlchars) + l > con_width-11)
{
CON_Linefeed();
controlchars = 0;
con_line[con_cx++] = color;
controlchars = 1;
}
// a word at a time
@ -1539,8 +1547,7 @@ static void CON_DrawConsole(void)
i = con_cy - con_scrollup;
// skip the last empty line due to the cursor being at the start of a new line
if (!con_scrollup && !con_cx)
i--;
i--;
i -= (con_curlines - minheight) / charheight;

View File

@ -2056,17 +2056,11 @@ static void CL_ConnectToServer(boolean viams)
if (i != -1)
{
INT32 j;
UINT8 num = serverlist[i].info.gametype;
const char *gametypestr = NULL;
CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername);
for (j = 0; gametype_cons_t[j].strvalue; j++)
{
if (gametype_cons_t[j].value == serverlist[i].info.gametype)
{
gametypestr = gametype_cons_t[j].strvalue;
break;
}
}
if (num < NUMGAMETYPES)
gametypestr = Gametype_Names[num];
if (gametypestr)
CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr);
CONS_Printf(M_GetText("Version: %d.%d.%u\n"), serverlist[i].info.version/100,
@ -2598,7 +2592,10 @@ static void Command_Ban(void)
else
{
if (server) // only the server is allowed to do this right now
{
Ban_Add(COM_Argv(2));
D_SaveBan(); // save the ban list
}
if (COM_Argc() == 2)
{
@ -2629,6 +2626,42 @@ static void Command_Ban(void)
}
static void Command_BanIP(void)
{
if (COM_Argc() < 2)
{
CONS_Printf(M_GetText("banip <ip> <reason>: ban an ip address\n"));
return;
}
if (server) // Only the server can use this, otherwise does nothing.
{
const char *address = (COM_Argv(1));
const char *reason;
if (COM_Argc() == 2)
reason = NULL;
else
reason = COM_Argv(2);
if (I_SetBanAddress && I_SetBanAddress(address, NULL))
{
if (reason)
CONS_Printf("Banned IP address %s for: %s\n", address, reason);
else
CONS_Printf("Banned IP address %s\n", address);
Ban_Add(reason);
D_SaveBan();
}
else
{
return;
}
}
}
static void Command_Kick(void)
{
if (COM_Argc() < 2)
@ -2908,6 +2941,7 @@ void D_ClientServerInit(void)
COM_AddCommand("getplayernum", Command_GetPlayerNum);
COM_AddCommand("kick", Command_Kick);
COM_AddCommand("ban", Command_Ban);
COM_AddCommand("banip", Command_BanIP);
COM_AddCommand("clearbans", Command_ClearBans);
COM_AddCommand("showbanlist", Command_ShowBan);
COM_AddCommand("reloadbans", Command_ReloadBan);
@ -4563,7 +4597,7 @@ void TryRunTics(tic_t realtics)
if (realtics >= 1)
{
COM_BufExecute();
COM_BufTicker();
if (mapchangepending)
D_MapChange(-1, 0, ultimatemode, false, 2, false, fromlevelselect); // finish the map change
}

View File

@ -176,37 +176,11 @@ void D_PostEvent_end(void) {};
#endif
// modifier keys
// Now handled in I_OsPolling
UINT8 shiftdown = 0; // 0x1 left, 0x2 right
UINT8 ctrldown = 0; // 0x1 left, 0x2 right
UINT8 altdown = 0; // 0x1 left, 0x2 right
boolean capslock = 0; // gee i wonder what this does.
//
// D_ModifierKeyResponder
// Sets global shift/ctrl/alt variables, never actually eats events
//
static inline void D_ModifierKeyResponder(event_t *ev)
{
if (ev->type == ev_keydown || ev->type == ev_console) switch (ev->data1)
{
case KEY_LSHIFT: shiftdown |= 0x1; return;
case KEY_RSHIFT: shiftdown |= 0x2; return;
case KEY_LCTRL: ctrldown |= 0x1; return;
case KEY_RCTRL: ctrldown |= 0x2; return;
case KEY_LALT: altdown |= 0x1; return;
case KEY_RALT: altdown |= 0x2; return;
default: return;
}
else if (ev->type == ev_keyup) switch (ev->data1)
{
case KEY_LSHIFT: shiftdown &= ~0x1; return;
case KEY_RSHIFT: shiftdown &= ~0x2; return;
case KEY_LCTRL: ctrldown &= ~0x1; return;
case KEY_RCTRL: ctrldown &= ~0x2; return;
case KEY_LALT: altdown &= ~0x1; return;
case KEY_RALT: altdown &= ~0x2; return;
default: return;
}
}
//
// D_ProcessEvents
@ -220,9 +194,6 @@ void D_ProcessEvents(void)
{
ev = &events[eventtail];
// Set global shift/ctrl/alt down variables
D_ModifierKeyResponder(ev); // never eats events
// Screenshots over everything so that they can be taken anywhere.
if (M_ScreenshotResponder(ev))
continue; // ate the event
@ -726,7 +697,6 @@ void D_StartTitle(void)
paused = false;
advancedemo = false;
F_StartTitleScreen();
CON_ToggleOff();
// Reset the palette
if (rendermode != render_none)
@ -1362,13 +1332,9 @@ void D_SRB2Main(void)
INT16 newgametype = -1;
const char *sgametype = M_GetNextParm();
for (j = 0; gametype_cons_t[j].strvalue; j++)
if (!strcasecmp(gametype_cons_t[j].strvalue, sgametype))
{
newgametype = (INT16)gametype_cons_t[j].value;
break;
}
if (!gametype_cons_t[j].strvalue) // reached end of the list with no match
newgametype = G_GetGametypeByName(sgametype);
if (newgametype == -1) // reached end of the list with no match
{
j = atoi(sgametype); // assume they gave us a gametype number, which is okay too
if (j >= 0 && j < NUMGAMETYPES)
@ -1400,13 +1366,13 @@ void D_SRB2Main(void)
}
else if (M_CheckParm("-skipintro"))
{
CON_ToggleOff();
CON_ClearHUD();
F_StartTitleScreen();
}
else
F_StartIntro(); // Tails 03-03-2002
CON_ToggleOff();
if (dedicated && server)
{
pagename = "TITLESKY";

View File

@ -409,6 +409,16 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
*/
void D_RegisterServerCommands(void)
{
INT32 i;
for (i = 0; i < NUMGAMETYPES; i++)
{
gametype_cons_t[i].value = i;
gametype_cons_t[i].strvalue = Gametype_Names[i];
}
gametype_cons_t[NUMGAMETYPES].value = 0;
gametype_cons_t[NUMGAMETYPES].strvalue = NULL;
RegisterNetXCmd(XD_NAMEANDCOLOR, Got_NameAndColor);
RegisterNetXCmd(XD_WEAPONPREF, Got_WeaponPref);
RegisterNetXCmd(XD_MAP, Got_Mapcmd);
@ -1639,7 +1649,7 @@ static void Command_Map_f(void)
{
const char *mapname;
size_t i;
INT32 j, newmapnum;
INT32 newmapnum;
boolean newresetplayers;
INT32 newgametype = gametype;
@ -1707,27 +1717,13 @@ static void Command_Map_f(void)
return;
}
for (j = 0; gametype_cons_t[j].strvalue; j++)
if (!strcasecmp(gametype_cons_t[j].strvalue, COM_Argv(i+1)))
{
// Don't do any variable setting here. Wait until you get your
// map packet first to avoid sending the same info twice!
newgametype = gametype_cons_t[j].value;
newgametype = G_GetGametypeByName(COM_Argv(i+1));
break;
}
if (!gametype_cons_t[j].strvalue) // reached end of the list with no match
if (newgametype == -1) // reached end of the list with no match
{
// assume they gave us a gametype number, which is okay too
for (j = 0; gametype_cons_t[j].strvalue != NULL; j++)
{
if (atoi(COM_Argv(i+1)) == gametype_cons_t[j].value)
{
newgametype = gametype_cons_t[j].value;
break;
}
}
INT32 j = atoi(COM_Argv(i+1)); // assume they gave us a gametype number, which is okay too
if (j >= 0 && j < NUMGAMETYPES)
newgametype = (INT16)j;
}
}
@ -1742,12 +1738,11 @@ static void Command_Map_f(void)
char gametypestring[32] = "Single Player";
if (multiplayer)
for (i = 0; gametype_cons_t[i].strvalue != NULL; i++)
if (gametype_cons_t[i].value == newgametype)
{
strcpy(gametypestring, gametype_cons_t[i].strvalue);
break;
}
{
if (newgametype >= 0 && newgametype < NUMGAMETYPES
&& Gametype_Names[newgametype])
strcpy(gametypestring, Gametype_Names[newgametype]);
}
CONS_Alert(CONS_WARNING, M_GetText("%s doesn't support %s mode!\n(Use -force to override)\n"), mapname, gametypestring);
return;
@ -1831,9 +1826,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
CONS_Printf(M_GetText("Speeding off to level...\n"));
}
CON_ToggleOff();
CON_ClearHUD();
if (demoplayback && !timingdemo)
precache = false;
@ -3486,7 +3478,6 @@ static void Command_ModDetails_f(void)
//
static void Command_ShowGametype_f(void)
{
INT32 j;
const char *gametypestr = NULL;
if (!(netgame || multiplayer)) // print "Single player" instead of "Co-op"
@ -3494,15 +3485,11 @@ static void Command_ShowGametype_f(void)
CONS_Printf(M_GetText("Current gametype is %s\n"), M_GetText("Single player"));
return;
}
// find name string for current gametype
for (j = 0; gametype_cons_t[j].strvalue; j++)
{
if (gametype_cons_t[j].value == gametype)
{
gametypestr = gametype_cons_t[j].strvalue;
break;
}
}
// get name string for current gametype
if (gametype >= 0 && gametype < NUMGAMETYPES)
gametypestr = Gametype_Names[gametype];
if (gametypestr)
CONS_Printf(M_GetText("Current gametype is %s\n"), gametypestr);
else // string for current gametype was not found above (should never happen)
@ -3644,15 +3631,13 @@ void D_GameTypeChanged(INT32 lastgametype)
{
if (netgame)
{
INT32 j;
const char *oldgt = NULL, *newgt = NULL;
for (j = 0; gametype_cons_t[j].strvalue; j++)
{
if (gametype_cons_t[j].value == lastgametype)
oldgt = gametype_cons_t[j].strvalue;
if (gametype_cons_t[j].value == gametype)
newgt = gametype_cons_t[j].strvalue;
}
if (lastgametype >= 0 && lastgametype < NUMGAMETYPES)
oldgt = Gametype_Names[lastgametype];
if (gametype >= 0 && lastgametype < NUMGAMETYPES)
newgt = Gametype_Names[gametype];
if (oldgt && newgt)
CONS_Printf(M_GetText("Gametype was changed from %s to %s\n"), oldgt, newgt);
}

View File

@ -1196,6 +1196,13 @@ static void readlevelheader(MYFILE *f, INT32 num)
#endif
else if (fastcmp(word, "MUSICTRACK"))
mapheaderinfo[num-1]->mustrack = ((UINT16)i - 1);
else if (fastcmp(word, "MUSICPOS"))
mapheaderinfo[num-1]->muspos = (UINT32)get_number(word2);
else if (fastcmp(word, "MUSICINTERFADEOUT"))
mapheaderinfo[num-1]->musinterfadeout = (UINT32)get_number(word2);
else if (fastcmp(word, "MUSICINTER"))
deh_strlcpy(mapheaderinfo[num-1]->musintername, word2,
sizeof(mapheaderinfo[num-1]->musintername), va("Level header %d: intermission music", num));
else if (fastcmp(word, "FORCECHARACTER"))
{
strlcpy(mapheaderinfo[num-1]->forcecharacter, word2, SKINNAMESIZE+1);
@ -1499,6 +1506,11 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musswitchflags), UNDO_NONE);
cutscenes[num]->scene[scenenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK;
}
else if (fastcmp(word, "MUSICPOS"))
{
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musswitchposition), UNDO_NONE);
cutscenes[num]->scene[scenenum].musswitchposition = (UINT32)get_number(word2);
}
else if (fastcmp(word, "MUSICLOOP"))
{
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musicloop), UNDO_NONE);
@ -7003,6 +7015,7 @@ struct {
// doomdef.h constants
{"TICRATE",TICRATE},
{"MUSICRATE",MUSICRATE},
{"RING_DIST",RING_DIST},
{"PUSHACCEL",PUSHACCEL},
{"MODID",MODID}, // I don't know, I just thought it would be cool for a wad to potentially know what mod it was loaded into.
@ -8314,6 +8327,9 @@ static inline int lib_getenum(lua_State *L)
} else if (fastcmp(word,"mapmusflags")) {
lua_pushinteger(L, mapmusflags);
return 1;
} else if (fastcmp(word,"mapmusposition")) {
lua_pushinteger(L, mapmusposition);
return 1;
} else if (fastcmp(word,"server")) {
if ((!multiplayer || !netgame) && !playeringame[serverplayer])
return 0;

View File

@ -438,6 +438,37 @@ boolean I_SetSongSpeed(float speed)
return false;
}
/// ------------------------
// MUSIC SEEKING
/// ------------------------
UINT32 I_GetSongLength(void)
{
return 0;
}
boolean I_SetSongLoopPoint(UINT32 looppoint)
{
(void)looppoint;
return false;
}
UINT32 I_GetSongLoopPoint(void)
{
return 0;
}
boolean I_SetSongPosition(UINT32 position)
{
(void)position;
return false;
}
UINT32 I_GetSongPosition(void)
{
return 0;
}
/// ------------------------
// MUSIC PLAYBACK
/// ------------------------
@ -545,3 +576,44 @@ int I_QrySongPlaying(int handle)
return (midi_pos==-1);
}
#endif
/// ------------------------
// MUSIC FADING
/// ------------------------
void I_SetInternalMusicVolume(UINT8 volume)
{
(void)volume;
}
void I_StopFadingSong(void)
{
}
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
{
(void)target_volume;
(void)source_volume;
(void)ms;
return false;
}
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
{
(void)target_volume;
(void)ms;
return false;
}
boolean I_FadeOutStopSong(UINT32 ms)
{
(void)ms;
return false;
}
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
{
(void)ms;
(void)looping;
return false;
}

View File

@ -305,6 +305,8 @@ typedef enum
#define NEWTICRATERATIO 1 // try 4 for 140 fps :)
#define NEWTICRATE (TICRATE*NEWTICRATERATIO)
#define MUSICRATE 1000 // sound timing is calculated by milliseconds
#define RING_DIST 512*FRACUNIT // how close you need to be to a ring to attract it
#define PUSHACCEL (2*FRACUNIT) // Acceleration for MF2_SLIDEPUSH items.

View File

@ -33,8 +33,10 @@
extern INT16 gamemap;
extern char mapmusname[7];
extern UINT16 mapmusflags;
extern UINT32 mapmusposition;
#define MUSIC_TRACKMASK 0x0FFF // ----************
#define MUSIC_RELOADRESET 0x8000 // *---------------
#define MUSIC_FORCERESET 0x4000 // -*--------------
// Use other bits if necessary.
extern INT16 maptol;
@ -145,6 +147,7 @@ typedef struct
char musswitch[7];
UINT16 musswitchflags;
UINT32 musswitchposition;
UINT8 fadecolor; // Color number for fade, 0 means don't do the first fade
UINT8 fadeinid; // ID of the first fade, to a color -- ignored if fadecolor is 0
@ -215,6 +218,7 @@ typedef struct
INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end.
char musname[7]; ///< Music track to play. "" for no music.
UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
UINT32 muspos; ///< Music position to jump to.
char forcecharacter[17]; ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable.
UINT8 weather; ///< 0 = sunny day, 1 = storm, 2 = snow, 3 = rain, 4 = blank, 5 = thunder w/o rain, 6 = rain w/o lightning, 7 = heat wave.
INT16 skynum; ///< Sky number to use.
@ -243,6 +247,10 @@ typedef struct
UINT8 numGradedMares; ///< Internal. For grade support.
nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful.
// Music stuff.
UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds
char musintername[7]; ///< Intermission screen music.
// Lua stuff.
// (This is not ifdeffed so the map header structure can stay identical, just in case.)
UINT8 numCustomOptions; ///< Internal. For Lua custom value support.
@ -310,7 +318,10 @@ enum GameType
NUMGAMETYPES
};
// If you alter this list, update gametype_cons_t in m_menu.c
// If you alter this list, update dehacked.c, and Gametype_Names in g_game.c
// String names for gametypes
extern const char *Gametype_Names[NUMGAMETYPES];
extern tic_t totalplaytime;

View File

@ -95,6 +95,37 @@ boolean I_SetSongSpeed(float speed)
return false;
}
/// ------------------------
// MUSIC SEEKING
/// ------------------------
UINT32 I_GetSongLength(void)
{
return 0;
}
boolean I_SetSongLoopPoint(UINT32 looppoint)
{
(void)looppoint;
return false;
}
UINT32 I_GetSongLoopPoint(void)
{
return 0;
}
boolean I_SetSongPosition(UINT32 position)
{
(void)position;
return false;
}
UINT32 I_GetSongPosition(void)
{
return 0;
}
/// ------------------------
// MUSIC PLAYBACK
/// ------------------------
@ -142,4 +173,45 @@ boolean I_SetSongTrack(int track)
{
(void)track;
return false;
}
}
/// ------------------------
// MUSIC FADING
/// ------------------------
void I_SetInternalMusicVolume(UINT8 volume)
{
(void)volume;
}
void I_StopFadingSong(void)
{
}
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
{
(void)target_volume;
(void)source_volume;
(void)ms;
return false;
}
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
{
(void)target_volume;
(void)ms;
return false;
}
boolean I_FadeOutStopSong(UINT32 ms)
{
(void)ms;
return false;
}
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
{
(void)ms;
(void)looping;
return false;
}

View File

@ -444,7 +444,6 @@ void F_StartIntro(void)
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
CON_ClearHUD();
F_NewCutscene(introtext[0]);
intro_scenenum = 0;
@ -1146,7 +1145,6 @@ void F_StartCredits(void)
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
CON_ClearHUD();
S_StopMusic();
S_ChangeMusicInternal("credit", false);
@ -1192,16 +1190,34 @@ void F_CreditDrawer(void)
if (FixedMul(y,vid.dupy) > vid.height)
break;
}
}
void F_CreditTicker(void)
{
// "Simulate" the drawing of the credits so that dedicated mode doesn't get stuck
UINT16 i;
fixed_t y = (80<<FRACBITS) - 5*(animtimer<<FRACBITS)/8;
// Draw credits text on top
for (i = 0; credits[i]; i++)
{
switch(credits[i][0])
{
case 0: y += 80<<FRACBITS; break;
case 1: y += 30<<FRACBITS; break;
default: y += 12<<FRACBITS; break;
}
if (FixedMul(y,vid.dupy) > vid.height)
break;
}
// Do this here rather than in the drawer you doofus! (this is why dedicated mode broke at credits)
if (!credits[i] && y <= 120<<FRACBITS && !finalecount)
{
timetonext = 5*TICRATE+1;
finalecount = 5*TICRATE;
}
}
void F_CreditTicker(void)
{
if (timetonext)
timetonext--;
else
@ -1295,7 +1311,6 @@ void F_StartGameEvaluation(void)
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
CON_ClearHUD();
finalecount = 0;
}
@ -1405,7 +1420,6 @@ void F_StartGameEnd(void)
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
CON_ClearHUD();
S_StopMusic();
// In case menus are still up?!!
@ -1608,7 +1622,6 @@ void F_StartContinue(void)
keypressed = false;
paused = false;
CON_ToggleOff();
CON_ClearHUD();
// In case menus are still up?!!
M_ClearMenus(true);
@ -1728,9 +1741,10 @@ static void F_AdvanceToNextScene(void)
picypos = cutscenes[cutnum]->scene[scenenum].ycoord[picnum];
if (cutscenes[cutnum]->scene[scenenum].musswitch[0])
S_ChangeMusic(cutscenes[cutnum]->scene[scenenum].musswitch,
S_ChangeMusicEx(cutscenes[cutnum]->scene[scenenum].musswitch,
cutscenes[cutnum]->scene[scenenum].musswitchflags,
cutscenes[cutnum]->scene[scenenum].musicloop);
cutscenes[cutnum]->scene[scenenum].musicloop,
cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0);
// Fade to the next
dofadenow = true;
@ -1779,8 +1793,6 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
F_NewCutscene(cutscenes[cutscenenum]->scene[0].text);
CON_ClearHUD();
cutsceneover = false;
runningprecutscene = precutscene;
precutresetplayer = resetplayer;
@ -1801,9 +1813,10 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
stoptimer = 0;
if (cutscenes[cutnum]->scene[0].musswitch[0])
S_ChangeMusic(cutscenes[cutnum]->scene[0].musswitch,
S_ChangeMusicEx(cutscenes[cutnum]->scene[0].musswitch,
cutscenes[cutnum]->scene[0].musswitchflags,
cutscenes[cutnum]->scene[0].musicloop);
cutscenes[cutnum]->scene[0].musicloop,
cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0);
else
S_StopMusic();
}

View File

@ -71,6 +71,7 @@ static void G_DoWorldDone(void);
char mapmusname[7]; // Music name
UINT16 mapmusflags; // Track and reset bit
UINT32 mapmusposition; // Position to jump to
INT16 gamemap = 1;
INT16 maptol;
@ -2268,9 +2269,14 @@ void G_PlayerReborn(INT32 player)
{
strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7);
mapmusname[6] = 0;
mapmusflags = mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK;
mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK);
mapmusposition = mapheaderinfo[gamemap-1]->muspos;
}
S_ChangeMusic(mapmusname, mapmusflags, true);
// This is in S_Start, but this was not here previously.
// if (cv_resetmusic.value)
// S_StopMusic();
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
}
if (gametype == GT_COOP)
@ -2692,6 +2698,38 @@ void G_ExitLevel(void)
}
}
// See also the enum GameType in doomstat.h
const char *Gametype_Names[NUMGAMETYPES] =
{
"Co-op", // GT_COOP
"Competition", // GT_COMPETITION
"Race", // GT_RACE
"Match", // GT_MATCH
"Team Match", // GT_TEAMMATCH
"Tag", // GT_TAG
"Hide and Seek", // GT_HIDEANDSEEK
"CTF" // GT_CTF
};
//
// G_GetGametypeByName
//
// Returns the number for the given gametype name string, or -1 if not valid.
//
INT32 G_GetGametypeByName(const char *gametypestr)
{
INT32 i;
for (i = 0; i < NUMGAMETYPES; i++)
if (!stricmp(gametypestr, Gametype_Names[i]))
return i;
return -1; // unknown gametype
}
//
// G_IsSpecialStage
//

View File

@ -163,6 +163,7 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void);
void G_StopDemo(void);
boolean G_CheckDemoStatus(void);
INT32 G_GetGametypeByName(const char *gametypestr);
boolean G_IsSpecialStage(INT32 mapnum);
boolean G_GametypeUsesLives(void);
boolean G_GametypeHasTeams(void);

View File

@ -4246,10 +4246,43 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t
}
}
// This is expecting a pointer to an array containing 4 wallVerts for a sprite
static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts)
{
if (cv_grspritebillboarding.value && spr && spr->mobj && wallVerts)
{
float basey = FIXED_TO_FLOAT(spr->mobj->z);
float lowy = wallVerts[0].y;
if (P_MobjFlip(spr->mobj) == -1)
{
basey = FIXED_TO_FLOAT(spr->mobj->z + spr->mobj->height);
}
// Rotate sprites to fully billboard with the camera
// X, Y, AND Z need to be manipulated for the polys to rotate around the
// origin, because of how the origin setting works I believe that should
// be mobj->z or mobj->z + mobj->height
wallVerts[2].y = wallVerts[3].y = (spr->ty - basey) * gr_viewludsin + basey;
wallVerts[0].y = wallVerts[1].y = (lowy - basey) * gr_viewludsin + basey;
// translate back to be around 0 before translating back
wallVerts[3].x += ((spr->ty - basey) * gr_viewludcos) * gr_viewcos;
wallVerts[2].x += ((spr->ty - basey) * gr_viewludcos) * gr_viewcos;
wallVerts[0].x += ((lowy - basey) * gr_viewludcos) * gr_viewcos;
wallVerts[1].x += ((lowy - basey) * gr_viewludcos) * gr_viewcos;
wallVerts[3].z += ((spr->ty - basey) * gr_viewludcos) * gr_viewsin;
wallVerts[2].z += ((spr->ty - basey) * gr_viewludcos) * gr_viewsin;
wallVerts[0].z += ((lowy - basey) * gr_viewludcos) * gr_viewsin;
wallVerts[1].z += ((lowy - basey) * gr_viewludcos) * gr_viewsin;
}
}
static void HWR_SplitSprite(gr_vissprite_t *spr)
{
float this_scale = 1.0f;
FOutVector wallVerts[4];
FOutVector baseWallVerts[4]; // This is what the verts should end up as
GLPatch_t *gpatch;
FSurfaceInfo Surf;
const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES);
@ -4262,11 +4295,13 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
float realtop, realbot, top, bot;
float towtop, towbot, towmult;
float bheight;
float realheight, heightmult;
const sector_t *sector = spr->mobj->subsector->sector;
const lightlist_t *list = sector->lightlist;
#ifdef ESLOPE
float endrealtop, endrealbot, endtop, endbot;
float endbheight;
float endrealheight;
fixed_t temp;
fixed_t v1x, v1y, v2x, v2y;
#endif
@ -4299,16 +4334,16 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
HWR_DrawSpriteShadow(spr, gpatch, this_scale);
}
wallVerts[0].x = wallVerts[3].x = spr->x1;
wallVerts[2].x = wallVerts[1].x = spr->x2;
wallVerts[0].z = wallVerts[3].z = spr->z1;
wallVerts[1].z = wallVerts[2].z = spr->z2;
baseWallVerts[0].x = baseWallVerts[3].x = spr->x1;
baseWallVerts[2].x = baseWallVerts[1].x = spr->x2;
baseWallVerts[0].z = baseWallVerts[3].z = spr->z1;
baseWallVerts[1].z = baseWallVerts[2].z = spr->z2;
wallVerts[2].y = wallVerts[3].y = spr->ty;
baseWallVerts[2].y = baseWallVerts[3].y = spr->ty;
if (spr->mobj && fabsf(this_scale - 1.0f) > 1.0E-36f)
wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height * this_scale;
baseWallVerts[0].y = baseWallVerts[1].y = spr->ty - gpatch->height * this_scale;
else
wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height;
baseWallVerts[0].y = baseWallVerts[1].y = spr->ty - gpatch->height;
v1x = FLOAT_TO_FIXED(spr->x1);
v1y = FLOAT_TO_FIXED(spr->z1);
@ -4317,44 +4352,56 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
if (spr->flip)
{
wallVerts[0].sow = wallVerts[3].sow = gpatch->max_s;
wallVerts[2].sow = wallVerts[1].sow = 0;
}else{
wallVerts[0].sow = wallVerts[3].sow = 0;
wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s;
baseWallVerts[0].sow = baseWallVerts[3].sow = gpatch->max_s;
baseWallVerts[2].sow = baseWallVerts[1].sow = 0;
}
else
{
baseWallVerts[0].sow = baseWallVerts[3].sow = 0;
baseWallVerts[2].sow = baseWallVerts[1].sow = gpatch->max_s;
}
// flip the texture coords (look familiar?)
if (spr->vflip)
{
wallVerts[3].tow = wallVerts[2].tow = gpatch->max_t;
wallVerts[0].tow = wallVerts[1].tow = 0;
}else{
wallVerts[3].tow = wallVerts[2].tow = 0;
wallVerts[0].tow = wallVerts[1].tow = gpatch->max_t;
baseWallVerts[3].tow = baseWallVerts[2].tow = gpatch->max_t;
baseWallVerts[0].tow = baseWallVerts[1].tow = 0;
}
else
{
baseWallVerts[3].tow = baseWallVerts[2].tow = 0;
baseWallVerts[0].tow = baseWallVerts[1].tow = gpatch->max_t;
}
// if it has a dispoffset, push it a little towards the camera
if (spr->dispoffset) {
float co = -gr_viewcos*(0.05f*spr->dispoffset);
float si = -gr_viewsin*(0.05f*spr->dispoffset);
wallVerts[0].z = wallVerts[3].z = wallVerts[0].z+si;
wallVerts[1].z = wallVerts[2].z = wallVerts[1].z+si;
wallVerts[0].x = wallVerts[3].x = wallVerts[0].x+co;
wallVerts[1].x = wallVerts[2].x = wallVerts[1].x+co;
baseWallVerts[0].z = baseWallVerts[3].z = baseWallVerts[0].z+si;
baseWallVerts[1].z = baseWallVerts[2].z = baseWallVerts[1].z+si;
baseWallVerts[0].x = baseWallVerts[3].x = baseWallVerts[0].x+co;
baseWallVerts[1].x = baseWallVerts[2].x = baseWallVerts[1].x+co;
}
realtop = top = wallVerts[3].y;
realbot = bot = wallVerts[0].y;
towtop = wallVerts[3].tow;
towbot = wallVerts[0].tow;
// Let dispoffset work first since this adjust each vertex
HWR_RotateSpritePolyToAim(spr, baseWallVerts);
realtop = top = baseWallVerts[3].y;
realbot = bot = baseWallVerts[0].y;
towtop = baseWallVerts[3].tow;
towbot = baseWallVerts[0].tow;
towmult = (towbot - towtop) / (top - bot);
#ifdef ESLOPE
endrealtop = endtop = wallVerts[2].y;
endrealbot = endbot = wallVerts[1].y;
endrealtop = endtop = baseWallVerts[2].y;
endrealbot = endbot = baseWallVerts[1].y;
#endif
// copy the contents of baseWallVerts into the drawn wallVerts array
// baseWallVerts is used to know the final shape to easily get the vertex
// co-ordinates
memcpy(wallVerts, baseWallVerts, sizeof(baseWallVerts));
if (!cv_translucency.value) // translucency disabled
{
Surf.FlatColor.s.alpha = 0xFF;
@ -4481,12 +4528,53 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
wallVerts[2].y = endtop;
wallVerts[0].y = bot;
wallVerts[1].y = endbot;
// The x and y only need to be adjusted in the case that it's not a papersprite
if (cv_grspritebillboarding.value && spr->mobj)
{
// Get the x and z of the vertices so billboarding draws correctly
realheight = realbot - realtop;
endrealheight = endrealbot - endrealtop;
heightmult = (realtop - top) / realheight;
wallVerts[3].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult;
wallVerts[3].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult;
heightmult = (endrealtop - endtop) / endrealheight;
wallVerts[2].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult;
wallVerts[2].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult;
heightmult = (realtop - bot) / realheight;
wallVerts[0].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult;
wallVerts[0].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult;
heightmult = (endrealtop - endbot) / endrealheight;
wallVerts[1].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult;
wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult;
}
#else
wallVerts[3].tow = wallVerts[2].tow = towtop + ((realtop - top) * towmult);
wallVerts[0].tow = wallVerts[1].tow = towtop + ((realtop - bot) * towmult);
wallVerts[2].y = wallVerts[3].y = top;
wallVerts[0].y = wallVerts[1].y = bot;
// The x and y only need to be adjusted in the case that it's not a papersprite
if (cv_grspritebillboarding.value && spr->mobj)
{
// Get the x and z of the vertices so billboarding draws correctly
realheight = realbot - realtop;
heightmult = (realtop - top) / realheight;
wallVerts[3].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult;
wallVerts[3].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult;
wallVerts[2].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult;
wallVerts[2].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult;
heightmult = (realtop - bot) / realheight;
wallVerts[0].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult;
wallVerts[0].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult;
wallVerts[1].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult;
wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult;
}
#endif
if (colormap)
@ -4655,6 +4743,9 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
wallVerts[1].x = wallVerts[2].x = wallVerts[1].x+co;
}
// Let dispoffset work first since this adjust each vertex
HWR_RotateSpritePolyToAim(spr, wallVerts);
// This needs to be AFTER the shadows so that the regular sprites aren't drawn completely black.
// sprite lighting by modulating the RGB components
/// \todo coloured
@ -4736,6 +4827,9 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
wallVerts[0].z = wallVerts[3].z = spr->z1;
wallVerts[1].z = wallVerts[2].z = spr->z2;
// Let dispoffset work first since this adjust each vertex
HWR_RotateSpritePolyToAim(spr, wallVerts);
wallVerts[0].sow = wallVerts[3].sow = 0;
wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s;

View File

@ -95,6 +95,7 @@ extern consvar_t cv_grcorrecttricks;
extern consvar_t cv_voodoocompatibility;
extern consvar_t cv_grfovchange;
extern consvar_t cv_grsolvetjoin;
extern consvar_t cv_grspritebillboarding;
extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy;

View File

@ -1072,7 +1072,9 @@ static INT16 typelines = 1; // number of drawfill lines we need when drawing the
//
boolean HU_Responder(event_t *ev)
{
#ifndef NONET
INT32 c=0;
#endif
if (ev->type != ev_keydown)
return false;
@ -1099,19 +1101,9 @@ boolean HU_Responder(event_t *ev)
return false;
}*/ //We don't actually care about that unless we get splitscreen netgames. :V
#ifndef NONET
c = (INT32)ev->data1;
// capslock (now handled outside of chat on so that it works everytime......)
if (c && c == KEY_CAPSLOCK) // it's a toggle.
{
if (capslock)
capslock = false;
else
capslock = true;
return true;
}
#ifndef NONET
if (!chat_on)
{
// enter chat mode
@ -1952,19 +1944,17 @@ static void HU_DrawCEcho(void)
static void HU_drawGametype(void)
{
INT32 i = 0;
const char *strvalue = NULL;
for (i = 0; gametype_cons_t[i].strvalue; i++)
{
if (gametype_cons_t[i].value == gametype)
{
if (splitscreen)
V_DrawString(4, 184, 0, gametype_cons_t[i].strvalue);
else
V_DrawString(4, 192, 0, gametype_cons_t[i].strvalue);
return;
}
}
if (gametype < 0 || gametype >= NUMGAMETYPES)
return; // not a valid gametype???
strvalue = Gametype_Names[gametype];
if (splitscreen)
V_DrawString(4, 184, 0, strvalue);
else
V_DrawString(4, 192, 0, strvalue);
}
//

View File

@ -146,6 +146,18 @@ boolean I_SongPaused(void);
boolean I_SetSongSpeed(float speed);
/// ------------------------
// MUSIC SEEKING
/// ------------------------
UINT32 I_GetSongLength(void);
boolean I_SetSongLoopPoint(UINT32 looppoint);
UINT32 I_GetSongLoopPoint(void);
boolean I_SetSongPosition(UINT32 position);
UINT32 I_GetSongPosition(void);
/// ------------------------
// MUSIC PLAYBACK
/// ------------------------
@ -216,6 +228,17 @@ void I_SetMusicVolume(UINT8 volume);
boolean I_SetSongTrack(INT32 track);
/// ------------------------
/// MUSIC FADING
/// ------------------------
void I_SetInternalMusicVolume(UINT8 volume);
void I_StopFadingSong(void);
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
boolean I_FadeOutStopSong(UINT32 ms);
boolean I_FadeInPlaySong(UINT32 ms, boolean looping);
/// ------------------------
// CD MUSIC I/O
/// ------------------------

View File

@ -612,7 +612,7 @@ static boolean SOCK_Get(void)
if (c != ERRSOCKET)
{
// find remote node number
for (j = 0; j <= MAXNETNODES; j++) //include LAN
for (j = 1; j <= MAXNETNODES; j++) //include LAN
{
if (SOCK_cmpaddr(&fromaddress, &clientaddress[j], 0))
{
@ -1340,8 +1340,12 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
while (runp != NULL)
{
// find ip of the server
memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen);
runp = NULL;
if (sendto(mysockets[0], NULL, 0, 0, runp->ai_addr, runp->ai_addrlen) == 0)
{
memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen);
break;
}
runp = runp->ai_next;
}
I_freeaddrinfo(ai);
return newnode;

View File

@ -780,7 +780,8 @@ static int lib_pRestoreMusic(lua_State *L)
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_RestoreMusic(player);
if (P_IsLocalPlayer(player))
P_RestoreMusic(player);
return 0;
}
@ -1820,7 +1821,7 @@ static int lib_sChangeMusic(lua_State *L)
{
#ifdef MUSICSLOT_COMPATIBILITY
const char *music_name;
UINT32 music_num;
UINT32 music_num, position, prefadems, fadeinms;
char music_compat_name[7];
boolean looping;
@ -1848,7 +1849,6 @@ static int lib_sChangeMusic(lua_State *L)
music_name = luaL_checkstring(L, 1);
}
looping = (boolean)lua_opttrueboolean(L, 2);
#else
@ -1873,8 +1873,12 @@ static int lib_sChangeMusic(lua_State *L)
#endif
music_flags = (UINT16)luaL_optinteger(L, 4, 0);
position = (UINT32)luaL_optinteger(L, 5, 0);
prefadems = (UINT32)luaL_optinteger(L, 6, 0);
fadeinms = (UINT32)luaL_optinteger(L, 7, 0);
if (!player || P_IsLocalPlayer(player))
S_ChangeMusic(music_name, music_flags, looping);
S_ChangeMusicEx(music_name, music_flags, looping, position, prefadems, fadeinms);
return 0;
}
@ -1891,10 +1895,8 @@ static int lib_sSpeedMusic(lua_State *L)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_SpeedMusic(speed));
else
lua_pushboolean(L, false);
return 1;
S_SpeedMusic(speed);
return 0;
}
static int lib_sStopMusic(lua_State *L)
@ -1912,6 +1914,110 @@ static int lib_sStopMusic(lua_State *L)
return 0;
}
static int lib_sSetInternalMusicVolume(lua_State *L)
{
UINT32 volume = (UINT32)luaL_checkinteger(L, 1);
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
{
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
S_SetInternalMusicVolume(volume);
lua_pushboolean(L, true);
}
else
lua_pushnil(L);
return 1;
}
static int lib_sStopFadingMusic(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
S_StopFadingMusic();
lua_pushboolean(L, true);
}
else
lua_pushnil(L);
return 1;
}
static int lib_sFadeMusic(lua_State *L)
{
UINT32 target_volume = (UINT32)luaL_checkinteger(L, 1);
UINT32 ms;
INT32 source_volume;
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
{
player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
ms = (UINT32)luaL_checkinteger(L, 2);
source_volume = -1;
}
else if (!lua_isnone(L, 4) && lua_isuserdata(L, 4))
{
player = *((player_t **)luaL_checkudata(L, 4, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
source_volume = (INT32)luaL_checkinteger(L, 2);
ms = (UINT32)luaL_checkinteger(L, 3);
}
else if (luaL_optinteger(L, 3, INT32_MAX) == INT32_MAX)
{
ms = (UINT32)luaL_checkinteger(L, 2);
source_volume = -1;
}
else
{
source_volume = (INT32)luaL_checkinteger(L, 2);
ms = (UINT32)luaL_checkinteger(L, 3);
}
NOHUD
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_FadeMusicFromVolume(target_volume, source_volume, ms));
else
lua_pushnil(L);
return 1;
}
static int lib_sFadeOutStopMusic(lua_State *L)
{
UINT32 ms = (UINT32)luaL_checkinteger(L, 1);
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
{
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
lua_pushboolean(L, S_FadeOutStopMusic(ms));
}
else
lua_pushnil(L);
return 1;
}
static int lib_sOriginPlaying(lua_State *L)
{
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -2264,6 +2370,10 @@ static luaL_Reg lib[] = {
{"S_ChangeMusic",lib_sChangeMusic},
{"S_SpeedMusic",lib_sSpeedMusic},
{"S_StopMusic",lib_sStopMusic},
{"S_SetInternalMusicVolume", lib_sSetInternalMusicVolume},
{"S_StopFadingMusic",lib_sStopFadingMusic},
{"S_FadeMusic",lib_sFadeMusic},
{"S_FadeOutStopMusic",lib_sFadeOutStopMusic},
{"S_OriginPlaying",lib_sOriginPlaying},
{"S_IdPlaying",lib_sIdPlaying},
{"S_SoundPlaying",lib_sSoundPlaying},

View File

@ -1468,6 +1468,12 @@ static int mapheaderinfo_get(lua_State *L)
lua_pushstring(L, header->musname);
else if (fastcmp(field,"mustrack"))
lua_pushinteger(L, header->mustrack);
else if (fastcmp(field,"muspos"))
lua_pushinteger(L, header->muspos);
else if (fastcmp(field,"musinterfadeout"))
lua_pushinteger(L, header->musinterfadeout);
else if (fastcmp(field,"musintername"))
lua_pushstring(L, header->musintername);
else if (fastcmp(field,"forcecharacter"))
lua_pushstring(L, header->forcecharacter);
else if (fastcmp(field,"weather"))

View File

@ -347,23 +347,9 @@ static CV_PossibleValue_t skins_cons_t[MAXSKINS+1] = {{1, DEFAULTSKIN}};
consvar_t cv_chooseskin = {"chooseskin", DEFAULTSKIN, CV_HIDEN|CV_CALL, skins_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL};
// This gametype list is integral for many different reasons.
// When you add gametypes here, don't forget to update them in CV_AddValue!
CV_PossibleValue_t gametype_cons_t[] =
{
{GT_COOP, "Co-op"},
// When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h!
CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1];
{GT_COMPETITION, "Competition"},
{GT_RACE, "Race"},
{GT_MATCH, "Match"},
{GT_TEAMMATCH, "Team Match"},
{GT_TAG, "Tag"},
{GT_HIDEANDSEEK, "Hide and Seek"},
{GT_CTF, "CTF"},
{0, NULL}
};
consvar_t cv_newgametype = {"newgametype", "Co-op", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t serversort_cons_t[] = {
@ -6545,7 +6531,7 @@ static void M_DrawRoomMenu(void)
static void M_DrawConnectMenu(void)
{
UINT16 i, j;
UINT16 i;
const char *gt = "Unknown";
INT32 numPages = (serverlistcount+(SERVERS_PER_PAGE-1))/SERVERS_PER_PAGE;
@ -6591,11 +6577,8 @@ static void M_DrawConnectMenu(void)
va("Ping: %u", (UINT32)LONG(serverlist[slindex].info.time)));
gt = "Unknown";
for (j = 0; gametype_cons_t[j].strvalue; j++)
{
if (gametype_cons_t[j].value == serverlist[slindex].info.gametype)
gt = gametype_cons_t[j].strvalue;
}
if (serverlist[slindex].info.gametype < NUMGAMETYPES)
gt = Gametype_Names[serverlist[slindex].info.gametype];
V_DrawSmallString(currentMenu->x+46,S_LINEY(i)+8, globalflags,
va("Players: %02d/%02d", serverlist[slindex].info.numberofplayer, serverlist[slindex].info.maxplayer));

View File

@ -2643,7 +2643,7 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
}
}
static inline void P_SuperDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage)
static void P_SuperDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage)
{
fixed_t fallbackspeed;
angle_t ang;

View File

@ -647,8 +647,6 @@ static void P_NetArchiveWorld(void)
WRITEUINT16(put, 0xffff);
mld = W_CacheLumpNum(lastloadedmaplumpnum+ML_LINEDEFS, PU_CACHE);
msd = W_CacheLumpNum(lastloadedmaplumpnum+ML_SIDEDEFS, PU_CACHE);
// do lines
for (i = 0; i < numlines; i++, mld++, li++)
{

View File

@ -187,6 +187,12 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
mapheaderinfo[num]->musname[6] = 0;
DEH_WriteUndoline("MUSICTRACK", va("%d", mapheaderinfo[num]->mustrack), UNDO_NONE);
mapheaderinfo[num]->mustrack = 0;
DEH_WriteUndoline("MUSICPOS", va("%d", mapheaderinfo[num]->muspos), UNDO_NONE);
mapheaderinfo[num]->muspos = 0;
DEH_WriteUndoline("MUSICINTERFADEOUT", va("%d", mapheaderinfo[num]->musinterfadeout), UNDO_NONE);
mapheaderinfo[num]->musinterfadeout = 0;
DEH_WriteUndoline("MUSICINTER", mapheaderinfo[num]->musintername, UNDO_NONE);
mapheaderinfo[num]->musintername[0] = '\0';
DEH_WriteUndoline("FORCECHARACTER", va("%d", mapheaderinfo[num]->forcecharacter), UNDO_NONE);
mapheaderinfo[num]->forcecharacter[0] = '\0';
DEH_WriteUndoline("WEATHER", va("%d", mapheaderinfo[num]->weather), UNDO_NONE);
@ -1527,19 +1533,33 @@ static void P_LoadRawSideDefs2(void *data)
{
M_Memcpy(process,msd->bottomtexture,8);
process[8] = '\0';
sd->bottomtexture = get_number(process)-1;
sd->bottomtexture = get_number(process);
}
M_Memcpy(process,msd->toptexture,8);
process[8] = '\0';
sd->text = Z_Malloc(7, PU_LEVEL, NULL);
// If they type in O_ or D_ and their music name, just shrug,
// then copy the rest instead.
if ((process[0] == 'O' || process[0] == 'D') && process[7])
M_Memcpy(sd->text, process+2, 6);
else // Assume it's a proper music name.
M_Memcpy(sd->text, process, 6);
sd->text[6] = 0;
if (!(msd->midtexture[0] == '-' && msd->midtexture[1] == '\0') || msd->midtexture[1] != '\0')
{
M_Memcpy(process,msd->midtexture,8);
process[8] = '\0';
sd->midtexture = get_number(process);
}
// always process if back sidedef, because we need that - symbol
sd->text = Z_Malloc(7, PU_LEVEL, NULL);
if (i == 1 || msd->toptexture[0] != '-' || msd->toptexture[1] != '\0')
{
M_Memcpy(process,msd->toptexture,8);
process[8] = '\0';
// If they type in O_ or D_ and their music name, just shrug,
// then copy the rest instead.
if ((process[0] == 'O' || process[0] == 'D') && process[7])
M_Memcpy(sd->text, process+2, 6);
else // Assume it's a proper music name.
M_Memcpy(sd->text, process, 6);
sd->text[6] = 0;
}
else
sd->text[0] = 0;
break;
}

View File

@ -2408,16 +2408,68 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
// console player only unless NOCLIMB is set
if ((line->flags & ML_NOCLIMB) || (mo && mo->player && P_IsLocalPlayer(mo->player)))
{
UINT16 tracknum = (UINT16)sides[line->sidenum[0]].bottomtexture;
boolean musicsame = (!sides[line->sidenum[0]].text[0] || !strnicmp(sides[line->sidenum[0]].text, S_MusicName(), 7));
UINT16 tracknum = (UINT16)max(sides[line->sidenum[0]].bottomtexture, 0);
INT32 position = (INT32)max(sides[line->sidenum[0]].midtexture, 0);
UINT32 prefadems = (UINT32)max(sides[line->sidenum[0]].textureoffset >> FRACBITS, 0);
UINT32 postfadems = (UINT32)max(sides[line->sidenum[0]].rowoffset >> FRACBITS, 0);
UINT8 fadetarget = (UINT8)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].textureoffset >> FRACBITS : 0, 0);
INT16 fadesource = (INT16)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].rowoffset >> FRACBITS : -1, -1);
strncpy(mapmusname, sides[line->sidenum[0]].text, 7);
mapmusname[6] = 0;
// Seek offset from current song position
if (line->flags & ML_EFFECT1)
{
// adjust for loop point if subtracting
if (position < 0 && S_GetMusicLength() &&
S_GetMusicPosition() > S_GetMusicLoopPoint() &&
S_GetMusicPosition() + position < S_GetMusicLoopPoint())
position = max(S_GetMusicLength() - (S_GetMusicLoopPoint() - (S_GetMusicPosition() + position)), 0);
else
position = max(S_GetMusicPosition() + position, 0);
}
mapmusflags = tracknum & MUSIC_TRACKMASK;
if (!(line->flags & ML_BLOCKMONSTERS))
mapmusflags |= MUSIC_RELOADRESET;
// Fade current music to target volume (if music won't be changed)
if ((line->flags & ML_EFFECT2) && fadetarget && musicsame)
{
// 0 fadesource means fade from current volume.
// meaning that we can't specify volume 0 as the source volume -- this starts at 1.
if (!fadesource)
fadesource = -1;
S_ChangeMusic(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4));
if (!postfadems)
S_SetInternalMusicVolume(fadetarget);
else
S_FadeMusicFromVolume(fadetarget, fadesource, postfadems);
if (position)
S_SetMusicPosition(position);
}
// Change the music and apply position/fade operations
else
{
strncpy(mapmusname, sides[line->sidenum[0]].text, 7);
mapmusname[6] = 0;
mapmusflags = tracknum & MUSIC_TRACKMASK;
if (!(line->flags & ML_BLOCKMONSTERS))
mapmusflags |= MUSIC_RELOADRESET;
if (line->flags & ML_BOUNCY)
mapmusflags |= MUSIC_FORCERESET;
mapmusposition = position;
S_ChangeMusicEx(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4), position,
!(line->flags & ML_EFFECT2) ? prefadems : 0,
!(line->flags & ML_EFFECT2) ? postfadems : 0);
if ((line->flags & ML_EFFECT2) && fadetarget)
{
if (!postfadems)
S_SetInternalMusicVolume(fadetarget);
else
S_FadeMusicFromVolume(fadetarget, fadesource, postfadems);
}
}
// Except, you can use the ML_BLOCKMONSTERS flag to change this behavior.
// if (mapmusflags & MUSIC_RELOADRESET) then it will reset the music in G_PlayerReborn.

View File

@ -1124,13 +1124,13 @@ void P_RestoreMusic(player_t *player)
if (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)
{
S_SpeedMusic(1.4f);
S_ChangeMusic(mapmusname, mapmusflags, true);
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
}
else
S_ChangeMusicInternal("shoes", true);
}
else
S_ChangeMusic(mapmusname, mapmusflags, true);
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
}
//

View File

@ -1407,6 +1407,7 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_grcoronasize);
#endif
CV_RegisterVar(&cv_grmd2);
CV_RegisterVar(&cv_grspritebillboarding);
#endif
#ifdef HWRENDER

View File

@ -854,24 +854,26 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
if (leftheight > pfloorleft && rightheight > pfloorright && i+1 < dc_numlights)
{
lightlist_t *nextlight = &frontsector->lightlist[i+1];
if (nextlight->slope ? P_GetZAt(nextlight->slope, ds->leftpos.x, ds->leftpos.y) : nextlight->height > pfloorleft
&& nextlight->slope ? P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y) : nextlight->height > pfloorright)
if ((nextlight->slope ? P_GetZAt(nextlight->slope, ds->leftpos.x, ds->leftpos.y) : nextlight->height) > pfloorleft
&& (nextlight->slope ? P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y) : nextlight->height) > pfloorright)
continue;
}
leftheight -= viewz;
rightheight -= viewz;
#define OVERFLOWTEST(height, scale) \
overflow_test = (INT64)centeryfrac - (((INT64)height*scale)>>FRACBITS); \
if (overflow_test < 0) overflow_test = -overflow_test; \
if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) continue;
#define CLAMPMAX INT32_MAX
#define CLAMPMIN (-INT32_MAX) // This is not INT32_MIN on purpose! INT32_MIN makes the drawers freak out.
// Monster Iestyn (25/03/18): do not skip these lights if they fail overflow test, just clamp them instead so they behave.
overflow_test = (INT64)centeryfrac - (((INT64)leftheight*ds->scale1)>>FRACBITS);
if (overflow_test > (INT64)CLAMPMAX) rlight->height = CLAMPMAX;
else if (overflow_test > (INT64)CLAMPMIN) rlight->height = (fixed_t)overflow_test;
else rlight->height = CLAMPMIN;
OVERFLOWTEST(leftheight, ds->scale1)
OVERFLOWTEST(rightheight, ds->scale2)
rlight->height = (centeryfrac) - FixedMul(leftheight, ds->scale1);
rlight->heightstep = (centeryfrac) - FixedMul(rightheight, ds->scale2);
overflow_test = (INT64)centeryfrac - (((INT64)rightheight*ds->scale2)>>FRACBITS);
if (overflow_test > (INT64)CLAMPMAX) rlight->heightstep = CLAMPMAX;
else if (overflow_test > (INT64)CLAMPMIN) rlight->heightstep = (fixed_t)overflow_test;
else rlight->heightstep = CLAMPMIN;
rlight->heightstep = (rlight->heightstep-rlight->height)/(range);
#else
if (light->height < *pfloor->bottomheight)
@ -893,12 +895,16 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
leftheight -= viewz;
rightheight -= viewz;
OVERFLOWTEST(leftheight, ds->scale1)
OVERFLOWTEST(rightheight, ds->scale2)
#undef OVERFLOWTEST
// Monster Iestyn (25/03/18): do not skip these lights if they fail overflow test, just clamp them instead so they behave.
overflow_test = (INT64)centeryfrac - (((INT64)leftheight*ds->scale1)>>FRACBITS);
if (overflow_test > (INT64)CLAMPMAX) rlight->botheight = CLAMPMAX;
else if (overflow_test > (INT64)CLAMPMIN) rlight->botheight = (fixed_t)overflow_test;
else rlight->botheight = CLAMPMIN;
rlight->botheight = (centeryfrac) - FixedMul(leftheight, ds->scale1);
rlight->botheightstep = (centeryfrac) - FixedMul(rightheight, ds->scale2);
overflow_test = (INT64)centeryfrac - (((INT64)rightheight*ds->scale2)>>FRACBITS);
if (overflow_test > (INT64)CLAMPMAX) rlight->botheightstep = CLAMPMAX;
else if (overflow_test > (INT64)CLAMPMIN) rlight->botheightstep = (fixed_t)overflow_test;
else rlight->botheightstep = CLAMPMIN;
rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(range);
#else
lheight = *light->caster->bottomheight;// > *pfloor->topheight ? *pfloor->topheight + FRACUNIT : *light->caster->bottomheight;
@ -1071,9 +1077,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
}
#endif
#define CLAMPMAX INT32_MAX
#define CLAMPMIN (-INT32_MAX) // This is not INT32_MIN on purpose! INT32_MIN makes the drawers freak out.
// draw the columns
for (dc_x = x1; dc_x <= x2; dc_x++)
{

View File

@ -38,6 +38,10 @@ extern INT32 msg_id;
#include "p_local.h" // camera info
#include "m_misc.h" // for tunes command
#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS)
#include "lua_hook.h" // MusicChange hook
#endif
#ifdef HW3SOUND
// 3D Sound Interface
#include "hardware/hw3sound.h"
@ -1241,6 +1245,12 @@ static void *music_data;
static UINT16 music_flags;
static boolean music_looping;
static char queue_name[7];
static UINT16 queue_flags;
static boolean queue_looping;
static UINT32 queue_position;
static UINT32 queue_fadeinms;
/// ------------------------
/// Music Status
/// ------------------------
@ -1275,6 +1285,11 @@ musictype_t S_MusicType(void)
return I_SongType();
}
const char *S_MusicName(void)
{
return music_name;
}
boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping)
{
if (!I_SongPlaying())
@ -1305,6 +1320,35 @@ boolean S_SpeedMusic(float speed)
return I_SetSongSpeed(speed);
}
/// ------------------------
/// Music Seeking
/// ------------------------
UINT32 S_GetMusicLength(void)
{
return I_GetSongLength();
}
boolean S_SetMusicLoopPoint(UINT32 looppoint)
{
return I_SetSongLoopPoint(looppoint);
}
UINT32 S_GetMusicLoopPoint(void)
{
return I_GetSongLoopPoint();
}
boolean S_SetMusicPosition(UINT32 position)
{
return I_SetSongPosition(position);
}
UINT32 S_GetMusicPosition(void)
{
return I_GetSongPosition();
}
/// ------------------------
/// Music Playback
/// ------------------------
@ -1377,12 +1421,13 @@ static void S_UnloadMusic(void)
music_looping = false;
}
static boolean S_PlayMusic(boolean looping)
static boolean S_PlayMusic(boolean looping, UINT32 fadeinms)
{
if (S_MusicDisabled())
return false;
if (!I_PlaySong(looping))
if ((!fadeinms && !I_PlaySong(looping)) ||
(fadeinms && !I_FadeInPlaySong(fadeinms, looping)))
{
S_UnloadMusic();
return false;
@ -1392,8 +1437,30 @@ static boolean S_PlayMusic(boolean looping)
return true;
}
void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping)
static void S_QueueMusic(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 fadeinms)
{
strncpy(queue_name, mmusic, 7);
queue_flags = mflags;
queue_looping = looping;
queue_position = position;
queue_fadeinms = fadeinms;
}
static void S_ClearQueue(void)
{
queue_name[0] = queue_flags = queue_looping = queue_position = queue_fadeinms = 0;
}
static void S_ChangeMusicToQueue(void)
{
S_ChangeMusicEx(queue_name, queue_flags, queue_looping, queue_position, 0, queue_fadeinms);
S_ClearQueue();
}
void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms)
{
char newmusic[7];
#if defined (DC) || defined (_WIN32_WCE) || defined (PSP) || defined(GP2X)
S_ClearSfx();
#endif
@ -1401,33 +1468,66 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping)
if (S_MusicDisabled())
return;
// No Music (empty string)
if (mmusic[0] == 0)
{
S_StopMusic();
strncpy(newmusic, mmusic, 7);
#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS)
if(LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms))
return;
#endif
newmusic[6] = 0;
// No Music (empty string)
if (newmusic[0] == 0)
{
if (prefadems)
I_FadeSong(0, prefadems, &S_StopMusic);
else
S_StopMusic();
return;
}
if (strnicmp(music_name, mmusic, 6))
if (prefadems && S_MusicPlaying()) // queue music change for after fade // allow even if the music is the same
{
S_StopMusic(); // shutdown old music
CONS_Debug(DBG_DETAILED, "Now fading out song %s\n", music_name);
S_QueueMusic(newmusic, mflags, looping, position, fadeinms);
I_FadeSong(0, prefadems, S_ChangeMusicToQueue);
return;
}
else if (strnicmp(music_name, newmusic, 6) || (mflags & MUSIC_FORCERESET))
{
CONS_Debug(DBG_DETAILED, "Now playing song %s\n", newmusic);
if (!S_LoadMusic(mmusic))
S_StopMusic();
if (!S_LoadMusic(newmusic))
{
CONS_Alert(CONS_ERROR, "Music %.6s could not be loaded!\n", mmusic);
CONS_Alert(CONS_ERROR, "Music %.6s could not be loaded!\n", newmusic);
return;
}
music_flags = mflags;
music_looping = looping;
if (!S_PlayMusic(looping))
{
CONS_Alert(CONS_ERROR, "Music %.6s could not be played!\n", mmusic);
if (!S_PlayMusic(looping, fadeinms))
{
CONS_Alert(CONS_ERROR, "Music %.6s could not be played!\n", newmusic);
return;
}
if (position)
I_SetSongPosition(position);
I_SetSongTrack(mflags & MUSIC_TRACKMASK);
}
else if (fadeinms) // let fades happen with same music
{
I_SetSongPosition(position);
I_FadeSong(100, fadeinms, NULL);
}
else // reset volume to 100 with same music
{
I_StopFadingSong();
I_FadeSong(100, 500, NULL);
}
I_SetSongTrack(mflags & MUSIC_TRACKMASK);
}
void S_StopMusic(void)
@ -1502,6 +1602,32 @@ void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume)
}
}
/// ------------------------
/// Music Fading
/// ------------------------
void S_SetInternalMusicVolume(INT32 volume)
{
I_SetInternalMusicVolume(min(max(volume, 0), 100));
}
void S_StopFadingMusic(void)
{
I_StopFadingSong();
}
boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 ms)
{
if (source_volume < 0)
return I_FadeSong(target_volume, ms, NULL);
else
return I_FadeSongFromVolume(target_volume, source_volume, ms, NULL);
}
boolean S_FadeOutStopMusic(UINT32 ms)
{
return I_FadeSong(0, ms, &S_StopMusic);
}
/// ------------------------
/// Init & Others
@ -1519,22 +1645,24 @@ void S_Start(void)
strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7);
mapmusname[6] = 0;
mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK);
mapmusposition = mapheaderinfo[gamemap-1]->muspos;
}
if (cv_resetmusic.value)
S_StopMusic();
S_ChangeMusic(mapmusname, mapmusflags, true);
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
}
static void Command_Tunes_f(void)
{
const char *tunearg;
UINT16 tunenum, track = 0;
UINT32 position = 0;
const size_t argc = COM_Argc();
if (argc < 2) //tunes slot ...
{
CONS_Printf("tunes <name/num> [track] [speed] / <-show> / <-default> / <-none>:\n");
CONS_Printf("tunes <name/num> [track] [speed] [position] / <-show> / <-default> / <-none>:\n");
CONS_Printf(M_GetText("Play an arbitrary music lump. If a map number is used, 'MAP##M' is played.\n"));
CONS_Printf(M_GetText("If the format supports multiple songs, you can specify which one to play.\n\n"));
CONS_Printf(M_GetText("* With \"-show\", shows the currently playing tune and track.\n"));
@ -1581,10 +1709,15 @@ static void Command_Tunes_f(void)
snprintf(mapmusname, 7, "%sM", G_BuildMapName(tunenum));
else
strncpy(mapmusname, tunearg, 7);
if (argc > 4)
position = (UINT32)atoi(COM_Argv(4));
mapmusname[6] = 0;
mapmusflags = (track & MUSIC_TRACKMASK);
mapmusposition = position;
S_ChangeMusic(mapmusname, mapmusflags, true);
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
if (argc > 3)
{

View File

@ -112,29 +112,49 @@ boolean S_MusicDisabled(void);
boolean S_MusicPlaying(void);
boolean S_MusicPaused(void);
musictype_t S_MusicType(void);
const char *S_MusicName(void);
boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping);
boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi);
#define S_DigExists(a) S_MusicExists(a, false, true)
#define S_MIDIExists(a) S_MusicExists(a, true, false)
//
// Music Properties
// Music Effects
//
// Set Speed of Music
boolean S_SpeedMusic(float speed);
//
// Music Routines
// Music Seeking
//
// Get Length of Music
UINT32 S_GetMusicLength(void);
// Set LoopPoint of Music
boolean S_SetMusicLoopPoint(UINT32 looppoint);
// Get LoopPoint of Music
UINT32 S_GetMusicLoopPoint(void);
// Set Position of Music
boolean S_SetMusicPosition(UINT32 position);
// Get Position of Music
UINT32 S_GetMusicPosition(void);
//
// Music Playback
//
// Start music track, arbitrary, given its name, and set whether looping
// note: music flags 12 bits for tracknum (gme, other formats with more than one track)
// 13-15 aren't used yet
// and the last bit we ignore (internal game flag for resetting music on reload)
#define S_ChangeMusicInternal(a,b) S_ChangeMusic(a,0,b)
void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping);
void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms);
#define S_ChangeMusicInternal(a,b) S_ChangeMusicEx(a,0,b,0,0,0)
#define S_ChangeMusic(a,b,c) S_ChangeMusicEx(a,b,c,0,0,0)
// Stops the music.
void S_StopMusic(void);
@ -143,6 +163,17 @@ void S_StopMusic(void);
void S_PauseAudio(void);
void S_ResumeAudio(void);
//
// Music Fading
//
void S_SetInternalMusicVolume(INT32 volume);
void S_StopFadingMusic(void);
boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 ms);
#define S_FadeMusic(a, b) S_FadeMusicFromVolume(a, -1, b)
#define S_FadeInChangeMusic(a,b,c,d) S_ChangeMusicEx(a,b,c,0,0,d)
boolean S_FadeOutStopMusic(UINT32 ms);
//
// Updates music & sounds
//

View File

@ -1402,7 +1402,13 @@ static int joy_open2(const char *fname)
void I_InitJoystick(void)
{
I_ShutdownJoystick();
SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
if (M_CheckParm("-noxinput"))
SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
if (M_CheckParm("-nohidapi"))
SDL_SetHintWithPriority("SDL_JOYSTICK_HIDAPI", "0", SDL_HINT_OVERRIDE);
if (!strcmp(cv_usejoystick.string, "0") || M_CheckParm("-nojoy"))
return;
if (joy_open(cv_usejoystick.string) != -1)
@ -1418,7 +1424,13 @@ void I_InitJoystick(void)
void I_InitJoystick2(void)
{
I_ShutdownJoystick2();
SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
if (M_CheckParm("-noxinput"))
SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
if (M_CheckParm("-nohidapi"))
SDL_SetHintWithPriority("SDL_JOYSTICK_HIDAPI", "0", SDL_HINT_OVERRIDE);
if (!strcmp(cv_usejoystick2.string, "0") || M_CheckParm("-nojoy"))
return;
if (joy_open2(cv_usejoystick2.string) != -1)

View File

@ -580,8 +580,6 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
if (cv_usemouse.value) I_StartupMouse();
}
//else firsttimeonmouse = SDL_FALSE;
capslock = !!( SDL_GetModState() & KMOD_CAPS );// in case CL changes
}
else if (!mousefocus && !kbfocus)
{
@ -939,6 +937,8 @@ void I_StartupMouse(void)
//
void I_OsPolling(void)
{
SDL_Keymod mod;
if (consolevent)
I_GetConsoleEvents();
if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
@ -951,6 +951,18 @@ void I_OsPolling(void)
I_GetMouseEvents();
I_GetEvent();
mod = SDL_GetModState();
/* Handle here so that our state is always synched with the system. */
shiftdown = ctrldown = altdown = 0;
capslock = false;
if (mod & KMOD_LSHIFT) shiftdown |= 1;
if (mod & KMOD_RSHIFT) shiftdown |= 2;
if (mod & KMOD_LCTRL) ctrldown |= 1;
if (mod & KMOD_RCTRL) ctrldown |= 2;
if (mod & KMOD_LALT) altdown |= 1;
if (mod & KMOD_RALT) altdown |= 2;
if (mod & KMOD_CAPS) capslock = true;
}
//
@ -984,6 +996,7 @@ void I_UpdateNoBlit(void)
// from PrBoom's src/SDL/i_video.c
static inline boolean I_SkipFrame(void)
{
#if 0
static boolean skip = false;
if (rendermode != render_soft)
@ -1003,6 +1016,8 @@ static inline boolean I_SkipFrame(void)
default:
return false;
}
#endif
return false;
}
//

View File

@ -75,15 +75,41 @@
UINT8 sound_started = false;
static Mix_Music *music;
static UINT8 music_volume, sfx_volume;
static UINT8 music_volume, sfx_volume, internal_volume;
static float loop_point;
static float song_length; // length in seconds
static boolean songpaused;
static UINT32 music_bytes;
static boolean is_looping;
// fading
static boolean is_fading;
static UINT8 fading_source;
static UINT8 fading_target;
static UINT32 fading_timer;
static UINT32 fading_duration;
static INT32 fading_id;
static void (*fading_callback)(void);
#ifdef HAVE_LIBGME
static Music_Emu *gme;
static INT32 current_track;
#endif
static void var_cleanup(void)
{
loop_point = song_length =\
music_bytes = fading_source = fading_target =\
fading_timer = fading_duration = 0;
songpaused = is_looping =\
is_fading = false;
fading_callback = NULL;
internal_volume = 100;
}
/// ------------------------
/// Audio System
/// ------------------------
@ -111,6 +137,8 @@ void I_StartupSound(void)
return;
}
var_cleanup();
music = NULL;
music_volume = sfx_volume = 0;
@ -336,6 +364,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
len = (info->play_length * 441 / 10) << 2;
mem = malloc(len);
gme_play(emu, len >> 1, mem);
gme_free_info(info);
gme_delete(emu);
return Mix_QuickLoad_RAW((Uint8 *)mem, len);
@ -408,6 +437,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
len = (info->play_length * 441 / 10) << 2;
mem = malloc(len);
gme_play(emu, len >> 1, mem);
gme_free_info(info);
gme_delete(emu);
return Mix_QuickLoad_RAW((Uint8 *)mem, len);
@ -482,14 +512,102 @@ void I_SetSfxVolume(UINT8 volume)
sfx_volume = volume;
}
/// ------------------------
/// Music Utilities
/// ------------------------
static UINT32 get_real_volume(UINT8 volume)
{
#ifdef _WIN32
if (I_SongType() == MU_MID)
// HACK: Until we stop using native MIDI,
// disable volume changes
return ((UINT32)31*128/31); // volume = 31
else
#endif
// convert volume to mixer's 128 scale
// then apply internal_volume as a percentage
return ((UINT32)volume*128/31) * (UINT32)internal_volume / 100;
}
static UINT32 get_adjusted_position(UINT32 position)
{
// all in milliseconds
UINT32 length = I_GetSongLength();
UINT32 looppoint = I_GetSongLoopPoint();
if (length)
return position >= length ? (position % (length-looppoint)) : position;
else
return position;
}
static void do_fading_callback(void)
{
if (fading_callback)
(*fading_callback)();
fading_callback = NULL;
}
/// ------------------------
/// Music Hooks
/// ------------------------
static void count_music_bytes(int chan, void *stream, int len, void *udata)
{
(void)chan;
(void)stream;
(void)udata;
if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || I_SongType() == MU_MID)
return;
music_bytes += len;
}
static void music_loop(void)
{
Mix_PlayMusic(music, 0);
Mix_SetMusicPosition(loop_point);
if (is_looping)
{
Mix_PlayMusic(music, 0);
Mix_SetMusicPosition(loop_point);
music_bytes = loop_point*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition)
}
else
I_StopSong();
}
static UINT32 music_fade(UINT32 interval, void *param)
{
(void)param;
if (!is_fading ||
internal_volume == fading_target ||
fading_duration == 0)
{
I_StopFadingSong();
do_fading_callback();
return 0;
}
else if (songpaused) // don't decrement timer
return interval;
else if ((fading_timer -= 10) <= 0)
{
internal_volume = fading_target;
Mix_VolumeMusic(get_real_volume(music_volume));
I_StopFadingSong();
do_fading_callback();
return 0;
}
else
{
UINT8 delta = abs(fading_target - fading_source);
fixed_t factor = FixedDiv(fading_duration - fading_timer, fading_duration);
if (fading_target < fading_source)
internal_volume = max(min(internal_volume, fading_source - FixedMul(delta, factor)), fading_target);
else if (fading_target > fading_source)
internal_volume = min(max(internal_volume, fading_source + FixedMul(delta, factor)), fading_target);
Mix_VolumeMusic(get_real_volume(music_volume));
return interval;
}
}
#ifdef HAVE_LIBGME
@ -509,7 +627,7 @@ static void mix_gme(void *udata, Uint8 *stream, int len)
// apply volume to stream
for (i = 0, p = (short *)stream; i < len/2; i++, p++)
*p = ((INT32)*p) * music_volume*2 / 42;
*p = ((INT32)*p) * (music_volume*internal_volume/100)*2 / 42;
}
#endif
@ -587,6 +705,194 @@ boolean I_SetSongSpeed(float speed)
return false;
}
/// ------------------------
/// MUSIC SEEKING
/// ------------------------
UINT32 I_GetSongLength(void)
{
INT32 length;
#ifdef HAVE_LIBGME
if (gme)
{
gme_info_t *info;
gme_err_t gme_e = gme_track_info(gme, &info, current_track);
if (gme_e != NULL)
{
CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e);
length = 0;
}
else
{
// reconstruct info->play_length, from GME source
// we only want intro + 1 loop, not 2
length = info->length;
if (length <= 0)
{
length = info->intro_length + info->loop_length; // intro + 1 loop
if (length <= 0)
length = 150 * 1000; // 2.5 minutes
}
}
gme_free_info(info);
return max(length, 0);
}
else
#endif
if (!music || I_SongType() == MU_MOD || I_SongType() == MU_MID)
return 0;
else
{
// VERY IMPORTANT to set your LENGTHMS= in your song files, folks!
// SDL mixer can't read music length itself.
length = (UINT32)(song_length*1000);
if (!length)
CONS_Debug(DBG_DETAILED, "Getting music length: music is missing LENGTHMS= tag. Needed for seeking.\n");
return length;
}
}
boolean I_SetSongLoopPoint(UINT32 looppoint)
{
if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || I_SongType() == MU_MID || !is_looping)
return false;
else
{
UINT32 length = I_GetSongLength();
if (length > 0)
looppoint %= length;
loop_point = max((float)(looppoint / 1000.0L), 0);
return true;
}
}
UINT32 I_GetSongLoopPoint(void)
{
#ifdef HAVE_LIBGME
if (gme)
{
INT32 looppoint;
gme_info_t *info;
gme_err_t gme_e = gme_track_info(gme, &info, current_track);
if (gme_e != NULL)
{
CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e);
looppoint = 0;
}
else
looppoint = info->intro_length > 0 ? info->intro_length : 0;
gme_free_info(info);
return max(looppoint, 0);
}
else
#endif
if (!music || I_SongType() == MU_MOD || I_SongType() == MU_MID)
return 0;
else
return (UINT32)(loop_point * 1000);
}
boolean I_SetSongPosition(UINT32 position)
{
UINT32 length;
#ifdef HAVE_LIBGME
if (gme)
{
// this is unstable, so fail silently
return true;
// this isn't required technically, but GME thread-locks for a second
// if you seek too high from the counter
// length = I_GetSongLength();
// if (length)
// position = get_adjusted_position(position);
// SDL_LockAudio();
// gme_err_t gme_e = gme_seek(gme, position);
// SDL_UnlockAudio();
// if (gme_e != NULL)
// {
// CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e);
// return false;
// }
// else
// return true;
}
else
#endif
if (!music || I_SongType() == MU_MID)
return false;
else if (I_SongType() == MU_MOD)
return Mix_SetMusicPosition(position); // Goes by channels
else
{
// Because SDL mixer can't identify song length, if you have
// a position input greater than the real length, then
// music_bytes becomes inaccurate.
length = I_GetSongLength(); // get it in MS
if (length)
position = get_adjusted_position(position);
Mix_RewindMusic(); // needed for mp3
if(Mix_SetMusicPosition((float)(position/1000.0L)) == 0)
music_bytes = position/1000.0L*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition)
else
// NOTE: This block fires on incorrect song format,
// NOT if position input is greater than song length.
music_bytes = 0;
return true;
}
}
UINT32 I_GetSongPosition(void)
{
#ifdef HAVE_LIBGME
if (gme)
{
INT32 position = gme_tell(gme);
gme_info_t *info;
gme_err_t gme_e = gme_track_info(gme, &info, current_track);
if (gme_e != NULL)
{
CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e);
return position;
}
else
{
// adjust position, since GME's counter keeps going past loop
if (info->length > 0)
position %= info->length;
else if (info->intro_length + info->loop_length > 0)
position = position >= (info->intro_length + info->loop_length) ? (position % info->loop_length) : position;
else
position %= 150 * 1000; // 2.5 minutes
}
gme_free_info(info);
return max(position, 0);
}
else
#endif
if (!music || I_SongType() == MU_MID)
return 0;
else
return music_bytes/44100.0L*1000.0L/4; //assume 44.1khz
// 4 = byte length for 16-bit samples (AUDIO_S16SYS), stereo (2-channel)
// This is hardcoded in I_StartupSound. Other formats for factor:
// 8M: 1 | 8S: 2 | 16M: 2 | 16S: 4
}
/// ------------------------
/// Music Playback
/// ------------------------
@ -599,6 +905,7 @@ boolean I_LoadSong(char *data, size_t len)
const size_t key1len = strlen(key1);
const size_t key2len = strlen(key2);
const size_t key3len = strlen(key3);
char *p = data;
SDL_RWops *rw;
@ -609,6 +916,9 @@ boolean I_LoadSong(char *data, size_t len)
)
I_UnloadSong();
// always do this whether or not a music already exists
var_cleanup();
#ifdef HAVE_LIBGME
if ((UINT8)data[0] == 0x1F
&& (UINT8)data[1] == 0x8B)
@ -718,30 +1028,35 @@ boolean I_LoadSong(char *data, size_t len)
// Find the OGG loop point.
loop_point = 0.0f;
song_length = 0.0f;
while ((UINT32)(p - data) < len)
{
if (strncmp(p++, key1, key1len))
continue;
p += key1len-1; // skip OOP (the L was skipped in strncmp)
if (!strncmp(p, key2, key2len)) // is it LOOPPOINT=?
if (fpclassify(loop_point) == FP_ZERO && !strncmp(p, key1, key1len))
{
p += key2len; // skip POINT=
loop_point = (float)((44.1L+atoi(p)) / 44100.0L); // LOOPPOINT works by sample count.
// because SDL_Mixer is USELESS and can't even tell us
// something simple like the frequency of the streaming music,
// we are unfortunately forced to assume that ALL MUSIC is 44100hz.
// This means a lot of tracks that are only 22050hz for a reasonable downloadable file size will loop VERY badly.
p += key1len; // skip LOOP
if (!strncmp(p, key2, key2len)) // is it LOOPPOINT=?
{
p += key2len; // skip POINT=
loop_point = (float)((44.1L+atoi(p)) / 44100.0L); // LOOPPOINT works by sample count.
// because SDL_Mixer is USELESS and can't even tell us
// something simple like the frequency of the streaming music,
// we are unfortunately forced to assume that ALL MUSIC is 44100hz.
// This means a lot of tracks that are only 22050hz for a reasonable downloadable file size will loop VERY badly.
}
else if (!strncmp(p, key3, key3len)) // is it LOOPMS=?
{
p += key3len; // skip MS=
loop_point = (float)(atoi(p) / 1000.0L); // LOOPMS works by real time, as miliseconds.
// Everything that uses LOOPMS will work perfectly with SDL_Mixer.
}
}
else if (!strncmp(p, key3, key3len)) // is it LOOPMS=?
{
p += key3len; // skip MS=
loop_point = (float)(atoi(p) / 1000.0L); // LOOPMS works by real time, as miliseconds.
// Everything that uses LOOPMS will work perfectly with SDL_Mixer.
}
// Neither?! Continue searching.
}
if (fpclassify(loop_point) != FP_ZERO) // Got what we needed
break;
else // continue searching
p++;
}
return true;
}
@ -765,7 +1080,6 @@ void I_UnloadSong(void)
boolean I_PlaySong(boolean looping)
{
boolean lpz = fpclassify(loop_point) == FP_ZERO;
#ifdef HAVE_LIBGME
if (gme)
{
@ -779,21 +1093,37 @@ boolean I_PlaySong(boolean looping)
if (!music)
return false;
if (fpclassify(song_length) == FP_ZERO && (I_SongType() == MU_OGG || I_SongType() == MU_MP3 || I_SongType() == MU_FLAC))
CONS_Debug(DBG_DETAILED, "This song is missing a LENGTHMS= tag! Required to make seeking work properly.\n");
if (Mix_PlayMusic(music, looping && lpz ? -1 : 0) == -1)
if (I_SongType() != MU_MOD && I_SongType() != MU_MID && Mix_PlayMusic(music, 0) == -1)
{
CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError());
return false;
}
else if ((I_SongType() == MU_MOD || I_SongType() == MU_MID) && Mix_PlayMusic(music, looping ? -1 : 0) == -1) // if MOD, loop forever
{
CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError());
return false;
}
Mix_VolumeMusic((UINT32)music_volume*128/31);
if (!lpz)
Mix_HookMusicFinished(music_loop);
is_looping = looping;
I_SetMusicVolume(music_volume);
if (I_SongType() != MU_MOD && I_SongType() != MU_MID)
Mix_HookMusicFinished(music_loop); // don't bother counting if MOD
if(I_SongType() != MU_MOD && I_SongType() != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL))
CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError());
return true;
}
void I_StopSong(void)
{
I_StopFadingSong();
#ifdef HAVE_LIBGME
if (gme)
{
@ -803,19 +1133,40 @@ void I_StopSong(void)
#endif
if (music)
{
Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes);
Mix_HookMusicFinished(NULL);
Mix_HaltMusic();
}
var_cleanup();
}
void I_PauseSong(void)
{
if(I_SongType() == MU_MID) // really, SDL Mixer? why can't you pause MIDI???
return;
if(I_SongType() != MU_GME && I_SongType() != MU_MOD && I_SongType() != MU_MID)
Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes);
Mix_PauseMusic();
songpaused = true;
}
void I_ResumeSong(void)
{
if (I_SongType() == MU_MID)
return;
if (I_SongType() != MU_GME && I_SongType() != MU_MOD && I_SongType() != MU_MID)
{
while(Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes) != 0) { }
// HACK: fixes issue of multiple effect callbacks being registered
if(music && I_SongType() != MU_MOD && I_SongType() != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL))
CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError());
}
Mix_ResumeMusic();
songpaused = false;
}
@ -834,7 +1185,7 @@ void I_SetMusicVolume(UINT8 volume)
#endif
music_volume = volume;
Mix_VolumeMusic((UINT32)music_volume*128/31);
Mix_VolumeMusic(get_real_volume(music_volume));
}
boolean I_SetSongTrack(int track)
@ -863,9 +1214,100 @@ boolean I_SetSongTrack(int track)
SDL_UnlockAudio();
return false;
}
else
#endif
if (I_SongType() == MU_MOD)
return !Mix_SetMusicPosition(track);
(void)track;
return false;
}
/// ------------------------
/// MUSIC FADING
/// ------------------------
void I_SetInternalMusicVolume(UINT8 volume)
{
internal_volume = volume;
if (!I_SongPlaying())
return;
Mix_VolumeMusic(get_real_volume(music_volume));
}
void I_StopFadingSong(void)
{
if (fading_id)
SDL_RemoveTimer(fading_id);
is_fading = false;
fading_source = fading_target = fading_timer = fading_duration = fading_id = 0;
}
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void))
{
INT16 volume_delta;
source_volume = min(source_volume, 100);
volume_delta = (INT16)(target_volume - source_volume);
I_StopFadingSong();
if (!ms && volume_delta)
{
I_SetInternalMusicVolume(target_volume);
if (callback)
(*callback)();
return true;
}
else if (!volume_delta)
{
if (callback)
(*callback)();
return true;
}
// Round MS to nearest 10
// If n - lower > higher - n, then round up
ms = (ms - ((ms / 10) * 10) > (((ms / 10) * 10) + 10) - ms) ?
(((ms / 10) * 10) + 10) // higher
: ((ms / 10) * 10); // lower
if (!ms)
I_SetInternalMusicVolume(target_volume);
else if (source_volume != target_volume)
{
fading_id = SDL_AddTimer(10, music_fade, NULL);
if (fading_id)
{
is_fading = true;
fading_timer = fading_duration = ms;
fading_source = source_volume;
fading_target = target_volume;
fading_callback = callback;
if (internal_volume != source_volume)
I_SetInternalMusicVolume(source_volume);
}
}
return is_fading;
}
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void))
{
return I_FadeSongFromVolume(target_volume, internal_volume, ms, callback);
}
boolean I_FadeOutStopSong(UINT32 ms)
{
return I_FadeSongFromVolume(0, internal_volume, ms, &I_StopSong);
}
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
{
if (I_PlaySong(looping))
return I_FadeSongFromVolume(100, 0, ms, NULL);
else
return false;
}
#endif

View File

@ -1375,6 +1375,37 @@ boolean I_SetSongSpeed(float speed)
return false;
}
/// ------------------------
// MUSIC SEEKING
/// ------------------------
UINT32 I_GetSongLength(void)
{
return 0;
}
boolean I_SetSongLoopPoint(UINT32 looppoint)
{
(void)looppoint;
return false;
}
UINT32 I_GetSongLoopPoint(void)
{
return 0;
}
boolean I_SetSongPosition(UINT32 position)
{
(void)position;
return false;
}
UINT32 I_GetSongPosition(void)
{
return 0;
}
/// ------------------------
// MUSIC PLAYBACK
/// ------------------------
@ -1443,6 +1474,47 @@ boolean I_SetSongTrack(int track)
return false;
}
/// ------------------------
/// MUSIC FADING
/// ------------------------
void I_SetInternalMusicVolume(UINT8 volume)
{
(void)volume;
}
void I_StopFadingSong(void)
{
}
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void))
{
(void)target_volume;
(void)source_volume;
(void)ms;
return false;
}
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void))
{
(void)target_volume;
(void)ms;
return false;
}
boolean I_FadeOutStopSong(UINT32 ms)
{
(void)ms;
return false;
}
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
{
(void)ms;
(void)looping;
return false;
}
/// ------------------------
// MUSIC LOADING AND CLEANUP
// \todo Split logic between loading and playing,

View File

@ -81,6 +81,7 @@ consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE| CV_FLOAT, 0, NULL, 0
static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NULL}};
// console variables in development
consvar_t cv_grmd2 = {"gr_md2", "Off", CV_SAVE, CV_MD2, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
const UINT8 gammatable[5][256] =

View File

@ -1179,6 +1179,23 @@ void zerr(int ret)
}
#endif
#define NO_PNG_LUMPS
#ifdef NO_PNG_LUMPS
static void ErrorIfPNG(UINT8 *d, size_t s, char *f, char *l)
{
if (s < 67) // http://garethrees.org/2007/11/14/pngcrush/
return;
// Check for PNG file signature using memcmp
// As it may be faster on CPUs with slow unaligned memory access
// Ref: http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature
if (memcmp(&d[0], "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8) == 0)
{
I_Error("W_Wad: Lump \"%s\" in file \"%s\" is a .PNG - please convert to either Doom or Flat (raw) image format.", l, f);
}
}
#endif
/** Reads bytes from the head of a lump.
* Note: If the lump is compressed, the whole thing has to be read anyway.
*
@ -1218,7 +1235,15 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
switch(wadfiles[wad]->lumpinfo[lump].compression)
{
case CM_NOCOMPRESSION: // If it's uncompressed, we directly write the data into our destination, and return the bytes read.
#ifdef NO_PNG_LUMPS
{
size_t bytesread = fread(dest, 1, size, handle);
ErrorIfPNG(dest, bytesread, wadfiles[wad]->filename, l->name2);
return bytesread;
}
#else
return fread(dest, 1, size, handle);
#endif
case CM_LZF: // Is it LZF compressed? Used by ZWADs.
{
#ifdef ZWAD
@ -1253,11 +1278,15 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
M_Memcpy(dest, decData + offset, size);
Z_Free(rawData);
Z_Free(decData);
#ifdef NO_PNG_LUMPS
ErrorIfPNG(dest, size, wadfiles[wad]->filename, l->name2);
#endif
return size;
#else
//I_Error("ZWAD files not supported on this platform.");
return 0;
#endif
}
#ifdef HAVE_ZLIB
case CM_DEFLATE: // Is it compressed via DEFLATE? Very common in ZIPs/PK3s, also what most doom-related editors support.
@ -1311,6 +1340,9 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
Z_Free(rawData);
Z_Free(decData);
#ifdef NO_PNG_LUMPS
ErrorIfPNG(dest, size, wadfiles[wad]->filename, l->name2);
#endif
return size;
}
#endif

View File

@ -24,8 +24,10 @@ ifndef NOASM
USEASM=1
endif
ifndef NONET
ifndef MINGW64 #miniupnc is broken with MINGW64
HAVE_MINIUPNPC=1
endif
endif
OPTS=-DSTDC_HEADERS

View File

@ -815,6 +815,60 @@ void I_SetMusicVolume(UINT8 volume)
FMR_MUSIC(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0));
}
UINT32 I_GetSongLength(void)
{
UINT32 length;
if (I_SongType() == MU_MID)
return 0;
FMR_MUSIC(FMOD_Sound_GetLength(music_stream, &length, FMOD_TIMEUNIT_MS));
return length;
}
boolean I_SetSongLoopPoint(UINT32 looppoint)
{
(void)looppoint;
return false;
}
UINT32 I_GetSongLoopPoint(void)
{
return 0;
}
boolean I_SetSongPosition(UINT32 position)
{
FMOD_RESULT e;
if(I_SongType() == MU_MID)
// Dummy out; this works for some MIDI, but not others.
// SDL does not support this for any MIDI.
return false;
e = FMOD_Channel_SetPosition(music_channel, position, FMOD_TIMEUNIT_MS);
if (e == FMOD_OK)
return true;
else if (e == FMOD_ERR_UNSUPPORTED // Only music modules, numbnuts!
|| e == FMOD_ERR_INVALID_POSITION) // Out-of-bounds!
return false;
else // Congrats, you horribly broke it somehow
{
FMR_MUSIC(e);
return false;
}
}
UINT32 I_GetSongPosition(void)
{
FMOD_RESULT e;
unsigned int fmposition = 0;
if(I_SongType() == MU_MID)
// Dummy out because unsupported, even though FMOD does this correctly.
return 0;
e = FMOD_Channel_GetPosition(music_channel, &fmposition, FMOD_TIMEUNIT_MS);
if (e == FMOD_OK)
return (UINT32)fmposition;
else
return 0;
}
boolean I_SetSongTrack(INT32 track)
{
if (track != current_track) // If the track's already playing, then why bother?
@ -859,3 +913,46 @@ boolean I_SetSongTrack(INT32 track)
}
return false;
}
/// ------------------------
/// MUSIC FADING
/// ------------------------
void I_SetInternalMusicVolume(UINT8 volume)
{
(void)volume;
}
void I_StopFadingSong(void)
{
}
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void))
{
(void)target_volume;
(void)source_volume;
(void)ms;
(void)callback;
return false;
}
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void))
{
(void)target_volume;
(void)ms;
(void)callback;
return false;
}
boolean I_FadeOutStopSong(UINT32 ms)
{
(void)ms;
return false;
}
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
{
(void)ms;
(void)looping;
return false;
}

View File

@ -639,9 +639,6 @@ void I_Error(const char *error, ...)
if (!errorcount)
{
M_SaveConfig(NULL); // save game config, cvars..
#ifndef NONET
D_SaveBan(); // save the ban list
#endif
G_SaveGameData();
}

View File

@ -696,7 +696,19 @@ void Y_Ticker(void)
boolean anybonuses = false;
if (!intertic) // first time only
S_ChangeMusicInternal("lclear", false); // don't loop it
{
if (mapheaderinfo[gamemap-1]->musinterfadeout
#ifdef _WIN32
// can't fade midi due to win32 volume hack
&& S_MusicType() != MU_MID
#endif
)
S_FadeOutStopMusic(mapheaderinfo[gamemap-1]->musinterfadeout);
else if (mapheaderinfo[gamemap-1]->musintername[0] && S_MusicExists(mapheaderinfo[gamemap-1]->musintername, !midi_disabled, !digital_disabled))
S_ChangeMusicInternal(mapheaderinfo[gamemap-1]->musintername, false); // don't loop it
else
S_ChangeMusicInternal("lclear", false); // don't loop it
}
if (intertic < TICRATE) // one second pause before tally begins
return;
@ -757,7 +769,17 @@ void Y_Ticker(void)
if (!intertic) // first time only
{
S_ChangeMusicInternal("lclear", false); // don't loop it
if (mapheaderinfo[gamemap-1]->musinterfadeout
#ifdef _WIN32
// can't fade midi due to win32 volume hack
&& S_MusicType() != MU_MID
#endif
)
S_FadeOutStopMusic(mapheaderinfo[gamemap-1]->musinterfadeout);
else if (mapheaderinfo[gamemap-1]->musintername[0] && S_MusicExists(mapheaderinfo[gamemap-1]->musintername, !midi_disabled, !digital_disabled))
S_ChangeMusicInternal(mapheaderinfo[gamemap-1]->musintername, false); // don't loop it
else
S_ChangeMusicInternal("lclear", false); // don't loop it
tallydonetic = 0;
}