diff --git a/.travis.yml b/.travis.yml index 6d4cc4bb7..77a2ea7ce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ git: matrix: include: - os: osx - osx_image: xcode8.2 + osx_image: xcode8.3 env: - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.7" diff --git a/soundfont/gzdoom.sf2 b/soundfont/gzdoom.sf2 new file mode 100644 index 000000000..27cc01c18 Binary files /dev/null and b/soundfont/gzdoom.sf2 differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a9b65cb1d..387d6855f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -517,7 +517,6 @@ set( PLAT_UNIX_SOURCES posix/unix/i_specialpaths.cpp posix/unix/iwadpicker_gtk.cpp ) set( PLAT_OSX_SOURCES - sound/mididevices/music_audiotoolbox_mididevice.cpp posix/osx/iwadpicker_cocoa.mm posix/osx/i_specialpaths.mm posix/osx/zdoom.icns ) @@ -1254,12 +1253,17 @@ if( MSVC ) create_default_target_launcher( zdoom WORKING_DIRECTORY ${ZDOOM_OUTPUT_DIR} ) endif() -if( NOT WIN32 ) +if( NOT WIN32 AND NOT APPLE ) FILE( WRITE ${CMAKE_CURRENT_BINARY_DIR}/link-make "if [ ! -e ${ZDOOM_OUTPUT_DIR}/${ZDOOM_EXE_NAME} ]; then ln -sf ${CMAKE_CURRENT_BINARY_DIR}/${ZDOOM_EXE_NAME} ${ZDOOM_OUTPUT_DIR}/${ZDOOM_EXE_NAME}; fi" ) add_custom_command( TARGET zdoom POST_BUILD COMMAND chmod +x ${CMAKE_CURRENT_BINARY_DIR}/link-make COMMAND /bin/sh -c ${CMAKE_CURRENT_BINARY_DIR}/link-make ) endif() + +add_custom_command(TARGET zdoom POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_SOURCE_DIR}/soundfont/gzdoom.sf2 $) + if( CMAKE_COMPILER_IS_GNUCXX ) # GCC misoptimizes this file set_source_files_properties( oplsynth/fmopl.cpp PROPERTIES COMPILE_FLAGS "-fno-tree-dominator-opts -fno-tree-fre" ) @@ -1278,7 +1282,7 @@ endif() if( APPLE ) set_target_properties(zdoom PROPERTIES - LINK_FLAGS "-framework AudioToolbox -framework AudioUnit -framework Carbon -framework Cocoa -framework IOKit -framework OpenGL" + LINK_FLAGS "-framework Carbon -framework Cocoa -framework IOKit -framework OpenGL" MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/posix/osx/zdoom-info.plist" ) endif() diff --git a/src/d_main.cpp b/src/d_main.cpp index 12acc62f5..650d99ae8 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -149,7 +149,7 @@ void ParseGLDefs(); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- void D_DoomLoop (); -static const char *BaseFileSearch (const char *file, const char *ext, bool lookfirstinprogdir=false); +const char *BaseFileSearch (const char *file, const char *ext, bool lookfirstinprogdir=false); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- @@ -1693,7 +1693,7 @@ static void D_AddDirectory (TArray &wadfiles, const char *dir) // //========================================================================== -static const char *BaseFileSearch (const char *file, const char *ext, bool lookfirstinprogdir) +const char *BaseFileSearch (const char *file, const char *ext, bool lookfirstinprogdir) { static char wad[PATH_MAX]; diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index 468ecefc2..5bccda3e7 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -119,6 +119,7 @@ void GLPortal::ClearScreen() gl_RenderState.mViewMatrix.loadIdentity(); gl_RenderState.mProjectionMatrix.ortho(0, SCREENWIDTH, SCREENHEIGHT, 0, -1.0f, 1.0f); gl_RenderState.ApplyMatrices(); + glVertexAttrib4f(VATTR_COLOR, 0, 0, 0, 1); // color should be black. glDisable(GL_MULTISAMPLE); glDisable(GL_DEPTH_TEST); diff --git a/src/p_map.cpp b/src/p_map.cpp index d997cffe6..5ffcbc423 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -2763,7 +2763,11 @@ bool P_CheckMove(AActor *thing, const DVector2 &pos, int flags) FCheckPosition tm; double newz = thing->Z(); - if (!P_CheckPosition(thing, pos, tm)) + auto f1 = thing->flags & MF_PICKUP; + thing->flags &= ~MF_PICKUP; + auto res = P_CheckPosition(thing, pos, tm); + thing->flags |= f1; + if (!res) { // Ignore PCM_DROPOFF. Not necessary here: a little later it is. if (!flags || (!(flags & PCM_NOACTORS) && !(flags & PCM_NOLINES))) diff --git a/src/polyrenderer/poly_renderer.cpp b/src/polyrenderer/poly_renderer.cpp index a0a0483b3..2da2dbcf9 100644 --- a/src/polyrenderer/poly_renderer.cpp +++ b/src/polyrenderer/poly_renderer.cpp @@ -159,8 +159,6 @@ void PolyRenderer::ClearBuffers() PolyStencilBuffer::Instance()->Clear(RenderTarget->GetWidth(), RenderTarget->GetHeight(), 0); PolySubsectorGBuffer::Instance()->Resize(RenderTarget->GetPitch(), RenderTarget->GetHeight()); NextStencilValue = 0; - SeenLinePortals.clear(); - SeenMirrors.clear(); } void PolyRenderer::SetSceneViewport() @@ -216,13 +214,3 @@ void PolyRenderer::SetupPerspectiveMatrix() WorldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView; } - -bool PolyRenderer::InsertSeenLinePortal(FLinePortal *portal) -{ - return SeenLinePortals.insert(portal).second; -} - -bool PolyRenderer::InsertSeenMirror(line_t *mirrorLine) -{ - return SeenMirrors.insert(mirrorLine).second; -} diff --git a/src/polyrenderer/poly_renderer.h b/src/polyrenderer/poly_renderer.h index ead3c8eac..efd1bbf67 100644 --- a/src/polyrenderer/poly_renderer.h +++ b/src/polyrenderer/poly_renderer.h @@ -52,9 +52,6 @@ public: uint32_t GetNextStencilValue() { uint32_t value = NextStencilValue; NextStencilValue += 2; return value; } - bool InsertSeenLinePortal(FLinePortal *portal); - bool InsertSeenMirror(line_t *mirrorLine); - bool DontMapLines = false; RenderMemory FrameMemory; @@ -75,7 +72,4 @@ private: PolySkyDome Skydome; RenderPolyPlayerSprites PlayerSprites; uint32_t NextStencilValue = 0; - - std::set SeenLinePortals; - std::set SeenMirrors; }; diff --git a/src/polyrenderer/scene/poly_cull.cpp b/src/polyrenderer/scene/poly_cull.cpp index 623b6e9df..8f19cb901 100644 --- a/src/polyrenderer/scene/poly_cull.cpp +++ b/src/polyrenderer/scene/poly_cull.cpp @@ -70,6 +70,20 @@ void PolyCull::CullNode(void *node) void PolyCull::CullSubsector(subsector_t *sub) { + // Check if subsector is clipped entirely by the portal clip plane + bool visible = false; + for (uint32_t i = 0; i < sub->numlines; i++) + { + seg_t *line = &sub->firstline[i]; + if (PortalClipPlane.A * line->v1->fX() + PortalClipPlane.B * line->v1->fY() + PortalClipPlane.D > 0.0) + { + visible = true; + break; + } + } + if (!visible) + return; + // Update sky heights for the scene if (!FirstSkyHeight) { @@ -98,6 +112,13 @@ void PolyCull::CullSubsector(subsector_t *sub) if (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0) continue; + // Skip line if entirely behind portal clipping plane + if ((PortalClipPlane.A * line->v1->fX() + PortalClipPlane.B * line->v1->fY() + PortalClipPlane.D <= 0.0) || + (PortalClipPlane.A * line->v2->fX() + PortalClipPlane.B * line->v2->fY() + PortalClipPlane.D <= 0.0)) + { + continue; + } + angle_t angle1, angle2; if (GetAnglesForLine(line->v1->fX(), line->v1->fY(), line->v2->fX(), line->v2->fY(), angle1, angle2)) { @@ -119,11 +140,11 @@ void PolyCull::InvertSegments() angle_t cur = 0; for (const auto &segment : TempInvertSolidSegments) { - if (segment.Start != 0 || segment.End != ANGLE_MAX) + if (cur < segment.Start) MarkSegmentCulled(cur, segment.Start - 1); cur = segment.End + 1; } - if (cur != 0) + if (cur < ANGLE_MAX) MarkSegmentCulled(cur, ANGLE_MAX); } @@ -241,32 +262,6 @@ bool PolyCull::CheckBBox(float *bspcoord) bool PolyCull::GetAnglesForLine(double x1, double y1, double x2, double y2, angle_t &angle1, angle_t &angle2) const { -#if 0 - // Clip line to the portal clip plane - float distance1 = Vec4f::dot(PortalClipPlane, Vec4f((float)x1, (float)y1, 0.0f, 1.0f)); - float distance2 = Vec4f::dot(PortalClipPlane, Vec4f((float)x2, (float)y2, 0.0f, 1.0f)); - if (distance1 < 0.0f && distance2 < 0.0f) - { - return false; - } - else if (distance1 < 0.0f || distance2 < 0.0f) - { - double t1 = 0.0f, t2 = 1.0f; - if (distance1 < 0.0f) - t1 = clamp(distance1 / (distance1 - distance2), 0.0f, 1.0f); - else - t2 = clamp(distance2 / (distance1 - distance2), 0.0f, 1.0f); - double nx1 = x1 * (1.0 - t1) + x2 * t1; - double ny1 = y1 * (1.0 - t1) + y2 * t1; - double nx2 = x1 * (1.0 - t2) + x2 * t2; - double ny2 = y1 * (1.0 - t2) + y2 * t2; - x1 = nx1; - x2 = nx2; - y1 = ny1; - y2 = ny2; - } -#endif - angle2 = PointToPseudoAngle(x1, y1); angle1 = PointToPseudoAngle(x2, y2); return !IsSegmentCulled(angle1, angle2); diff --git a/src/polyrenderer/scene/poly_cull.h b/src/polyrenderer/scene/poly_cull.h index 64e4d5739..0af3b22f9 100644 --- a/src/polyrenderer/scene/poly_cull.h +++ b/src/polyrenderer/scene/poly_cull.h @@ -40,6 +40,8 @@ public: double MaxCeilingHeight = 0.0; double MinFloorHeight = 0.0; + static angle_t PointToPseudoAngle(double x, double y); + private: struct SolidSegment { @@ -62,6 +64,5 @@ private: PolyClipPlane PortalClipPlane; - static angle_t PointToPseudoAngle(double x, double y); static angle_t AngleToPseudo(angle_t ang); }; diff --git a/src/polyrenderer/scene/poly_portal.cpp b/src/polyrenderer/scene/poly_portal.cpp index 0e0ffbf38..ff529895f 100644 --- a/src/polyrenderer/scene/poly_portal.cpp +++ b/src/polyrenderer/scene/poly_portal.cpp @@ -43,44 +43,10 @@ void PolyDrawSectorPortal::Render(int portalDepth) if (Portal->mType == PORTS_HORIZON || Portal->mType == PORTS_PLANE) return; - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - - PolyClipPlane portalPlane(0.0f, 0.0f, 0.0f, 1.0f); - if (Portal->mType != PORTS_SKYVIEWPOINT) - { - float minHeight; - float maxHeight; - bool first = true; - for (const auto &range : Shape) - { - for (int i = 0; i < range.Count; i++) - { - if (first) - { - minHeight = range.Vertices[i].z; - maxHeight = range.Vertices[i].z; - first = false; - } - else - { - minHeight = MIN(minHeight, range.Vertices[i].z); - maxHeight = MAX(maxHeight, range.Vertices[i].z); - } - } - } - - if (!first && minHeight > viewpoint.Pos.Z) - { - portalPlane = PolyClipPlane(0.0f, 0.0f, 1.0f, -minHeight); - } - else if (!first && maxHeight < viewpoint.Pos.Z) - { - portalPlane = PolyClipPlane(0.0f, 0.0f, -1.0f, maxHeight); - } - } - SaveGlobals(); + const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; + // To do: get this information from PolyRenderer instead of duplicating the code.. const auto &viewwindow = PolyRenderer::Instance()->Viewwindow; double radPitch = viewpoint.Angles.Pitch.Normalized180().Radians(); @@ -100,6 +66,7 @@ void PolyDrawSectorPortal::Render(int portalDepth) TriMatrix::translate((float)-viewpoint.Pos.X, (float)-viewpoint.Pos.Y, (float)-viewpoint.Pos.Z); TriMatrix worldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView; + PolyClipPlane portalPlane(0.0f, 0.0f, 0.0f, 1.0f); RenderPortal.SetViewpoint(worldToClip, portalPlane, StencilValue); RenderPortal.SetPortalSegments(Segments); RenderPortal.Render(portalDepth); @@ -211,14 +178,29 @@ void PolyDrawLinePortal::Render(int portalDepth) worldToView = TriMatrix::scale(-1.0f, 1.0f, 1.0f) * worldToView; TriMatrix worldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView; - // Calculate plane clipping + // Find portal destination line and make sure it faces the right way line_t *clipLine = Portal ? Portal->mDestination : Mirror; - DVector2 planePos = clipLine->v1->fPos(); - DVector2 planeNormal = (clipLine->v2->fPos() - clipLine->v1->fPos()).Rotated90CW(); + DVector2 pt1 = clipLine->v1->fPos() - viewpoint.Pos; + DVector2 pt2 = clipLine->v2->fPos() - viewpoint.Pos; + bool backfacing = (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0); + vertex_t *v1 = backfacing ? clipLine->v1 : clipLine->v2; + vertex_t *v2 = backfacing ? clipLine->v2 : clipLine->v1; + + // Calculate plane clipping + DVector2 planePos = v1->fPos(); + DVector2 planeNormal = (v2->fPos() - v1->fPos()).Rotated90CW(); planeNormal.MakeUnit(); double planeD = -(planeNormal | (planePos + planeNormal * 0.001)); PolyClipPlane portalPlane((float)planeNormal.X, (float)planeNormal.Y, (float)0.0f, (float)planeD); + // Cull everything outside the portal line + // To do: this doesn't work for some strange reason.. + /*angle_t angle1 = PolyCull::PointToPseudoAngle(v1->fX(), v1->fY()); + angle_t angle2 = PolyCull::PointToPseudoAngle(v2->fX(), v2->fY()); + Segments.clear(); + Segments.push_back({ angle1, angle2 });*/ + + RenderPortal.LastPortalLine = clipLine; RenderPortal.SetViewpoint(worldToClip, portalPlane, StencilValue); RenderPortal.SetPortalSegments(Segments); RenderPortal.Render(portalDepth); @@ -296,6 +278,9 @@ void PolyDrawLinePortal::SaveGlobals() P_TranslatePortalXY(src, viewpoint.Path[0].X, viewpoint.Path[0].Y); P_TranslatePortalXY(src, viewpoint.Path[1].X, viewpoint.Path[1].Y); + if (viewpoint.camera) + viewpoint.camera->renderflags &= ~RF_INVISIBLE; + if (!viewpoint.showviewer && viewpoint.camera && P_PointOnLineSidePrecise(viewpoint.Path[0], dst) != P_PointOnLineSidePrecise(viewpoint.Path[1], dst)) { double distp = (viewpoint.Path[0] - viewpoint.Path[1]).Length(); @@ -312,8 +297,8 @@ void PolyDrawLinePortal::SaveGlobals() } } - //camera = nullptr; - //viewsector = R_PointInSubsector(ViewPos)->sector; + viewpoint.camera = nullptr; + viewpoint.sector = R_PointInSubsector(viewpoint.Pos)->sector; R_SetViewAngle(viewpoint, viewwindow); if (Mirror) diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index 21ae23fc8..ad0d88d34 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -219,7 +219,7 @@ void RenderPolyScene::RenderPolySubsector(subsector_t *sub, uint32_t subsectorDe } // Render wall, and update culling info if its an occlusion blocker - if (RenderPolyWall::RenderLine(WorldToClip, PortalPlane, Cull, line, frontsector, subsectorDepth, StencilValue, TranslucentObjects, LinePortals)) + if (RenderPolyWall::RenderLine(WorldToClip, PortalPlane, Cull, line, frontsector, subsectorDepth, StencilValue, TranslucentObjects, LinePortals, LastPortalLine)) { Cull.MarkSegmentCulled(angle1, angle2); } @@ -319,7 +319,7 @@ void RenderPolyScene::RenderLine(subsector_t *sub, seg_t *line, sector_t *fronts } // Render wall, and update culling info if its an occlusion blocker - if (RenderPolyWall::RenderLine(WorldToClip, PortalPlane, Cull, line, frontsector, subsectorDepth, StencilValue, TranslucentObjects, LinePortals)) + if (RenderPolyWall::RenderLine(WorldToClip, PortalPlane, Cull, line, frontsector, subsectorDepth, StencilValue, TranslucentObjects, LinePortals, LastPortalLine)) { Cull.MarkSegmentCulled(angle1, angle2); } diff --git a/src/polyrenderer/scene/poly_scene.h b/src/polyrenderer/scene/poly_scene.h index fc89de7cd..8dafc949b 100644 --- a/src/polyrenderer/scene/poly_scene.h +++ b/src/polyrenderer/scene/poly_scene.h @@ -80,6 +80,8 @@ public: static const uint32_t SkySubsectorDepth = 0x7fffffff; + line_t *LastPortalLine = nullptr; + private: void ClearBuffers(); void RenderPortals(int portalDepth); diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index ce9e78456..87ee9ec12 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -37,36 +37,51 @@ EXTERN_CVAR(Bool, r_drawmirrors) -bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals) +bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals, line_t *lastPortalLine) { + double frontceilz1 = frontsector->ceilingplane.ZatPoint(line->v1); + double frontfloorz1 = frontsector->floorplane.ZatPoint(line->v1); + double frontceilz2 = frontsector->ceilingplane.ZatPoint(line->v2); + double frontfloorz2 = frontsector->floorplane.ZatPoint(line->v2); + double topTexZ = frontsector->GetPlaneTexZ(sector_t::ceiling); + double bottomTexZ = frontsector->GetPlaneTexZ(sector_t::floor); + PolyDrawLinePortal *polyportal = nullptr; if (line->backsector == nullptr && line->linedef && line->sidedef == line->linedef->sidedef[0] && (line->linedef->special == Line_Mirror && r_drawmirrors)) { - if (PolyRenderer::Instance()->InsertSeenMirror(line->linedef)) + if (lastPortalLine == line->linedef || + (line->linedef->v1->fX() * clipPlane.A + line->linedef->v1->fY() * clipPlane.B + clipPlane.D <= 0.0f) || + (line->linedef->v2->fX() * clipPlane.A + line->linedef->v2->fY() * clipPlane.B + clipPlane.D <= 0.0f)) { - linePortals.push_back(std::unique_ptr(new PolyDrawLinePortal(line->linedef))); - polyportal = linePortals.back().get(); + return false; } + + linePortals.push_back(std::unique_ptr(new PolyDrawLinePortal(line->linedef))); + polyportal = linePortals.back().get(); } else if (line->linedef && line->linedef->isVisualPortal()) { - FLinePortal *portal = line->linedef->getPortal(); - if (PolyRenderer::Instance()->InsertSeenLinePortal(portal)) + if (lastPortalLine == line->linedef || + (line->linedef->v1->fX() * clipPlane.A + line->linedef->v1->fY() * clipPlane.B + clipPlane.D <= 0.0f) || + (line->linedef->v2->fX() * clipPlane.A + line->linedef->v2->fY() * clipPlane.B + clipPlane.D <= 0.0f)) { - for (auto &p : linePortals) + return false; + } + + FLinePortal *portal = line->linedef->getPortal(); + for (auto &p : linePortals) + { + if (p->Portal == portal) // To do: what other criterias do we need to check for? { - if (p->Portal == portal) // To do: what other criterias do we need to check for? - { - polyportal = p.get(); - break; - } - } - if (!polyportal) - { - linePortals.push_back(std::unique_ptr(new PolyDrawLinePortal(portal))); - polyportal = linePortals.back().get(); + polyportal = p.get(); + break; } } + if (!polyportal) + { + linePortals.push_back(std::unique_ptr(new PolyDrawLinePortal(portal))); + polyportal = linePortals.back().get(); + } } RenderPolyWall wall; @@ -78,13 +93,6 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const PolyClipPlan wall.SubsectorDepth = subsectorDepth; wall.StencilValue = stencilValue; - double frontceilz1 = frontsector->ceilingplane.ZatPoint(line->v1); - double frontfloorz1 = frontsector->floorplane.ZatPoint(line->v1); - double frontceilz2 = frontsector->ceilingplane.ZatPoint(line->v2); - double frontfloorz2 = frontsector->floorplane.ZatPoint(line->v2); - double topTexZ = frontsector->GetPlaneTexZ(sector_t::ceiling); - double bottomTexZ = frontsector->GetPlaneTexZ(sector_t::floor); - if (line->backsector == nullptr) { if (line->sidedef) @@ -244,6 +252,14 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip, const PolyClipPlane &c vertices[3].u = (float)texcoordsU.u1; vertices[3].v = (float)texcoordsVLeft.v2; } + else + { + for (int i = 0; i < 4; i++) + { + vertices[i].u = 0.0f; + vertices[i].v = 0.0f; + } + } // Masked walls clamp to the 0-1 range (no texture repeat) if (Masked) @@ -259,7 +275,7 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip, const PolyClipPlane &c args.SetFaceCullCCW(true); args.SetStencilTestValue(StencilValue); args.SetWriteStencil(true, StencilValue + 1); - if (tex) + if (tex && !Polyportal) args.SetTexture(tex); args.SetClipPlane(clipPlane); @@ -270,10 +286,6 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip, const PolyClipPlane &c args.SetWriteSubsectorDepth(false); args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan); Polyportal->Shape.push_back({ vertices, 4, true, SubsectorDepth }); - - angle_t angle1, angle2; - if (cull.GetAnglesForLine(v1.X, v1.Y, v2.X, v2.Y, angle1, angle2)) - Polyportal->Segments.push_back({ angle1, angle2 }); } else if (!Masked) { @@ -363,20 +375,24 @@ int RenderPolyWall::GetLightLevel() PolyWallTextureCoordsU::PolyWallTextureCoordsU(FTexture *tex, const seg_t *lineseg, const line_t *line, const side_t *side, side_t::ETexpart texpart) { - double lineLength = side->TexelLength; - double lineStart = 0.0; - - bool entireSegment = ((lineseg->v1 == line->v1) && (lineseg->v2 == line->v2)) || ((lineseg->v2 == line->v1) && (lineseg->v1 == line->v2)); - if (!entireSegment) + double t1, t2; + double deltaX = line->v2->fX() - line->v1->fX(); + double deltaY = line->v2->fY() - line->v1->fY(); + if (fabs(deltaX) > fabs(deltaY)) { - lineLength = (lineseg->v2->fPos() - lineseg->v1->fPos()).Length(); - lineStart = (lineseg->v1->fPos() - line->v1->fPos()).Length(); + t1 = (lineseg->v1->fX() - line->v1->fX()) / deltaX; + t2 = (lineseg->v2->fX() - line->v1->fX()) / deltaX; + } + else + { + t1 = (lineseg->v1->fY() - line->v1->fY()) / deltaY; + t2 = (lineseg->v2->fY() - line->v1->fY()) / deltaY; } int texWidth = tex->GetWidth(); double uscale = side->GetTextureXScale(texpart) * tex->Scale.X; - u1 = lineStart + side->GetTextureXOffset(texpart); - u2 = u1 + lineLength; + u1 = t1 * side->TexelLength + side->GetTextureXOffset(texpart); + u2 = t2 * side->TexelLength + side->GetTextureXOffset(texpart); u1 *= uscale; u2 *= uscale; u1 /= texWidth; diff --git a/src/polyrenderer/scene/poly_wall.h b/src/polyrenderer/scene/poly_wall.h index 8a38447c8..f519b4a55 100644 --- a/src/polyrenderer/scene/poly_wall.h +++ b/src/polyrenderer/scene/poly_wall.h @@ -31,7 +31,7 @@ class PolyCull; class RenderPolyWall { public: - static bool RenderLine(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals); + static bool RenderLine(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals, line_t *lastPortalLine); static void Render3DFloorLine(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, PolyCull &cull, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector &translucentWallsOutput); void SetCoords(const DVector2 &v1, const DVector2 &v2, double ceil1, double floor1, double ceil2, double floor2); diff --git a/src/portal.cpp b/src/portal.cpp index 9926f289e..41158e0ee 100644 --- a/src/portal.cpp +++ b/src/portal.cpp @@ -1027,8 +1027,17 @@ void P_CreateLinkedPortals() { if (linePortals[i].mType == PORTT_LINKED) { - if (CollectSectors(id, linePortals[i].mOrigin->frontsector)) id++; - if (CollectSectors(id, linePortals[i].mDestination->frontsector)) id++; + if (linePortals[i].mDestination == nullptr) + { + Printf("Linked portal on line %d is unconnected and will be disabled\n", linePortals[i].mOrigin->Index()); + linePortals[i].mOrigin->portalindex = UINT_MAX; + linePortals[i].mType = PORTT_VISUAL; + } + else + { + if (CollectSectors(id, linePortals[i].mOrigin->frontsector)) id++; + if (CollectSectors(id, linePortals[i].mDestination->frontsector)) id++; + } } } @@ -1237,6 +1246,7 @@ bool P_CollectConnectedGroups(int startgroup, const DVector3 &position, double u { int othergroup = wsec->GetOppositePortalGroup(sector_t::ceiling); DVector2 pos = Displacements.getOffset(startgroup, othergroup) + position; + if (processMask.getBit(othergroup)) break; processMask.setBit(othergroup); out.Add(othergroup | FPortalGroupArray::UPPER); wsec = P_PointInSector(pos); // get upper sector at the exact spot we want to check and repeat @@ -1247,6 +1257,7 @@ bool P_CollectConnectedGroups(int startgroup, const DVector3 &position, double u { int othergroup = wsec->GetOppositePortalGroup(sector_t::floor); DVector2 pos = Displacements.getOffset(startgroup, othergroup) + position; + if (processMask.getBit(othergroup)) break; processMask.setBit(othergroup); out.Add(othergroup | FPortalGroupArray::LOWER); wsec = P_PointInSector(pos); // get lower sector at the exact spot we want to check and repeat diff --git a/src/posix/sdl/sdlglvideo.cpp b/src/posix/sdl/sdlglvideo.cpp index 0aacb8454..e2318a1fb 100644 --- a/src/posix/sdl/sdlglvideo.cpp +++ b/src/posix/sdl/sdlglvideo.cpp @@ -555,3 +555,38 @@ int SDLGLFB::GetClientHeight() SDL_GL_GetDrawableSize(Screen, nullptr, &height); return height; } + +void SDLGLFB::ScaleCoordsFromWindow(int16_t &x, int16_t &y) +{ + int w, h; + SDL_GetWindowSize (Screen, &w, &h); + + // Detect if we're doing scaling in the Window and adjust the mouse + // coordinates accordingly. This could be more efficent, but I + // don't think performance is an issue in the menus. + if(IsFullscreen()) + { + int realw = w, realh = h; + ScaleWithAspect (realw, realh, SCREENWIDTH, SCREENHEIGHT); + if (realw != SCREENWIDTH || realh != SCREENHEIGHT) + { + double xratio = (double)SCREENWIDTH/realw; + double yratio = (double)SCREENHEIGHT/realh; + if (realw < w) + { + x = (x - (w - realw)/2)*xratio; + y *= yratio; + } + else + { + y = (y - (h - realh)/2)*yratio; + x *= xratio; + } + } + } + else + { + x = (int16_t)(x*Width/w); + y = (int16_t)(y*Height/h); + } +} diff --git a/src/posix/sdl/sdlglvideo.h b/src/posix/sdl/sdlglvideo.h index 69472c848..8fcc184e6 100644 --- a/src/posix/sdl/sdlglvideo.h +++ b/src/posix/sdl/sdlglvideo.h @@ -72,6 +72,8 @@ public: int GetClientWidth(); int GetClientHeight(); + virtual void ScaleCoordsFromWindow(int16_t &x, int16_t &y); + SDL_Window *GetSDLWindow() override { return Screen; } protected: diff --git a/src/posix/sdl/sdlvideo.cpp b/src/posix/sdl/sdlvideo.cpp index 5186b2553..828a47f74 100644 --- a/src/posix/sdl/sdlvideo.cpp +++ b/src/posix/sdl/sdlvideo.cpp @@ -112,31 +112,6 @@ static cycle_t SDLFlipCycles; // CODE -------------------------------------------------------------------- -void ScaleWithAspect (int &w, int &h, int Width, int Height) -{ - int resRatio = CheckRatio (Width, Height); - int screenRatio; - CheckRatio (w, h, &screenRatio); - if (resRatio == screenRatio) - return; - - double yratio; - switch(resRatio) - { - case 0: yratio = 4./3.; break; - case 1: yratio = 16./9.; break; - case 2: yratio = 16./10.; break; - case 3: yratio = 17./10.; break; - case 4: yratio = 5./4.; break; - default: return; - } - double y = w/yratio; - if (y > h) - w = h*yratio; - else - h = y; -} - // FrameBuffer implementation ----------------------------------------------- SDLFB::SDLFB (int width, int height, bool bgra, bool fullscreen, SDL_Window *oldwin) diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index 054062033..661af0270 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -236,11 +236,6 @@ public: { return "Null sound module has no stats."; } - - virtual MIDIDevice* CreateMIDIDevice() const override - { - return nullptr; - } }; void I_InitSound () diff --git a/src/sound/i_sound.h b/src/sound/i_sound.h index d6c4a7d78..333eda229 100644 --- a/src/sound/i_sound.h +++ b/src/sound/i_sound.h @@ -168,8 +168,6 @@ public: virtual void DrawWaveDebug(int mode); - virtual MIDIDevice* CreateMIDIDevice() const = 0; - static SoundDecoder *CreateDecoder(FileReader *reader); }; diff --git a/src/sound/mididevices/music_audiotoolbox_mididevice.cpp b/src/sound/mididevices/music_audiotoolbox_mididevice.cpp deleted file mode 100644 index 859fdd31c..000000000 --- a/src/sound/mididevices/music_audiotoolbox_mididevice.cpp +++ /dev/null @@ -1,344 +0,0 @@ -// -//--------------------------------------------------------------------------- -// -// MIDI device for Apple's macOS using AudioToolbox framework -// Copyright(C) 2017 Alexey Lysiuk -// All rights reserved. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ -// -//-------------------------------------------------------------------------- -// - -// Implementation is loosely based on macOS native MIDI support from SDL_mixer - -#ifdef __APPLE__ - -#include -#include "i_musicinterns.h" -#include "templates.h" - -// AudioToolbox implementation of a MIDI output device ---------------------- - -class AudioToolboxMIDIDevice : public MIDIDevice -{ -public: - virtual int Open(MidiCallback, void *userData) override; - virtual void Close() override; - virtual bool IsOpen() const override; - virtual int GetTechnology() const override; - virtual int SetTempo(int tempo) override; - virtual int SetTimeDiv(int timediv) override; - virtual int StreamOut(MidiHeader *data) override; - virtual int StreamOutSync(MidiHeader *data) override; - virtual int Resume() override; - virtual void Stop() override; - virtual int PrepareHeader(MidiHeader* data) override; - virtual bool FakeVolume() override { return true; } - virtual bool Pause(bool paused) override; - virtual bool Preprocess(MIDIStreamer *song, bool looping) override; - -private: - MusicPlayer m_player = nullptr; - MusicSequence m_sequence = nullptr; - AudioUnit m_audioUnit = nullptr; - CFRunLoopTimerRef m_timer = nullptr; - MusicTimeStamp m_length = 0; - - MidiCallback m_callback = nullptr; - void* m_userData = nullptr; - - static void TimerCallback(CFRunLoopTimerRef timer, void* info); -}; - - - -#define AT_MIDI_CHECK_ERROR(CALL,...) \ -{ \ - const OSStatus result = CALL; \ - if (noErr != result) \ - { \ - DPrintf(DMSG_ERROR, \ - "Failed with error 0x%08X at " __FILE__ ":%d:\n> %s", \ - int(result), __LINE__, #CALL); \ - return __VA_ARGS__; \ - } \ -} - -int AudioToolboxMIDIDevice::Open(MidiCallback callback, void *userData) -{ - AT_MIDI_CHECK_ERROR(NewMusicPlayer(&m_player), false); - AT_MIDI_CHECK_ERROR(NewMusicSequence(&m_sequence), false); - AT_MIDI_CHECK_ERROR(MusicPlayerSetSequence(m_player, m_sequence), false); - - CFRunLoopTimerContext context = { 0, this, nullptr, nullptr, nullptr }; - m_timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent(), 0.1, 0, 0, TimerCallback, &context); - - if (nullptr == m_timer) - { - DPrintf(DMSG_ERROR, "Failed with create timer for MIDI playback"); - return 1; - } - - CFRunLoopAddTimer(CFRunLoopGetCurrent(), m_timer, kCFRunLoopDefaultMode); - - m_callback = callback; - m_userData = userData; - - return 0; -} - -void AudioToolboxMIDIDevice::Close() -{ - m_length = 0; - m_audioUnit = nullptr; - - m_callback = nullptr; - m_userData = nullptr; - - if (nullptr != m_timer) - { - CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), m_timer, kCFRunLoopDefaultMode); - - CFRelease(m_timer); - m_timer = nullptr; - } - - if (nullptr != m_sequence) - { - DisposeMusicSequence(m_sequence); - m_sequence = nullptr; - } - - if (nullptr != m_player) - { - DisposeMusicPlayer(m_player); - m_player = nullptr; - } -} - -bool AudioToolboxMIDIDevice::IsOpen() const -{ - return nullptr != m_player - && nullptr != m_sequence - && nullptr != m_timer; -} - -int AudioToolboxMIDIDevice::GetTechnology() const -{ - return MIDIDEV_SWSYNTH; -} - -int AudioToolboxMIDIDevice::SetTempo(int tempo) -{ - return 0; -} - -int AudioToolboxMIDIDevice::SetTimeDiv(int timediv) -{ - return 0; -} - -int AudioToolboxMIDIDevice::StreamOut(MidiHeader* data) -{ - return 0; -} - -int AudioToolboxMIDIDevice::StreamOutSync(MidiHeader* data) -{ - return 0; -} - -int AudioToolboxMIDIDevice::Resume() -{ - AT_MIDI_CHECK_ERROR(MusicPlayerSetTime(m_player, 0), false); - AT_MIDI_CHECK_ERROR(MusicPlayerPreroll(m_player), false); - - if (nullptr == m_audioUnit) - { - AUGraph graph; - AT_MIDI_CHECK_ERROR(MusicSequenceGetAUGraph(m_sequence, &graph), false); - - UInt32 nodecount; - AT_MIDI_CHECK_ERROR(AUGraphGetNodeCount(graph, &nodecount), false); - - for (UInt32 i = 0; i < nodecount; ++i) - { - AUNode node; - AT_MIDI_CHECK_ERROR(AUGraphGetIndNode(graph, i, &node), false); - - AudioUnit audioUnit = nullptr; -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 - ComponentDescription desc = {}; - UInt32 classdatasize = 0; - void *classdata = nullptr; - AT_MIDI_CHECK_ERROR(AUGraphGetNodeInfo(graph, node, &desc, &classdatasize, &classdata, &audioUnit), false); -#else // 10.5 and above - AudioComponentDescription desc = {}; - AT_MIDI_CHECK_ERROR(AUGraphNodeInfo(graph, node, &desc, &audioUnit), false); -#endif // prior to 10.5 - - if ( kAudioUnitType_Output != desc.componentType - || kAudioUnitSubType_DefaultOutput != desc.componentSubType) - { - continue; - } - - const float volume = clamp(snd_musicvolume * relative_volume, 0.f, 1.f); - AT_MIDI_CHECK_ERROR(AudioUnitSetParameter(audioUnit, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, volume, 0), false); - - m_audioUnit = audioUnit; - break; - } - } - - AT_MIDI_CHECK_ERROR(MusicPlayerStart(m_player), false); - - return 0; -} - -void AudioToolboxMIDIDevice::Stop() -{ - AT_MIDI_CHECK_ERROR(MusicPlayerStop(m_player)); -} - -int AudioToolboxMIDIDevice::PrepareHeader(MidiHeader* data) -{ - MidiHeader* events = data; - uint32_t position = 0; - - while (nullptr != events) - { - uint32_t* const event = reinterpret_cast(events->lpData + position); - const uint32_t message = event[2]; - - if (0 == MEVENT_EVENTTYPE(message)) - { - static const uint32_t VOLUME_CHANGE_EVENT = 7; - - const uint32_t status = message & 0xFF; - const uint32_t param1 = (message >> 8) & 0x7F; - const uint32_t param2 = (message >> 16) & 0x7F; - - if (nullptr != m_audioUnit && MIDI_CTRLCHANGE == status && VOLUME_CHANGE_EVENT == param1) - { - AT_MIDI_CHECK_ERROR(AudioUnitSetParameter(m_audioUnit, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, param2 / 100.f, 0), false); - } - } - - // Advance to next event - position += 12 + ( (message < 0x80000000) - ? 0 - : ((MEVENT_EVENTPARM(message) + 3) & ~3) ); - - // Did we use up this buffer? - if (position >= events->dwBytesRecorded) - { - events = events->lpNext; - position = 0; - } - - if (nullptr == events) - { - break; - } - } - - return 0; -} - -bool AudioToolboxMIDIDevice::Pause(bool paused) -{ - return false; -} - -static MusicTimeStamp GetSequenceLength(MusicSequence sequence) -{ - UInt32 trackCount; - AT_MIDI_CHECK_ERROR(MusicSequenceGetTrackCount(sequence, &trackCount), 0); - - MusicTimeStamp result = 0; - - for (UInt32 i = 0; i < trackCount; ++i) - { - MusicTrack track; - AT_MIDI_CHECK_ERROR(MusicSequenceGetIndTrack(sequence, i, &track), 0); - - MusicTimeStamp trackLength = 0; - UInt32 trackLengthSize = sizeof trackLength; - - AT_MIDI_CHECK_ERROR(MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength, &trackLength, &trackLengthSize), 0); - - if (result < trackLength) - { - result = trackLength; - } - } - - return result; -} - -bool AudioToolboxMIDIDevice::Preprocess(MIDIStreamer* song, bool looping) -{ - assert(nullptr != song); - - TArray midi; - song->CreateSMF(midi, looping ? 0 : 1); - - CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, &midi[0], midi.Size(), kCFAllocatorNull); - if (nullptr == data) - { - DPrintf(DMSG_ERROR, "Failed with create CFDataRef for MIDI song"); - return false; - } - -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 - AT_MIDI_CHECK_ERROR(MusicSequenceLoadSMFDataWithFlags(m_sequence, data, 0), false); -#else // 10.5 and above - AT_MIDI_CHECK_ERROR(MusicSequenceFileLoadData(m_sequence, data, kMusicSequenceFile_MIDIType, 0), CFRelease(data), false); -#endif // prior to 10.5 - - CFRelease(data); - - m_length = GetSequenceLength(m_sequence); - - return true; -} - -void AudioToolboxMIDIDevice::TimerCallback(CFRunLoopTimerRef timer, void* info) -{ - AudioToolboxMIDIDevice* const self = static_cast(info); - - if (nullptr != self->m_callback) - { - self->m_callback(self->m_userData); - } - - MusicTimeStamp currentTime = 0; - AT_MIDI_CHECK_ERROR(MusicPlayerGetTime(self->m_player, ¤tTime)); - - if (currentTime > self->m_length) - { - MusicPlayerSetTime(self->m_player, 0); - } -} - -#undef AT_MIDI_CHECK_ERROR - -MIDIDevice *CreateAudioToolboxMIDIDevice() -{ - return new AudioToolboxMIDIDevice(); -} - -#endif // __APPLE__ diff --git a/src/sound/mididevices/music_fluidsynth_mididevice.cpp b/src/sound/mididevices/music_fluidsynth_mididevice.cpp index 47378ff56..07102c43d 100644 --- a/src/sound/mididevices/music_fluidsynth_mididevice.cpp +++ b/src/sound/mididevices/music_fluidsynth_mididevice.cpp @@ -43,6 +43,7 @@ #include "m_swap.h" #include "w_wad.h" #include "v_text.h" +#include "version.h" #include "cmdlib.h" // MACROS ------------------------------------------------------------------ @@ -91,6 +92,8 @@ extern "C" unsigned __stdcall GetSystemDirectoryA(char *lpBuffer, unsigned uSize // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- +const char *BaseFileSearch(const char *file, const char *ext, bool lookfirstinprogdir = false); + // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- @@ -315,44 +318,54 @@ FluidSynthMIDIDevice::FluidSynthMIDIDevice(const char *args) int res = 0; if (args != NULL && *args != 0) { - res = LoadPatchSets(args); + if (LoadPatchSets(args)) return; } - if (res == 0 && 0 == LoadPatchSets(fluid_patchset)) + if (LoadPatchSets(fluid_patchset)) { -#ifdef __unix__ - // This is the standard location on Ubuntu. - if (0 == LoadPatchSets("/usr/share/sounds/sf2/FluidR3_GS.sf2:/usr/share/sounds/sf2/FluidR3_GM.sf2")) - { -#endif -#ifdef _WIN32 - // On Windows, look for the 4 megabyte patch set installed by Creative's drivers as a default. - char sysdir[MAX_PATH+sizeof("\\CT4MGM.SF2")]; - uint32_t filepart; - if (0 != (filepart = GetSystemDirectoryA(sysdir, MAX_PATH))) - { - strcat(sysdir, "\\CT4MGM.SF2"); - if (0 == LoadPatchSets(sysdir)) - { - // Try again with CT2MGM.SF2 - sysdir[filepart + 3] = '2'; - if (0 == LoadPatchSets(sysdir)) - { -#endif - Printf("Failed to load any MIDI patches.\n"); - delete_fluid_synth(FluidSynth); - FluidSynth = NULL; -#ifdef _WIN32 - } - } - } -#endif -#ifdef __unix__ - } -#endif + return; } +#ifdef __unix__ + // This is the standard location on Ubuntu. + if (LoadPatchSets("/usr/share/sounds/sf2/FluidR3_GS.sf2:/usr/share/sounds/sf2/FluidR3_GM.sf2")) + { + return; + } +#endif +#ifdef _WIN32 + // On Windows, look for the 4 megabyte patch set installed by Creative's drivers as a default. + char sysdir[MAX_PATH + sizeof("\\CT4MGM.SF2")]; + uint32_t filepart; + if (0 != (filepart = GetSystemDirectoryA(sysdir, MAX_PATH))) + { + strcat(sysdir, "\\CT4MGM.SF2"); + if (LoadPatchSets(sysdir)) + { + return; + } + // Try again with CT2MGM.SF2 + sysdir[filepart + 3] = '2'; + if (LoadPatchSets(sysdir)) + { + return; + } + } + +#endif + // Last try the base sound font which should be provided by the GZDoom binary package. + auto wad = BaseFileSearch(BASESF, NULL, true); + if (wad != NULL && LoadPatchSets(wad)) + { + return; + } + + Printf("Failed to load any MIDI patches.\n"); + delete_fluid_synth(FluidSynth); + FluidSynth = NULL; + } + //========================================================================== // // FluidSynthMIDIDevice Destructor @@ -513,14 +526,21 @@ int FluidSynthMIDIDevice::LoadPatchSets(const char *patches) { path = NicePath(tok); } - if (FLUID_FAILED != fluid_synth_sfload(FluidSynth, path, count == 0)) + if (FileExists(path)) { - DPrintf(DMSG_NOTIFY, "Loaded patch set %s.\n", tok); - count++; + if (FLUID_FAILED != fluid_synth_sfload(FluidSynth, path, count == 0)) + { + DPrintf(DMSG_NOTIFY, "Loaded patch set %s.\n", tok); + count++; + } + else + { + DPrintf(DMSG_ERROR, "Failed to load patch set %s.\n", tok); + } } else { - DPrintf(DMSG_ERROR, "Failed to load patch set %s.\n", tok); + DPrintf(DMSG_ERROR, "Could not find patch set %s.\n", tok); } tok = strtok(NULL, delim); } diff --git a/src/sound/music_midi_base.cpp b/src/sound/music_midi_base.cpp index c437af696..10ee4a2c2 100644 --- a/src/sound/music_midi_base.cpp +++ b/src/sound/music_midi_base.cpp @@ -51,9 +51,9 @@ static uint32_t nummididevices; static bool nummididevicesset; #ifdef HAVE_FLUIDSYNTH -#define NUM_DEF_DEVICES 6 -#else #define NUM_DEF_DEVICES 5 +#else +#define NUM_DEF_DEVICES 4 #endif static void AddDefaultMidiDevices(FOptionValues *opt) @@ -75,8 +75,6 @@ static void AddDefaultMidiDevices(FOptionValues *opt) pair[p+2].Value = -2.0; pair[p+3].Text = "WildMidi"; pair[p+3].Value = -6.0; - pair[p+4].Text = "Sound System"; - pair[p+4].Value = -1.0; } @@ -117,10 +115,16 @@ void MIDIDeviceChanged(int newdev, bool force) if (!force) oldmididev = newdev; } +#ifdef HAVE_FLUIDSYNTH +#define DEF_MIDIDEV -5 +#else +#define DEF_MIDIDEV -3 +#endif + #ifdef _WIN32 unsigned mididevice; -CUSTOM_CVAR (Int, snd_mididevice, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CUSTOM_CVAR (Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) { if (!nummididevicesset) return; @@ -131,10 +135,11 @@ CUSTOM_CVAR (Int, snd_mididevice, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) if (self != 0) { Printf("ID out of range. Using default device.\n"); - self = 0; + self = DEF_MIDIDEV; } return; } + else if (self == -1) self = DEF_MIDIDEV; mididevice = MAX(0, self); MIDIDeviceChanged(self); } @@ -215,7 +220,6 @@ CCMD (snd_listmididevices) PrintMidiDevice (-4, "Gravis Ultrasound Emulation", MIDIDEV_SWSYNTH, 0); PrintMidiDevice (-3, "Emulated OPL FM Synth", MIDIDEV_FMSYNTH, 0); PrintMidiDevice (-2, "TiMidity++", MIDIDEV_SWSYNTH, 0); - PrintMidiDevice (-1, "Sound System", 0, 0); if (nummididevices != 0) { for (id = 0; id < nummididevices; ++id) @@ -237,12 +241,12 @@ CCMD (snd_listmididevices) // Everything but Windows uses this code. -CUSTOM_CVAR(Int, snd_mididevice, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) { if (self < -6) self = -6; - else if (self > -1) - self = -1; + else if (self > -2) + self = -2; else MIDIDeviceChanged(self); } @@ -261,6 +265,5 @@ CCMD (snd_listmididevices) Printf("%s-4. Gravis Ultrasound Emulation\n", -4 == snd_mididevice ? TEXTCOLOR_BOLD : ""); Printf("%s-3. Emulated OPL FM Synth\n", -3 == snd_mididevice ? TEXTCOLOR_BOLD : ""); Printf("%s-2. TiMidity++\n", -2 == snd_mididevice ? TEXTCOLOR_BOLD : ""); - Printf("%s-1. Sound System\n", -1 == snd_mididevice ? TEXTCOLOR_BOLD : ""); } #endif diff --git a/src/sound/musicformats/music_hmi_midiout.cpp b/src/sound/musicformats/music_hmi_midiout.cpp index f5322d2c1..791c8ec3d 100644 --- a/src/sound/musicformats/music_hmi_midiout.cpp +++ b/src/sound/musicformats/music_hmi_midiout.cpp @@ -651,7 +651,7 @@ uint32_t *HMISong::SendCommand (uint32_t *events, TrackInfo *track, uint32_t del if (event == MIDI_SYSEX || event == MIDI_SYSEXEND) { len = ReadVarLen(track); - if (len >= (MAX_EVENTS-1)*3*4 || DeviceType == MDEV_SNDSYS) + if (len >= (MAX_EVENTS-1)*3*4) { // This message will never fit. Throw it away. track->TrackP += len; } diff --git a/src/sound/musicformats/music_midistream.cpp b/src/sound/musicformats/music_midistream.cpp index e23c03a3c..2a8abdae9 100644 --- a/src/sound/musicformats/music_midistream.cpp +++ b/src/sound/musicformats/music_midistream.cpp @@ -181,11 +181,6 @@ EMidiDevice MIDIStreamer::SelectMIDIDevice(EMidiDevice device) - if explicitly selected by $mididevice - when snd_mididevice is -2 and no midi device is set for the song - - Sound System: - - if explicitly selected by $mididevice - - when snd_mididevice is -1 and no midi device is set for the song - - as fallback when both OPL and Timidity failed unless snd_mididevice is >= 0 - - MMAPI (Win32 only): - if explicitly selected by $mididevice (non-Win32 redirects this to Sound System) - when snd_mididevice is >= 0 and no midi device is set for the song @@ -233,16 +228,19 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) assert(0); // Intentional fall-through for non-Windows systems. + case MDEV_GUS: + return new TimidityMIDIDevice(Args); + #ifdef HAVE_FLUIDSYNTH case MDEV_FLUIDSYNTH: return new FluidSynthMIDIDevice(Args); #endif case MDEV_SNDSYS: - return GSnd->CreateMIDIDevice(); - - case MDEV_GUS: - return new TimidityMIDIDevice(Args); +#ifdef HAVE_FLUIDSYNTH + return new FluidSynthMIDIDevice(nullptr); +#endif + // if no FluidSynth, fall through to OPL. case MDEV_OPL: try @@ -252,8 +250,13 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) catch (CRecoverableError &err) { // The creation of an OPL MIDI device can abort with an error if no GENMIDI lump can be found. - Printf("Unable to create OPL MIDI device: %s\nFalling back to Sound System playback", err.GetMessage()); - return GSnd->CreateMIDIDevice(); + Printf("Unable to create OPL MIDI device: %s\nFalling back to default playback", err.GetMessage()); +#ifdef HAVE_FLUIDSYNTH + return new FluidSynthMIDIDevice(nullptr); +#else + // Someone dared to compile GZDoom without FluidSynth support and then started an IWAD without GENMIDI support. Ugh... + return nullptr; +#endif } case MDEV_TIMIDITY: diff --git a/src/sound/musicformats/music_smf_midiout.cpp b/src/sound/musicformats/music_smf_midiout.cpp index 32de991b3..7d2131fc9 100644 --- a/src/sound/musicformats/music_smf_midiout.cpp +++ b/src/sound/musicformats/music_smf_midiout.cpp @@ -592,7 +592,7 @@ uint32_t *MIDISong2::SendCommand (uint32_t *events, TrackInfo *track, uint32_t d if (event == MIDI_SYSEX || event == MIDI_SYSEXEND) { len = track->ReadVarLen(); - if (len >= (MAX_EVENTS-1)*3*4 || DeviceType == MDEV_SNDSYS) + if (len >= (MAX_EVENTS-1)*3*4) { // This message will never fit. Throw it away. track->TrackP += len; } diff --git a/src/sound/musicformats/music_xmi_midiout.cpp b/src/sound/musicformats/music_xmi_midiout.cpp index fd595cb09..a4e23423b 100644 --- a/src/sound/musicformats/music_xmi_midiout.cpp +++ b/src/sound/musicformats/music_xmi_midiout.cpp @@ -522,7 +522,7 @@ uint32_t *XMISong::SendCommand (uint32_t *events, EventSource due, uint32_t dela if (event == MIDI_SYSEX || event == MIDI_SYSEXEND) { len = track->ReadVarLen(); - if (len >= (MAX_EVENTS-1)*3*4 || DeviceType == MDEV_SNDSYS) + if (len >= (MAX_EVENTS-1)*3*4) { // This message will never fit. Throw it away. track->EventP += len; } diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 6a0c9ff1c..e9fde9263 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -2320,18 +2320,6 @@ void OpenALSoundRenderer::PrintDriversList() } } -MIDIDevice* OpenALSoundRenderer::CreateMIDIDevice() const -{ -#ifdef _WIN32 - extern unsigned mididevice; - return CreateWinMIDIDevice(mididevice); -#elif defined __APPLE__ - return CreateAudioToolboxMIDIDevice(); -#else - return new OPLMIDIDevice(nullptr); -#endif -} - void OpenALSoundRenderer::PurgeStoppedSources() { // Release channels that are stopped diff --git a/src/sound/oalsound.h b/src/sound/oalsound.h index 7a1ed2a23..92d2235aa 100644 --- a/src/sound/oalsound.h +++ b/src/sound/oalsound.h @@ -175,8 +175,6 @@ public: virtual void PrintDriversList(); virtual FString GatherStats(); - virtual MIDIDevice* CreateMIDIDevice() const override; - private: struct { bool EXT_EFX; diff --git a/src/v_video.cpp b/src/v_video.cpp index 651d3d7de..a3c7d3878 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1747,6 +1747,32 @@ bool AspectTallerThanWide(float aspect) return aspect < 1.333f; } +void ScaleWithAspect (int &w, int &h, int Width, int Height) +{ + int resRatio = CheckRatio (Width, Height); + int screenRatio; + CheckRatio (w, h, &screenRatio); + if (resRatio == screenRatio) + return; + + double yratio; + switch(resRatio) + { + case 0: yratio = 4./3.; break; + case 1: yratio = 16./9.; break; + case 2: yratio = 16./10.; break; + case 3: yratio = 17./10.; break; + case 4: yratio = 5./4.; break; + case 6: yratio = 21./9.; break; + default: return; + } + double y = w/yratio; + if (y > h) + w = h*yratio; + else + h = y; +} + void IVideo::DumpAdapters () { Printf("Multi-monitor support unavailable.\n"); diff --git a/src/v_video.h b/src/v_video.h index c4f9bdb95..fc4d3924d 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -565,6 +565,8 @@ int AspectBaseHeight(float aspect); double AspectPspriteOffset(float aspect); int AspectMultiplier(float aspect); bool AspectTallerThanWide(float aspect); +void ScaleWithAspect(int &w, int &h, int Width, int Height); + int GetUIScale(int altval); EXTERN_CVAR(Int, uiscale); diff --git a/src/version.h b/src/version.h index ab4a53c0a..19347fafe 100644 --- a/src/version.h +++ b/src/version.h @@ -96,6 +96,7 @@ const char *GetVersionString(); // This is so that derivates can use the same savegame versions without worrying about engine compatibility #define GAMESIG "QZDOOM" #define BASEWAD "qzdoom.pk3" +#define BASESF "gzdoom.sf2" // More stuff that needs to be different for derivatives. #define GAMENAME "QZDoom" diff --git a/tools/updaterevision/updaterevision.c b/tools/updaterevision/updaterevision.c index 7260f4131..bbb6dddf3 100644 --- a/tools/updaterevision/updaterevision.c +++ b/tools/updaterevision/updaterevision.c @@ -51,7 +51,7 @@ int main(int argc, char **argv) // on a tag, it returns that tag. Otherwise it returns --. // Use git log to get the time of the latest commit in ISO 8601 format and its full hash. - stream = popen("git describe --tags && git log -1 --format=%ai*%H", "r"); + stream = popen("git describe --tags --dirty=-m && git log -1 --format=%ai*%H", "r"); if (NULL != stream) {