This commit is contained in:
Rachael Alexanderson 2017-05-10 05:15:49 -04:00
commit ac244b3229
21 changed files with 125 additions and 64 deletions

View file

@ -21,8 +21,6 @@ before_build:
- cd build - cd build
- if "%PLATFORM%"=="Win32" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015 - if "%PLATFORM%"=="Win32" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015
- if "%PLATFORM%"=="x64" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015 Win64 - 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" - cmake -G "%CMAKE_GENERATOR_NAME%" -T "v140_xp"
-DCMAKE_BUILD_TYPE="%CONFIGURATION%" -DCMAKE_BUILD_TYPE="%CONFIGURATION%"
.. ..
@ -32,6 +30,13 @@ build:
parallel: true parallel: true
verbosity: minimal 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: notifications:
- provider: Email - provider: Email
on_build_success: false on_build_success: false

View file

@ -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" ) set_source_files_properties( oplsynth/fmopl.cpp PROPERTIES COMPILE_FLAGS "-fno-tree-dominator-opts -fno-tree-fre" )
endif() endif()
if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
# Need to enable intrinsics for this file. # Need to enable intrinsics for these files.
if( SSE_MATTERS ) if( SSE_MATTERS )
set_source_files_properties( set_source_files_properties(
x86.cpp gl/system/gl_swframebuffer.cpp
swrenderer/r_all.cpp
polyrenderer/poly_all.cpp polyrenderer/poly_all.cpp
swrenderer/r_all.cpp
x86.cpp
PROPERTIES COMPILE_FLAGS "-msse2 -mmmx" ) PROPERTIES COMPILE_FLAGS "-msse2 -mmmx" )
endif() endif()
endif() endif()

View file

@ -132,6 +132,7 @@ extern void M_SetDefaultMode ();
extern void G_NewInit (); extern void G_NewInit ();
extern void SetupPlayerClasses (); extern void SetupPlayerClasses ();
extern void HUD_InitHud(); extern void HUD_InitHud();
void gl_PatchMenu(); // remove modern OpenGL options on old hardware.
void DeinitMenus(); void DeinitMenus();
const FIWADInfo *D_FindIWAD(TArray<FString> &wadfiles, const char *iwad, const char *basewad); const FIWADInfo *D_FindIWAD(TArray<FString> &wadfiles, const char *iwad, const char *basewad);
@ -2639,6 +2640,7 @@ void D_DoomMain (void)
} }
V_Init2(); V_Init2();
gl_PatchMenu();
UpdateJoystickMenu(NULL); UpdateJoystickMenu(NULL);
v = Args->CheckValue ("-loadgame"); v = Args->CheckValue ("-loadgame");

View file

@ -53,6 +53,7 @@
CVAR(Bool, gl_lights_additive, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) 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() void gl_PatchMenu()
{ {
// Radial fog and Doom lighting are not available without full shader support. // Radial fog and Doom lighting are not available without full shader support.
if (!gl_legacy_mode) return;
FOptionValues **opt = OptionValues.CheckKey("LightingModes"); FOptionValues **opt = OptionValues.CheckKey("LightingModes");
if (opt != NULL) if (opt != NULL)

View file

@ -69,6 +69,7 @@ public:
void InitClipper(angle_t a1, angle_t a2) void InitClipper(angle_t a1, angle_t a2)
{ {
clipper.Clear();
clipper.SafeAddClipRangeRealAngles(a1, a2); clipper.SafeAddClipRangeRealAngles(a1, a2);
} }

View file

@ -338,6 +338,7 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
{ {
RenderStyle = rs.first; RenderStyle = rs.first;
} }
if (RenderStyle.BlendOp == STYLEOP_None) continue;
if (vis.Invert) if (vis.Invert)
{ {

View file

@ -42,6 +42,8 @@ void gl_PatchMenu();
static TArray<FString> m_Extensions; static TArray<FString> m_Extensions;
RenderContext gl; RenderContext gl;
EXTERN_CVAR(Bool, gl_legacy_mode)
//========================================================================== //==========================================================================
// //
// //
@ -311,8 +313,8 @@ void gl_LoadExtensions()
FUDGE_FUNC(glRenderbufferStorage, EXT); FUDGE_FUNC(glRenderbufferStorage, EXT);
FUDGE_FUNC(glBindRenderbuffer, EXT); FUDGE_FUNC(glBindRenderbuffer, EXT);
FUDGE_FUNC(glCheckFramebufferStatus, EXT); FUDGE_FUNC(glCheckFramebufferStatus, EXT);
gl_PatchMenu();
} }
gl_legacy_mode = gl.legacyMode;
} }
//========================================================================== //==========================================================================

View file

@ -92,6 +92,7 @@ EXTERN_CVAR(Float, Gamma)
EXTERN_CVAR(Bool, vid_vsync) EXTERN_CVAR(Bool, vid_vsync)
EXTERN_CVAR(Float, transsouls) EXTERN_CVAR(Float, transsouls)
EXTERN_CVAR(Int, vid_refreshrate) 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_width, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Int, vid_max_height, 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); const char *glversion = (const char*)glGetString(GL_VERSION);
bool isGLES = (glversion && strlen(glversion) > 10 && memcmp(glversion, "OpenGL ES ", 10) == 0); 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) if (!isGLES && ogl_IsVersionGEQ(3, 0) == 0)
{ {
Printf("OpenGL acceleration requires at least OpenGL 3.0. No Acceleration will be used.\n"); Printf("OpenGL acceleration requires at least OpenGL 3.0. No Acceleration will be used.\n");

View file

@ -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) void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgflags)
{ {
FName mod; FName mod;
FString ret;
const char *message; const char *message;
const char *messagename; const char *messagename;
char gendermessage[1024]; char gendermessage[1024];
@ -218,17 +219,17 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf
} }
FString obit = DamageTypeDefinition::GetObituary(mod); FString obit = DamageTypeDefinition::GetObituary(mod);
if (attacker == nullptr) messagename = obit; if (attacker == nullptr && obit.IsNotEmpty()) messagename = obit;
else else
{ {
switch (mod) switch (mod)
{ {
case NAME_Suicide: message = "$OB_SUICIDE"; break; case NAME_Suicide: messagename = "$OB_SUICIDE"; break;
case NAME_Falling: message = "$OB_FALLING"; break; case NAME_Falling: messagename = "$OB_FALLING"; break;
case NAME_Crush: message = "$OB_CRUSH"; break; case NAME_Crush: messagename = "$OB_CRUSH"; break;
case NAME_Exit: message = "$OB_EXIT"; break; case NAME_Exit: messagename = "$OB_EXIT"; break;
case NAME_Drowning: message = "$OB_WATER"; break; case NAME_Drowning: messagename = "$OB_WATER"; break;
case NAME_Slime: message = "$OB_SLIME"; break; case NAME_Slime: messagename = "$OB_SLIME"; break;
case NAME_Fire: messagename = "$OB_LAVA"; 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) IFVIRTUALPTR(attacker, AActor, GetObituary)
{ {
VMValue params[] = { attacker, self, inflictor, mod.GetIndex(), !!(dmgflags & DMG_PLAYERATTACK) }; VMValue params[] = { attacker, self, inflictor, mod.GetIndex(), !!(dmgflags & DMG_PLAYERATTACK) };
FString ret;
VMReturn rett(&ret); VMReturn rett(&ret);
VMCall(func, params, countof(params), &rett, 1); VMCall(func, params, countof(params), &rett, 1);
if (ret.IsNotEmpty()) message = ret; if (ret.IsNotEmpty()) message = ret;

View file

@ -3823,28 +3823,22 @@ DEFINE_ACTION_FUNCTION(AActor, PlayActiveSound)
bool AActor::IsOkayToAttack (AActor *link) 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, // Standard things to eliminate: an actor shouldn't attack itself,
// or a non-shootable, dormant, non-player-and-non-monster actor. // or a non-shootable, dormant, non-player-and-non-monster actor.
if (link == this) return false; if (link == this) return false;
if (!(link->player||(link->flags3 & MF3_ISMONSTER)))return false; if (!(link->player||(link->flags3 & MF3_ISMONSTER)))return false;
if (!(link->flags & MF_SHOOTABLE)) return false; if (!(link->flags & MF_SHOOTABLE)) return false;
if (link->flags2 & MF2_DORMANT) 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 // An actor shouldn't attack friendly actors. The reference depends
// on the type of actor: for a player's actor, itself; for a projectile, // on the type of actor: for a player's actor, itself; for a projectile,
// its target; and for a summoned minion, its tracer. // its target; and for a summoned minion, its tracer.
AActor * Friend = NULL; AActor * Friend;
if (player) Friend = this; if (flags5 & MF5_SUMMONEDMONSTER) Friend = tracer;
else if (flags5 & MF5_SUMMONEDMONSTER) Friend = tracer;
else if (flags2 & MF2_SEEKERMISSILE) Friend = target; else if (flags2 & MF2_SEEKERMISSILE) Friend = target;
else if ((flags & MF_FRIENDLY) && FriendPlayer) Friend = players[FriendPlayer-1].mo; else if ((flags & MF_FRIENDLY) && FriendPlayer) Friend = players[FriendPlayer-1].mo;
else Friend = this;
// Friend checks // Friend checks
if (link == Friend) return false; if (link == Friend) return false;

View file

@ -152,8 +152,28 @@ ShadedTriVertex PolyTriangleDrawer::shade_vertex(const TriMatrix &objectToClip,
return sv; 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) 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 // Cull, clip and generate additional vertices as needed
TriVertex clippedvert[max_additional_vertices]; TriVertex clippedvert[max_additional_vertices];
int numclipvert = clipedge(vert, clippedvert); int numclipvert = clipedge(vert, clippedvert);
@ -224,14 +244,13 @@ void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool
// Draw screen triangles // Draw screen triangles
if (ccw) if (ccw)
{ {
for (int i = numclipvert; i > 1; i--) for (int i = numclipvert - 1; i > 1; i--)
{ {
args->v1 = &clippedvert[numclipvert - 1]; args->v1 = &clippedvert[numclipvert - 1];
args->v2 = &clippedvert[i - 1]; args->v2 = &clippedvert[i - 1];
args->v3 = &clippedvert[i - 2]; args->v3 = &clippedvert[i - 2];
args->CalculateGradients(); if (args->CalculateGradients())
ScreenTriangle::Draw(args, thread);
ScreenTriangle::Draw(args, thread);
} }
} }
else else
@ -241,9 +260,8 @@ void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool
args->v1 = &clippedvert[0]; args->v1 = &clippedvert[0];
args->v2 = &clippedvert[i - 1]; args->v2 = &clippedvert[i - 1];
args->v3 = &clippedvert[i]; args->v3 = &clippedvert[i];
args->CalculateGradients(); if (args->CalculateGradients())
ScreenTriangle::Draw(args, thread);
ScreenTriangle::Draw(args, thread);
} }
} }
} }

