diff --git a/GpApp/Main.cpp b/GpApp/Main.cpp index 3d06b89..8c6215e 100644 --- a/GpApp/Main.cpp +++ b/GpApp/Main.cpp @@ -6,17 +6,29 @@ //============================================================================ +#include #include "PLApplication.h" #include "PLKeyEncoding.h" +#include "PLStandardColors.h" +#include "PLSysCalls.h" #include "Externs.h" #include "Environ.h" +#include "FontFamily.h" +#include "GpRenderedFontMetrics.h" #include "HostDisplayDriver.h" #include "IGpDisplayDriver.h" #include "GpIOStream.h" #include "House.h" +#include "RenderedFont.h" +#include "ResolveCachingColor.h" #include "WindowManager.h" +WindowPtr loadScreenWindow; +Rect loadScreenProgressBarRect; +int loadScreenProgress; + + #define kPrefsVersion 0x0038 @@ -52,8 +64,8 @@ THandle globalModulePrefs; //============================================================== Functions //-------------------------------------------------------------- ReadInPrefs -// Called only once when game launches - reads in the preferences savedÉ -// from the last time Glider PRO was launched. If no prefs are found,É +// Called only once when game launches - reads in the preferences saved? +// from the last time Glider PRO was launched. If no prefs are found,? // it assigns default settings. void ReadInPrefs (void) @@ -61,7 +73,7 @@ void ReadInPrefs (void) prefsInfo thePrefs; THandle modulePrefs; - + if (LoadPrefs(&thePrefs, &modulePrefs, kPrefsVersion)) { #ifdef COMPILEDEMO @@ -171,7 +183,7 @@ void ReadInPrefs (void) isVolume = 1; else if (isVolume > 3) isVolume = 3; - + isDepthPref = kSwitchIfNeeded; isSoundOn = true; isMusicOn = true; @@ -223,13 +235,13 @@ void ReadInPrefs (void) modulePrefs.Dispose(); } - + if ((numNeighbors > 1) && (thisMac.constrainedScreen.right <= 512)) numNeighbors = 1; - + UnivGetSoundVolume(&wasVolume, thisMac.hasSM3); UnivSetSoundVolume(isVolume, thisMac.hasSM3); - + if (isVolume == 0) isSoundOn = false; else @@ -238,15 +250,15 @@ void ReadInPrefs (void) //-------------------------------------------------------------- WriteOutPrefs -// Called just before Glider PRO quits. This function writes outÉ +// Called just before Glider PRO quits. This function writes out? // the user preferences to disk. void WriteOutPrefs (void) { - prefsInfo thePrefs; - + prefsInfo thePrefs; + UnivGetSoundVolume(&isVolume, thisMac.hasSM3); - + #ifdef COMPILEDEMO PasStringCopy("\pDemo House", thePrefs.wasDefaultName); #else @@ -322,10 +334,93 @@ void WriteOutPrefs (void) SysBeep(1); modulePrefs.Dispose(); - + UnivSetSoundVolume(wasVolume, thisMac.hasSM3); } +void StepLoadScreen(int steps) +{ + if (loadScreenWindow) + { + int oldProgress = loadScreenProgress; + int loadScreenMax = 19; + loadScreenProgress = loadScreenProgress + steps; + if (loadScreenProgress > loadScreenMax) + loadScreenProgress = loadScreenMax; + + PortabilityLayer::ResolveCachingColor blackColor(StdColors::Black()); + + int prevStep = oldProgress * loadScreenProgressBarRect.Width() / loadScreenMax; + int thisStep = loadScreenProgress * loadScreenProgressBarRect.Width() / loadScreenMax; + + loadScreenWindow->GetDrawSurface()->FillRect(Rect::Create(loadScreenProgressBarRect.top, loadScreenProgressBarRect.left + prevStep, loadScreenProgressBarRect.bottom, loadScreenProgressBarRect.left + thisStep), blackColor); + ForceSyncFrame(); + } + + SpinCursor(steps); +} + +void InitLoadingWindow() +{ + static const int kLoadScreenHeight = 32; + static const int kLoadScreenWidth = 256; + + ForceSyncFrame(); + PLSysCalls::Sleep(1); + + int32_t lsX = (thisMac.fullScreen.Width() - kLoadScreenWidth) / 2; + int32_t lsY = (thisMac.fullScreen.Height() - kLoadScreenHeight) / 2; + + + const Rect loadScreenRect = Rect::Create(lsY, lsX, lsY + kLoadScreenHeight, lsX + kLoadScreenWidth); + const Rect loadScreenLocalRect = Rect::Create(0, 0, loadScreenRect.Height(), loadScreenRect.Width()); + + PortabilityLayer::WindowDef def = PortabilityLayer::WindowDef::Create(loadScreenRect, PortabilityLayer::WindowStyleFlags::kAlert, true, 0, 0, PSTR("")); + + loadScreenWindow = PortabilityLayer::WindowManager::GetInstance()->CreateWindow(def); + PortabilityLayer::WindowManager::GetInstance()->PutWindowBehind(loadScreenWindow, PL_GetPutInFrontWindowPtr()); + + DrawSurface *surface = loadScreenWindow->GetDrawSurface(); + PortabilityLayer::ResolveCachingColor blackColor(StdColors::Black()); + PortabilityLayer::ResolveCachingColor whiteColor(StdColors::White()); + + surface->FillRect(loadScreenLocalRect, whiteColor); + + PortabilityLayer::WindowManager::GetInstance()->FlickerWindowIn(loadScreenWindow, 32); + + const PLPasStr loadingText = PSTR("Loading..."); + PortabilityLayer::RenderedFont *font = GetApplicationFont(18, PortabilityLayer::FontFamilyFlag_None, true); + int32_t textY = (kLoadScreenHeight + font->GetMetrics().m_ascent) / 2; + surface->DrawString(Point::Create(4+16, textY), loadingText, blackColor, font); + + static const int32_t loadBarPadding = 16; + int32_t loadBarStartX = static_cast(font->MeasureString(loadingText.UChars(), loadingText.Length())) + 4 + 16 + loadBarPadding; + int32_t loadBarEndX = loadScreenLocalRect.right - loadBarPadding; + + loadScreenProgressBarRect = Rect::Create((loadScreenLocalRect.Height() - 8) / 2, loadBarStartX, (loadScreenLocalRect.Height() + 8) / 2, loadBarEndX); + loadScreenProgress = 0; + + surface->FrameRect(loadScreenProgressBarRect, blackColor); +} + +void PreloadFonts() +{ + GetApplicationFont(8, PortabilityLayer::FontFamilyFlag_None, true); + StepLoadScreen(1); + GetApplicationFont(9, PortabilityLayer::FontFamilyFlag_None, true); + StepLoadScreen(1); + GetApplicationFont(9, PortabilityLayer::FontFamilyFlag_Bold, true); + StepLoadScreen(1); + GetApplicationFont(14, PortabilityLayer::FontFamilyFlag_Bold, true); + StepLoadScreen(1); + GetApplicationFont(12, PortabilityLayer::FontFamilyFlag_Bold, true); + StepLoadScreen(1); + GetApplicationFont(10, PortabilityLayer::FontFamilyFlags::FontFamilyFlag_Bold, true); + StepLoadScreen(1); + GetSystemFont(12, PortabilityLayer::FontFamilyFlag_Bold, true); + StepLoadScreen(1); +} + //-------------------------------------------------------------- main // Here is main(). The first function called when Glider PRO comes up. @@ -337,10 +432,11 @@ int gpAppMain() Boolean whoCares, copyGood; PL_Init(); - + ToolBoxInit(); CheckOurEnvirons(); InstallResolutionHandler(); + if (!thisMac.hasColor) RedAlert(kErrNeedColorQD); if (!thisMac.hasSystem7) @@ -354,7 +450,10 @@ int gpAppMain() SpinCursor(2); // Tick once to let the display driver flush any resolution changes from prefs FlushResolutionChange(); - + + InitLoadingWindow(); StepLoadScreen(2); + PreloadFonts(); StepLoadScreen(2); + #if defined COMPILEDEMO copyGood = true; #elif defined COMPILENOCP @@ -366,18 +465,23 @@ int gpAppMain() if (!copyGood) encryptedNumber = 0L; else if (didValidation) - WriteOutPrefs(); SpinCursor(3); + WriteOutPrefs(); StepLoadScreen(3); #endif // if ((thisMac.numScreens > 1) && (isUseSecondScreen)) // ReflectSecondMonitorEnvirons(false, true, true); HandleDepthSwitching(); - VariableInit(); SpinCursor(2); - GetExtraCursors(); SpinCursor(2); + VariableInit(); StepLoadScreen(2); + GetExtraCursors(); StepLoadScreen(2); InitMarquee(); - CreatePointers(); SpinCursor(2); + CreatePointers(); StepLoadScreen(2); InitSrcRects(); - CreateOffscreens(); SpinCursor(2); + CreateOffscreens(); StepLoadScreen(2); + + PortabilityLayer::WindowManager::GetInstance()->FlickerWindowOut(loadScreenWindow, 32); + PortabilityLayer::WindowManager::GetInstance()->DestroyWindow(loadScreenWindow); + PLSysCalls::Sleep(15); + OpenMainWindow(); if (isDoColorFade) @@ -388,27 +492,27 @@ int gpAppMain() BuildHouseList(); if (OpenHouse()) whoCares = ReadHouse(); - + PlayPrioritySound(kBirdSound, kBirdPriority); DelayTicks(6); InitializeMenus(); InitCursor(); - + #if BUILD_ARCADE_VERSION // HideMenuBarOld(); #endif - + if (isDoColorFade) WashColorIn(); UpdateMainWindow(); - + while (!quitting) // this is the main loop HandleEvent(); -/* +/* #if BUILD_ARCADE_VERSION ShowMenuBarOld(); #endif -*/ +*/ KillMusic(); KillSound(); if (houseOpen) diff --git a/GpCommon/GpDisplayDriverTickStatus.h b/GpCommon/GpDisplayDriverTickStatus.h index 73777b5..1380c51 100644 --- a/GpCommon/GpDisplayDriverTickStatus.h +++ b/GpCommon/GpDisplayDriverTickStatus.h @@ -9,6 +9,8 @@ namespace GpDisplayDriverTickStatuses kFatalFault = 2, kApplicationTerminated = 3, + + kSynchronizing = 4, }; } diff --git a/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp b/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp index 9a776f6..bcc71ba 100644 --- a/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp +++ b/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp @@ -768,7 +768,12 @@ GpDisplayDriverTickStatus_t GpDisplayDriverD3D11::PresentFrameAndSync() GpDisplayDriverTickStatus_t tickStatus = m_properties.m_tickFunc(m_properties.m_tickFuncContext, m_vosFiber); m_frameTimeAccumulated -= m_frameTimeSliceSize; - if (tickStatus != GpDisplayDriverTickStatuses::kOK) + if (tickStatus == GpDisplayDriverTickStatuses::kSynchronizing) + { + m_frameTimeAccumulated = 0; + break; + } + else if (tickStatus != GpDisplayDriverTickStatuses::kOK) return tickStatus; } } diff --git a/GpShell/GpAppEnvironment.cpp b/GpShell/GpAppEnvironment.cpp index 4ec01cb..8c00ab8 100644 --- a/GpShell/GpAppEnvironment.cpp +++ b/GpShell/GpAppEnvironment.cpp @@ -79,6 +79,15 @@ GpDisplayDriverTickStatus_t GpAppEnvironment::Tick(IGpFiber *vosFiber) return GpDisplayDriverTickStatuses::kOK; } break; + case ApplicationState_Synchronizing: + if (m_delaySuspendTicks == 0) + m_applicationState = ApplicationState_Running; + else + { + m_delaySuspendTicks--; + return GpDisplayDriverTickStatuses::kSynchronizing; + } + break; case ApplicationState_Terminated: m_applicationFiber->Destroy(); m_applicationFiber = nullptr; @@ -182,6 +191,10 @@ void GpAppEnvironment::DispatchSystemCall(PortabilityLayer::HostSuspendCallID ca m_applicationState = ApplicationState_TimedSuspend; m_delaySuspendTicks = args[0].m_uint; break; + case PortabilityLayer::HostSuspendCallID_ForceSyncFrame: + m_applicationState = ApplicationState_Synchronizing; + m_delaySuspendTicks = 1; + break; case PortabilityLayer::HostSuspendCallID_CallOnVOSThread: args[0].m_functionPtr(static_cast(args[1].m_constPointer), static_cast(args[2].m_pointer)); m_applicationState = ApplicationState_Running; diff --git a/GpShell/GpAppEnvironment.h b/GpShell/GpAppEnvironment.h index 30b58b2..f33dac1 100644 --- a/GpShell/GpAppEnvironment.h +++ b/GpShell/GpAppEnvironment.h @@ -47,6 +47,7 @@ private: ApplicationState_Terminated, ApplicationState_SystemCall, ApplicationState_TimedSuspend, + ApplicationState_Synchronizing, }; static void StaticAppThreadFunc(void *context); diff --git a/PortabilityLayer/HostSuspendCallID.h b/PortabilityLayer/HostSuspendCallID.h index cd9e90b..de203db 100644 --- a/PortabilityLayer/HostSuspendCallID.h +++ b/PortabilityLayer/HostSuspendCallID.h @@ -9,7 +9,8 @@ namespace PortabilityLayer HostSuspendCallID_Unknown, HostSuspendCallID_Delay, - HostSuspendCallID_CallOnVOSThread, + HostSuspendCallID_CallOnVOSThread, + HostSuspendCallID_ForceSyncFrame }; } diff --git a/PortabilityLayer/PLCore.cpp b/PortabilityLayer/PLCore.cpp index edae34e..b21ea99 100644 --- a/PortabilityLayer/PLCore.cpp +++ b/PortabilityLayer/PLCore.cpp @@ -108,6 +108,11 @@ void Delay(int ticks, UInt32 *endTickCount) *endTickCount = PortabilityLayer::DisplayDeviceManager::GetInstance()->GetTickCount(); } +void ForceSyncFrame() +{ + PLSysCalls::ForceSyncFrame(); +} + short FindWindow(Point point, WindowPtr *window) { short part = 0; diff --git a/PortabilityLayer/PLCore.h b/PortabilityLayer/PLCore.h index 5198197..7b23249 100644 --- a/PortabilityLayer/PLCore.h +++ b/PortabilityLayer/PLCore.h @@ -216,6 +216,7 @@ void InitCursor(); void HideCursor(); void Delay(int ticks, UInt32 *endTickCount); +void ForceSyncFrame(); short FindWindow(Point point, WindowPtr *window); // Translates global coordinates to window coordinates, returns a region ID bool TrackGoAway(WindowPtr window, Point point); // Returns true if the close box was actually clicked (?) diff --git a/PortabilityLayer/PLSysCalls.cpp b/PortabilityLayer/PLSysCalls.cpp index 1f94116..92ff313 100644 --- a/PortabilityLayer/PLSysCalls.cpp +++ b/PortabilityLayer/PLSysCalls.cpp @@ -184,4 +184,9 @@ namespace PLSysCalls AnimationManager::GetInstance()->TickPlayers(ticks); } } + + void ForceSyncFrame() + { + PortabilityLayer::SuspendApplication(PortabilityLayer::HostSuspendCallID_ForceSyncFrame, nullptr, nullptr); + } } diff --git a/PortabilityLayer/PLSysCalls.h b/PortabilityLayer/PLSysCalls.h index 0afce1e..98c6b53 100644 --- a/PortabilityLayer/PLSysCalls.h +++ b/PortabilityLayer/PLSysCalls.h @@ -7,4 +7,5 @@ namespace PLSysCalls { void Sleep(uint32_t ticks); + void ForceSyncFrame(); }