Partial resolution change support

This commit is contained in:
elasota
2020-04-01 14:53:44 -04:00
parent e114d5c5dd
commit 6326a0b2d9
24 changed files with 495 additions and 124 deletions

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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"<22>
// 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

View File

@@ -28,9 +28,10 @@ typedef struct
Boolean hasSM3;
Boolean hasQT;
Boolean hasDrag;
Boolean isResolutionDirty;
} macEnviron;
extern macEnviron thisMac;
void FlushResolutionChange(void);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -27,11 +27,10 @@ struct IGpCursor;
extern THandle<Rect> 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,<2C>
@@ -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();
}

View File

@@ -315,6 +315,7 @@ int gpAppMain()
ToolBoxInit();
CheckOurEnvirons();
InstallResolutionHandler();
if (!thisMac.hasColor)
RedAlert(kErrNeedColorQD);
if (!thisMac.hasSystem7)

View File

@@ -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);

View File

@@ -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);

View File

@@ -34,9 +34,7 @@ void CopyRectsQD (void);
Rect work2MainRects[kMaxGarbageRects];
Rect back2WorkRects[kMaxGarbageRects];
Rect shieldRect;
THandle<Rect> mirrorRects;
Point shieldPt;
long nextFrame;
short numWork2Main, numBack2Work;
Boolean hasMirror;

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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<65>
@@ -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);

View File

@@ -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;

View File

@@ -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 <d3d11.h>
#include <dxgi1_2.h>
@@ -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<IDXGISwapChain1>& outSwapChain, GpComPtr<ID3D11Device>& outDevice, GpComPtr<ID3D11DeviceContext>& outContext)
bool InitSwapChainForWindow(HWND hWnd, ID3D11Device *device, GpComPtr<IDXGISwapChain1>& outSwapChain)
{
outSwapChain = nullptr;
DXGI_SWAP_CHAIN_DESC1 swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
@@ -76,6 +80,46 @@ void StartD3DForWindow(HWND hWnd, GpComPtr<IDXGISwapChain1>& 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<void**>(&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<void**>(&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<IDXGISwapChain1>& outSwapChain, GpComPtr<ID3D11Device>& outDevice, GpComPtr<ID3D11DeviceContext>& outContext)
{
DXGI_SWAP_CHAIN_FULLSCREEN_DESC swapChainFullscreenDesc;
ZeroMemory(&swapChainFullscreenDesc, sizeof(swapChainFullscreenDesc));
@@ -90,7 +134,9 @@ void StartD3DForWindow(HWND hWnd, GpComPtr<IDXGISwapChain1>& 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<IDXGISwapChain1>& 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<void**>(&dxgiDevice));
IDXGIAdapter *dxgiAdapter = nullptr;
result = dxgiDevice->GetAdapter(&dxgiAdapter);
IDXGIFactory2 *dxgiFactory = nullptr;
result = dxgiAdapter->GetParent(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&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<LPVOID*>(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;

View File

@@ -70,6 +70,8 @@ private:
GpDisplayDriverD3D11(const GpDisplayDriverProperties &properties);
~GpDisplayDriverD3D11();
bool DetachSwapChain();
bool InitBackBuffer();
bool InitResources();
GpDisplayDriverTickStatus_t PresentFrameAndSync();

View File

@@ -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<intptr_t>(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()
{

View File

@@ -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:
};
}

View File

@@ -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;
}
}

View File

@@ -17,6 +17,8 @@
#include "Vec2i.h"
#include "WindowDef.h"
#include <algorithm>
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<int64_t>(newWidth) - paddedWidth) / 2;
else
{
uint32_t prevClearanceX = prevWidth - paddedWidth;
uint32_t newClearanceX = newWidth - paddedWidth;
newX = static_cast<int64_t>(window->m_wmX) * static_cast<int64_t>(newClearanceX) / static_cast<int64_t>(prevClearanceX);
}
int64_t newY = 0;
if (newHeight <= paddedHeight || prevHeight <= paddedHeight)
newY = (static_cast<int64_t>(newHeight) - paddedHeight) / 2;
else
{
uint32_t prevClearanceY = prevHeight - paddedHeight;
uint32_t newClearanceY = newHeight - paddedHeight;
newY = static_cast<int64_t>(window->m_wmY) * static_cast<int64_t>(newClearanceY) / static_cast<int64_t>(prevClearanceY);
}
newX = std::max<int64_t>(0, std::min<int64_t>(newX, newWidth - 1));
newY = std::max<int64_t>(0, std::min<int64_t>(newY, newHeight - 1));
window->m_wmX = static_cast<int32_t>(newX);
window->m_wmY = static_cast<int32_t>(newY);
}
}
void WindowManagerImpl::ResizeWindow(Window *window, int width, int height)
{
static_cast<WindowImpl*>(window)->Resize(width, height);

View File

@@ -1,5 +1,7 @@
#pragma once
#include <stdint.h>
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();
};
}

View File

@@ -6,7 +6,7 @@ namespace PortabilityLayer
{
class IOStream;
struct ZipCentralDirectoryFileHeader;
class ZipFileProxy
{
public: