From 6326a0b2d9dafd0efb2c456fb56a7af06c6a2c50 Mon Sep 17 00:00:00 2001 From: elasota Date: Wed, 1 Apr 2020 14:53:44 -0400 Subject: [PATCH] Partial resolution change support --- GpApp/DynamicMaps.cpp | 11 +- GpApp/Dynamics3.cpp | 67 +++++++-- GpApp/Environ.cpp | 49 +++++- GpApp/Environ.h | 3 +- GpApp/Externs.h | 1 + GpApp/GliderProtos.h | 10 +- GpApp/Grease.cpp | 3 +- GpApp/InterfaceInit.cpp | 60 ++++---- GpApp/Main.cpp | 1 + GpApp/ObjectDrawAll.cpp | 4 +- GpApp/Play.cpp | 36 ++++- GpApp/Render.cpp | 2 - GpApp/RoomGraphics.cpp | 73 ++++----- GpApp/Scoreboard.cpp | 2 + GpApp/StructuresInit2.cpp | 42 ++++-- GpCommon/GpVOSEvent.h | 10 ++ .../GpDisplayDriverD3D11.cpp | 139 ++++++++++++++++-- GpDisplayDriver_D3D11/GpDisplayDriverD3D11.h | 2 + PortabilityLayer/DisplayDeviceManager.cpp | 15 ++ PortabilityLayer/DisplayDeviceManager.h | 18 ++- PortabilityLayer/PLSysCalls.cpp | 10 ++ PortabilityLayer/WindowManager.cpp | 55 ++++++- PortabilityLayer/WindowManager.h | 4 + PortabilityLayer/ZipFileProxy.h | 2 +- 24 files changed, 495 insertions(+), 124 deletions(-) diff --git a/GpApp/DynamicMaps.cpp b/GpApp/DynamicMaps.cpp index 4814c4d..e41c831 100644 --- a/GpApp/DynamicMaps.cpp +++ b/GpApp/DynamicMaps.cpp @@ -112,6 +112,8 @@ short ReBackUpSavedMap (Rect *theRect, short where, short who) foundIndex = i; mapRect = *theRect; ZeroRectCorner(&mapRect); + + savedMaps[foundIndex].dest = *theRect; CopyBits((BitMap *)*GetGWorldPixMap(backSrcMap), GetPortBitMapForCopyBits(savedMaps[foundIndex].map), @@ -544,7 +546,7 @@ void BackUpPendulum (Rect *src, short index) // Backs up the pendulums in the event of lights going on or off. -void ReBackUpPendulum (short where, short who) +void ReBackUpPendulum (short where, short who, short h, short v) { short i, f; @@ -556,7 +558,12 @@ void ReBackUpPendulum (short where, short who) { if (pendulums[f].who == i) { - BackUpPendulum(&pendulums[f].dest, i); + Rect &pendulumDest = pendulums[f].dest; + pendulumDest.right += h - pendulumDest.left; + pendulumDest.bottom += v - pendulumDest.top; + pendulumDest.left = h; + pendulumDest.top = v; + BackUpPendulum(&pendulumDest, i); return; } } diff --git a/GpApp/Dynamics3.cpp b/GpApp/Dynamics3.cpp index 5011153..50d214f 100644 --- a/GpApp/Dynamics3.cpp +++ b/GpApp/Dynamics3.cpp @@ -153,6 +153,48 @@ void RenderDynamics (void) } } +//-------------------------------------------------------------- ZeroDinah + +void ZeroDinah(dynaType &dinah) +{ + dinah.type = kObjectIsEmpty; + QSetRect(&dinah.dest, 0, 0, 0, 0); + QSetRect(&dinah.whole, 0, 0, 0, 0); + dinah.hVel = 0; + dinah.vVel = 0; + dinah.count = 0; + dinah.frame = 0; + dinah.timer = 0; + dinah.position = 0; + dinah.room = 0; + dinah.byte0 = 0; + dinah.active = false; +} + +//-------------------------------------------------------------- ZeroDinahsNotInRoom +void ZeroDinahsNotInRoom (SInt16 room) +{ + short i; + short newNumDynamics = 0; + + for (i = 0; i < numDynamics; i++) + { + dynaType &dinah = dinahs[i]; + if (dinah.room == room) + { + if (newNumDynamics != numDynamics) + memcpy(&dinahs[newNumDynamics], &dinahs[i], sizeof(dynaType)); + + newNumDynamics++; + } + } + + for (i = newNumDynamics; i < kMaxDynamicObs; i++) + ZeroDinah(dinahs[i]); + + numDynamics = newNumDynamics; +} + //-------------------------------------------------------------- ZeroDinahs // This clears all dynamics - zeros them all out. Used to initialize them. @@ -162,20 +204,8 @@ void ZeroDinahs (void) short i; for (i = 0; i < kMaxDynamicObs; i++) - { - dinahs[i].type = kObjectIsEmpty; - QSetRect(&dinahs[i].dest, 0, 0, 0, 0); - QSetRect(&dinahs[i].whole, 0, 0, 0, 0); - dinahs[i].hVel = 0; - dinahs[i].vVel = 0; - dinahs[i].count = 0; - dinahs[i].frame = 0; - dinahs[i].timer = 0; - dinahs[i].position = 0; - dinahs[i].room = 0; - dinahs[i].byte0 = 0; - dinahs[i].active = false; - } + ZeroDinah(dinahs[i]); + numDynamics = 0; } @@ -553,3 +583,12 @@ short AddDynamicObject (short what, Rect *where, objectType *who, return (numDynamics - 1); } +void OffsetDynamics(SInt16 h, SInt16 v) +{ + for (int i = 0; i < numDynamics; i++) + { + dynaType &dinah = dinahs[i]; + //QOffsetRect(&dinah.dest, h, v); + //QOffsetRect(&dinah.whole, h, v); + } +} diff --git a/GpApp/Environ.cpp b/GpApp/Environ.cpp index effabdd..2d19672 100644 --- a/GpApp/Environ.cpp +++ b/GpApp/Environ.cpp @@ -8,12 +8,14 @@ #include "PLResources.h" #include "PLPasStr.h" +#include "DisplayDeviceManager.h" #include "Externs.h" #include "Environ.h" #include "HostDisplayDriver.h" #include "HostSystemServices.h" +#include "MenuManager.h" #include "IGpDisplayDriver.h" - +#include "WindowManager.h" #define kSwitchDepthAlert 130 #define kSetMemoryAlert 180 @@ -272,6 +274,18 @@ short HowManyUsableScreens (Boolean use1Bit, Boolean use4Bit, Boolean use8Bit) return 1; } +//-------------------------------------------------------------- FlushResolutionChange +void FlushResolutionChange(void) +{ + if (thisMac.isResolutionDirty) + { + GetDeviceRect(&thisMac.screen); + thisMac.gray = thisMac.screen; + thisMac.gray.top = 20; + thisMac.isResolutionDirty = false; + } +} + //-------------------------------------------------------------- CheckOurEnvirons // Calls all the above functions in order to fill out a sort of "spec sheet"É // for the current Mac. @@ -293,10 +307,41 @@ void CheckOurEnvirons (void) thisMac.can4Bit = true; thisMac.can8Bit = true; thisMac.numScreens = HowManyUsableScreens(false, true, true); - GetDeviceRect(&thisMac.screen); thisMac.wasDepth = WhatsOurDepth(); thisMac.wasColorOrGray = AreWeColorOrGrayscale(); + + thisMac.isResolutionDirty = true; + FlushResolutionChange(); +} + +//-------------------------------------------------------------- HandleResolutionChange +// Installs handler +void HandleResolutionChange(uint32_t prevWidth, uint32_t prevHeight, uint32_t newWidth, uint32_t newHeight) +{ + PortabilityLayer::WindowManager::GetInstance()->HandleScreenResolutionChange(prevWidth, prevHeight, newWidth, newHeight); + PortabilityLayer::MenuManager::GetInstance()->DrawMenuBar(); + thisMac.isResolutionDirty = true; // Because of legacy code, we don't want to update thisMac.screen immediately, but rather, let the editor or game pick it up +} + +class GpAppResolutionChangeHandler final : public PortabilityLayer::DisplayDeviceManager::IResolutionChangeHandler +{ +public: + void OnResolutionChanged(uint32_t prevWidth, uint32_t prevHeight, uint32_t newWidth, uint32_t newHeight) override + { + HandleResolutionChange(prevWidth, prevHeight, newWidth, newHeight); + } + + static GpAppResolutionChangeHandler ms_instance; +}; + +GpAppResolutionChangeHandler GpAppResolutionChangeHandler::ms_instance; + +//-------------------------------------------------------------- InstallResolutionHandler +// Installs handler +void InstallResolutionHandler(void) +{ + PortabilityLayer::DisplayDeviceManager::GetInstance()->SetResolutionChangeHandler(&GpAppResolutionChangeHandler::ms_instance); } //-------------------------------------------------------------- ReflectMonitor2Environs diff --git a/GpApp/Environ.h b/GpApp/Environ.h index 8e6dad3..104eac8 100644 --- a/GpApp/Environ.h +++ b/GpApp/Environ.h @@ -28,9 +28,10 @@ typedef struct Boolean hasSM3; Boolean hasQT; Boolean hasDrag; + Boolean isResolutionDirty; } macEnviron; extern macEnviron thisMac; - +void FlushResolutionChange(void); diff --git a/GpApp/Externs.h b/GpApp/Externs.h index ee23a5d..c1db6c5 100644 --- a/GpApp/Externs.h +++ b/GpApp/Externs.h @@ -167,6 +167,7 @@ void IgnoreThisClick (void); short WhatsOurDepth (void); // --- Environs.c void SwitchToDepth (short, Boolean); void CheckOurEnvirons (void); +void InstallResolutionHandler (void); //void ReflectSecondMonitorEnvirons (Boolean, Boolean, Boolean); void HandleDepthSwitching (void); void RestoreColorDepth (void); diff --git a/GpApp/GliderProtos.h b/GpApp/GliderProtos.h index d2a515c..01054f0 100644 --- a/GpApp/GliderProtos.h +++ b/GpApp/GliderProtos.h @@ -34,7 +34,7 @@ void ReBackUpTikiFlames (SInt16, SInt16); void AddTikiFlame (SInt16, SInt16, SInt16, SInt16); void ReBackUpBBQCoals (SInt16, SInt16); void AddBBQCoals (SInt16, SInt16, SInt16, SInt16); -void ReBackUpPendulum (SInt16, SInt16); +void ReBackUpPendulum (SInt16, SInt16, SInt16, SInt16); void AddPendulum (SInt16, SInt16, SInt16, SInt16); void ReBackUpStar (SInt16, SInt16); void AddStar (SInt16, SInt16, SInt16, SInt16); @@ -73,7 +73,10 @@ void HandleFish (SInt16); void HandleDynamics (void); // --- Dynamics3.c void RenderDynamics (void); void ZeroDinahs (void); +void ZeroDinahsNotInRoom (SInt16); + SInt16 AddDynamicObject (SInt16, Rect *, objectType *, SInt16, SInt16, Boolean); +void OffsetDynamics(SInt16 h, SInt16 v); void DoGameOver (void); // --- GameOver.c void FlagGameOver (void); @@ -132,6 +135,7 @@ void FlagStillOvers (gliderPtr); void InitializeMenus (void); // --- InterfaceInit.c void GetExtraCursors (void); +void RecomputeInterfaceRects (void); void VariableInit (void); void GetDemoInput (gliderPtr); // --- Input.c @@ -407,7 +411,8 @@ Boolean DoesRoomHaveFloor (void); Boolean DoesRoomHaveCeiling (void); void ReadyLevel (void); // --- RoomGraphics.c -void DrawLocale (void); +void ResetLocale (Boolean soft); +void DrawLocale (Boolean soft); void RedrawRoomLighting (void); Boolean PictIDExists (SInt16); // --- RoomInfo.c @@ -470,6 +475,7 @@ void InitEnemies (void); void CreateOffscreens (void); // --- StructuresInit2.c void CreatePointers (void); void InitSrcRects (void); +PLError_t RecreateOffscreens (void); void UpdateToolsWindow (void); // --- Tools.c void EraseSelectedTool (void); diff --git a/GpApp/Grease.cpp b/GpApp/Grease.cpp index 7eb73ee..c77d668 100644 --- a/GpApp/Grease.cpp +++ b/GpApp/Grease.cpp @@ -28,8 +28,7 @@ short numGrease; extern hotPtr hotSpots; extern savedType savedMaps[]; -extern Point shieldPt; -extern Rect greaseSrcRt[], greaseSrcLf[], shieldRect; +extern Rect greaseSrcRt[], greaseSrcLf[]; //============================================================== Functions diff --git a/GpApp/InterfaceInit.cpp b/GpApp/InterfaceInit.cpp index e64aac8..7c2e7f6 100644 --- a/GpApp/InterfaceInit.cpp +++ b/GpApp/InterfaceInit.cpp @@ -27,11 +27,10 @@ struct IGpCursor; extern THandle mirrorRects; extern WindowPtr mapWindow, toolsWindow, linkWindow; extern WindowPtr menuWindow; -extern Rect shieldRect, boardSrcRect, localRoomsDest[]; +extern Rect boardSrcRect, localRoomsDest[]; extern IGpCursor *handCursor, *vertCursor, *horiCursor; extern IGpCursor *diagCursor; extern MenuHandle appleMenu, gameMenu, optionsMenu, houseMenu; -extern Point shieldPt; extern long incrementModeTime; extern UInt32 doubleTime; extern short fadeInSequence[], idleMode; @@ -99,6 +98,34 @@ void GetExtraCursors (void) RedAlert(kErrFailedResourceLoad); } +//-------------------------------------------------------------- RecomputeScreenRects +void RecomputeInterfaceRects (void) +{ + houseRect = thisMac.screen; + houseRect.bottom -= kScoreboardTall; + if (houseRect.right > kMaxViewWidth) + houseRect.right = kMaxViewWidth; + if (houseRect.bottom > kMaxViewHeight) + houseRect.bottom = kMaxViewHeight; + + playOriginH = (RectWide(&thisMac.screen) - kRoomWide) / 2; + playOriginV = (RectTall(&thisMac.screen) - kTileHigh) / 2; + + for (int i = 0; i < 9; i++) + { + QSetRect(&localRoomsDest[i], 0, 0, kRoomWide, kTileHigh); + QOffsetRect(&localRoomsDest[i], playOriginH, playOriginV); + } + QOffsetRect(&localRoomsDest[kNorthRoom], 0, -kVertLocalOffset); + QOffsetRect(&localRoomsDest[kNorthEastRoom], kRoomWide, -kVertLocalOffset); + QOffsetRect(&localRoomsDest[kEastRoom], kRoomWide, 0); + QOffsetRect(&localRoomsDest[kSouthEastRoom], kRoomWide, kVertLocalOffset); + QOffsetRect(&localRoomsDest[kSouthRoom], 0, kVertLocalOffset); + QOffsetRect(&localRoomsDest[kSouthWestRoom], -kRoomWide, kVertLocalOffset); + QOffsetRect(&localRoomsDest[kWestRoom], -kRoomWide, 0); + QOffsetRect(&localRoomsDest[kNorthWestRoom], -kRoomWide, -kVertLocalOffset); +} + //-------------------------------------------------------------- VariableInit // All the simple interface variables are intialized here - Booleans,É @@ -108,10 +135,6 @@ void VariableInit (void) { short i; - shieldPt.h = 0; - shieldPt.v = 0; - shieldRect = thisMac.screen; - menusUp = false; quitting = false; houseOpen = false; @@ -186,28 +209,5 @@ void VariableInit (void) nailSrcMap = nil; menuWindow = nil; - houseRect = thisMac.screen; - houseRect.bottom -= kScoreboardTall; - if (houseRect.right > kMaxViewWidth) - houseRect.right = kMaxViewWidth; - if (houseRect.bottom > kMaxViewHeight) - houseRect.bottom = kMaxViewHeight; - - playOriginH = (RectWide(&thisMac.screen) - kRoomWide) / 2; - playOriginV = (RectTall(&thisMac.screen) - kTileHigh) / 2; - - for (i = 0; i < 9; i++) - { - QSetRect(&localRoomsDest[i], 0, 0, kRoomWide, kTileHigh); - QOffsetRect(&localRoomsDest[i], playOriginH, playOriginV); - } - QOffsetRect(&localRoomsDest[kNorthRoom], 0, -kVertLocalOffset); - QOffsetRect(&localRoomsDest[kNorthEastRoom], kRoomWide, -kVertLocalOffset); - QOffsetRect(&localRoomsDest[kEastRoom], kRoomWide, 0); - QOffsetRect(&localRoomsDest[kSouthEastRoom], kRoomWide, kVertLocalOffset); - QOffsetRect(&localRoomsDest[kSouthRoom], 0, kVertLocalOffset); - QOffsetRect(&localRoomsDest[kSouthWestRoom], -kRoomWide, kVertLocalOffset); - QOffsetRect(&localRoomsDest[kWestRoom], -kRoomWide, 0); - QOffsetRect(&localRoomsDest[kNorthWestRoom], -kRoomWide, -kVertLocalOffset); + RecomputeInterfaceRects(); } - diff --git a/GpApp/Main.cpp b/GpApp/Main.cpp index ac64e1e..6df200d 100644 --- a/GpApp/Main.cpp +++ b/GpApp/Main.cpp @@ -315,6 +315,7 @@ int gpAppMain() ToolBoxInit(); CheckOurEnvirons(); + InstallResolutionHandler(); if (!thisMac.hasColor) RedAlert(kErrNeedColorQD); if (!thisMac.hasSystem7) diff --git a/GpApp/ObjectDrawAll.cpp b/GpApp/ObjectDrawAll.cpp index ffe3bfb..7fe3943 100644 --- a/GpApp/ObjectDrawAll.cpp +++ b/GpApp/ObjectDrawAll.cpp @@ -333,8 +333,10 @@ void DrawARoomsObjects (short neighbor, Boolean redraw) if (legit != -1) { DrawCuckoo(&itsRect); + short pendulumH = itsRect.left + 4; + short pendulumV = itsRect.top + 46; if (redraw) - ReBackUpPendulum(localNumbers[neighbor], i); + ReBackUpPendulum(localNumbers[neighbor], i, pendulumH, pendulumV); else AddPendulum(localNumbers[neighbor], i, itsRect.left + 4, itsRect.top + 46); diff --git a/GpApp/Play.cpp b/GpApp/Play.cpp index fa06980..f483877 100644 --- a/GpApp/Play.cpp +++ b/GpApp/Play.cpp @@ -8,6 +8,7 @@ #include "PLResources.h" #include "PLStandardColors.h" +#include "DisplayDeviceManager.h" #include "Externs.h" #include "Environ.h" #include "House.h" @@ -66,6 +67,7 @@ extern short numStarsRemaining, numChimes, saidFollow; extern Boolean quitting, isMusicOn, gameOver, hasMirror, onePlayerLeft; extern Boolean isPlayMusicIdle, failedMusic, quickerTransitions; extern Boolean switchedOut; +extern short wasScoreboardTitleMode; //============================================================== Functions @@ -156,7 +158,7 @@ void NewGame (short mode) // DebugStr("\pIf screen isn't black, exit to shell."); // TEMP TEMP TEMP - DrawLocale(); + ResetLocale(false); RefreshScoreboard(kNormalTitleMode); // if (quickerTransitions) // DissBitsChunky(&justRoomsRect); @@ -362,12 +364,42 @@ void SetHouseToSavedRoom (void) ForceThisRoom(smallGame.roomNumber); } +//-------------------------------------------------------------- HandleGameResolutionChange + +void HandleGameResolutionChange(void) +{ + short prevPlayOriginH = playOriginH; + short prevPlayOriginV = playOriginV; + + Rect prevResolution = thisMac.screen; + FlushResolutionChange(); + + RecomputeInterfaceRects(); + RecreateOffscreens(); + CloseMainWindow(); + OpenMainWindow(); + + if (hasMovie) + theMovie.m_surface = &mainWindow->m_surface; + + OffsetDynamics(playOriginH - prevPlayOriginH, playOriginV - prevPlayOriginV); + + ResetLocale(true); + RefreshScoreboard(wasScoreboardTitleMode); + DumpScreenOn(&justRoomsRect); +} + //-------------------------------------------------------------- PlayGame void PlayGame (void) { while ((playing) && (!quitting)) { + if (thisMac.isResolutionDirty) + { + HandleGameResolutionChange(); + } + gameFrame++; evenFrame = !evenFrame; @@ -730,7 +762,7 @@ void RestoreEntireGameScreen (void) surface->SetForeColor(StdColors::Black()); surface->FillRect(tempRect); - DrawLocale(); + ResetLocale(false); RefreshScoreboard(kNormalTitleMode); // if (quickerTransitions) // DissBitsChunky(&justRoomsRect); diff --git a/GpApp/Render.cpp b/GpApp/Render.cpp index d1c9f62..d2a0ad4 100644 --- a/GpApp/Render.cpp +++ b/GpApp/Render.cpp @@ -34,9 +34,7 @@ void CopyRectsQD (void); Rect work2MainRects[kMaxGarbageRects]; Rect back2WorkRects[kMaxGarbageRects]; -Rect shieldRect; THandle mirrorRects; -Point shieldPt; long nextFrame; short numWork2Main, numBack2Work; Boolean hasMirror; diff --git a/GpApp/RoomGraphics.cpp b/GpApp/RoomGraphics.cpp index 51b7522..27ab544 100644 --- a/GpApp/RoomGraphics.cpp +++ b/GpApp/RoomGraphics.cpp @@ -42,33 +42,39 @@ extern Boolean shadowVisible, takingTheStairs; //============================================================== Functions //-------------------------------------------------------------- DrawLocale -void DrawLocale (void) +void ResetLocale (Boolean soft) { - short i, roomV; + short i; char wasState; - DrawSurface *wasCPort; - - ZeroFlamesAndTheLike(); - ZeroDinahs(); - KillAllBands(); - ZeroMirrorRegion(); - ZeroTriggers(); - numTempManholes = 0; - FlushAnyTriggerPlaying(); - DumpTriggerSound(); - tvInRoom = false; - tvWithMovieNumber = -1; - - roomV = (*thisHouse)->rooms[thisRoomNumber].floor; - - for (i = 0; i < 9; i++) + + if (soft) { - localNumbers[i] = GetNeighborRoomNumber(i); - isStructure[i] = IsRoomAStructure(localNumbers[i]); } - ListAllLocalObjects(); - - wasCPort = GetGraphicsPort(); + else + { + ZeroFlamesAndTheLike(); + ZeroDinahs(); + KillAllBands(); + ZeroMirrorRegion(); + ZeroTriggers(); + numTempManholes = 0; + FlushAnyTriggerPlaying(); + DumpTriggerSound(); + tvInRoom = false; + tvWithMovieNumber = -1; + + for (i = 0; i < 9; i++) + { + localNumbers[i] = GetNeighborRoomNumber(i); + isStructure[i] = IsRoomAStructure(localNumbers[i]); + } + ListAllLocalObjects(); + } + + takingTheStairs = false; + + DrawSurface *wasCPort = GetGraphicsPort(); + const short roomV = (*thisHouse)->rooms[thisRoomNumber].floor; backSrcMap->SetForeColor(StdColors::Black()); backSrcMap->FillRect(backSrcRect); @@ -77,52 +83,51 @@ void DrawLocale (void) { numLights = GetNumberOfLights(localNumbers[kNorthWestRoom]); DrawRoomBackground(localNumbers[kNorthWestRoom], kNorthWestRoom, roomV + 1); - DrawARoomsObjects(kNorthWestRoom, false); + DrawARoomsObjects(kNorthWestRoom, soft); numLights = GetNumberOfLights(localNumbers[kNorthEastRoom]); DrawRoomBackground(localNumbers[kNorthEastRoom], kNorthEastRoom, roomV + 1); - DrawARoomsObjects(kNorthEastRoom, false); + DrawARoomsObjects(kNorthEastRoom, soft); numLights = GetNumberOfLights(localNumbers[kNorthRoom]); DrawRoomBackground(localNumbers[kNorthRoom], kNorthRoom, roomV + 1); - DrawARoomsObjects(kNorthRoom, false); + DrawARoomsObjects(kNorthRoom, soft); numLights = GetNumberOfLights(localNumbers[kSouthWestRoom]); DrawRoomBackground(localNumbers[kSouthWestRoom], kSouthWestRoom, roomV - 1); - DrawARoomsObjects(kSouthWestRoom, false); + DrawARoomsObjects(kSouthWestRoom, soft); numLights = GetNumberOfLights(localNumbers[kSouthEastRoom]); DrawRoomBackground(localNumbers[kSouthEastRoom], kSouthEastRoom, roomV - 1); - DrawARoomsObjects(kSouthEastRoom, false); + DrawARoomsObjects(kSouthEastRoom, soft); numLights = GetNumberOfLights(localNumbers[kSouthRoom]); DrawRoomBackground(localNumbers[kSouthRoom], kSouthRoom, roomV - 1); - DrawARoomsObjects(kSouthRoom, false); + DrawARoomsObjects(kSouthRoom, soft); } if (numNeighbors > 1) { numLights = GetNumberOfLights(localNumbers[kWestRoom]); DrawRoomBackground(localNumbers[kWestRoom], kWestRoom, roomV); - DrawARoomsObjects(kWestRoom, false); + DrawARoomsObjects(kWestRoom, soft); DrawLighting(); numLights = GetNumberOfLights(localNumbers[kEastRoom]); DrawRoomBackground(localNumbers[kEastRoom], kEastRoom, roomV); - DrawARoomsObjects(kEastRoom, false); + DrawARoomsObjects(kEastRoom, soft); DrawLighting(); } numLights = GetNumberOfLights(localNumbers[kCentralRoom]); DrawRoomBackground(localNumbers[kCentralRoom], kCentralRoom, roomV); - DrawARoomsObjects(kCentralRoom, false); + DrawARoomsObjects(kCentralRoom, soft); DrawLighting(); if (numNeighbors > 3) DrawFloorSupport(); RestoreWorkMap(); shadowVisible = IsShadowVisible(); - takingTheStairs = false; SetGraphicsPort(wasCPort); } @@ -385,7 +390,7 @@ void ReadyLevel (void) #endif DetermineRoomOpenings(); - DrawLocale(); + ResetLocale(false); InitGarbageRects(); } diff --git a/GpApp/Scoreboard.cpp b/GpApp/Scoreboard.cpp index 41c7076..b9136a8 100644 --- a/GpApp/Scoreboard.cpp +++ b/GpApp/Scoreboard.cpp @@ -43,6 +43,7 @@ Rect badgesDestRects[4]; DrawSurface *boardPSrcMap; long displayedScore; short wasScoreboardMode; +short wasScoreboardTitleMode; Boolean doRollScore; extern Rect localRoomsDest[], justRoomsRect; @@ -63,6 +64,7 @@ void MarkScoreboardPortDirty(void) void RefreshScoreboard (SInt16 mode) { + wasScoreboardTitleMode = mode; doRollScore = true; RefreshRoomTitle(mode); diff --git a/GpApp/StructuresInit2.cpp b/GpApp/StructuresInit2.cpp index 90a5ddd..15de057 100644 --- a/GpApp/StructuresInit2.cpp +++ b/GpApp/StructuresInit2.cpp @@ -11,6 +11,7 @@ #include "GameOver.h" #include "MainWindow.h" #include "Objects.h" +#include "QDManager.h" #include "RectUtils.h" #include "ResourceManager.h" #include "Room.h" @@ -112,6 +113,34 @@ void InitAngel (void) LoadGraphic(angelMaskMap, kAngelPictID + 1); } +//-------------------------------------------------------------- RecreateOffscreens +// Recreates resolution-dependent offscreen work +PLError_t RecreateOffscreens(void) +{ + PLError_t theErr; + + PortabilityLayer::QDManager::GetInstance()->SetPort(nullptr); + + if (workSrcMap) + DisposeGWorld(workSrcMap); + + if (backSrcMap) + DisposeGWorld(backSrcMap); + + justRoomsRect = houseRect; + ZeroRectCorner(&justRoomsRect); + + workSrcRect = houseRect; // Set up work map + ZeroRectCorner(&workSrcRect); + theErr = CreateOffScreenGWorld(&workSrcMap, &workSrcRect, kPreferredPixelFormat); + + backSrcRect = houseRect; // Set up background map + ZeroRectCorner(&backSrcRect); + theErr = CreateOffScreenGWorld(&backSrcMap, &backSrcRect, kPreferredPixelFormat); + + return PLErrors::kNone; +} + //-------------------------------------------------------------- CreateOffscreens // All "utility" or "work" offscreen pix/bit maps are created here. // These would be offscreens that are reused throughout a game - theyÉ @@ -121,17 +150,8 @@ void InitAngel (void) void CreateOffscreens (void) { PLError_t theErr; - - justRoomsRect = houseRect; - ZeroRectCorner(&justRoomsRect); - - workSrcRect = houseRect; // Set up work map - ZeroRectCorner(&workSrcRect); - theErr = CreateOffScreenGWorld(&workSrcMap, &workSrcRect, kPreferredPixelFormat); - - backSrcRect = houseRect; // Set up background map - ZeroRectCorner(&backSrcRect); - theErr = CreateOffScreenGWorld(&backSrcMap, &backSrcRect, kPreferredPixelFormat); + + theErr = RecreateOffscreens(); InitScoreboardMap(); SpinCursor(1); InitGliderMap(); SpinCursor(1); diff --git a/GpCommon/GpVOSEvent.h b/GpCommon/GpVOSEvent.h index 9a8ef6f..eab1637 100644 --- a/GpCommon/GpVOSEvent.h +++ b/GpCommon/GpVOSEvent.h @@ -235,6 +235,14 @@ struct GpMouseInputEvent GpMouseButton_t m_button; }; +struct GpVideoResolutionChangedEvent +{ + uint32_t m_prevWidth; + uint32_t m_prevHeight; + uint32_t m_newWidth; + uint32_t m_newHeight; +}; + namespace GpVOSEventTypes { enum GpVOSEventType @@ -242,6 +250,7 @@ namespace GpVOSEventTypes kKeyboardInput, kMouseInput, kGamepadInput, + kVideoResolutionChanged, }; } @@ -254,6 +263,7 @@ struct GpVOSEvent GpKeyboardInputEvent m_keyboardInputEvent; GpMouseInputEvent m_mouseInputEvent; GpGamepadInputEvent m_gamepadInputEvent; + GpVideoResolutionChangedEvent m_resolutionChangedEvent; }; EventUnion m_event; diff --git a/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp b/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp index 134abbc..339ae55 100644 --- a/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp +++ b/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp @@ -2,9 +2,11 @@ #include "GpApplicationName.h" #include "GpDisplayDriverD3D11.h" #include "GpDisplayDriverSurfaceD3D11.h" +#include "GpVOSEvent.h" #include "GpWindows.h" #include "IGpCursor_Win32.h" #include "IGpFiber.h" +#include "IGpVOSEventQueue.h" #include #include @@ -64,8 +66,10 @@ LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) return DefWindowProc(hWnd, message, wParam, lParam); } -void StartD3DForWindow(HWND hWnd, GpComPtr& outSwapChain, GpComPtr& outDevice, GpComPtr& outContext) +bool InitSwapChainForWindow(HWND hWnd, ID3D11Device *device, GpComPtr& outSwapChain) { + outSwapChain = nullptr; + DXGI_SWAP_CHAIN_DESC1 swapChainDesc; ZeroMemory(&swapChainDesc, sizeof(swapChainDesc)); @@ -76,6 +80,46 @@ void StartD3DForWindow(HWND hWnd, GpComPtr& outSwapChain, GpCom swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + HRESULT result; + + IDXGIDevice2 *dxgiDevice = nullptr; + result = device->QueryInterface(__uuidof(IDXGIDevice2), reinterpret_cast(&dxgiDevice)); + if (result != S_OK) + return false; + + IDXGIAdapter *dxgiAdapter = nullptr; + result = dxgiDevice->GetAdapter(&dxgiAdapter); + if (result != S_OK) + return false; + + IDXGIFactory2 *dxgiFactory = nullptr; + result = dxgiAdapter->GetParent(__uuidof(IDXGIFactory2), reinterpret_cast(&dxgiFactory)); + if (result != S_OK) + return false; + + IDXGISwapChain1 *swapChain = nullptr; + result = dxgiFactory->CreateSwapChainForHwnd(device, hWnd, &swapChainDesc, nullptr, nullptr, &swapChain); + if (result != S_OK) + return false; + + outSwapChain = swapChain; + + return true; +} + +bool ResizeSwapChain(IDXGISwapChain1 *swapChain, UINT width, UINT height) +{ + HRESULT result; + + result = swapChain->ResizeBuffers(0, width, height, DXGI_FORMAT_R8G8B8A8_UNORM, 0); + if (result != S_OK) + return false; + + return true; +} + +void StartD3DForWindow(HWND hWnd, GpComPtr& outSwapChain, GpComPtr& outDevice, GpComPtr& outContext) +{ DXGI_SWAP_CHAIN_FULLSCREEN_DESC swapChainFullscreenDesc; ZeroMemory(&swapChainFullscreenDesc, sizeof(swapChainFullscreenDesc)); @@ -90,7 +134,9 @@ void StartD3DForWindow(HWND hWnd, GpComPtr& outSwapChain, GpCom D3D_FEATURE_LEVEL_10_0 }; +#ifndef NDEBUG flags |= D3D11_CREATE_DEVICE_DEBUG; +#endif ID3D11Device *device = NULL; ID3D11DeviceContext *context = NULL; @@ -100,27 +146,54 @@ void StartD3DForWindow(HWND hWnd, GpComPtr& outSwapChain, GpCom HRESULT result = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, featureLevels, sizeof(featureLevels) / sizeof(featureLevels[0]), D3D11_SDK_VERSION, &device, &selectedFeatureLevel, &context); - IDXGIDevice2 *dxgiDevice = nullptr; - result = device->QueryInterface(__uuidof(IDXGIDevice2), reinterpret_cast(&dxgiDevice)); - - IDXGIAdapter *dxgiAdapter = nullptr; - result = dxgiDevice->GetAdapter(&dxgiAdapter); - - IDXGIFactory2 *dxgiFactory = nullptr; - result = dxgiAdapter->GetParent(__uuidof(IDXGIFactory2), reinterpret_cast(&dxgiFactory)); - - IDXGISwapChain1 *swapChain = nullptr; - result = dxgiFactory->CreateSwapChainForHwnd(device, hWnd, &swapChainDesc, nullptr, nullptr, &swapChain); + InitSwapChainForWindow(hWnd, device, outSwapChain); // GP TODO: Fix the error handling here, it's bad... - outSwapChain = swapChain; outDevice = device; outContext = context; } -bool GpDisplayDriverD3D11::InitResources() +bool ResizeD3DWindow(HWND hWnd, DWORD &windowWidth, DWORD &windowHeight, LONG desiredWidth, LONG desiredHeight, DWORD windowStyle, HMENU menus) +{ + if (desiredWidth < 640) + desiredWidth = 640; + else if (desiredWidth > MAXDWORD) + desiredWidth = MAXDWORD; + + if (desiredHeight < 480) + desiredHeight = 480; + else if (desiredHeight > MAXDWORD) + desiredHeight = MAXDWORD; + + RECT windowRect; + GetClientRect(hWnd, &windowRect); + windowRect.right = windowRect.left + desiredWidth; + windowRect.bottom = windowRect.top + desiredHeight; + if (!AdjustWindowRect(&windowRect, windowStyle, menus != nullptr)) + return false; + + SetWindowPos(hWnd, HWND_TOP, windowRect.left, windowRect.top, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, SWP_NOZORDER | SWP_NOMOVE); + + windowWidth = desiredWidth; + windowHeight = desiredHeight; + + return true; +} + +bool GpDisplayDriverD3D11::DetachSwapChain() +{ + m_deviceContext->OMSetRenderTargets(0, nullptr, nullptr); + m_backBufferRTV = nullptr; + m_backBufferTexture = nullptr; + + m_deviceContext->ClearState(); + m_deviceContext->Flush(); + + return true; +} + +bool GpDisplayDriverD3D11::InitBackBuffer() { - // Fetch back buffer m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast(m_backBufferTexture.GetMutablePtr())); { @@ -136,6 +209,14 @@ bool GpDisplayDriverD3D11::InitResources() return false; } + return true; +} + +bool GpDisplayDriverD3D11::InitResources() +{ + if (!InitBackBuffer()) + return false; + // Quad vertex constant buffer { D3D11_BUFFER_DESC bufferDesc; @@ -599,6 +680,34 @@ void GpDisplayDriverD3D11::Run() } else { + RECT clientRect; + GetClientRect(m_hwnd, &clientRect); + + LONG desiredWidth = clientRect.right - clientRect.left; + LONG desiredHeight = clientRect.bottom - clientRect.top; + if (clientRect.right - clientRect.left != m_windowWidth || clientRect.bottom - clientRect.top != m_windowHeight) + { + uint32_t prevWidth = m_windowWidth; + uint32_t prevHeight = m_windowHeight; + + bool resizedOK = ResizeD3DWindow(m_hwnd, m_windowWidth, m_windowHeight, desiredWidth, desiredHeight, windowStyle, menus); + resizedOK = resizedOK && DetachSwapChain(); + resizedOK = resizedOK && ResizeSwapChain(m_swapChain, m_windowWidth, m_windowHeight); + resizedOK = resizedOK && InitBackBuffer(); + + if (!resizedOK) + break; // Critical video driver error, exit + + if (GpVOSEvent *resizeEvent = m_properties.m_eventQueue->QueueEvent()) + { + resizeEvent->m_eventType = GpVOSEventTypes::kVideoResolutionChanged; + resizeEvent->m_event.m_resolutionChangedEvent.m_prevWidth = prevWidth; + resizeEvent->m_event.m_resolutionChangedEvent.m_prevHeight = prevHeight; + resizeEvent->m_event.m_resolutionChangedEvent.m_newWidth = m_windowWidth; + resizeEvent->m_event.m_resolutionChangedEvent.m_newHeight = m_windowHeight; + } + } + GpDisplayDriverTickStatus_t tickStatus = PresentFrameAndSync(); if (tickStatus == GpDisplayDriverTickStatuses::kFatalFault || tickStatus == GpDisplayDriverTickStatuses::kApplicationTerminated) break; diff --git a/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.h b/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.h index a9a61e2..aec226f 100644 --- a/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.h +++ b/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.h @@ -70,6 +70,8 @@ private: GpDisplayDriverD3D11(const GpDisplayDriverProperties &properties); ~GpDisplayDriverD3D11(); + bool DetachSwapChain(); + bool InitBackBuffer(); bool InitResources(); GpDisplayDriverTickStatus_t PresentFrameAndSync(); diff --git a/PortabilityLayer/DisplayDeviceManager.cpp b/PortabilityLayer/DisplayDeviceManager.cpp index 45ea8aa..a2da391 100644 --- a/PortabilityLayer/DisplayDeviceManager.cpp +++ b/PortabilityLayer/DisplayDeviceManager.cpp @@ -22,6 +22,9 @@ namespace PortabilityLayer void IncrementTickCount(uint32_t count) override; uint32_t GetTickCount() override; + void SetResolutionChangeHandler(IResolutionChangeHandler *handler) override; + IResolutionChangeHandler *GetResolutionChangeHandler() const override; + static DisplayDeviceManagerImpl *GetInstance(); private: @@ -29,6 +32,8 @@ namespace PortabilityLayer GpPixelFormat_t m_pixelFormat; bool m_paletteIsDirty; + IResolutionChangeHandler *m_resChangeHandler; + PortabilityLayer::RGBAColor *m_palette; uint8_t m_paletteStorage[256 * sizeof(PortabilityLayer::RGBAColor) + GP_SYSTEM_MEMORY_ALIGNMENT]; @@ -39,6 +44,7 @@ namespace PortabilityLayer : m_tickCount(1) , m_paletteIsDirty(true) , m_pixelFormat(GpPixelFormats::k8BitStandard) + , m_resChangeHandler(nullptr) { uint8_t *paletteStorage = m_paletteStorage; while (reinterpret_cast(paletteStorage) % GP_SYSTEM_MEMORY_ALIGNMENT != 0) @@ -93,6 +99,15 @@ namespace PortabilityLayer return m_tickCount; } + void DisplayDeviceManagerImpl::SetResolutionChangeHandler(IResolutionChangeHandler *handler) + { + m_resChangeHandler = handler; + } + + DisplayDeviceManagerImpl::IResolutionChangeHandler *DisplayDeviceManagerImpl::GetResolutionChangeHandler() const + { + return m_resChangeHandler; + } DisplayDeviceManagerImpl *DisplayDeviceManagerImpl::GetInstance() { diff --git a/PortabilityLayer/DisplayDeviceManager.h b/PortabilityLayer/DisplayDeviceManager.h index 4318775..585eaf1 100644 --- a/PortabilityLayer/DisplayDeviceManager.h +++ b/PortabilityLayer/DisplayDeviceManager.h @@ -8,10 +8,15 @@ struct IGpDisplayDriver; namespace PortabilityLayer -{ +{ class DisplayDeviceManager { - public: + public: + struct IResolutionChangeHandler + { + virtual void OnResolutionChanged(uint32_t prevWidth, uint32_t prevHeight, uint32_t newWidth, uint32_t newHeight) = 0; + }; + virtual void Init() = 0; virtual void Shutdown() = 0; @@ -19,9 +24,14 @@ namespace PortabilityLayer virtual void SyncPalette(IGpDisplayDriver *displayDriver) = 0; virtual void IncrementTickCount(uint32_t count) = 0; - virtual uint32_t GetTickCount() = 0; + virtual uint32_t GetTickCount() = 0; + + virtual void SetResolutionChangeHandler(IResolutionChangeHandler *handler) = 0; + virtual IResolutionChangeHandler *GetResolutionChangeHandler() const = 0; - static DisplayDeviceManager *GetInstance(); + static DisplayDeviceManager *GetInstance(); + + public: }; } diff --git a/PortabilityLayer/PLSysCalls.cpp b/PortabilityLayer/PLSysCalls.cpp index 95ea907..ce67e17 100644 --- a/PortabilityLayer/PLSysCalls.cpp +++ b/PortabilityLayer/PLSysCalls.cpp @@ -47,6 +47,13 @@ static void TranslateGamepadInputEvent(const GpGamepadInputEvent &vosEvent, Port PL_DEAD(queue); } +static void TranslateVideoResolutionChangedEvent(const GpVideoResolutionChangedEvent &evt) +{ + PortabilityLayer::DisplayDeviceManager::IResolutionChangeHandler *chgHandler = PortabilityLayer::DisplayDeviceManager::GetInstance()->GetResolutionChangeHandler(); + if (chgHandler) + chgHandler->OnResolutionChanged(evt.m_prevWidth, evt.m_prevHeight, evt.m_newWidth, evt.m_newHeight); +} + static void TranslateKeyboardInputEvent(const GpVOSEvent &vosEventBase, uint32_t timestamp, PortabilityLayer::EventQueue *queue) { const GpKeyboardInputEvent &vosEvent = vosEventBase.m_event.m_keyboardInputEvent; @@ -108,6 +115,9 @@ static void TranslateVOSEvent(const GpVOSEvent *vosEvent, uint32_t timestamp, Po case GpVOSEventTypes::kGamepadInput: TranslateGamepadInputEvent(vosEvent->m_event.m_gamepadInputEvent, queue); break; + case GpVOSEventTypes::kVideoResolutionChanged: + TranslateVideoResolutionChangedEvent(vosEvent->m_event.m_resolutionChangedEvent); + break; } } diff --git a/PortabilityLayer/WindowManager.cpp b/PortabilityLayer/WindowManager.cpp index 225f83e..689fc62 100644 --- a/PortabilityLayer/WindowManager.cpp +++ b/PortabilityLayer/WindowManager.cpp @@ -17,6 +17,8 @@ #include "Vec2i.h" #include "WindowDef.h" +#include + struct GDevice; namespace PortabilityLayer @@ -130,6 +132,8 @@ namespace PortabilityLayer void RenderFrame(IGpDisplayDriver *displayDriver) override; + void HandleScreenResolutionChange(uint32_t prevWidth, uint32_t prevHeight, uint32_t newWidth, uint32_t newHeight) override; + Window *GetPutInFrontSentinel() const override; static WindowManagerImpl *GetInstance(); @@ -553,7 +557,13 @@ namespace PortabilityLayer void WindowImpl::GetChromePadding(uint16_t padding[WindowChromeSides::kCount]) const { - return m_chromeTheme->GetChromePadding(this, padding); + if (m_chromeTheme) + m_chromeTheme->GetChromePadding(this, padding); + else + { + for (int i = 0; i < WindowChromeSides::kCount; i++) + padding[i] = 0; + } } void WindowImpl::GetChromeDimensions(int width, int height, Rect dimensions[WindowChromeSides::kCount]) const @@ -572,6 +582,9 @@ namespace PortabilityLayer bool WindowImpl::GetChromeInteractionZone(const Vec2i &point, RegionID_t &outRegion) const { + if (!m_chromeTheme) + return false; + return m_chromeTheme->GetChromeInteractionZone(this, point, outRegion); } @@ -798,6 +811,46 @@ namespace PortabilityLayer } } + void WindowManagerImpl::HandleScreenResolutionChange(uint32_t prevWidth, uint32_t prevHeight, uint32_t newWidth, uint32_t newHeight) + { + for (PortabilityLayer::WindowImpl *window = m_windowStackTop; window != nullptr; window = window->GetWindowBelow()) + { + uint16_t chromePadding[WindowChromeSides::kCount]; + window->GetChromePadding(chromePadding); + + const Rect surfaceRect = window->GetDrawSurface()->m_port.GetRect(); + + uint32_t paddedWidth = surfaceRect.Width() + chromePadding[WindowChromeSides::kLeft] + chromePadding[WindowChromeSides::kRight]; + uint32_t paddedHeight = surfaceRect.Height() + chromePadding[WindowChromeSides::kTop] + chromePadding[WindowChromeSides::kBottom]; + + int64_t newX = 0; + if (newWidth <= paddedWidth || prevWidth <= paddedWidth) + newX = (static_cast(newWidth) - paddedWidth) / 2; + else + { + uint32_t prevClearanceX = prevWidth - paddedWidth; + uint32_t newClearanceX = newWidth - paddedWidth; + newX = static_cast(window->m_wmX) * static_cast(newClearanceX) / static_cast(prevClearanceX); + } + + int64_t newY = 0; + if (newHeight <= paddedHeight || prevHeight <= paddedHeight) + newY = (static_cast(newHeight) - paddedHeight) / 2; + else + { + uint32_t prevClearanceY = prevHeight - paddedHeight; + uint32_t newClearanceY = newHeight - paddedHeight; + newY = static_cast(window->m_wmY) * static_cast(newClearanceY) / static_cast(prevClearanceY); + } + + newX = std::max(0, std::min(newX, newWidth - 1)); + newY = std::max(0, std::min(newY, newHeight - 1)); + + window->m_wmX = static_cast(newX); + window->m_wmY = static_cast(newY); + } + } + void WindowManagerImpl::ResizeWindow(Window *window, int width, int height) { static_cast(window)->Resize(width, height); diff --git a/PortabilityLayer/WindowManager.h b/PortabilityLayer/WindowManager.h index c93dcb5..631169e 100644 --- a/PortabilityLayer/WindowManager.h +++ b/PortabilityLayer/WindowManager.h @@ -1,5 +1,7 @@ #pragma once +#include + struct Window; struct DrawSurface; struct GDevice; @@ -30,6 +32,8 @@ namespace PortabilityLayer virtual void RenderFrame(IGpDisplayDriver *displayDriver) = 0; + virtual void HandleScreenResolutionChange(uint32_t prevWidth, uint32_t prevHeight, uint32_t newWidth, uint32_t newHeight) = 0; + static WindowManager *GetInstance(); }; } diff --git a/PortabilityLayer/ZipFileProxy.h b/PortabilityLayer/ZipFileProxy.h index 38c7195..006321b 100644 --- a/PortabilityLayer/ZipFileProxy.h +++ b/PortabilityLayer/ZipFileProxy.h @@ -6,7 +6,7 @@ namespace PortabilityLayer { class IOStream; struct ZipCentralDirectoryFileHeader; - + class ZipFileProxy { public: