diff --git a/.appveyor.yml b/.appveyor.yml index c02cfca649..48b51af0b1 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -21,8 +21,6 @@ before_build: - cd build - if "%PLATFORM%"=="Win32" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015 - if "%PLATFORM%"=="x64" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015 Win64 - - set DEPS_INCLUDE_DIR=%APPVEYOR_BUILD_FOLDER%\ci_deps_win\include - - set DEPS_LIB_DIR=%APPVEYOR_BUILD_FOLDER%\ci_deps_win\lib\%PLATFORM% - cmake -G "%CMAKE_GENERATOR_NAME%" -T "v140_xp" -DCMAKE_BUILD_TYPE="%CONFIGURATION%" .. @@ -32,6 +30,13 @@ build: parallel: true verbosity: minimal +after_build: + - set OUTPUT_DIR=%APPVEYOR_BUILD_FOLDER%\build\%CONFIGURATION%\ + - 7z a ..\gzdoom.zip "%OUTPUT_DIR%gzdoom.exe" "%OUTPUT_DIR%*.pk3" + +artifacts: + - path: gzdoom.zip + notifications: - provider: Email on_build_success: false diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 95ab613c0a..a9b65cb1df 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1265,12 +1265,13 @@ if( CMAKE_COMPILER_IS_GNUCXX ) set_source_files_properties( oplsynth/fmopl.cpp PROPERTIES COMPILE_FLAGS "-fno-tree-dominator-opts -fno-tree-fre" ) endif() if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) - # Need to enable intrinsics for this file. + # Need to enable intrinsics for these files. if( SSE_MATTERS ) set_source_files_properties( - x86.cpp - swrenderer/r_all.cpp + gl/system/gl_swframebuffer.cpp polyrenderer/poly_all.cpp + swrenderer/r_all.cpp + x86.cpp PROPERTIES COMPILE_FLAGS "-msse2 -mmmx" ) endif() endif() diff --git a/src/d_main.cpp b/src/d_main.cpp index bed80387b0..12acc62f5a 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -132,6 +132,7 @@ extern void M_SetDefaultMode (); extern void G_NewInit (); extern void SetupPlayerClasses (); extern void HUD_InitHud(); +void gl_PatchMenu(); // remove modern OpenGL options on old hardware. void DeinitMenus(); const FIWADInfo *D_FindIWAD(TArray &wadfiles, const char *iwad, const char *basewad); @@ -2639,6 +2640,7 @@ void D_DoomMain (void) } V_Init2(); + gl_PatchMenu(); UpdateJoystickMenu(NULL); v = Args->CheckValue ("-loadgame"); diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index d29823b759..d714d3e46d 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -53,6 +53,7 @@ CVAR(Bool, gl_lights_additive, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Bool, gl_legacy_mode, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) //========================================================================== // @@ -64,6 +65,7 @@ CVAR(Bool, gl_lights_additive, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) void gl_PatchMenu() { // Radial fog and Doom lighting are not available without full shader support. + if (!gl_legacy_mode) return; FOptionValues **opt = OptionValues.CheckKey("LightingModes"); if (opt != NULL) diff --git a/src/gl/scene/gl_scenedrawer.h b/src/gl/scene/gl_scenedrawer.h index 00426e36b4..9209e6dad9 100644 --- a/src/gl/scene/gl_scenedrawer.h +++ b/src/gl/scene/gl_scenedrawer.h @@ -69,6 +69,7 @@ public: void InitClipper(angle_t a1, angle_t a2) { + clipper.Clear(); clipper.SafeAddClipRangeRealAngles(a1, a2); } diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index 2d2d827c63..23610fb01a 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -338,6 +338,7 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) { RenderStyle = rs.first; } + if (RenderStyle.BlendOp == STYLEOP_None) continue; if (vis.Invert) { diff --git a/src/gl/system/gl_interface.cpp b/src/gl/system/gl_interface.cpp index 1a3f4b1aec..308d741bb3 100644 --- a/src/gl/system/gl_interface.cpp +++ b/src/gl/system/gl_interface.cpp @@ -42,6 +42,8 @@ void gl_PatchMenu(); static TArray m_Extensions; RenderContext gl; +EXTERN_CVAR(Bool, gl_legacy_mode) + //========================================================================== // // @@ -311,8 +313,8 @@ void gl_LoadExtensions() FUDGE_FUNC(glRenderbufferStorage, EXT); FUDGE_FUNC(glBindRenderbuffer, EXT); FUDGE_FUNC(glCheckFramebufferStatus, EXT); - gl_PatchMenu(); } + gl_legacy_mode = gl.legacyMode; } //========================================================================== diff --git a/src/gl/system/gl_swframebuffer.cpp b/src/gl/system/gl_swframebuffer.cpp index 44d3b6d8bc..fd0bb395e4 100644 --- a/src/gl/system/gl_swframebuffer.cpp +++ b/src/gl/system/gl_swframebuffer.cpp @@ -92,6 +92,7 @@ EXTERN_CVAR(Float, Gamma) EXTERN_CVAR(Bool, vid_vsync) EXTERN_CVAR(Float, transsouls) EXTERN_CVAR(Int, vid_refreshrate) +EXTERN_CVAR(Bool, gl_legacy_mode) CVAR(Int, vid_max_width, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Int, vid_max_height, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -205,6 +206,13 @@ OpenGLSWFrameBuffer::OpenGLSWFrameBuffer(void *hMonitor, int width, int height, const char *glversion = (const char*)glGetString(GL_VERSION); bool isGLES = (glversion && strlen(glversion) > 10 && memcmp(glversion, "OpenGL ES ", 10) == 0); + + // GL 3.0 is mostly broken on MESA drivers which really are the only relevant case here that doesn't fulfill the requirements based on version number alone. +#ifdef _WIN32 + gl_legacy_mode = !ogl_IsVersionGEQ(3, 0); +#else + gl_legacy_mode = !ogl_IsVersionGEQ(3, 1); +#endif if (!isGLES && ogl_IsVersionGEQ(3, 0) == 0) { Printf("OpenGL acceleration requires at least OpenGL 3.0. No Acceleration will be used.\n"); diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 35e2bf7bc9..7a9bdafe87 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -187,6 +187,7 @@ void SexMessage (const char *from, char *to, int gender, const char *victim, con void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgflags) { FName mod; + FString ret; const char *message; const char *messagename; char gendermessage[1024]; @@ -218,17 +219,17 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf } FString obit = DamageTypeDefinition::GetObituary(mod); - if (attacker == nullptr) messagename = obit; + if (attacker == nullptr && obit.IsNotEmpty()) messagename = obit; else { switch (mod) { - case NAME_Suicide: message = "$OB_SUICIDE"; break; - case NAME_Falling: message = "$OB_FALLING"; break; - case NAME_Crush: message = "$OB_CRUSH"; break; - case NAME_Exit: message = "$OB_EXIT"; break; - case NAME_Drowning: message = "$OB_WATER"; break; - case NAME_Slime: message = "$OB_SLIME"; break; + case NAME_Suicide: messagename = "$OB_SUICIDE"; break; + case NAME_Falling: messagename = "$OB_FALLING"; break; + case NAME_Crush: messagename = "$OB_CRUSH"; break; + case NAME_Exit: messagename = "$OB_EXIT"; break; + case NAME_Drowning: messagename = "$OB_WATER"; break; + case NAME_Slime: messagename = "$OB_SLIME"; break; case NAME_Fire: messagename = "$OB_LAVA"; break; } } @@ -250,7 +251,6 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf IFVIRTUALPTR(attacker, AActor, GetObituary) { VMValue params[] = { attacker, self, inflictor, mod.GetIndex(), !!(dmgflags & DMG_PLAYERATTACK) }; - FString ret; VMReturn rett(&ret); VMCall(func, params, countof(params), &rett, 1); if (ret.IsNotEmpty()) message = ret; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 66b1f35bd8..2db57b613a 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3823,28 +3823,22 @@ DEFINE_ACTION_FUNCTION(AActor, PlayActiveSound) bool AActor::IsOkayToAttack (AActor *link) { - if (!(player // Original AActor::IsOkayToAttack was only for players - // || (flags & MF_FRIENDLY) // Maybe let friendly monsters use the function as well? - || (flags5 & MF5_SUMMONEDMONSTER) // AMinotaurFriend has its own version, generalized to other summoned monsters - || (flags2 & MF2_SEEKERMISSILE))) // AHolySpirit and AMageStaffFX2 as well, generalized to other seeker missiles - { // Normal monsters and other actors always return false. - return false; - } // Standard things to eliminate: an actor shouldn't attack itself, // or a non-shootable, dormant, non-player-and-non-monster actor. if (link == this) return false; if (!(link->player||(link->flags3 & MF3_ISMONSTER)))return false; if (!(link->flags & MF_SHOOTABLE)) return false; if (link->flags2 & MF2_DORMANT) return false; + if (link->flags7 & MF7_NEVERTARGET) return false; // NEVERTARGET means just that. // An actor shouldn't attack friendly actors. The reference depends // on the type of actor: for a player's actor, itself; for a projectile, // its target; and for a summoned minion, its tracer. - AActor * Friend = NULL; - if (player) Friend = this; - else if (flags5 & MF5_SUMMONEDMONSTER) Friend = tracer; + AActor * Friend; + if (flags5 & MF5_SUMMONEDMONSTER) Friend = tracer; else if (flags2 & MF2_SEEKERMISSILE) Friend = target; else if ((flags & MF_FRIENDLY) && FriendPlayer) Friend = players[FriendPlayer-1].mo; + else Friend = this; // Friend checks if (link == Friend) return false; diff --git a/src/polyrenderer/drawers/poly_triangle.cpp b/src/polyrenderer/drawers/poly_triangle.cpp index 19628cf473..1cf9609ccd 100644 --- a/src/polyrenderer/drawers/poly_triangle.cpp +++ b/src/polyrenderer/drawers/poly_triangle.cpp @@ -152,8 +152,28 @@ ShadedTriVertex PolyTriangleDrawer::shade_vertex(const TriMatrix &objectToClip, return sv; } +bool PolyTriangleDrawer::is_degenerate(const ShadedTriVertex *vert) +{ + // A degenerate triangle has a zero cross product for two of its sides. + float ax = vert[1].x - vert[0].x; + float ay = vert[1].y - vert[0].y; + float az = vert[1].w - vert[0].w; + float bx = vert[2].x - vert[0].x; + float by = vert[2].y - vert[0].y; + float bz = vert[2].w - vert[0].w; + float crossx = ay * bz - az * by; + float crossy = az * bx - ax * bz; + float crossz = ax * by - ay * bx; + float crosslengthsqr = crossx * crossx + crossy * crossy + crossz * crossz; + return crosslengthsqr <= 1.e-6f; +} + void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread) { + // Reject triangle if degenerate + if (is_degenerate(vert)) + return; + // Cull, clip and generate additional vertices as needed TriVertex clippedvert[max_additional_vertices]; int numclipvert = clipedge(vert, clippedvert); @@ -224,14 +244,13 @@ void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool // Draw screen triangles if (ccw) { - for (int i = numclipvert; i > 1; i--) + for (int i = numclipvert - 1; i > 1; i--) { args->v1 = &clippedvert[numclipvert - 1]; args->v2 = &clippedvert[i - 1]; args->v3 = &clippedvert[i - 2]; - args->CalculateGradients(); - - ScreenTriangle::Draw(args, thread); + if (args->CalculateGradients()) + ScreenTriangle::Draw(args, thread); } } else @@ -241,9 +260,8 @@ void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool args->v1 = &clippedvert[0]; args->v2 = &clippedvert[i - 1]; args->v3 = &clippedvert[i]; - args->CalculateGradients(); - - ScreenTriangle::Draw(args, thread); + if (args->CalculateGradients()) + ScreenTriangle::Draw(args, thread); } } } diff --git a/src/polyrenderer/drawers/poly_triangle.h b/src/polyrenderer/drawers/poly_triangle.h index c939149d31..c663cd2d00 100644 --- a/src/polyrenderer/drawers/poly_triangle.h +++ b/src/polyrenderer/drawers/poly_triangle.h @@ -47,6 +47,7 @@ private: static ShadedTriVertex shade_vertex(const TriMatrix &objectToClip, const float *clipPlane, const TriVertex &v); static void draw_arrays(const PolyDrawArgs &args, WorkerThreadData *thread); static void draw_shaded_triangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread); + static bool is_degenerate(const ShadedTriVertex *vertices); static int clipedge(const ShadedTriVertex *verts, TriVertex *clippedvert); diff --git a/src/polyrenderer/drawers/screen_triangle.h b/src/polyrenderer/drawers/screen_triangle.h index 3dd4c24eb4..4339edaf4b 100644 --- a/src/polyrenderer/drawers/screen_triangle.h +++ b/src/polyrenderer/drawers/screen_triangle.h @@ -66,29 +66,31 @@ struct TriDrawTriangleArgs ScreenTriangleStepVariables gradientX; ScreenTriangleStepVariables gradientY; - void CalculateGradients() + bool CalculateGradients() { - gradientX.W = FindGradientX(v1->x, v1->y, v2->x, v2->y, v3->x, v3->y, v1->w, v2->w, v3->w); - gradientY.W = FindGradientY(v1->x, v1->y, v2->x, v2->y, v3->x, v3->y, v1->w, v2->w, v3->w); - gradientX.U = FindGradientX(v1->x, v1->y, v2->x, v2->y, v3->x, v3->y, v1->u * v1->w, v2->u * v2->w, v3->u * v3->w); - gradientY.U = FindGradientY(v1->x, v1->y, v2->x, v2->y, v3->x, v3->y, v1->u * v1->w, v2->u * v2->w, v3->u * v3->w); - gradientX.V = FindGradientX(v1->x, v1->y, v2->x, v2->y, v3->x, v3->y, v1->v * v1->w, v2->v * v2->w, v3->v * v3->w); - gradientY.V = FindGradientY(v1->x, v1->y, v2->x, v2->y, v3->x, v3->y, v1->v * v1->w, v2->v * v2->w, v3->v * v3->w); + float bottomX = (v2->x - v3->x) * (v1->y - v3->y) - (v1->x - v3->x) * (v2->y - v3->y); + float bottomY = (v1->x - v3->x) * (v2->y - v3->y) - (v2->x - v3->x) * (v1->y - v3->y); + if ((bottomX >= -FLT_EPSILON && bottomX <= FLT_EPSILON) || (bottomY >= -FLT_EPSILON && bottomY <= FLT_EPSILON)) + return false; + + gradientX.W = FindGradientX(bottomX, v1->w, v2->w, v3->w); + gradientY.W = FindGradientY(bottomY, v1->w, v2->w, v3->w); + gradientX.U = FindGradientX(bottomX, v1->u * v1->w, v2->u * v2->w, v3->u * v3->w); + gradientY.U = FindGradientY(bottomY, v1->u * v1->w, v2->u * v2->w, v3->u * v3->w); + gradientX.V = FindGradientX(bottomX, v1->v * v1->w, v2->v * v2->w, v3->v * v3->w); + gradientY.V = FindGradientY(bottomY, v1->v * v1->w, v2->v * v2->w, v3->v * v3->w); + return true; } private: - static float FindGradientX(float x0, float y0, float x1, float y1, float x2, float y2, float c0, float c1, float c2) + float FindGradientX(float bottomX, float c0, float c1, float c2) { - float top = (c1 - c2) * (y0 - y2) - (c0 - c2) * (y1 - y2); - float bottom = (x1 - x2) * (y0 - y2) - (x0 - x2) * (y1 - y2); - return top / bottom; + return ((c1 - c2) * (v1->y - v3->y) - (c0 - c2) * (v2->y - v3->y)) / bottomX; } - static float FindGradientY(float x0, float y0, float x1, float y1, float x2, float y2, float c0, float c1, float c2) + float FindGradientY(float bottomY, float c0, float c1, float c2) { - float top = (c1 - c2) * (x0 - x2) - (c0 - c2) * (x1 - x2); - float bottom = (x0 - x2) * (y1 - y2) - (x1 - x2) * (y0 - y2); - return top / bottom; + return ((c1 - c2) * (v1->x - v3->x) - (c0 - c2) * (v2->x - v3->x)) / bottomY; } }; diff --git a/src/posix/cocoa/i_system.mm b/src/posix/cocoa/i_system.mm index a9cb708096..7b7c6dcc2c 100644 --- a/src/posix/cocoa/i_system.mm +++ b/src/posix/cocoa/i_system.mm @@ -77,7 +77,12 @@ void I_WaitVBL(const int count) { // I_WaitVBL is never used to actually synchronize to the // vertical blank. Instead, it's used for delay purposes. - usleep(1000000 * count / 70); + struct timespec delay, rem; + delay.tv_sec = count / 70; + /* Avoid overflow. Microsec res should be good enough. */ + delay.tv_nsec = (count%70)*1000000/70 * 1000; + while(nanosleep(&delay, &rem) == -1 && errno == EINTR) + delay = rem; } diff --git a/src/posix/sdl/i_system.cpp b/src/posix/sdl/i_system.cpp index 753589819b..02dc270e46 100644 --- a/src/posix/sdl/i_system.cpp +++ b/src/posix/sdl/i_system.cpp @@ -113,7 +113,12 @@ void I_WaitVBL (int count) { // I_WaitVBL is never used to actually synchronize to the // vertical blank. Instead, it's used for delay purposes. - usleep (1000000 * count / 70); + struct timespec delay, rem; + delay.tv_sec = count / 70; + /* Avoid overflow. Microsec res should be good enough. */ + delay.tv_nsec = (count%70)*1000000/70 * 1000; + while(nanosleep(&delay, &rem) == -1 && errno == EINTR) + delay = rem; } // diff --git a/src/s_sound.cpp b/src/s_sound.cpp index d2a830fef1..ea12fe97e3 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -594,15 +594,14 @@ void S_CacheSound (sfxinfo_t *sfx) void S_UnloadSound (sfxinfo_t *sfx) { + if (sfx->data3d.isValid() && sfx->data != sfx->data3d) + GSnd->UnloadSound(sfx->data3d); if (sfx->data.isValid()) - { - if(sfx->data3d.isValid() && sfx->data != sfx->data3d) - GSnd->UnloadSound(sfx->data3d); GSnd->UnloadSound(sfx->data); - sfx->data.Clear(); - sfx->data3d.Clear(); + if (sfx->data.isValid() || sfx->data3d.isValid()) DPrintf(DMSG_NOTIFY, "Unloaded sound \"%s\" (%td)\n", sfx->name.GetChars(), sfx - &S_sfx[0]); - } + sfx->data.Clear(); + sfx->data3d.Clear(); } //========================================================================== diff --git a/src/sound/musicformats/music_libsndfile.cpp b/src/sound/musicformats/music_libsndfile.cpp index 91951c18b0..85b670a6b3 100644 --- a/src/sound/musicformats/music_libsndfile.cpp +++ b/src/sound/musicformats/music_libsndfile.cpp @@ -38,10 +38,7 @@ #include "c_cvars.h" #include "critsec.h" #include "v_text.h" -#include "files.h" #include "templates.h" -#include "sndfile_decoder.h" -#include "mpg123_decoder.h" #include "m_fixed.h" // MACROS ------------------------------------------------------------------ @@ -82,6 +79,18 @@ protected: // PUBLIC DATA DEFINITIONS ------------------------------------------------- +CUSTOM_CVAR(Int, snd_streambuffersize, 64, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 16) + { + self = 16; + } + else if (self > 1024) + { + self = 1024; + } +} + // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- @@ -121,7 +130,7 @@ void FindLoopTags(FileReader *fr, uint32_t *start, bool *startass, uint32_t *end } c -= 3; int len = c[0] + 256*c[1] + 65536*c[2]; - if (c[3] || len > 1000000 || len <= (eqp - c + 1)) + if (c[3] || len > 1000000 || len < (eqp - c - 3)) { // length looks fishy so retry with the next '=' continue; @@ -209,7 +218,7 @@ SndFileSong::SndFileSong(FileReader *reader, SoundDecoder *decoder, uint32_t loo Reader = reader; Decoder = decoder; Channels = iChannels == ChannelConfig_Stereo? 2:1; - m_Stream = GSnd->CreateStream(Read, 32*1024, iChannels == ChannelConfig_Stereo? 0 : SoundStream::Mono, SampleRate, this); + m_Stream = GSnd->CreateStream(Read, snd_streambuffersize * 1024, iChannels == ChannelConfig_Stereo? 0 : SoundStream::Mono, SampleRate, this); } //========================================================================== @@ -330,7 +339,7 @@ bool SndFileSong::Read(SoundStream *stream, void *vbuff, int ilen, void *userdat if (currentpos + framestoread > song->Loop_End) { size_t endblock = (song->Loop_End - currentpos) * song->Channels * 2; - size_t endlen = song->Decoder->read(buff, endblock); + size_t endlen = song->Decoder->read(buff, 0 == endblock ? len : endblock); if (endlen != 0) { buff = buff + endlen; diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index f323f858a2..77068cf96d 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -1585,7 +1585,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int else { if((chanflags&SNDF_ABSTIME)) - alSourcef(source, AL_SAMPLE_OFFSET, reuse_chan->StartTime.Lo); + alSourcei(source, AL_SAMPLE_OFFSET, reuse_chan->StartTime.Lo); else { float offset = std::chrono::duration_cast>( @@ -1793,7 +1793,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener else { if((chanflags&SNDF_ABSTIME)) - alSourcef(source, AL_SAMPLE_OFFSET, reuse_chan->StartTime.Lo); + alSourcei(source, AL_SAMPLE_OFFSET, reuse_chan->StartTime.Lo); else { float offset = std::chrono::duration_cast>( diff --git a/src/sound/oplsynth/oplio.cpp b/src/sound/oplsynth/oplio.cpp index e810a58c18..fb4d507a76 100644 --- a/src/sound/oplsynth/oplio.cpp +++ b/src/sound/oplsynth/oplio.cpp @@ -420,7 +420,7 @@ void OPLio::WriteTremolo(uint32_t channel, struct GenMidiVoice *voice, bool vibr val2 |= 0x40; } WriteOperator(OPL_REGS_TREMOLO, channel, 1, val2); - WriteOperator(OPL_REGS_TREMOLO, channel, 0, val2); + WriteOperator(OPL_REGS_TREMOLO, channel, 0, val1); } //---------------------------------------------------------------------------- diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index bf16a87085..c82fb19694 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -1222,7 +1222,11 @@ LONG WINAPI CatchAllExceptions (LPEXCEPTION_POINTERS info) // Otherwise, put the crashing thread to sleep and signal the main thread to clean up. if (GetCurrentThreadId() == MainThreadID) { +#ifdef _M_X64 *info->ContextRecord = MainThreadContext; +#else + info->ContextRecord->Eip = (DWORD_PTR)ExitFatally; +#endif // _M_X64 } else { @@ -1315,6 +1319,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE nothing, LPSTR cmdline, int n { SetUnhandledExceptionFilter (CatchAllExceptions); +#ifdef _M_X64 static bool setJumpResult = false; RtlCaptureContext(&MainThreadContext); if (setJumpResult) @@ -1323,6 +1328,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE nothing, LPSTR cmdline, int n return 0; } setJumpResult = true; +#endif // _M_X64 } #endif diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index b799f98c25..1223b6bf8e 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -817,7 +817,7 @@ class PlayerPawn : Actor native double factor = 1.; for(let it = Inv; it != null; it = it.Inv) { - factor *= Inv.GetSpeedFactor (); + factor *= it.GetSpeedFactor (); } forward *= factor; side *= factor;