View file

@ -47,6 +47,7 @@ private:
static ShadedTriVertex shade_vertex(const TriMatrix &objectToClip, const float *clipPlane, const TriVertex &v); 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_arrays(const PolyDrawArgs &args, WorkerThreadData *thread);
static void draw_shaded_triangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *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); static int clipedge(const ShadedTriVertex *verts, TriVertex *clippedvert);

View file

@ -66,29 +66,31 @@ struct TriDrawTriangleArgs
ScreenTriangleStepVariables gradientX; ScreenTriangleStepVariables gradientX;
ScreenTriangleStepVariables gradientY; 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); float bottomX = (v2->x - v3->x) * (v1->y - v3->y) - (v1->x - v3->x) * (v2->y - v3->y);
gradientY.W = FindGradientY(v1->x, v1->y, v2->x, v2->y, v3->x, v3->y, v1->w, v2->w, v3->w); float bottomY = (v1->x - v3->x) * (v2->y - v3->y) - (v2->x - v3->x) * (v1->y - v3->y);
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); if ((bottomX >= -FLT_EPSILON && bottomX <= FLT_EPSILON) || (bottomY >= -FLT_EPSILON && bottomY <= FLT_EPSILON))
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); return false;
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); 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: 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); return ((c1 - c2) * (v1->y - v3->y) - (c0 - c2) * (v2->y - v3->y)) / bottomX;
float bottom = (x1 - x2) * (y0 - y2) - (x0 - x2) * (y1 - y2);
return top / bottom;
} }
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); return ((c1 - c2) * (v1->x - v3->x) - (c0 - c2) * (v2->x - v3->x)) / bottomY;
float bottom = (x0 - x2) * (y1 - y2) - (x1 - x2) * (y0 - y2);
return top / bottom;
} }
}; };

View file

@ -77,7 +77,12 @@ void I_WaitVBL(const int count)
{ {
// I_WaitVBL is never used to actually synchronize to the // I_WaitVBL is never used to actually synchronize to the
// vertical blank. Instead, it's used for delay purposes. // 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;
} }

View file

@ -113,7 +113,12 @@ void I_WaitVBL (int count)
{ {
// I_WaitVBL is never used to actually synchronize to the // I_WaitVBL is never used to actually synchronize to the
// vertical blank. Instead, it's used for delay purposes. // 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;
} }
// //

View file

@ -594,15 +594,14 @@ void S_CacheSound (sfxinfo_t *sfx)
void S_UnloadSound (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->data.isValid())
{
if(sfx->data3d.isValid() && sfx->data != sfx->data3d)
GSnd->UnloadSound(sfx->data3d);
GSnd->UnloadSound(sfx->data); GSnd->UnloadSound(sfx->data);
sfx->data.Clear(); if (sfx->data.isValid() || sfx->data3d.isValid())
sfx->data3d.Clear();
DPrintf(DMSG_NOTIFY, "Unloaded sound \"%s\" (%td)\n", sfx->name.GetChars(), sfx - &S_sfx[0]); DPrintf(DMSG_NOTIFY, "Unloaded sound \"%s\" (%td)\n", sfx->name.GetChars(), sfx - &S_sfx[0]);
} sfx->data.Clear();
sfx->data3d.Clear();
} }
//========================================================================== //==========================================================================

