diff --git a/src/am_map.cpp b/src/am_map.cpp index 46819b44a..aaf82a1a3 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -2817,8 +2817,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]); @@ -2918,8 +2918,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, @@ -3012,7 +3012,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; 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/src/d_main.cpp b/src/d_main.cpp index c3813562d..b03059e58 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -914,7 +914,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 @@ -1013,7 +1012,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/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]) 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 diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index cbc5d3451..d7c47c618 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)); @@ -453,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; } } 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) { 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(); } //============================================================================= 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; } 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/src/s_sound.cpp b/src/s_sound.cpp index 832cdce40..edb426e9a 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -2661,17 +2661,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 669280430..459de90c2 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -333,7 +333,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/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/i_sound.h b/src/sound/i_sound.h index 9a12b8f06..f520a213d 100644 --- a/src/sound/i_sound.h +++ b/src/sound/i_sound.h @@ -148,7 +148,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/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/music_midi_base.cpp b/src/sound/music_midi_base.cpp index e05c96530..61e051bae 100644 --- a/src/sound/music_midi_base.cpp +++ b/src/sound/music_midi_base.cpp @@ -75,8 +75,12 @@ CUSTOM_CVAR (Int, snd_mididevice, 0, 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); diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index bf7bede82..8ac41a04b 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -221,7 +221,7 @@ class OpenALSoundStream : public SoundStream ALuint Buffers[BufferCount]; ALuint Source; - bool Playing; + std::atomic Playing; bool Looping; ALfloat Volume; @@ -287,12 +287,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); @@ -309,9 +311,6 @@ public: } getALError(); - Renderer->Streams.Delete(Renderer->Streams.Find(this)); - Renderer = NULL; - delete Decoder; delete Reader; } @@ -321,7 +320,7 @@ public: { SetVolume(vol); - if(Playing) + if(Playing.load()) return true; /* Clear the buffer queue, then fill and queue each buffer */ @@ -342,21 +341,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) @@ -382,21 +384,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); @@ -405,6 +411,8 @@ public: return 0; size_t pos = Decoder->getSampleOffset(); + lock.unlock(); + if(state != AL_STOPPED) { size_t rem = queued*(Data.Size()/FrameSize) - offset; @@ -416,54 +424,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; @@ -474,6 +438,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); @@ -481,16 +446,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 @@ -516,6 +484,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()) @@ -707,7 +726,7 @@ static void LoadALCFunc(ALCdevice *device, const char *name, T *x) #define LOAD_FUNC(x) (LoadALFunc(#x, &x)) #define LOAD_DEV_FUNC(d, x) (LoadALCFunc(d, #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; @@ -940,6 +959,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]; @@ -974,6 +1002,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; @@ -1252,6 +1317,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)) { @@ -1263,6 +1330,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))) { @@ -1460,7 +1529,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 +1557,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 +1812,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(); } @@ -1852,13 +1949,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 88dcbc238..09fe64d92 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" @@ -114,7 +119,6 @@ public: virtual void UpdateListener(SoundListener *); virtual void UpdateSounds(); - virtual void UpdateMusic(); virtual void MarkStartTime(FISoundChannel*); virtual float GetAudibility(FISoundChannel*); @@ -184,10 +188,19 @@ private: void (ALC_APIENTRY*alcDevicePauseSOFT)(ALCdevice *device); void (ALC_APIENTRY*alcDeviceResumeSOFT)(ALCdevice *device); + 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; 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; } 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..f7250117d 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 { diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index 59f50510f..d5f831d50 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -51,6 +51,15 @@ A80E7EE40E0D0C76A6FBD242BE29FE27 // map15 resetplayerspeed } +5C594C67CF7721005DE71429F9811370 // Eternal Doom map03 +{ + // 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 { stairs