From 204d0c8572a6397fc0ac778d991f5b7432caea1c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 26 Apr 2016 05:55:18 -0700 Subject: [PATCH 01/15] Don't try to define __try/__except on non-MSVC systems They didn't do anything anyway, and can clash with other compilers since they may be used internally (macros and keywords starting with __ are for compiler use). --- src/sound/except.h | 15 +-------------- src/sound/fmodsound.cpp | 4 ++-- src/sound/mpg123_decoder.cpp | 11 ++++++----- src/sound/sndfile_decoder.cpp | 11 ++++++----- 4 files changed, 15 insertions(+), 26 deletions(-) diff --git a/src/sound/except.h b/src/sound/except.h index 023ddb6d4..f6bef4fc6 100644 --- a/src/sound/except.h +++ b/src/sound/except.h @@ -23,19 +23,6 @@ inline int CheckException(DWORD code) return EXCEPTION_CONTINUE_SEARCH; } - -#else - -#ifdef __try -#undef __try -#endif -#define __try - -#ifdef __except -#undef __except -#endif -#define __except(a) if (0) - #endif -#endif \ No newline at end of file +#endif diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index a62998d3d..3d0f0ba67 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -3192,8 +3192,8 @@ 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. +#elif !defined _MSC_VER + return true; // on non-MSVC we cannot delay load the library so it has to be present. #else static bool cached_result; static bool done = false; diff --git a/src/sound/mpg123_decoder.cpp b/src/sound/mpg123_decoder.cpp index 4deab7e5b..9d1fff97e 100644 --- a/src/sound/mpg123_decoder.cpp +++ b/src/sound/mpg123_decoder.cpp @@ -56,17 +56,18 @@ bool MPG123Decoder::open(FileReader *reader) { if(!inited) { - __try - { +#ifdef _MSC_VER + __try { +#endif if(mpg123_init() != MPG123_OK) return false; inited = true; - } - __except (CheckException(GetExceptionCode())) - { +#ifdef _MSC_VER + } __except (CheckException(GetExceptionCode())) { // this means that the delay loaded decoder DLL was not found. return false; } +#endif } Reader = reader; diff --git a/src/sound/sndfile_decoder.cpp b/src/sound/sndfile_decoder.cpp index 382b22ab6..b0c35c2a0 100644 --- a/src/sound/sndfile_decoder.cpp +++ b/src/sound/sndfile_decoder.cpp @@ -54,8 +54,9 @@ SndFileDecoder::~SndFileDecoder() bool SndFileDecoder::open(FileReader *reader) { - __try - { +#ifdef _MSC_VER + __try { +#endif SF_VIRTUAL_IO sfio = { file_get_filelen, file_seek, file_read, file_write, file_tell }; Reader = reader; @@ -68,11 +69,11 @@ bool SndFileDecoder::open(FileReader *reader) sf_close(SndFile); SndFile = 0; } - } - __except (CheckException(GetExceptionCode())) - { +#ifdef _MSC_VER + } __except (CheckException(GetExceptionCode())) { // this means that the delay loaded decoder DLL was not found. } +#endif return false; } From 6e25d3f618a039ad7ad038425d394409a2bfd0d6 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 26 Apr 2016 06:12:56 -0700 Subject: [PATCH 02/15] Use a background thread for processing OpenAL streams --- src/d_main.cpp | 2 - src/s_sound.cpp | 11 --- src/s_sound.h | 1 - src/sound/i_sound.h | 1 - src/sound/oalsound.cpp | 202 +++++++++++++++++++++++++++-------------- src/sound/oalsound.h | 14 ++- 6 files changed, 145 insertions(+), 86 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 84e03cdaa..4c0d2537d 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -913,7 +913,6 @@ 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 @@ -1012,7 +1011,6 @@ 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. :( if (wantToRestart) { wantToRestart = false; diff --git a/src/s_sound.cpp b/src/s_sound.cpp index ac4dbc78f..8cafa4d6a 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -2605,17 +2605,6 @@ void S_StopMusic (bool force) } } -//========================================================================== -// -// -// -//========================================================================== - -void S_UpdateMusic() -{ - GSnd->UpdateMusic(); -} - //========================================================================== // // CCMD playsound diff --git a/src/s_sound.h b/src/s_sound.h index ad06195e1..a3a1a39f3 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -329,7 +329,6 @@ 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); diff --git a/src/sound/i_sound.h b/src/sound/i_sound.h index 836d62019..426dcadbd 100644 --- a/src/sound/i_sound.h +++ b/src/sound/i_sound.h @@ -147,7 +147,6 @@ public: virtual void UpdateListener (SoundListener *) = 0; virtual void UpdateSounds () = 0; - virtual void UpdateMusic() {} virtual bool IsValid () = 0; virtual void PrintStatus () = 0; diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 9b7de9e43..560446732 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -218,7 +218,7 @@ class OpenALSoundStream : public SoundStream ALuint Buffers[BufferCount]; ALuint Source; - bool Playing; + std::atomic Playing; bool Looping; ALfloat Volume; @@ -282,12 +282,14 @@ public: OpenALSoundStream(OpenALSoundRenderer *renderer) : Renderer(renderer), Source(0), Playing(false), Looping(false), Volume(1.0f), Reader(NULL), Decoder(NULL) { - Renderer->Streams.Push(this); memset(Buffers, 0, sizeof(Buffers)); + Renderer->AddStream(this); } virtual ~OpenALSoundStream() { + Renderer->RemoveStream(this); + if(Source) { alSourceRewind(Source); @@ -304,9 +306,6 @@ public: } getALError(); - Renderer->Streams.Delete(Renderer->Streams.Find(this)); - Renderer = NULL; - delete Decoder; delete Reader; } @@ -316,7 +315,7 @@ public: { SetVolume(vol); - if(Playing) + if(Playing.load()) return true; /* Clear the buffer queue, then fill and queue each buffer */ @@ -337,21 +336,24 @@ public: return false; alSourcePlay(Source); - Playing = (getALError()==AL_NO_ERROR); + if(getALError() != AL_NO_ERROR) + return false; - return Playing; + Playing.store(true); + return true; } virtual void Stop() { - if(!Playing) + if(!Playing.load()) return; + std::unique_lock lock(Renderer->StreamLock); alSourceStop(Source); alSourcei(Source, AL_BUFFER, 0); getALError(); - Playing = false; + Playing.store(false); } virtual void SetVolume(float vol) @@ -377,21 +379,25 @@ public: virtual bool SetPosition(unsigned int ms_pos) { + std::unique_lock lock(Renderer->StreamLock); if(!Decoder->seek(ms_pos)) return false; - if(!Playing) + if(!Playing.load()) return true; - // Stop the source so that all buffers become processed, then call - // IsEnded() to refill and restart the source queue with the new + // Stop the source so that all buffers become processed, which will + // allow the next update to restart the source queue with the new // position. alSourceStop(Source); getALError(); - return !IsEnded(); + lock.unlock(); + Renderer->StreamWake.notify_all(); + return true; } virtual unsigned int GetPosition() { + std::unique_lock lock(Renderer->StreamLock); ALint offset, queued, state; alGetSourcei(Source, AL_SAMPLE_OFFSET, &offset); alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued); @@ -400,6 +406,8 @@ public: return 0; size_t pos = Decoder->getSampleOffset(); + lock.unlock(); + if(state != AL_STOPPED) { size_t rem = queued*(Data.Size()/FrameSize) - offset; @@ -411,54 +419,10 @@ public: virtual bool IsEnded() { - if(!Playing) - return true; - - ALint state, processed; - alGetSourcei(Source, AL_SOURCE_STATE, &state); - alGetSourcei(Source, AL_BUFFERS_PROCESSED, &processed); - - Playing = (getALError()==AL_NO_ERROR); - if(!Playing) - return true; - - // For each processed buffer in the queue... - while(processed > 0) - { - ALuint bufid; - - // Unqueue the oldest buffer, fill it with more data, and queue it - // on the end - alSourceUnqueueBuffers(Source, 1, &bufid); - processed--; - - if(Callback(this, &Data[0], Data.Size(), UserData)) - { - alBufferData(bufid, Format, &Data[0], Data.Size(), SampleRate); - alSourceQueueBuffers(Source, 1, &bufid); - } - } - - // If the source is not playing or paused, and there are buffers queued, - // then there was an underrun. Restart the source. - Playing = (getALError()==AL_NO_ERROR); - if(Playing && state != AL_PLAYING && state != AL_PAUSED) - { - ALint queued = 0; - alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued); - - Playing = (getALError() == AL_NO_ERROR) && (queued > 0); - if(Playing) - { - alSourcePlay(Source); - Playing = (getALError()==AL_NO_ERROR); - } - } - - return !Playing; + return !Playing.load(); } - FString GetStats() + virtual FString GetStats() { FString stats; size_t pos, len; @@ -469,6 +433,7 @@ public: ALint state; ALenum err; + std::unique_lock lock(Renderer->StreamLock); alGetSourcef(Source, AL_GAIN, &volume); alGetSourcei(Source, AL_SAMPLE_OFFSET, &offset); alGetSourcei(Source, AL_BUFFERS_PROCESSED, &processed); @@ -476,16 +441,19 @@ public: alGetSourcei(Source, AL_SOURCE_STATE, &state); if((err=alGetError()) != AL_NO_ERROR) { + lock.unlock(); stats = "Error getting stats: "; stats += alGetString(err); return stats; } + pos = Decoder->getSampleOffset(); + len = Decoder->getSampleLength(); + lock.unlock(); + stats = (state == AL_INITIAL) ? "Buffering" : (state == AL_STOPPED) ? "Underrun" : (state == AL_PLAYING || state == AL_PAUSED) ? "Ready" : "Unknown state"; - pos = Decoder->getSampleOffset(); - len = Decoder->getSampleLength(); if(state == AL_STOPPED) offset = BufferCount * (Data.Size()/FrameSize); else @@ -511,6 +479,57 @@ public: return stats; } + bool Process() + { + if(!Playing.load()) + return false; + + ALint state, processed; + alGetSourcei(Source, AL_SOURCE_STATE, &state); + alGetSourcei(Source, AL_BUFFERS_PROCESSED, &processed); + if(getALError() != AL_NO_ERROR) + { + Playing.store(false); + return false; + } + + // For each processed buffer in the queue... + while(processed > 0) + { + ALuint bufid; + + // Unqueue the oldest buffer, fill it with more data, and queue it + // on the end + alSourceUnqueueBuffers(Source, 1, &bufid); + processed--; + + if(Callback(this, &Data[0], Data.Size(), UserData)) + { + alBufferData(bufid, Format, &Data[0], Data.Size(), SampleRate); + alSourceQueueBuffers(Source, 1, &bufid); + } + } + + // If the source is not playing or paused, and there are buffers queued, + // then there was an underrun. Restart the source. + bool ok = (getALError()==AL_NO_ERROR); + if(ok && state != AL_PLAYING && state != AL_PAUSED) + { + ALint queued = 0; + alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued); + + ok = (getALError() == AL_NO_ERROR) && (queued > 0); + if(ok) + { + alSourcePlay(Source); + ok = (getALError()==AL_NO_ERROR); + } + } + + Playing.store(ok); + return ok; + } + bool Init(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) { if(!SetupSource()) @@ -688,7 +707,7 @@ static void LoadALFunc(const char *name, T *x) #define LOAD_FUNC(x) (LoadALFunc(#x, &x)) OpenALSoundRenderer::OpenALSoundRenderer() - : Device(NULL), Context(NULL), SFXPaused(0), PrevEnvironment(NULL), EnvSlot(0) + : QuitThread(false), Device(NULL), Context(NULL), SFXPaused(0), PrevEnvironment(NULL), EnvSlot(0) { EnvFilters[0] = EnvFilters[1] = 0; @@ -912,6 +931,15 @@ OpenALSoundRenderer::~OpenALSoundRenderer() if(!Device) return; + if(StreamThread.joinable()) + { + std::unique_lock lock(StreamLock); + QuitThread.store(true); + lock.unlock(); + StreamWake.notify_all(); + StreamThread.join(); + } + while(Streams.Size() > 0) delete Streams[0]; @@ -946,6 +974,43 @@ OpenALSoundRenderer::~OpenALSoundRenderer() Device = NULL; } +void OpenALSoundRenderer::BackgroundProc() +{ + std::unique_lock lock(StreamLock); + while(!QuitThread.load()) + { + if(Streams.Size() == 0) + { + // If there's nothing to play, wait indefinitely. + StreamWake.wait(lock); + } + else + { + // Else, process all active streams and sleep for 100ms + for(size_t i = 0;i < Streams.Size();i++) + Streams[i]->Process(); + StreamWake.wait_for(lock, std::chrono::milliseconds(100)); + } + } +} + +void OpenALSoundRenderer::AddStream(OpenALSoundStream *stream) +{ + std::unique_lock lock(StreamLock); + Streams.Push(stream); + lock.unlock(); + // There's a stream to play, make sure the background thread is aware + StreamWake.notify_all(); +} + +void OpenALSoundRenderer::RemoveStream(OpenALSoundStream *stream) +{ + std::unique_lock lock(StreamLock); + unsigned int idx = Streams.Find(stream); + if(idx < Streams.Size()) + Streams.Delete(idx); +} + void OpenALSoundRenderer::SetSfxVolume(float volume) { SfxVolume = volume; @@ -1172,6 +1237,8 @@ void OpenALSoundRenderer::UnloadSound(SoundHandle sfx) SoundStream *OpenALSoundRenderer::CreateStream(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) { + if(StreamThread.get_id() == std::thread::id()) + StreamThread = std::thread(std::mem_fn(&OpenALSoundRenderer::BackgroundProc), this); OpenALSoundStream *stream = new OpenALSoundStream(this); if (!stream->Init(callback, buffbytes, flags, samplerate, userdata)) { @@ -1183,6 +1250,8 @@ SoundStream *OpenALSoundRenderer::CreateStream(SoundStreamCallback callback, int SoundStream *OpenALSoundRenderer::OpenStream(FileReader *reader, int flags) { + if(StreamThread.get_id() == std::thread::id()) + StreamThread = std::thread(std::mem_fn(&OpenALSoundRenderer::BackgroundProc), this); OpenALSoundStream *stream = new OpenALSoundStream(this); if (!stream->Init(reader, !!(flags&SoundStream::Loop))) { @@ -1741,13 +1810,6 @@ void OpenALSoundRenderer::UpdateSounds() PurgeStoppedSources(); } -void OpenALSoundRenderer::UpdateMusic() -{ - // For some reason this isn't being called? - for(uint32 i = 0;i < Streams.Size();++i) - Streams[i]->IsEnded(); -} - bool OpenALSoundRenderer::IsValid() { return Device != NULL; diff --git a/src/sound/oalsound.h b/src/sound/oalsound.h index f528dbc6a..525078dc6 100644 --- a/src/sound/oalsound.h +++ b/src/sound/oalsound.h @@ -1,6 +1,11 @@ #ifndef OALSOUND_H #define OALSOUND_H +#include +#include +#include +#include + #include "i_sound.h" #include "s_sound.h" #include "menu/menu.h" @@ -109,7 +114,6 @@ public: virtual void UpdateListener(SoundListener *); virtual void UpdateSounds(); - virtual void UpdateMusic(); virtual void MarkStartTime(FISoundChannel*); virtual float GetAudibility(FISoundChannel*); @@ -174,10 +178,18 @@ private: ALvoid (AL_APIENTRY*alDeferUpdatesSOFT)(void); ALvoid (AL_APIENTRY*alProcessUpdatesSOFT)(void); + void BackgroundProc(); + void AddStream(OpenALSoundStream *stream); + void RemoveStream(OpenALSoundStream *stream); void LoadReverb(const ReverbContainer *env); void PurgeStoppedSources(); static FSoundChan *FindLowestChannel(); + std::thread StreamThread; + std::mutex StreamLock; + std::condition_variable StreamWake; + std::atomic QuitThread; + ALCdevice *Device; ALCcontext *Context; From fe966916d75bd53aa8a8ba884bc550cac35514cd Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 16 May 2016 17:02:39 -0700 Subject: [PATCH 03/15] Set head-relative for sources near the listener This matches the behavior of the FMOD backend --- src/sound/oalsound.cpp | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index bf7bede82..ac6a7aedb 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -1460,7 +1460,17 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener } dir += listener->position; - alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); + if(dist_sqr < (0.0004f*0.0004f)) + { + // Head relative + alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); + alSource3f(source, AL_POSITION, 0.f, 0.f, 0.f); + } + else + { + alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); + alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); + } } else { @@ -1478,12 +1488,21 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener dir += listener->position; } - alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); + if(dist_sqr < (0.0004f*0.0004f)) + { + // Head relative + alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); + alSource3f(source, AL_POSITION, 0.f, 0.f, 0.f); + } + else + { + alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); + alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); + } } alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); alSource3f(source, AL_DIRECTION, 0.f, 0.f, 0.f); - alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); alSourcei(source, AL_LOOPING, (chanflags&SNDF_LOOP) ? AL_TRUE : AL_FALSE); alSourcef(source, AL_MAX_GAIN, SfxVolume); @@ -1724,9 +1743,18 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh dir += listener->position; alDeferUpdatesSOFT(); - ALuint source = GET_PTRID(chan->SysChannel); - alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); + + if(chan->DistanceSqr < (0.0004f*0.0004f)) + { + alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); + alSource3f(source, AL_POSITION, 0.f, 0.f, 0.f); + } + else + { + alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); + alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); + } alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); getALError(); } From 362e21a6b32e3aa1b773afcf9dd8fb4a28a34722 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 17 May 2016 09:12:26 +0200 Subject: [PATCH 04/15] - fixed: The pitch negation required for INHERITACTORPITCH was also applied to the one from PITCHFROMMOMENTUM. --- src/gl/models/gl_models.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index c87cb52c2..a79e5ba7c 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -963,7 +963,7 @@ void gl_RenderModel(GLSprite * spr) // Added MDL_INHERITACTORPITCH and MDL_INHERITACTORROLL flags processing. // If both flags MDL_INHERITACTORPITCH and MDL_PITCHFROMMOMENTUM are set, the pitch sums up the actor pitch and the momentum vector pitch. - if(smf->flags & MDL_INHERITACTORPITCH) pitch += spr->actor->Angles.Pitch.Degrees; + if(smf->flags & MDL_INHERITACTORPITCH) pitch -= spr->actor->Angles.Pitch.Degrees; if(smf->flags & MDL_INHERITACTORROLL) roll += spr->actor->Angles.Roll.Degrees; gl_RenderState.mModelMatrix.loadIdentity(); @@ -974,7 +974,7 @@ void gl_RenderModel(GLSprite * spr) // Applying model transformations: // 1) Applying actor angle, pitch and roll to the model gl_RenderState.mModelMatrix.rotate(-angle, 0, 1, 0); - gl_RenderState.mModelMatrix.rotate(-pitch, 0, 0, 1); + gl_RenderState.mModelMatrix.rotate(pitch, 0, 0, 1); gl_RenderState.mModelMatrix.rotate(-roll, 1, 0, 0); // 2) Applying Doomsday like rotation of the weapon pickup models From 661c2e5919f7f35d6b553e4e6a778bb5583e23a4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 18 May 2016 09:39:19 +0200 Subject: [PATCH 05/15] - added missing NULL pointer check to ACS's CheckInventory. --- src/p_acs.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 032abbc27..3248e738c 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1333,9 +1333,13 @@ static int CheckInventory (AActor *activator, const char *type, bool max) if (max) { if (item) + { return item->MaxAmount; - else - return ((AInventory *)GetDefaultByType (info))->MaxAmount; + } + else if (info != nullptr && info->IsDescendantOf(RUNTIME_CLASS(AInventory))) + { + return ((AInventory *)GetDefaultByType(info))->MaxAmount; + } } return item ? item->Amount : 0; } From 115dbd0b58876fd3fcb0fc0c9e52f06e8d366c76 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Tue, 17 May 2016 15:44:03 -0500 Subject: [PATCH 06/15] - Added A_WeaponOffset(x = 0, y = 32, flags). - Places the weapon offset by the defined x and y. Both are floats. This stacks with weapon bobbing. - WOF_KEEPX: Don't change the X offset. - WOF_KEEPY: Don't change the Y offset. - WOF_ADD: Add onto instead of replacing the coordinates. --- src/p_pspr.cpp | 57 +++++++++++++++++++++++ wadsrc/static/actors/constants.txt | 8 ++++ wadsrc/static/actors/shared/inventory.txt | 1 + 3 files changed, 66 insertions(+) diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index d7da8fa4c..fad782b41 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -783,6 +783,63 @@ DEFINE_ACTION_FUNCTION(AInventory, A_CheckReload) return 0; } +//--------------------------------------------------------------------------- +// +// PROC A_WeaponOffset +// +//--------------------------------------------------------------------------- +enum WOFFlags +{ + WOF_KEEPX = 1, + WOF_KEEPY = 1 << 1, + WOF_ADD = 1 << 2, +}; + +DEFINE_ACTION_FUNCTION(AInventory, A_WeaponOffset) +{ + PARAM_ACTION_PROLOGUE; + PARAM_FLOAT_OPT(wx) { wx = 0.; } + PARAM_FLOAT_OPT(wy) { wy = 32.; } + PARAM_INT_OPT(flags) { flags = 0; } + + if ((flags & WOF_KEEPX) && (flags & WOF_KEEPY)) + { + return 0; + } + + player_t *player = self->player; + pspdef_t *psp; + + if (player && (player->playerstate != PST_DEAD)) + { + psp = &player->psprites[ps_weapon]; + if (!(flags & WOF_KEEPX)) + { + if (flags & WOF_ADD) + { + psp->sx += wx; + } + else + { + psp->sx = wx; + } + } + if (!(flags & WOF_KEEPY)) + { + if (flags & WOF_ADD) + { + psp->sy += wy; + } + else + { + psp->sy = wy; + } + } + } + + return 0; +} + //--------------------------------------------------------------------------- // // PROC A_Lower diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 2468174b7..911e1036b 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -561,3 +561,11 @@ enum GZF_NOPORTALS = 1 << 4, // Don't pass through any portals. GZF_NO3DFLOOR = 1 << 5, // Pass all 3D floors. }; + +// Flags for A_WeaponOffset +enum +{ + WOF_KEEPX = 1, + WOF_KEEPY = 1 << 1, + WOF_ADD = 1 << 2, +}; \ No newline at end of file diff --git a/wadsrc/static/actors/shared/inventory.txt b/wadsrc/static/actors/shared/inventory.txt index cf01cd54c..ae519704c 100644 --- a/wadsrc/static/actors/shared/inventory.txt +++ b/wadsrc/static/actors/shared/inventory.txt @@ -48,6 +48,7 @@ ACTOR Inventory native action native A_RestoreSpecialDoomThing(); action native A_RestoreSpecialThing1(); action native A_RestoreSpecialThing2(); + action native A_WeaponOFfset(float wx = 0, float wy = 32, int flags = 0); States { From cd3a3d4472f436d314de994dfe109d8efb343b24 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Tue, 17 May 2016 16:19:37 -0500 Subject: [PATCH 07/15] Not like this makes a difference. --- wadsrc/static/actors/shared/inventory.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/actors/shared/inventory.txt b/wadsrc/static/actors/shared/inventory.txt index ae519704c..f7250117d 100644 --- a/wadsrc/static/actors/shared/inventory.txt +++ b/wadsrc/static/actors/shared/inventory.txt @@ -48,7 +48,7 @@ ACTOR Inventory native action native A_RestoreSpecialDoomThing(); action native A_RestoreSpecialThing1(); action native A_RestoreSpecialThing2(); - action native A_WeaponOFfset(float wx = 0, float wy = 32, int flags = 0); + action native A_WeaponOffset(float wx = 0, float wy = 32, int flags = 0); States { From 3dcb05e5d261c8b8a6db5df73c977385ee048f37 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 18 May 2016 11:56:39 +0200 Subject: [PATCH 08/15] - fixed: Lock #255 was inaccessible for LOCKDEFS. --- src/g_shared/a_keys.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_shared/a_keys.cpp b/src/g_shared/a_keys.cpp index 1164135bc..2d2b5be87 100644 --- a/src/g_shared/a_keys.cpp +++ b/src/g_shared/a_keys.cpp @@ -223,7 +223,7 @@ static void ParseLock(FScanner &sc) } ignorekey = true; - if (keynum > 0 && keynum < 255) + if (keynum > 0 && keynum <= 255) { lock = new Lock; if (locks[keynum]) From 7642c2cdaab6ed4611c8f31adba4d4fb8f8548ce Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 18 May 2016 12:02:54 +0200 Subject: [PATCH 09/15] - fixed: Opening a non-existent menu left the engine in an invalid state. --- src/menu/menu.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index fb0ea80d7..5e5124b2a 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -458,6 +458,7 @@ void M_SetMenu(FName menu, int param) } } Printf("Attempting to open menu of unknown type '%s'\n", menu.GetChars()); + M_ClearMenus(); } //============================================================================= From 9e0301c1a1cf7be1649d8e5ffdbe9f3256db7082 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 18 May 2016 13:11:01 +0200 Subject: [PATCH 10/15] - prevent message spam with no MIDI devices. --- src/sound/music_midi_base.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/sound/music_midi_base.cpp b/src/sound/music_midi_base.cpp index a08625292..8c44a2ac4 100644 --- a/src/sound/music_midi_base.cpp +++ b/src/sound/music_midi_base.cpp @@ -74,8 +74,12 @@ CUSTOM_CVAR (Int, snd_mididevice, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) if ((self >= (signed)nummididevices) || (self < -6)) { - Printf ("ID out of range. Using default device.\n"); - self = 0; + // Don't do repeated message spam if there is no valid device. + if (self != 0) + { + Printf("ID out of range. Using default device.\n"); + self = 0; + } return; } mididevice = MAX(0, self); From ae3f50d1b295dea0503d0a21f5a6399c4d7d1e44 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 18 May 2016 13:11:31 +0200 Subject: [PATCH 11/15] - set a compatibility option to build the stairs in Eternal Doom MAP03 correctly. --- wadsrc/static/compatibility.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index 099456405..d796db843 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -51,6 +51,11 @@ A80E7EE40E0D0C76A6FBD242BE29FE27 // map15 resetplayerspeed } +5C594C67CF7721005DE71429F9811370 // Eternal Doom map03 +{ + stairs +} + 6DA6FCBA8089161BDEC6A1D3F6C8D60F // Eternal Doom MAP25 { stairs From f22adcc3986a0ffa999b131f6e9df012e1bd7a8d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 18 May 2016 21:06:07 +0200 Subject: [PATCH 12/15] - be more thorough with Eternal Doom MAP03. The compatibility option does not seem to fully solve the problem, so let's just clear the tags in the bogus stair sectors. --- src/compatibility.cpp | 9 ++++++++- wadsrc/static/compatibility.txt | 6 +++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/compatibility.cpp b/src/compatibility.cpp index e7121da8b..ae3b905d0 100644 --- a/src/compatibility.cpp +++ b/src/compatibility.cpp @@ -555,7 +555,14 @@ void SetCompatibilityParams() if ((unsigned)CompatParams[i + 1] < (unsigned)numsectors) { // this assumes that the sector does not have any tags yet! - tagManager.AddSectorTag(CompatParams[i + 1], CompatParams[i + 2]); + if (CompatParams[i + 2] == 0) + { + tagManager.RemoveSectorTags(CompatParams[i + 1]); + } + else + { + tagManager.AddSectorTag(CompatParams[i + 1], CompatParams[i + 2]); + } } i += 3; break; diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index d796db843..61d13b6df 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -53,7 +53,11 @@ A80E7EE40E0D0C76A6FBD242BE29FE27 // map15 5C594C67CF7721005DE71429F9811370 // Eternal Doom map03 { - stairs + // fix broken staircase. The compatibility option is not sufficient + // to reliably handle this so clear the tags from the unwanted sectors. + setsectortag 212 0 + setsectortag 213 0 + setsectortag 214 0 } 6DA6FCBA8089161BDEC6A1D3F6C8D60F // Eternal Doom MAP25 From 78055733c89b2083b60ef6c574829afd7bbcac1f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 18 May 2016 21:25:58 +0200 Subject: [PATCH 13/15] - fixed: automap markers were scaled too small --- src/am_map.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index bd5bbe8fe..3a4e0aaa1 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -2816,8 +2816,8 @@ void AM_drawThings () if (texture == NULL) goto drawTriangle; // fall back to standard display if no sprite can be found. - const double spriteXScale = (t->Scale.X * 10 * scale_mtof); - const double spriteYScale = (t->Scale.Y * 10 * scale_mtof); + const double spriteXScale = (t->Scale.X * (10. / 16.) * scale_mtof); + const double spriteYScale = (t->Scale.Y * (10. / 16.) * scale_mtof); DrawMarker (texture, p.x, p.y, 0, !!(frame->Flip & (1 << rotation)), spriteXScale, spriteYScale, t->Translation, 1., 0, LegacyRenderStyles[STYLE_Normal]); @@ -2917,8 +2917,8 @@ static void DrawMarker (FTexture *tex, double x, double y, int yadjust, AM_rotatePoint (&x, &y); } screen->DrawTexture (tex, CXMTOF(x) + f_x, CYMTOF(y) + yadjust + f_y, - DTA_DestWidthF, tex->GetScaledWidthDouble() * CleanXfac * xscale / 16, - DTA_DestHeightF, tex->GetScaledHeightDouble() * CleanYfac * yscale / 16, + DTA_DestWidthF, tex->GetScaledWidthDouble() * CleanXfac * xscale, + DTA_DestHeightF, tex->GetScaledHeightDouble() * CleanYfac * yscale, DTA_ClipTop, f_y, DTA_ClipBottom, f_y + f_h, DTA_ClipLeft, f_x, @@ -3011,7 +3011,7 @@ void AM_drawAuthorMarkers () marked->subsector->flags & SSECF_DRAWN : marked->Sector->MoreFlags & SECF_DRAWN))) { - DrawMarker (tex, marked->X(), marked->Y(), 0, flip, mark->Scale.X*16, mark->Scale.Y*16, mark->Translation, + DrawMarker (tex, marked->X(), marked->Y(), 0, flip, mark->Scale.X, mark->Scale.Y, mark->Translation, mark->Alpha, mark->fillcolor, mark->RenderStyle); } marked = mark->args[0] != 0 ? it.Next() : NULL; From 13da14e91566132476ceb4548e95766265efd0e6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 18 May 2016 22:20:18 +0200 Subject: [PATCH 14/15] - disable dynamic lights on additively blended surfaces because it doesn't look good at all. --- src/gl/scene/gl_flats.cpp | 2 ++ src/gl/scene/gl_walls_draw.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index cbc5d3451..5164e0676 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -120,6 +120,8 @@ void GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, int *dli) { Plane p; + if (renderstyle == STYLE_Add) return; // no lights on additively blended surfaces. + if (dli != NULL && *dli != -1) { gl_RenderState.ApplyLightIndex(GLRenderer->mLights->GetIndex(*dli)); diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index a7cd23d42..20d170977 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -73,6 +73,8 @@ FDynLightData lightdata; void GLWall::SetupLights() { + if (RenderStyle == STYLE_Add) return; // no lights on additively blended surfaces. + // check for wall types which cannot have dynamic lights on them (portal types never get here so they don't need to be checked.) switch (type) { From 5017a192eb6ba3717e416730e1ae124e59411f9f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 19 May 2016 12:22:39 +0200 Subject: [PATCH 15/15] - fixed: The texture matrix was not reset after drawing the texture pass for multipass textured dynamic lights. --- src/gl/scene/gl_flats.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 5164e0676..d7c47c618 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -455,6 +455,7 @@ void GLFlat::Draw(int pass, bool trans) // trans only has meaning for GLPASS_LIG gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false); gl_SetPlaneTextureRotation(&plane, gltexture); DrawSubsectors(pass, false, false); + gl_RenderState.EnableTextureMatrix(false); break; } }