View file

@ -38,10 +38,7 @@
#include "c_cvars.h" #include "c_cvars.h"
#include "critsec.h" #include "critsec.h"
#include "v_text.h" #include "v_text.h"
#include "files.h"
#include "templates.h" #include "templates.h"
#include "sndfile_decoder.h"
#include "mpg123_decoder.h"
#include "m_fixed.h" #include "m_fixed.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -82,6 +79,18 @@ protected:
// PUBLIC DATA DEFINITIONS ------------------------------------------------- // 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 ------------------------------------------------ // PRIVATE DATA DEFINITIONS ------------------------------------------------
// CODE -------------------------------------------------------------------- // CODE --------------------------------------------------------------------
@ -121,7 +130,7 @@ void FindLoopTags(FileReader *fr, uint32_t *start, bool *startass, uint32_t *end
} }
c -= 3; c -= 3;
int len = c[0] + 256*c[1] + 65536*c[2]; 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 '=' // length looks fishy so retry with the next '='
continue; continue;
@ -209,7 +218,7 @@ SndFileSong::SndFileSong(FileReader *reader, SoundDecoder *decoder, uint32_t loo
Reader = reader; Reader = reader;
Decoder = decoder; Decoder = decoder;
Channels = iChannels == ChannelConfig_Stereo? 2:1; 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) if (currentpos + framestoread > song->Loop_End)
{ {
size_t endblock = (song->Loop_End - currentpos) * song->Channels * 2; 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) if (endlen != 0)
{ {
buff = buff + endlen; buff = buff + endlen;

View file

@ -1585,7 +1585,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int
else else
{ {
if((chanflags&SNDF_ABSTIME)) if((chanflags&SNDF_ABSTIME))
alSourcef(source, AL_SAMPLE_OFFSET, reuse_chan->StartTime.Lo); alSourcei(source, AL_SAMPLE_OFFSET, reuse_chan->StartTime.Lo);
else else
{ {
float offset = std::chrono::duration_cast<std::chrono::duration<float>>( float offset = std::chrono::duration_cast<std::chrono::duration<float>>(
@ -1793,7 +1793,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
else else
{ {
if((chanflags&SNDF_ABSTIME)) if((chanflags&SNDF_ABSTIME))
alSourcef(source, AL_SAMPLE_OFFSET, reuse_chan->StartTime.Lo); alSourcei(source, AL_SAMPLE_OFFSET, reuse_chan->StartTime.Lo);
else else
{ {
float offset = std::chrono::duration_cast<std::chrono::duration<float>>( float offset = std::chrono::duration_cast<std::chrono::duration<float>>(

View file

@ -420,7 +420,7 @@ void OPLio::WriteTremolo(uint32_t channel, struct GenMidiVoice *voice, bool vibr
val2 |= 0x40; val2 |= 0x40;
} }
WriteOperator(OPL_REGS_TREMOLO, channel, 1, val2); WriteOperator(OPL_REGS_TREMOLO, channel, 1, val2);
WriteOperator(OPL_REGS_TREMOLO, channel, 0, val2); WriteOperator(OPL_REGS_TREMOLO, channel, 0, val1);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View file

@ -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. // Otherwise, put the crashing thread to sleep and signal the main thread to clean up.
if (GetCurrentThreadId() == MainThreadID) if (GetCurrentThreadId() == MainThreadID)
{ {
#ifdef _M_X64
*info->ContextRecord = MainThreadContext; *info->ContextRecord = MainThreadContext;
#else
info->ContextRecord->Eip = (DWORD_PTR)ExitFatally;
#endif // _M_X64
} }
else else
{ {
@ -1315,6 +1319,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE nothing, LPSTR cmdline, int n
{ {
SetUnhandledExceptionFilter (CatchAllExceptions); SetUnhandledExceptionFilter (CatchAllExceptions);
#ifdef _M_X64
static bool setJumpResult = false; static bool setJumpResult = false;
RtlCaptureContext(&MainThreadContext); RtlCaptureContext(&MainThreadContext);
if (setJumpResult) if (setJumpResult)
@ -1323,6 +1328,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE nothing, LPSTR cmdline, int n
return 0; return 0;
} }
setJumpResult = true; setJumpResult = true;
#endif // _M_X64
} }
#endif #endif

View file

@ -817,7 +817,7 @@ class PlayerPawn : Actor native
double factor = 1.; double factor = 1.;
for(let it = Inv; it != null; it = it.Inv) for(let it = Inv; it != null; it = it.Inv)
{ {
factor *= Inv.GetSpeedFactor (); factor *= it.GetSpeedFactor ();
} }
forward *= factor; forward *= factor;
side *= factor; side *= factor;