mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-24 13:11:33 +00:00
Merge branch 'master' into scripting
Conflicts: src/p_effect.cpp src/p_effect.h src/p_local.h src/p_map.cpp src/thingdef/thingdef_codeptr.cpp wadsrc/static/actors/actor.txt wadsrc/static/actors/shared/inventory.txt zdoom.vcproj
This commit is contained in:
commit
2e0f999fea
108 changed files with 5421 additions and 1028 deletions
|
@ -106,6 +106,9 @@ endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
|
|||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}")
|
||||
|
||||
option( NO_FMOD "Disable FMODEx sound support" OFF )
|
||||
option( NO_OPENAL "Disable OpenAL sound support" OFF )
|
||||
|
||||
find_package( BZip2 )
|
||||
find_package( JPEG )
|
||||
find_package( ZLIB )
|
||||
|
|
28
FindMPG123.cmake
Normal file
28
FindMPG123.cmake
Normal file
|
@ -0,0 +1,28 @@
|
|||
# - Find mpg123
|
||||
# Find the native mpg123 includes and library
|
||||
#
|
||||
# MPG123_INCLUDE_DIR - where to find mpg123.h
|
||||
# MPG123_LIBRARIES - List of libraries when using mpg123.
|
||||
# MPG123_FOUND - True if mpg123 found.
|
||||
|
||||
IF(MPG123_INCLUDE_DIR AND MPG123_LIBRARIES)
|
||||
# Already in cache, be silent
|
||||
SET(MPG123_FIND_QUIETLY TRUE)
|
||||
ENDIF(MPG123_INCLUDE_DIR AND MPG123_LIBRARIES)
|
||||
|
||||
FIND_PATH(MPG123_INCLUDE_DIR mpg123.h
|
||||
PATHS "${MPG123_DIR}"
|
||||
PATH_SUFFIXES include
|
||||
)
|
||||
|
||||
FIND_LIBRARY(MPG123_LIBRARIES NAMES mpg123 mpg123-0
|
||||
PATHS "${MPG123_DIR}"
|
||||
PATH_SUFFIXES lib
|
||||
)
|
||||
|
||||
# MARK_AS_ADVANCED(MPG123_LIBRARIES MPG123_INCLUDE_DIR)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set MPG123_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MPG123 DEFAULT_MSG MPG123_LIBRARIES MPG123_INCLUDE_DIR)
|
29
FindSndFile.cmake
Normal file
29
FindSndFile.cmake
Normal file
|
@ -0,0 +1,29 @@
|
|||
# - Try to find SndFile
|
||||
# Once done this will define
|
||||
#
|
||||
# SNDFILE_FOUND - system has SndFile
|
||||
# SNDFILE_INCLUDE_DIRS - the SndFile include directory
|
||||
# SNDFILE_LIBRARIES - Link these to use SndFile
|
||||
#
|
||||
# Copyright © 2006 Wengo
|
||||
# Copyright © 2009 Guillaume Martres
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
find_path(SNDFILE_INCLUDE_DIR NAMES sndfile.h)
|
||||
|
||||
find_library(SNDFILE_LIBRARY NAMES sndfile sndfile-1)
|
||||
|
||||
set(SNDFILE_INCLUDE_DIRS ${SNDFILE_INCLUDE_DIR})
|
||||
set(SNDFILE_LIBRARIES ${SNDFILE_LIBRARY})
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set SNDFILE_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SndFile DEFAULT_MSG SNDFILE_LIBRARY SNDFILE_INCLUDE_DIR)
|
||||
|
||||
# show the SNDFILE_INCLUDE_DIRS and SNDFILE_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(SNDFILE_INCLUDE_DIRS SNDFILE_LIBRARIES)
|
|
@ -1,9 +1,11 @@
|
|||
cmake_minimum_required( VERSION 2.4 )
|
||||
add_library( output_sdl MODULE output_sdl.c )
|
||||
include_directories( ${FMOD_INCLUDE_DIR} ${SDL2_INCLUDE_DIR} )
|
||||
target_link_libraries( output_sdl ${SDL2_LIBRARY} )
|
||||
if( NOT NO_FMOD AND FMOD_INCLUDE_DIR )
|
||||
add_library( output_sdl MODULE output_sdl.c )
|
||||
include_directories( ${FMOD_INCLUDE_DIR} ${SDL2_INCLUDE_DIR} )
|
||||
target_link_libraries( output_sdl ${SDL2_LIBRARY} )
|
||||
|
||||
FILE( WRITE ${CMAKE_CURRENT_BINARY_DIR}/link-make "if [ ! -e ${ZDOOM_OUTPUT_DIR}/liboutput_sdl.so ]; then ln -sf output_sdl/liboutput_sdl.so ${ZDOOM_OUTPUT_DIR}/liboutput_sdl.so; fi" )
|
||||
add_custom_command( TARGET output_sdl POST_BUILD
|
||||
COMMAND chmod +x ${CMAKE_CURRENT_BINARY_DIR}/link-make
|
||||
COMMAND /bin/sh -c ${CMAKE_CURRENT_BINARY_DIR}/link-make )
|
||||
FILE( WRITE ${CMAKE_CURRENT_BINARY_DIR}/link-make "if [ ! -e ${ZDOOM_OUTPUT_DIR}/liboutput_sdl.so ]; then ln -sf output_sdl/liboutput_sdl.so ${ZDOOM_OUTPUT_DIR}/liboutput_sdl.so; fi" )
|
||||
add_custom_command( TARGET output_sdl POST_BUILD
|
||||
COMMAND chmod +x ${CMAKE_CURRENT_BINARY_DIR}/link-make
|
||||
COMMAND /bin/sh -c ${CMAKE_CURRENT_BINARY_DIR}/link-make )
|
||||
endif( NOT NO_FMOD AND FMOD_INCLUDE_DIR )
|
||||
|
|
|
@ -119,6 +119,7 @@ Note: All <bool> fields default to false unless mentioned otherwise.
|
|||
blockhitscan = <bool>; // Line blocks hitscan attacks
|
||||
locknumber = <int>; // Line special is locked
|
||||
arg0str = <string>; // Alternate string-based version of arg0
|
||||
moreids = <string>; // Additional line IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505")
|
||||
|
||||
transparent = <bool>; // true = line is a Strife transparent line (alpha 0.25)
|
||||
|
||||
|
@ -201,6 +202,7 @@ Note: All <bool> fields default to false unless mentioned otherwise.
|
|||
// sound sequence thing in the sector will override this property.
|
||||
hidden = <bool>; // if true this sector will not be drawn on the textured automap.
|
||||
waterzone = <bool>; // Sector is under water and swimmable
|
||||
moreids = <string>; // Additional sector IDs/tags, specified as a space separated list of numbers (e.g. "2 666 1003 4505")
|
||||
|
||||
* Note about dropactors
|
||||
|
||||
|
@ -370,6 +372,9 @@ Added transparent line property (to be folded back to core UDMF standard), and h
|
|||
Added plane equations for sector slopes. (Please read carefully to ensure proper use!)
|
||||
Changed language describing the DIALOGUE lump to mention USDF as an option.
|
||||
|
||||
1.25 19.04.2015
|
||||
Added 'moreids' for linedefs and sectors.
|
||||
|
||||
===============================================================================
|
||||
EOF
|
||||
===============================================================================
|
||||
|
|
|
@ -212,59 +212,88 @@ else( WIN32 )
|
|||
endif( FPU_CONTROL_DIR )
|
||||
endif( WIN32 )
|
||||
|
||||
# Decide on the name of the FMOD library we want to use.
|
||||
|
||||
if( NOT FMOD_LIB_NAME AND MSVC )
|
||||
set( FMOD_LIB_NAME fmodex${X64}_vc )
|
||||
endif( NOT FMOD_LIB_NAME AND MSVC )
|
||||
if( NOT NO_OPENAL )
|
||||
find_package( OpenAL )
|
||||
mark_as_advanced(CLEAR OPENAL_LIBRARY OPENAL_INCLUDE_DIR)
|
||||
if( OPENAL_FOUND )
|
||||
include_directories( ${OPENAL_INCLUDE_DIR} )
|
||||
set( ZDOOM_LIBS ${OPENAL_LIBRARY} ${ZDOOM_LIBS} )
|
||||
else( OPENAL_FOUND )
|
||||
set( NO_OPENAL ON )
|
||||
endif( OPENAL_FOUND )
|
||||
endif( NOT NO_OPENAL )
|
||||
|
||||
if( NOT FMOD_LIB_NAME AND BORLAND )
|
||||
set( FMOD_LIB_NAME fmodex${X64}_bc )
|
||||
endif( NOT FMOD_LIB_NAME AND BORLAND )
|
||||
if( NOT NO_FMOD )
|
||||
# Search for FMOD include files
|
||||
if( NOT WIN32 )
|
||||
find_path( FMOD_INCLUDE_DIR fmod.hpp
|
||||
PATHS ${FMOD_LOCAL_INC_DIRS} )
|
||||
endif( NOT WIN32 )
|
||||
|
||||
if( NOT FMOD_LIB_NAME )
|
||||
set( FMOD_LIB_NAME fmodex${X64} )
|
||||
endif( NOT FMOD_LIB_NAME )
|
||||
if( NOT FMOD_INCLUDE_DIR )
|
||||
find_path( FMOD_INCLUDE_DIR fmod.hpp
|
||||
PATHS ${FMOD_SEARCH_PATHS}
|
||||
${FMOD_INC_PATH_SUFFIXES} )
|
||||
endif( NOT FMOD_INCLUDE_DIR )
|
||||
|
||||
if( FMOD_INCLUDE_DIR )
|
||||
message( STATUS "FMOD include files found at ${FMOD_INCLUDE_DIR}" )
|
||||
include_directories( "${FMOD_INCLUDE_DIR}" )
|
||||
else( FMOD_INCLUDE_DIR )
|
||||
message( STATUS "Could not find FMOD include files" )
|
||||
set( NO_FMOD ON )
|
||||
endif( FMOD_INCLUDE_DIR )
|
||||
endif( NOT NO_FMOD )
|
||||
|
||||
# Search for FMOD include files
|
||||
if( NOT NO_FMOD )
|
||||
# Decide on the name of the FMOD library we want to use.
|
||||
if( NOT FMOD_LIB_NAME AND MSVC )
|
||||
set( FMOD_LIB_NAME fmodex${X64}_vc )
|
||||
endif( NOT FMOD_LIB_NAME AND MSVC )
|
||||
|
||||
if( NOT WIN32 )
|
||||
find_path( FMOD_INCLUDE_DIR fmod.hpp
|
||||
PATHS ${FMOD_LOCAL_INC_DIRS} )
|
||||
endif( NOT WIN32 )
|
||||
if( NOT FMOD_LIB_NAME AND BORLAND )
|
||||
set( FMOD_LIB_NAME fmodex${X64}_bc )
|
||||
endif( NOT FMOD_LIB_NAME AND BORLAND )
|
||||
|
||||
if( NOT FMOD_INCLUDE_DIR )
|
||||
find_path( FMOD_INCLUDE_DIR fmod.hpp
|
||||
PATHS ${FMOD_SEARCH_PATHS}
|
||||
${FMOD_INC_PATH_SUFFIXES} )
|
||||
endif( NOT FMOD_INCLUDE_DIR )
|
||||
if( NOT FMOD_LIB_NAME )
|
||||
set( FMOD_LIB_NAME fmodex${X64} )
|
||||
endif( NOT FMOD_LIB_NAME )
|
||||
|
||||
if( FMOD_INCLUDE_DIR )
|
||||
message( STATUS "FMOD include files found at ${FMOD_INCLUDE_DIR}" )
|
||||
else( FMOD_INCLUDE_DIR )
|
||||
message( SEND_ERROR "Could not find FMOD include files" )
|
||||
endif( FMOD_INCLUDE_DIR )
|
||||
# Search for FMOD library
|
||||
if( WIN32 OR APPLE )
|
||||
find_library( FMOD_LIBRARY ${FMOD_LIB_NAME}
|
||||
PATHS ${FMOD_SEARCH_PATHS}
|
||||
${FMOD_LIB_PATH_SUFFIXES} )
|
||||
else( WIN32 OR APPLE )
|
||||
find_library( FMOD_LIBRARY
|
||||
NAMES ${FMOD_VERSIONS}
|
||||
PATHS ${FMOD_LOCAL_LIB_DIRS} )
|
||||
endif( WIN32 OR APPLE )
|
||||
|
||||
if( FMOD_LIBRARY )
|
||||
message( STATUS "FMOD library found at ${FMOD_LIBRARY}" )
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FMOD_LIBRARY}" )
|
||||
else( FMOD_LIBRARY )
|
||||
message( STATUS "Could not find FMOD library" )
|
||||
set( NO_FMOD ON )
|
||||
endif( FMOD_LIBRARY )
|
||||
endif( NOT NO_FMOD )
|
||||
|
||||
# Search for FMOD library
|
||||
if( NO_FMOD )
|
||||
add_definitions( -DNO_FMOD=1 )
|
||||
endif( NO_FMOD )
|
||||
if( NO_OPENAL )
|
||||
add_definitions( -DNO_OPENAL=1 )
|
||||
endif( NO_OPENAL )
|
||||
|
||||
if( WIN32 OR APPLE )
|
||||
find_library( FMOD_LIBRARY ${FMOD_LIB_NAME}
|
||||
PATHS ${FMOD_SEARCH_PATHS}
|
||||
${FMOD_LIB_PATH_SUFFIXES} )
|
||||
else( WIN32 OR APPLE )
|
||||
find_library( FMOD_LIBRARY
|
||||
NAMES ${FMOD_VERSIONS}
|
||||
PATHS ${FMOD_LOCAL_LIB_DIRS} )
|
||||
endif( WIN32 OR APPLE )
|
||||
# Search for libSndFile
|
||||
|
||||
if( FMOD_LIBRARY )
|
||||
message( STATUS "FMOD library found at ${FMOD_LIBRARY}" )
|
||||
else( FMOD_LIBRARY )
|
||||
message( SEND_ERROR "Could not find FMOD library" )
|
||||
endif( FMOD_LIBRARY )
|
||||
find_package( SndFile )
|
||||
|
||||
# Search for libmpg123
|
||||
|
||||
find_package( MPG123 )
|
||||
|
||||
# Search for FluidSynth
|
||||
|
||||
|
@ -512,9 +541,17 @@ add_custom_target( revision_check ALL
|
|||
# Libraries ZDoom needs
|
||||
|
||||
message( STATUS "Fluid synth libs: ${FLUIDSYNTH_LIBRARIES}" )
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${GME_LIBRARIES}" "${FMOD_LIBRARY}" )
|
||||
include_directories( "${ZLIB_INCLUDE_DIR}" "${FMOD_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GME_INCLUDE_DIR}" )
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${GME_LIBRARIES}" )
|
||||
include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GME_INCLUDE_DIR}" )
|
||||
|
||||
if( SNDFILE_FOUND )
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${SNDFILE_LIBRARIES}" )
|
||||
include_directories( "${SNDFILE_INCLUDE_DIRS}" )
|
||||
endif( SNDFILE_FOUND )
|
||||
if( MPG123_FOUND )
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${MPG123_LIBRARIES}" )
|
||||
include_directories( "${MPG123_INCLUDE_DIR}" )
|
||||
endif( MPG123_FOUND )
|
||||
if( NOT DYN_FLUIDSYNTH)
|
||||
if( FLUIDSYNTH_FOUND )
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FLUIDSYNTH_LIBRARIES}" )
|
||||
|
@ -655,6 +692,12 @@ else( SSE_MATTERS )
|
|||
set( X86_SOURCES )
|
||||
endif( SSE_MATTERS )
|
||||
|
||||
if( SNDFILE_FOUND )
|
||||
add_definitions( -DHAVE_SNDFILE )
|
||||
endif( SNDFILE_FOUND )
|
||||
if( MPG123_FOUND )
|
||||
add_definitions( -DHAVE_MPG123 )
|
||||
endif( MPG123_FOUND )
|
||||
if( DYN_FLUIDSYNTH )
|
||||
add_definitions( -DHAVE_FLUIDSYNTH -DDYN_FLUIDSYNTH )
|
||||
elseif( FLUIDSYNTH_FOUND )
|
||||
|
@ -905,6 +948,7 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
|
|||
p_spec.cpp
|
||||
p_states.cpp
|
||||
p_switch.cpp
|
||||
p_tags.cpp
|
||||
p_teleport.cpp
|
||||
p_terrain.cpp
|
||||
p_things.cpp
|
||||
|
@ -1035,6 +1079,7 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
|
|||
sound/fmodsound.cpp
|
||||
sound/i_music.cpp
|
||||
sound/i_sound.cpp
|
||||
sound/mpg123_decoder.cpp
|
||||
sound/music_cd.cpp
|
||||
sound/music_dumb.cpp
|
||||
sound/music_gme.cpp
|
||||
|
@ -1051,6 +1096,8 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
|
|||
sound/music_softsynth_mididevice.cpp
|
||||
sound/music_timidity_mididevice.cpp
|
||||
sound/music_win_mididevice.cpp
|
||||
sound/oalsound.cpp
|
||||
sound/sndfile_decoder.cpp
|
||||
sound/music_pseudo_mididevice.cpp
|
||||
textures/animations.cpp
|
||||
textures/anim_switches.cpp
|
||||
|
@ -1171,9 +1218,9 @@ endif( NOT ZDOOM_OUTPUT_OLDSTYLE OR NO_GENERATOR_EXPRESSIONS )
|
|||
if( MSVC )
|
||||
option( ZDOOM_GENERATE_MAPFILE "Generate .map file for debugging." OFF )
|
||||
if( ZDOOM_GENERATE_MAPFILE )
|
||||
set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /MAP")
|
||||
set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /DELAYLOAD:\"openal32.dll\" /DELAYLOAD:\"libmpg123-0.dll\" /DELAYLOAD:\"libsndfile-1.dll\" /MAP")
|
||||
else( ZDOOM_GENERATE_MAPFILE )
|
||||
set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\"")
|
||||
set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /DELAYLOAD:\"openal32.dll\" /DELAYLOAD:\"libmpg123-0.dll\" /DELAYLOAD:\"libsndfile-1.dll\"")
|
||||
endif( ZDOOM_GENERATE_MAPFILE )
|
||||
|
||||
add_custom_command(TARGET zdoom POST_BUILD
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "gi.h"
|
||||
#include "g_level.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "p_tags.h"
|
||||
#include "r_state.h"
|
||||
#include "w_wad.h"
|
||||
|
||||
|
@ -551,8 +552,8 @@ void SetCompatibilityParams()
|
|||
{
|
||||
if ((unsigned)CompatParams[i + 1] < (unsigned)numsectors)
|
||||
{
|
||||
sectors[CompatParams[i + 1]].ClearTags();
|
||||
sectors[CompatParams[i + 1]].SetMainTag(CompatParams[i + 2]);
|
||||
// this assumes that the sector does not have any tags yet!
|
||||
tagManager.AddSectorTag(CompatParams[i + 1], CompatParams[i + 2]);
|
||||
}
|
||||
i += 3;
|
||||
break;
|
||||
|
|
|
@ -905,6 +905,7 @@ void D_Display ()
|
|||
} while (diff < 1);
|
||||
wipestart = nowtime;
|
||||
done = screen->WipeDo (1);
|
||||
S_UpdateMusic(); // OpenAL needs this to keep the music running, thanks to a complete lack of a sane streaming implementation using callbacks. :(
|
||||
C_DrawConsole (hw2d); // console and
|
||||
M_Drawer (); // menu are drawn even on top of wipes
|
||||
screen->Update (); // page flip or blit buffer
|
||||
|
@ -1003,6 +1004,7 @@ void D_DoomLoop ()
|
|||
// Update display, next frame, with current state.
|
||||
I_StartTic ();
|
||||
D_Display ();
|
||||
S_UpdateMusic(); // OpenAL needs this to keep the music running, thanks to a complete lack of a sane streaming implementation using callbacks. :(
|
||||
}
|
||||
catch (CRecoverableError &error)
|
||||
{
|
||||
|
@ -1999,6 +2001,9 @@ static void D_DoomInit()
|
|||
}
|
||||
|
||||
FRandom::StaticClearRandom ();
|
||||
|
||||
Printf ("M_LoadDefaults: Load system defaults.\n");
|
||||
M_LoadDefaults (); // load before initing other systems
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -2007,7 +2012,7 @@ static void D_DoomInit()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static void AddAutoloadFiles(const char *autoname)
|
||||
static void AddAutoloadFiles(const char *autoname)
|
||||
{
|
||||
LumpFilterIWAD.Format("%s.", autoname); // The '.' is appened to simplify parsing the string
|
||||
|
||||
|
@ -2249,8 +2254,8 @@ void D_DoomMain (void)
|
|||
iwad_man = new FIWadManager;
|
||||
iwad_man->ParseIWadInfos(basewad);
|
||||
|
||||
Printf ("M_LoadDefaults: Load system defaults.\n");
|
||||
M_LoadDefaults (iwad_man); // load before initing other systems
|
||||
// Now that we have the IWADINFO, initialize the autoload ini sections.
|
||||
GameConfig->DoAutoloadSetup(iwad_man);
|
||||
|
||||
// reinit from here
|
||||
|
||||
|
@ -2291,7 +2296,7 @@ void D_DoomMain (void)
|
|||
FBaseCVar::DisableCallbacks();
|
||||
GameConfig->DoGameSetup (gameinfo.ConfigName);
|
||||
|
||||
AddAutoloadFiles(iwad_info->Autoname);
|
||||
AddAutoloadFiles(iwad_info->Autoname);
|
||||
|
||||
// Process automatically executed files
|
||||
FExecList *exec;
|
||||
|
|
|
@ -544,3 +544,59 @@ char *MemoryReader::Gets(char *strbuf, int len)
|
|||
{
|
||||
return GetsFromBuffer(bufptr, strbuf, len);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MemoryArrayReader
|
||||
//
|
||||
// reads data from an array of memory
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
MemoryArrayReader::MemoryArrayReader (const char *buffer, long length)
|
||||
{
|
||||
buf.Resize(length);
|
||||
memcpy(&buf[0], buffer, length);
|
||||
Length=length;
|
||||
FilePos=0;
|
||||
}
|
||||
|
||||
MemoryArrayReader::~MemoryArrayReader ()
|
||||
{
|
||||
}
|
||||
|
||||
long MemoryArrayReader::Tell () const
|
||||
{
|
||||
return FilePos;
|
||||
}
|
||||
|
||||
long MemoryArrayReader::Seek (long offset, int origin)
|
||||
{
|
||||
switch (origin)
|
||||
{
|
||||
case SEEK_CUR:
|
||||
offset+=FilePos;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
offset+=Length;
|
||||
break;
|
||||
|
||||
}
|
||||
FilePos=clamp<long>(offset,0,Length-1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
long MemoryArrayReader::Read (void *buffer, long len)
|
||||
{
|
||||
if (len>Length-FilePos) len=Length-FilePos;
|
||||
if (len<0) len=0;
|
||||
memcpy(buffer,&buf[FilePos],len);
|
||||
FilePos+=len;
|
||||
return len;
|
||||
}
|
||||
|
||||
char *MemoryArrayReader::Gets(char *strbuf, int len)
|
||||
{
|
||||
return GetsFromBuffer((char*)&buf[0], strbuf, len);
|
||||
}
|
||||
|
|
18
src/files.h
18
src/files.h
|
@ -336,6 +336,24 @@ protected:
|
|||
const char * bufptr;
|
||||
};
|
||||
|
||||
class MemoryArrayReader : public FileReader
|
||||
{
|
||||
public:
|
||||
MemoryArrayReader (const char *buffer, long length);
|
||||
~MemoryArrayReader ();
|
||||
|
||||
virtual long Tell () const;
|
||||
virtual long Seek (long offset, int origin);
|
||||
virtual long Read (void *buffer, long len);
|
||||
virtual char *Gets(char *strbuf, int len);
|
||||
virtual const char *GetBuffer() const { return (char*)&buf[0]; }
|
||||
TArray<BYTE> &GetArray() { return buf; }
|
||||
|
||||
void UpdateLength() { Length = buf.Size(); }
|
||||
|
||||
protected:
|
||||
TArray<BYTE> buf;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -169,6 +169,7 @@ void FS_EmulateCmd(char * string)
|
|||
{
|
||||
// No, this is not correct. But this is the way Legacy WADs expect it to be handled!
|
||||
if (players[i].mo != NULL) players[i].mo->ViewHeight = playerviewheight;
|
||||
players[i].viewheight = playerviewheight;
|
||||
players[i].Uncrouch();
|
||||
}
|
||||
while (sc.GetString())
|
||||
|
|
|
@ -1165,7 +1165,7 @@ void FParser::SF_ObjSector(void)
|
|||
}
|
||||
|
||||
t_return.type = svt_int;
|
||||
t_return.value.i = mo ? mo->Sector->GetMainTag() : 0; // nullptr check
|
||||
t_return.value.i = mo ? tagManager.GetFirstSectorTag(mo->Sector) : 0; // nullptr check
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -2235,7 +2235,7 @@ void FParser::SF_LineTrigger()
|
|||
maplinedef_t mld;
|
||||
mld.special=intvalue(t_argv[0]);
|
||||
mld.tag=t_argc > 1 ? intvalue(t_argv[1]) : 0;
|
||||
P_TranslateLineDef(&line, &mld, false);
|
||||
P_TranslateLineDef(&line, &mld);
|
||||
P_ExecuteSpecial(line.special, NULL, Script->trigger, false,
|
||||
line.args[0],line.args[1],line.args[2],line.args[3],line.args[4]);
|
||||
}
|
||||
|
@ -4312,7 +4312,7 @@ void FParser::SF_KillInSector()
|
|||
|
||||
while ((mo=it.Next()))
|
||||
{
|
||||
if (mo->flags3&MF3_ISMONSTER && mo->Sector->HasTag(tag)) P_DamageMobj(mo, NULL, NULL, 1000000, NAME_Massacre);
|
||||
if (mo->flags3&MF3_ISMONSTER && tagManager.SectorHasTag(mo->Sector, tag)) P_DamageMobj(mo, NULL, NULL, 1000000, NAME_Massacre);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4385,7 +4385,7 @@ void FParser::SF_SetLineTrigger()
|
|||
mld.tag = tag;
|
||||
mld.flags = 0;
|
||||
int f = lines[i].flags;
|
||||
P_TranslateLineDef(&lines[i], &mld, false);
|
||||
P_TranslateLineDef(&lines[i], &mld);
|
||||
lines[i].flags = (lines[i].flags & (ML_MONSTERSCANACTIVATE | ML_REPEAT_SPECIAL | ML_SPAC_MASK | ML_FIRSTSIDEONLY)) |
|
||||
(f & ~(ML_MONSTERSCANACTIVATE | ML_REPEAT_SPECIAL | ML_SPAC_MASK | ML_FIRSTSIDEONLY));
|
||||
|
||||
|
|
|
@ -213,13 +213,12 @@ void FMapInfoParser::ParseDoomEdNums()
|
|||
DoomEdFromMapinfo.Insert(ednum, editem);
|
||||
continue;
|
||||
}
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetNumber();
|
||||
}
|
||||
int i = 0;
|
||||
while (i < 5)
|
||||
{
|
||||
editem.args[i++] = sc.Number;
|
||||
editem.args[i] = sc.Number;
|
||||
i++;
|
||||
if (!sc.CheckString(",")) break;
|
||||
sc.MustGetNumber();
|
||||
|
|
|
@ -1229,6 +1229,7 @@ void G_FinishTravel ()
|
|||
pawn->lastenemy = NULL;
|
||||
pawn->player->mo = pawn;
|
||||
pawn->player->camera = pawn;
|
||||
pawn->player->viewheight = pawn->ViewHeight;
|
||||
pawn->flags2 &= ~MF2_BLASTED;
|
||||
DObject::StaticPointerSubstitution (oldpawn, pawn);
|
||||
oldpawn->Destroy();
|
||||
|
|
|
@ -639,7 +639,7 @@ bool AInventory::HandlePickup (AInventory *item)
|
|||
{
|
||||
if (item->GetClass() == GetClass())
|
||||
{
|
||||
if (Amount < MaxAmount || sv_unlimited_pickup)
|
||||
if (Amount < MaxAmount || (sv_unlimited_pickup && !item->ShouldStay()))
|
||||
{
|
||||
if (Amount > 0 && Amount + item->Amount < 0)
|
||||
{
|
||||
|
|
|
@ -665,7 +665,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CheckTerrain)
|
|||
}
|
||||
else if ((sec->special & 0xFF) == Scroll_StrifeCurrent)
|
||||
{
|
||||
int anglespeed = sec->GetMainTag() - 100;
|
||||
int anglespeed = tagManager.GetFirstSectorTag(sec) - 100;
|
||||
fixed_t speed = (anglespeed % 10) << (FRACBITS - 4);
|
||||
angle_t finean = (anglespeed / 10) << (32-3);
|
||||
finean >>= ANGLETOFINESHIFT;
|
||||
|
|
|
@ -76,7 +76,7 @@ EXTERN_CVAR (Color, am_cdwallcolor)
|
|||
EXTERN_CVAR (Float, spc_amp)
|
||||
EXTERN_CVAR (Bool, wi_percents)
|
||||
|
||||
FGameConfigFile::FGameConfigFile (FIWadManager *iwad_man)
|
||||
FGameConfigFile::FGameConfigFile ()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
FString user_docs, user_app_support, local_app_support;
|
||||
|
@ -161,6 +161,27 @@ FGameConfigFile::FGameConfigFile (FIWadManager *iwad_man)
|
|||
SetValueForKey ("Path", "$DOOMWADDIR", true);
|
||||
}
|
||||
|
||||
// Add some self-documentation.
|
||||
SetSectionNote("IWADSearch.Directories",
|
||||
"# These are the directories to automatically search for IWADs.\n"
|
||||
"# Each directory should be on a separate line, preceded by Path=\n");
|
||||
SetSectionNote("FileSearch.Directories",
|
||||
"# These are the directories to search for wads added with the -file\n"
|
||||
"# command line parameter, if they cannot be found with the path\n"
|
||||
"# as-is. Layout is the same as for IWADSearch.Directories\n");
|
||||
}
|
||||
|
||||
FGameConfigFile::~FGameConfigFile ()
|
||||
{
|
||||
}
|
||||
|
||||
void FGameConfigFile::WriteCommentHeader (FILE *file) const
|
||||
{
|
||||
fprintf (file, "# This file was generated by " GAMENAME " %s on %s\n", GetVersionString(), myasctime());
|
||||
}
|
||||
|
||||
void FGameConfigFile::DoAutoloadSetup (FIWadManager *iwad_man)
|
||||
{
|
||||
// Create auto-load sections, so users know what's available.
|
||||
// Note that this totem pole is the reverse of the order that
|
||||
// they will appear in the file.
|
||||
|
@ -220,14 +241,6 @@ FGameConfigFile::FGameConfigFile (FIWadManager *iwad_man)
|
|||
MoveSectionToStart("FileSearch.Directories");
|
||||
MoveSectionToStart("IWADSearch.Directories");
|
||||
|
||||
// Add some self-documentation.
|
||||
SetSectionNote("IWADSearch.Directories",
|
||||
"# These are the directories to automatically search for IWADs.\n"
|
||||
"# Each directory should be on a separate line, preceded by Path=\n");
|
||||
SetSectionNote("FileSearch.Directories",
|
||||
"# These are the directories to search for wads added with the -file\n"
|
||||
"# command line parameter, if they cannot be found with the path\n"
|
||||
"# as-is. Layout is the same as for IWADSearch.Directories\n");
|
||||
SetSectionNote("Doom.AutoExec",
|
||||
"# Files to automatically execute when running the corresponding game.\n"
|
||||
"# Each file should be on its own line, preceded by Path=\n\n");
|
||||
|
@ -245,15 +258,6 @@ FGameConfigFile::FGameConfigFile (FIWadManager *iwad_man)
|
|||
"# 'doom.doom2.commercial.Autoload' only when playing doom2.wad.\n\n");
|
||||
}
|
||||
|
||||
FGameConfigFile::~FGameConfigFile ()
|
||||
{
|
||||
}
|
||||
|
||||
void FGameConfigFile::WriteCommentHeader (FILE *file) const
|
||||
{
|
||||
fprintf (file, "# This file was generated by " GAMENAME " %s on %s\n", GetVersionString(), myasctime());
|
||||
}
|
||||
|
||||
void FGameConfigFile::DoGlobalSetup ()
|
||||
{
|
||||
if (SetSection ("GlobalSettings.Unknown"))
|
||||
|
|
|
@ -43,9 +43,10 @@ class FIWadManager;
|
|||
class FGameConfigFile : public FConfigFile
|
||||
{
|
||||
public:
|
||||
FGameConfigFile (FIWadManager *iwad_man);
|
||||
FGameConfigFile ();
|
||||
~FGameConfigFile ();
|
||||
|
||||
void DoAutoloadSetup (FIWadManager *iwad_man);
|
||||
void DoGlobalSetup ();
|
||||
void DoGameSetup (const char *gamename);
|
||||
void DoKeySetup (const char *gamename);
|
||||
|
|
|
@ -319,7 +319,11 @@ void PacketGet (void)
|
|||
}
|
||||
else if (c > 0)
|
||||
{ //The packet is not from any in-game node, so we might as well discard it.
|
||||
Printf("Dropped packet: Unknown host (%s:%d)\n", inet_ntoa(fromaddress.sin_addr), fromaddress.sin_port);
|
||||
// Don't show the message for disconnect notifications.
|
||||
if (c != 2 || TransmitBuffer[0] != PRE_FAKE || TransmitBuffer[1] != PRE_DISCONNECT)
|
||||
{
|
||||
DPrintf("Dropped packet: Unknown host (%s:%d)\n", inet_ntoa(fromaddress.sin_addr), fromaddress.sin_port);
|
||||
}
|
||||
doomcom.remotenode = -1;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -358,7 +358,7 @@ void PClassActor::RegisterIDs()
|
|||
if (ConversationID > 0)
|
||||
{
|
||||
StrifeTypes[ConversationID] = cls;
|
||||
if (cls != Class)
|
||||
if (cls != this)
|
||||
{
|
||||
Printf(TEXTCOLOR_RED"Conversation ID %d refers to hidden class type '%s'\n", SpawnID, cls->TypeName.GetChars());
|
||||
}
|
||||
|
|
|
@ -410,9 +410,9 @@ CCMD (writeini)
|
|||
// M_LoadDefaults
|
||||
//
|
||||
|
||||
void M_LoadDefaults (FIWadManager *iwad_man)
|
||||
void M_LoadDefaults ()
|
||||
{
|
||||
GameConfig = new FGameConfigFile(iwad_man);
|
||||
GameConfig = new FGameConfigFile;
|
||||
GameConfig->DoGlobalSetup ();
|
||||
atterm (M_SaveDefaultsFinal);
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ void M_FindResponseFile (void);
|
|||
// Pass a NULL to get the original behavior.
|
||||
void M_ScreenShot (const char *filename);
|
||||
|
||||
void M_LoadDefaults (FIWadManager *iwad_man);
|
||||
void M_LoadDefaults ();
|
||||
|
||||
bool M_SaveDefaults (const char *filename);
|
||||
void M_SaveCustomKeys (FConfigFile *config, char *section, char *subsection, size_t sublen);
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include "i_system.h"
|
||||
|
||||
typedef HRESULT (WINAPI *GKFP)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR *);
|
||||
|
||||
//===========================================================================
|
||||
|
@ -73,18 +75,7 @@ bool UseKnownFolders()
|
|||
|
||||
bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create, FString &path)
|
||||
{
|
||||
static GKFP SHGetKnownFolderPath = NULL;
|
||||
static bool tested = false;
|
||||
|
||||
if (!tested)
|
||||
{
|
||||
tested = true;
|
||||
HMODULE shell32 = GetModuleHandle("shell32.dll");
|
||||
if (shell32 != NULL)
|
||||
{
|
||||
SHGetKnownFolderPath = (GKFP)GetProcAddress(shell32, "SHGetKnownFolderPath");
|
||||
}
|
||||
}
|
||||
static TOptWin32Proc<GKFP> SHGetKnownFolderPath("shell32.dll", "SHGetKnownFolderPath");
|
||||
|
||||
char pathstr[MAX_PATH];
|
||||
|
||||
|
@ -92,6 +83,13 @@ bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create
|
|||
// new to Vista, hence the reason we support both.
|
||||
if (SHGetKnownFolderPath == NULL)
|
||||
{
|
||||
static TOptWin32Proc<HRESULT(*)(HWND, int, HANDLE, DWORD, LPTSTR)>
|
||||
SHGetFolderPathA("shell32.dll", "SHGetFolderPathA");
|
||||
|
||||
// NT4 doesn't even have this function.
|
||||
if (SHGetFolderPathA == NULL)
|
||||
return false;
|
||||
|
||||
if (shell_folder < 0)
|
||||
{ // Not supported by SHGetFolderPath
|
||||
return false;
|
||||
|
@ -100,7 +98,7 @@ bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create
|
|||
{
|
||||
shell_folder |= CSIDL_FLAG_CREATE;
|
||||
}
|
||||
if (FAILED(SHGetFolderPathA(NULL, shell_folder, NULL, 0, pathstr)))
|
||||
if (FAILED(SHGetFolderPathA.Call(NULL, shell_folder, NULL, 0, pathstr)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -110,7 +108,7 @@ bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create
|
|||
else
|
||||
{
|
||||
PWSTR wpath;
|
||||
if (FAILED(SHGetKnownFolderPath(known_folder, create ? KF_FLAG_CREATE : 0, NULL, &wpath)))
|
||||
if (FAILED(SHGetKnownFolderPath.Call(known_folder, create ? KF_FLAG_CREATE : 0, NULL, &wpath)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "i_music.h"
|
||||
#include "m_joy.h"
|
||||
#include "gi.h"
|
||||
#include "i_sound.h"
|
||||
|
||||
#include "optionmenuitems.h"
|
||||
|
||||
|
@ -60,6 +61,8 @@ static FOptionMenuDescriptor DefaultOptionMenuSettings; // contains common setti
|
|||
FOptionMenuSettings OptionSettings;
|
||||
FOptionMap OptionValues;
|
||||
|
||||
void I_BuildALDeviceList(FOptionValues *opt);
|
||||
|
||||
static void DeinitMenus()
|
||||
{
|
||||
{
|
||||
|
@ -168,6 +171,14 @@ static bool CheckSkipOptionBlock(FScanner &sc)
|
|||
filter = true;
|
||||
#endif
|
||||
}
|
||||
else if (sc.Compare("OpenAL"))
|
||||
{
|
||||
filter |= IsOpenALPresent();
|
||||
}
|
||||
else if (sc.Compare("FModEx"))
|
||||
{
|
||||
filter |= IsFModExPresent();
|
||||
}
|
||||
}
|
||||
while (sc.CheckString(","));
|
||||
sc.MustGetStringName(")");
|
||||
|
@ -589,7 +600,11 @@ static void ParseOptionSettings(FScanner &sc)
|
|||
while (!sc.CheckString("}"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("ifgame"))
|
||||
if (sc.Compare("else"))
|
||||
{
|
||||
SkipSubBlock(sc);
|
||||
}
|
||||
else if (sc.Compare("ifgame"))
|
||||
{
|
||||
if (!CheckSkipGameBlock(sc))
|
||||
{
|
||||
|
@ -626,7 +641,11 @@ static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc)
|
|||
while (!sc.CheckString("}"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("ifgame"))
|
||||
if (sc.Compare("else"))
|
||||
{
|
||||
SkipSubBlock(sc);
|
||||
}
|
||||
else if (sc.Compare("ifgame"))
|
||||
{
|
||||
if (!CheckSkipGameBlock(sc))
|
||||
{
|
||||
|
@ -1262,6 +1281,11 @@ void M_CreateMenus()
|
|||
{
|
||||
I_BuildMIDIMenuList(*opt);
|
||||
}
|
||||
opt = OptionValues.CheckKey(NAME_Aldevices);
|
||||
if (opt != NULL)
|
||||
{
|
||||
I_BuildALDeviceList(*opt);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
|
|
@ -489,7 +489,13 @@ bool FOptionMenuItem::MouseEvent(int type, int x, int y)
|
|||
|
||||
int FOptionMenuItem::GetIndent()
|
||||
{
|
||||
return mCentered? 0 : SmallFont->StringWidth(mLabel);
|
||||
if (mCentered)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
const char *label = mLabel;
|
||||
if (*label == '$') label = GStrings(label+1);
|
||||
return SmallFont->StringWidth(label);
|
||||
}
|
||||
|
||||
void FOptionMenuItem::drawLabel(int indent, int y, EColorRange color, bool grayed)
|
||||
|
|
|
@ -338,6 +338,7 @@ xx(Arg4)
|
|||
xx(Arg0Str)
|
||||
xx(Arg1Str)
|
||||
xx(Id)
|
||||
xx(MoreIds)
|
||||
xx(V1)
|
||||
xx(V2)
|
||||
|
||||
|
@ -565,6 +566,7 @@ xx(Controlmessage)
|
|||
xx(Crosshairs)
|
||||
xx(Colorpickermenu)
|
||||
xx(Mididevices)
|
||||
xx(Aldevices)
|
||||
xx(CustomizeControls)
|
||||
xx(MessageOptions)
|
||||
xx(AutomapOptions)
|
||||
|
|
|
@ -113,7 +113,7 @@ public:
|
|||
BYTE chipnum = reg >> 8;
|
||||
if (chipnum != CurChip)
|
||||
{
|
||||
BYTE switcher[2] = { chipnum + 1, 2 };
|
||||
BYTE switcher[2] = { (BYTE)(chipnum + 1), 2 };
|
||||
fwrite(switcher, 1, 2, File);
|
||||
}
|
||||
reg &= 255;
|
||||
|
@ -192,7 +192,7 @@ public:
|
|||
"\0\0\0\0" // Total milliseconds
|
||||
"\0\0\0", // Total data
|
||||
1, 20, File);
|
||||
char type[4] = { Dual * 2, 0, 0, 0 }; // Single or dual OPL-2
|
||||
char type[4] = { (char)(Dual * 2), 0, 0, 0 }; // Single or dual OPL-2
|
||||
fwrite(type, 1, 4, File);
|
||||
}
|
||||
virtual ~OPL_DOSBOXdump()
|
||||
|
|
|
@ -52,29 +52,22 @@ void OPLmusicBlock::Restart()
|
|||
LastOffset = 0;
|
||||
}
|
||||
|
||||
OPLmusicFile::OPLmusicFile (FILE *file, BYTE *musiccache, int len)
|
||||
: ScoreLen (len)
|
||||
OPLmusicFile::OPLmusicFile (FileReader *reader)
|
||||
: ScoreLen (reader->GetLength())
|
||||
{
|
||||
if (io == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
scoredata = new BYTE[len];
|
||||
scoredata = new BYTE[ScoreLen];
|
||||
|
||||
if (file)
|
||||
{
|
||||
if (fread (scoredata, 1, len, file) != (size_t)len)
|
||||
{
|
||||
fail: delete[] scoredata;
|
||||
scoredata = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(scoredata, &musiccache[0], len);
|
||||
}
|
||||
if (reader->Read(scoredata, ScoreLen) != ScoreLen)
|
||||
{
|
||||
fail: delete[] scoredata;
|
||||
scoredata = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == (NumChips = io->OPLinit(NumChips)))
|
||||
{
|
||||
|
@ -100,7 +93,7 @@ fail: delete[] scoredata;
|
|||
{
|
||||
RawPlayer = DosBox1;
|
||||
SamplesPerTick = OPL_SAMPLE_RATE / 1000;
|
||||
ScoreLen = MIN<int>(len - 24, LittleLong(((DWORD *)scoredata)[4])) + 24;
|
||||
ScoreLen = MIN<int>(ScoreLen - 24, LittleLong(((DWORD *)scoredata)[4])) + 24;
|
||||
}
|
||||
else if (((DWORD *)scoredata)[2] == MAKE_ID(2,0,0,0))
|
||||
{
|
||||
|
@ -120,7 +113,7 @@ fail: delete[] scoredata;
|
|||
RawPlayer = DosBox2;
|
||||
SamplesPerTick = OPL_SAMPLE_RATE / 1000;
|
||||
int headersize = 0x1A + scoredata[0x19];
|
||||
ScoreLen = MIN<int>(len - headersize, LittleLong(((DWORD *)scoredata)[3]) * 2) + headersize;
|
||||
ScoreLen = MIN<int>(ScoreLen - headersize, LittleLong(((DWORD *)scoredata)[3]) * 2) + headersize;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -29,7 +29,7 @@ protected:
|
|||
class OPLmusicFile : public OPLmusicBlock
|
||||
{
|
||||
public:
|
||||
OPLmusicFile(FILE *file, BYTE *musiccache, int len);
|
||||
OPLmusicFile(FileReader *reader);
|
||||
OPLmusicFile(const OPLmusicFile *source, const char *filename);
|
||||
virtual ~OPLmusicFile();
|
||||
|
||||
|
|
|
@ -844,7 +844,7 @@ void P_Spawn3DFloors (void)
|
|||
{
|
||||
if (line->args[1]&8)
|
||||
{
|
||||
line->SetMainId(line->args[4]);
|
||||
tagManager.AddLineID(i, line->args[4]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -167,7 +167,7 @@ void P_Attach3dMidtexLinesToSector(sector_t *sector, int lineid, int tag, bool c
|
|||
{
|
||||
line_t *ln = sectors[sec].lines[line];
|
||||
|
||||
if (lineid != 0 && !ln->HasId(lineid)) continue;
|
||||
if (lineid != 0 && !tagManager.LineHasID(ln, lineid)) continue;
|
||||
|
||||
if (ln->frontsector == NULL || ln->backsector == NULL || !(ln->flags & ML_3DMIDTEX))
|
||||
{
|
||||
|
|
|
@ -1562,7 +1562,7 @@ void FBehavior::StaticSerializeModuleStates (FArchive &arc)
|
|||
|
||||
if (modnum != StaticModules.Size())
|
||||
{
|
||||
I_Error ("Level was saved with a different number of ACS modules.");
|
||||
I_Error("Level was saved with a different number of ACS modules. (Have %d, save has %d)", StaticModules.Size(), modnum);
|
||||
}
|
||||
|
||||
for (modnum = 0; modnum < StaticModules.Size(); ++modnum)
|
||||
|
@ -1583,7 +1583,7 @@ void FBehavior::StaticSerializeModuleStates (FArchive &arc)
|
|||
if (stricmp (modname, module->ModuleName) != 0)
|
||||
{
|
||||
delete[] modname;
|
||||
I_Error ("Level was saved with a different set of ACS modules.");
|
||||
I_Error("Level was saved with a different set or order of ACS modules. (Have %s, save has %s)", module->ModuleName, modname);
|
||||
}
|
||||
else if (ModSize != module->GetDataSize())
|
||||
{
|
||||
|
@ -3210,7 +3210,7 @@ do_count:
|
|||
if (actor->health > 0 &&
|
||||
(kind == NULL || actor->IsA (kind)))
|
||||
{
|
||||
if (actor->Sector->HasTag(tag) || tag == -1)
|
||||
if (tag == -1 || tagManager.SectorHasTag(actor->Sector, tag))
|
||||
{
|
||||
// Don't count items in somebody's inventory
|
||||
if (!actor->IsKindOf (RUNTIME_CLASS(AInventory)) ||
|
||||
|
@ -3230,7 +3230,7 @@ do_count:
|
|||
if (actor->health > 0 &&
|
||||
(kind == NULL || actor->IsA (kind)))
|
||||
{
|
||||
if (actor->Sector->HasTag(tag) || tag == -1)
|
||||
if (tag == -1 || tagManager.SectorHasTag(actor->Sector, tag))
|
||||
{
|
||||
// Don't count items in somebody's inventory
|
||||
if (!actor->IsKindOf (RUNTIME_CLASS(AInventory)) ||
|
||||
|
@ -3898,7 +3898,13 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value)
|
|||
|
||||
case APROP_ViewHeight:
|
||||
if (actor->IsKindOf (RUNTIME_CLASS (APlayerPawn)))
|
||||
{
|
||||
static_cast<APlayerPawn *>(actor)->ViewHeight = value;
|
||||
if (actor->player != NULL)
|
||||
{
|
||||
actor->player->viewheight = value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case APROP_AttackZOffset:
|
||||
|
|
|
@ -586,7 +586,7 @@ void P_DrawSplash2 (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, i
|
|||
}
|
||||
}
|
||||
|
||||
void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end, int color1, int color2, double maxdiff_d, int flags, PClassActor *spawnclass, angle_t angle, int duration, double sparsity, double drift)
|
||||
void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end, int color1, int color2, double maxdiff_d, int flags, PClassActor *spawnclass, angle_t angle, int duration, double sparsity, double drift, int SpiralOffset)
|
||||
{
|
||||
double length, lengthsquared;
|
||||
int steps, i;
|
||||
|
@ -679,7 +679,7 @@ void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end
|
|||
|
||||
color1 = color1 == 0 ? -1 : ParticleColor(color1);
|
||||
pos = start;
|
||||
deg = FAngle(270);
|
||||
deg = FAngle(SpiralOffset);
|
||||
for (i = spiral_steps; i; i--)
|
||||
{
|
||||
particle_t *p = NewParticle ();
|
||||
|
|
|
@ -88,7 +88,7 @@ void P_RunEffects (void);
|
|||
|
||||
void P_RunEffect (AActor *actor, int effects);
|
||||
|
||||
void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end, int color1, int color2, double maxdiff = 0, int flags = 0, PClassActor *spawnclass = NULL, angle_t angle = 0, int duration = 35, double sparsity = 1.0, double drift = 1.0);
|
||||
void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end, int color1, int color2, double maxdiff = 0, int flags = 0, PClassActor *spawnclass = NULL, angle_t angle = 0, int duration = 35, double sparsity = 1.0, double drift = 1.0, int SpiralOffset = 270);
|
||||
void P_DrawSplash (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, int kind);
|
||||
void P_DrawSplash2 (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, int updown, int kind);
|
||||
void P_DisconnectEffect (AActor *actor);
|
||||
|
|
|
@ -838,7 +838,7 @@ void EV_StopLightEffect (int tag)
|
|||
|
||||
while ((effect = iterator.Next()) != NULL)
|
||||
{
|
||||
if (effect->GetSector()->HasTag(tag))
|
||||
if (tagManager.SectorHasTag(effect->GetSector(), tag))
|
||||
{
|
||||
effect->Destroy();
|
||||
}
|
||||
|
|
|
@ -278,7 +278,7 @@ static void RemoveTaggedSectors(extsector_t::linked::plane &scrollplane, int tag
|
|||
{
|
||||
for(int i = scrollplane.Sectors.Size()-1; i>=0; i--)
|
||||
{
|
||||
if (scrollplane.Sectors[i].Sector->HasTag(tag))
|
||||
if (tagManager.SectorHasTag(scrollplane.Sectors[i].Sector, tag))
|
||||
{
|
||||
scrollplane.Sectors.Delete(i);
|
||||
}
|
||||
|
|
|
@ -1266,7 +1266,7 @@ FUNC(LS_Thing_Destroy)
|
|||
while (actor)
|
||||
{
|
||||
AActor *temp = iterator.Next ();
|
||||
if (actor->flags & MF_SHOOTABLE && actor->Sector->HasTag(arg2))
|
||||
if (actor->flags & MF_SHOOTABLE && tagManager.SectorHasTag(actor->Sector, arg2))
|
||||
P_DamageMobj (actor, NULL, it, arg1 ? TELEFRAG_DAMAGE : actor->health, NAME_None);
|
||||
actor = temp;
|
||||
}
|
||||
|
@ -1279,7 +1279,7 @@ FUNC(LS_Thing_Destroy)
|
|||
while (actor)
|
||||
{
|
||||
AActor *temp = iterator.Next ();
|
||||
if (actor->flags & MF_SHOOTABLE && (arg2 == 0 || actor->Sector->HasTag(arg2)))
|
||||
if (actor->flags & MF_SHOOTABLE && (arg2 == 0 || tagManager.SectorHasTag(actor->Sector, arg2)))
|
||||
P_DamageMobj (actor, NULL, it, arg1 ? TELEFRAG_DAMAGE : actor->health, NAME_None);
|
||||
actor = temp;
|
||||
}
|
||||
|
@ -2063,7 +2063,7 @@ static void SetWallScroller (int id, int sidechoice, fixed_t dx, fixed_t dy, int
|
|||
{
|
||||
int wallnum = scroller->GetWallNum ();
|
||||
|
||||
if (wallnum >= 0 && sides[wallnum].linedef->HasId(id) &&
|
||||
if (wallnum >= 0 && tagManager.LineHasID(sides[wallnum].linedef, id) &&
|
||||
int(sides[wallnum].linedef->sidedef[sidechoice] - sides) == wallnum &&
|
||||
Where == scroller->GetScrollParts())
|
||||
{
|
||||
|
@ -2082,7 +2082,7 @@ static void SetWallScroller (int id, int sidechoice, fixed_t dx, fixed_t dy, int
|
|||
while ( (collect.Obj = iterator.Next ()) )
|
||||
{
|
||||
if ((collect.RefNum = ((DScroller *)collect.Obj)->GetWallNum ()) != -1 &&
|
||||
sides[collect.RefNum].linedef->HasId(id) &&
|
||||
tagManager.LineHasID(sides[collect.RefNum].linedef, id) &&
|
||||
int(sides[collect.RefNum].linedef->sidedef[sidechoice] - sides) == collect.RefNum &&
|
||||
Where == ((DScroller *)collect.Obj)->GetScrollParts())
|
||||
{
|
||||
|
@ -2169,7 +2169,7 @@ static void SetScroller (int tag, DScroller::EScrollType type, fixed_t dx, fixed
|
|||
{
|
||||
if (scroller->IsType (type))
|
||||
{
|
||||
if (sectors[scroller->GetAffectee ()].HasTag(tag))
|
||||
if (tagManager.SectorHasTag(scroller->GetAffectee (), tag))
|
||||
{
|
||||
i++;
|
||||
scroller->SetRate (dx, dy);
|
||||
|
|
|
@ -478,7 +478,7 @@ void P_TraceBleed (int damage, AActor *target); // random direction version
|
|||
bool P_HitFloor (AActor *thing);
|
||||
bool P_HitWater (AActor *thing, sector_t *sec, fixed_t splashx = FIXED_MIN, fixed_t splashy = FIXED_MIN, fixed_t splashz=FIXED_MIN, bool checkabove = false, bool alert = true);
|
||||
void P_CheckSplash(AActor *self, fixed_t distance);
|
||||
void P_RailAttack (AActor *source, int damage, int offset_xy, fixed_t offset_z = 0, int color1 = 0, int color2 = 0, double maxdiff = 0, int flags = 0, PClassActor *puff = NULL, angle_t angleoffset = 0, angle_t pitchoffset = 0, fixed_t distance = 8192*FRACUNIT, int duration = 0, double sparsity = 1.0, double drift = 1.0, PClassActor *spawnclass = NULL); // [RH] Shoot a railgun
|
||||
void P_RailAttack (AActor *source, int damage, int offset_xy, fixed_t offset_z = 0, int color1 = 0, int color2 = 0, double maxdiff = 0, int flags = 0, PClassActor *puff = NULL, angle_t angleoffset = 0, angle_t pitchoffset = 0, fixed_t distance = 8192*FRACUNIT, int duration = 0, double sparsity = 1.0, double drift = 1.0, PClassActor *spawnclass = NULL, int SpiralOffset = 270); // [RH] Shoot a railgun
|
||||
|
||||
enum // P_RailAttack / A_RailAttack / A_CustomRailgun / P_DrawRailTrail flags
|
||||
{
|
||||
|
|
|
@ -1034,7 +1034,7 @@ bool PIT_CheckThing(AActor *thing, FCheckPosition &tm)
|
|||
// Both things overlap in x or y direction
|
||||
bool unblocking = false;
|
||||
|
||||
if (tm.FromPMove || tm.thing->player != NULL)
|
||||
if ((tm.FromPMove || tm.thing->player != NULL) && thing->flags&MF_SOLID)
|
||||
{
|
||||
// Both actors already overlap. To prevent them from remaining stuck allow the move if it
|
||||
// takes them further apart or the move does not change the position (when called from P_ChangeSector.)
|
||||
|
@ -1042,7 +1042,9 @@ bool PIT_CheckThing(AActor *thing, FCheckPosition &tm)
|
|||
{
|
||||
unblocking = true;
|
||||
}
|
||||
else
|
||||
else if (abs(thing->x - tm.thing->x) < (thing->radius+tm.thing->radius)/2 &&
|
||||
abs(thing->y - tm.thing->y) < (thing->radius+tm.thing->radius)/2)
|
||||
|
||||
{
|
||||
fixed_t newdist = P_AproxDistance(thing->x - tm.x, thing->y - tm.y);
|
||||
fixed_t olddist = P_AproxDistance(thing->x - tm.thing->x, thing->y - tm.thing->y);
|
||||
|
@ -4140,7 +4142,7 @@ static ETraceStatus ProcessRailHit(FTraceResults &res, void *userdata)
|
|||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void P_RailAttack(AActor *source, int damage, int offset_xy, fixed_t offset_z, int color1, int color2, double maxdiff, int railflags, PClassActor *puffclass, angle_t angleoffset, angle_t pitchoffset, fixed_t distance, int duration, double sparsity, double drift, PClassActor *spawnclass)
|
||||
void P_RailAttack(AActor *source, int damage, int offset_xy, fixed_t offset_z, int color1, int color2, double maxdiff, int railflags, PClassActor *puffclass, angle_t angleoffset, angle_t pitchoffset, fixed_t distance, int duration, double sparsity, double drift, PClassActor *spawnclass, int SpiralOffset)
|
||||
{
|
||||
fixed_t vx, vy, vz;
|
||||
angle_t angle, pitch;
|
||||
|
@ -4295,7 +4297,7 @@ void P_RailAttack(AActor *source, int damage, int offset_xy, fixed_t offset_z, i
|
|||
end.X = FIXED2FLOAT(trace.X);
|
||||
end.Y = FIXED2FLOAT(trace.Y);
|
||||
end.Z = FIXED2FLOAT(trace.Z);
|
||||
P_DrawRailTrail(source, start, end, color1, color2, maxdiff, railflags, spawnclass, source->angle + angleoffset, duration, sparsity, drift);
|
||||
P_DrawRailTrail(source, start, end, color1, color2, maxdiff, railflags, spawnclass, source->angle + angleoffset, duration, sparsity, drift, SpiralOffset);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -3545,7 +3545,7 @@ void AActor::Tick ()
|
|||
}
|
||||
else if (scrolltype == Scroll_StrifeCurrent)
|
||||
{ // Strife scroll special
|
||||
int anglespeed = sec->GetMainTag() - 100;
|
||||
int anglespeed = tagManager.GetFirstSectorTag(sec) - 100;
|
||||
fixed_t carryspeed = DivScale32 (anglespeed % 10, 16*CARRYFACTOR);
|
||||
angle_t fineangle = (anglespeed / 10) << (32-3);
|
||||
fineangle >>= ANGLETOFINESHIFT;
|
||||
|
@ -4857,7 +4857,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
|
|||
// [RH] sound sequence overriders
|
||||
if (mentry->Type == NULL && mentry->Special == SMT_SSeqOverride)
|
||||
{
|
||||
int type = mentry->Args[0];
|
||||
int type = mthing->args[0];
|
||||
if (type == 255) type = -1;
|
||||
if (type > 63)
|
||||
{
|
||||
|
|
|
@ -348,9 +348,13 @@ void P_SerializeWorld (FArchive &arc)
|
|||
{
|
||||
arc << sec->lightlevel;
|
||||
}
|
||||
arc << sec->special
|
||||
<< sec->tag
|
||||
<< sec->soundtraversed
|
||||
arc << sec->special;
|
||||
if (SaveVersion < 4523)
|
||||
{
|
||||
short tag;
|
||||
arc << tag;
|
||||
}
|
||||
arc << sec->soundtraversed
|
||||
<< sec->seqType
|
||||
<< sec->friction
|
||||
<< sec->movefactor
|
||||
|
@ -405,8 +409,13 @@ void P_SerializeWorld (FArchive &arc)
|
|||
arc << li->flags
|
||||
<< li->activation
|
||||
<< li->special
|
||||
<< li->Alpha
|
||||
<< li->id;
|
||||
<< li->Alpha;
|
||||
|
||||
if (SaveVersion < 4523)
|
||||
{
|
||||
int id;
|
||||
arc << id;
|
||||
}
|
||||
if (P_IsACSSpecial(li->special))
|
||||
{
|
||||
P_SerializeACSScriptNumber(arc, li->args[0], false);
|
||||
|
|
|
@ -825,77 +825,6 @@ sector_t *sector_t::GetHeightSec() const
|
|||
}
|
||||
|
||||
|
||||
bool sector_t::HasTag(int checktag) const
|
||||
{
|
||||
return tag == checktag;
|
||||
}
|
||||
|
||||
bool sector_t::HasTags() const
|
||||
{
|
||||
return tag != 0;
|
||||
}
|
||||
|
||||
void sector_t::SetMainTag(int tagnum)
|
||||
{
|
||||
tag = tagnum;
|
||||
}
|
||||
|
||||
int sector_t::GetMainTag() const
|
||||
{
|
||||
return tag;
|
||||
}
|
||||
|
||||
void sector_t::ClearTags()
|
||||
{
|
||||
tag = 0;
|
||||
}
|
||||
|
||||
void sector_t::HashTags()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=numsectors; --i>=0; ) // Initially make all slots empty.
|
||||
sectors[i].firsttag = -1;
|
||||
for (i=numsectors; --i>=0; ) // Proceed from last to first sector
|
||||
{ // so that lower sectors appear first
|
||||
int j = (unsigned) sectors[i].tag % (unsigned) numsectors; // Hash func
|
||||
sectors[i].nexttag = sectors[j].firsttag; // Prepend sector to chain
|
||||
sectors[j].firsttag = i;
|
||||
}
|
||||
}
|
||||
|
||||
void line_t::SetMainId(int newid)
|
||||
{
|
||||
id = newid;
|
||||
}
|
||||
|
||||
void line_t::ClearIds()
|
||||
{
|
||||
id = -1;
|
||||
}
|
||||
|
||||
bool line_t::HasId(int checkid) const
|
||||
{
|
||||
return id == checkid;
|
||||
}
|
||||
|
||||
|
||||
void line_t::HashIds()
|
||||
{
|
||||
// killough 4/17/98: same thing, only for linedefs
|
||||
int i;
|
||||
|
||||
for (i=numlines; --i>=0; ) // Initially make all slots empty.
|
||||
lines[i].firstid = -1;
|
||||
for (i=numlines; --i>=0; ) // Proceed from last to first linedef
|
||||
{ // so that lower linedefs appear first
|
||||
int j = (unsigned) lines[i].id % (unsigned) numlines; // Hash func
|
||||
lines[i].nextid = lines[j].firstid; // Prepend linedef to chain
|
||||
lines[j].firstid = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool secplane_t::CopyPlaneIfValid (secplane_t *dest, const secplane_t *opp) const
|
||||
{
|
||||
bool copy = false;
|
||||
|
|
|
@ -1513,7 +1513,7 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex)
|
|||
else // [RH] Translate to new sector special
|
||||
ss->special = P_TranslateSectorSpecial (LittleShort(ms->special));
|
||||
ss->secretsector = !!(ss->special&SECRET_MASK);
|
||||
ss->SetMainTag(LittleShort(ms->tag));
|
||||
tagManager.AddSectorTag(i, LittleShort(ms->tag));
|
||||
ss->thinglist = NULL;
|
||||
ss->touching_thinglist = NULL; // phares 3/14/98
|
||||
ss->seqType = defSeqType;
|
||||
|
@ -1904,54 +1904,59 @@ void P_AdjustLine (line_t *ld)
|
|||
}
|
||||
}
|
||||
|
||||
void P_SetLineID (line_t *ld)
|
||||
void P_SetLineID (int i, line_t *ld)
|
||||
{
|
||||
// [RH] Set line id (as appropriate) here
|
||||
// for Doom format maps this must be done in P_TranslateLineDef because
|
||||
// the tag doesn't always go into the first arg.
|
||||
if (level.maptype == MAPTYPE_HEXEN)
|
||||
{
|
||||
int setid = -1;
|
||||
switch (ld->special)
|
||||
{
|
||||
case Line_SetIdentification:
|
||||
if (!(level.flags2 & LEVEL2_HEXENHACK))
|
||||
{
|
||||
ld->SetMainId(ld->args[0] + 256 * ld->args[4]);
|
||||
setid = ld->args[0] + 256 * ld->args[4];
|
||||
ld->flags |= ld->args[1]<<16;
|
||||
}
|
||||
else
|
||||
{
|
||||
ld->SetMainId(ld->args[0]);
|
||||
setid = ld->args[0];
|
||||
}
|
||||
ld->special = 0;
|
||||
break;
|
||||
|
||||
case TranslucentLine:
|
||||
ld->SetMainId(ld->args[0]);
|
||||
setid = ld->args[0];
|
||||
ld->flags |= ld->args[3]<<16;
|
||||
break;
|
||||
|
||||
case Teleport_Line:
|
||||
case Scroll_Texture_Model:
|
||||
ld->SetMainId(ld->args[0]);
|
||||
setid = ld->args[0];
|
||||
break;
|
||||
|
||||
case Polyobj_StartLine:
|
||||
ld->SetMainId(ld->args[3]);
|
||||
setid = ld->args[3];
|
||||
break;
|
||||
|
||||
case Polyobj_ExplicitLine:
|
||||
ld->SetMainId(ld->args[4]);
|
||||
setid = ld->args[4];
|
||||
break;
|
||||
|
||||
case Plane_Align:
|
||||
ld->SetMainId(ld->args[2]);
|
||||
setid = ld->args[2];
|
||||
break;
|
||||
|
||||
case Static_Init:
|
||||
if (ld->args[1] == Init_SectorLink) ld->SetMainId(ld->args[0]);
|
||||
if (ld->args[1] == Init_SectorLink) setid = ld->args[0];
|
||||
break;
|
||||
}
|
||||
if (setid != -1)
|
||||
{
|
||||
tagManager.AddLineID(i, setid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2034,7 +2039,7 @@ void P_FinishLoadingLineDef(line_t *ld, int alpha)
|
|||
{
|
||||
for (j = 0; j < numlines; j++)
|
||||
{
|
||||
if (lines[j].HasId(ld->args[0]))
|
||||
if (tagManager.LineHasID(j, ld->args[0]))
|
||||
{
|
||||
lines[j].Alpha = alpha;
|
||||
if (additive)
|
||||
|
@ -2136,13 +2141,13 @@ void P_LoadLineDefs (MapData * map)
|
|||
|
||||
mld = (maplinedef_t *)mldf;
|
||||
ld = lines;
|
||||
for (i = numlines; i > 0; i--, mld++, ld++)
|
||||
for (i = 0; i < numlines; i++, mld++, ld++)
|
||||
{
|
||||
ld->Alpha = FRACUNIT; // [RH] Opaque by default
|
||||
|
||||
// [RH] Translate old linedef special and flags to be
|
||||
// compatible with the new format.
|
||||
P_TranslateLineDef (ld, mld, true);
|
||||
P_TranslateLineDef (ld, mld, i);
|
||||
|
||||
ld->v1 = &vertexes[LittleShort(mld->v1)];
|
||||
ld->v2 = &vertexes[LittleShort(mld->v2)];
|
||||
|
@ -2215,7 +2220,7 @@ void P_LoadLineDefs2 (MapData * map)
|
|||
|
||||
mld = (maplinedef2_t *)mldf;
|
||||
ld = lines;
|
||||
for (i = numlines; i > 0; i--, mld++, ld++)
|
||||
for (i = 0; i < numlines; i++, mld++, ld++)
|
||||
{
|
||||
int j;
|
||||
|
||||
|
@ -2228,13 +2233,12 @@ void P_LoadLineDefs2 (MapData * map)
|
|||
ld->v1 = &vertexes[LittleShort(mld->v1)];
|
||||
ld->v2 = &vertexes[LittleShort(mld->v2)];
|
||||
ld->Alpha = FRACUNIT; // [RH] Opaque by default
|
||||
ld->ClearIds();
|
||||
|
||||
P_SetSideNum (&ld->sidedef[0], LittleShort(mld->sidenum[0]));
|
||||
P_SetSideNum (&ld->sidedef[1], LittleShort(mld->sidenum[1]));
|
||||
|
||||
P_AdjustLine (ld);
|
||||
P_SetLineID(ld);
|
||||
P_SetLineID(i, ld);
|
||||
P_SaveLineSpecial (ld);
|
||||
if (level.flags2 & LEVEL2_CLIPMIDTEX) ld->flags |= ML_CLIP_MIDTEX;
|
||||
if (level.flags2 & LEVEL2_WRAPMIDTEX) ld->flags |= ML_WRAP_MIDTEX;
|
||||
|
@ -2490,7 +2494,7 @@ void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, intmaps
|
|||
|
||||
for (s = 0; s < numsectors; s++)
|
||||
{
|
||||
if (sectors[s].HasTag(tag))
|
||||
if (tagManager.SectorHasTag(s, tag))
|
||||
{
|
||||
if (!colorgood) color = sectors[s].ColorMap->Color;
|
||||
if (!foggood) fog = sectors[s].ColorMap->Fade;
|
||||
|
@ -3126,9 +3130,9 @@ static void P_GroupLines (bool buildmap)
|
|||
{
|
||||
if (sector->linecount == 0)
|
||||
{
|
||||
Printf ("Sector %i (tag %i) has no lines\n", i, sector->GetMainTag());
|
||||
Printf ("Sector %i (tag %i) has no lines\n", i, tagManager.GetFirstSectorTag(sector));
|
||||
// 0 the sector's tag so that no specials can use it
|
||||
sector->ClearTags();
|
||||
tagManager.RemoveSectorTags(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3205,8 +3209,7 @@ static void P_GroupLines (bool buildmap)
|
|||
// [RH] Moved this here
|
||||
times[4].Clock();
|
||||
// killough 1/30/98: Create xref tables for tags
|
||||
sector_t::HashTags();
|
||||
line_t::HashIds();
|
||||
tagManager.HashTags();
|
||||
times[4].Unclock();
|
||||
|
||||
times[5].Clock();
|
||||
|
@ -3337,6 +3340,7 @@ void P_FreeLevelData ()
|
|||
FPolyObj::ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process.
|
||||
SN_StopAllSequences ();
|
||||
DThinker::DestroyAllThinkers ();
|
||||
tagManager.Clear();
|
||||
level.total_monsters = level.total_items = level.total_secrets =
|
||||
level.killed_monsters = level.found_items = level.found_secrets =
|
||||
wminfo.maxfrags = 0;
|
||||
|
|
|
@ -115,7 +115,7 @@ struct line_t;
|
|||
struct maplinedef_t;
|
||||
|
||||
void P_LoadTranslator(const char *lumpname);
|
||||
void P_TranslateLineDef (line_t *ld, maplinedef_t *mld, bool setlineid);
|
||||
void P_TranslateLineDef (line_t *ld, maplinedef_t *mld, int lineindexforid = -1);
|
||||
int P_TranslateSectorSpecial (int);
|
||||
|
||||
int GetUDMFInt(int type, int index, const char *key);
|
||||
|
|
|
@ -186,57 +186,6 @@ bool CheckIfExitIsGood (AActor *self, level_info_t *info)
|
|||
// UTILITIES
|
||||
//
|
||||
|
||||
|
||||
|
||||
//
|
||||
// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
|
||||
//
|
||||
|
||||
// Find the next sector with a specified tag.
|
||||
// Rewritten by Lee Killough to use chained hashing to improve speed
|
||||
|
||||
int FSectorTagIterator::Next()
|
||||
{
|
||||
int ret;
|
||||
if (searchtag == INT_MIN)
|
||||
{
|
||||
ret = start;
|
||||
start = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (start != -1 && sectors[start].tag != searchtag) start = sectors[start].nexttag;
|
||||
if (start == -1) return -1;
|
||||
ret = start;
|
||||
start = sectors[start].nexttag;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int FSectorTagIterator::NextCompat(bool compat, int start)
|
||||
{
|
||||
if (!compat) return Next();
|
||||
|
||||
for (int i = start + 1; i < numsectors; i++)
|
||||
{
|
||||
if (sectors[i].HasTag(searchtag)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// killough 4/16/98: Same thing, only for linedefs
|
||||
|
||||
int FLineIdIterator::Next()
|
||||
{
|
||||
while (start != -1 && lines[start].id != searchtag) start = lines[start].nextid;
|
||||
if (start == -1) return -1;
|
||||
int ret = start;
|
||||
start = lines[start].nextid;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// P_ActivateLine
|
||||
|
@ -283,7 +232,7 @@ bool P_ActivateLine (line_t *line, AActor *mo, int side, int activationType)
|
|||
!repeat && // only non-repeatable triggers
|
||||
(special<Generic_Floor || special>Generic_Crusher) && // not for Boom's generalized linedefs
|
||||
special && // not for lines without a special
|
||||
line->HasId(line->args[0]) && // Safety check: exclude edited UDMF linedefs or ones that don't map the tag to args[0]
|
||||
tagManager.LineHasID(line, line->args[0]) && // Safety check: exclude edited UDMF linedefs or ones that don't map the tag to args[0]
|
||||
line->args[0] && // only if there's a tag (which is stored in the first arg)
|
||||
P_FindFirstSectorFromTag (line->args[0]) == -1) // only if no sector is tagged to this linedef
|
||||
{
|
||||
|
@ -1792,7 +1741,7 @@ static void P_SpawnScrollers(void)
|
|||
if (lines[i].special == Sector_CopyScroller)
|
||||
{
|
||||
// don't allow copying the scroller if the sector has the same tag as it would just duplicate it.
|
||||
if (lines[i].frontsector->HasTag(lines[i].args[0]))
|
||||
if (tagManager.SectorHasTag(lines[i].frontsector, lines[i].args[0]))
|
||||
{
|
||||
copyscrollers.Push(i);
|
||||
}
|
||||
|
@ -2200,7 +2149,7 @@ DPusher::DPusher (DPusher::EPusher type, line_t *l, int magnitude, int angle,
|
|||
|
||||
int DPusher::CheckForSectorMatch (EPusher type, int tag)
|
||||
{
|
||||
if (m_Type == type && sectors[m_Affectee].HasTag(tag))
|
||||
if (m_Type == type && tagManager.SectorHasTag(m_Affectee, tag))
|
||||
return m_Affectee;
|
||||
else
|
||||
return -1;
|
||||
|
|
60
src/p_spec.h
60
src/p_spec.h
|
@ -242,66 +242,8 @@ inline sector_t *getNextSector (line_t *line, const sector_t *sec)
|
|||
line->frontsector;
|
||||
}
|
||||
|
||||
class FSectorTagIterator
|
||||
{
|
||||
protected:
|
||||
int searchtag;
|
||||
int start;
|
||||
|
||||
public:
|
||||
FSectorTagIterator(int tag)
|
||||
{
|
||||
searchtag = tag;
|
||||
start = sectors[(unsigned)tag % (unsigned)numsectors].firsttag;
|
||||
}
|
||||
|
||||
// Special constructor for actions that treat tag 0 as 'back of activation line'
|
||||
FSectorTagIterator(int tag, line_t *line)
|
||||
{
|
||||
if (tag == 0)
|
||||
{
|
||||
searchtag = INT_MIN;
|
||||
start = (line == NULL || line->backsector == NULL)? -1 : (int)(line->backsector - sectors);
|
||||
}
|
||||
else
|
||||
{
|
||||
searchtag = tag;
|
||||
start = sectors[(unsigned)tag % (unsigned)numsectors].firsttag;
|
||||
}
|
||||
}
|
||||
|
||||
int Next();
|
||||
int NextCompat(bool compat, int secnum);
|
||||
};
|
||||
|
||||
class FLineIdIterator
|
||||
{
|
||||
protected:
|
||||
int searchtag;
|
||||
int start;
|
||||
|
||||
public:
|
||||
FLineIdIterator(int id)
|
||||
{
|
||||
searchtag = id;
|
||||
start = lines[(unsigned) id % (unsigned) numlines].firstid;
|
||||
}
|
||||
|
||||
int Next();
|
||||
};
|
||||
|
||||
|
||||
inline int P_FindFirstSectorFromTag(int tag)
|
||||
{
|
||||
FSectorTagIterator it(tag);
|
||||
return it.Next();
|
||||
}
|
||||
|
||||
inline int P_FindFirstLineFromID(int tag)
|
||||
{
|
||||
FLineIdIterator it(tag);
|
||||
return it.Next();
|
||||
}
|
||||
#include "p_tags.h"
|
||||
|
||||
//
|
||||
// P_LIGHTS
|
||||
|
|
353
src/p_tags.cpp
Normal file
353
src/p_tags.cpp
Normal file
|
@ -0,0 +1,353 @@
|
|||
/*
|
||||
** p_tags.cpp
|
||||
** everything to do with tags and their management
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2015 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
#include "p_tags.h"
|
||||
#include "c_dispatch.h"
|
||||
|
||||
FTagManager tagManager;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static inline int sectindex(const sector_t *sector)
|
||||
{
|
||||
return (int)(intptr_t)(sector - sectors);
|
||||
}
|
||||
|
||||
static inline int lineindex(const line_t *line)
|
||||
{
|
||||
return (int)(intptr_t)(line - lines);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FTagManager::AddSectorTag(int sector, int tag)
|
||||
{
|
||||
if (tag == 0) return;
|
||||
|
||||
// This function assumes that all tags for a single sector get added sequentially.
|
||||
// Should there ever be some need for compatibility.txt to add tags to sectors which already have a tag this function needs to be changed to adjust the startForSector indices.
|
||||
while (startForSector.Size() <= (unsigned int)sector)
|
||||
{
|
||||
startForSector.Push(-1);
|
||||
}
|
||||
if (startForSector[sector] == -1)
|
||||
{
|
||||
startForSector[sector] = allTags.Size();
|
||||
}
|
||||
else
|
||||
{
|
||||
// check if the key was already defined
|
||||
for (unsigned i = startForSector[sector]; i < allTags.Size(); i++)
|
||||
{
|
||||
if (allTags[i].tag == tag)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
FTagItem it = { sector, tag, -1 };
|
||||
allTags.Push(it);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FTagManager::RemoveSectorTags(int sect)
|
||||
{
|
||||
int start = startForSector[sect];
|
||||
if (start >= 0)
|
||||
{
|
||||
while (allTags[start].target == sect)
|
||||
{
|
||||
allTags[start].tag = allTags[start].target = -1;
|
||||
start++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FTagManager::AddLineID(int line, int tag)
|
||||
{
|
||||
if (tag == -1) return; // For line IDs -1 means 'not set', unlike sectors.
|
||||
|
||||
// This function assumes that all ids for a single line get added sequentially.
|
||||
while (startForLine.Size() <= (unsigned int)line)
|
||||
{
|
||||
startForLine.Push(-1);
|
||||
}
|
||||
if (startForLine[line] == -1)
|
||||
{
|
||||
startForLine[line] = allIDs.Size();
|
||||
}
|
||||
else
|
||||
{
|
||||
// check if the key was already defined
|
||||
for (unsigned i = startForLine[line]; i < allIDs.Size(); i++)
|
||||
{
|
||||
if (allIDs[i].tag == tag)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
FTagItem it = { line, tag, -1 };
|
||||
allIDs.Push(it);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FTagManager::HashTags()
|
||||
{
|
||||
// add an end marker so we do not need to check for the array's size in the other functions.
|
||||
static FTagItem it = { -1, -1, -1 };
|
||||
allTags.Push(it);
|
||||
allIDs.Push(it);
|
||||
|
||||
// Initially make all slots empty.
|
||||
memset(TagHashFirst, -1, sizeof(TagHashFirst));
|
||||
memset(IDHashFirst, -1, sizeof(IDHashFirst));
|
||||
|
||||
// Proceed from last to first so that lower targets appear first
|
||||
for (int i = allTags.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (allTags[i].target >= 0) // only link valid entries
|
||||
{
|
||||
int hash = ((unsigned int)allTags[i].tag) % FTagManager::TAG_HASH_SIZE;
|
||||
allTags[i].nexttag = TagHashFirst[hash];
|
||||
TagHashFirst[hash] = i;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = allIDs.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (allIDs[i].target >= 0) // only link valid entries
|
||||
{
|
||||
int hash = ((unsigned int)allIDs[i].tag) % FTagManager::TAG_HASH_SIZE;
|
||||
allIDs[i].nexttag = IDHashFirst[hash];
|
||||
IDHashFirst[hash] = i;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool FTagManager::SectorHasTags(const sector_t *sector) const
|
||||
{
|
||||
int i = sectindex(sector);
|
||||
return SectorHasTags(i);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int FTagManager::GetFirstSectorTag(const sector_t *sect) const
|
||||
{
|
||||
int i = sectindex(sect);
|
||||
return SectorHasTags(i) ? allTags[startForSector[i]].tag : 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool FTagManager::SectorHasTag(int i, int tag) const
|
||||
{
|
||||
if (SectorHasTags(i))
|
||||
{
|
||||
int ndx = startForSector[i];
|
||||
while (allTags[ndx].target == i)
|
||||
{
|
||||
if (allTags[ndx].tag == tag) return true;
|
||||
ndx++;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool FTagManager::SectorHasTag(const sector_t *sector, int tag) const
|
||||
{
|
||||
return SectorHasTag(sectindex(sector), tag);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool FTagManager::LineHasID(int i, int tag) const
|
||||
{
|
||||
if (LineHasIDs(i))
|
||||
{
|
||||
int ndx = startForLine[i];
|
||||
while (allIDs[ndx].target == i)
|
||||
{
|
||||
if (allIDs[ndx].tag == tag) return true;
|
||||
ndx++;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool FTagManager::LineHasID(const line_t *line, int tag) const
|
||||
{
|
||||
return LineHasID(lineindex(line), tag);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FTagManager::DumpTags()
|
||||
{
|
||||
for (unsigned i = 0; i < allTags.Size(); i++)
|
||||
{
|
||||
Printf("Sector %d, tag %d\n", allTags[i].target, allTags[i].tag);
|
||||
}
|
||||
for (unsigned i = 0; i < allIDs.Size(); i++)
|
||||
{
|
||||
Printf("Line %d, ID %d\n", allIDs[i].target, allIDs[i].tag);
|
||||
}
|
||||
}
|
||||
|
||||
CCMD(dumptags)
|
||||
{
|
||||
tagManager.DumpTags();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
|
||||
//
|
||||
// Find the next sector with a specified tag.
|
||||
// Rewritten by Lee Killough to use chained hashing to improve speed
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int FSectorTagIterator::Next()
|
||||
{
|
||||
int ret;
|
||||
if (searchtag == INT_MIN)
|
||||
{
|
||||
ret = start;
|
||||
start = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (start >= 0 && tagManager.allTags[start].tag != searchtag) start = tagManager.allTags[start].nexttag;
|
||||
if (start == -1) return -1;
|
||||
ret = tagManager.allTags[start].target;
|
||||
start = start = tagManager.allTags[start].nexttag;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// linear search for compatible stair building
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int FSectorTagIterator::NextCompat(bool compat, int start)
|
||||
{
|
||||
if (!compat) return Next();
|
||||
|
||||
for (int i = start + 1; i < numsectors; i++)
|
||||
{
|
||||
if (tagManager.SectorHasTag(i, searchtag)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// killough 4/16/98: Same thing, only for linedefs
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int FLineIdIterator::Next()
|
||||
{
|
||||
while (start >= 0 && tagManager.allIDs[start].tag != searchtag) start = tagManager.allIDs[start].nexttag;
|
||||
if (start == -1) return -1;
|
||||
int ret = tagManager.allIDs[start].target;
|
||||
start = start = tagManager.allIDs[start].nexttag;
|
||||
return ret;
|
||||
}
|
133
src/p_tags.h
Normal file
133
src/p_tags.h
Normal file
|
@ -0,0 +1,133 @@
|
|||
#ifndef P_TAGS_H
|
||||
#define P_TAGS_H 1
|
||||
|
||||
#include "r_defs.h"
|
||||
#include "r_state.h"
|
||||
|
||||
struct FTagItem
|
||||
{
|
||||
int target; // either sector or line
|
||||
int tag;
|
||||
int nexttag; // for hashing
|
||||
};
|
||||
|
||||
class FSectorTagIterator;
|
||||
class FLineIdIterator;
|
||||
|
||||
class FTagManager
|
||||
{
|
||||
enum
|
||||
{
|
||||
TAG_HASH_SIZE = 256
|
||||
};
|
||||
|
||||
friend class FSectorTagIterator;
|
||||
friend class FLineIdIterator;
|
||||
|
||||
TArray<FTagItem> allTags;
|
||||
TArray<FTagItem> allIDs;
|
||||
TArray<int> startForSector;
|
||||
TArray<int> startForLine;
|
||||
int TagHashFirst[TAG_HASH_SIZE];
|
||||
int IDHashFirst[TAG_HASH_SIZE];
|
||||
|
||||
bool SectorHasTags(int sect) const
|
||||
{
|
||||
return sect >= 0 && sect < (int)startForSector.Size() && startForSector[sect] >= 0;
|
||||
}
|
||||
|
||||
bool LineHasIDs(int sect) const
|
||||
{
|
||||
return sect >= 0 && sect < (int)startForLine.Size() && startForLine[sect] >= 0;
|
||||
}
|
||||
|
||||
public:
|
||||
void Clear()
|
||||
{
|
||||
allTags.Clear();
|
||||
allIDs.Clear();
|
||||
startForSector.Clear();
|
||||
startForLine.Clear();
|
||||
memset(TagHashFirst, -1, sizeof(TagHashFirst));
|
||||
}
|
||||
|
||||
bool SectorHasTags(const sector_t *sector) const;
|
||||
int GetFirstSectorTag(const sector_t *sect) const;
|
||||
bool SectorHasTag(int sector, int tag) const;
|
||||
bool SectorHasTag(const sector_t *sector, int tag) const;
|
||||
|
||||
bool LineHasID(int line, int id) const;
|
||||
bool LineHasID(const line_t *line, int id) const;
|
||||
|
||||
void HashTags();
|
||||
void AddSectorTag(int sector, int tag);
|
||||
void AddLineID(int line, int tag);
|
||||
void RemoveSectorTags(int sect);
|
||||
|
||||
void DumpTags();
|
||||
};
|
||||
|
||||
extern FTagManager tagManager;
|
||||
|
||||
class FSectorTagIterator
|
||||
{
|
||||
protected:
|
||||
int searchtag;
|
||||
int start;
|
||||
|
||||
public:
|
||||
FSectorTagIterator(int tag)
|
||||
{
|
||||
searchtag = tag;
|
||||
start = tagManager.TagHashFirst[((unsigned int)tag) % FTagManager::TAG_HASH_SIZE];
|
||||
}
|
||||
|
||||
// Special constructor for actions that treat tag 0 as 'back of activation line'
|
||||
FSectorTagIterator(int tag, line_t *line)
|
||||
{
|
||||
if (tag == 0)
|
||||
{
|
||||
searchtag = INT_MIN;
|
||||
start = (line == NULL || line->backsector == NULL)? -1 : (int)(line->backsector - sectors);
|
||||
}
|
||||
else
|
||||
{
|
||||
searchtag = tag;
|
||||
start = tagManager.TagHashFirst[((unsigned int)tag) % FTagManager::TAG_HASH_SIZE];
|
||||
}
|
||||
}
|
||||
|
||||
int Next();
|
||||
int NextCompat(bool compat, int secnum);
|
||||
};
|
||||
|
||||
class FLineIdIterator
|
||||
{
|
||||
protected:
|
||||
int searchtag;
|
||||
int start;
|
||||
|
||||
public:
|
||||
FLineIdIterator(int id)
|
||||
{
|
||||
searchtag = id;
|
||||
start = tagManager.IDHashFirst[((unsigned int)id) % FTagManager::TAG_HASH_SIZE];
|
||||
}
|
||||
|
||||
int Next();
|
||||
};
|
||||
|
||||
|
||||
inline int P_FindFirstSectorFromTag(int tag)
|
||||
{
|
||||
FSectorTagIterator it(tag);
|
||||
return it.Next();
|
||||
}
|
||||
|
||||
inline int P_FindFirstLineFromID(int tag)
|
||||
{
|
||||
FLineIdIterator it(tag);
|
||||
return it.Next();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -249,7 +249,7 @@ static AActor *SelectTeleDest (int tid, int tag, bool norandom)
|
|||
int count = 0;
|
||||
while ( (searcher = iterator.Next ()) )
|
||||
{
|
||||
if (tag == 0 || searcher->Sector->HasTag(tag))
|
||||
if (tag == 0 || tagManager.SectorHasTag(searcher->Sector, tag))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
@ -288,7 +288,7 @@ static AActor *SelectTeleDest (int tid, int tag, bool norandom)
|
|||
while (count > 0)
|
||||
{
|
||||
searcher = iterator.Next ();
|
||||
if (tag == 0 || searcher->Sector->HasTag(tag))
|
||||
if (tag == 0 || tagManager.SectorHasTag(searcher->Sector, tag))
|
||||
{
|
||||
count--;
|
||||
}
|
||||
|
|
|
@ -659,8 +659,12 @@ void InitClassMap(FClassMap &themap, SpawnMap &thedata)
|
|||
pair->Value.filename.GetChars(), pair->Value.linenum, pair->Value.classname.GetChars());
|
||||
error++;
|
||||
}
|
||||
themap.Insert(pair->Key, cls);
|
||||
}
|
||||
else
|
||||
{
|
||||
themap.Remove(pair->Key);
|
||||
}
|
||||
themap.Insert(pair->Key, cls);
|
||||
}
|
||||
if (error > 0)
|
||||
{
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "r_state.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "w_wad.h"
|
||||
#include "p_tags.h"
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
@ -754,7 +755,7 @@ public:
|
|||
mld.flags = 0;
|
||||
mld.special = th->special;
|
||||
mld.tag = th->args[0];
|
||||
P_TranslateLineDef(&ld, &mld, true);
|
||||
P_TranslateLineDef(&ld, &mld);
|
||||
th->special = ld.special;
|
||||
memcpy(th->args, ld.args, sizeof (ld.args));
|
||||
}
|
||||
|
@ -779,10 +780,10 @@ public:
|
|||
bool strifetrans2 = false;
|
||||
FString arg0str, arg1str;
|
||||
int lineid; // forZDoomTranslated namespace
|
||||
FString tagstring;
|
||||
|
||||
memset(ld, 0, sizeof(*ld));
|
||||
ld->Alpha = FRACUNIT;
|
||||
ld->ClearIds();
|
||||
ld->sidedef[0] = ld->sidedef[1] = NULL;
|
||||
if (level.flags2 & LEVEL2_CLIPMIDTEX) ld->flags |= ML_CLIP_MIDTEX;
|
||||
if (level.flags2 & LEVEL2_WRAPMIDTEX) ld->flags |= ML_WRAP_MIDTEX;
|
||||
|
@ -816,7 +817,7 @@ public:
|
|||
|
||||
case NAME_Id:
|
||||
lineid = CheckInt(key);
|
||||
ld->SetMainId(lineid);
|
||||
tagManager.AddLineID(index, lineid);
|
||||
continue;
|
||||
|
||||
case NAME_Sidefront:
|
||||
|
@ -1039,22 +1040,17 @@ public:
|
|||
Flag(ld->flags, ML_3DMIDTEX_IMPASS, key);
|
||||
continue;
|
||||
|
||||
case NAME_MoreIds:
|
||||
// delay parsing of the tag string until parsing of the sector is complete
|
||||
// This ensures that the ID is always the first tag in the list.
|
||||
tagstring = CheckString(key);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0 // for later
|
||||
if (namespace_bits & (Zd)) && !strnicmp(key.GetChars(), "Id", 2))
|
||||
{
|
||||
char *endp;
|
||||
int num = strtol(key.GetChars(), &endp, 10);
|
||||
if (num > 0 && *endp == NULL)
|
||||
{
|
||||
// only allow ID## with ## as a proper number
|
||||
ld->SetId((short)CheckInt(key), false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((namespace_bits & (Zd | Zdt)) && !strnicmp("user_", key.GetChars(), 5))
|
||||
{
|
||||
|
@ -1062,6 +1058,17 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
if (tagstring.IsNotEmpty())
|
||||
{
|
||||
FScanner sc;
|
||||
sc.OpenString("tagstring", tagstring);
|
||||
// scan the string as long as valid numbers can be found
|
||||
while (sc.CheckNumber())
|
||||
{
|
||||
if (sc.Number != 0) tagManager.AddLineID(index, sc.Number);
|
||||
}
|
||||
}
|
||||
|
||||
if (isTranslated)
|
||||
{
|
||||
int saved = ld->flags;
|
||||
|
@ -1070,7 +1077,7 @@ public:
|
|||
memset(&mld, 0, sizeof(mld));
|
||||
mld.special = ld->special;
|
||||
mld.tag = lineid;
|
||||
P_TranslateLineDef(ld, &mld, false);
|
||||
P_TranslateLineDef(ld, &mld);
|
||||
ld->flags = saved | (ld->flags&(ML_MONSTERSCANACTIVATE|ML_REPEAT_SPECIAL|ML_FIRSTSIDEONLY));
|
||||
}
|
||||
if (passuse && (ld->activation & SPAC_Use))
|
||||
|
@ -1269,6 +1276,7 @@ public:
|
|||
int desaturation = -1;
|
||||
int fplaneflags = 0, cplaneflags = 0;
|
||||
double fp[4] = { 0 }, cp[4] = { 0 };
|
||||
FString tagstring;
|
||||
|
||||
memset(sec, 0, sizeof(*sec));
|
||||
sec->lightlevel = 160;
|
||||
|
@ -1332,7 +1340,7 @@ public:
|
|||
continue;
|
||||
|
||||
case NAME_Id:
|
||||
sec->SetMainTag((short)CheckInt(key));
|
||||
tagManager.AddSectorTag(index, CheckInt(key));
|
||||
continue;
|
||||
|
||||
default:
|
||||
|
@ -1510,28 +1518,32 @@ public:
|
|||
cp[3] = CheckFloat(key);
|
||||
break;
|
||||
|
||||
case NAME_MoreIds:
|
||||
// delay parsing of the tag string until parsing of the sector is complete
|
||||
// This ensures that the ID is always the first tag in the list.
|
||||
tagstring = CheckString(key);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#if 0 // for later
|
||||
if (namespace_bits & (Zd)) && !strnicmp(key.GetChars(), "Id", 2))
|
||||
{
|
||||
char *endp;
|
||||
int num = strtol(key.GetChars(), &endp, 10);
|
||||
if (num > 0 && *endp == NULL)
|
||||
{
|
||||
// only allow ID## with ## as a proper number
|
||||
sec->SetTag((short)CheckInt(key), false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((namespace_bits & (Zd | Zdt)) && !strnicmp("user_", key.GetChars(), 5))
|
||||
{
|
||||
AddUserKey(key, UDMF_Sector, index);
|
||||
}
|
||||
}
|
||||
|
||||
if (tagstring.IsNotEmpty())
|
||||
{
|
||||
FScanner sc;
|
||||
sc.OpenString("tagstring", tagstring);
|
||||
// scan the string as long as valid numbers can be found
|
||||
while (sc.CheckNumber())
|
||||
{
|
||||
if (sc.Number != 0) tagManager.AddSectorTag(index, sc.Number);
|
||||
}
|
||||
}
|
||||
|
||||
sec->secretsector = !!(sec->special&SECRET_MASK);
|
||||
|
||||
// Reset the planes to their defaults if not all of the plane equation's parameters were found.
|
||||
|
|
|
@ -262,7 +262,7 @@ static int WriteSECTORS (FILE *file)
|
|||
uppercopy (ms.ceilingpic, GetTextureName (sectors[i].GetTexture(sector_t::ceiling)));
|
||||
ms.lightlevel = LittleShort((short)sectors[i].lightlevel);
|
||||
ms.special = LittleShort(sectors[i].special);
|
||||
ms.tag = LittleShort(sectors[i].GetMainTag());
|
||||
ms.tag = LittleShort(tagManager.GetFirstSectorTag(§ors[i]));
|
||||
fwrite (&ms, sizeof(ms), 1, file);
|
||||
}
|
||||
return numsectors * sizeof(ms);
|
||||
|
|
|
@ -60,7 +60,7 @@ typedef enum
|
|||
PushMany,
|
||||
} triggertype_e;
|
||||
|
||||
void P_TranslateLineDef (line_t *ld, maplinedef_t *mld, bool setid)
|
||||
void P_TranslateLineDef (line_t *ld, maplinedef_t *mld, int lineindexforid)
|
||||
{
|
||||
unsigned short special = (unsigned short) LittleShort(mld->special);
|
||||
short tag = LittleShort(mld->tag);
|
||||
|
@ -100,13 +100,13 @@ void P_TranslateLineDef (line_t *ld, maplinedef_t *mld, bool setid)
|
|||
}
|
||||
flags = newflags;
|
||||
|
||||
if (setid)
|
||||
if (lineindexforid >= 0)
|
||||
{
|
||||
// For purposes of maintaining BOOM compatibility, each
|
||||
// line also needs to have its ID set to the same as its tag.
|
||||
// An external conversion program would need to do this more
|
||||
// intelligently.
|
||||
ld->SetMainId(tag);
|
||||
tagManager.AddLineID(lineindexforid, tag);
|
||||
}
|
||||
|
||||
// 0 specials are never translated.
|
||||
|
@ -307,7 +307,7 @@ void P_TranslateTeleportThings ()
|
|||
|
||||
while ( (dest = iterator.Next()) )
|
||||
{
|
||||
if (!dest->Sector->HasTags())
|
||||
if (!tagManager.SectorHasTags(dest->Sector))
|
||||
{
|
||||
dest->tid = 1;
|
||||
dest->AddToHash ();
|
||||
|
|
18
src/r_defs.h
18
src/r_defs.h
|
@ -633,12 +633,6 @@ struct sector_t
|
|||
return pos == floor? floorplane:ceilingplane;
|
||||
}
|
||||
|
||||
bool HasTag(int checktag) const;
|
||||
bool HasTags() const;
|
||||
void SetMainTag(int tagnum);
|
||||
int GetMainTag() const;
|
||||
void ClearTags();
|
||||
static void HashTags();
|
||||
|
||||
bool PlaneMoving(int pos);
|
||||
|
||||
|
@ -657,12 +651,9 @@ struct sector_t
|
|||
TObjPtr<AActor> SoundTarget;
|
||||
|
||||
short special;
|
||||
short tag;
|
||||
short lightlevel;
|
||||
short seqType; // this sector's sound sequence
|
||||
|
||||
int nexttag,firsttag; // killough 1/30/98: improves searches for tags.
|
||||
|
||||
int sky;
|
||||
FNameNoInit SeqName; // Sound sequence name. Setting seqType non-negative will override this.
|
||||
|
||||
|
@ -897,21 +888,12 @@ struct line_t
|
|||
DWORD activation; // activation type
|
||||
int special;
|
||||
fixed_t Alpha; // <--- translucency (0=invisibile, FRACUNIT=opaque)
|
||||
int id; // <--- same as tag or set with Line_SetIdentification
|
||||
int args[5]; // <--- hexen-style arguments (expanded to ZDoom's full width)
|
||||
int firstid, nextid;
|
||||
side_t *sidedef[2];
|
||||
//DWORD sidenum[2]; // sidenum[1] will be NO_SIDE if one sided
|
||||
fixed_t bbox[4]; // bounding box, for the extent of the LineDef.
|
||||
sector_t *frontsector, *backsector;
|
||||
int validcount; // if == validcount, already checked
|
||||
int locknumber; // [Dusk] lock number for special
|
||||
|
||||
|
||||
void SetMainId(int newid);
|
||||
void ClearIds();
|
||||
bool HasId(int id) const;
|
||||
static void HashIds();
|
||||
};
|
||||
|
||||
// phares 3/14/98
|
||||
|
|
|
@ -1366,7 +1366,7 @@ static void S_AddSNDINFO (int lump)
|
|||
FName nm = sc.String;
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("timidity")) MidiDevices[nm] = MDEV_TIMIDITY;
|
||||
else if (sc.Compare("fmod")) MidiDevices[nm] = MDEV_FMOD;
|
||||
else if (sc.Compare("fmod") || sc.Compare("sndsys")) MidiDevices[nm] = MDEV_SNDSYS;
|
||||
else if (sc.Compare("standard")) MidiDevices[nm] = MDEV_MMAPI;
|
||||
else if (sc.Compare("opl")) MidiDevices[nm] = MDEV_OPL;
|
||||
else if (sc.Compare("default")) MidiDevices[nm] = MDEV_DEFAULT;
|
||||
|
|
157
src/s_sound.cpp
157
src/s_sound.cpp
|
@ -383,7 +383,7 @@ void S_Start ()
|
|||
{
|
||||
// kill all playing sounds at start of level (trust me - a good idea)
|
||||
S_StopAllChannels();
|
||||
|
||||
|
||||
// Check for local sound definitions. Only reload if they differ
|
||||
// from the previous ones.
|
||||
FString LocalSndInfo;
|
||||
|
@ -487,6 +487,11 @@ void S_PrecacheLevel ()
|
|||
{
|
||||
level.info->PrecacheSounds[i].MarkUsed();
|
||||
}
|
||||
// Don't unload sounds that are playing right now.
|
||||
for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan)
|
||||
{
|
||||
chan->SoundID.MarkUsed();
|
||||
}
|
||||
|
||||
for (i = 1; i < S_sfx.Size(); ++i)
|
||||
{
|
||||
|
@ -1311,52 +1316,35 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx)
|
|||
int size = Wads.LumpLength(sfx->lumpnum);
|
||||
if (size > 0)
|
||||
{
|
||||
BYTE *sfxdata;
|
||||
BYTE *sfxstart;
|
||||
FWadLump wlump = Wads.OpenLumpNum(sfx->lumpnum);
|
||||
sfxstart = sfxdata = new BYTE[size];
|
||||
BYTE *sfxdata = new BYTE[size];
|
||||
wlump.Read(sfxdata, size);
|
||||
SDWORD len = LittleLong(((SDWORD *)sfxdata)[1]);
|
||||
SDWORD dmxlen = LittleLong(((SDWORD *)sfxdata)[1]);
|
||||
|
||||
// If the sound is voc, use the custom loader.
|
||||
if (strncmp ((const char *)sfxstart, "Creative Voice File", 19) == 0)
|
||||
if (strncmp ((const char *)sfxdata, "Creative Voice File", 19) == 0)
|
||||
{
|
||||
sfx->data = GSnd->LoadSoundVoc(sfxstart, size);
|
||||
sfx->data = GSnd->LoadSoundVoc(sfxdata, size);
|
||||
}
|
||||
// If the sound is raw, just load it as such.
|
||||
// Otherwise, try the sound as DMX format.
|
||||
// If that fails, let FMOD try and figure it out.
|
||||
else if (sfx->bLoadRAW ||
|
||||
(((BYTE *)sfxdata)[0] == 3 && ((BYTE *)sfxdata)[1] == 0 && len <= size - 8))
|
||||
else if (sfx->bLoadRAW)
|
||||
{
|
||||
int frequency;
|
||||
|
||||
if (sfx->bLoadRAW)
|
||||
{
|
||||
len = Wads.LumpLength (sfx->lumpnum);
|
||||
frequency = sfx->RawRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
frequency = LittleShort(((WORD *)sfxdata)[1]);
|
||||
if (frequency == 0)
|
||||
{
|
||||
frequency = 11025;
|
||||
}
|
||||
sfxstart = sfxdata + 8;
|
||||
}
|
||||
sfx->data = GSnd->LoadSoundRaw(sfxstart, len, frequency, 1, 8, sfx->LoopStart);
|
||||
sfx->data = GSnd->LoadSoundRaw(sfxdata, size, sfx->RawRate, 1, 8, sfx->LoopStart);
|
||||
}
|
||||
// Otherwise, try the sound as DMX format.
|
||||
else if (((BYTE *)sfxdata)[0] == 3 && ((BYTE *)sfxdata)[1] == 0 && dmxlen <= size - 8)
|
||||
{
|
||||
int frequency = LittleShort(((WORD *)sfxdata)[1]);
|
||||
if (frequency == 0) frequency = 11025;
|
||||
sfx->data = GSnd->LoadSoundRaw(sfxdata+8, dmxlen, frequency, 1, 8, sfx->LoopStart);
|
||||
}
|
||||
// If that fails, let the sound system try and figure it out.
|
||||
else
|
||||
{
|
||||
len = Wads.LumpLength (sfx->lumpnum);
|
||||
sfx->data = GSnd->LoadSound(sfxstart, len);
|
||||
}
|
||||
|
||||
if (sfxdata != NULL)
|
||||
{
|
||||
delete[] sfxdata;
|
||||
sfx->data = GSnd->LoadSound(sfxdata, size);
|
||||
}
|
||||
|
||||
delete[] sfxdata;
|
||||
}
|
||||
|
||||
if (!sfx->data.isValid())
|
||||
|
@ -1925,29 +1913,32 @@ void S_UpdateSounds (AActor *listenactor)
|
|||
S_ActivatePlayList(false);
|
||||
}
|
||||
|
||||
// should never happen
|
||||
S_SetListener(listener, listenactor);
|
||||
|
||||
for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan)
|
||||
if (listenactor != NULL)
|
||||
{
|
||||
if ((chan->ChanFlags & (CHAN_EVICTED | CHAN_IS3D)) == CHAN_IS3D)
|
||||
// should never happen
|
||||
S_SetListener(listener, listenactor);
|
||||
|
||||
for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan)
|
||||
{
|
||||
CalcPosVel(chan, &pos, &vel);
|
||||
GSnd->UpdateSoundParams3D(&listener, chan, !!(chan->ChanFlags & CHAN_AREA), pos, vel);
|
||||
if ((chan->ChanFlags & (CHAN_EVICTED | CHAN_IS3D)) == CHAN_IS3D)
|
||||
{
|
||||
CalcPosVel(chan, &pos, &vel);
|
||||
GSnd->UpdateSoundParams3D(&listener, chan, !!(chan->ChanFlags & CHAN_AREA), pos, vel);
|
||||
}
|
||||
chan->ChanFlags &= ~CHAN_JUSTSTARTED;
|
||||
}
|
||||
chan->ChanFlags &= ~CHAN_JUSTSTARTED;
|
||||
}
|
||||
|
||||
SN_UpdateActiveSequences();
|
||||
SN_UpdateActiveSequences();
|
||||
|
||||
|
||||
GSnd->UpdateListener(&listener);
|
||||
GSnd->UpdateSounds();
|
||||
GSnd->UpdateListener(&listener);
|
||||
GSnd->UpdateSounds();
|
||||
|
||||
if (level.time >= RestartEvictionsAt)
|
||||
{
|
||||
RestartEvictionsAt = 0;
|
||||
S_RestoreEvictedChannels();
|
||||
if (level.time >= RestartEvictionsAt)
|
||||
{
|
||||
RestartEvictionsAt = 0;
|
||||
S_RestoreEvictedChannels();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2083,12 +2074,6 @@ void S_ChannelEnded(FISoundChannel *ichan)
|
|||
evicted = (pos < len);
|
||||
}
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
evicted = false;
|
||||
}
|
||||
*/
|
||||
if (!evicted)
|
||||
{
|
||||
S_ReturnChannel(schan);
|
||||
|
@ -2346,8 +2331,6 @@ bool S_StartMusic (const char *m_id)
|
|||
// specified, it will only be played if the specified CD is in a drive.
|
||||
//==========================================================================
|
||||
|
||||
TArray<BYTE> musiccache;
|
||||
|
||||
bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
|
||||
{
|
||||
if (!force && PlayList)
|
||||
|
@ -2427,7 +2410,7 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
|
|||
else
|
||||
{
|
||||
int lumpnum = -1;
|
||||
int offset = 0, length = 0;
|
||||
int length = 0;
|
||||
int device = MDEV_DEFAULT;
|
||||
MusInfo *handle = NULL;
|
||||
FName musicasname = musicname;
|
||||
|
@ -2448,6 +2431,7 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
|
|||
musicname += 7;
|
||||
}
|
||||
|
||||
FileReader *reader = NULL;
|
||||
if (!FileExists (musicname))
|
||||
{
|
||||
if ((lumpnum = Wads.CheckNumForFullName (musicname, true, ns_music)) == -1)
|
||||
|
@ -2470,34 +2454,22 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
|
|||
}
|
||||
if (handle == NULL)
|
||||
{
|
||||
if (!Wads.IsUncompressedFile(lumpnum))
|
||||
if (Wads.LumpLength (lumpnum) == 0)
|
||||
{
|
||||
// We must cache the music data and use it from memory.
|
||||
|
||||
// shut down old music before reallocating and overwriting the cache!
|
||||
S_StopMusic (true);
|
||||
|
||||
offset = -1; // this tells the low level code that the music
|
||||
// is being used from memory
|
||||
length = Wads.LumpLength (lumpnum);
|
||||
if (length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
musiccache.Resize(length);
|
||||
Wads.ReadLump(lumpnum, &musiccache[0]);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
reader = Wads.ReopenLumpNumNewFile(lumpnum);
|
||||
if (reader == NULL)
|
||||
{
|
||||
offset = Wads.GetLumpOffset (lumpnum);
|
||||
length = Wads.LumpLength (lumpnum);
|
||||
if (length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load an external file.
|
||||
reader = new FileReader(musicname);
|
||||
}
|
||||
|
||||
// shutdown old music
|
||||
S_StopMusic (true);
|
||||
|
@ -2509,6 +2481,7 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
|
|||
mus_playing.name = musicname;
|
||||
mus_playing.baseorder = order;
|
||||
LastSong = musicname;
|
||||
delete reader;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2516,16 +2489,11 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
|
|||
if (handle != NULL)
|
||||
{
|
||||
mus_playing.handle = handle;
|
||||
}
|
||||
else if (offset != -1)
|
||||
{
|
||||
mus_playing.handle = I_RegisterSong (lumpnum != -1 ?
|
||||
Wads.GetWadFullName (Wads.GetLumpFile (lumpnum)) :
|
||||
musicname, NULL, offset, length, device);
|
||||
delete reader;
|
||||
}
|
||||
else
|
||||
{
|
||||
mus_playing.handle = I_RegisterSong (NULL, &musiccache[0], -1, length, device);
|
||||
mus_playing.handle = I_RegisterSong (reader, device);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2623,6 +2591,17 @@ void S_StopMusic (bool force)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void S_UpdateMusic()
|
||||
{
|
||||
GSnd->UpdateMusic();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CCMD playsound
|
||||
|
|
|
@ -329,6 +329,7 @@ int S_GetMusic (char **name);
|
|||
|
||||
// Stops the music for sure.
|
||||
void S_StopMusic (bool force);
|
||||
void S_UpdateMusic();
|
||||
|
||||
// Stop and resume music, during game PAUSE.
|
||||
void S_PauseSound (bool notmusic, bool notsfx);
|
||||
|
@ -389,7 +390,7 @@ enum EMidiDevice
|
|||
MDEV_DEFAULT = -1,
|
||||
MDEV_MMAPI = 0,
|
||||
MDEV_OPL = 1,
|
||||
MDEV_FMOD = 2,
|
||||
MDEV_SNDSYS = 2,
|
||||
MDEV_TIMIDITY = 3,
|
||||
MDEV_FLUIDSYNTH = 4,
|
||||
MDEV_GUS = 5,
|
||||
|
|
|
@ -196,9 +196,22 @@ void FScanner::OpenFile (const char *name)
|
|||
//==========================================================================
|
||||
|
||||
void FScanner::OpenMem (const char *name, const char *buffer, int size)
|
||||
{
|
||||
OpenString(name, FString(buffer, size));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FScanner :: OpenString
|
||||
//
|
||||
// Like OpenMem, but takes a string directly.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::OpenString (const char *name, FString buffer)
|
||||
{
|
||||
Close ();
|
||||
ScriptBuffer = FString(buffer, size);
|
||||
ScriptBuffer = buffer;
|
||||
ScriptName = name;
|
||||
LumpNum = -1;
|
||||
PrepareScript ();
|
||||
|
|
|
@ -21,6 +21,7 @@ public:
|
|||
void Open(const char *lumpname);
|
||||
void OpenFile(const char *filename);
|
||||
void OpenMem(const char *name, const char *buffer, int size);
|
||||
void OpenString(const char *name, FString buffer);
|
||||
void OpenLumpNum(int lump);
|
||||
void Close();
|
||||
|
||||
|
|
758
src/sound/efx.h
Normal file
758
src/sound/efx.h
Normal file
|
@ -0,0 +1,758 @@
|
|||
#ifndef AL_EFX_H
|
||||
#define AL_EFX_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ALC_EXT_EFX_NAME "ALC_EXT_EFX"
|
||||
|
||||
#define ALC_EFX_MAJOR_VERSION 0x20001
|
||||
#define ALC_EFX_MINOR_VERSION 0x20002
|
||||
#define ALC_MAX_AUXILIARY_SENDS 0x20003
|
||||
|
||||
|
||||
/* Listener properties. */
|
||||
#define AL_METERS_PER_UNIT 0x20004
|
||||
|
||||
/* Source properties. */
|
||||
#define AL_DIRECT_FILTER 0x20005
|
||||
#define AL_AUXILIARY_SEND_FILTER 0x20006
|
||||
#define AL_AIR_ABSORPTION_FACTOR 0x20007
|
||||
#define AL_ROOM_ROLLOFF_FACTOR 0x20008
|
||||
#define AL_CONE_OUTER_GAINHF 0x20009
|
||||
#define AL_DIRECT_FILTER_GAINHF_AUTO 0x2000A
|
||||
#define AL_AUXILIARY_SEND_FILTER_GAIN_AUTO 0x2000B
|
||||
#define AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO 0x2000C
|
||||
|
||||
|
||||
/* Effect properties. */
|
||||
|
||||
/* Reverb effect parameters */
|
||||
#define AL_REVERB_DENSITY 0x0001
|
||||
#define AL_REVERB_DIFFUSION 0x0002
|
||||
#define AL_REVERB_GAIN 0x0003
|
||||
#define AL_REVERB_GAINHF 0x0004
|
||||
#define AL_REVERB_DECAY_TIME 0x0005
|
||||
#define AL_REVERB_DECAY_HFRATIO 0x0006
|
||||
#define AL_REVERB_REFLECTIONS_GAIN 0x0007
|
||||
#define AL_REVERB_REFLECTIONS_DELAY 0x0008
|
||||
#define AL_REVERB_LATE_REVERB_GAIN 0x0009
|
||||
#define AL_REVERB_LATE_REVERB_DELAY 0x000A
|
||||
#define AL_REVERB_AIR_ABSORPTION_GAINHF 0x000B
|
||||
#define AL_REVERB_ROOM_ROLLOFF_FACTOR 0x000C
|
||||
#define AL_REVERB_DECAY_HFLIMIT 0x000D
|
||||
|
||||
/* EAX Reverb effect parameters */
|
||||
#define AL_EAXREVERB_DENSITY 0x0001
|
||||
#define AL_EAXREVERB_DIFFUSION 0x0002
|
||||
#define AL_EAXREVERB_GAIN 0x0003
|
||||
#define AL_EAXREVERB_GAINHF 0x0004
|
||||
#define AL_EAXREVERB_GAINLF 0x0005
|
||||
#define AL_EAXREVERB_DECAY_TIME 0x0006
|
||||
#define AL_EAXREVERB_DECAY_HFRATIO 0x0007
|
||||
#define AL_EAXREVERB_DECAY_LFRATIO 0x0008
|
||||
#define AL_EAXREVERB_REFLECTIONS_GAIN 0x0009
|
||||
#define AL_EAXREVERB_REFLECTIONS_DELAY 0x000A
|
||||
#define AL_EAXREVERB_REFLECTIONS_PAN 0x000B
|
||||
#define AL_EAXREVERB_LATE_REVERB_GAIN 0x000C
|
||||
#define AL_EAXREVERB_LATE_REVERB_DELAY 0x000D
|
||||
#define AL_EAXREVERB_LATE_REVERB_PAN 0x000E
|
||||
#define AL_EAXREVERB_ECHO_TIME 0x000F
|
||||
#define AL_EAXREVERB_ECHO_DEPTH 0x0010
|
||||
#define AL_EAXREVERB_MODULATION_TIME 0x0011
|
||||
#define AL_EAXREVERB_MODULATION_DEPTH 0x0012
|
||||
#define AL_EAXREVERB_AIR_ABSORPTION_GAINHF 0x0013
|
||||
#define AL_EAXREVERB_HFREFERENCE 0x0014
|
||||
#define AL_EAXREVERB_LFREFERENCE 0x0015
|
||||
#define AL_EAXREVERB_ROOM_ROLLOFF_FACTOR 0x0016
|
||||
#define AL_EAXREVERB_DECAY_HFLIMIT 0x0017
|
||||
|
||||
/* Chorus effect parameters */
|
||||
#define AL_CHORUS_WAVEFORM 0x0001
|
||||
#define AL_CHORUS_PHASE 0x0002
|
||||
#define AL_CHORUS_RATE 0x0003
|
||||
#define AL_CHORUS_DEPTH 0x0004
|
||||
#define AL_CHORUS_FEEDBACK 0x0005
|
||||
#define AL_CHORUS_DELAY 0x0006
|
||||
|
||||
/* Distortion effect parameters */
|
||||
#define AL_DISTORTION_EDGE 0x0001
|
||||
#define AL_DISTORTION_GAIN 0x0002
|
||||
#define AL_DISTORTION_LOWPASS_CUTOFF 0x0003
|
||||
#define AL_DISTORTION_EQCENTER 0x0004
|
||||
#define AL_DISTORTION_EQBANDWIDTH 0x0005
|
||||
|
||||
/* Echo effect parameters */
|
||||
#define AL_ECHO_DELAY 0x0001
|
||||
#define AL_ECHO_LRDELAY 0x0002
|
||||
#define AL_ECHO_DAMPING 0x0003
|
||||
#define AL_ECHO_FEEDBACK 0x0004
|
||||
#define AL_ECHO_SPREAD 0x0005
|
||||
|
||||
/* Flanger effect parameters */
|
||||
#define AL_FLANGER_WAVEFORM 0x0001
|
||||
#define AL_FLANGER_PHASE 0x0002
|
||||
#define AL_FLANGER_RATE 0x0003
|
||||
#define AL_FLANGER_DEPTH 0x0004
|
||||
#define AL_FLANGER_FEEDBACK 0x0005
|
||||
#define AL_FLANGER_DELAY 0x0006
|
||||
|
||||
/* Frequency shifter effect parameters */
|
||||
#define AL_FREQUENCY_SHIFTER_FREQUENCY 0x0001
|
||||
#define AL_FREQUENCY_SHIFTER_LEFT_DIRECTION 0x0002
|
||||
#define AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION 0x0003
|
||||
|
||||
/* Vocal morpher effect parameters */
|
||||
#define AL_VOCAL_MORPHER_PHONEMEA 0x0001
|
||||
#define AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING 0x0002
|
||||
#define AL_VOCAL_MORPHER_PHONEMEB 0x0003
|
||||
#define AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING 0x0004
|
||||
#define AL_VOCAL_MORPHER_WAVEFORM 0x0005
|
||||
#define AL_VOCAL_MORPHER_RATE 0x0006
|
||||
|
||||
/* Pitchshifter effect parameters */
|
||||
#define AL_PITCH_SHIFTER_COARSE_TUNE 0x0001
|
||||
#define AL_PITCH_SHIFTER_FINE_TUNE 0x0002
|
||||
|
||||
/* Ringmodulator effect parameters */
|
||||
#define AL_RING_MODULATOR_FREQUENCY 0x0001
|
||||
#define AL_RING_MODULATOR_HIGHPASS_CUTOFF 0x0002
|
||||
#define AL_RING_MODULATOR_WAVEFORM 0x0003
|
||||
|
||||
/* Autowah effect parameters */
|
||||
#define AL_AUTOWAH_ATTACK_TIME 0x0001
|
||||
#define AL_AUTOWAH_RELEASE_TIME 0x0002
|
||||
#define AL_AUTOWAH_RESONANCE 0x0003
|
||||
#define AL_AUTOWAH_PEAK_GAIN 0x0004
|
||||
|
||||
/* Compressor effect parameters */
|
||||
#define AL_COMPRESSOR_ONOFF 0x0001
|
||||
|
||||
/* Equalizer effect parameters */
|
||||
#define AL_EQUALIZER_LOW_GAIN 0x0001
|
||||
#define AL_EQUALIZER_LOW_CUTOFF 0x0002
|
||||
#define AL_EQUALIZER_MID1_GAIN 0x0003
|
||||
#define AL_EQUALIZER_MID1_CENTER 0x0004
|
||||
#define AL_EQUALIZER_MID1_WIDTH 0x0005
|
||||
#define AL_EQUALIZER_MID2_GAIN 0x0006
|
||||
#define AL_EQUALIZER_MID2_CENTER 0x0007
|
||||
#define AL_EQUALIZER_MID2_WIDTH 0x0008
|
||||
#define AL_EQUALIZER_HIGH_GAIN 0x0009
|
||||
#define AL_EQUALIZER_HIGH_CUTOFF 0x000A
|
||||
|
||||
/* Effect type */
|
||||
#define AL_EFFECT_FIRST_PARAMETER 0x0000
|
||||
#define AL_EFFECT_LAST_PARAMETER 0x8000
|
||||
#define AL_EFFECT_TYPE 0x8001
|
||||
|
||||
/* Effect types, used with the AL_EFFECT_TYPE property */
|
||||
#define AL_EFFECT_NULL 0x0000
|
||||
#define AL_EFFECT_REVERB 0x0001
|
||||
#define AL_EFFECT_CHORUS 0x0002
|
||||
#define AL_EFFECT_DISTORTION 0x0003
|
||||
#define AL_EFFECT_ECHO 0x0004
|
||||
#define AL_EFFECT_FLANGER 0x0005
|
||||
#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006
|
||||
#define AL_EFFECT_VOCAL_MORPHER 0x0007
|
||||
#define AL_EFFECT_PITCH_SHIFTER 0x0008
|
||||
#define AL_EFFECT_RING_MODULATOR 0x0009
|
||||
#define AL_EFFECT_AUTOWAH 0x000A
|
||||
#define AL_EFFECT_COMPRESSOR 0x000B
|
||||
#define AL_EFFECT_EQUALIZER 0x000C
|
||||
#define AL_EFFECT_EAXREVERB 0x8000
|
||||
|
||||
/* Auxiliary Effect Slot properties. */
|
||||
#define AL_EFFECTSLOT_EFFECT 0x0001
|
||||
#define AL_EFFECTSLOT_GAIN 0x0002
|
||||
#define AL_EFFECTSLOT_AUXILIARY_SEND_AUTO 0x0003
|
||||
|
||||
/* NULL Auxiliary Slot ID to disable a source send. */
|
||||
#define AL_EFFECTSLOT_NULL 0x0000
|
||||
|
||||
|
||||
/* Filter properties. */
|
||||
|
||||
/* Lowpass filter parameters */
|
||||
#define AL_LOWPASS_GAIN 0x0001
|
||||
#define AL_LOWPASS_GAINHF 0x0002
|
||||
|
||||
/* Highpass filter parameters */
|
||||
#define AL_HIGHPASS_GAIN 0x0001
|
||||
#define AL_HIGHPASS_GAINLF 0x0002
|
||||
|
||||
/* Bandpass filter parameters */
|
||||
#define AL_BANDPASS_GAIN 0x0001
|
||||
#define AL_BANDPASS_GAINLF 0x0002
|
||||
#define AL_BANDPASS_GAINHF 0x0003
|
||||
|
||||
/* Filter type */
|
||||
#define AL_FILTER_FIRST_PARAMETER 0x0000
|
||||
#define AL_FILTER_LAST_PARAMETER 0x8000
|
||||
#define AL_FILTER_TYPE 0x8001
|
||||
|
||||
/* Filter types, used with the AL_FILTER_TYPE property */
|
||||
#define AL_FILTER_NULL 0x0000
|
||||
#define AL_FILTER_LOWPASS 0x0001
|
||||
#define AL_FILTER_HIGHPASS 0x0002
|
||||
#define AL_FILTER_BANDPASS 0x0003
|
||||
|
||||
|
||||
/* Effect object function types. */
|
||||
typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*);
|
||||
typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, ALuint*);
|
||||
typedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint);
|
||||
typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint);
|
||||
typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat);
|
||||
typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, ALfloat*);
|
||||
typedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*);
|
||||
typedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*);
|
||||
|
||||
/* Filter object function types. */
|
||||
typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*);
|
||||
typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, ALuint*);
|
||||
typedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint);
|
||||
typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint);
|
||||
typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat);
|
||||
typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, ALfloat*);
|
||||
typedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*);
|
||||
typedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*);
|
||||
|
||||
/* Auxiliary Effect Slot object function types. */
|
||||
typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*);
|
||||
typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*);
|
||||
typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint);
|
||||
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint);
|
||||
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat);
|
||||
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*);
|
||||
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*);
|
||||
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*);
|
||||
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects);
|
||||
AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, ALuint *effects);
|
||||
AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect);
|
||||
AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue);
|
||||
AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue);
|
||||
AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters);
|
||||
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters);
|
||||
AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter);
|
||||
AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue);
|
||||
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue);
|
||||
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
|
||||
AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
|
||||
AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot);
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue);
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue);
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);
|
||||
#endif
|
||||
|
||||
/* Filter ranges and defaults. */
|
||||
|
||||
/* Lowpass filter */
|
||||
#define LOWPASS_MIN_GAIN (0.0f)
|
||||
#define LOWPASS_MAX_GAIN (1.0f)
|
||||
#define LOWPASS_DEFAULT_GAIN (1.0f)
|
||||
|
||||
#define LOWPASS_MIN_GAINHF (0.0f)
|
||||
#define LOWPASS_MAX_GAINHF (1.0f)
|
||||
#define LOWPASS_DEFAULT_GAINHF (1.0f)
|
||||
|
||||
/* Highpass filter */
|
||||
#define HIGHPASS_MIN_GAIN (0.0f)
|
||||
#define HIGHPASS_MAX_GAIN (1.0f)
|
||||
#define HIGHPASS_DEFAULT_GAIN (1.0f)
|
||||
|
||||
#define HIGHPASS_MIN_GAINLF (0.0f)
|
||||
#define HIGHPASS_MAX_GAINLF (1.0f)
|
||||
#define HIGHPASS_DEFAULT_GAINLF (1.0f)
|
||||
|
||||
/* Bandpass filter */
|
||||
#define BANDPASS_MIN_GAIN (0.0f)
|
||||
#define BANDPASS_MAX_GAIN (1.0f)
|
||||
#define BANDPASS_DEFAULT_GAIN (1.0f)
|
||||
|
||||
#define BANDPASS_MIN_GAINHF (0.0f)
|
||||
#define BANDPASS_MAX_GAINHF (1.0f)
|
||||
#define BANDPASS_DEFAULT_GAINHF (1.0f)
|
||||
|
||||
#define BANDPASS_MIN_GAINLF (0.0f)
|
||||
#define BANDPASS_MAX_GAINLF (1.0f)
|
||||
#define BANDPASS_DEFAULT_GAINLF (1.0f)
|
||||
|
||||
|
||||
/* Effect parameter ranges and defaults. */
|
||||
|
||||
/* Standard reverb effect */
|
||||
#define AL_REVERB_MIN_DENSITY (0.0f)
|
||||
#define AL_REVERB_MAX_DENSITY (1.0f)
|
||||
#define AL_REVERB_DEFAULT_DENSITY (1.0f)
|
||||
|
||||
#define AL_REVERB_MIN_DIFFUSION (0.0f)
|
||||
#define AL_REVERB_MAX_DIFFUSION (1.0f)
|
||||
#define AL_REVERB_DEFAULT_DIFFUSION (1.0f)
|
||||
|
||||
#define AL_REVERB_MIN_GAIN (0.0f)
|
||||
#define AL_REVERB_MAX_GAIN (1.0f)
|
||||
#define AL_REVERB_DEFAULT_GAIN (0.32f)
|
||||
|
||||
#define AL_REVERB_MIN_GAINHF (0.0f)
|
||||
#define AL_REVERB_MAX_GAINHF (1.0f)
|
||||
#define AL_REVERB_DEFAULT_GAINHF (0.89f)
|
||||
|
||||
#define AL_REVERB_MIN_DECAY_TIME (0.1f)
|
||||
#define AL_REVERB_MAX_DECAY_TIME (20.0f)
|
||||
#define AL_REVERB_DEFAULT_DECAY_TIME (1.49f)
|
||||
|
||||
#define AL_REVERB_MIN_DECAY_HFRATIO (0.1f)
|
||||
#define AL_REVERB_MAX_DECAY_HFRATIO (2.0f)
|
||||
#define AL_REVERB_DEFAULT_DECAY_HFRATIO (0.83f)
|
||||
|
||||
#define AL_REVERB_MIN_REFLECTIONS_GAIN (0.0f)
|
||||
#define AL_REVERB_MAX_REFLECTIONS_GAIN (3.16f)
|
||||
#define AL_REVERB_DEFAULT_REFLECTIONS_GAIN (0.05f)
|
||||
|
||||
#define AL_REVERB_MIN_REFLECTIONS_DELAY (0.0f)
|
||||
#define AL_REVERB_MAX_REFLECTIONS_DELAY (0.3f)
|
||||
#define AL_REVERB_DEFAULT_REFLECTIONS_DELAY (0.007f)
|
||||
|
||||
#define AL_REVERB_MIN_LATE_REVERB_GAIN (0.0f)
|
||||
#define AL_REVERB_MAX_LATE_REVERB_GAIN (10.0f)
|
||||
#define AL_REVERB_DEFAULT_LATE_REVERB_GAIN (1.26f)
|
||||
|
||||
#define AL_REVERB_MIN_LATE_REVERB_DELAY (0.0f)
|
||||
#define AL_REVERB_MAX_LATE_REVERB_DELAY (0.1f)
|
||||
#define AL_REVERB_DEFAULT_LATE_REVERB_DELAY (0.011f)
|
||||
|
||||
#define AL_REVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f)
|
||||
#define AL_REVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f)
|
||||
#define AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f)
|
||||
|
||||
#define AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f)
|
||||
#define AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f)
|
||||
#define AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)
|
||||
|
||||
#define AL_REVERB_MIN_DECAY_HFLIMIT AL_FALSE
|
||||
#define AL_REVERB_MAX_DECAY_HFLIMIT AL_TRUE
|
||||
#define AL_REVERB_DEFAULT_DECAY_HFLIMIT AL_TRUE
|
||||
|
||||
/* EAX reverb effect */
|
||||
#define AL_EAXREVERB_MIN_DENSITY (0.0f)
|
||||
#define AL_EAXREVERB_MAX_DENSITY (1.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_DENSITY (1.0f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_DIFFUSION (0.0f)
|
||||
#define AL_EAXREVERB_MAX_DIFFUSION (1.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_DIFFUSION (1.0f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_GAIN (0.0f)
|
||||
#define AL_EAXREVERB_MAX_GAIN (1.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_GAIN (0.32f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_GAINHF (0.0f)
|
||||
#define AL_EAXREVERB_MAX_GAINHF (1.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_GAINHF (0.89f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_GAINLF (0.0f)
|
||||
#define AL_EAXREVERB_MAX_GAINLF (1.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_GAINLF (1.0f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_DECAY_TIME (0.1f)
|
||||
#define AL_EAXREVERB_MAX_DECAY_TIME (20.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_DECAY_TIME (1.49f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_DECAY_HFRATIO (0.1f)
|
||||
#define AL_EAXREVERB_MAX_DECAY_HFRATIO (2.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_DECAY_HFRATIO (0.83f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_DECAY_LFRATIO (0.1f)
|
||||
#define AL_EAXREVERB_MAX_DECAY_LFRATIO (2.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_DECAY_LFRATIO (1.0f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_REFLECTIONS_GAIN (0.0f)
|
||||
#define AL_EAXREVERB_MAX_REFLECTIONS_GAIN (3.16f)
|
||||
#define AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN (0.05f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_REFLECTIONS_DELAY (0.0f)
|
||||
#define AL_EAXREVERB_MAX_REFLECTIONS_DELAY (0.3f)
|
||||
#define AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY (0.007f)
|
||||
|
||||
#define AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ (0.0f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_LATE_REVERB_GAIN (0.0f)
|
||||
#define AL_EAXREVERB_MAX_LATE_REVERB_GAIN (10.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN (1.26f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_LATE_REVERB_DELAY (0.0f)
|
||||
#define AL_EAXREVERB_MAX_LATE_REVERB_DELAY (0.1f)
|
||||
#define AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY (0.011f)
|
||||
|
||||
#define AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ (0.0f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_ECHO_TIME (0.075f)
|
||||
#define AL_EAXREVERB_MAX_ECHO_TIME (0.25f)
|
||||
#define AL_EAXREVERB_DEFAULT_ECHO_TIME (0.25f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_ECHO_DEPTH (0.0f)
|
||||
#define AL_EAXREVERB_MAX_ECHO_DEPTH (1.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_ECHO_DEPTH (0.0f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_MODULATION_TIME (0.04f)
|
||||
#define AL_EAXREVERB_MAX_MODULATION_TIME (4.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_MODULATION_TIME (0.25f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_MODULATION_DEPTH (0.0f)
|
||||
#define AL_EAXREVERB_MAX_MODULATION_DEPTH (1.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_MODULATION_DEPTH (0.0f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f)
|
||||
#define AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_HFREFERENCE (1000.0f)
|
||||
#define AL_EAXREVERB_MAX_HFREFERENCE (20000.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_HFREFERENCE (5000.0f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_LFREFERENCE (20.0f)
|
||||
#define AL_EAXREVERB_MAX_LFREFERENCE (1000.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_LFREFERENCE (250.0f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f)
|
||||
#define AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)
|
||||
|
||||
#define AL_EAXREVERB_MIN_DECAY_HFLIMIT AL_FALSE
|
||||
#define AL_EAXREVERB_MAX_DECAY_HFLIMIT AL_TRUE
|
||||
#define AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT AL_TRUE
|
||||
|
||||
/* Chorus effect */
|
||||
#define AL_CHORUS_WAVEFORM_SINUSOID (0)
|
||||
#define AL_CHORUS_WAVEFORM_TRIANGLE (1)
|
||||
|
||||
#define AL_CHORUS_MIN_WAVEFORM (0)
|
||||
#define AL_CHORUS_MAX_WAVEFORM (1)
|
||||
#define AL_CHORUS_DEFAULT_WAVEFORM (1)
|
||||
|
||||
#define AL_CHORUS_MIN_PHASE (-180)
|
||||
#define AL_CHORUS_MAX_PHASE (180)
|
||||
#define AL_CHORUS_DEFAULT_PHASE (90)
|
||||
|
||||
#define AL_CHORUS_MIN_RATE (0.0f)
|
||||
#define AL_CHORUS_MAX_RATE (10.0f)
|
||||
#define AL_CHORUS_DEFAULT_RATE (1.1f)
|
||||
|
||||
#define AL_CHORUS_MIN_DEPTH (0.0f)
|
||||
#define AL_CHORUS_MAX_DEPTH (1.0f)
|
||||
#define AL_CHORUS_DEFAULT_DEPTH (0.1f)
|
||||
|
||||
#define AL_CHORUS_MIN_FEEDBACK (-1.0f)
|
||||
#define AL_CHORUS_MAX_FEEDBACK (1.0f)
|
||||
#define AL_CHORUS_DEFAULT_FEEDBACK (0.25f)
|
||||
|
||||
#define AL_CHORUS_MIN_DELAY (0.0f)
|
||||
#define AL_CHORUS_MAX_DELAY (0.016f)
|
||||
#define AL_CHORUS_DEFAULT_DELAY (0.016f)
|
||||
|
||||
/* Distortion effect */
|
||||
#define AL_DISTORTION_MIN_EDGE (0.0f)
|
||||
#define AL_DISTORTION_MAX_EDGE (1.0f)
|
||||
#define AL_DISTORTION_DEFAULT_EDGE (0.2f)
|
||||
|
||||
#define AL_DISTORTION_MIN_GAIN (0.01f)
|
||||
#define AL_DISTORTION_MAX_GAIN (1.0f)
|
||||
#define AL_DISTORTION_DEFAULT_GAIN (0.05f)
|
||||
|
||||
#define AL_DISTORTION_MIN_LOWPASS_CUTOFF (80.0f)
|
||||
#define AL_DISTORTION_MAX_LOWPASS_CUTOFF (24000.0f)
|
||||
#define AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF (8000.0f)
|
||||
|
||||
#define AL_DISTORTION_MIN_EQCENTER (80.0f)
|
||||
#define AL_DISTORTION_MAX_EQCENTER (24000.0f)
|
||||
#define AL_DISTORTION_DEFAULT_EQCENTER (3600.0f)
|
||||
|
||||
#define AL_DISTORTION_MIN_EQBANDWIDTH (80.0f)
|
||||
#define AL_DISTORTION_MAX_EQBANDWIDTH (24000.0f)
|
||||
#define AL_DISTORTION_DEFAULT_EQBANDWIDTH (3600.0f)
|
||||
|
||||
/* Echo effect */
|
||||
#define AL_ECHO_MIN_DELAY (0.0f)
|
||||
#define AL_ECHO_MAX_DELAY (0.207f)
|
||||
#define AL_ECHO_DEFAULT_DELAY (0.1f)
|
||||
|
||||
#define AL_ECHO_MIN_LRDELAY (0.0f)
|
||||
#define AL_ECHO_MAX_LRDELAY (0.404f)
|
||||
#define AL_ECHO_DEFAULT_LRDELAY (0.1f)
|
||||
|
||||
#define AL_ECHO_MIN_DAMPING (0.0f)
|
||||
#define AL_ECHO_MAX_DAMPING (0.99f)
|
||||
#define AL_ECHO_DEFAULT_DAMPING (0.5f)
|
||||
|
||||
#define AL_ECHO_MIN_FEEDBACK (0.0f)
|
||||
#define AL_ECHO_MAX_FEEDBACK (1.0f)
|
||||
#define AL_ECHO_DEFAULT_FEEDBACK (0.5f)
|
||||
|
||||
#define AL_ECHO_MIN_SPREAD (-1.0f)
|
||||
#define AL_ECHO_MAX_SPREAD (1.0f)
|
||||
#define AL_ECHO_DEFAULT_SPREAD (-1.0f)
|
||||
|
||||
/* Flanger effect */
|
||||
#define AL_FLANGER_WAVEFORM_SINUSOID (0)
|
||||
#define AL_FLANGER_WAVEFORM_TRIANGLE (1)
|
||||
|
||||
#define AL_FLANGER_MIN_WAVEFORM (0)
|
||||
#define AL_FLANGER_MAX_WAVEFORM (1)
|
||||
#define AL_FLANGER_DEFAULT_WAVEFORM (1)
|
||||
|
||||
#define AL_FLANGER_MIN_PHASE (-180)
|
||||
#define AL_FLANGER_MAX_PHASE (180)
|
||||
#define AL_FLANGER_DEFAULT_PHASE (0)
|
||||
|
||||
#define AL_FLANGER_MIN_RATE (0.0f)
|
||||
#define AL_FLANGER_MAX_RATE (10.0f)
|
||||
#define AL_FLANGER_DEFAULT_RATE (0.27f)
|
||||
|
||||
#define AL_FLANGER_MIN_DEPTH (0.0f)
|
||||
#define AL_FLANGER_MAX_DEPTH (1.0f)
|
||||
#define AL_FLANGER_DEFAULT_DEPTH (1.0f)
|
||||
|
||||
#define AL_FLANGER_MIN_FEEDBACK (-1.0f)
|
||||
#define AL_FLANGER_MAX_FEEDBACK (1.0f)
|
||||
#define AL_FLANGER_DEFAULT_FEEDBACK (-0.5f)
|
||||
|
||||
#define AL_FLANGER_MIN_DELAY (0.0f)
|
||||
#define AL_FLANGER_MAX_DELAY (0.004f)
|
||||
#define AL_FLANGER_DEFAULT_DELAY (0.002f)
|
||||
|
||||
/* Frequency shifter effect */
|
||||
#define AL_FREQUENCY_SHIFTER_MIN_FREQUENCY (0.0f)
|
||||
#define AL_FREQUENCY_SHIFTER_MAX_FREQUENCY (24000.0f)
|
||||
#define AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY (0.0f)
|
||||
|
||||
#define AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION (0)
|
||||
#define AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION (2)
|
||||
#define AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION (0)
|
||||
|
||||
#define AL_FREQUENCY_SHIFTER_DIRECTION_DOWN (0)
|
||||
#define AL_FREQUENCY_SHIFTER_DIRECTION_UP (1)
|
||||
#define AL_FREQUENCY_SHIFTER_DIRECTION_OFF (2)
|
||||
|
||||
#define AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION (0)
|
||||
#define AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION (2)
|
||||
#define AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION (0)
|
||||
|
||||
/* Vocal morpher effect */
|
||||
#define AL_VOCAL_MORPHER_MIN_PHONEMEA (0)
|
||||
#define AL_VOCAL_MORPHER_MAX_PHONEMEA (29)
|
||||
#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA (0)
|
||||
|
||||
#define AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING (-24)
|
||||
#define AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING (24)
|
||||
#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING (0)
|
||||
|
||||
#define AL_VOCAL_MORPHER_MIN_PHONEMEB (0)
|
||||
#define AL_VOCAL_MORPHER_MAX_PHONEMEB (29)
|
||||
#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB (10)
|
||||
|
||||
#define AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING (-24)
|
||||
#define AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING (24)
|
||||
#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING (0)
|
||||
|
||||
#define AL_VOCAL_MORPHER_PHONEME_A (0)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_E (1)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_I (2)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_O (3)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_U (4)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_AA (5)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_AE (6)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_AH (7)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_AO (8)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_EH (9)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_ER (10)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_IH (11)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_IY (12)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_UH (13)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_UW (14)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_B (15)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_D (16)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_F (17)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_G (18)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_J (19)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_K (20)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_L (21)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_M (22)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_N (23)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_P (24)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_R (25)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_S (26)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_T (27)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_V (28)
|
||||
#define AL_VOCAL_MORPHER_PHONEME_Z (29)
|
||||
|
||||
#define AL_VOCAL_MORPHER_WAVEFORM_SINUSOID (0)
|
||||
#define AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE (1)
|
||||
#define AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH (2)
|
||||
|
||||
#define AL_VOCAL_MORPHER_MIN_WAVEFORM (0)
|
||||
#define AL_VOCAL_MORPHER_MAX_WAVEFORM (2)
|
||||
#define AL_VOCAL_MORPHER_DEFAULT_WAVEFORM (0)
|
||||
|
||||
#define AL_VOCAL_MORPHER_MIN_RATE (0.0f)
|
||||
#define AL_VOCAL_MORPHER_MAX_RATE (10.0f)
|
||||
#define AL_VOCAL_MORPHER_DEFAULT_RATE (1.41f)
|
||||
|
||||
/* Pitch shifter effect */
|
||||
#define AL_PITCH_SHIFTER_MIN_COARSE_TUNE (-12)
|
||||
#define AL_PITCH_SHIFTER_MAX_COARSE_TUNE (12)
|
||||
#define AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE (12)
|
||||
|
||||
#define AL_PITCH_SHIFTER_MIN_FINE_TUNE (-50)
|
||||
#define AL_PITCH_SHIFTER_MAX_FINE_TUNE (50)
|
||||
#define AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE (0)
|
||||
|
||||
/* Ring modulator effect */
|
||||
#define AL_RING_MODULATOR_MIN_FREQUENCY (0.0f)
|
||||
#define AL_RING_MODULATOR_MAX_FREQUENCY (8000.0f)
|
||||
#define AL_RING_MODULATOR_DEFAULT_FREQUENCY (440.0f)
|
||||
|
||||
#define AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF (0.0f)
|
||||
#define AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF (24000.0f)
|
||||
#define AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF (800.0f)
|
||||
|
||||
#define AL_RING_MODULATOR_SINUSOID (0)
|
||||
#define AL_RING_MODULATOR_SAWTOOTH (1)
|
||||
#define AL_RING_MODULATOR_SQUARE (2)
|
||||
|
||||
#define AL_RING_MODULATOR_MIN_WAVEFORM (0)
|
||||
#define AL_RING_MODULATOR_MAX_WAVEFORM (2)
|
||||
#define AL_RING_MODULATOR_DEFAULT_WAVEFORM (0)
|
||||
|
||||
/* Autowah effect */
|
||||
#define AL_AUTOWAH_MIN_ATTACK_TIME (0.0001f)
|
||||
#define AL_AUTOWAH_MAX_ATTACK_TIME (1.0f)
|
||||
#define AL_AUTOWAH_DEFAULT_ATTACK_TIME (0.06f)
|
||||
|
||||
#define AL_AUTOWAH_MIN_RELEASE_TIME (0.0001f)
|
||||
#define AL_AUTOWAH_MAX_RELEASE_TIME (1.0f)
|
||||
#define AL_AUTOWAH_DEFAULT_RELEASE_TIME (0.06f)
|
||||
|
||||
#define AL_AUTOWAH_MIN_RESONANCE (2.0f)
|
||||
#define AL_AUTOWAH_MAX_RESONANCE (1000.0f)
|
||||
#define AL_AUTOWAH_DEFAULT_RESONANCE (1000.0f)
|
||||
|
||||
#define AL_AUTOWAH_MIN_PEAK_GAIN (0.00003f)
|
||||
#define AL_AUTOWAH_MAX_PEAK_GAIN (31621.0f)
|
||||
#define AL_AUTOWAH_DEFAULT_PEAK_GAIN (11.22f)
|
||||
|
||||
/* Compressor effect */
|
||||
#define AL_COMPRESSOR_MIN_ONOFF (0)
|
||||
#define AL_COMPRESSOR_MAX_ONOFF (1)
|
||||
#define AL_COMPRESSOR_DEFAULT_ONOFF (1)
|
||||
|
||||
/* Equalizer effect */
|
||||
#define AL_EQUALIZER_MIN_LOW_GAIN (0.126f)
|
||||
#define AL_EQUALIZER_MAX_LOW_GAIN (7.943f)
|
||||
#define AL_EQUALIZER_DEFAULT_LOW_GAIN (1.0f)
|
||||
|
||||
#define AL_EQUALIZER_MIN_LOW_CUTOFF (50.0f)
|
||||
#define AL_EQUALIZER_MAX_LOW_CUTOFF (800.0f)
|
||||
#define AL_EQUALIZER_DEFAULT_LOW_CUTOFF (200.0f)
|
||||
|
||||
#define AL_EQUALIZER_MIN_MID1_GAIN (0.126f)
|
||||
#define AL_EQUALIZER_MAX_MID1_GAIN (7.943f)
|
||||
#define AL_EQUALIZER_DEFAULT_MID1_GAIN (1.0f)
|
||||
|
||||
#define AL_EQUALIZER_MIN_MID1_CENTER (200.0f)
|
||||
#define AL_EQUALIZER_MAX_MID1_CENTER (3000.0f)
|
||||
#define AL_EQUALIZER_DEFAULT_MID1_CENTER (500.0f)
|
||||
|
||||
#define AL_EQUALIZER_MIN_MID1_WIDTH (0.01f)
|
||||
#define AL_EQUALIZER_MAX_MID1_WIDTH (1.0f)
|
||||
#define AL_EQUALIZER_DEFAULT_MID1_WIDTH (1.0f)
|
||||
|
||||
#define AL_EQUALIZER_MIN_MID2_GAIN (0.126f)
|
||||
#define AL_EQUALIZER_MAX_MID2_GAIN (7.943f)
|
||||
#define AL_EQUALIZER_DEFAULT_MID2_GAIN (1.0f)
|
||||
|
||||
#define AL_EQUALIZER_MIN_MID2_CENTER (1000.0f)
|
||||
#define AL_EQUALIZER_MAX_MID2_CENTER (8000.0f)
|
||||
#define AL_EQUALIZER_DEFAULT_MID2_CENTER (3000.0f)
|
||||
|
||||
#define AL_EQUALIZER_MIN_MID2_WIDTH (0.01f)
|
||||
#define AL_EQUALIZER_MAX_MID2_WIDTH (1.0f)
|
||||
#define AL_EQUALIZER_DEFAULT_MID2_WIDTH (1.0f)
|
||||
|
||||
#define AL_EQUALIZER_MIN_HIGH_GAIN (0.126f)
|
||||
#define AL_EQUALIZER_MAX_HIGH_GAIN (7.943f)
|
||||
#define AL_EQUALIZER_DEFAULT_HIGH_GAIN (1.0f)
|
||||
|
||||
#define AL_EQUALIZER_MIN_HIGH_CUTOFF (4000.0f)
|
||||
#define AL_EQUALIZER_MAX_HIGH_CUTOFF (16000.0f)
|
||||
#define AL_EQUALIZER_DEFAULT_HIGH_CUTOFF (6000.0f)
|
||||
|
||||
|
||||
/* Source parameter value ranges and defaults. */
|
||||
#define AL_MIN_AIR_ABSORPTION_FACTOR (0.0f)
|
||||
#define AL_MAX_AIR_ABSORPTION_FACTOR (10.0f)
|
||||
#define AL_DEFAULT_AIR_ABSORPTION_FACTOR (0.0f)
|
||||
|
||||
#define AL_MIN_ROOM_ROLLOFF_FACTOR (0.0f)
|
||||
#define AL_MAX_ROOM_ROLLOFF_FACTOR (10.0f)
|
||||
#define AL_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)
|
||||
|
||||
#define AL_MIN_CONE_OUTER_GAINHF (0.0f)
|
||||
#define AL_MAX_CONE_OUTER_GAINHF (1.0f)
|
||||
#define AL_DEFAULT_CONE_OUTER_GAINHF (1.0f)
|
||||
|
||||
#define AL_MIN_DIRECT_FILTER_GAINHF_AUTO AL_FALSE
|
||||
#define AL_MAX_DIRECT_FILTER_GAINHF_AUTO AL_TRUE
|
||||
#define AL_DEFAULT_DIRECT_FILTER_GAINHF_AUTO AL_TRUE
|
||||
|
||||
#define AL_MIN_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_FALSE
|
||||
#define AL_MAX_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE
|
||||
#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE
|
||||
|
||||
#define AL_MIN_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_FALSE
|
||||
#define AL_MAX_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE
|
||||
#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE
|
||||
|
||||
|
||||
/* Listener parameter value ranges and defaults. */
|
||||
#define AL_MIN_METERS_PER_UNIT FLT_MIN
|
||||
#define AL_MAX_METERS_PER_UNIT FLT_MAX
|
||||
#define AL_DEFAULT_METERS_PER_UNIT (1.0f)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* AL_EFX_H */
|
41
src/sound/except.h
Normal file
41
src/sound/except.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef __EXCEPT_H
|
||||
#define __EXCEPT_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
//==========================================================================
|
||||
//
|
||||
// CheckException
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
#ifndef FACILITY_VISUALCPP
|
||||
#define FACILITY_VISUALCPP ((LONG)0x6d)
|
||||
#endif
|
||||
#define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err)
|
||||
|
||||
inline int CheckException(DWORD code)
|
||||
{
|
||||
if (code == VcppException(ERROR_SEVERITY_ERROR,ERROR_MOD_NOT_FOUND) ||
|
||||
code == VcppException(ERROR_SEVERITY_ERROR,ERROR_PROC_NOT_FOUND))
|
||||
{
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __try
|
||||
#undef __try
|
||||
#endif
|
||||
#define __try
|
||||
|
||||
#ifdef __except
|
||||
#undef __except
|
||||
#endif
|
||||
#define __except(a) if (0)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -2,6 +2,8 @@
|
|||
#ifndef FMOD_WRAP_H
|
||||
#define FMOD_WRAP_H
|
||||
|
||||
#ifndef NO_FMOD
|
||||
|
||||
#if !defined(_WIN32) || defined(_MSC_VER)
|
||||
// Use the real C++ interface if it's supported on this platform.
|
||||
#include "fmod.hpp"
|
||||
|
@ -610,3 +612,4 @@ namespace FMOD
|
|||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -52,6 +52,7 @@ extern HWND Window;
|
|||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include "except.h"
|
||||
#include "templates.h"
|
||||
#include "fmodsound.h"
|
||||
#include "c_cvars.h"
|
||||
|
@ -62,6 +63,7 @@ extern HWND Window;
|
|||
#include "v_palette.h"
|
||||
#include "cmdlib.h"
|
||||
#include "s_sound.h"
|
||||
#include "files.h"
|
||||
|
||||
#if FMOD_VERSION > 0x42899 && FMOD_VERSION < 0x43400
|
||||
#error You are trying to compile with an unsupported version of FMOD.
|
||||
|
@ -79,6 +81,35 @@ extern HWND Window;
|
|||
|
||||
#define SPECTRUM_SIZE 256
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
ReverbContainer *ForcedEnvironment;
|
||||
|
||||
CVAR (Int, snd_driver, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Int, snd_buffercount, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, snd_hrtf, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, snd_waterreverb, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (String, snd_resampler, "Linear", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (String, snd_speakermode, "Auto", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (String, snd_output_format, "PCM-16", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (String, snd_midipatchset, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, snd_profile, false, 0)
|
||||
|
||||
// Underwater low-pass filter cutoff frequency. Set to 0 to disable the filter.
|
||||
CUSTOM_CVAR (Float, snd_waterlp, 250, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
{
|
||||
// Clamp to the DSP unit's limits.
|
||||
if (*self < 10 && *self != 0)
|
||||
{
|
||||
self = 10;
|
||||
}
|
||||
else if (*self > 22000)
|
||||
{
|
||||
self = 22000;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_FMOD
|
||||
#if FMOD_VERSION < 0x43400
|
||||
#define FMOD_OPENSTATE_PLAYING FMOD_OPENSTATE_STREAMING
|
||||
#endif
|
||||
|
@ -112,34 +143,6 @@ EXTERN_CVAR (Int, snd_channels)
|
|||
|
||||
extern int sfx_empty;
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
ReverbContainer *ForcedEnvironment;
|
||||
|
||||
CVAR (Int, snd_driver, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Int, snd_buffercount, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, snd_hrtf, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, snd_waterreverb, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (String, snd_resampler, "Linear", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (String, snd_speakermode, "Auto", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (String, snd_output_format, "PCM-16", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, snd_profile, false, 0)
|
||||
CVAR (String, snd_midipatchset, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
||||
|
||||
// Underwater low-pass filter cutoff frequency. Set to 0 to disable the filter.
|
||||
CUSTOM_CVAR (Float, snd_waterlp, 250, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
{
|
||||
// Clamp to the DSP unit's limits.
|
||||
if (*self < 10 && *self != 0)
|
||||
{
|
||||
self = 10;
|
||||
}
|
||||
else if (*self > 22000)
|
||||
{
|
||||
self = 22000;
|
||||
}
|
||||
}
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
static const ReverbContainer *PrevEnvironment;
|
||||
|
@ -165,9 +168,6 @@ static const FEnumList OutputNames[] =
|
|||
{ "Windows Multimedia", FMOD_OUTPUTTYPE_WINMM },
|
||||
{ "WinMM", FMOD_OUTPUTTYPE_WINMM },
|
||||
{ "WaveOut", FMOD_OUTPUTTYPE_WINMM },
|
||||
#if FMOD_VERSION < 0x43400
|
||||
{ "OpenAL", FMOD_OUTPUTTYPE_OPENAL },
|
||||
#endif
|
||||
{ "WASAPI", FMOD_OUTPUTTYPE_WASAPI },
|
||||
{ "ASIO", FMOD_OUTPUTTYPE_ASIO },
|
||||
|
||||
|
@ -182,9 +182,6 @@ static const FEnumList OutputNames[] =
|
|||
{ "SDL", 666 },
|
||||
|
||||
// Mac
|
||||
#if FMOD_VERSION < 0x43000
|
||||
{ "Sound Manager", FMOD_OUTPUTTYPE_SOUNDMANAGER },
|
||||
#endif
|
||||
{ "Core Audio", FMOD_OUTPUTTYPE_COREAUDIO },
|
||||
|
||||
{ NULL, 0 }
|
||||
|
@ -307,14 +304,21 @@ class FMODStreamCapsule : public SoundStream
|
|||
public:
|
||||
FMODStreamCapsule(FMOD::Sound *stream, FMODSoundRenderer *owner, const char *url)
|
||||
: Owner(owner), Stream(NULL), Channel(NULL),
|
||||
UserData(NULL), Callback(NULL), URL(url), Ended(false)
|
||||
UserData(NULL), Callback(NULL), URL(url), Reader(NULL), Ended(false)
|
||||
{
|
||||
SetStream(stream);
|
||||
}
|
||||
|
||||
FMODStreamCapsule(FMOD::Sound *stream, FMODSoundRenderer *owner, FileReader *reader)
|
||||
: Owner(owner), Stream(NULL), Channel(NULL),
|
||||
UserData(NULL), Callback(NULL), Reader(reader), Ended(false)
|
||||
{
|
||||
SetStream(stream);
|
||||
}
|
||||
|
||||
FMODStreamCapsule(void *udata, SoundStreamCallback callback, FMODSoundRenderer *owner)
|
||||
: Owner(owner), Stream(NULL), Channel(NULL),
|
||||
UserData(udata), Callback(callback), Ended(false)
|
||||
UserData(udata), Callback(callback), Reader(NULL), Ended(false)
|
||||
{}
|
||||
|
||||
~FMODStreamCapsule()
|
||||
|
@ -327,6 +331,10 @@ public:
|
|||
{
|
||||
Stream->release();
|
||||
}
|
||||
if (Reader != NULL)
|
||||
{
|
||||
delete Reader;
|
||||
}
|
||||
}
|
||||
|
||||
void SetStream(FMOD::Sound *stream)
|
||||
|
@ -596,6 +604,7 @@ private:
|
|||
FMOD::Channel *Channel;
|
||||
void *UserData;
|
||||
SoundStreamCallback Callback;
|
||||
FileReader *Reader;
|
||||
FString URL;
|
||||
bool Ended;
|
||||
bool JustStarted;
|
||||
|
@ -625,30 +634,6 @@ bool FMODSoundRenderer::IsValid()
|
|||
return InitSuccess;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
//==========================================================================
|
||||
//
|
||||
// CheckException
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
#ifndef FACILITY_VISUALCPP
|
||||
#define FACILITY_VISUALCPP ((LONG)0x6d)
|
||||
#endif
|
||||
#define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err)
|
||||
|
||||
static int CheckException(DWORD code)
|
||||
{
|
||||
if (code == VcppException(ERROR_SEVERITY_ERROR,ERROR_MOD_NOT_FOUND) ||
|
||||
code == VcppException(ERROR_SEVERITY_ERROR,ERROR_PROC_NOT_FOUND))
|
||||
{
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMODSoundRenderer :: Init
|
||||
|
@ -686,14 +671,8 @@ bool FMODSoundRenderer::Init()
|
|||
|
||||
Printf("I_InitSound: Initializing FMOD\n");
|
||||
|
||||
// Create a System object and initialize.
|
||||
#ifdef _MSC_VER
|
||||
__try {
|
||||
#endif
|
||||
result = FMOD::System_Create(&Sys);
|
||||
#ifdef _MSC_VER
|
||||
}
|
||||
__except(CheckException(GetExceptionCode()))
|
||||
// This is just for safety. Normally this should never be called if FMod Ex cannot be found.
|
||||
if (!IsFModExPresent())
|
||||
{
|
||||
Sys = NULL;
|
||||
Printf(TEXTCOLOR_ORANGE"Failed to load fmodex"
|
||||
|
@ -703,7 +682,9 @@ bool FMODSoundRenderer::Init()
|
|||
".dll\n");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create a System object and initialize.
|
||||
result = FMOD::System_Create(&Sys);
|
||||
if (result != FMOD_OK)
|
||||
{
|
||||
Sys = NULL;
|
||||
|
@ -895,6 +876,15 @@ bool FMODSoundRenderer::Init()
|
|||
// Set software format
|
||||
eval = Enum_NumForName(SoundFormatNames, snd_output_format);
|
||||
format = eval >= 0 ? FMOD_SOUND_FORMAT(eval) : FMOD_SOUND_FORMAT_PCM16;
|
||||
if (format == FMOD_SOUND_FORMAT_PCM8)
|
||||
{
|
||||
// PCM-8 sounds like garbage with anything but DirectSound.
|
||||
FMOD_OUTPUTTYPE output;
|
||||
if (FMOD_OK != Sys->getOutput(&output) || output != FMOD_OUTPUTTYPE_DSOUND)
|
||||
{
|
||||
format = FMOD_SOUND_FORMAT_PCM16;
|
||||
}
|
||||
}
|
||||
eval = Enum_NumForName(ResamplerNames, snd_resampler);
|
||||
resampler = eval >= 0 ? FMOD_DSP_RESAMPLER(eval) : FMOD_DSP_RESAMPLER_LINEAR;
|
||||
// These represented the frequency limits for hardware channels, which we never used anyway.
|
||||
|
@ -1601,83 +1591,171 @@ static void SetCustomLoopPts(FMOD::Sound *sound)
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMODSoundRenderer :: OpenStream
|
||||
// open_reader_callback
|
||||
// close_reader_callback
|
||||
// read_reader_callback
|
||||
// seek_reader_callback
|
||||
//
|
||||
// Creates a streaming sound from a file on disk.
|
||||
// FMOD_CREATESOUNDEXINFO callbacks to handle reading resource data from a
|
||||
// FileReader.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
SoundStream *FMODSoundRenderer::OpenStream(const char *filename_or_data, int flags, int offset, int length)
|
||||
static FMOD_RESULT F_CALLBACK open_reader_callback(const char *name, int unicode, unsigned int *filesize, void **handle, void **userdata)
|
||||
{
|
||||
FMOD_MODE mode;
|
||||
FMOD_CREATESOUNDEXINFO exinfo;
|
||||
FMOD::Sound *stream;
|
||||
FMOD_RESULT result;
|
||||
bool url;
|
||||
FString patches;
|
||||
FileReader *reader = NULL;
|
||||
if(sscanf(name, "_FileReader_%p", &reader) != 1)
|
||||
{
|
||||
Printf("Invalid name in callback: %s\n", name);
|
||||
return FMOD_ERR_FILE_NOTFOUND;
|
||||
}
|
||||
|
||||
InitCreateSoundExInfo(&exinfo);
|
||||
mode = FMOD_SOFTWARE | FMOD_2D | FMOD_CREATESTREAM;
|
||||
if (flags & SoundStream::Loop)
|
||||
{
|
||||
mode |= FMOD_LOOP_NORMAL;
|
||||
}
|
||||
if (offset == -1)
|
||||
{
|
||||
mode |= FMOD_OPENMEMORY;
|
||||
offset = 0;
|
||||
}
|
||||
exinfo.length = length;
|
||||
exinfo.fileoffset = offset;
|
||||
if ((*snd_midipatchset)[0] != '\0')
|
||||
{
|
||||
*filesize = reader->GetLength();
|
||||
*handle = reader;
|
||||
*userdata = reader;
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
static FMOD_RESULT F_CALLBACK close_reader_callback(void *handle, void *userdata)
|
||||
{
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
static FMOD_RESULT F_CALLBACK read_reader_callback(void *handle, void *buffer, unsigned int sizebytes, unsigned int *bytesread, void *userdata)
|
||||
{
|
||||
FileReader *reader = reinterpret_cast<FileReader*>(handle);
|
||||
*bytesread = reader->Read(buffer, sizebytes);
|
||||
if(*bytesread > 0) return FMOD_OK;
|
||||
return FMOD_ERR_FILE_EOF;
|
||||
}
|
||||
|
||||
static FMOD_RESULT F_CALLBACK seek_reader_callback(void *handle, unsigned int pos, void *userdata)
|
||||
{
|
||||
FileReader *reader = reinterpret_cast<FileReader*>(handle);
|
||||
if(reader->Seek(pos, SEEK_SET) == 0)
|
||||
return FMOD_OK;
|
||||
return FMOD_ERR_FILE_COULDNOTSEEK;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMODSoundRenderer :: OpenStream
|
||||
//
|
||||
// Creates a streaming sound from a FileReader.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
SoundStream *FMODSoundRenderer::OpenStream(FileReader *reader, int flags)
|
||||
{
|
||||
FMOD_MODE mode;
|
||||
FMOD_CREATESOUNDEXINFO exinfo;
|
||||
FMOD::Sound *stream;
|
||||
FMOD_RESULT result;
|
||||
FString patches;
|
||||
FString name;
|
||||
|
||||
InitCreateSoundExInfo(&exinfo);
|
||||
exinfo.useropen = open_reader_callback;
|
||||
exinfo.userclose = close_reader_callback;
|
||||
exinfo.userread = read_reader_callback;
|
||||
exinfo.userseek = seek_reader_callback;
|
||||
|
||||
mode = FMOD_SOFTWARE | FMOD_2D | FMOD_CREATESTREAM;
|
||||
if(flags & SoundStream::Loop)
|
||||
mode |= FMOD_LOOP_NORMAL;
|
||||
if((*snd_midipatchset)[0] != '\0')
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// If the path does not contain any path separators, automatically
|
||||
// prepend $PROGDIR to the path.
|
||||
if (strcspn(snd_midipatchset, ":/\\") == strlen(snd_midipatchset))
|
||||
{
|
||||
patches << "$PROGDIR/" << snd_midipatchset;
|
||||
patches = NicePath(patches);
|
||||
}
|
||||
else
|
||||
// If the path does not contain any path separators, automatically
|
||||
// prepend $PROGDIR to the path.
|
||||
if (strcspn(snd_midipatchset, ":/\\") == strlen(snd_midipatchset))
|
||||
{
|
||||
patches << "$PROGDIR/" << snd_midipatchset;
|
||||
patches = NicePath(patches);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
patches = NicePath(snd_midipatchset);
|
||||
}
|
||||
exinfo.dlsname = patches;
|
||||
}
|
||||
{
|
||||
patches = NicePath(snd_midipatchset);
|
||||
}
|
||||
exinfo.dlsname = patches;
|
||||
}
|
||||
|
||||
url = (offset == 0 && length == 0 && strstr(filename_or_data, "://") > filename_or_data);
|
||||
if (url)
|
||||
{
|
||||
// Use a larger buffer for URLs so that it's less likely to be effected
|
||||
// by hiccups in the data rate from the remote server.
|
||||
Sys->setStreamBufferSize(64*1024, FMOD_TIMEUNIT_RAWBYTES);
|
||||
}
|
||||
result = Sys->createSound(filename_or_data, mode, &exinfo, &stream);
|
||||
if (url)
|
||||
{
|
||||
// Restore standard buffer size.
|
||||
Sys->setStreamBufferSize(16*1024, FMOD_TIMEUNIT_RAWBYTES);
|
||||
}
|
||||
if (result == FMOD_ERR_FORMAT && exinfo.dlsname != NULL)
|
||||
{
|
||||
// FMOD_ERR_FORMAT could refer to either the main sound file or
|
||||
// to the DLS instrument set. Try again without special DLS
|
||||
// instruments to see if that lets it succeed.
|
||||
exinfo.dlsname = NULL;
|
||||
result = Sys->createSound(filename_or_data, mode, &exinfo, &stream);
|
||||
if (result == FMOD_OK)
|
||||
{
|
||||
Printf("%s is an unsupported format.\n", *snd_midipatchset);
|
||||
}
|
||||
}
|
||||
if (result == FMOD_OK)
|
||||
{
|
||||
SetCustomLoopPts(stream);
|
||||
return new FMODStreamCapsule(stream, this, url ? filename_or_data : NULL);
|
||||
}
|
||||
return NULL;
|
||||
name.Format("_FileReader_%p", reader);
|
||||
result = Sys->createSound(name, mode, &exinfo, &stream);
|
||||
if(result == FMOD_ERR_FORMAT && exinfo.dlsname != NULL)
|
||||
{
|
||||
// FMOD_ERR_FORMAT could refer to either the main sound file or
|
||||
// to the DLS instrument set. Try again without special DLS
|
||||
// instruments to see if that lets it succeed.
|
||||
exinfo.dlsname = NULL;
|
||||
result = Sys->createSound(name, mode, &exinfo, &stream);
|
||||
if (result == FMOD_OK)
|
||||
{
|
||||
Printf("%s is an unsupported format.\n", *snd_midipatchset);
|
||||
}
|
||||
}
|
||||
if(result != FMOD_OK)
|
||||
return NULL;
|
||||
|
||||
SetCustomLoopPts(stream);
|
||||
return new FMODStreamCapsule(stream, this, reader);
|
||||
}
|
||||
|
||||
SoundStream *FMODSoundRenderer::OpenStream(const char *url, int flags)
|
||||
{
|
||||
FMOD_MODE mode;
|
||||
FMOD_CREATESOUNDEXINFO exinfo;
|
||||
FMOD::Sound *stream;
|
||||
FMOD_RESULT result;
|
||||
FString patches;
|
||||
|
||||
InitCreateSoundExInfo(&exinfo);
|
||||
mode = FMOD_SOFTWARE | FMOD_2D | FMOD_CREATESTREAM;
|
||||
if(flags & SoundStream::Loop)
|
||||
mode |= FMOD_LOOP_NORMAL;
|
||||
if((*snd_midipatchset)[0] != '\0')
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// If the path does not contain any path separators, automatically
|
||||
// prepend $PROGDIR to the path.
|
||||
if (strcspn(snd_midipatchset, ":/\\") == strlen(snd_midipatchset))
|
||||
{
|
||||
patches << "$PROGDIR/" << snd_midipatchset;
|
||||
patches = NicePath(patches);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
patches = NicePath(snd_midipatchset);
|
||||
}
|
||||
exinfo.dlsname = patches;
|
||||
}
|
||||
|
||||
// Use a larger buffer for URLs so that it's less likely to be effected
|
||||
// by hiccups in the data rate from the remote server.
|
||||
Sys->setStreamBufferSize(64*1024, FMOD_TIMEUNIT_RAWBYTES);
|
||||
|
||||
result = Sys->createSound(url, mode, &exinfo, &stream);
|
||||
if(result == FMOD_ERR_FORMAT && exinfo.dlsname != NULL)
|
||||
{
|
||||
exinfo.dlsname = NULL;
|
||||
result = Sys->createSound(url, mode, &exinfo, &stream);
|
||||
if(result == FMOD_OK)
|
||||
{
|
||||
Printf("%s is an unsupported format.\n", *snd_midipatchset);
|
||||
}
|
||||
}
|
||||
|
||||
// Restore standard buffer size.
|
||||
Sys->setStreamBufferSize(16*1024, FMOD_TIMEUNIT_RAWBYTES);
|
||||
|
||||
if(result != FMOD_OK)
|
||||
return NULL;
|
||||
|
||||
SetCustomLoopPts(stream);
|
||||
return new FMODStreamCapsule(stream, this, url);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -2047,7 +2125,7 @@ FISoundChannel *FMODSoundRenderer::CommonChannelSetup(FMOD::Channel *chan, FISou
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMODSoundRenderer :: StopSound
|
||||
// FMODSoundRenderer :: StopChannel
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
|
@ -2055,7 +2133,10 @@ void FMODSoundRenderer::StopChannel(FISoundChannel *chan)
|
|||
{
|
||||
if (chan != NULL && chan->SysChannel != NULL)
|
||||
{
|
||||
((FMOD::Channel *)chan->SysChannel)->stop();
|
||||
if (((FMOD::Channel *)chan->SysChannel)->stop() == FMOD_ERR_INVALID_HANDLE)
|
||||
{ // The channel handle was invalid; pretend it ended.
|
||||
S_ChannelEnded(chan);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3092,3 +3173,45 @@ FMOD_RESULT FMODSoundRenderer::SetSystemReverbProperties(const REVERB_PROPERTIES
|
|||
#endif
|
||||
}
|
||||
|
||||
#endif // NO_FMOD
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// IsFModExPresent
|
||||
//
|
||||
// Check if FMod can be used
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool IsFModExPresent()
|
||||
{
|
||||
#ifdef NO_FMOD
|
||||
return false;
|
||||
#elif !defined _WIN32
|
||||
return true; // on non-Windows we cannot delay load the library so it has to be present.
|
||||
#else
|
||||
static bool cached_result;
|
||||
static bool done = false;
|
||||
|
||||
if (!done)
|
||||
{
|
||||
done = true;
|
||||
|
||||
FMOD::System *Sys;
|
||||
FMOD_RESULT result;
|
||||
__try
|
||||
{
|
||||
result = FMOD::System_Create(&Sys);
|
||||
}
|
||||
__except (CheckException(GetExceptionCode()))
|
||||
{
|
||||
// FMod could not be delay loaded
|
||||
return false;
|
||||
}
|
||||
if (result == FMOD_OK) Sys->release();
|
||||
cached_result = true;
|
||||
}
|
||||
return cached_result;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#define FMODSOUND_H
|
||||
|
||||
#include "i_sound.h"
|
||||
|
||||
#ifndef NO_FMOD
|
||||
#include "fmod_wrap.h"
|
||||
|
||||
class FMODSoundRenderer : public SoundRenderer
|
||||
|
@ -22,9 +24,8 @@ public:
|
|||
|
||||
// Streaming sounds.
|
||||
SoundStream *CreateStream (SoundStreamCallback callback, int buffsamples, int flags, int samplerate, void *userdata);
|
||||
SoundStream *OpenStream (const char *filename, int flags, int offset, int length);
|
||||
long PlayStream (SoundStream *stream, int volume);
|
||||
void StopStream (SoundStream *stream);
|
||||
SoundStream *OpenStream (FileReader *reader, int flags);
|
||||
SoundStream *OpenStream (const char *url, int flags);
|
||||
|
||||
// Starts a sound.
|
||||
FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan);
|
||||
|
@ -126,3 +127,4 @@ private:
|
|||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -99,7 +99,7 @@ EXTERN_CVAR (Int, snd_mididevice)
|
|||
|
||||
static bool MusicDown = true;
|
||||
|
||||
static BYTE *ungzip(BYTE *data, int *size);
|
||||
static bool ungzip(BYTE *data, int size, TArray<BYTE> &newdata);
|
||||
|
||||
MusInfo *currSong;
|
||||
int nomusic = 0;
|
||||
|
@ -301,21 +301,21 @@ MusInfo *MusInfo::GetWaveDumper(const char *filename, int rate)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static MIDIStreamer *CreateMIDIStreamer(FILE *file, BYTE *musiccache, int len, EMidiDevice devtype, EMIDIType miditype)
|
||||
static MIDIStreamer *CreateMIDIStreamer(FileReader &reader, EMidiDevice devtype, EMIDIType miditype)
|
||||
{
|
||||
switch (miditype)
|
||||
{
|
||||
case MIDI_MUS:
|
||||
return new MUSSong2(file, musiccache, len, devtype);
|
||||
return new MUSSong2(reader, devtype);
|
||||
|
||||
case MIDI_MIDI:
|
||||
return new MIDISong2(file, musiccache, len, devtype);
|
||||
return new MIDISong2(reader, devtype);
|
||||
|
||||
case MIDI_HMI:
|
||||
return new HMISong(file, musiccache, len, devtype);
|
||||
return new HMISong(reader, devtype);
|
||||
|
||||
case MIDI_XMI:
|
||||
return new XMISong(file, musiccache, len, devtype);
|
||||
return new XMISong(reader, devtype);
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
|
@ -377,100 +377,61 @@ static EMIDIType IdentifyMIDIType(DWORD *id, int size)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int len, int device)
|
||||
MusInfo *I_RegisterSong (FileReader *reader, int device)
|
||||
{
|
||||
FILE *file;
|
||||
MusInfo *info = NULL;
|
||||
const char *fmt;
|
||||
DWORD id[32/4];
|
||||
BYTE *ungzipped;
|
||||
int i;
|
||||
|
||||
if (nomusic)
|
||||
{
|
||||
delete reader;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (offset != -1)
|
||||
if(reader->Read(id, 32) != 32 || reader->Seek(-32, SEEK_CUR) != 0)
|
||||
{
|
||||
file = fopen (filename, "rb");
|
||||
if (file == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (len == 0 && offset == 0)
|
||||
{
|
||||
fseek (file, 0, SEEK_END);
|
||||
len = ftell (file);
|
||||
fseek (file, 0, SEEK_SET);
|
||||
}
|
||||
else
|
||||
{
|
||||
fseek (file, offset, SEEK_SET);
|
||||
}
|
||||
if (len < 32)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (fread (id, 4, 32/4, file) != 32/4)
|
||||
{
|
||||
fclose (file);
|
||||
return 0;
|
||||
}
|
||||
fseek (file, -32, SEEK_CUR);
|
||||
}
|
||||
else
|
||||
{
|
||||
file = NULL;
|
||||
if (len < 32)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < 32/4; ++i)
|
||||
{
|
||||
id[i] = ((DWORD *)musiccache)[i];
|
||||
}
|
||||
delete reader;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
// non-Windows platforms don't support MDEV_MMAPI so map to MDEV_FMOD
|
||||
// non-Windows platforms don't support MDEV_MMAPI so map to MDEV_SNDSYS
|
||||
if (device == MDEV_MMAPI)
|
||||
device = MDEV_FMOD;
|
||||
device = MDEV_SNDSYS;
|
||||
#endif
|
||||
|
||||
// Check for gzip compression. Some formats are expected to have players
|
||||
// that can handle it, so it simplifies things if we make all songs
|
||||
// gzippable.
|
||||
ungzipped = NULL;
|
||||
if ((id[0] & MAKE_ID(255,255,255,0)) == GZIP_ID)
|
||||
// Check for gzip compression. Some formats are expected to have players
|
||||
// that can handle it, so it simplifies things if we make all songs
|
||||
// gzippable.
|
||||
if ((id[0] & MAKE_ID(255, 255, 255, 0)) == GZIP_ID)
|
||||
{
|
||||
if (offset != -1)
|
||||
int len = reader->GetLength();
|
||||
BYTE *gzipped = new BYTE[len];
|
||||
if (reader->Read(gzipped, len) != len)
|
||||
{
|
||||
BYTE *gzipped = new BYTE[len];
|
||||
if (fread(gzipped, 1, len, file) != (size_t)len)
|
||||
{
|
||||
delete[] gzipped;
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
ungzipped = ungzip(gzipped, &len);
|
||||
delete[] gzipped;
|
||||
}
|
||||
else
|
||||
{
|
||||
ungzipped = ungzip(musiccache, &len);
|
||||
}
|
||||
if (ungzipped == NULL)
|
||||
{
|
||||
fclose(file);
|
||||
delete reader;
|
||||
return NULL;
|
||||
}
|
||||
musiccache = ungzipped;
|
||||
for (i = 0; i < 32/4; ++i)
|
||||
delete reader;
|
||||
|
||||
MemoryArrayReader *memreader = new MemoryArrayReader(NULL, 0);
|
||||
if (!ungzip(gzipped, len, memreader->GetArray()))
|
||||
{
|
||||
id[i] = ((DWORD *)musiccache)[i];
|
||||
delete[] gzipped;
|
||||
delete memreader;
|
||||
return 0;
|
||||
}
|
||||
delete[] gzipped;
|
||||
memreader->UpdateLength();
|
||||
|
||||
if (memreader->Read(id, 32) != 32 || memreader->Seek(-32, SEEK_CUR) != 0)
|
||||
{
|
||||
delete memreader;
|
||||
return 0;
|
||||
}
|
||||
reader = memreader;
|
||||
}
|
||||
|
||||
EMIDIType miditype = IdentifyMIDIType(id, sizeof(id));
|
||||
|
@ -478,22 +439,22 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
|
|||
{
|
||||
EMidiDevice devtype = (EMidiDevice)device;
|
||||
|
||||
retry_as_fmod:
|
||||
info = CreateMIDIStreamer(file, musiccache, len, devtype, miditype);
|
||||
retry_as_sndsys:
|
||||
info = CreateMIDIStreamer(*reader, devtype, miditype);
|
||||
if (info != NULL && !info->IsValid())
|
||||
{
|
||||
delete info;
|
||||
info = NULL;
|
||||
}
|
||||
if (info == NULL && devtype != MDEV_FMOD && snd_mididevice < 0)
|
||||
if (info == NULL && devtype != MDEV_SNDSYS && snd_mididevice < 0)
|
||||
{
|
||||
devtype = MDEV_FMOD;
|
||||
goto retry_as_fmod;
|
||||
devtype = MDEV_SNDSYS;
|
||||
goto retry_as_sndsys;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
if (info == NULL && devtype != MDEV_MMAPI && snd_mididevice >= 0)
|
||||
{
|
||||
info = CreateMIDIStreamer(file, musiccache, len, MDEV_MMAPI, miditype);
|
||||
info = CreateMIDIStreamer(*reader, MDEV_MMAPI, miditype);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -504,74 +465,62 @@ retry_as_fmod:
|
|||
(id[0] == MAKE_ID('D','B','R','A') && id[1] == MAKE_ID('W','O','P','L')) || // DosBox Raw OPL
|
||||
(id[0] == MAKE_ID('A','D','L','I') && *((BYTE *)id + 4) == 'B')) // Martin Fernandez's modified IMF
|
||||
{
|
||||
info = new OPLMUSSong (file, musiccache, len);
|
||||
info = new OPLMUSSong (*reader);
|
||||
}
|
||||
// Check for game music
|
||||
else if ((fmt = GME_CheckFormat(id[0])) != NULL && fmt[0] != '\0')
|
||||
{
|
||||
info = GME_OpenSong(file, musiccache, len, fmt);
|
||||
info = GME_OpenSong(*reader, fmt);
|
||||
}
|
||||
// Check for module formats
|
||||
else
|
||||
{
|
||||
info = MOD_OpenSong(file, musiccache, len);
|
||||
info = MOD_OpenSong(*reader);
|
||||
}
|
||||
|
||||
if (info == NULL)
|
||||
{
|
||||
// Check for CDDA "format"
|
||||
if (id[0] == (('R')|(('I')<<8)|(('F')<<16)|(('F')<<24)))
|
||||
{
|
||||
if (file != NULL)
|
||||
{
|
||||
DWORD subid;
|
||||
if (info == NULL)
|
||||
{
|
||||
// Check for CDDA "format"
|
||||
if (id[0] == (('R')|(('I')<<8)|(('F')<<16)|(('F')<<24)))
|
||||
{
|
||||
DWORD subid;
|
||||
|
||||
fseek (file, 8, SEEK_CUR);
|
||||
if (fread (&subid, 4, 1, file) != 1)
|
||||
{
|
||||
fclose (file);
|
||||
return 0;
|
||||
}
|
||||
fseek (file, -12, SEEK_CUR);
|
||||
reader->Seek(8, SEEK_CUR);
|
||||
if (reader->Read (&subid, 4) != 4)
|
||||
{
|
||||
delete reader;
|
||||
return 0;
|
||||
}
|
||||
reader->Seek(-12, SEEK_CUR);
|
||||
|
||||
if (subid == (('C')|(('D')<<8)|(('D')<<16)|(('A')<<24)))
|
||||
{
|
||||
// This is a CDDA file
|
||||
info = new CDDAFile (file, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (subid == (('C')|(('D')<<8)|(('D')<<16)|(('A')<<24)))
|
||||
{
|
||||
// This is a CDDA file
|
||||
info = new CDDAFile (*reader);
|
||||
}
|
||||
}
|
||||
|
||||
// no FMOD => no modules/streams
|
||||
// 1024 bytes is an arbitrary restriction. It's assumed that anything
|
||||
// smaller than this can't possibly be a valid music file if it hasn't
|
||||
// been identified already, so don't even bother trying to load it.
|
||||
// Of course MIDIs shorter than 1024 bytes should pass.
|
||||
if (info == NULL && (len >= 1024 || id[0] == MAKE_ID('M','T','h','d')))
|
||||
{
|
||||
// Let FMOD figure out what it is.
|
||||
if (file != NULL)
|
||||
{
|
||||
fclose (file);
|
||||
file = NULL;
|
||||
}
|
||||
info = new StreamSong (offset >= 0 ? filename : (const char *)musiccache, offset, len);
|
||||
}
|
||||
}
|
||||
// no support in sound system => no modules/streams
|
||||
// 1024 bytes is an arbitrary restriction. It's assumed that anything
|
||||
// smaller than this can't possibly be a valid music file if it hasn't
|
||||
// been identified already, so don't even bother trying to load it.
|
||||
// Of course MIDIs shorter than 1024 bytes should pass.
|
||||
if (info == NULL && (reader->GetLength() >= 1024 || id[0] == MAKE_ID('M','T','h','d')))
|
||||
{
|
||||
// Let the sound system figure out what it is.
|
||||
info = new StreamSong (reader);
|
||||
// Assumed ownership
|
||||
reader = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (reader != NULL) delete reader;
|
||||
|
||||
if (info && !info->IsValid ())
|
||||
{
|
||||
delete info;
|
||||
info = NULL;
|
||||
}
|
||||
if (file != NULL)
|
||||
{
|
||||
fclose (file);
|
||||
}
|
||||
if (ungzipped != NULL)
|
||||
{
|
||||
delete[] ungzipped;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
@ -605,7 +554,7 @@ MusInfo *I_RegisterURLSong (const char *url)
|
|||
{
|
||||
StreamSong *song;
|
||||
|
||||
song = new StreamSong(url, 0, 0);
|
||||
song = new StreamSong(url);
|
||||
if (song->IsValid())
|
||||
{
|
||||
return song;
|
||||
|
@ -623,13 +572,12 @@ MusInfo *I_RegisterURLSong (const char *url)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
BYTE *ungzip(BYTE *data, int *complen)
|
||||
static bool ungzip(BYTE *data, int complen, TArray<BYTE> &newdata)
|
||||
{
|
||||
const BYTE *max = data + *complen - 8;
|
||||
const BYTE *max = data + complen - 8;
|
||||
const BYTE *compstart = data + 10;
|
||||
BYTE flags = data[3];
|
||||
unsigned isize;
|
||||
BYTE *newdata;
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
|
@ -658,16 +606,16 @@ BYTE *ungzip(BYTE *data, int *complen)
|
|||
}
|
||||
if (compstart >= max - 1)
|
||||
{
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decompress
|
||||
isize = LittleLong(*(DWORD *)(data + *complen - 4));
|
||||
newdata = new BYTE[isize];
|
||||
isize = LittleLong(*(DWORD *)(data + complen - 4));
|
||||
newdata.Resize(isize);
|
||||
|
||||
stream.next_in = (Bytef *)compstart;
|
||||
stream.avail_in = (uInt)(max - compstart);
|
||||
stream.next_out = newdata;
|
||||
stream.next_out = &newdata[0];
|
||||
stream.avail_out = isize;
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
|
@ -675,25 +623,20 @@ BYTE *ungzip(BYTE *data, int *complen)
|
|||
err = inflateInit2(&stream, -MAX_WBITS);
|
||||
if (err != Z_OK)
|
||||
{
|
||||
delete[] newdata;
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END)
|
||||
{
|
||||
inflateEnd(&stream);
|
||||
delete[] newdata;
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
err = inflateEnd(&stream);
|
||||
if (err != Z_OK)
|
||||
{
|
||||
delete[] newdata;
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
*complen = isize;
|
||||
return newdata;
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -52,7 +52,7 @@ void I_SetMusicVolume (float volume);
|
|||
|
||||
// Registers a song handle to song data.
|
||||
class MusInfo;
|
||||
MusInfo *I_RegisterSong (const char *file, BYTE *musiccache, int offset, int length, int device);
|
||||
MusInfo *I_RegisterSong (FileReader *reader, int device);
|
||||
MusInfo *I_RegisterCDSong (int track, int cdid = 0);
|
||||
MusInfo *I_RegisterURLSong (const char *url);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "i_sound.h"
|
||||
#include "i_music.h"
|
||||
#include "s_sound.h"
|
||||
#include "files.h"
|
||||
|
||||
void I_InitMusicWin32 ();
|
||||
void I_ShutdownMusicWin32 ();
|
||||
|
@ -168,16 +169,16 @@ protected:
|
|||
bool bLooping;
|
||||
};
|
||||
|
||||
// FMOD pseudo-MIDI device --------------------------------------------------
|
||||
// Sound System pseudo-MIDI device ------------------------------------------
|
||||
|
||||
class FMODMIDIDevice : public PseudoMIDIDevice
|
||||
class SndSysMIDIDevice : public PseudoMIDIDevice
|
||||
{
|
||||
public:
|
||||
int Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata);
|
||||
bool Preprocess(MIDIStreamer *song, bool looping);
|
||||
};
|
||||
|
||||
// MIDI file played with TiMidity++ and possibly streamed through FMOD ------
|
||||
// MIDI file played with TiMidity++ and possibly streamed through the Sound System
|
||||
|
||||
class TimidityPPMIDIDevice : public PseudoMIDIDevice
|
||||
{
|
||||
|
@ -500,7 +501,7 @@ protected:
|
|||
class MUSSong2 : public MIDIStreamer
|
||||
{
|
||||
public:
|
||||
MUSSong2(FILE *file, BYTE *musiccache, int length, EMidiDevice type);
|
||||
MUSSong2(FileReader &reader, EMidiDevice type);
|
||||
~MUSSong2();
|
||||
|
||||
MusInfo *GetOPLDumper(const char *filename);
|
||||
|
@ -526,7 +527,7 @@ protected:
|
|||
class MIDISong2 : public MIDIStreamer
|
||||
{
|
||||
public:
|
||||
MIDISong2(FILE *file, BYTE *musiccache, int length, EMidiDevice type);
|
||||
MIDISong2(FileReader &reader, EMidiDevice type);
|
||||
~MIDISong2();
|
||||
|
||||
MusInfo *GetOPLDumper(const char *filename);
|
||||
|
@ -583,7 +584,7 @@ protected:
|
|||
class HMISong : public MIDIStreamer
|
||||
{
|
||||
public:
|
||||
HMISong(FILE *file, BYTE *musiccache, int length, EMidiDevice type);
|
||||
HMISong(FileReader &reader, EMidiDevice type);
|
||||
~HMISong();
|
||||
|
||||
MusInfo *GetOPLDumper(const char *filename);
|
||||
|
@ -626,7 +627,7 @@ protected:
|
|||
class XMISong : public MIDIStreamer
|
||||
{
|
||||
public:
|
||||
XMISong(FILE *file, BYTE *musiccache, int length, EMidiDevice type);
|
||||
XMISong(FileReader &reader, EMidiDevice type);
|
||||
~XMISong();
|
||||
|
||||
MusInfo *GetOPLDumper(const char *filename);
|
||||
|
@ -660,12 +661,13 @@ protected:
|
|||
EventSource EventDue;
|
||||
};
|
||||
|
||||
// Anything supported by FMOD out of the box --------------------------------
|
||||
// Anything supported by the sound system out of the box --------------------
|
||||
|
||||
class StreamSong : public MusInfo
|
||||
{
|
||||
public:
|
||||
StreamSong (const char *file, int offset, int length);
|
||||
StreamSong (FileReader *reader);
|
||||
StreamSong (const char *url);
|
||||
~StreamSong ();
|
||||
void Play (bool looping, int subsong);
|
||||
void Pause ();
|
||||
|
@ -683,12 +685,12 @@ protected:
|
|||
SoundStream *m_Stream;
|
||||
};
|
||||
|
||||
// MUS file played by a software OPL2 synth and streamed through FMOD -------
|
||||
// MUS file played by a software OPL2 synth and streamed through the sound system
|
||||
|
||||
class OPLMUSSong : public StreamSong
|
||||
{
|
||||
public:
|
||||
OPLMUSSong (FILE *file, BYTE *musiccache, int length);
|
||||
OPLMUSSong (FileReader &reader);
|
||||
~OPLMUSSong ();
|
||||
void Play (bool looping, int subsong);
|
||||
bool IsPlaying ();
|
||||
|
@ -737,17 +739,17 @@ protected:
|
|||
class CDDAFile : public CDSong
|
||||
{
|
||||
public:
|
||||
CDDAFile (FILE *file, int length);
|
||||
CDDAFile (FileReader &reader);
|
||||
};
|
||||
|
||||
// Module played via foo_dumb -----------------------------------------------
|
||||
|
||||
MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int len);
|
||||
MusInfo *MOD_OpenSong(FileReader &reader);
|
||||
|
||||
// Music played via Game Music Emu ------------------------------------------
|
||||
|
||||
const char *GME_CheckFormat(uint32 header);
|
||||
MusInfo *GME_OpenSong(FILE *file, BYTE *musiccache, int len, const char *fmt);
|
||||
MusInfo *GME_OpenSong(FileReader &reader, const char *fmt);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -52,7 +52,12 @@ extern HINSTANCE g_hInst;
|
|||
#include "doomtype.h"
|
||||
#include <math.h>
|
||||
|
||||
#include "except.h"
|
||||
#include "fmodsound.h"
|
||||
#include "oalsound.h"
|
||||
|
||||
#include "mpg123_decoder.h"
|
||||
#include "sndfile_decoder.h"
|
||||
|
||||
#include "m_swap.h"
|
||||
#include "stats.h"
|
||||
|
@ -77,6 +82,16 @@ CVAR (Int, snd_samplerate, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|||
CVAR (Int, snd_buffersize, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (String, snd_output, "default", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
|
||||
#ifndef NO_FMOD
|
||||
#define DEF_BACKEND "fmod"
|
||||
#elif !defined(NO_OPENAL)
|
||||
#define DEF_BACKEND "openal"
|
||||
#else
|
||||
#define DEF_BACKEND "null"
|
||||
#endif
|
||||
|
||||
CVAR(String, snd_backend, DEF_BACKEND, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
// killough 2/21/98: optionally use varying pitched sounds
|
||||
CVAR (Bool, snd_pitched, false, CVAR_ARCHIVE)
|
||||
|
||||
|
@ -159,8 +174,9 @@ public:
|
|||
{
|
||||
return NULL;
|
||||
}
|
||||
SoundStream *OpenStream (const char *filename, int flags, int offset, int length)
|
||||
SoundStream *OpenStream (FileReader *reader, int flags)
|
||||
{
|
||||
delete reader;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -242,6 +258,7 @@ void I_InitSound ()
|
|||
nosound = !!Args->CheckParm ("-nosound");
|
||||
nosfx = !!Args->CheckParm ("-nosfx");
|
||||
|
||||
GSnd = NULL;
|
||||
if (nosound)
|
||||
{
|
||||
GSnd = new NullSoundRenderer;
|
||||
|
@ -249,9 +266,51 @@ void I_InitSound ()
|
|||
return;
|
||||
}
|
||||
|
||||
GSnd = new FMODSoundRenderer;
|
||||
|
||||
if (!GSnd->IsValid ())
|
||||
// This has been extended to allow falling back from FMod to OpenAL and vice versa if the currently active sound system cannot be found.
|
||||
if (stricmp(snd_backend, "null") == 0)
|
||||
{
|
||||
GSnd = new NullSoundRenderer;
|
||||
}
|
||||
else if(stricmp(snd_backend, "fmod") == 0)
|
||||
{
|
||||
#ifndef NO_FMOD
|
||||
if (IsFModExPresent())
|
||||
{
|
||||
GSnd = new FMODSoundRenderer;
|
||||
}
|
||||
#endif
|
||||
#ifndef NO_OPENAL
|
||||
if ((!GSnd || !GSnd->IsValid()) && IsOpenALPresent())
|
||||
{
|
||||
Printf (TEXTCOLOR_RED"FMod Ex Sound init failed. Trying OpenAL.\n");
|
||||
GSnd = new OpenALSoundRenderer;
|
||||
snd_backend = "openal";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if(stricmp(snd_backend, "openal") == 0)
|
||||
{
|
||||
#ifndef NO_OPENAL
|
||||
if (IsOpenALPresent())
|
||||
{
|
||||
GSnd = new OpenALSoundRenderer;
|
||||
}
|
||||
#endif
|
||||
#ifndef NO_FMOD
|
||||
if ((!GSnd || !GSnd->IsValid()) && IsFModExPresent())
|
||||
{
|
||||
Printf (TEXTCOLOR_RED"OpenAL Sound init failed. Trying FMod Ex.\n");
|
||||
GSnd = new FMODSoundRenderer;
|
||||
snd_backend = "fmod";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf (TEXTCOLOR_RED"%s: Unknown sound system specified\n", *snd_backend);
|
||||
snd_backend = "null";
|
||||
}
|
||||
if (!GSnd || !GSnd->IsValid ())
|
||||
{
|
||||
I_CloseSound();
|
||||
GSnd = new NullSoundRenderer;
|
||||
|
@ -283,6 +342,27 @@ void I_ShutdownSound()
|
|||
}
|
||||
}
|
||||
|
||||
const char *GetSampleTypeName(enum SampleType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case SampleType_UInt8: return "Unsigned 8-bit";
|
||||
case SampleType_Int16: return "Signed 16-bit";
|
||||
}
|
||||
return "(invalid sample type)";
|
||||
}
|
||||
|
||||
const char *GetChannelConfigName(enum ChannelConfig chan)
|
||||
{
|
||||
switch(chan)
|
||||
{
|
||||
case ChannelConfig_Mono: return "Mono";
|
||||
case ChannelConfig_Stereo: return "Stereo";
|
||||
}
|
||||
return "(invalid channel config)";
|
||||
}
|
||||
|
||||
|
||||
CCMD (snd_status)
|
||||
{
|
||||
GSnd->PrintStatus ();
|
||||
|
@ -321,9 +401,28 @@ FString SoundRenderer::GatherStats ()
|
|||
return "No stats for this sound renderer.";
|
||||
}
|
||||
|
||||
short *SoundRenderer::DecodeSample(int outlen, const void *coded, int sizebytes, ECodecType type)
|
||||
short *SoundRenderer::DecodeSample(int outlen, const void *coded, int sizebytes, ECodecType ctype)
|
||||
{
|
||||
return NULL;
|
||||
MemoryReader reader((const char*)coded, sizebytes);
|
||||
short *samples = (short*)calloc(1, outlen);
|
||||
ChannelConfig chans;
|
||||
SampleType type;
|
||||
int srate;
|
||||
|
||||
SoundDecoder *decoder = CreateDecoder(&reader);
|
||||
if(!decoder) return samples;
|
||||
|
||||
decoder->getInfo(&srate, &chans, &type);
|
||||
if(chans != ChannelConfig_Mono || type != SampleType_Int16)
|
||||
{
|
||||
DPrintf("Sample is not 16-bit mono\n");
|
||||
delete decoder;
|
||||
return samples;
|
||||
}
|
||||
|
||||
decoder->read((char*)samples, outlen);
|
||||
delete decoder;
|
||||
return samples;
|
||||
}
|
||||
|
||||
void SoundRenderer::DrawWaveDebug(int mode)
|
||||
|
@ -504,3 +603,51 @@ SoundHandle SoundRenderer::LoadSoundVoc(BYTE *sfxdata, int length)
|
|||
return retval;
|
||||
}
|
||||
|
||||
SoundStream *SoundRenderer::OpenStream(const char *url, int flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SoundDecoder *SoundRenderer::CreateDecoder(FileReader *reader)
|
||||
{
|
||||
SoundDecoder *decoder = NULL;
|
||||
int pos = reader->Tell();
|
||||
|
||||
#ifdef HAVE_MPG123
|
||||
decoder = new MPG123Decoder;
|
||||
if (decoder->open(reader))
|
||||
return decoder;
|
||||
reader->Seek(pos, SEEK_SET);
|
||||
|
||||
delete decoder;
|
||||
decoder = NULL;
|
||||
#endif
|
||||
#ifdef HAVE_SNDFILE
|
||||
decoder = new SndFileDecoder;
|
||||
if (decoder->open(reader))
|
||||
return decoder;
|
||||
reader->Seek(pos, SEEK_SET);
|
||||
|
||||
delete decoder;
|
||||
decoder = NULL;
|
||||
#endif
|
||||
return decoder;
|
||||
}
|
||||
|
||||
|
||||
// Default readAll implementation, for decoders that can't do anything better
|
||||
TArray<char> SoundDecoder::readAll()
|
||||
{
|
||||
TArray<char> output;
|
||||
unsigned total = 0;
|
||||
unsigned got;
|
||||
|
||||
output.Resize(total+32768);
|
||||
while((got=(unsigned)read(&output[total], output.Size()-total)) > 0)
|
||||
{
|
||||
total += got;
|
||||
output.Resize(total*2);
|
||||
}
|
||||
output.Resize(total);
|
||||
return output;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
#include "doomtype.h"
|
||||
#include "i_soundinternal.h"
|
||||
|
||||
class FileReader;
|
||||
|
||||
enum ECodecType
|
||||
{
|
||||
CODEC_Unknown,
|
||||
|
@ -82,6 +84,8 @@ public:
|
|||
|
||||
typedef bool (*SoundStreamCallback)(SoundStream *stream, void *buff, int len, void *userdata);
|
||||
|
||||
struct SoundDecoder;
|
||||
|
||||
class SoundRenderer
|
||||
{
|
||||
public:
|
||||
|
@ -101,7 +105,8 @@ public:
|
|||
|
||||
// Streaming sounds.
|
||||
virtual SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) = 0;
|
||||
virtual SoundStream *OpenStream (const char *filename, int flags, int offset, int length) = 0;
|
||||
virtual SoundStream *OpenStream (FileReader *reader, int flags) = 0;
|
||||
virtual SoundStream *OpenStream (const char *url, int flags);
|
||||
|
||||
// Starts a sound.
|
||||
virtual FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan) = 0;
|
||||
|
@ -142,6 +147,7 @@ public:
|
|||
|
||||
virtual void UpdateListener (SoundListener *) = 0;
|
||||
virtual void UpdateSounds () = 0;
|
||||
virtual void UpdateMusic() {}
|
||||
|
||||
virtual bool IsValid () = 0;
|
||||
virtual void PrintStatus () = 0;
|
||||
|
@ -150,6 +156,9 @@ public:
|
|||
virtual short *DecodeSample(int outlen, const void *coded, int sizebytes, ECodecType type);
|
||||
|
||||
virtual void DrawWaveDebug(int mode);
|
||||
|
||||
protected:
|
||||
virtual SoundDecoder *CreateDecoder(FileReader *reader);
|
||||
};
|
||||
|
||||
extern SoundRenderer *GSnd;
|
||||
|
@ -166,4 +175,7 @@ FISoundChannel *S_GetChannel(void *syschan);
|
|||
|
||||
extern ReverbContainer *DefaultEnvironments[26];
|
||||
|
||||
bool IsFModExPresent();
|
||||
bool IsOpenALPresent();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
#ifndef __SNDINT_H
|
||||
#define __SNDINT_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "basictypes.h"
|
||||
#include "vectors.h"
|
||||
#include "tarray.h"
|
||||
|
||||
class FileReader;
|
||||
|
||||
// For convenience, this structure matches FMOD_REVERB_PROPERTIES.
|
||||
// Since I can't very well #include system-specific stuff in the
|
||||
|
@ -96,8 +102,46 @@ struct FISoundChannel
|
|||
// callback that can't be passed a sound channel pointer
|
||||
FRolloffInfo Rolloff;
|
||||
float DistanceScale;
|
||||
float DistanceSqr;
|
||||
bool ManualRolloff;
|
||||
};
|
||||
|
||||
|
||||
enum SampleType
|
||||
{
|
||||
SampleType_UInt8,
|
||||
SampleType_Int16
|
||||
};
|
||||
enum ChannelConfig
|
||||
{
|
||||
ChannelConfig_Mono,
|
||||
ChannelConfig_Stereo
|
||||
};
|
||||
|
||||
const char *GetSampleTypeName(enum SampleType type);
|
||||
const char *GetChannelConfigName(enum ChannelConfig chan);
|
||||
|
||||
struct SoundDecoder
|
||||
{
|
||||
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0;
|
||||
|
||||
virtual size_t read(char *buffer, size_t bytes) = 0;
|
||||
virtual TArray<char> readAll();
|
||||
virtual bool seek(size_t ms_offset) = 0;
|
||||
virtual size_t getSampleOffset() = 0;
|
||||
virtual size_t getSampleLength() { return 0; }
|
||||
|
||||
SoundDecoder() { }
|
||||
virtual ~SoundDecoder() { }
|
||||
|
||||
protected:
|
||||
virtual bool open(FileReader *reader) = 0;
|
||||
friend class SoundRenderer;
|
||||
|
||||
private:
|
||||
// Make non-copyable
|
||||
SoundDecoder(const SoundDecoder &rhs);
|
||||
SoundDecoder& operator=(const SoundDecoder &rhs);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
206
src/sound/mpg123_decoder.cpp
Normal file
206
src/sound/mpg123_decoder.cpp
Normal file
|
@ -0,0 +1,206 @@
|
|||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#define USE_WINDOWS_DWORD
|
||||
#endif
|
||||
|
||||
#include "mpg123_decoder.h"
|
||||
#include "files.h"
|
||||
#include "except.h"
|
||||
|
||||
#ifdef HAVE_MPG123
|
||||
static bool inited = false;
|
||||
|
||||
|
||||
off_t MPG123Decoder::file_lseek(void *handle, off_t offset, int whence)
|
||||
{
|
||||
MPG123Decoder *self = reinterpret_cast<MPG123Decoder*>(handle);
|
||||
FileReader *reader = self->Reader;
|
||||
|
||||
if(whence == SEEK_SET)
|
||||
offset += self->StartOffset;
|
||||
else if(whence == SEEK_CUR)
|
||||
{
|
||||
if(offset < 0 && reader->Tell()+offset < self->StartOffset)
|
||||
return -1;
|
||||
}
|
||||
else if(whence == SEEK_END)
|
||||
{
|
||||
if(offset < 0 && reader->GetLength()+offset < self->StartOffset)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(reader->Seek(offset, whence) != 0)
|
||||
return -1;
|
||||
return reader->Tell() - self->StartOffset;
|
||||
}
|
||||
|
||||
ssize_t MPG123Decoder::file_read(void *handle, void *buffer, size_t bytes)
|
||||
{
|
||||
FileReader *reader = reinterpret_cast<MPG123Decoder*>(handle)->Reader;
|
||||
return reader->Read(buffer, bytes);
|
||||
}
|
||||
|
||||
|
||||
MPG123Decoder::~MPG123Decoder()
|
||||
{
|
||||
if(MPG123)
|
||||
{
|
||||
mpg123_close(MPG123);
|
||||
mpg123_delete(MPG123);
|
||||
MPG123 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool MPG123Decoder::open(FileReader *reader)
|
||||
{
|
||||
if(!inited)
|
||||
{
|
||||
__try
|
||||
{
|
||||
if(mpg123_init() != MPG123_OK)
|
||||
return false;
|
||||
inited = true;
|
||||
}
|
||||
__except (CheckException(GetExceptionCode()))
|
||||
{
|
||||
// this means that the delay loaded decoder DLL was not found.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reader = reader;
|
||||
StartOffset = 0;
|
||||
|
||||
char data[10];
|
||||
if(file_read(this, data, 10) != 10)
|
||||
return false;
|
||||
|
||||
int start_offset = 0;
|
||||
// Check for ID3 tags and skip them
|
||||
if(memcmp(data, "ID3", 3) == 0 &&
|
||||
(BYTE)data[3] <= 4 && (BYTE)data[4] != 0xff &&
|
||||
(data[5]&0x0f) == 0 && (data[6]&0x80) == 0 &&
|
||||
(data[7]&0x80) == 0 && (data[8]&0x80) == 0 &&
|
||||
(data[9]&0x80) == 0)
|
||||
{
|
||||
// ID3v2
|
||||
start_offset = (data[6]<<21) | (data[7]<<14) |
|
||||
(data[8]<< 7) | (data[9] );
|
||||
start_offset += ((data[5]&0x10) ? 20 : 10);
|
||||
}
|
||||
|
||||
StartOffset = start_offset;
|
||||
if(file_lseek(this, 0, SEEK_SET) != 0)
|
||||
return false;
|
||||
|
||||
// Check for a frame header
|
||||
bool frame_ok = false;
|
||||
if(file_read(this, data, 3) == 3)
|
||||
{
|
||||
if((BYTE)data[0] == 0xff &&
|
||||
((data[1]&0xfe) == 0xfa/*MPEG-1*/ || (data[1]&0xfe) == 0xf2/*MPEG-2*/))
|
||||
{
|
||||
int brate_idx = (data[2]>>4) & 0x0f;
|
||||
int srate_idx = (data[2]>>2) & 0x03;
|
||||
if(brate_idx != 0 && brate_idx != 15 && srate_idx != 3)
|
||||
frame_ok = (file_lseek(this, 0, SEEK_SET) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(frame_ok)
|
||||
{
|
||||
MPG123 = mpg123_new(NULL, NULL);
|
||||
if(mpg123_replace_reader_handle(MPG123, file_read, file_lseek, NULL) == MPG123_OK &&
|
||||
mpg123_open_handle(MPG123, this) == MPG123_OK)
|
||||
{
|
||||
int enc, channels;
|
||||
long srate;
|
||||
|
||||
if(mpg123_getformat(MPG123, &srate, &channels, &enc) == MPG123_OK)
|
||||
{
|
||||
if((channels == 1 || channels == 2) && srate > 0 &&
|
||||
mpg123_format_none(MPG123) == MPG123_OK &&
|
||||
mpg123_format(MPG123, srate, channels, MPG123_ENC_SIGNED_16) == MPG123_OK)
|
||||
{
|
||||
// All OK
|
||||
Done = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
mpg123_close(MPG123);
|
||||
}
|
||||
mpg123_delete(MPG123);
|
||||
MPG123 = 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MPG123Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
|
||||
{
|
||||
int enc = 0, channels = 0;
|
||||
long srate = 0;
|
||||
|
||||
mpg123_getformat(MPG123, &srate, &channels, &enc);
|
||||
|
||||
*samplerate = srate;
|
||||
|
||||
if(channels == 2)
|
||||
*chans = ChannelConfig_Stereo;
|
||||
else
|
||||
*chans = ChannelConfig_Mono;
|
||||
|
||||
*type = SampleType_Int16;
|
||||
}
|
||||
|
||||
size_t MPG123Decoder::read(char *buffer, size_t bytes)
|
||||
{
|
||||
size_t amt = 0;
|
||||
while(!Done && bytes > 0)
|
||||
{
|
||||
size_t got = 0;
|
||||
int ret = mpg123_read(MPG123, (unsigned char*)buffer, bytes, &got);
|
||||
|
||||
bytes -= got;
|
||||
buffer += got;
|
||||
amt += got;
|
||||
|
||||
if(ret == MPG123_NEW_FORMAT || ret == MPG123_DONE || got == 0)
|
||||
{
|
||||
Done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return amt;
|
||||
}
|
||||
|
||||
bool MPG123Decoder::seek(size_t ms_offset)
|
||||
{
|
||||
int enc, channels;
|
||||
long srate;
|
||||
|
||||
if(mpg123_getformat(MPG123, &srate, &channels, &enc) == MPG123_OK)
|
||||
{
|
||||
size_t smp_offset = (size_t)((double)ms_offset / 1000. * srate);
|
||||
if(mpg123_seek(MPG123, smp_offset, SEEK_SET) >= 0)
|
||||
{
|
||||
Done = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t MPG123Decoder::getSampleOffset()
|
||||
{
|
||||
return mpg123_tell(MPG123);
|
||||
}
|
||||
|
||||
size_t MPG123Decoder::getSampleLength()
|
||||
{
|
||||
off_t len = mpg123_length(MPG123);
|
||||
return (len > 0) ? len : 0;
|
||||
}
|
||||
|
||||
#endif
|
44
src/sound/mpg123_decoder.h
Normal file
44
src/sound/mpg123_decoder.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifndef MPG123_DECODER_H
|
||||
#define MPG123_DECODER_H
|
||||
|
||||
#include "i_soundinternal.h"
|
||||
|
||||
#ifdef HAVE_MPG123
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef int ssize_t;
|
||||
#endif
|
||||
#include "mpg123.h"
|
||||
|
||||
struct MPG123Decoder : public SoundDecoder
|
||||
{
|
||||
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
|
||||
|
||||
virtual size_t read(char *buffer, size_t bytes);
|
||||
virtual bool seek(size_t ms_offset);
|
||||
virtual size_t getSampleOffset();
|
||||
virtual size_t getSampleLength();
|
||||
|
||||
MPG123Decoder() : MPG123(0) { }
|
||||
virtual ~MPG123Decoder();
|
||||
|
||||
protected:
|
||||
virtual bool open(FileReader *reader);
|
||||
|
||||
private:
|
||||
mpg123_handle *MPG123;
|
||||
bool Done;
|
||||
|
||||
FileReader *Reader;
|
||||
int StartOffset;
|
||||
static off_t file_lseek(void *handle, off_t offset, int whence);
|
||||
static ssize_t file_read(void *handle, void *buffer, size_t bytes);
|
||||
|
||||
// Make non-copyable
|
||||
MPG123Decoder(const MPG123Decoder &rhs);
|
||||
MPG123Decoder& operator=(const MPG123Decoder &rhs);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* MPG123_DECODER_H */
|
|
@ -1,5 +1,6 @@
|
|||
#include "i_musicinterns.h"
|
||||
#include "i_cd.h"
|
||||
#include "files.h"
|
||||
|
||||
void CDSong::Play (bool looping, int subsong)
|
||||
{
|
||||
|
@ -78,31 +79,31 @@ bool CDSong::IsPlaying ()
|
|||
return m_Status != STATE_Stopped;
|
||||
}
|
||||
|
||||
CDDAFile::CDDAFile (FILE *file, int length)
|
||||
CDDAFile::CDDAFile (FileReader &reader)
|
||||
: CDSong ()
|
||||
{
|
||||
DWORD chunk;
|
||||
WORD track;
|
||||
DWORD discid;
|
||||
long endpos = ftell (file) + length - 8;
|
||||
long endpos = reader.Tell() + reader.GetLength() - 8;
|
||||
|
||||
// I_RegisterSong already identified this as a CDDA file, so we
|
||||
// just need to check the contents we're interested in.
|
||||
fseek (file, 12, SEEK_CUR);
|
||||
reader.Seek(12, SEEK_CUR);
|
||||
|
||||
while (ftell (file) < endpos)
|
||||
while (reader.Tell() < endpos)
|
||||
{
|
||||
fread (&chunk, 4, 1, file);
|
||||
reader.Read(&chunk, 4);
|
||||
if (chunk != (('f')|(('m')<<8)|(('t')<<16)|((' ')<<24)))
|
||||
{
|
||||
fread (&chunk, 4, 1, file);
|
||||
fseek (file, chunk, SEEK_CUR);
|
||||
reader.Read(&chunk, 4);
|
||||
reader.Seek(chunk, SEEK_CUR);
|
||||
}
|
||||
else
|
||||
{
|
||||
fseek (file, 6, SEEK_CUR);
|
||||
fread (&track, 2, 1, file);
|
||||
fread (&discid, 4, 1, file);
|
||||
reader.Seek(6, SEEK_CUR);
|
||||
reader.Read(&track, 2);
|
||||
reader.Read(&discid, 4);
|
||||
|
||||
if (CD_InitID (discid) && CD_CheckTrack (track))
|
||||
{
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "c_cvars.h"
|
||||
#include "i_sound.h"
|
||||
#include "i_system.h"
|
||||
#include "files.h"
|
||||
|
||||
#undef CDECL // w32api's windef.h defines this
|
||||
#include "../dumb/include/dumb.h"
|
||||
|
@ -531,31 +532,24 @@ static DUMBFILE_SYSTEM mem_dfs = {
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
DUMBFILE *dumb_read_allfile(dumbfile_mem_status *filestate, BYTE *start, FILE *file, BYTE *musiccache, int lenhave, int lenfull)
|
||||
DUMBFILE *dumb_read_allfile(dumbfile_mem_status *filestate, BYTE *start, FileReader &reader, int lenhave, int lenfull)
|
||||
{
|
||||
filestate->size = lenfull;
|
||||
filestate->offset = 0;
|
||||
if (lenhave >= lenfull)
|
||||
{
|
||||
filestate->ptr = (BYTE *)start;
|
||||
return dumbfile_open_ex(filestate, &mem_dfs);
|
||||
}
|
||||
if (musiccache != NULL)
|
||||
{
|
||||
filestate->ptr = (BYTE *)musiccache;
|
||||
}
|
||||
else
|
||||
{
|
||||
BYTE *mem = new BYTE[lenfull];
|
||||
memcpy(mem, start, lenhave);
|
||||
if (fread(mem + lenhave, 1, lenfull - lenhave, file) != (size_t)(lenfull - lenhave))
|
||||
{
|
||||
delete[] mem;
|
||||
return NULL;
|
||||
}
|
||||
filestate->ptr = mem;
|
||||
}
|
||||
return dumbfile_open_ex(filestate, &mem_dfs);
|
||||
else
|
||||
{
|
||||
BYTE *mem = new BYTE[lenfull];
|
||||
memcpy(mem, start, lenhave);
|
||||
if (reader.Read(mem + lenhave, lenfull - lenhave) != (lenfull - lenhave))
|
||||
{
|
||||
delete[] mem;
|
||||
return NULL;
|
||||
}
|
||||
filestate->ptr = mem;
|
||||
}
|
||||
return dumbfile_open_ex(filestate, &mem_dfs);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -753,7 +747,7 @@ static void MOD_SetAutoChip(DUH *duh)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
|
||||
MusInfo *MOD_OpenSong(FileReader &reader)
|
||||
{
|
||||
DUH *duh = 0;
|
||||
int headsize;
|
||||
|
@ -777,40 +771,36 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
|
|||
|
||||
atterm(dumb_exit);
|
||||
|
||||
int size = reader.GetLength();
|
||||
fpos = reader.Tell();
|
||||
|
||||
filestate.ptr = start;
|
||||
filestate.offset = 0;
|
||||
headsize = MIN((int)sizeof(start), size);
|
||||
if (musiccache != NULL)
|
||||
{
|
||||
memcpy(start, musiccache, headsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpos = ftell(file);
|
||||
if ((size_t)headsize != fread(start, 1, headsize, file))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (headsize != reader.Read(start, headsize))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (size >= 4 && dstart[0] == MAKE_ID('I','M','P','M'))
|
||||
{
|
||||
is_it = true;
|
||||
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size)))
|
||||
if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
|
||||
{
|
||||
duh = dumb_read_it_quick(f);
|
||||
}
|
||||
}
|
||||
else if (size >= 17 && !memcmp(start, "Extended Module: ", 17))
|
||||
{
|
||||
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size)))
|
||||
if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
|
||||
{
|
||||
duh = dumb_read_xm_quick(f);
|
||||
}
|
||||
}
|
||||
else if (size >= 0x30 && dstart[11] == MAKE_ID('S','C','R','M'))
|
||||
{
|
||||
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size)))
|
||||
if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
|
||||
{
|
||||
duh = dumb_read_s3m_quick(f);
|
||||
}
|
||||
|
@ -821,7 +811,7 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
|
|||
!memcmp( &start[20], "BMOD2STM", 8 ) ||
|
||||
!memcmp( &start[20], "WUZAMOD!", 8 ) ) )
|
||||
{
|
||||
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size)))
|
||||
if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
|
||||
{
|
||||
duh = dumb_read_stm_quick(f);
|
||||
}
|
||||
|
@ -830,21 +820,21 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
|
|||
((start[0] == 0x69 && start[1] == 0x66) ||
|
||||
(start[0] == 0x4A && start[1] == 0x4E)))
|
||||
{
|
||||
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size)))
|
||||
if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
|
||||
{
|
||||
duh = dumb_read_669_quick(f);
|
||||
}
|
||||
}
|
||||
else if (size >= 0x30 && dstart[11] == MAKE_ID('P','T','M','F'))
|
||||
{
|
||||
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size)))
|
||||
if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
|
||||
{
|
||||
duh = dumb_read_ptm_quick(f);
|
||||
}
|
||||
}
|
||||
else if (size >= 4 && dstart[0] == MAKE_ID('P','S','M',' '))
|
||||
{
|
||||
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size)))
|
||||
if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
|
||||
{
|
||||
duh = dumb_read_psm_quick(f, 0/*start_order*/);
|
||||
/*start_order = 0;*/
|
||||
|
@ -852,14 +842,14 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
|
|||
}
|
||||
else if (size >= 4 && dstart[0] == (DWORD)MAKE_ID('P','S','M',254))
|
||||
{
|
||||
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size)))
|
||||
if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
|
||||
{
|
||||
duh = dumb_read_old_psm_quick(f);
|
||||
}
|
||||
}
|
||||
else if (size >= 3 && start[0] == 'M' && start[1] == 'T' && start[2] == 'M')
|
||||
{
|
||||
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size)))
|
||||
if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
|
||||
{
|
||||
duh = dumb_read_mtm_quick(f);
|
||||
}
|
||||
|
@ -869,7 +859,7 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
|
|||
dstart[2] == MAKE_ID('A','M',' ',' ') ||
|
||||
dstart[2] == MAKE_ID('A','M','F','F')))
|
||||
{
|
||||
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size)))
|
||||
if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
|
||||
{
|
||||
duh = dumb_read_riff_quick(f);
|
||||
}
|
||||
|
@ -878,7 +868,7 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
|
|||
!memcmp( start, "ASYLUM Music Format", 19 ) &&
|
||||
!memcmp( start + 19, " V1.0", 5 ) )
|
||||
{
|
||||
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size)))
|
||||
if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
|
||||
{
|
||||
duh = dumb_read_asy_quick(f);
|
||||
}
|
||||
|
@ -887,7 +877,7 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
|
|||
dstart[0] == MAKE_ID('O','K','T','A') &&
|
||||
dstart[1] == MAKE_ID('S','O','N','G'))
|
||||
{
|
||||
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size)))
|
||||
if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
|
||||
{
|
||||
duh = dumb_read_okt_quick(f);
|
||||
}
|
||||
|
@ -898,12 +888,9 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
|
|||
is_dos = false;
|
||||
if (filestate.ptr == (BYTE *)start)
|
||||
{
|
||||
if (!(f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size)))
|
||||
if (!(f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
|
||||
{
|
||||
if (file != NULL)
|
||||
{
|
||||
fseek(file, fpos, SEEK_SET);
|
||||
}
|
||||
reader.Seek(fpos, SEEK_SET);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -914,8 +901,8 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
|
|||
// No way to get the filename, so we can't check for a .mod extension, and
|
||||
// therefore, trying to load an old 15-instrument SoundTracker module is not
|
||||
// safe. We'll restrict MOD loading to 31-instrument modules with known
|
||||
// signatures and let FMOD worry about 15-instrument ones. (Assuming it even
|
||||
// supports them; I have not checked.)
|
||||
// signatures and let the sound system worry about 15-instrument ones.
|
||||
// (Assuming it even supports them)
|
||||
duh = dumb_read_mod_quick(f, TRUE);
|
||||
}
|
||||
|
||||
|
@ -944,12 +931,9 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
|
|||
else
|
||||
{
|
||||
// Reposition file pointer for other codecs to do their checks.
|
||||
if (file != NULL)
|
||||
{
|
||||
fseek(file, fpos, SEEK_SET);
|
||||
}
|
||||
reader.Seek(fpos, SEEK_SET);
|
||||
}
|
||||
if (filestate.ptr != (BYTE *)start && filestate.ptr != musiccache)
|
||||
if (filestate.ptr != (BYTE *)start)
|
||||
{
|
||||
delete[] const_cast<BYTE *>(filestate.ptr);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "critsec.h"
|
||||
#include <gme/gme.h>
|
||||
#include "v_text.h"
|
||||
#include "files.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -104,7 +105,7 @@ const char *GME_CheckFormat(uint32 id)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
MusInfo *GME_OpenSong(FILE *file, BYTE *musiccache, int len, const char *fmt)
|
||||
MusInfo *GME_OpenSong(FileReader &reader, const char *fmt)
|
||||
{
|
||||
gme_type_t type;
|
||||
gme_err_t err;
|
||||
|
@ -123,29 +124,26 @@ MusInfo *GME_OpenSong(FILE *file, BYTE *musiccache, int len, const char *fmt)
|
|||
{
|
||||
return NULL;
|
||||
}
|
||||
if (musiccache != NULL)
|
||||
{
|
||||
song = musiccache;
|
||||
}
|
||||
else
|
||||
{
|
||||
song = new BYTE[len];
|
||||
if (fread(song, 1, len, file) != (size_t)len)
|
||||
{
|
||||
delete[] song;
|
||||
gme_delete(emu);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int fpos = reader.Tell();
|
||||
int len = reader.GetLength();
|
||||
song = new BYTE[len];
|
||||
if (reader.Read(song, len) != len)
|
||||
{
|
||||
delete[] song;
|
||||
gme_delete(emu);
|
||||
reader.Seek(fpos, SEEK_SET);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = gme_load_data(emu, song, len);
|
||||
if (song != musiccache)
|
||||
{
|
||||
delete[] song;
|
||||
}
|
||||
delete[] song;
|
||||
|
||||
if (err != NULL)
|
||||
{
|
||||
Printf("Failed loading song: %s\n", err);
|
||||
gme_delete(emu);
|
||||
reader.Seek(fpos, SEEK_SET);
|
||||
return NULL;
|
||||
}
|
||||
return new GMESong(emu, sample_rate);
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "templates.h"
|
||||
#include "doomdef.h"
|
||||
#include "m_swap.h"
|
||||
#include "files.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -127,7 +128,7 @@ extern char MIDI_CommonLengths[15];
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
HMISong::HMISong (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
|
||||
HMISong::HMISong (FileReader &reader, EMidiDevice type)
|
||||
: MIDIStreamer(type), MusHeader(0), Tracks(0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
@ -136,6 +137,7 @@ HMISong::HMISong (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
int len = reader.GetLength();
|
||||
if (len < 0x100)
|
||||
{ // Way too small to be HMI.
|
||||
return;
|
||||
|
@ -143,15 +145,8 @@ HMISong::HMISong (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
|
|||
MusHeader = new BYTE[len];
|
||||
SongLen = len;
|
||||
NumTracks = 0;
|
||||
if (file != NULL)
|
||||
{
|
||||
if (fread(MusHeader, 1, len, file) != (size_t)len)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(MusHeader, musiccache, len);
|
||||
}
|
||||
if (reader.Read(MusHeader, len) != len)
|
||||
return;
|
||||
|
||||
// Do some validation of the MIDI file
|
||||
if (memcmp(MusHeader, HMI_SONG_MAGIC, sizeof(HMI_SONG_MAGIC)) == 0)
|
||||
|
|
|
@ -33,7 +33,7 @@ static void AddDefaultMidiDevices(FOptionValues *opt)
|
|||
pair[p+1].Value = -3.0;
|
||||
pair[p+2].Text = "TiMidity++";
|
||||
pair[p+2].Value = -2.0;
|
||||
pair[p+3].Text = "FMOD";
|
||||
pair[p+3].Text = "Sound System";
|
||||
pair[p+3].Value = -1.0;
|
||||
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ CCMD (snd_listmididevices)
|
|||
PrintMidiDevice (-4, "Gravis Ultrasound Emulation", MOD_SWSYNTH, 0);
|
||||
PrintMidiDevice (-3, "Emulated OPL FM Synth", MOD_FMSYNTH, 0);
|
||||
PrintMidiDevice (-2, "TiMidity++", MOD_SWSYNTH, 0);
|
||||
PrintMidiDevice (-1, "FMOD", MOD_SWSYNTH, 0);
|
||||
PrintMidiDevice (-1, "Sound System", 0, 0);
|
||||
if (nummididevices != 0)
|
||||
{
|
||||
for (id = 0; id < nummididevices; ++id)
|
||||
|
@ -217,6 +217,6 @@ CCMD (snd_listmididevices)
|
|||
Printf("%s-4. Gravis Ultrasound Emulation\n", -4 == snd_mididevice ? TEXTCOLOR_BOLD : "");
|
||||
Printf("%s-3. Emulated OPL FM Synth\n", -3 == snd_mididevice ? TEXTCOLOR_BOLD : "");
|
||||
Printf("%s-2. TiMidity++\n", -2 == snd_mididevice ? TEXTCOLOR_BOLD : "");
|
||||
Printf("%s-1. FMOD\n", -1 == snd_mididevice ? TEXTCOLOR_BOLD : "");
|
||||
Printf("%s-1. Sound System\n", -1 == snd_mididevice ? TEXTCOLOR_BOLD : "");
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -611,7 +611,7 @@ int TimidityPPMIDIDevice::Resume()
|
|||
{
|
||||
if (LaunchTimidity())
|
||||
{
|
||||
// Assume success if not mixing with FMOD
|
||||
// Assume success if not mixing with the sound system
|
||||
if (Stream == NULL || Stream->Play(true, timidity_mastervolume))
|
||||
{
|
||||
Started = true;
|
||||
|
|
|
@ -215,13 +215,13 @@ EMidiDevice MIDIStreamer::SelectMIDIDevice(EMidiDevice device)
|
|||
- if explicitly selected by $mididevice
|
||||
- when snd_mididevice is -2 and no midi device is set for the song
|
||||
|
||||
- FMod:
|
||||
- Sound System:
|
||||
- if explicitly selected by $mididevice
|
||||
- when snd_mididevice is -1 and no midi device is set for the song
|
||||
- as fallback when both OPL and Timidity failed unless snd_mididevice is >= 0
|
||||
|
||||
- MMAPI (Win32 only):
|
||||
- if explicitly selected by $mididevice (non-Win32 redirects this to FMOD)
|
||||
- if explicitly selected by $mididevice (non-Win32 redirects this to Sound System)
|
||||
- when snd_mididevice is >= 0 and no midi device is set for the song
|
||||
- as fallback when both OPL and Timidity failed and snd_mididevice is >= 0
|
||||
*/
|
||||
|
@ -233,7 +233,7 @@ EMidiDevice MIDIStreamer::SelectMIDIDevice(EMidiDevice device)
|
|||
}
|
||||
switch (snd_mididevice)
|
||||
{
|
||||
case -1: return MDEV_FMOD;
|
||||
case -1: return MDEV_SNDSYS;
|
||||
case -2: return MDEV_TIMIDITY;
|
||||
case -3: return MDEV_OPL;
|
||||
case -4: return MDEV_GUS;
|
||||
|
@ -244,7 +244,7 @@ EMidiDevice MIDIStreamer::SelectMIDIDevice(EMidiDevice device)
|
|||
#ifdef _WIN32
|
||||
return MDEV_MMAPI;
|
||||
#else
|
||||
return MDEV_FMOD;
|
||||
return MDEV_SNDSYS;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -271,8 +271,8 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) const
|
|||
return new FluidSynthMIDIDevice;
|
||||
#endif
|
||||
|
||||
case MDEV_FMOD:
|
||||
return new FMODMIDIDevice;
|
||||
case MDEV_SNDSYS:
|
||||
return new SndSysMIDIDevice;
|
||||
|
||||
case MDEV_GUS:
|
||||
return new TimidityMIDIDevice;
|
||||
|
@ -285,8 +285,8 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) const
|
|||
catch (CRecoverableError &err)
|
||||
{
|
||||
// The creation of an OPL MIDI device can abort with an error if no GENMIDI lump can be found.
|
||||
Printf("Unable to create OPL MIDI device: %s\nFalling back to FModEx playback", err.GetMessage());
|
||||
return new FMODMIDIDevice;
|
||||
Printf("Unable to create OPL MIDI device: %s\nFalling back to Sound System playback", err.GetMessage());
|
||||
return new SndSysMIDIDevice;
|
||||
}
|
||||
|
||||
case MDEV_TIMIDITY:
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "templates.h"
|
||||
#include "doomdef.h"
|
||||
#include "m_swap.h"
|
||||
#include "files.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -91,7 +92,7 @@ static const BYTE CtrlTranslate[15] =
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
MUSSong2::MUSSong2 (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
|
||||
MUSSong2::MUSSong2 (FileReader &reader, EMidiDevice type)
|
||||
: MIDIStreamer(type), MusHeader(0), MusBuffer(0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
@ -104,11 +105,7 @@ MUSSong2::MUSSong2 (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
|
|||
BYTE front[32];
|
||||
int start;
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
memcpy(front, musiccache, sizeof(front));
|
||||
}
|
||||
else if (fread(front, 1, sizeof(front), file) != sizeof(front))
|
||||
if (reader.Read(front, sizeof(front)) != sizeof(front))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -124,24 +121,17 @@ MUSSong2::MUSSong2 (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
|
|||
}
|
||||
|
||||
// Read the remainder of the song.
|
||||
len = int(len - start);
|
||||
int len = int(reader.GetLength() - start);
|
||||
if (len < (int)sizeof(MusHeader))
|
||||
{ // It's too short.
|
||||
return;
|
||||
}
|
||||
MusHeader = (MUSHeader *)new BYTE[len];
|
||||
if (file == NULL)
|
||||
{
|
||||
memcpy(MusHeader, musiccache + start, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(MusHeader, front + start, sizeof(front) - start);
|
||||
if (fread((BYTE *)MusHeader + sizeof(front) - start, 1, len - (sizeof(front) - start), file) != (size_t)(len - (32 - start)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
memcpy(MusHeader, front + start, sizeof(front) - start);
|
||||
if (reader.Read((BYTE *)MusHeader + sizeof(front) - start, len - (sizeof(front) - start)) != (len - (32 - start)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Do some validation of the MUS file.
|
||||
if (LittleShort(MusHeader->NumChans) > 15)
|
||||
|
|
|
@ -22,11 +22,11 @@ CUSTOM_CVAR (Int, opl_numchips, 2, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|||
|
||||
CVAR(Int, opl_core, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
|
||||
OPLMUSSong::OPLMUSSong (FILE *file, BYTE *musiccache, int len)
|
||||
OPLMUSSong::OPLMUSSong (FileReader &reader)
|
||||
{
|
||||
int samples = int(OPL_SAMPLE_RATE / 14);
|
||||
|
||||
Music = new OPLmusicFile (file, musiccache, len);
|
||||
Music = new OPLmusicFile (&reader);
|
||||
|
||||
m_Stream = GSnd->CreateStream (FillStream, samples*4,
|
||||
(opl_core == 0 ? SoundStream::Mono : 0) | SoundStream::Float, int(OPL_SAMPLE_RATE), this);
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "templates.h"
|
||||
#include "doomdef.h"
|
||||
#include "m_swap.h"
|
||||
#include "files.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -234,29 +235,30 @@ FString PseudoMIDIDevice::GetStats()
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMODMIDIDevice :: Open
|
||||
// SndSysMIDIDevice :: Open
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FMODMIDIDevice::Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata)
|
||||
int SndSysMIDIDevice::Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMODMIDIDevice :: Preprocess
|
||||
// SndSysMIDIDevice :: Preprocess
|
||||
//
|
||||
// Create a standard MIDI file and stream it.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FMODMIDIDevice::Preprocess(MIDIStreamer *song, bool looping)
|
||||
bool SndSysMIDIDevice::Preprocess(MIDIStreamer *song, bool looping)
|
||||
{
|
||||
TArray<BYTE> midi;
|
||||
MemoryArrayReader *reader = new MemoryArrayReader(NULL, 0);
|
||||
song->CreateSMF(reader->GetArray(), looping ? 0 : 1);
|
||||
reader->UpdateLength();
|
||||
|
||||
song->CreateSMF(midi, looping ? 0 : 1);
|
||||
bLooping = looping;
|
||||
Stream = GSnd->OpenStream((char *)&midi[0], looping ? SoundStream::Loop : 0, -1, midi.Size());
|
||||
return false;
|
||||
bLooping = looping;
|
||||
Stream = GSnd->OpenStream(reader, looping ? SoundStream::Loop : 0);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "templates.h"
|
||||
#include "doomdef.h"
|
||||
#include "m_swap.h"
|
||||
#include "files.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -101,7 +102,7 @@ char MIDI_CommonLengths[15] = { 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
MIDISong2::MIDISong2 (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
|
||||
MIDISong2::MIDISong2 (FileReader &reader, EMidiDevice type)
|
||||
: MIDIStreamer(type), MusHeader(0), Tracks(0)
|
||||
{
|
||||
int p;
|
||||
|
@ -113,17 +114,10 @@ MIDISong2::MIDISong2 (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
MusHeader = new BYTE[len];
|
||||
SongLen = len;
|
||||
if (file != NULL)
|
||||
{
|
||||
if (fread(MusHeader, 1, len, file) != (size_t)len)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(MusHeader, musiccache, len);
|
||||
}
|
||||
SongLen = reader.GetLength();
|
||||
MusHeader = new BYTE[SongLen];
|
||||
if (reader.Read(MusHeader, SongLen) != SongLen)
|
||||
return;
|
||||
|
||||
// Do some validation of the MIDI file
|
||||
if (MusHeader[4] != 0 || MusHeader[5] != 0 || MusHeader[6] != 0 || MusHeader[7] != 6)
|
||||
|
@ -153,7 +147,7 @@ MIDISong2::MIDISong2 (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
|
|||
Tracks = new TrackInfo[NumTracks];
|
||||
|
||||
// Gather information about each track
|
||||
for (i = 0, p = 14; i < NumTracks && p < len + 8; ++i)
|
||||
for (i = 0, p = 14; i < NumTracks && p < SongLen + 8; ++i)
|
||||
{
|
||||
DWORD chunkLen =
|
||||
(MusHeader[p+4]<<24) |
|
||||
|
@ -161,9 +155,9 @@ MIDISong2::MIDISong2 (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
|
|||
(MusHeader[p+6]<<8) |
|
||||
(MusHeader[p+7]);
|
||||
|
||||
if (chunkLen + p + 8 > (DWORD)len)
|
||||
if (chunkLen + p + 8 > (DWORD)SongLen)
|
||||
{ // Track too long, so truncate it
|
||||
chunkLen = len - p - 8;
|
||||
chunkLen = SongLen - p - 8;
|
||||
}
|
||||
|
||||
if (MusHeader[p+0] == 'M' &&
|
||||
|
|
|
@ -52,9 +52,14 @@ StreamSong::~StreamSong ()
|
|||
}
|
||||
}
|
||||
|
||||
StreamSong::StreamSong (const char *filename_or_data, int offset, int len)
|
||||
StreamSong::StreamSong (FileReader *reader)
|
||||
{
|
||||
m_Stream = GSnd->OpenStream (filename_or_data, SoundStream::Loop, offset, len);
|
||||
m_Stream = GSnd->OpenStream (reader, SoundStream::Loop);
|
||||
}
|
||||
|
||||
StreamSong::StreamSong (const char *url)
|
||||
{
|
||||
m_Stream = GSnd->OpenStream (url, SoundStream::Loop);
|
||||
}
|
||||
|
||||
bool StreamSong::IsPlaying ()
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "templates.h"
|
||||
#include "doomdef.h"
|
||||
#include "m_swap.h"
|
||||
#include "files.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -107,7 +108,7 @@ extern char MIDI_CommonLengths[15];
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
XMISong::XMISong (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
|
||||
XMISong::XMISong (FileReader &reader, EMidiDevice type)
|
||||
: MIDIStreamer(type), MusHeader(0), Songs(0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
@ -116,20 +117,13 @@ XMISong::XMISong (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
MusHeader = new BYTE[len];
|
||||
SongLen = len;
|
||||
if (file != NULL)
|
||||
{
|
||||
if (fread(MusHeader, 1, len, file) != (size_t)len)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(MusHeader, musiccache, len);
|
||||
}
|
||||
SongLen = reader.GetLength();
|
||||
MusHeader = new BYTE[SongLen];
|
||||
if (reader.Read(MusHeader, SongLen) != SongLen)
|
||||
return;
|
||||
|
||||
// Find all the songs in this file.
|
||||
NumSongs = FindXMIDforms(MusHeader, len, NULL);
|
||||
NumSongs = FindXMIDforms(MusHeader, SongLen, NULL);
|
||||
if (NumSongs == 0)
|
||||
{
|
||||
return;
|
||||
|
@ -147,7 +141,7 @@ XMISong::XMISong (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
|
|||
|
||||
Songs = new TrackInfo[NumSongs];
|
||||
memset(Songs, 0, sizeof(*Songs) * NumSongs);
|
||||
FindXMIDforms(MusHeader, len, Songs);
|
||||
FindXMIDforms(MusHeader, SongLen, Songs);
|
||||
CurrSong = Songs;
|
||||
DPrintf("XMI song count: %d\n", NumSongs);
|
||||
}
|
||||
|
|
1973
src/sound/oalsound.cpp
Normal file
1973
src/sound/oalsound.cpp
Normal file
File diff suppressed because it is too large
Load diff
211
src/sound/oalsound.h
Normal file
211
src/sound/oalsound.h
Normal file
|
@ -0,0 +1,211 @@
|
|||
#ifndef OALSOUND_H
|
||||
#define OALSOUND_H
|
||||
|
||||
#include "i_sound.h"
|
||||
#include "s_sound.h"
|
||||
#include "menu/menu.h"
|
||||
|
||||
#ifndef NO_OPENAL
|
||||
|
||||
#include "al.h"
|
||||
#include "alc.h"
|
||||
|
||||
#ifndef ALC_ENUMERATE_ALL_EXT
|
||||
#define ALC_ENUMERATE_ALL_EXT 1
|
||||
#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
|
||||
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
|
||||
#endif
|
||||
|
||||
#ifndef ALC_EXT_disconnect
|
||||
#define ALC_EXT_disconnect 1
|
||||
#define ALC_CONNECTED 0x313
|
||||
#endif
|
||||
|
||||
#ifndef AL_EXT_source_distance_model
|
||||
#define AL_EXT_source_distance_model 1
|
||||
#define AL_SOURCE_DISTANCE_MODEL 0x200
|
||||
#endif
|
||||
|
||||
#ifndef AL_SOFT_loop_points
|
||||
#define AL_SOFT_loop_points 1
|
||||
#define AL_LOOP_POINTS_SOFT 0x2015
|
||||
#endif
|
||||
|
||||
#ifndef AL_EXT_float32
|
||||
#define AL_EXT_float32 1
|
||||
#define AL_FORMAT_MONO_FLOAT32 0x10010
|
||||
#define AL_FORMAT_STEREO_FLOAT32 0x10011
|
||||
#endif
|
||||
|
||||
#ifndef AL_EXT_MCFORMATS
|
||||
#define AL_EXT_MCFORMATS 1
|
||||
#define AL_FORMAT_QUAD8 0x1204
|
||||
#define AL_FORMAT_QUAD16 0x1205
|
||||
#define AL_FORMAT_QUAD32 0x1206
|
||||
#define AL_FORMAT_REAR8 0x1207
|
||||
#define AL_FORMAT_REAR16 0x1208
|
||||
#define AL_FORMAT_REAR32 0x1209
|
||||
#define AL_FORMAT_51CHN8 0x120A
|
||||
#define AL_FORMAT_51CHN16 0x120B
|
||||
#define AL_FORMAT_51CHN32 0x120C
|
||||
#define AL_FORMAT_61CHN8 0x120D
|
||||
#define AL_FORMAT_61CHN16 0x120E
|
||||
#define AL_FORMAT_61CHN32 0x120F
|
||||
#define AL_FORMAT_71CHN8 0x1210
|
||||
#define AL_FORMAT_71CHN16 0x1211
|
||||
#define AL_FORMAT_71CHN32 0x1212
|
||||
#endif
|
||||
|
||||
#include "efx.h"
|
||||
|
||||
|
||||
class OpenALSoundStream;
|
||||
|
||||
class OpenALSoundRenderer : public SoundRenderer
|
||||
{
|
||||
public:
|
||||
OpenALSoundRenderer();
|
||||
virtual ~OpenALSoundRenderer();
|
||||
|
||||
virtual void SetSfxVolume(float volume);
|
||||
virtual void SetMusicVolume(float volume);
|
||||
virtual SoundHandle LoadSound(BYTE *sfxdata, int length);
|
||||
virtual SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1);
|
||||
virtual void UnloadSound(SoundHandle sfx);
|
||||
virtual unsigned int GetMSLength(SoundHandle sfx);
|
||||
virtual unsigned int GetSampleLength(SoundHandle sfx);
|
||||
virtual float GetOutputRate();
|
||||
|
||||
// Streaming sounds.
|
||||
virtual SoundStream *CreateStream(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata);
|
||||
virtual SoundStream *OpenStream(FileReader *reader, int flags);
|
||||
|
||||
// Starts a sound.
|
||||
virtual FISoundChannel *StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan);
|
||||
virtual FISoundChannel *StartSound3D(SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan);
|
||||
|
||||
// Changes a channel's volume.
|
||||
virtual void ChannelVolume(FISoundChannel *chan, float volume);
|
||||
|
||||
// Stops a sound channel.
|
||||
virtual void StopChannel(FISoundChannel *chan);
|
||||
|
||||
// Returns position of sound on this channel, in samples.
|
||||
virtual unsigned int GetPosition(FISoundChannel *chan);
|
||||
|
||||
// Synchronizes following sound startups.
|
||||
virtual void Sync(bool sync);
|
||||
|
||||
// Pauses or resumes all sound effect channels.
|
||||
virtual void SetSfxPaused(bool paused, int slot);
|
||||
|
||||
// Pauses or resumes *every* channel, including environmental reverb.
|
||||
virtual void SetInactive(SoundRenderer::EInactiveState inactive);
|
||||
|
||||
// Updates the volume, separation, and pitch of a sound channel.
|
||||
virtual void UpdateSoundParams3D(SoundListener *listener, FISoundChannel *chan, bool areasound, const FVector3 &pos, const FVector3 &vel);
|
||||
|
||||
virtual void UpdateListener(SoundListener *);
|
||||
virtual void UpdateSounds();
|
||||
virtual void UpdateMusic();
|
||||
|
||||
virtual void MarkStartTime(FISoundChannel*);
|
||||
virtual float GetAudibility(FISoundChannel*);
|
||||
|
||||
|
||||
virtual bool IsValid();
|
||||
virtual void PrintStatus();
|
||||
virtual void PrintDriversList();
|
||||
virtual FString GatherStats();
|
||||
|
||||
private:
|
||||
struct {
|
||||
bool EXT_EFX;
|
||||
bool EXT_disconnect;
|
||||
} ALC;
|
||||
struct {
|
||||
bool EXT_source_distance_model;
|
||||
bool SOFT_deferred_updates;
|
||||
bool SOFT_loop_points;
|
||||
} AL;
|
||||
|
||||
// EFX Extension function pointer variables. Loaded after context creation
|
||||
// if EFX is supported. These pointers may be context- or device-dependant,
|
||||
// thus can't be static
|
||||
// Effect objects
|
||||
LPALGENEFFECTS alGenEffects;
|
||||
LPALDELETEEFFECTS alDeleteEffects;
|
||||
LPALISEFFECT alIsEffect;
|
||||
LPALEFFECTI alEffecti;
|
||||
LPALEFFECTIV alEffectiv;
|
||||
LPALEFFECTF alEffectf;
|
||||
LPALEFFECTFV alEffectfv;
|
||||
LPALGETEFFECTI alGetEffecti;
|
||||
LPALGETEFFECTIV alGetEffectiv;
|
||||
LPALGETEFFECTF alGetEffectf;
|
||||
LPALGETEFFECTFV alGetEffectfv;
|
||||
// Filter objects
|
||||
LPALGENFILTERS alGenFilters;
|
||||
LPALDELETEFILTERS alDeleteFilters;
|
||||
LPALISFILTER alIsFilter;
|
||||
LPALFILTERI alFilteri;
|
||||
LPALFILTERIV alFilteriv;
|
||||
LPALFILTERF alFilterf;
|
||||
LPALFILTERFV alFilterfv;
|
||||
LPALGETFILTERI alGetFilteri;
|
||||
LPALGETFILTERIV alGetFilteriv;
|
||||
LPALGETFILTERF alGetFilterf;
|
||||
LPALGETFILTERFV alGetFilterfv;
|
||||
// Auxiliary slot objects
|
||||
LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;
|
||||
LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;
|
||||
LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;
|
||||
LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;
|
||||
LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;
|
||||
LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;
|
||||
LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;
|
||||
LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;
|
||||
LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;
|
||||
LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;
|
||||
LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;
|
||||
|
||||
ALvoid (AL_APIENTRY*alDeferUpdatesSOFT)(void);
|
||||
ALvoid (AL_APIENTRY*alProcessUpdatesSOFT)(void);
|
||||
|
||||
void LoadReverb(const ReverbContainer *env);
|
||||
void PurgeStoppedSources();
|
||||
static FSoundChan *FindLowestChannel();
|
||||
|
||||
ALCdevice *Device;
|
||||
ALCcontext *Context;
|
||||
|
||||
TArray<ALuint> Sources;
|
||||
|
||||
ALfloat SfxVolume;
|
||||
ALfloat MusicVolume;
|
||||
|
||||
int SFXPaused;
|
||||
TArray<ALuint> FreeSfx;
|
||||
TArray<ALuint> PausableSfx;
|
||||
TArray<ALuint> ReverbSfx;
|
||||
TArray<ALuint> SfxGroup;
|
||||
|
||||
const ReverbContainer *PrevEnvironment;
|
||||
|
||||
typedef TMap<WORD,ALuint> EffectMap;
|
||||
typedef TMapIterator<WORD,ALuint> EffectMapIter;
|
||||
ALuint EnvSlot;
|
||||
ALuint EnvFilters[2];
|
||||
EffectMap EnvEffects;
|
||||
|
||||
bool WasInWater;
|
||||
|
||||
TArray<OpenALSoundStream*> Streams;
|
||||
friend class OpenALSoundStream;
|
||||
|
||||
ALCdevice *InitDevice();
|
||||
};
|
||||
|
||||
#endif // NO_OPENAL
|
||||
|
||||
#endif
|
152
src/sound/sndfile_decoder.cpp
Normal file
152
src/sound/sndfile_decoder.cpp
Normal file
|
@ -0,0 +1,152 @@
|
|||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#define USE_WINDOWS_DWORD
|
||||
#endif
|
||||
|
||||
#include "sndfile_decoder.h"
|
||||
#include "templates.h"
|
||||
#include "files.h"
|
||||
#include "xs_Float.h"
|
||||
#include "except.h"
|
||||
|
||||
#ifdef HAVE_SNDFILE
|
||||
|
||||
sf_count_t SndFileDecoder::file_get_filelen(void *user_data)
|
||||
{
|
||||
FileReader *reader = reinterpret_cast<SndFileDecoder*>(user_data)->Reader;
|
||||
return reader->GetLength();
|
||||
}
|
||||
|
||||
sf_count_t SndFileDecoder::file_seek(sf_count_t offset, int whence, void *user_data)
|
||||
{
|
||||
FileReader *reader = reinterpret_cast<SndFileDecoder*>(user_data)->Reader;
|
||||
|
||||
if(reader->Seek((long)offset, whence) != 0)
|
||||
return -1;
|
||||
return reader->Tell();
|
||||
}
|
||||
|
||||
sf_count_t SndFileDecoder::file_read(void *ptr, sf_count_t count, void *user_data)
|
||||
{
|
||||
FileReader *reader = reinterpret_cast<SndFileDecoder*>(user_data)->Reader;
|
||||
return reader->Read(ptr, (long)count);
|
||||
}
|
||||
|
||||
sf_count_t SndFileDecoder::file_write(const void *ptr, sf_count_t count, void *user_data)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sf_count_t SndFileDecoder::file_tell(void *user_data)
|
||||
{
|
||||
FileReader *reader = reinterpret_cast<SndFileDecoder*>(user_data)->Reader;
|
||||
return reader->Tell();
|
||||
}
|
||||
|
||||
|
||||
SndFileDecoder::~SndFileDecoder()
|
||||
{
|
||||
if(SndFile)
|
||||
sf_close(SndFile);
|
||||
SndFile = 0;
|
||||
}
|
||||
|
||||
bool SndFileDecoder::open(FileReader *reader)
|
||||
{
|
||||
__try
|
||||
{
|
||||
SF_VIRTUAL_IO sfio = { file_get_filelen, file_seek, file_read, file_write, file_tell };
|
||||
|
||||
Reader = reader;
|
||||
SndFile = sf_open_virtual(&sfio, SFM_READ, &SndInfo, this);
|
||||
if (SndFile)
|
||||
{
|
||||
if (SndInfo.channels == 1 || SndInfo.channels == 2)
|
||||
return true;
|
||||
|
||||
sf_close(SndFile);
|
||||
SndFile = 0;
|
||||
}
|
||||
}
|
||||
__except (CheckException(GetExceptionCode()))
|
||||
{
|
||||
// this means that the delay loaded decoder DLL was not found.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SndFileDecoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
|
||||
{
|
||||
*samplerate = SndInfo.samplerate;
|
||||
|
||||
if(SndInfo.channels == 2)
|
||||
*chans = ChannelConfig_Stereo;
|
||||
else
|
||||
*chans = ChannelConfig_Mono;
|
||||
|
||||
*type = SampleType_Int16;
|
||||
}
|
||||
|
||||
size_t SndFileDecoder::read(char *buffer, size_t bytes)
|
||||
{
|
||||
short *out = (short*)buffer;
|
||||
size_t frames = bytes / SndInfo.channels / 2;
|
||||
size_t total = 0;
|
||||
|
||||
// It seems libsndfile has a bug with converting float samples from Vorbis
|
||||
// to the 16-bit shorts we use, which causes some PCM samples to overflow
|
||||
// and wrap, creating static. So instead, read the samples as floats and
|
||||
// convert to short ourselves.
|
||||
// Use a loop to convert a handful of samples at a time, avoiding a heap
|
||||
// allocation for temporary storage. 64 at a time works, though maybe it
|
||||
// could be more.
|
||||
while(total < frames)
|
||||
{
|
||||
size_t todo = MIN<size_t>(frames-total, 64/SndInfo.channels);
|
||||
float tmp[64];
|
||||
|
||||
size_t got = (size_t)sf_readf_float(SndFile, tmp, todo);
|
||||
if(got < todo) frames = total + got;
|
||||
|
||||
for(size_t i = 0;i < got*SndInfo.channels;i++)
|
||||
*out++ = (short)xs_CRoundToInt(clamp(tmp[i] * 32767.f, -32768.f, 32767.f));
|
||||
total += got;
|
||||
}
|
||||
return total * SndInfo.channels * 2;
|
||||
}
|
||||
|
||||
TArray<char> SndFileDecoder::readAll()
|
||||
{
|
||||
if(SndInfo.frames <= 0)
|
||||
return SoundDecoder::readAll();
|
||||
|
||||
int framesize = 2 * SndInfo.channels;
|
||||
TArray<char> output;
|
||||
|
||||
output.Resize((unsigned)(SndInfo.frames * framesize));
|
||||
size_t got = read(&output[0], output.Size());
|
||||
output.Resize(got);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
bool SndFileDecoder::seek(size_t ms_offset)
|
||||
{
|
||||
size_t smp_offset = (size_t)((double)ms_offset / 1000. * SndInfo.samplerate);
|
||||
if(sf_seek(SndFile, smp_offset, SEEK_SET) < 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t SndFileDecoder::getSampleOffset()
|
||||
{
|
||||
return (size_t)sf_seek(SndFile, 0, SEEK_CUR);
|
||||
}
|
||||
|
||||
size_t SndFileDecoder::getSampleLength()
|
||||
{
|
||||
return (size_t)((SndInfo.frames > 0) ? SndInfo.frames : 0);
|
||||
}
|
||||
|
||||
#endif
|
44
src/sound/sndfile_decoder.h
Normal file
44
src/sound/sndfile_decoder.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifndef SNDFILE_DECODER_H
|
||||
#define SNDFILE_DECODER_H
|
||||
|
||||
#include "i_soundinternal.h"
|
||||
|
||||
#ifdef HAVE_SNDFILE
|
||||
|
||||
#include "sndfile.h"
|
||||
|
||||
struct SndFileDecoder : public SoundDecoder
|
||||
{
|
||||
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
|
||||
|
||||
virtual size_t read(char *buffer, size_t bytes);
|
||||
virtual TArray<char> readAll();
|
||||
virtual bool seek(size_t ms_offset);
|
||||
virtual size_t getSampleOffset();
|
||||
virtual size_t getSampleLength();
|
||||
|
||||
SndFileDecoder() : SndFile(0) { }
|
||||
virtual ~SndFileDecoder();
|
||||
|
||||
protected:
|
||||
virtual bool open(FileReader *reader);
|
||||
|
||||
private:
|
||||
SNDFILE *SndFile;
|
||||
SF_INFO SndInfo;
|
||||
|
||||
FileReader *Reader;
|
||||
static sf_count_t file_get_filelen(void *user_data);
|
||||
static sf_count_t file_seek(sf_count_t offset, int whence, void *user_data);
|
||||
static sf_count_t file_read(void *ptr, sf_count_t count, void *user_data);
|
||||
static sf_count_t file_write(const void *ptr, sf_count_t count, void *user_data);
|
||||
static sf_count_t file_tell(void *user_data);
|
||||
|
||||
// Make non-copyable
|
||||
SndFileDecoder(const SndFileDecoder &rhs);
|
||||
SndFileDecoder& operator=(const SndFileDecoder &rhs);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SNDFILE_DECODER_H */
|
11
src/tarray.h
11
src/tarray.h
|
@ -160,6 +160,17 @@ public:
|
|||
return Array[Count-1];
|
||||
}
|
||||
|
||||
unsigned int Find(const T& item) const
|
||||
{
|
||||
unsigned int i;
|
||||
for(i = 0;i < Count;++i)
|
||||
{
|
||||
if(Array[i] == item)
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
unsigned int Push (const T &item)
|
||||
{
|
||||
Grow (1);
|
||||
|
|
|
@ -1679,6 +1679,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RailAttack)
|
|||
PARAM_FLOAT_OPT (driftspeed) { driftspeed = 1; }
|
||||
PARAM_CLASS_OPT (spawnclass, AActor){ spawnclass = NULL; }
|
||||
PARAM_FIXED_OPT (spawnofs_z) { spawnofs_z = 0; }
|
||||
PARAM_INT_OPT (SpiralOffset) { SpiralOffset = 270; }
|
||||
|
||||
if (range == 0) range = 8192*FRACUNIT;
|
||||
if (sparsity == 0) sparsity=1.0;
|
||||
|
@ -1709,7 +1710,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RailAttack)
|
|||
slope = pr_crailgun.Random2() * (spread_z / 255);
|
||||
}
|
||||
|
||||
P_RailAttack (self, damage, spawnofs_xy, spawnofs_z, color1, color2, maxdiff, flags, pufftype, angle, slope, range, duration, sparsity, driftspeed, spawnclass);
|
||||
P_RailAttack (self, damage, spawnofs_xy, spawnofs_z, color1, color2, maxdiff, flags, pufftype, angle, slope, range, duration, sparsity, driftspeed, spawnclass, SpiralOffset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1745,6 +1746,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
|
|||
PARAM_FLOAT_OPT (driftspeed) { driftspeed = 1; }
|
||||
PARAM_CLASS_OPT (spawnclass, AActor){ spawnclass = NULL; }
|
||||
PARAM_FIXED_OPT (spawnofs_z) { spawnofs_z = 0; }
|
||||
PARAM_INT_OPT (SpiralOffset) { SpiralOffset = 270; }
|
||||
|
||||
if (range == 0) range = 8192*FRACUNIT;
|
||||
if (sparsity == 0) sparsity = 1;
|
||||
|
@ -1828,7 +1830,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
|
|||
slopeoffset = pr_crailgun.Random2() * (spread_z / 255);
|
||||
}
|
||||
|
||||
P_RailAttack (self, damage, spawnofs_xy, spawnofs_z, color1, color2, maxdiff, flags, pufftype, angleoffset, slopeoffset, range, duration, sparsity, driftspeed, spawnclass);
|
||||
P_RailAttack (self, damage, spawnofs_xy, spawnofs_z, color1, color2, maxdiff, flags, pufftype, angleoffset, slopeoffset, range, duration, sparsity, driftspeed, spawnclass,SpiralOffset);
|
||||
|
||||
self->x = saved_x;
|
||||
self->y = saved_y;
|
||||
|
@ -4871,7 +4873,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LineEffect)
|
|||
if ((oldjunk.special = special)) // Linedef type
|
||||
{
|
||||
oldjunk.tag = tag; // Sector tag for linedef
|
||||
P_TranslateLineDef(&junk, &oldjunk, false); // Turn into native type
|
||||
P_TranslateLineDef(&junk, &oldjunk); // Turn into native type
|
||||
res = !!P_ExecuteSpecial(junk.special, NULL, self, false, junk.args[0],
|
||||
junk.args[1], junk.args[2], junk.args[3], junk.args[4]);
|
||||
if (res && !(junk.flags & ML_REPEAT_SPECIAL)) // If only once,
|
||||
|
|
|
@ -333,6 +333,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag
|
|||
int intval;
|
||||
bool translationset = false;
|
||||
bool virtBottom;
|
||||
bool fillcolorset = false;
|
||||
|
||||
if (img == NULL || img->UseType == FTexture::TEX_Null)
|
||||
{
|
||||
|
@ -539,6 +540,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag
|
|||
|
||||
case DTA_FillColor:
|
||||
parms->fillcolor = va_arg(tags, uint32);
|
||||
fillcolorset = true;
|
||||
break;
|
||||
|
||||
case DTA_Translation:
|
||||
|
@ -711,7 +713,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag
|
|||
|
||||
if (parms->style.BlendOp == 255)
|
||||
{
|
||||
if (parms->fillcolor != ~0u)
|
||||
if (fillcolorset)
|
||||
{
|
||||
if (parms->alphaChannel)
|
||||
{
|
||||
|
|
|
@ -74,7 +74,7 @@ enum
|
|||
DTA_DestWidth, // width of area to draw to
|
||||
DTA_DestHeight, // height of area to draw to
|
||||
DTA_Alpha, // alpha value for translucency
|
||||
DTA_FillColor, // color to stencil onto the destination
|
||||
DTA_FillColor, // color to stencil onto the destination (RGB is the color for truecolor drawers, A is the palette index for paletted drawers)
|
||||
DTA_Translation, // translation table to recolor the source
|
||||
DTA_AlphaChannel, // bool: the source is an alpha channel; used with DTA_FillColor
|
||||
DTA_Clean, // bool: scale texture size and position by CleanXfac and CleanYfac
|
||||
|
|
|
@ -76,7 +76,7 @@ const char *GetVersionString();
|
|||
|
||||
// Use 4500 as the base git save version, since it's higher than the
|
||||
// SVN revision ever got.
|
||||
#define SAVEVER 4522
|
||||
#define SAVEVER 4523
|
||||
|
||||
#define SAVEVERSTRINGIFY2(x) #x
|
||||
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)
|
||||
|
|
|
@ -1228,6 +1228,17 @@ FWadLump *FWadCollection::ReopenLumpNum (int lump)
|
|||
return new FWadLump(LumpInfo[lump].lump, true);
|
||||
}
|
||||
|
||||
FWadLump *FWadCollection::ReopenLumpNumNewFile (int lump)
|
||||
{
|
||||
if ((unsigned)lump >= (unsigned)LumpInfo.Size())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new FWadLump(lump, LumpInfo[lump].lump);
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// GetFileReader
|
||||
|
@ -1417,6 +1428,34 @@ FWadLump::FWadLump(FResourceLump *lump, bool alwayscache)
|
|||
}
|
||||
}
|
||||
|
||||
FWadLump::FWadLump(int lumpnum, FResourceLump *lump)
|
||||
: FileReader()
|
||||
{
|
||||
FileReader *f = lump->GetReader();
|
||||
|
||||
if (f != NULL && f->GetFile() != NULL)
|
||||
{
|
||||
// Uncompressed lump in a file. For this we will have to open a new FILE, since we need it for streaming
|
||||
int fileno = Wads.GetLumpFile(lumpnum);
|
||||
const char *filename = Wads.GetWadFullName(fileno);
|
||||
File = fopen(filename, "rb");
|
||||
if (File != NULL)
|
||||
{
|
||||
Length = lump->LumpSize;
|
||||
StartPos = FilePos = lump->GetFileOffset();
|
||||
Lump = NULL;
|
||||
CloseOnDestruct = true;
|
||||
Seek(0, SEEK_SET);
|
||||
return;
|
||||
}
|
||||
}
|
||||
File = NULL;
|
||||
Length = lump->LumpSize;
|
||||
StartPos = FilePos = 0;
|
||||
Lump = lump;
|
||||
Lump->CacheLump();
|
||||
}
|
||||
|
||||
FWadLump::~FWadLump()
|
||||
{
|
||||
if (Lump != NULL)
|
||||
|
|
|
@ -112,6 +112,7 @@ public:
|
|||
|
||||
private:
|
||||
FWadLump (FResourceLump *Lump, bool alwayscache = false);
|
||||
FWadLump(int lumpnum, FResourceLump *lump);
|
||||
|
||||
FResourceLump *Lump;
|
||||
|
||||
|
@ -185,6 +186,7 @@ public:
|
|||
FWadLump OpenLumpNum (int lump);
|
||||
FWadLump OpenLumpName (const char *name) { return OpenLumpNum (GetNumForName (name)); }
|
||||
FWadLump *ReopenLumpNum (int lump); // Opens a new, independent FILE
|
||||
FWadLump *ReopenLumpNumNewFile (int lump); // Opens a new, independent FILE
|
||||
|
||||
FileReader * GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD
|
||||
|
||||
|
|
|
@ -1600,13 +1600,20 @@ unsigned int I_MakeRNGSeed()
|
|||
|
||||
FString I_GetLongPathName(FString shortpath)
|
||||
{
|
||||
DWORD buffsize = GetLongPathName(shortpath.GetChars(), NULL, 0);
|
||||
static TOptWin32Proc<DWORD (WINAPI*)(LPCTSTR, LPTSTR, DWORD)>
|
||||
GetLongPathNameA("kernel32.dll", "GetLongPathNameA");
|
||||
|
||||
// Doesn't exist on NT4
|
||||
if (GetLongPathName == NULL)
|
||||
return shortpath;
|
||||
|
||||
DWORD buffsize = GetLongPathNameA.Call(shortpath.GetChars(), NULL, 0);
|
||||
if (buffsize == 0)
|
||||
{ // nothing to change (it doesn't exist, maybe?)
|
||||
return shortpath;
|
||||
}
|
||||
TCHAR *buff = new TCHAR[buffsize];
|
||||
DWORD buffsize2 = GetLongPathName(shortpath.GetChars(), buff, buffsize);
|
||||
DWORD buffsize2 = GetLongPathNameA.Call(shortpath.GetChars(), buff, buffsize);
|
||||
if (buffsize2 >= buffsize)
|
||||
{ // Failure! Just return the short path
|
||||
delete[] buff;
|
||||
|
|
|
@ -51,6 +51,30 @@ typedef enum {
|
|||
|
||||
extern os_t OSPlatform;
|
||||
|
||||
// Helper template so that we can access newer Win32 functions with a single static
|
||||
// variable declaration. If this were C++11 it could be totally transparent.
|
||||
template<typename Proto>
|
||||
class TOptWin32Proc
|
||||
{
|
||||
static Proto GetOptionalWin32Proc(const char* module, const char* function)
|
||||
{
|
||||
HMODULE hmodule = GetModuleHandle(module);
|
||||
if (hmodule == NULL)
|
||||
return NULL;
|
||||
|
||||
return (Proto)GetProcAddress(hmodule, function);
|
||||
}
|
||||
|
||||
public:
|
||||
const Proto Call;
|
||||
|
||||
TOptWin32Proc(const char* module, const char* function)
|
||||
: Call(GetOptionalWin32Proc(module, function)) {}
|
||||
|
||||
// Wrapper object can be tested against NULL, but not directly called.
|
||||
operator const void*() const { return Call; }
|
||||
};
|
||||
|
||||
// Called by DoomMain.
|
||||
void I_Init (void);
|
||||
|
||||
|
|
|
@ -414,7 +414,10 @@ void Win32Video::DumpAdapters()
|
|||
HMONITOR hm = D3D->GetAdapterMonitor(i);
|
||||
MONITORINFOEX mi;
|
||||
mi.cbSize = sizeof(mi);
|
||||
if (GetMonitorInfo(hm, &mi))
|
||||
|
||||
TOptWin32Proc<BOOL(WINAPI*)(HMONITOR, LPMONITORINFO)> GetMonitorInfo("user32.dll", "GetMonitorInfoW");
|
||||
assert(GetMonitorInfo != NULL); // Missing in NT4, but so is D3D
|
||||
if (GetMonitorInfo.Call(hm, &mi))
|
||||
{
|
||||
mysnprintf(moreinfo, countof(moreinfo), " [%ldx%ld @ (%ld,%ld)]%s",
|
||||
mi.rcMonitor.right - mi.rcMonitor.left,
|
||||
|
|
|
@ -178,7 +178,7 @@ ACTOR Actor native //: Thinker
|
|||
action native A_Jump(int chance = 256, state label, ...);
|
||||
action native A_CustomMissile(class<Actor> missiletype, float spawnheight = 32, int spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0, int ptr = AAPTR_TARGET);
|
||||
action native A_CustomBulletAttack(float/*angle*/ spread_xy, float/*angle*/ spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET);
|
||||
action native A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, int aim = 0, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float/*angle*/ spread_xy = 0, float/*angle*/ spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none", float spawnofs_z = 0);
|
||||
action native A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, int aim = 0, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float/*angle*/ spread_xy = 0, float/*angle*/ spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270);
|
||||
action native A_JumpIfHealthLower(int health, state label, int ptr_selector = AAPTR_DEFAULT);
|
||||
action native A_JumpIfCloser(float distance, state label);
|
||||
action native A_JumpIfTracerCloser(float distance, state label);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue