Compare commits

...

35 Commits
1.0.15 ... web

Author SHA1 Message Date
elasota
b90d0c303c Fix AerofoilX 2021-04-07 11:42:57 -04:00
elasota
7842e721e5 Remove Resources dir from Windows release 2021-04-07 10:52:18 -04:00
elasota
93195207dc Disable glGetError calls in release config 2021-04-07 00:03:09 -04:00
elasota
59741dd966 Bump Android version to 1.1.0 2021-04-07 00:02:52 -04:00
elasota
1ac69c2c75 Misc tweaks, partially bump version to 1.1 2021-03-30 05:24:37 -04:00
elasota
69f59f769d Fix broken thread events 2021-03-30 05:24:18 -04:00
elasota
bb2af5abb3 Fix bad parameter 2021-03-30 05:23:54 -04:00
elasota
3692a966bf Tweak some values to help with sound choppiness in Chrome slightly, until we port to OpenAL 2021-03-30 05:23:44 -04:00
elasota
7916c72fc4 Fix incorrect fast AA calculations 2021-03-30 05:23:02 -04:00
elasota
7951f579e0 Remove logs 2021-03-30 00:01:37 -04:00
elasota
b64c904558 Remove junk 2021-03-30 00:00:17 -04:00
elasota
a6f6ffcdcc Remove log func 2021-03-30 00:00:07 -04:00
elasota
6fb45f480b Emscripten port 2021-03-29 21:41:11 -04:00
elasota
9ba0e9f13d Remove FreeType from Android build 2021-03-29 11:57:04 -04:00
elasota
0df94405f8 Faster AA table generation 2021-03-27 03:01:43 -04:00
elasota
ae69696cbd Remove unused header 2021-03-27 03:01:30 -04:00
elasota
50f420d2b1 Font system refactor, use pre-rendered fonts 2021-03-27 03:01:19 -04:00
elasota
c87f238563 Display driver loop refactor 2021-03-26 17:05:38 -04:00
elasota
48fe83bb33 EOL fix 2021-03-19 03:45:43 -04:00
elasota
b2b27ef335 Fix some splash screen inconsistencies 2021-03-19 03:16:59 -04:00
elasota
89831f0ff6 Fix Windows SDL build 2021-03-18 19:05:16 -04:00
elasota
99fd71196d Tentative Linux readme 2021-03-18 18:16:18 -04:00
elasota
7060676b73 Cygwin port 2021-03-18 17:08:11 -04:00
elasota
184f867f79 Fix Android symlinks 2021-03-18 17:05:29 -04:00
elasota
cbd759c754 Add README.md 2021-03-16 03:02:18 -04:00
elasota
2ada8029d0 Fixed source code export not working 2021-03-15 19:36:07 -04:00
elasota
8e0d8e261e Bump version to 1.0.17 2021-03-12 18:42:54 -05:00
elasota
20b9eef64d Fix missing FreeType2 PDBs 2021-03-12 18:26:08 -05:00
elasota
c147e1100e Change MiniRez to use WindowsUnicodeToolShim 2021-03-11 22:28:01 -05:00
elasota
0a2e730d26 Change FTagData to use WindowsUnicodeToolShim 2021-03-11 22:22:30 -05:00
elasota
922cd0fd06 Add debug/release props to WindowsUnicodeToolShim 2021-03-11 22:22:14 -05:00
elasota
b8bf6be44f Change hqx2gp to use WindowsUnicodeToolShim 2021-03-11 22:18:07 -05:00
elasota
2897c4ffab Fix saved game deletion not working 2021-03-11 21:40:22 -05:00
elasota
35c174984b Bump version to 1.0.16 2021-03-11 21:36:06 -05:00
elasota
da16edea8d Fix broken AA table preloader, use load bar first time on desktop 2021-03-09 04:15:59 -05:00
213 changed files with 5342 additions and 2248 deletions

13
.gitignore vendored
View File

@@ -20,6 +20,7 @@
*.idb
*.aps
*.res
*.a
.vs/*
Packaged/*
DebugData/*
@@ -30,9 +31,21 @@ InstallerPackages/*
*.wixobj
*.CopyComplete
*.lnk
*.cmake
ReleasePackageInstaller/obj/*
ReleasePackageInstaller/bin/*
ReleasePackageInstaller/AerofoilPackageDefs.wxi
ReleasePackageInstaller/AerofoilPackageVersion.wxi
packages/*
!SDL2-2.0.12/lib/x64/*
CMakeCache.txt
CMakeFiles/*
Makefile
SDL2-2.0.12/CMakeFiles/*
SDL2-2.0.12/build
SDL2-2.0.12/config.status
SDL2-2.0.12/libtool
SDL2-2.0.12/Makefile.rules
SDL2-2.0.12/sdl2.pc
SDL2-2.0.12/sdl2-config
install_manifest.txt

View File

@@ -63,6 +63,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AerofoilSDL", "AerofoilSDL\
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MergeGPF", "MergeGPF\MergeGPF.vcxproj", "{36DAF5FA-6ADB-4F20-9810-1610DE0AE653}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GenerateFonts", "GenerateFonts\GenerateFonts.vcxproj", "{3B7FD18D-7A50-4DF5-AC25-543E539BFACE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bin2h", "bin2h\bin2h.vcxproj", "{D045F28D-F245-44DD-B576-CC91BF3BE6E9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -175,6 +179,14 @@ Global
{36DAF5FA-6ADB-4F20-9810-1610DE0AE653}.Debug|x64.Build.0 = Debug|x64
{36DAF5FA-6ADB-4F20-9810-1610DE0AE653}.Release|x64.ActiveCfg = Release|x64
{36DAF5FA-6ADB-4F20-9810-1610DE0AE653}.Release|x64.Build.0 = Release|x64
{3B7FD18D-7A50-4DF5-AC25-543E539BFACE}.Debug|x64.ActiveCfg = Debug|x64
{3B7FD18D-7A50-4DF5-AC25-543E539BFACE}.Debug|x64.Build.0 = Debug|x64
{3B7FD18D-7A50-4DF5-AC25-543E539BFACE}.Release|x64.ActiveCfg = Release|x64
{3B7FD18D-7A50-4DF5-AC25-543E539BFACE}.Release|x64.Build.0 = Release|x64
{D045F28D-F245-44DD-B576-CC91BF3BE6E9}.Debug|x64.ActiveCfg = Debug|x64
{D045F28D-F245-44DD-B576-CC91BF3BE6E9}.Debug|x64.Build.0 = Debug|x64
{D045F28D-F245-44DD-B576-CC91BF3BE6E9}.Release|x64.ActiveCfg = Release|x64
{D045F28D-F245-44DD-B576-CC91BF3BE6E9}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -84,14 +84,12 @@
<ItemGroup>
<ClCompile Include="GpBWCursor_Win32.cpp" />
<ClCompile Include="GpColorCursor_Win32.cpp" />
<ClCompile Include="GpFiber_Win32.cpp" />
<ClCompile Include="GpFileStream_Win32.cpp" />
<ClCompile Include="GpFileSystem_Win32.cpp" />
<ClCompile Include="GpLogDriver_Win32.cpp" />
<ClCompile Include="GpMain_Win32.cpp" />
<ClCompile Include="GpMutex_Win32.cpp" />
<ClCompile Include="GpSystemServices_Win32.cpp" />
<ClCompile Include="GpFiberStarter_Win32.cpp" />
<ClCompile Include="GpThreadEvent_Win32.cpp" />
</ItemGroup>
<ItemGroup>
@@ -108,7 +106,6 @@
<ClInclude Include="..\GpCommon\IGpLogDriver.h" />
<ClInclude Include="..\GpCommon\IGpPrefsHandler.h" />
<ClInclude Include="GpBWCursor_Win32.h" />
<ClInclude Include="GpFiber_Win32.h" />
<ClInclude Include="GpFileStream_Win32.h" />
<ClInclude Include="GpFileSystem_Win32.h" />
<ClInclude Include="GpLogDriver_Win32.h" />
@@ -127,9 +124,6 @@
<ProjectReference Include="..\GpDisplayDriver_D3D11\GpDisplayDriver_D3D11.vcxproj">
<Project>{ffc961ac-55b4-4a38-a83e-06ae98f59acc}</Project>
</ProjectReference>
<ProjectReference Include="..\GpFontHandler_FreeType2\GpFontHandler_FreeType2.vcxproj">
<Project>{4b564030-8985-4975-91e1-e1b2c16ae2a1}</Project>
</ProjectReference>
<ProjectReference Include="..\GpInputDriver_XInput\GpInputDriver_XInput.vcxproj">
<Project>{17b96f07-ef92-47cd-95a5-8e6ee38ab564}</Project>
</ProjectReference>

View File

@@ -4,12 +4,6 @@
<ClCompile Include="GpColorCursor_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpFiber_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpFiberStarter_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpFileStream_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -48,9 +42,6 @@
<ClInclude Include="..\GpCommon\GpDisplayDriverTickStatus.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpFiber_Win32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\GpFileCreationDisposition.h">
<Filter>Header Files</Filter>
</ClInclude>

View File

@@ -1,56 +0,0 @@
#include "GpFiberStarter.h"
#include "GpFiber_Win32.h"
#include "GpWindows.h"
#include <assert.h>
namespace GpFiberStarter_Win32
{
struct FiberStartState
{
GpFiberStarter::ThreadFunc_t m_threadFunc;
IGpFiber *m_creatingFiber;
void *m_context;
};
static VOID WINAPI FiberStartRoutine(LPVOID lpThreadParameter)
{
const FiberStartState *tss = static_cast<const FiberStartState*>(lpThreadParameter);
GpFiberStarter::ThreadFunc_t threadFunc = tss->m_threadFunc;
IGpFiber *creatingFiber = tss->m_creatingFiber;
void *context = tss->m_context;
SwitchToFiber(static_cast<GpFiber_Win32*>(creatingFiber)->GetFiber());
threadFunc(context);
assert(!"Fiber function exited");
}
}
IGpFiber *GpFiberStarter::StartFiber(IGpSystemServices *systemServices, ThreadFunc_t threadFunc, void *context, IGpFiber *creatingFiber)
{
ULONG_PTR lowLimit;
ULONG_PTR highLimit;
#if 0
GetCurrentThreadStackLimits(&lowLimit, &highLimit);
ULONG_PTR stackSize = highLimit - lowLimit;
#else
ULONG_PTR stackSize = 1024 * 1024;
#endif
GpFiberStarter_Win32::FiberStartState startState;
startState.m_context = context;
startState.m_creatingFiber = creatingFiber;
startState.m_threadFunc = threadFunc;
void *fiber = CreateFiber(static_cast<SIZE_T>(stackSize), GpFiberStarter_Win32::FiberStartRoutine, &startState);
if (!fiber)
return nullptr;
SwitchToFiber(fiber);
return GpFiber_Win32::Create(fiber);
}

View File

@@ -1,37 +0,0 @@
#include "GpFiber_Win32.h"
#include <new>
GpFiber_Win32::GpFiber_Win32(LPVOID fiber)
: m_fiber(fiber)
{
}
void GpFiber_Win32::YieldTo(IGpFiber *toFiber)
{
SwitchToFiber(static_cast<GpFiber_Win32*>(toFiber)->m_fiber);
}
void GpFiber_Win32::YieldToTerminal(IGpFiber *toFiber)
{
YieldTo(toFiber);
}
void GpFiber_Win32::Destroy()
{
this->~GpFiber_Win32();
free(this);
}
GpFiber_Win32::~GpFiber_Win32()
{
DeleteFiber(m_fiber);
}
IGpFiber *GpFiber_Win32::Create(LPVOID fiber)
{
void *storage = malloc(sizeof(GpFiber_Win32));
if (!storage)
return nullptr;
return new (storage) GpFiber_Win32(fiber);
}

View File

@@ -1,26 +0,0 @@
#pragma once
#include "GpWindows.h"
#include "IGpFiber.h"
class GpFiber_Win32 final : public IGpFiber
{
public:
void YieldTo(IGpFiber *toFiber) override;
void YieldToTerminal(IGpFiber *toFiber) override;
void Destroy() override;
static IGpFiber *Create(LPVOID fiber);
LPVOID GetFiber() const;
private:
explicit GpFiber_Win32(LPVOID fiber);
~GpFiber_Win32();
LPVOID m_fiber;
};
inline LPVOID GpFiber_Win32::GetFiber() const
{
return m_fiber;
}

View File

@@ -158,7 +158,7 @@ GpFileSystem_Win32::GpFileSystem_Win32()
continue;
}
if (wcscat_s(m_executablePath, L"Resources"))
if (wcscat_s(m_executablePath, L"Packaged"))
{
currentPathLength = 0;
break;
@@ -177,7 +177,6 @@ GpFileSystem_Win32::GpFileSystem_Win32()
{
m_packagedDir = std::wstring(m_executablePath) + L"Packaged\\";
m_housesDir = std::wstring(m_executablePath) + L"Packaged\\Houses\\";
m_resourcesDir = std::wstring(m_executablePath) + L"Resources\\";
}
}
@@ -319,11 +318,6 @@ bool GpFileSystem_Win32::ValidateFilePathUnicodeChar(uint32_t c) const
return false;
}
void GpFileSystem_Win32::SetMainThreadRelay(IGpThreadRelay *relay)
{
(void)relay;
}
void GpFileSystem_Win32::SetDelayCallback(GpFileSystem_Win32::DelayCallback_t delayCallback)
{
}

View File

@@ -21,7 +21,6 @@ public:
bool ValidateFilePath(const char *path, size_t sz) const override;
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
void SetMainThreadRelay(IGpThreadRelay *relay) override;
void SetDelayCallback(DelayCallback_t delayCallback) override;
const wchar_t *GetBasePath() const;

View File

@@ -4,7 +4,6 @@
#include "GpColorCursor_Win32.h"
#include "GpDisplayDriverFactory.h"
#include "GpGlobalConfig.h"
#include "GpFiber_Win32.h"
#include "GpFileSystem_Win32.h"
#include "GpLogDriver_Win32.h"
#include "GpFontHandlerFactory.h"
@@ -28,7 +27,6 @@ GpWindowsGlobals g_gpWindowsGlobals;
extern "C" __declspec(dllimport) IGpAudioDriver *GpDriver_CreateAudioDriver_XAudio2(const GpAudioDriverProperties &properties);
extern "C" __declspec(dllimport) IGpDisplayDriver *GpDriver_CreateDisplayDriver_D3D11(const GpDisplayDriverProperties &properties);
extern "C" __declspec(dllimport) IGpInputDriver *GpDriver_CreateInputDriver_XInput(const GpInputDriverProperties &properties);
extern "C" __declspec(dllimport) IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties);
static void PostMouseEvent(IGpVOSEventQueue *eventQueue, GpMouseEventType_t eventType, GpMouseButton_t button, int32_t x, int32_t y, float pixelScaleX, float pixelScaleY)
{
@@ -430,7 +428,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
g_gpWindowsGlobals.m_hIcon = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_ICON1));
g_gpWindowsGlobals.m_hIconSm = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_ICON2));
g_gpWindowsGlobals.m_createFiberFunc = GpFiber_Win32::Create;
g_gpWindowsGlobals.m_createBWCursorFunc = GpBWCursor_Win32::Create;
g_gpWindowsGlobals.m_createColorCursorFunc = GpColorCursor_Win32::Create;
g_gpWindowsGlobals.m_translateWindowsMessageFunc = TranslateWindowsMessage;
@@ -439,7 +436,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
g_gpGlobalConfig.m_audioDriverType = EGpAudioDriverType_XAudio2;
g_gpGlobalConfig.m_fontHandlerType = EGpFontHandlerType_FreeType2;
g_gpGlobalConfig.m_fontHandlerType = EGpFontHandlerType_None;
EGpInputDriverType inputDrivers[] =
{
@@ -456,7 +453,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_D3D11, GpDriver_CreateDisplayDriver_D3D11);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_XAudio2, GpDriver_CreateAudioDriver_XAudio2);
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_XInput, GpDriver_CreateInputDriver_XInput);
GpFontHandlerFactory::RegisterFontHandlerFactory(EGpFontHandlerType_FreeType2, GpDriver_CreateFontHandler_FreeType2);
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Windows environment configured, starting up");

View File

@@ -15,8 +15,8 @@ android {
}
minSdkVersion 16
targetSdkVersion 29
versionCode 11
versionName "1.0.15"
versionCode 14
versionName "1.1.0"
externalNativeBuild {
ndkBuild {
arguments "APP_PLATFORM=android-16"

View File

@@ -1,4 +1,5 @@
AerofoilSDL
AerofoilPortable
Common
FreeType
GpApp

View File

@@ -1 +0,0 @@
../../../AerofoilPortable

View File

@@ -24,7 +24,7 @@ LOCAL_SRC_FILES := \
LOCAL_SHARED_LIBRARIES := SDL2
LOCAL_STATIC_LIBRARIES := GpShell GpFontHandler_FreeType2 AerofoilPortable AerofoilSDL GpApp
LOCAL_STATIC_LIBRARIES := GpShell AerofoilPortable AerofoilSDL GpApp
LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -llog

View File

@@ -450,7 +450,6 @@ bool GpFileSystem_Android::ResolvePath(PortabilityLayer::VirtualDirectory_t virt
GpFileSystem_Android::GpFileSystem_Android()
: m_activity(nullptr)
, m_relay(nullptr)
, m_delayCallback(nullptr)
, m_sourceExportMutex(nullptr)
, m_sourceExportFD(0)
@@ -680,25 +679,6 @@ bool GpFileSystem_Android::DeleteFile(PortabilityLayer::VirtualDirectory_t virtu
}
IGpDirectoryCursor *GpFileSystem_Android::ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *const *paths, size_t numPaths)
{
ScanDirectoryNestedContext ctx;
ctx.m_this = this;
ctx.m_returnValue = nullptr;
ctx.m_virtualDirectory = virtualDirectory;
ctx.m_paths = paths;
ctx.m_numPaths = numPaths;
m_relay->Invoke(ScanDirectoryNestedThunk, &ctx);
return ctx.m_returnValue;
}
void GpFileSystem_Android::ScanDirectoryNestedThunk(void *context)
{
ScanDirectoryNestedContext *ctx = static_cast<ScanDirectoryNestedContext*>(context);
ctx->m_returnValue = ctx->m_this->ScanDirectoryNestedInternal(ctx->m_virtualDirectory, ctx->m_paths, ctx->m_numPaths);
}
IGpDirectoryCursor *GpFileSystem_Android::ScanDirectoryNestedInternal(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *const *paths, size_t numPaths)
{
if (virtualDirectory == PortabilityLayer::VirtualDirectories::kGameData || virtualDirectory == PortabilityLayer::VirtualDirectories::kApplicationData)
return ScanAssetDirectory(virtualDirectory, paths, numPaths);
@@ -752,11 +732,6 @@ bool GpFileSystem_Android::ValidateFilePathUnicodeChar(uint32_t c) const
return false;
}
void GpFileSystem_Android::SetMainThreadRelay(IGpThreadRelay *relay)
{
m_relay = relay;
}
void GpFileSystem_Android::SetDelayCallback(DelayCallback_t delayCallback)
{
m_delayCallback = delayCallback;

View File

@@ -27,7 +27,6 @@ public:
bool ValidateFilePath(const char *path, size_t pathLen) const override;
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
void SetMainThreadRelay(IGpThreadRelay *relay) override;
void SetDelayCallback(DelayCallback_t delayCallback) override;
void PostSourceExportRequest(bool cancelled, int fd, jobject pfd);
@@ -36,26 +35,12 @@ public:
static GpFileSystem_Android *GetInstance();
private:
struct ScanDirectoryNestedContext
{
GpFileSystem_Android *m_this;
IGpDirectoryCursor *m_returnValue;
PortabilityLayer::VirtualDirectory_t m_virtualDirectory;
char const *const *m_paths;
size_t m_numPaths;
};
static void ScanDirectoryNestedThunk(void *context);
IGpDirectoryCursor *ScanDirectoryNestedInternal(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
IGpDirectoryCursor *ScanAssetDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
IGpDirectoryCursor *ScanStorageDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
bool OpenSourceExportFD(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, int &fd, jobject &pfd);
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution, bool &isAsset);
IGpThreadRelay *m_relay;
DelayCallback_t m_delayCallback;
jobject m_activity;

View File

@@ -4,7 +4,6 @@
#include "GpAudioDriverFactory.h"
#include "GpDisplayDriverFactory.h"
#include "GpGlobalConfig.h"
#include "GpFiber_SDL.h"
#include "GpFileSystem_Android.h"
#include "GpFontHandlerFactory.h"
#include "GpInputDriverFactory.h"
@@ -24,8 +23,6 @@
GpAndroidGlobals g_gpAndroidGlobals;
extern "C" IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties);
IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties);
IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties);
@@ -91,7 +88,7 @@ int main(int argc, char* argv[])
g_gpGlobalConfig.m_audioDriverType = EGpAudioDriverType_SDL2;
g_gpGlobalConfig.m_fontHandlerType = EGpFontHandlerType_FreeType2;
g_gpGlobalConfig.m_fontHandlerType = EGpFontHandlerType_None;
g_gpGlobalConfig.m_inputDriverTypes = nullptr;
g_gpGlobalConfig.m_numInputDrivers = 0;
@@ -102,7 +99,6 @@ int main(int argc, char* argv[])
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_SDL_GL2, GpDriver_CreateDisplayDriver_SDL_GL2);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_SDL2, GpDriver_CreateAudioDriver_SDL);
GpFontHandlerFactory::RegisterFontHandlerFactory(EGpFontHandlerType_FreeType2, GpDriver_CreateFontHandler_FreeType2);
int returnCode = GpMain::Run();

View File

@@ -11,12 +11,9 @@ mklink /D app\jni\SDL2 ..\..\..\SDL2-2.0.12
mklink /D app\jni\GpApp ..\..\..\GpApp
mklink /D app\jni\GpShell ..\..\..\GpShell
mklink /D app\jni\GpCommon ..\..\..\GpCommon
mklink /D app\jni\GpFontHandler_FreeType2 ..\..\..\GpFontHandler_FreeType2
mklink /D app\jni\PortabilityLayer ..\..\..\PortabilityLayer
mklink /D app\jni\FreeType ..\..\..\FreeType
mklink /D app\jni\rapidjson ..\..\..\rapidjson
mklink /D app\jni\MacRomanConversion ..\..\..\MacRomanConversion
mklink /D app\jni\stb ..\..\..\stb
mklink /D app\src\main\assets\Resources ..\..\..\..\..\Resources
pause

View File

@@ -8,11 +8,7 @@ rmdir app\jni\SDL2
rmdir app\jni\GpShell
rmdir app\jni\GpCommon
rmdir app\jni\GpApp
rmdir app\jni\GpFontHandler_FreeType2
rmdir app\jni\PortabilityLayer
rmdir app\jni\FreeType
rmdir app\jni\zlib
rmdir app\jni\rapidjson
rmdir app\jni\MacRomanConversion
rmdir app\jni\stb
rmdir app\src\main\assets\Resources

8
AerofoilPortable.props Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup />
<ItemGroup />
</Project>

View File

@@ -17,4 +17,5 @@ LOCAL_SRC_FILES := \
GpThreadEvent_Cpp11.cpp \
GpSystemServices_POSIX.cpp
include $(BUILD_STATIC_LIBRARY)

View File

@@ -3,7 +3,7 @@
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IncludePath>$(SolutionDir)SDL2-2.0.12\include;$(IncludePath)</IncludePath>
<IncludePath>$(SolutionDir)SDL2-2.0.12\include;$(SolutionDir)AerofoilPortable;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)SDL2-2.0.12\lib\x64;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup>

View File

@@ -93,8 +93,6 @@
<ClCompile Include="..\Aerofoil\GpThreadEvent_Win32.cpp" />
<ClCompile Include="GpAudioDriver_SDL2.cpp" />
<ClCompile Include="GpDisplayDriver_SDL_GL2.cpp" />
<ClCompile Include="GpFiberStarter_SDL.cpp" />
<ClCompile Include="GpFiber_SDL.cpp" />
<ClCompile Include="GpInputDriver_SDL_Gamepad.cpp" />
<ClCompile Include="GpMain_SDL_Win32.cpp" />
<ClCompile Include="ShaderCode\CopyQuadP.cpp" />

View File

@@ -48,12 +48,6 @@
<ClCompile Include="ShaderCode\ScaleQuadP.cpp">
<Filter>Source Files\ShaderCode</Filter>
</ClCompile>
<ClCompile Include="GpFiber_SDL.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpFiberStarter_SDL.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpDisplayDriver_SDL_GL2.cpp">
<Filter>Source Files</Filter>
</ClCompile>

View File

@@ -0,0 +1,8 @@
#include "GpAudioDriver_SDL2.cpp"
#include "GpDisplayDriver_SDL_GL2.cpp"
#include "GpInputDriver_SDL_Gamepad.cpp"
#include "ShaderCode/CopyQuadP.cpp"
#include "ShaderCode/DrawQuadPaletteP.cpp"
#include "ShaderCode/DrawQuad32P.cpp"
#include "ShaderCode/DrawQuadV.cpp"
#include "ShaderCode/ScaleQuadP.cpp"

View File

@@ -11,6 +11,7 @@ LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/../GpShell \
$(LOCAL_PATH)/../Common \
$(LOCAL_PATH)/../PortabilityLayer \
$(LOCAL_PATH)/../AerofoilPortable \
$(LOCAL_PATH)/$(SDL_PATH)/include
LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0
@@ -19,8 +20,6 @@ LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0
LOCAL_SRC_FILES := \
GpAudioDriver_SDL2.cpp \
GpDisplayDriver_SDL_GL2.cpp \
GpFiber_SDL.cpp \
GpFiberStarter_SDL.cpp \
ShaderCode/CopyQuadP.cpp \
ShaderCode/DrawQuadPaletteP.cpp \
ShaderCode/DrawQuad32P.cpp \

View File

@@ -1,3 +1,4 @@
#include "CoreDefs.h"
#include "IGpAudioDriver.h"
#include "IGpAudioChannel.h"
#include "IGpAudioChannelCallbacks.h"
@@ -5,8 +6,7 @@
#include "IGpPrefsHandler.h"
#include "IGpSystemServices.h"
#include "GpAudioDriverProperties.h"
#include "CoreDefs.h"
#include "GpSDL.h"
#include "SDL_audio.h"
#include "GpRingBuffer.h"
@@ -437,7 +437,7 @@ bool GpAudioDriver_SDL2::Init()
requestedSpec.channels = 1;
requestedSpec.format = AUDIO_S16;
requestedSpec.freq = m_properties.m_sampleRate;
requestedSpec.samples = 512;
requestedSpec.samples = 1024;
requestedSpec.userdata = this;
if (SDL_OpenAudio(&requestedSpec, nullptr))

View File

@@ -1,12 +1,13 @@
#include "IGpDisplayDriver.h"
#include "CoreDefs.h"
#include "GpApplicationName.h"
#include "GpComPtr.h"
#include "GpFiber_SDL.h"
#include "GpDisplayDriverProperties.h"
#include "GpVOSEvent.h"
#include "GpRingBuffer.h"
#include "GpInputDriver_SDL_Gamepad.h"
#include "GpSDL.h"
#include "IGpCursor.h"
#include "IGpDisplayDriverSurface.h"
#include "IGpLogDriver.h"
@@ -28,6 +29,9 @@
#include <vector>
#include <algorithm>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#pragma push_macro("LoadCursor")
#ifdef LoadCursor
@@ -214,6 +218,7 @@ struct GpGLFunctions
static void CheckGLError(const GpGLFunctions &gl, IGpLogDriver *logger)
{
#if GP_DEBUG_CONFIG
GLenum errorCode = gl.GetError();
if (errorCode != 0)
{
@@ -222,6 +227,7 @@ static void CheckGLError(const GpGLFunctions &gl, IGpLogDriver *logger)
}
assert(errorCode == 0);
#endif
}
class GpGLObject
@@ -729,17 +735,18 @@ public:
explicit GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties);
~GpDisplayDriver_SDL_GL2();
bool Init();
bool Init() GP_ASYNCIFY_PARANOID_OVERRIDE;
void ServeTicks(int tickCount) GP_ASYNCIFY_PARANOID_OVERRIDE;
void ForceSync() override;
void Shutdown() GP_ASYNCIFY_PARANOID_OVERRIDE;
void TranslateSDLMessage(const SDL_Event *msg, IGpVOSEventQueue *eventQueue, float pixelScaleX, float pixelScaleY, bool obstructiveTextInput);
void Run() override;
void Shutdown() override;
void GetInitialDisplayResolution(unsigned int *width, unsigned int *height) override;
IGpDisplayDriverSurface *CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat, SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext) override;
void DrawSurface(IGpDisplayDriverSurface *surface, int32_t x, int32_t y, size_t width, size_t height, const GpDisplayDriverSurfaceEffects *effects) override;
IGpCursor *CreateBWCursor(size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY) override;
IGpCursor *CreateColorCursor(size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY) override;
IGpCursor *CreateBWCursor(size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY) GP_ASYNCIFY_PARANOID_OVERRIDE;
IGpCursor *CreateColorCursor(size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY) GP_ASYNCIFY_PARANOID_OVERRIDE;
void SetCursor(IGpCursor *cursor) override;
void SetStandardCursor(EGpStandardCursor_t standardCursor) override;
void UpdatePalette(const void *paletteData) override;
@@ -797,7 +804,7 @@ private:
void ScaleVirtualScreen();
GpDisplayDriverTickStatus_t PresentFrameAndSync();
bool SyncRender();
GpGLFunctions m_gl;
GpDisplayDriverProperties m_properties;
@@ -906,9 +913,6 @@ private:
EGpStandardCursor_t m_pendingStandardCursor;
bool m_mouseIsInClientArea;
IGpFiber *m_vosFiber;
IGpThreadEvent *m_vosEvent;
float m_bgColor[4];
bool m_bgIsDark;
@@ -1193,8 +1197,6 @@ GpDisplayDriver_SDL_GL2::GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties
, m_pixelScaleX(1.0f)
, m_pixelScaleY(1.0f)
, m_useUpscaleFilter(false)
, m_vosFiber(nullptr)
, m_vosEvent(nullptr)
, m_pendingCursor(nullptr)
, m_activeCursor(nullptr)
, m_currentStandardCursor(EGpStandardCursors::kArrow)
@@ -1339,9 +1341,247 @@ GpDisplayDriver_SDL_GL2::~GpDisplayDriver_SDL_GL2()
bool GpDisplayDriver_SDL_GL2::Init()
{
#if GP_GL_IS_OPENGL_4_CONTEXT
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
#else
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
#endif
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
IGpLogDriver *logger = m_properties.m_logger;
uint32_t windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
if (m_properties.m_systemServices->IsFullscreenOnStartup())
{
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
m_isFullScreen = true;
}
else
windowFlags |= SDL_WINDOW_RESIZABLE;
m_window = SDL_CreateWindow(GP_APPLICATION_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, m_windowWidthPhysical, m_windowHeightPhysical, windowFlags);
if (m_isFullScreen)
{
m_windowModeRevertWidth = m_windowWidthPhysical;
m_windowModeRevertHeight = m_windowHeightPhysical;
int windowWidth = 0;
int windowHeight = 0;
SDL_GetWindowSize(m_window, &windowWidth, &windowHeight);
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Initialized fullscreen SDL window %i x %i", windowWidth, windowHeight);
m_windowWidthPhysical = windowWidth;
m_windowHeightPhysical = windowHeight;
uint32_t desiredWidth = windowWidth;
uint32_t desiredHeight = windowHeight;
uint32_t virtualWidth = m_windowWidthVirtual;
uint32_t virtualHeight = m_windowHeightVirtual;
float pixelScaleX = m_pixelScaleX;
float pixelScaleY = m_pixelScaleY;
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
{
m_windowWidthVirtual = virtualWidth;
m_windowHeightVirtual = virtualHeight;
m_pixelScaleX = pixelScaleX;
m_pixelScaleY = pixelScaleY;
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "AdjustedRequestedResolution succeeded. Virtual dimensions %i x %i Pixel scale %f x %f", static_cast<int>(virtualWidth), static_cast<int>(virtualHeight), static_cast<float>(pixelScaleX), static_cast<float>(pixelScaleY));
}
else
{
if (logger)
logger->Printf(IGpLogDriver::Category_Error, "AdjustedRequestedResolution failed!");
}
}
const bool obstructiveTextInput = m_properties.m_systemServices->IsTextInputObstructive();
if (!obstructiveTextInput)
SDL_StartTextInput();
StartOpenGLForWindow(logger);
if (!m_gl.LookUpFunctions())
return false;
m_initialWidthVirtual = m_windowWidthVirtual;
m_initialHeightVirtual = m_windowHeightVirtual;
return true;
}
void GpDisplayDriver_SDL_GL2::ServeTicks(int ticks)
{
IGpLogDriver *logger = m_properties.m_logger;
const bool obstructiveTextInput = m_properties.m_systemServices->IsTextInputObstructive();
for (;;)
{
SDL_Event msg;
if (SDL_PollEvent(&msg) != 0)
{
switch (msg.type)
{
case SDL_MOUSEMOTION:
{
if (!m_mouseIsInClientArea)
m_mouseIsInClientArea = true;
}
break;
//case SDL_MOUSELEAVE: // Does SDL support this??
// m_mouseIsInClientArea = false;
// break;
case SDL_RENDER_DEVICE_RESET:
case SDL_RENDER_TARGETS_RESET:
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to device loss (Type: %i)", static_cast<int>(msg.type));
m_contextLost = true;
}
break;
case SDL_CONTROLLERAXISMOTION:
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
case SDL_CONTROLLERDEVICEADDED:
case SDL_CONTROLLERDEVICEREMOVED:
case SDL_CONTROLLERDEVICEREMAPPED:
if (IGpInputDriverSDLGamepad *gamepadDriver = IGpInputDriverSDLGamepad::GetInstance())
gamepadDriver->ProcessSDLEvent(msg);
break;
}
TranslateSDLMessage(&msg, m_properties.m_eventQueue, m_pixelScaleX, m_pixelScaleY, obstructiveTextInput);
}
else
{
if (m_isFullScreen != m_isFullScreenDesired)
{
if (m_isFullScreenDesired)
BecomeFullScreen();
else
BecomeWindowed();
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to fullscreen state change");
m_contextLost = true;
continue;
}
int clientWidth = 0;
int clientHeight = 0;
SDL_GetWindowSize(m_window, &clientWidth, &clientHeight);
unsigned int desiredWidth = clientWidth;
unsigned int desiredHeight = clientHeight;
if (desiredWidth != m_windowWidthPhysical || desiredHeight != m_windowHeightPhysical || m_isResolutionResetDesired)
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Detected window size change");
uint32_t prevWidthPhysical = m_windowWidthPhysical;
uint32_t prevHeightPhysical = m_windowHeightPhysical;
uint32_t prevWidthVirtual = m_windowWidthVirtual;
uint32_t prevHeightVirtual = m_windowHeightVirtual;
uint32_t virtualWidth = m_windowWidthVirtual;
uint32_t virtualHeight = m_windowHeightVirtual;
float pixelScaleX = 1.0f;
float pixelScaleY = 1.0f;
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
{
bool resizedOK = ResizeOpenGLWindow(m_windowWidthPhysical, m_windowHeightPhysical, desiredWidth, desiredHeight, logger);
if (!resizedOK)
break; // Critical video driver error, exit
m_windowWidthVirtual = virtualWidth;
m_windowHeightVirtual = virtualHeight;
m_pixelScaleX = pixelScaleX;
m_pixelScaleY = pixelScaleY;
m_isResolutionResetDesired = false;
if (GpVOSEvent *resizeEvent = m_properties.m_eventQueue->QueueEvent())
{
resizeEvent->m_eventType = GpVOSEventTypes::kVideoResolutionChanged;
resizeEvent->m_event.m_resolutionChangedEvent.m_prevWidth = prevWidthVirtual;
resizeEvent->m_event.m_resolutionChangedEvent.m_prevHeight = prevHeightVirtual;
resizeEvent->m_event.m_resolutionChangedEvent.m_newWidth = m_windowWidthVirtual;
resizeEvent->m_event.m_resolutionChangedEvent.m_newHeight = m_windowHeightVirtual;
}
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to window size change");
m_contextLost = true;
continue;
}
}
if (m_contextLost)
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Resetting OpenGL context. Physical: %i x %i Virtual %i x %i", static_cast<int>(m_windowWidthPhysical), static_cast<int>(m_windowHeightPhysical), static_cast<int>(m_windowWidthVirtual), static_cast<int>(m_windowHeightVirtual));
// Drop everything and reset
m_res.~InstancedResources();
new (&m_res) InstancedResources();
if (m_firstSurface)
m_firstSurface->DestroyAll();
if (!InitResources(m_windowWidthPhysical, m_windowHeightPhysical, m_windowWidthVirtual, m_windowHeightVirtual))
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Terminating display driver due to InitResources failing");
break;
}
if (m_firstSurface)
m_firstSurface->RecreateAll();
m_contextLost = false;
continue;
}
bool wantTextInput = m_properties.m_systemServices->IsTextInputEnabled();
if (wantTextInput != m_textInputEnabled)
{
m_textInputEnabled = wantTextInput;
if (m_textInputEnabled)
SDL_StartTextInput();
else
SDL_StopTextInput();
}
// Handle dismissal of on-screen keyboard
const bool isTextInputActuallyActive = SDL_IsTextInputActive();
m_textInputEnabled = isTextInputActuallyActive;
m_properties.m_systemServices->SetTextInputEnabled(isTextInputActuallyActive);
if (SyncRender())
{
ticks--;
if (ticks <= 0)
break;
}
}
}
}
void GpDisplayDriver_SDL_GL2::ForceSync()
{
m_frameTimeAccumulated = std::chrono::nanoseconds::zero();
}
static void PostMouseEvent(IGpVOSEventQueue *eventQueue, GpMouseEventType_t eventType, GpMouseButton_t button, int32_t x, int32_t y, float pixelScaleX, float pixelScaleY)
{
if (GpVOSEvent *evt = eventQueue->QueueEvent())
@@ -1379,7 +1619,7 @@ static void PostTouchEvent(IGpVOSEventQueue *eventQueue, GpTouchEventType_t even
static bool IdentifyVKey(const SDL_KeyboardEvent *keyEvt, GpKeyIDSubset_t &outSubset, GpKeyboardInputEvent::KeyUnion &outKey)
{
SDL_KeyCode keyCode = static_cast<SDL_KeyCode>(keyEvt->keysym.sym);
SDL_Keycode keyCode = static_cast<SDL_Keycode>(keyEvt->keysym.sym);
switch (keyCode)
{
@@ -1835,248 +2075,6 @@ void GpDisplayDriver_SDL_GL2::TranslateSDLMessage(const SDL_Event *msg, IGpVOSEv
}
}
void GpDisplayDriver_SDL_GL2::Run()
{
#if GP_GL_IS_OPENGL_4_CONTEXT
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
#else
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
#endif
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
IGpLogDriver *logger = m_properties.m_logger;
m_vosEvent = m_properties.m_systemServices->CreateThreadEvent(true, false);
m_vosFiber = new GpFiber_SDL(nullptr, m_vosEvent);
uint32_t windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
if (m_properties.m_systemServices->IsFullscreenOnStartup())
{
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
m_isFullScreen = true;
}
else
windowFlags |= SDL_WINDOW_RESIZABLE;
m_window = SDL_CreateWindow(GP_APPLICATION_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, m_windowWidthPhysical, m_windowHeightPhysical, windowFlags);
if (m_isFullScreen)
{
m_windowModeRevertWidth = m_windowWidthPhysical;
m_windowModeRevertHeight = m_windowHeightPhysical;
int windowWidth = 0;
int windowHeight = 0;
SDL_GetWindowSize(m_window, &windowWidth, &windowHeight);
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Initialized fullscreen SDL window %i x %i", windowWidth, windowHeight);
m_windowWidthPhysical = windowWidth;
m_windowHeightPhysical = windowHeight;
uint32_t desiredWidth = windowWidth;
uint32_t desiredHeight = windowHeight;
uint32_t virtualWidth = m_windowWidthVirtual;
uint32_t virtualHeight = m_windowHeightVirtual;
float pixelScaleX = m_pixelScaleX;
float pixelScaleY = m_pixelScaleY;
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
{
m_windowWidthVirtual = virtualWidth;
m_windowHeightVirtual = virtualHeight;
m_pixelScaleX = pixelScaleX;
m_pixelScaleY = pixelScaleY;
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "AdjustedRequestedResolution succeeded. Virtual dimensions %i x %i Pixel scale %f x %f", static_cast<int>(virtualWidth), static_cast<int>(virtualHeight), static_cast<float>(pixelScaleX), static_cast<float>(pixelScaleY));
}
else
{
if (logger)
logger->Printf(IGpLogDriver::Category_Error, "AdjustedRequestedResolution failed!");
}
}
const bool obstructiveTextInput = m_properties.m_systemServices->IsTextInputObstructive();
if (!obstructiveTextInput)
SDL_StartTextInput();
StartOpenGLForWindow(logger);
if (!m_gl.LookUpFunctions())
return;
m_initialWidthVirtual = m_windowWidthVirtual;
m_initialHeightVirtual = m_windowHeightVirtual;
for (;;)
{
SDL_Event msg;
if (SDL_PollEvent(&msg) != 0)
{
switch (msg.type)
{
case SDL_MOUSEMOTION:
{
if (!m_mouseIsInClientArea)
m_mouseIsInClientArea = true;
}
break;
//case SDL_MOUSELEAVE: // Does SDL support this??
// m_mouseIsInClientArea = false;
// break;
case SDL_RENDER_DEVICE_RESET:
case SDL_RENDER_TARGETS_RESET:
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to device loss (Type: %i)", static_cast<int>(msg.type));
m_contextLost = true;
}
break;
case SDL_CONTROLLERAXISMOTION:
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
case SDL_CONTROLLERDEVICEADDED:
case SDL_CONTROLLERDEVICEREMOVED:
case SDL_CONTROLLERDEVICEREMAPPED:
if (IGpInputDriverSDLGamepad *gamepadDriver = IGpInputDriverSDLGamepad::GetInstance())
gamepadDriver->ProcessSDLEvent(msg);
break;
}
TranslateSDLMessage(&msg, m_properties.m_eventQueue, m_pixelScaleX, m_pixelScaleY, obstructiveTextInput);
}
else
{
if (m_isFullScreen != m_isFullScreenDesired)
{
if (m_isFullScreenDesired)
BecomeFullScreen();
else
BecomeWindowed();
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to fullscreen state change");
m_contextLost = true;
continue;
}
int clientWidth = 0;
int clientHeight = 0;
SDL_GetWindowSize(m_window, &clientWidth, &clientHeight);
unsigned int desiredWidth = clientWidth;
unsigned int desiredHeight = clientHeight;
if (desiredWidth != m_windowWidthPhysical || desiredHeight != m_windowHeightPhysical || m_isResolutionResetDesired)
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Detected window size change");
uint32_t prevWidthPhysical = m_windowWidthPhysical;
uint32_t prevHeightPhysical = m_windowHeightPhysical;
uint32_t prevWidthVirtual = m_windowWidthVirtual;
uint32_t prevHeightVirtual = m_windowHeightVirtual;
uint32_t virtualWidth = m_windowWidthVirtual;
uint32_t virtualHeight = m_windowHeightVirtual;
float pixelScaleX = 1.0f;
float pixelScaleY = 1.0f;
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
{
bool resizedOK = ResizeOpenGLWindow(m_windowWidthPhysical, m_windowHeightPhysical, desiredWidth, desiredHeight, logger);
if (!resizedOK)
break; // Critical video driver error, exit
m_windowWidthVirtual = virtualWidth;
m_windowHeightVirtual = virtualHeight;
m_pixelScaleX = pixelScaleX;
m_pixelScaleY = pixelScaleY;
m_isResolutionResetDesired = false;
if (GpVOSEvent *resizeEvent = m_properties.m_eventQueue->QueueEvent())
{
resizeEvent->m_eventType = GpVOSEventTypes::kVideoResolutionChanged;
resizeEvent->m_event.m_resolutionChangedEvent.m_prevWidth = prevWidthVirtual;
resizeEvent->m_event.m_resolutionChangedEvent.m_prevHeight = prevHeightVirtual;
resizeEvent->m_event.m_resolutionChangedEvent.m_newWidth = m_windowWidthVirtual;
resizeEvent->m_event.m_resolutionChangedEvent.m_newHeight = m_windowHeightVirtual;
}
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to window size change");
m_contextLost = true;
continue;
}
}
if (m_contextLost)
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Resetting OpenGL context. Physical: %i x %i Virtual %i x %i", static_cast<int>(m_windowWidthPhysical), static_cast<int>(m_windowHeightPhysical), static_cast<int>(m_windowWidthVirtual), static_cast<int>(m_windowHeightVirtual));
// Drop everything and reset
m_res.~InstancedResources();
new (&m_res) InstancedResources();
if (m_firstSurface)
m_firstSurface->DestroyAll();
if (!InitResources(m_windowWidthPhysical, m_windowHeightPhysical, m_windowWidthVirtual, m_windowHeightVirtual))
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Terminating display driver due to InitResources failing");
break;
}
if (m_firstSurface)
m_firstSurface->RecreateAll();
m_contextLost = false;
continue;
}
bool wantTextInput = m_properties.m_systemServices->IsTextInputEnabled();
if (wantTextInput != m_textInputEnabled)
{
m_textInputEnabled = wantTextInput;
if (m_textInputEnabled)
SDL_StartTextInput();
else
SDL_StopTextInput();
}
// Handle dismissal of on-screen keyboard
const bool isTextInputActuallyActive = SDL_IsTextInputActive();
m_textInputEnabled = isTextInputActuallyActive;
m_properties.m_systemServices->SetTextInputEnabled(isTextInputActuallyActive);
GpDisplayDriverTickStatus_t tickStatus = PresentFrameAndSync();
if (tickStatus == GpDisplayDriverTickStatuses::kFatalFault || tickStatus == GpDisplayDriverTickStatuses::kApplicationTerminated)
{
if (logger)
{
if (tickStatus == GpDisplayDriverTickStatuses::kFatalFault)
logger->Printf(IGpLogDriver::Category_Information, "Terminating display driver due to fatal fault");
if (tickStatus == GpDisplayDriverTickStatuses::kApplicationTerminated)
logger->Printf(IGpLogDriver::Category_Information, "Terminating display driver due to application termination");
}
break;
}
}
}
// Exit
}
void GpDisplayDriver_SDL_GL2::Shutdown()
{
this->~GpDisplayDriver_SDL_GL2();
@@ -3058,8 +3056,15 @@ bool GpDisplayDriver_SDL_GL2::BlitQuadProgram::Link(GpDisplayDriver_SDL_GL2 *dri
return true;
}
GpDisplayDriverTickStatus_t GpDisplayDriver_SDL_GL2::PresentFrameAndSync()
bool GpDisplayDriver_SDL_GL2::SyncRender()
{
if (m_frameTimeAccumulated >= m_frameTimeSliceSize)
{
m_frameTimeAccumulated -= m_frameTimeSliceSize;
return true;
}
SynchronizeCursors();
float bgColor[4];
@@ -3091,6 +3096,10 @@ GpDisplayDriverTickStatus_t GpDisplayDriver_SDL_GL2::PresentFrameAndSync()
SDL_GL_SwapWindow(m_window);
#ifdef __EMSCRIPTEN__
emscripten_sleep(1);
#endif
std::chrono::time_point<std::chrono::high_resolution_clock>::duration syncTime = std::chrono::high_resolution_clock::now().time_since_epoch();
const intmax_t periodNum = std::chrono::high_resolution_clock::period::num;
const intmax_t periodDen = std::chrono::high_resolution_clock::period::den;
@@ -3181,22 +3190,9 @@ GpDisplayDriverTickStatus_t GpDisplayDriver_SDL_GL2::PresentFrameAndSync()
}
m_frameTimeAccumulated += frameTimeStep;
while (m_frameTimeAccumulated >= m_frameTimeSliceSize)
{
GpDisplayDriverTickStatus_t tickStatus = m_properties.m_tickFunc(m_properties.m_tickFuncContext, m_vosFiber);
m_frameTimeAccumulated -= m_frameTimeSliceSize;
if (tickStatus == GpDisplayDriverTickStatuses::kSynchronizing)
{
m_frameTimeAccumulated = std::chrono::high_resolution_clock::duration::zero();
break;
}
else if (tickStatus != GpDisplayDriverTickStatuses::kOK)
return tickStatus;
}
}
return GpDisplayDriverTickStatuses::kOK;
return false;
}
IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties)
@@ -3205,18 +3201,9 @@ IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProp
if (!driver)
return nullptr;
new (driver) GpDisplayDriver_SDL_GL2(properties);
if (!driver->Init())
{
driver->Shutdown();
return nullptr;
}
return driver;
return new (driver) GpDisplayDriver_SDL_GL2(properties);
}
template<class T>
T *GpGLObjectImpl<T>::Create(GpDisplayDriver_SDL_GL2 *driver)
{
@@ -3237,4 +3224,33 @@ T *GpGLObjectImpl<T>::Create(GpDisplayDriver_SDL_GL2 *driver)
return obj;
}
#if GP_ASYNCIFY_PARANOID
bool IGpDisplayDriver::Init()
{
return static_cast<GpDisplayDriver_SDL_GL2*>(this)->Init();
}
void IGpDisplayDriver::ServeTicks(int tickCount)
{
static_cast<GpDisplayDriver_SDL_GL2*>(this)->ServeTicks(tickCount);
}
void IGpDisplayDriver::Shutdown()
{
static_cast<GpDisplayDriver_SDL_GL2*>(this)->Shutdown();
}
IGpCursor *IGpDisplayDriver::CreateBWCursor(size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY)
{
return static_cast<GpDisplayDriver_SDL_GL2*>(this)->CreateBWCursor(width, height, pixelData, maskData, hotSpotX, hotSpotY);
}
IGpCursor *IGpDisplayDriver::CreateColorCursor(size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY)
{
return static_cast<GpDisplayDriver_SDL_GL2*>(this)->CreateColorCursor(width, height, pixelDataRGBA, hotSpotX, hotSpotY);
}
#endif
#pragma pop_macro("LoadCursor")

View File

@@ -1,70 +0,0 @@
#include "GpFiberStarter.h"
#include "GpFiber_SDL.h"
#include "IGpSystemServices.h"
#include "IGpThreadEvent.h"
#include "SDL_thread.h"
#include <assert.h>
namespace GpFiberStarter_SDL
{
struct FiberStartState
{
GpFiberStarter::ThreadFunc_t m_threadFunc;
IGpThreadEvent *m_creatingReturnEvent;
IGpThreadEvent *m_creatingWakeEvent;
void *m_context;
};
static int SDLCALL FiberStartRoutine(void *lpThreadParameter)
{
const FiberStartState *tss = static_cast<const FiberStartState*>(lpThreadParameter);
GpFiberStarter::ThreadFunc_t threadFunc = tss->m_threadFunc;
IGpThreadEvent *creatingReturnEvent = tss->m_creatingReturnEvent;
IGpThreadEvent *wakeEvent = tss->m_creatingWakeEvent;
void *context = tss->m_context;
creatingReturnEvent->Signal();
wakeEvent->Wait();
threadFunc(context);
return 0;
}
}
IGpFiber *GpFiberStarter::StartFiber(IGpSystemServices *systemServices, ThreadFunc_t threadFunc, void *context, IGpFiber *creatingFiber)
{
IGpThreadEvent *returnEvent = systemServices->CreateThreadEvent(true, false);
if (!returnEvent)
return nullptr;
IGpThreadEvent *wakeEvent = systemServices->CreateThreadEvent(true, false);
if (!wakeEvent)
{
returnEvent->Destroy();
return nullptr;
}
GpFiberStarter_SDL::FiberStartState startState;
startState.m_context = context;
startState.m_creatingReturnEvent = returnEvent;
startState.m_creatingWakeEvent = wakeEvent;
startState.m_threadFunc = threadFunc;
SDL_Thread *thread = SDL_CreateThread(GpFiberStarter_SDL::FiberStartRoutine, "Fiber", &startState);
if (!thread)
{
returnEvent->Destroy();
wakeEvent->Destroy();
return nullptr;
}
returnEvent->Wait();
returnEvent->Destroy();
return new GpFiber_SDL(thread, wakeEvent);
}

View File

@@ -1,29 +0,0 @@
#include "GpFiber_SDL.h"
#include "IGpThreadEvent.h"
GpFiber_SDL::GpFiber_SDL(SDL_Thread *thread, IGpThreadEvent *threadEvent)
: m_event(threadEvent)
, m_thread(thread)
{
}
GpFiber_SDL::~GpFiber_SDL()
{
m_event->Destroy();
}
void GpFiber_SDL::YieldTo(IGpFiber *toFiber)
{
static_cast<GpFiber_SDL*>(toFiber)->m_event->Signal();
m_event->Wait();
}
void GpFiber_SDL::YieldToTerminal(IGpFiber *toFiber)
{
static_cast<GpFiber_SDL*>(toFiber)->m_event->Signal();
}
void GpFiber_SDL::Destroy()
{
delete this;
}

View File

@@ -1,24 +0,0 @@
#pragma once
#include "IGpFiber.h"
#include "SDL_thread.h"
struct IGpThreadEvent;
class GpFiber_SDL final : public IGpFiber
{
public:
explicit GpFiber_SDL(SDL_Thread *thread, IGpThreadEvent *threadEvent);
~GpFiber_SDL();
void YieldTo(IGpFiber *fromFiber) override;
void YieldToTerminal(IGpFiber *fromFiber) override;
void Destroy() override;
private:
static int SDLCALL InternalThreadFunction(void *data);
bool m_isDestroying;
IGpThreadEvent *m_event;
SDL_Thread *m_thread;
};

View File

@@ -1,6 +1,5 @@
#include "GpInputDriver_SDL_Gamepad.h"
#include "GpVOSEvent.h"
#include "GpWindows.h"
#include "IGpVOSEventQueue.h"
#include "SDL_events.h"

View File

@@ -4,8 +4,6 @@
#include "GpAudioDriverFactory.h"
#include "GpDisplayDriverFactory.h"
#include "GpGlobalConfig.h"
#include "GpFiber_Win32.h"
#include "GpFiber_SDL.h"
#include "GpFileSystem_Win32.h"
#include "GpLogDriver_Win32.h"
#include "GpFontHandlerFactory.h"

5
AerofoilSDL/GpSDL.h Normal file
View File

@@ -0,0 +1,5 @@
#ifdef __CYGWIN__
#define GP_SDL_DIRECTORY_PREFIX "SDL2/"
#else
#define GP_SDL_DIRECTORY_PREFIX
#endif

3
AerofoilWeb/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
obj
res
bin

View File

@@ -0,0 +1,4 @@
#include "GpFileSystem_Web.cpp"
#include "GpLogDriver_Web.cpp"
#include "GpMain_SDL_Web.cpp"
#include "GpSystemServices_Web.cpp"

View File

@@ -0,0 +1,15 @@
#include <stdint.h>
#include "GpFileSystem_Web_Resources.h"
namespace GpFileSystem_Web_Resources
{
namespace ApplicationData
{
#include "res/ApplicationData.h"
}
namespace GameData
{
#include "res/GameData.h"
}
}

View File

@@ -0,0 +1,7 @@
set INPUT_DIR=../AerofoilSDL
set OUTPUT_DIR=obj
set FLAGS=-s USE_SDL=2 -flto -I../GpCommon/ -I../PortabilityLayer/ -I../Common/ -s ASYNCIFY -O3 -DGP_DEBUG_CONFIG=0
emcc -c %INPUT_DIR%/AerofoilSDL_Combined.cpp -o %OUTPUT_DIR%/AerofoilSDL_Combined.o %FLAGS%
pause

View File

@@ -0,0 +1,7 @@
set INPUT_DIR=.
set OUTPUT_DIR=obj
set FLAGS=-s USE_SDL=2 -flto -I../GpCommon/ -I../PortabilityLayer/ -I../Common/ -I../GpShell/ -s ASYNCIFY -O3 -DGP_DEBUG_CONFIG=0
emcc -c %INPUT_DIR%/AerofoilWeb_Combined.cpp -o %OUTPUT_DIR%/AerofoilWeb_Combined.o %FLAGS%
pause

View File

@@ -0,0 +1,7 @@
set INPUT_DIR=../GpApp
set OUTPUT_DIR=obj
set FLAGS=-s USE_SDL=2 -flto -I../GpCommon/ -I../PortabilityLayer/ -I../Common/ -s ASYNCIFY -O3 -DGP_DEBUG_CONFIG=0
emcc -c %INPUT_DIR%/GpApp_Combined.cpp -o %OUTPUT_DIR%/GpApp_Combined.o %FLAGS%
pause

View File

@@ -0,0 +1,7 @@
set INPUT_DIR=../GpShell
set OUTPUT_DIR=obj
set FLAGS=-s USE_SDL=2 -flto -I../GpCommon/ -I../PortabilityLayer/ -I../Common/ -s ASYNCIFY -O3 -DGP_DEBUG_CONFIG=0
emcc -c %INPUT_DIR%/GpShell_Combined.cpp -o %OUTPUT_DIR%/GpShell_Combined.o %FLAGS%
pause

View File

@@ -0,0 +1,7 @@
set INPUT_DIR=../MacRomanConversion
set OUTPUT_DIR=obj
set FLAGS=-flto -I../MacRomanConversion/ -s ASYNCIFY -O3
emcc -c %INPUT_DIR%/MacRomanConversion.cpp -o %OUTPUT_DIR%/MacRomanConversion.o %FLAGS%
pause

View File

@@ -0,0 +1,7 @@
set INPUT_DIR=../PortabilityLayer
set OUTPUT_DIR=obj
set FLAGS=-s USE_ZLIB=1 -flto -I../GpCommon/ -I../Common/ -I../PortabilityLayer/ -I../rapidjson/include/ -I../MacRomanConversion/ -I../stb/ -s ASYNCIFY -O3 -DGP_DEBUG_CONFIG=0 -Wno-tautological-constant-out-of-range-compare
emcc -c %INPUT_DIR%/PortabilityLayer_Combined.cpp -o %OUTPUT_DIR%/PortabilityLayer_Combined.o %FLAGS%
pause

View File

@@ -0,0 +1,10 @@
..\x64\Release\bin2h.exe ..\Packaged res\ApplicationData.h
..\x64\Release\bin2h.exe ..\Packaged\Houses res\GameData.h
set INPUT_DIR=.
set OUTPUT_DIR=obj
set FLAGS=-flto -O3 -DGP_DEBUG_CONFIG=0
emcc -c %INPUT_DIR%/AerofoilWeb_Resources.cpp -o %OUTPUT_DIR%/AerofoilWeb_Resources.o %FLAGS%
pause

View File

@@ -0,0 +1,626 @@
#define _LARGEFILE64_SOURCE
#include "GpFileSystem_Web.h"
#include "GpIOStream.h"
#include "IGpDirectoryCursor.h"
#include "IGpSystemServices.h"
#include "IGpMutex.h"
#include "VirtualDirectory.h"
#include "PLDrivers.h"
#include "SDL2/SDL.h"
#include "SDL2/SDL_rwops.h"
#include <string>
#include <vector>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <dirent.h>
#include "UTF8.h"
#if defined(__CYGWIN__) || defined(__EMSCRIPTEN__)
typedef off_t off64_t;
#define fstat64 fstat
#define fseek64 fseek
#define ftruncate64 ftruncate
#define stat64 stat
#endif
class GpFileStream_Web_StaticMemFile final : public GpIOStream
{
public:
GpFileStream_Web_StaticMemFile(const unsigned char *bytes, size_t size);
~GpFileStream_Web_StaticMemFile();
size_t Read(void *bytesOut, size_t size) override;
size_t Write(const void *bytes, size_t size) override;
bool IsSeekable() const override;
bool IsReadOnly() const override;
bool IsWriteOnly() const override;
bool SeekStart(GpUFilePos_t loc) override;
bool SeekCurrent(GpFilePos_t loc) override;
bool SeekEnd(GpUFilePos_t loc) override;
GpUFilePos_t Size() const override;
GpUFilePos_t Tell() const override;
void Close() override;
void Flush() override;
private:
const unsigned char *m_bytes;
size_t m_offset;
size_t m_size;
};
GpFileStream_Web_StaticMemFile::GpFileStream_Web_StaticMemFile(const unsigned char *bytes, size_t size)
: m_bytes(bytes)
, m_size(size)
, m_offset(0)
{
}
GpFileStream_Web_StaticMemFile::~GpFileStream_Web_StaticMemFile()
{
}
size_t GpFileStream_Web_StaticMemFile::Read(void *bytesOut, size_t size)
{
size_t available = m_size - m_offset;
size = std::min(size, available);
memcpy(bytesOut, m_bytes + m_offset, size);
m_offset += size;
return size;
}
size_t GpFileStream_Web_StaticMemFile::Write(const void *bytes, size_t size)
{
return 0;
}
bool GpFileStream_Web_StaticMemFile::IsSeekable() const
{
return true;
}
bool GpFileStream_Web_StaticMemFile::IsReadOnly() const
{
return true;
}
bool GpFileStream_Web_StaticMemFile::IsWriteOnly() const
{
return false;
}
bool GpFileStream_Web_StaticMemFile::SeekStart(GpUFilePos_t loc)
{
if (loc > m_size)
return false;
m_offset = static_cast<size_t>(loc);
return true;
}
bool GpFileStream_Web_StaticMemFile::SeekCurrent(GpFilePos_t loc)
{
GpFilePos_t minOffset = -static_cast<GpFilePos_t>(m_offset);
GpFilePos_t maxOffset = static_cast<GpFilePos_t>(m_size - m_offset);
if (loc < minOffset || loc > maxOffset)
return false;
m_offset = static_cast<size_t>(static_cast<GpFilePos_t>(m_offset) + loc);
return true;
}
bool GpFileStream_Web_StaticMemFile::SeekEnd(GpUFilePos_t loc)
{
if (loc > m_size)
return false;
m_offset = m_size - loc;
return true;
}
GpUFilePos_t GpFileStream_Web_StaticMemFile::Size() const
{
return m_size;
}
GpUFilePos_t GpFileStream_Web_StaticMemFile::Tell() const
{
return m_offset;
}
void GpFileStream_Web_StaticMemFile::Close()
{
delete this;
}
void GpFileStream_Web_StaticMemFile::Flush()
{
}
class GpFileStream_Web_File final : public GpIOStream
{
public:
GpFileStream_Web_File(FILE *f, bool readOnly, bool writeOnly);
~GpFileStream_Web_File();
size_t Read(void *bytesOut, size_t size) override;
size_t Write(const void *bytes, size_t size) override;
bool IsSeekable() const override;
bool IsReadOnly() const override;
bool IsWriteOnly() const override;
bool SeekStart(GpUFilePos_t loc) override;
bool SeekCurrent(GpFilePos_t loc) override;
bool SeekEnd(GpUFilePos_t loc) override;
GpUFilePos_t Size() const override;
GpUFilePos_t Tell() const override;
void Close() override;
void Flush() override;
private:
FILE *m_f;
bool m_seekable;
bool m_isReadOnly;
bool m_isWriteOnly;
};
GpFileStream_Web_File::GpFileStream_Web_File(FILE *f, bool readOnly, bool writeOnly)
: m_f(f)
, m_isReadOnly(readOnly)
, m_isWriteOnly(writeOnly)
{
m_seekable = (fseek(m_f, 0, SEEK_CUR) == 0);
}
GpFileStream_Web_File::~GpFileStream_Web_File()
{
fclose(m_f);
}
size_t GpFileStream_Web_File::Read(void *bytesOut, size_t size)
{
if (m_isWriteOnly)
return 0;
return fread(bytesOut, 1, size, m_f);
}
size_t GpFileStream_Web_File::Write(const void *bytes, size_t size)
{
if (m_isReadOnly)
return 0;
return fwrite(bytes, 1, size, m_f);
}
bool GpFileStream_Web_File::IsSeekable() const
{
return m_seekable;
}
bool GpFileStream_Web_File::IsReadOnly() const
{
return m_isReadOnly;
}
bool GpFileStream_Web_File::IsWriteOnly() const
{
return m_isWriteOnly;
}
bool GpFileStream_Web_File::SeekStart(GpUFilePos_t loc)
{
if (!m_seekable)
return false;
fflush(m_f);
return fseek64(m_f, static_cast<off64_t>(loc), SEEK_SET) >= 0;
}
bool GpFileStream_Web_File::SeekCurrent(GpFilePos_t loc)
{
if (!m_seekable)
return false;
fflush(m_f);
return fseek64(m_f, static_cast<off64_t>(loc), SEEK_CUR) >= 0;
}
bool GpFileStream_Web_File::SeekEnd(GpUFilePos_t loc)
{
if (!m_seekable)
return false;
fflush(m_f);
return fseek64(m_f, -static_cast<off64_t>(loc), SEEK_END) >= 0;
}
GpUFilePos_t GpFileStream_Web_File::Size() const
{
fflush(m_f);
struct stat64 s;
if (fstat64(fileno(m_f), &s) < 0)
return 0;
return static_cast<GpUFilePos_t>(s.st_size);
}
GpUFilePos_t GpFileStream_Web_File::Tell() const
{
return static_cast<GpUFilePos_t>(ftell(m_f));
}
void GpFileStream_Web_File::Close()
{
this->~GpFileStream_Web_File();
free(this);
}
void GpFileStream_Web_File::Flush()
{
fflush(m_f);
}
bool GpFileSystem_Web::ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution)
{
const char *prefsAppend = nullptr;
switch (virtualDirectory)
{
case PortabilityLayer::VirtualDirectories::kApplicationData:
resolution = std::string("Packaged");
break;
case PortabilityLayer::VirtualDirectories::kGameData:
resolution = std::string("Packaged/Houses");
break;
case PortabilityLayer::VirtualDirectories::kFonts:
resolution = std::string("Resources");
break;
case PortabilityLayer::VirtualDirectories::kHighScores:
prefsAppend = "HighScores";
break;
case PortabilityLayer::VirtualDirectories::kUserData:
prefsAppend = "Houses";
break;
case PortabilityLayer::VirtualDirectories::kUserSaves:
prefsAppend = "SavedGames";
break;
case PortabilityLayer::VirtualDirectories::kPrefs:
prefsAppend = "Prefs";
break;
case PortabilityLayer::VirtualDirectories::kFontCache:
prefsAppend = "FontCache";
break;
default:
return false;
};
if (prefsAppend)
resolution = m_prefsPath + prefsAppend;
else
resolution = m_basePath + resolution;
for (size_t i = 0; i < numPaths; i++)
{
resolution += "/";
resolution += paths[i];
}
return true;
}
GpFileSystem_Web::GpFileSystem_Web()
: m_delayCallback(nullptr)
{
}
GpFileSystem_Web::~GpFileSystem_Web()
{
}
void GpFileSystem_Web::Init()
{
char *prefsDir = SDL_GetPrefPath("aerofoil", "aerofoil");
m_prefsPath = prefsDir;
char *baseDir = SDL_GetBasePath();
m_basePath = baseDir;
SDL_free(baseDir);
char baseDirSeparator = m_basePath[m_basePath.size() - 1];
if (m_basePath.size() >= 4 && m_basePath.substr(m_basePath.size() - 4, 3) == "bin")
m_basePath = m_basePath.substr(0, m_basePath.size() - 4) + "lib" + baseDirSeparator + "aerofoil" + baseDirSeparator;
const char *extensions[] = { "HighScores", "Houses", "SavedGames", "Prefs", "FontCache" };
for (size_t i = 0; i < sizeof(extensions) / sizeof(extensions[0]); i++)
{
std::string prefsPath = std::string(prefsDir) + extensions[i];
int created = mkdir(prefsPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
}
SDL_free(prefsDir);
}
bool GpFileSystem_Web::FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path)
{
if (const GpFileSystem_Web_Resources::FileCatalog *catalog = GetCatalogForVirtualDirectory(virtualDirectory))
{
for (size_t i = 0; i < catalog->m_numEntries; i++)
{
const GpFileSystem_Web_Resources::FileCatalogEntry &entry = catalog->m_entries[i];
if (!strcmp(path, entry.m_fileName))
return true;
}
return false;
}
std::string resolvedPath;
if (!ResolvePath(virtualDirectory, &path, 1, resolvedPath))
return false;
struct stat s;
return stat(resolvedPath.c_str(), &s) == 0;
}
bool GpFileSystem_Web::FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &exists)
{
if (const GpFileSystem_Web_Resources::FileCatalog *catalog = GetCatalogForVirtualDirectory(virtualDirectory))
{
for (size_t i = 0; i < catalog->m_numEntries; i++)
{
const GpFileSystem_Web_Resources::FileCatalogEntry &entry = catalog->m_entries[i];
if (!strcmp(path, entry.m_fileName))
{
exists = true;
return true;
}
}
exists = false;
return false;
}
std::string resolvedPath;
if (!ResolvePath(virtualDirectory, &path, 1, resolvedPath))
{
if (exists)
exists = false;
return false;
}
int permissions = access(resolvedPath.c_str(), W_OK | F_OK);
exists = ((permissions & F_OK) != 0);
return ((permissions & W_OK) != 0);
}
GpIOStream *GpFileSystem_Web::OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* subPaths, size_t numSubPaths, bool writeAccess, GpFileCreationDisposition_t createDisposition)
{
if (numSubPaths == 1)
{
if (const GpFileSystem_Web_Resources::FileCatalog *catalog = GetCatalogForVirtualDirectory(virtualDirectory))
{
for (size_t i = 0; i < catalog->m_numEntries; i++)
{
const GpFileSystem_Web_Resources::FileCatalogEntry &entry = catalog->m_entries[i];
if (!strcmp(subPaths[0], entry.m_fileName))
return new GpFileStream_Web_StaticMemFile(entry.m_data, entry.m_size);
}
return nullptr;
}
}
const char *mode = nullptr;
bool canWrite = false;
bool needResetPosition = false;
switch (createDisposition)
{
case GpFileCreationDispositions::kCreateOrOverwrite:
mode = "wb";
break;
case GpFileCreationDispositions::kCreateNew:
mode = "x+b";
break;
case GpFileCreationDispositions::kCreateOrOpen:
mode = "a+b";
needResetPosition = true;
break;
case GpFileCreationDispositions::kOpenExisting:
mode = writeAccess ? "r+b" : "rb";
break;
case GpFileCreationDispositions::kOverwriteExisting:
mode = "r+b";
break;
default:
return nullptr;
};
if (virtualDirectory == PortabilityLayer::VirtualDirectories::kSourceExport)
return nullptr;
std::string resolvedPath;
if (!ResolvePath(virtualDirectory, subPaths, numSubPaths, resolvedPath))
return nullptr;
void *objStorage = malloc(sizeof(GpFileStream_Web_File));
if (!objStorage)
return nullptr;
FILE *f = fopen(resolvedPath.c_str(), mode);
if (!f)
{
free(objStorage);
return nullptr;
}
if (needResetPosition)
fseek(f, 0, SEEK_SET);
if (createDisposition == GpFileCreationDispositions::kOverwriteExisting)
{
if (ftruncate64(fileno(f), 0) < 0)
{
free(objStorage);
fclose(f);
return nullptr;
}
}
return new (objStorage) GpFileStream_Web_File(f, !writeAccess, false);
}
bool GpFileSystem_Web::DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed)
{
if (const GpFileSystem_Web_Resources::FileCatalog *catalog = GetCatalogForVirtualDirectory(virtualDirectory))
return false;
std::string resolvedPath;
if (!ResolvePath(virtualDirectory, &path, 1, resolvedPath))
{
existed = false;
return false;
}
if (unlink(resolvedPath.c_str()) < 0)
{
existed = (errno != ENOENT);
return false;
}
existed = true;
return true;
}
bool GpFileSystem_Web::ValidateFilePath(const char *path, size_t length) const
{
for (size_t i = 0; i < length; i++)
{
const char c = path[i];
if (c >= '0' && c <= '9')
continue;
if (c == '_' || c == '.' || c == '\'' || c == '!')
continue;
if (c == ' ' && i != 0 && i != length - 1)
continue;
if (c >= 'a' && c <= 'z')
continue;
if (c >= 'A' && c <= 'Z')
continue;
return false;
}
return true;
}
bool GpFileSystem_Web::ValidateFilePathUnicodeChar(uint32_t c) const
{
if (c >= '0' && c <= '9')
return true;
if (c == '_' || c == '\'')
return true;
if (c == ' ')
return true;
if (c >= 'a' && c <= 'z')
return true;
if (c >= 'A' && c <= 'Z')
return true;
return false;
}
void GpFileSystem_Web::SetDelayCallback(DelayCallback_t delayCallback)
{
m_delayCallback = delayCallback;
}
GpFileSystem_Web *GpFileSystem_Web::GetInstance()
{
return &ms_instance;
}
class GpDirectoryCursor_StringList final : public IGpDirectoryCursor
{
public:
explicit GpDirectoryCursor_StringList(std::vector<std::string> &paths);
~GpDirectoryCursor_StringList();
bool GetNext(const char *&outFileName) override;
void Destroy() override;
private:
std::vector<std::string> m_paths;
size_t m_index;
};
GpDirectoryCursor_StringList::GpDirectoryCursor_StringList(std::vector<std::string> &paths)
: m_index(0)
{
std::swap(paths, m_paths);
}
GpDirectoryCursor_StringList::~GpDirectoryCursor_StringList()
{
}
bool GpDirectoryCursor_StringList::GetNext(const char *&outFileName)
{
if (m_index == m_paths.size())
return false;
outFileName = m_paths[m_index].c_str();
m_index++;
return true;
}
void GpDirectoryCursor_StringList::Destroy()
{
delete this;
}
IGpDirectoryCursor *GpFileSystem_Web::ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths)
{
if (const GpFileSystem_Web_Resources::FileCatalog *catalog = GetCatalogForVirtualDirectory(virtualDirectory))
return ScanCatalog(*catalog);
return nullptr;
}
const GpFileSystem_Web_Resources::FileCatalog *GpFileSystem_Web::GetCatalogForVirtualDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory)
{
if (virtualDirectory == PortabilityLayer::VirtualDirectories::kApplicationData)
return &GpFileSystem_Web_Resources::ApplicationData::GetCatalog();
if (virtualDirectory == PortabilityLayer::VirtualDirectories::kGameData)
return &GpFileSystem_Web_Resources::GameData::GetCatalog();
return nullptr;
}
IGpDirectoryCursor *GpFileSystem_Web::ScanCatalog(const GpFileSystem_Web_Resources::FileCatalog &catalog)
{
std::vector<std::string> paths;
for (size_t i = 0; i < catalog.m_numEntries; i++)
paths.push_back(std::string(catalog.m_entries[i].m_fileName));
return new GpDirectoryCursor_StringList(paths);
}
GpFileSystem_Web GpFileSystem_Web::ms_instance;

View File

@@ -0,0 +1,62 @@
#pragma once
#include "IGpFileSystem.h"
#include "GpFileSystem_Web_Resources.h"
#include "GpCoreDefs.h"
#include <string>
#include <stdio.h>
struct IGpMutex;
class GpFileSystem_Web final : public IGpFileSystem
{
public:
GpFileSystem_Web();
~GpFileSystem_Web();
void Init();
bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override;
bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &exists) override;
GpIOStream *OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* subPaths, size_t numSubPaths, bool writeAccess, GpFileCreationDisposition_t createDisposition) override;
bool DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) override;
IGpDirectoryCursor *ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths) override;
bool ValidateFilePath(const char *path, size_t pathLen) const override;
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
void SetDelayCallback(DelayCallback_t delayCallback) override;
static GpFileSystem_Web *GetInstance();
private:
struct ScanDirectoryNestedContext
{
GpFileSystem_Web *m_this;
IGpDirectoryCursor *m_returnValue;
PortabilityLayer::VirtualDirectory_t m_virtualDirectory;
char const *const *m_paths;
size_t m_numPaths;
};
static void ScanDirectoryNestedThunk(void *context);
IGpDirectoryCursor *ScanDirectoryNestedInternal(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
IGpDirectoryCursor *ScanDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
static const GpFileSystem_Web_Resources::FileCatalog *GetCatalogForVirtualDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory);
static IGpDirectoryCursor *ScanCatalog(const GpFileSystem_Web_Resources::FileCatalog &catalog);
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution);
DelayCallback_t m_delayCallback;
std::string m_prefsPath;
std::string m_basePath;
static GpFileSystem_Web ms_instance;
};

View File

@@ -0,0 +1,28 @@
#pragma once
namespace GpFileSystem_Web_Resources
{
struct FileCatalogEntry
{
const char *m_fileName;
const unsigned char *m_data;
const unsigned int m_size;
};
struct FileCatalog
{
const FileCatalogEntry *m_entries;
const unsigned int m_numEntries;
const unsigned int m_size;
const unsigned int m_size0;
};
namespace ApplicationData
{
const FileCatalog &GetCatalog();
}
namespace GameData
{
const FileCatalog &GetCatalog();
}
}

View File

@@ -0,0 +1,89 @@
#include "GpLogDriver_Web.h"
#include "GpFileSystem_Web.h"
#include "GpApplicationName.h"
#include "GpIOStream.h"
#include <time.h>
#include <cstring>
GpLogDriver_Web::GpLogDriver_Web()
{
}
void GpLogDriver_Web::Init()
{
ms_instance.InitInternal();
}
void GpLogDriver_Web::VPrintf(Category category, const char *fmt, va_list args)
{
size_t fmtSize = 0;
bool hasFormatting = false;
for (const char *fmtCheck = fmt; *fmtCheck; fmtCheck++)
{
if (*fmtCheck == '%')
hasFormatting = true;
fmtSize++;
}
time_t t = time(nullptr);
struct tm sysTime = *localtime(&t);
char timestampBuffer[64];
sprintf(timestampBuffer, "[%02d:%02d:%02d] ", sysTime.tm_hour, sysTime.tm_min, sysTime.tm_sec);
const char *debugTag = "";
switch (category)
{
case Category_Warning:
debugTag = "[WARNING] ";
break;
case Category_Error:
debugTag = "[ERROR] ";
break;
default:
break;
};
int formattedSize = vsnprintf(nullptr, 0, fmt, args);
if (formattedSize <= 0)
return;
char *charBuff = static_cast<char*>(malloc(formattedSize + 1));
if (!charBuff)
return;
vsnprintf(charBuff, formattedSize + 1, fmt, args);
fprintf(stderr, "%s%s%s\n", timestampBuffer, debugTag, charBuff);
fflush(stderr);
free(charBuff);
}
void GpLogDriver_Web::Shutdown()
{
}
GpLogDriver_Web *GpLogDriver_Web::GetInstance()
{
return &ms_instance;
}
void GpLogDriver_Web::InitInternal()
{
time_t t = time(nullptr);
struct tm utcTime = *gmtime(&t);
this->Printf(IGpLogDriver::Category_Information, GP_APPLICATION_NAME " build " __TIMESTAMP__);
#if !GP_DEBUG_CONFIG
this->Printf(IGpLogDriver::Category_Information, "Configuration: Release");
#else
this->Printf(IGpLogDriver::Category_Information, "Configuration: Debug");
#endif
}
GpLogDriver_Web GpLogDriver_Web::ms_instance;

View File

@@ -0,0 +1,25 @@
#pragma once
#include "IGpLogDriver.h"
#include <stdio.h>
class GpIOStream;
class GpLogDriver_Web : public IGpLogDriver
{
public:
GpLogDriver_Web();
static void Init();
void VPrintf(Category category, const char *fmt, va_list args) override;
void Shutdown() override;
static GpLogDriver_Web *GetInstance();
private:
void InitInternal();
static GpLogDriver_Web ms_instance;
};

View File

@@ -0,0 +1,91 @@
#include <SDL.h>
#include "SDL_main.h"
#include "GpMain.h"
#include "GpAudioDriverFactory.h"
#include "GpDisplayDriverFactory.h"
#include "GpGlobalConfig.h"
#include "GpFileSystem_Web.h"
#include "GpLogDriver_Web.h"
#include "GpFontHandlerFactory.h"
#include "GpInputDriverFactory.h"
#include "GpAppInterface.h"
#include "GpSystemServices_Web.h"
#include "GpVOSEvent.h"
#include "GpX.h"
#include "IGpFileSystem.h"
#include "IGpThreadEvent.h"
#include "IGpVOSEventQueue.h"
#include <string>
GpXGlobals g_gpXGlobals;
extern "C" IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties);
IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties);
IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties);
IGpInputDriver *GpDriver_CreateInputDriver_SDL2_Gamepad(const GpInputDriverProperties &properties);
int main(int argc, char* argv[])
{
GpLogDriver_Web::Init();
IGpLogDriver *logger = GpLogDriver_Web::GetInstance();
#if GP_ASYNCIFY_PARANOID
SDL_SetHint(SDL_HINT_EMSCRIPTEN_ASYNCIFY, "0");
#endif
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0)
return -1;
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Starting filesystem...");
GpFileSystem_Web::GetInstance()->Init();
GpDriverCollection *drivers = GpAppInterface_Get()->PL_GetDriverCollection();
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Setting up drivers...");
drivers->SetDriver<GpDriverIDs::kFileSystem>(GpFileSystem_Web::GetInstance());
drivers->SetDriver<GpDriverIDs::kSystemServices>(GpSystemServices_Web::GetInstance());
drivers->SetDriver<GpDriverIDs::kLog>(GpLogDriver_Web::GetInstance());
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_SDL_GL2;
g_gpGlobalConfig.m_audioDriverType = EGpAudioDriverType_SDL2;
g_gpGlobalConfig.m_fontHandlerType = EGpFontHandlerType_None;
EGpInputDriverType inputDrivers[] =
{
EGpInputDriverType_SDL2_Gamepad
};
g_gpGlobalConfig.m_inputDriverTypes = inputDrivers;
g_gpGlobalConfig.m_numInputDrivers = sizeof(inputDrivers) / sizeof(inputDrivers[0]);
g_gpGlobalConfig.m_osGlobals = &g_gpXGlobals;
g_gpGlobalConfig.m_logger = logger;
g_gpGlobalConfig.m_systemServices = GpSystemServices_Web::GetInstance();
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_SDL_GL2, GpDriver_CreateDisplayDriver_SDL_GL2);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_SDL2, GpDriver_CreateAudioDriver_SDL);
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_SDL2_Gamepad, GpDriver_CreateInputDriver_SDL2_Gamepad);
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "SDL environment configured, starting up");
int returnCode = GpMain::Run();
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "SDL environment exited with code %i, cleaning up", returnCode);
SDL_Quit();
return returnCode;
}

View File

@@ -0,0 +1,209 @@
#include "GpSystemServices_Web.h"
#include "IGpClipboardContents.h"
#include "IGpThreadEvent.h"
#include "SDL2/SDL.h"
#include <time.h>
#include <unistd.h>
#include <string>
class GpMutex_Web_Null final : public IGpMutex
{
public:
void Destroy() override;
void Lock() override;
void Unlock() override;
static IGpMutex *GetInstance();
private:
static GpMutex_Web_Null ms_instance;
};
void GpMutex_Web_Null::Destroy()
{
}
void GpMutex_Web_Null::Lock()
{
}
void GpMutex_Web_Null::Unlock()
{
}
IGpMutex *GpMutex_Web_Null::GetInstance()
{
return &ms_instance;
}
GpMutex_Web_Null GpMutex_Web_Null::ms_instance;
class GpThreadEvent_Web_Null final : public IGpThreadEvent
{
public:
void Wait() override;
bool WaitTimed(uint32_t msec) override;
void Signal() override;
void Destroy() override;
static IGpThreadEvent *GetInstance();
private:
static GpThreadEvent_Web_Null ms_instance;
};
GpThreadEvent_Web_Null GpThreadEvent_Web_Null::ms_instance;
void GpThreadEvent_Web_Null::Wait()
{
}
bool GpThreadEvent_Web_Null::WaitTimed(uint32_t msec)
{
return true;
}
void GpThreadEvent_Web_Null::Signal()
{
}
void GpThreadEvent_Web_Null::Destroy()
{
}
IGpThreadEvent *GpThreadEvent_Web_Null::GetInstance()
{
return &ms_instance;
}
GpSystemServices_Web::GpSystemServices_Web()
: m_textInputEnabled(false)
, m_clipboardContents(nullptr)
{
}
int64_t GpSystemServices_Web::GetTime() const
{
time_t t = time(nullptr);
return static_cast<int64_t>(t) - 2082844800;
}
void GpSystemServices_Web::GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const
{
time_t t = time(nullptr);
tm *tmObject = localtime(&t);
year = static_cast<unsigned int>(tmObject->tm_year);
month = static_cast<unsigned int>(tmObject->tm_mon + 1);
hour = static_cast<unsigned int>(tmObject->tm_hour);
minute = static_cast<unsigned int>(tmObject->tm_min);
second = static_cast<unsigned int>(tmObject->tm_sec);
}
IGpMutex *GpSystemServices_Web::CreateMutex()
{
return GpMutex_Web_Null::GetInstance();
}
IGpMutex *GpSystemServices_Web::CreateRecursiveMutex()
{
return GpMutex_Web_Null::GetInstance();
}
IGpThreadEvent *GpSystemServices_Web::CreateThreadEvent(bool autoReset, bool startSignaled)
{
return GpThreadEvent_Web_Null::GetInstance();
}
uint64_t GpSystemServices_Web::GetFreeMemoryCosmetic() const
{
return 0;
}
GpSystemServices_Web::~GpSystemServices_Web()
{
if (m_clipboardContents)
m_clipboardContents->Destroy();
}
void *GpSystemServices_Web::CreateThread(ThreadFunc_t threadFunc, void *context)
{
return nullptr;
}
void GpSystemServices_Web::Beep() const
{
}
bool GpSystemServices_Web::IsTouchscreen() const
{
return false;
}
bool GpSystemServices_Web::IsUsingMouseAsTouch() const
{
return false;
}
bool GpSystemServices_Web::IsTextInputObstructive() const
{
return false;
}
bool GpSystemServices_Web::IsFullscreenPreferred() const
{
return false;
}
bool GpSystemServices_Web::IsFullscreenOnStartup() const
{
return false;
}
unsigned int GpSystemServices_Web::GetCPUCount() const
{
return SDL_GetCPUCount();
}
void GpSystemServices_Web::SetTextInputEnabled(bool isEnabled)
{
m_textInputEnabled = isEnabled;
}
bool GpSystemServices_Web::IsTextInputEnabled() const
{
return m_textInputEnabled;
}
bool GpSystemServices_Web::AreFontResourcesSeekable() const
{
return true;
}
IGpClipboardContents *GpSystemServices_Web::GetClipboardContents() const
{
return m_clipboardContents;
}
void GpSystemServices_Web::SetClipboardContents(IGpClipboardContents *contents)
{
if (contents != m_clipboardContents)
{
if (m_clipboardContents)
m_clipboardContents->Destroy();
m_clipboardContents = contents;
}
}
GpSystemServices_Web *GpSystemServices_Web::GetInstance()
{
return &ms_instance;
}
GpSystemServices_Web GpSystemServices_Web::ms_instance;

View File

@@ -0,0 +1,41 @@
#pragma once
#include "IGpSystemServices.h"
#include "GpCoreDefs.h"
struct IGpClipboardContents;
class GpSystemServices_Web final : public IGpSystemServices
{
public:
GpSystemServices_Web();
~GpSystemServices_Web();
void *CreateThread(ThreadFunc_t threadFunc, void *context) override;
void Beep() const override;
bool IsTouchscreen() const override;
bool IsUsingMouseAsTouch() const override;
bool IsTextInputObstructive() const override;
bool IsFullscreenPreferred() const override;
bool IsFullscreenOnStartup() const override;
unsigned int GetCPUCount() const override;
void SetTextInputEnabled(bool isEnabled) override;
bool IsTextInputEnabled() const override;
bool AreFontResourcesSeekable() const override;
IGpClipboardContents *GetClipboardContents() const override;
void SetClipboardContents(IGpClipboardContents *contents) override;
int64_t GetTime() const override;
void GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const override;
IGpMutex *CreateMutex() override;
IGpMutex *CreateRecursiveMutex() override;
IGpThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) override;
uint64_t GetFreeMemoryCosmetic() const override;
static GpSystemServices_Web *GetInstance();
private:
static GpSystemServices_Web ms_instance;
IGpClipboardContents *m_clipboardContents;
bool m_textInputEnabled;
};

5
AerofoilWeb/Link.bat Normal file
View File

@@ -0,0 +1,5 @@
set INPUT_DIR=.
set OUTPUT_DIR=bin
set FLAGS=-flto -O3 -s USE_SDL=2 -s USE_ZLIB=1 -s ASYNCIFY -s ASYNCIFY_IGNORE_INDIRECT -s INITIAL_MEMORY=33554432 -s ASYNCIFY_ADVISE
emcc obj/AerofoilWeb_Combined.o obj/AerofoilWeb_Resources.o obj/GpShell_Combined.o obj/AerofoilSDL_Combined.o obj/GpApp_Combined.o obj/PortabilityLayer_Combined.o obj/MacRomanConversion.o -o %OUTPUT_DIR%/aerofoil.html %FLAGS%

View File

@@ -0,0 +1,3 @@
mkdir obj
mkdir bin
mkdir res

9
AerofoilWeb/Rebuild.bat Normal file
View File

@@ -0,0 +1,9 @@
call MakeBuildDirs.bat
call BuildAerofoilSDL.bat
call BuildAerofoilWeb.bat
call BuildGpApp.bat
call BuildGpShell.bat
call BuildMacRomanConversion.bat
call BuildPortabilityLayer.bat
call BuildResources.bat
call Link.bat

1
AerofoilWeb/Run.bat Normal file
View File

@@ -0,0 +1 @@
emrun bin/aerofoil.html

12
AerofoilWin.props Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(SolutionDir)Aerofoil;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup />
</Project>

View File

@@ -0,0 +1,488 @@
#define _LARGEFILE64_SOURCE
#include "GpFileSystem_X.h"
#include "GpIOStream.h"
#include "IGpDirectoryCursor.h"
#include "IGpSystemServices.h"
#include "IGpMutex.h"
#include "IGpThreadRelay.h"
#include "VirtualDirectory.h"
#include "PLDrivers.h"
#include "SDL2/SDL.h"
#include "SDL2/SDL_rwops.h"
#include <string>
#include <vector>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <dirent.h>
#include "UTF8.h"
#ifdef __CYGWIN__
typedef off_t off64_t;
#define fstat64 fstat
#define fseek64 fseek
#define ftruncate64 ftruncate
#define stat64 stat
#endif
class GpFileStream_X_File final : public GpIOStream
{
public:
GpFileStream_X_File(FILE *f, bool readOnly, bool writeOnly);
~GpFileStream_X_File();
size_t Read(void *bytesOut, size_t size) override;
size_t Write(const void *bytes, size_t size) override;
bool IsSeekable() const override;
bool IsReadOnly() const override;
bool IsWriteOnly() const override;
bool SeekStart(GpUFilePos_t loc) override;
bool SeekCurrent(GpFilePos_t loc) override;
bool SeekEnd(GpUFilePos_t loc) override;
GpUFilePos_t Size() const override;
GpUFilePos_t Tell() const override;
void Close() override;
void Flush() override;
private:
FILE *m_f;
bool m_seekable;
bool m_isReadOnly;
bool m_isWriteOnly;
};
GpFileStream_X_File::GpFileStream_X_File(FILE *f, bool readOnly, bool writeOnly)
: m_f(f)
, m_isReadOnly(readOnly)
, m_isWriteOnly(writeOnly)
{
m_seekable = (fseek(m_f, 0, SEEK_CUR) == 0);
}
GpFileStream_X_File::~GpFileStream_X_File()
{
fclose(m_f);
}
size_t GpFileStream_X_File::Read(void *bytesOut, size_t size)
{
if (m_isWriteOnly)
return 0;
return fread(bytesOut, 1, size, m_f);
}
size_t GpFileStream_X_File::Write(const void *bytes, size_t size)
{
if (m_isReadOnly)
return 0;
return fwrite(bytes, 1, size, m_f);
}
bool GpFileStream_X_File::IsSeekable() const
{
return m_seekable;
}
bool GpFileStream_X_File::IsReadOnly() const
{
return m_isReadOnly;
}
bool GpFileStream_X_File::IsWriteOnly() const
{
return m_isWriteOnly;
}
bool GpFileStream_X_File::SeekStart(GpUFilePos_t loc)
{
if (!m_seekable)
return false;
fflush(m_f);
return fseek64(m_f, static_cast<off64_t>(loc), SEEK_SET) >= 0;
}
bool GpFileStream_X_File::SeekCurrent(GpFilePos_t loc)
{
if (!m_seekable)
return false;
fflush(m_f);
return fseek64(m_f, static_cast<off64_t>(loc), SEEK_CUR) >= 0;
}
bool GpFileStream_X_File::SeekEnd(GpUFilePos_t loc)
{
if (!m_seekable)
return false;
fflush(m_f);
return fseek64(m_f, -static_cast<off64_t>(loc), SEEK_END) >= 0;
}
GpUFilePos_t GpFileStream_X_File::Size() const
{
fflush(m_f);
struct stat64 s;
if (fstat64(fileno(m_f), &s) < 0)
return 0;
return static_cast<GpUFilePos_t>(s.st_size);
}
GpUFilePos_t GpFileStream_X_File::Tell() const
{
return static_cast<GpUFilePos_t>(ftell(m_f));
}
void GpFileStream_X_File::Close()
{
this->~GpFileStream_X_File();
free(this);
}
void GpFileStream_X_File::Flush()
{
fflush(m_f);
}
bool GpFileSystem_X::ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution)
{
const char *prefsAppend = nullptr;
switch (virtualDirectory)
{
case PortabilityLayer::VirtualDirectories::kApplicationData:
resolution = std::string("Packaged");
break;
case PortabilityLayer::VirtualDirectories::kGameData:
resolution = std::string("Packaged/Houses");
break;
case PortabilityLayer::VirtualDirectories::kFonts:
resolution = std::string("Resources");
break;
case PortabilityLayer::VirtualDirectories::kHighScores:
prefsAppend = "HighScores";
break;
case PortabilityLayer::VirtualDirectories::kUserData:
prefsAppend = "Houses";
break;
case PortabilityLayer::VirtualDirectories::kUserSaves:
prefsAppend = "SavedGames";
break;
case PortabilityLayer::VirtualDirectories::kPrefs:
prefsAppend = "Prefs";
break;
case PortabilityLayer::VirtualDirectories::kFontCache:
prefsAppend = "FontCache";
break;
default:
return false;
};
if (prefsAppend)
resolution = m_prefsPath + prefsAppend;
else
resolution = m_basePath + resolution;
for (size_t i = 0; i < numPaths; i++)
{
resolution += "/";
resolution += paths[i];
}
return true;
}
GpFileSystem_X::GpFileSystem_X()
: m_delayCallback(nullptr)
{
}
GpFileSystem_X::~GpFileSystem_X()
{
}
void GpFileSystem_X::Init()
{
char *prefsDir = SDL_GetPrefPath("aerofoil", "aerofoil");
m_prefsPath = prefsDir;
char *baseDir = SDL_GetBasePath();
m_basePath = baseDir;
SDL_free(baseDir);
char baseDirSeparator = m_basePath[m_basePath.size() - 1];
if (m_basePath.size() >= 4 && m_basePath.substr(m_basePath.size() - 4, 3) == "bin")
m_basePath = m_basePath.substr(0, m_basePath.size() - 4) + "lib" + baseDirSeparator + "aerofoil" + baseDirSeparator;
const char *extensions[] = { "HighScores", "Houses", "SavedGames", "Prefs", "FontCache" };
for (size_t i = 0; i < sizeof(extensions) / sizeof(extensions[0]); i++)
{
std::string prefsPath = std::string(prefsDir) + extensions[i];
int created = mkdir(prefsPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
}
SDL_free(prefsDir);
}
bool GpFileSystem_X::FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path)
{
std::string resolvedPath;
if (!ResolvePath(virtualDirectory, &path, 1, resolvedPath))
return false;
struct stat s;
return stat(resolvedPath.c_str(), &s) == 0;
}
bool GpFileSystem_X::FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &exists)
{
std::string resolvedPath;
if (!ResolvePath(virtualDirectory, &path, 1, resolvedPath))
{
if (exists)
exists = false;
return false;
}
int permissions = access(resolvedPath.c_str(), W_OK | F_OK);
exists = ((permissions & F_OK) != 0);
return ((permissions & W_OK) != 0);
}
GpIOStream *GpFileSystem_X::OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* subPaths, size_t numSubPaths, bool writeAccess, GpFileCreationDisposition_t createDisposition)
{
const char *mode = nullptr;
bool canWrite = false;
bool needResetPosition = false;
switch (createDisposition)
{
case GpFileCreationDispositions::kCreateOrOverwrite:
mode = "wb";
break;
case GpFileCreationDispositions::kCreateNew:
mode = "x+b";
break;
case GpFileCreationDispositions::kCreateOrOpen:
mode = "a+b";
needResetPosition = true;
break;
case GpFileCreationDispositions::kOpenExisting:
mode = writeAccess ? "r+b" : "rb";
break;
case GpFileCreationDispositions::kOverwriteExisting:
mode = "r+b";
break;
default:
return nullptr;
};
if (virtualDirectory == PortabilityLayer::VirtualDirectories::kSourceExport)
return nullptr;
std::string resolvedPath;
if (!ResolvePath(virtualDirectory, subPaths, numSubPaths, resolvedPath))
return nullptr;
void *objStorage = malloc(sizeof(GpFileStream_X_File));
if (!objStorage)
return nullptr;
FILE *f = fopen(resolvedPath.c_str(), mode);
if (!f)
{
free(objStorage);
return nullptr;
}
if (needResetPosition)
fseek(f, 0, SEEK_SET);
if (createDisposition == GpFileCreationDispositions::kOverwriteExisting)
{
if (ftruncate64(fileno(f), 0) < 0)
{
free(objStorage);
fclose(f);
return nullptr;
}
}
return new (objStorage) GpFileStream_X_File(f, !writeAccess, false);
}
bool GpFileSystem_X::DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed)
{
std::string resolvedPath;
if (!ResolvePath(virtualDirectory, &path, 1, resolvedPath))
{
existed = false;
return false;
}
if (unlink(resolvedPath.c_str()) < 0)
{
existed = (errno != ENOENT);
return false;
}
existed = true;
return true;
}
bool GpFileSystem_X::ValidateFilePath(const char *path, size_t length) const
{
for (size_t i = 0; i < length; i++)
{
const char c = path[i];
if (c >= '0' && c <= '9')
continue;
if (c == '_' || c == '.' || c == '\'' || c == '!')
continue;
if (c == ' ' && i != 0 && i != length - 1)
continue;
if (c >= 'a' && c <= 'z')
continue;
if (c >= 'A' && c <= 'Z')
continue;
return false;
}
return true;
}
bool GpFileSystem_X::ValidateFilePathUnicodeChar(uint32_t c) const
{
if (c >= '0' && c <= '9')
return true;
if (c == '_' || c == '\'')
return true;
if (c == ' ')
return true;
if (c >= 'a' && c <= 'z')
return true;
if (c >= 'A' && c <= 'Z')
return true;
return false;
}
void GpFileSystem_X::SetDelayCallback(DelayCallback_t delayCallback)
{
m_delayCallback = delayCallback;
}
GpFileSystem_X *GpFileSystem_X::GetInstance()
{
return &ms_instance;
}
class GpDirectoryCursor_StringList final : public IGpDirectoryCursor
{
public:
explicit GpDirectoryCursor_StringList(std::vector<std::string> &paths);
~GpDirectoryCursor_StringList();
bool GetNext(const char *&outFileName) override;
void Destroy() override;
private:
std::vector<std::string> m_paths;
size_t m_index;
};
GpDirectoryCursor_StringList::GpDirectoryCursor_StringList(std::vector<std::string> &paths)
: m_index(0)
{
std::swap(paths, m_paths);
}
GpDirectoryCursor_StringList::~GpDirectoryCursor_StringList()
{
}
bool GpDirectoryCursor_StringList::GetNext(const char *&outFileName)
{
if (m_index == m_paths.size())
return false;
outFileName = m_paths[m_index].c_str();
m_index++;
return true;
}
void GpDirectoryCursor_StringList::Destroy()
{
delete this;
}
class GpDirectoryCursor_POSIX final : public IGpDirectoryCursor
{
public:
explicit GpDirectoryCursor_POSIX(DIR *dir);
~GpDirectoryCursor_POSIX();
bool GetNext(const char *&outFileName) override;
void Destroy() override;
private:
DIR *m_dir;
};
GpDirectoryCursor_POSIX::GpDirectoryCursor_POSIX(DIR *dir)
: m_dir(dir)
{
}
GpDirectoryCursor_POSIX::~GpDirectoryCursor_POSIX()
{
closedir(m_dir);
}
bool GpDirectoryCursor_POSIX::GetNext(const char *&outFileName)
{
struct dirent *dir = readdir(m_dir);
if (!dir)
return false;
outFileName = dir->d_name;
return true;
}
void GpDirectoryCursor_POSIX::Destroy()
{
delete this;
}
IGpDirectoryCursor *GpFileSystem_X::ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths)
{
std::string resolvedPath;
std::vector<std::string> subPaths;
if (!ResolvePath(virtualDirectory, paths, numPaths, resolvedPath))
return nullptr;
DIR *d = opendir(resolvedPath.c_str());
if (!d)
return nullptr;
return new GpDirectoryCursor_POSIX(d);
}
GpFileSystem_X GpFileSystem_X::ms_instance;

View File

@@ -0,0 +1,42 @@
#pragma once
#include "IGpFileSystem.h"
#include "GpCoreDefs.h"
#include <string>
#include <stdio.h>
struct IGpMutex;
class GpFileSystem_X final : public IGpFileSystem
{
public:
GpFileSystem_X();
~GpFileSystem_X();
void Init();
bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override;
bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &exists) override;
GpIOStream *OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* subPaths, size_t numSubPaths, bool writeAccess, GpFileCreationDisposition_t createDisposition) override;
bool DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) override;
IGpDirectoryCursor *ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths) override;
bool ValidateFilePath(const char *path, size_t pathLen) const override;
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
void SetDelayCallback(DelayCallback_t delayCallback) override;
static GpFileSystem_X *GetInstance();
private:
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution);
DelayCallback_t m_delayCallback;
std::string m_prefsPath;
std::string m_basePath;
static GpFileSystem_X ms_instance;
};

127
AerofoilX/GpLogDriver_X.cpp Normal file
View File

@@ -0,0 +1,127 @@
#include "GpLogDriver_X.h"
#include "GpFileSystem_X.h"
#include "GpApplicationName.h"
#include "GpIOStream.h"
#include <time.h>
#include <cstring>
GpLogDriver_X::GpLogDriver_X()
: m_stream(nullptr)
, m_isInitialized(false)
{
}
void GpLogDriver_X::Init()
{
ms_instance.InitInternal();
}
void GpLogDriver_X::VPrintf(Category category, const char *fmt, va_list args)
{
size_t fmtSize = 0;
bool hasFormatting = false;
for (const char *fmtCheck = fmt; *fmtCheck; fmtCheck++)
{
if (*fmtCheck == '%')
hasFormatting = true;
fmtSize++;
}
time_t t = time(nullptr);
struct tm sysTime = *localtime(&t);
char timestampBuffer[64];
sprintf(timestampBuffer, "[%02d:%02d:%02d] ", sysTime.tm_hour, sysTime.tm_min, sysTime.tm_sec);
if (m_stream)
m_stream->Write(timestampBuffer, strlen(timestampBuffer));
const char *debugTag = "";
switch (category)
{
case Category_Warning:
debugTag = "[WARNING] ";
break;
case Category_Error:
debugTag = "[ERROR] ";
break;
};
if (debugTag[0])
{
if (m_stream)
m_stream->Write(debugTag, strlen(debugTag));
}
if (!hasFormatting)
{
if (m_stream)
m_stream->Write(fmt, fmtSize);
}
else
{
int formattedSize = vsnprintf(nullptr, 0, fmt, args);
if (formattedSize <= 0)
return;
char *charBuff = static_cast<char*>(malloc(formattedSize + 1));
if (!charBuff)
return;
vsnprintf(charBuff, formattedSize + 1, fmt, args);
if (m_stream)
m_stream->Write(charBuff, formattedSize);
free(charBuff);
}
if (m_stream)
{
m_stream->Write("\n", 1);
m_stream->Flush();
}
}
void GpLogDriver_X::Shutdown()
{
if (m_stream)
m_stream->Close();
}
GpLogDriver_X *GpLogDriver_X::GetInstance()
{
if (ms_instance.m_isInitialized)
return &ms_instance;
else
return nullptr;
}
void GpLogDriver_X::InitInternal()
{
time_t t = time(nullptr);
struct tm utcTime = *gmtime(&t);
char logFileName[256];
sprintf(logFileName, GP_APPLICATION_NAME "-%04d-%02d-%02d_%02d-%02d_%02d.txt", utcTime.tm_year, utcTime.tm_mon, utcTime.tm_mday, utcTime.tm_hour, utcTime.tm_min, utcTime.tm_sec);
m_stream = GpFileSystem_X::GetInstance()->OpenFile(PortabilityLayer::VirtualDirectories::kLogs, logFileName, true, GpFileCreationDispositions::kCreateOrOverwrite);
if (m_stream)
{
this->Printf(IGpLogDriver::Category_Information, GP_APPLICATION_NAME " build " __TIMESTAMP__);
#if !GP_DEBUG_CONFIG
this->Printf(IGpLogDriver::Category_Information, "Configuration: Release");
#else
this->Printf(IGpLogDriver::Category_Information, "Configuration: Debug");
#endif
m_isInitialized = true;
}
}
GpLogDriver_X GpLogDriver_X::ms_instance;

28
AerofoilX/GpLogDriver_X.h Normal file
View File

@@ -0,0 +1,28 @@
#pragma once
#include "IGpLogDriver.h"
#include <stdio.h>
class GpIOStream;
class GpLogDriver_X : public IGpLogDriver
{
public:
GpLogDriver_X();
static void Init();
void VPrintf(Category category, const char *fmt, va_list args) override;
void Shutdown() override;
static GpLogDriver_X *GetInstance();
private:
void InitInternal();
GpIOStream *m_stream;
bool m_isInitialized;
static GpLogDriver_X ms_instance;
};

View File

@@ -0,0 +1,77 @@
#include "SDL.h"
#include "SDL_main.h"
#include "GpMain.h"
#include "GpAudioDriverFactory.h"
#include "GpDisplayDriverFactory.h"
#include "GpGlobalConfig.h"
#include "GpFileSystem_X.h"
#include "GpLogDriver_X.h"
#include "GpFontHandlerFactory.h"
#include "GpInputDriverFactory.h"
#include "GpAppInterface.h"
#include "GpSystemServices_X.h"
#include "GpVOSEvent.h"
#include "GpX.h"
#include "IGpFileSystem.h"
#include "IGpThreadEvent.h"
#include "IGpVOSEventQueue.h"
#include <string>
GpXGlobals g_gpXGlobals;
IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties);
IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties);
IGpInputDriver *GpDriver_CreateInputDriver_SDL2_Gamepad(const GpInputDriverProperties &properties);
SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[])
{
GpLogDriver_X::Init();
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0)
return -1;
GpFileSystem_X::GetInstance()->Init();
IGpLogDriver *logger = GpLogDriver_X::GetInstance();
GpDriverCollection *drivers = GpAppInterface_Get()->PL_GetDriverCollection();
drivers->SetDriver<GpDriverIDs::kFileSystem>(GpFileSystem_X::GetInstance());
drivers->SetDriver<GpDriverIDs::kSystemServices>(GpSystemServices_X::GetInstance());
drivers->SetDriver<GpDriverIDs::kLog>(GpLogDriver_X::GetInstance());
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_SDL_GL2;
g_gpGlobalConfig.m_audioDriverType = EGpAudioDriverType_SDL2;
g_gpGlobalConfig.m_fontHandlerType = EGpFontHandlerType_None;
EGpInputDriverType inputDrivers[] =
{
EGpInputDriverType_SDL2_Gamepad
};
g_gpGlobalConfig.m_inputDriverTypes = inputDrivers;
g_gpGlobalConfig.m_numInputDrivers = sizeof(inputDrivers) / sizeof(inputDrivers[0]);
g_gpGlobalConfig.m_osGlobals = &g_gpXGlobals;
g_gpGlobalConfig.m_logger = logger;
g_gpGlobalConfig.m_systemServices = GpSystemServices_X::GetInstance();
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_SDL_GL2, GpDriver_CreateDisplayDriver_SDL_GL2);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_SDL2, GpDriver_CreateAudioDriver_SDL);
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_SDL2_Gamepad, GpDriver_CreateInputDriver_SDL2_Gamepad);
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "SDL environment configured, starting up");
int returnCode = GpMain::Run();
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "SDL environment exited with code %i, cleaning up", returnCode);
return returnCode;
}

View File

@@ -0,0 +1,137 @@
#include "GpSystemServices_X.h"
#include "IGpClipboardContents.h"
#include "IGpThreadEvent.h"
#include "SDL2/SDL.h"
#include <time.h>
#include <unistd.h>
#include <string>
struct GpSystemServices_X_ThreadStartParams
{
GpSystemServices_X::ThreadFunc_t m_threadFunc;
void *m_threadContext;
IGpThreadEvent *m_threadStartEvent;
};
static void *StaticStartThread(void *lpThreadParameter)
{
const GpSystemServices_X_ThreadStartParams *threadParams = static_cast<const GpSystemServices_X_ThreadStartParams*>(lpThreadParameter);
GpSystemServices_X::ThreadFunc_t threadFunc = threadParams->m_threadFunc;
void *threadContext = threadParams->m_threadContext;
IGpThreadEvent *threadStartEvent = threadParams->m_threadStartEvent;
threadStartEvent->Signal();
return reinterpret_cast<void*>(static_cast<intptr_t>(threadFunc(threadContext)));
}
GpSystemServices_X::GpSystemServices_X()
: m_textInputEnabled(false)
, m_clipboardContents(nullptr)
{
}
GpSystemServices_X::~GpSystemServices_X()
{
if (m_clipboardContents)
m_clipboardContents->Destroy();
}
void *GpSystemServices_X::CreateThread(ThreadFunc_t threadFunc, void *context)
{
IGpThreadEvent *evt = CreateThreadEvent(true, false);
if (!evt)
return nullptr;
GpSystemServices_X_ThreadStartParams startParams;
startParams.m_threadContext = context;
startParams.m_threadFunc = threadFunc;
startParams.m_threadStartEvent = evt;
pthread_t thread = nullptr;
if (pthread_create(&thread, nullptr, StaticStartThread, &startParams) != 0)
{
evt->Destroy();
return nullptr;
}
evt->Wait();
evt->Destroy();
return thread;
}
void GpSystemServices_X::Beep() const
{
}
bool GpSystemServices_X::IsTouchscreen() const
{
return false;
}
bool GpSystemServices_X::IsUsingMouseAsTouch() const
{
return false;
}
bool GpSystemServices_X::IsTextInputObstructive() const
{
return false;
}
bool GpSystemServices_X::IsFullscreenPreferred() const
{
return true;
}
bool GpSystemServices_X::IsFullscreenOnStartup() const
{
return false;
}
unsigned int GpSystemServices_X::GetCPUCount() const
{
return SDL_GetCPUCount();
}
void GpSystemServices_X::SetTextInputEnabled(bool isEnabled)
{
m_textInputEnabled = isEnabled;
}
bool GpSystemServices_X::IsTextInputEnabled() const
{
return m_textInputEnabled;
}
bool GpSystemServices_X::AreFontResourcesSeekable() const
{
return true;
}
IGpClipboardContents *GpSystemServices_X::GetClipboardContents() const
{
return m_clipboardContents;
}
void GpSystemServices_X::SetClipboardContents(IGpClipboardContents *contents)
{
if (contents != m_clipboardContents)
{
if (m_clipboardContents)
m_clipboardContents->Destroy();
m_clipboardContents = contents;
}
}
GpSystemServices_X *GpSystemServices_X::GetInstance()
{
return &ms_instance;
}
GpSystemServices_X GpSystemServices_X::ms_instance;

View File

@@ -0,0 +1,35 @@
#pragma once
#include "GpSystemServices_POSIX.h"
#include "GpCoreDefs.h"
struct IGpClipboardContents;
class GpSystemServices_X final : public GpSystemServices_POSIX
{
public:
GpSystemServices_X();
~GpSystemServices_X();
void *CreateThread(ThreadFunc_t threadFunc, void *context) override;
void Beep() const override;
bool IsTouchscreen() const override;
bool IsUsingMouseAsTouch() const override;
bool IsTextInputObstructive() const override;
bool IsFullscreenPreferred() const override;
bool IsFullscreenOnStartup() const override;
unsigned int GetCPUCount() const override;
void SetTextInputEnabled(bool isEnabled) override;
bool IsTextInputEnabled() const override;
bool AreFontResourcesSeekable() const override;
IGpClipboardContents *GetClipboardContents() const override;
void SetClipboardContents(IGpClipboardContents *contents) override;
static GpSystemServices_X *GetInstance();
private:
static GpSystemServices_X ms_instance;
IGpClipboardContents *m_clipboardContents;
bool m_textInputEnabled;
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -14,8 +14,6 @@
"DITL/2008.json" : "ApplicationResourcePatches/DITL/2008.json",
"PICT/1300.bmp" : "ApplicationResourcePatches/PICT/1300.bmp",
"PICT/1301.bmp" : "ApplicationResourcePatches/PICT/1301.bmp",
"PICT/1302.bmp" : "ApplicationResourcePatches/PICT/1302.bmp",
"PICT/1303.bmp" : "ApplicationResourcePatches/PICT/1303.bmp",
"PICT/1971.bmp" : "ApplicationResourcePatches/PICT/1971.bmp",
"PICT/1972.bmp" : "ApplicationResourcePatches/PICT/1972.bmp",
"PICT/1973.bmp" : "ApplicationResourcePatches/PICT/1973.bmp",

265
CMakeLists.txt Normal file
View File

@@ -0,0 +1,265 @@
cmake_minimum_required(VERSION 3.10)
project (Aerofoil)
message(${CMAKE_BINARY_DIR})
find_package(SDL2 REQUIRED)
add_definitions(-DGP_DEBUG_CONFIG=0)
add_library(stb STATIC
stb/stb_image_write.c
)
add_library(zlib STATIC
zlib/adler32.c
zlib/crc32.c
zlib/deflate.c
zlib/inffast.c
zlib/inflate.c
zlib/inftrees.c
zlib/trees.c
zlib/zutil.c
)
add_library(MacRomanConversion STATIC
MacRomanConversion/MacRomanConversion.cpp
)
add_library(PortabilityLayer STATIC
PortabilityLayer/AntiAliasTable.cpp
PortabilityLayer/AppEventHandler.cpp
PortabilityLayer/BinHex4.cpp
PortabilityLayer/BitmapImage.cpp
PortabilityLayer/ByteSwap.cpp
PortabilityLayer/CFileStream.cpp
PortabilityLayer/DeflateCodec.cpp
PortabilityLayer/DialogManager.cpp
PortabilityLayer/DisplayDeviceManager.cpp
PortabilityLayer/EllipsePlotter.cpp
PortabilityLayer/FileBrowserUI.cpp
PortabilityLayer/FileManager.cpp
PortabilityLayer/FileSectionStream.cpp
PortabilityLayer/FontFamily.cpp
PortabilityLayer/FontManager.cpp
PortabilityLayer/FontRenderer.cpp
PortabilityLayer/GPArchive.cpp
PortabilityLayer/HostSuspendHook.cpp
PortabilityLayer/IconLoader.cpp
PortabilityLayer/InflateStream.cpp
PortabilityLayer/InputManager.cpp
PortabilityLayer/LinePlotter.cpp
PortabilityLayer/MacBinary2.cpp
PortabilityLayer/MacFileInfo.cpp
PortabilityLayer/MacFileMem.cpp
PortabilityLayer/MemoryManager.cpp
PortabilityLayer/MemReaderStream.cpp
PortabilityLayer/MenuManager.cpp
PortabilityLayer/MMBlock.cpp
PortabilityLayer/MMHandleBlock.cpp
PortabilityLayer/PLApplication.cpp
PortabilityLayer/PLButtonWidget.cpp
PortabilityLayer/PLControlDefinitions.cpp
PortabilityLayer/PLCore.cpp
PortabilityLayer/PLCTabReducer.cpp
PortabilityLayer/PLDialogs.cpp
PortabilityLayer/PLDrivers.cpp
PortabilityLayer/PLEditboxWidget.cpp
PortabilityLayer/PLEventQueue.cpp
PortabilityLayer/PLHacks.cpp
PortabilityLayer/PLHandle.cpp
PortabilityLayer/PLIconWidget.cpp
PortabilityLayer/PLImageWidget.cpp
PortabilityLayer/PLInvisibleWidget.cpp
PortabilityLayer/PLKeyEncoding.cpp
PortabilityLayer/PLLabelWidget.cpp
PortabilityLayer/PLMenus.cpp
PortabilityLayer/PLMovies.cpp
PortabilityLayer/PLNumberFormatting.cpp
PortabilityLayer/PLPopupMenuWidget.cpp
PortabilityLayer/PLQDOffscreen.cpp
PortabilityLayer/PLQDraw.cpp
PortabilityLayer/PLResourceManager.cpp
PortabilityLayer/PLResources.cpp
PortabilityLayer/PLScrollBarWidget.cpp
PortabilityLayer/PLSound.cpp
PortabilityLayer/PLStandardColors.cpp
PortabilityLayer/PLStringCompare.cpp
PortabilityLayer/PLSysCalls.cpp
PortabilityLayer/PLTimeTaggedVOSEvent.cpp
PortabilityLayer/PLWidgets.cpp
PortabilityLayer/QDGraf.cpp
PortabilityLayer/QDManager.cpp
PortabilityLayer/QDPictDecoder.cpp
PortabilityLayer/QDPictEmitContext.cpp
PortabilityLayer/QDPictHeader.cpp
PortabilityLayer/QDPixMap.cpp
PortabilityLayer/QDPort.cpp
PortabilityLayer/QDStandardPalette.cpp
PortabilityLayer/RandomNumberGenerator.cpp
PortabilityLayer/ResolveCachingColor.cpp
PortabilityLayer/ResourceCompiledRef.cpp
PortabilityLayer/ResourceFile.cpp
PortabilityLayer/ScanlineMask.cpp
PortabilityLayer/ScanlineMaskBuilder.cpp
PortabilityLayer/ScanlineMaskConverter.cpp
PortabilityLayer/ScanlineMaskIterator.cpp
PortabilityLayer/SimpleGraphic.cpp
PortabilityLayer/TextPlacer.cpp
PortabilityLayer/UTF8.cpp
PortabilityLayer/UTF16.cpp
PortabilityLayer/WindowDef.cpp
PortabilityLayer/WindowManager.cpp
PortabilityLayer/WorkerThread.cpp
PortabilityLayer/XModemCRC.cpp
PortabilityLayer/ZipFileProxy.cpp
)
target_include_directories(PortabilityLayer PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/Common>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/GpCommon>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/PortabilityLayer>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/zlib>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/rapidjson/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/MacRomanConversion>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/stb>
)
target_compile_options(PortabilityLayer PRIVATE -Wno-multichar)
target_link_libraries(PortabilityLayer zlib MacRomanConversion stb)
add_library(GpShell STATIC
GpShell/GpAppEnvironment.cpp
GpShell/GpAudioDriverFactory.cpp
GpShell/GpDisplayDriverFactory.cpp
GpShell/GpFontHandlerFactory.cpp
GpShell/GpGlobalConfig.cpp
GpShell/GpInputDriverFactory.cpp
GpShell/GpMain.cpp
GpShell/GpVOSEventQueue.cpp
)
target_include_directories(GpShell PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/Common>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/GpCommon>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/PortabilityLayer>
)
add_library(GpApp STATIC
GpApp/About.cpp
GpApp/AnimCursor.cpp
GpApp/AppleEvents.cpp
GpApp/Banner.cpp
GpApp/ColorUtils.cpp
GpApp/Coordinates.cpp
GpApp/DialogUtils.cpp
GpApp/DynamicMaps.cpp
GpApp/Dynamics.cpp
GpApp/Dynamics2.cpp
GpApp/Dynamics3.cpp
GpApp/Environ.cpp
GpApp/Events.cpp
GpApp/FileError.cpp
GpApp/GameOver.cpp
GpApp/GpAppInterface.cpp
GpApp/Grease.cpp
GpApp/HighScores.cpp
GpApp/House.cpp
GpApp/HouseInfo.cpp
GpApp/HouseIO.cpp
GpApp/HouseLegal.cpp
GpApp/Input.cpp
GpApp/Interactions.cpp
GpApp/InterfaceInit.cpp
GpApp/Link.cpp
GpApp/Main.cpp
GpApp/MainMenuUI.cpp
GpApp/MainWindow.cpp
GpApp/Map.cpp
GpApp/Marquee.cpp
GpApp/Menu.cpp
GpApp/Modes.cpp
GpApp/Music.cpp
GpApp/ObjectAdd.cpp
GpApp/ObjectDraw.cpp
GpApp/ObjectDraw2.cpp
GpApp/ObjectDrawAll.cpp
GpApp/ObjectEdit.cpp
GpApp/ObjectInfo.cpp
GpApp/ObjectRects.cpp
GpApp/Objects.cpp
GpApp/Play.cpp
GpApp/Player.cpp
GpApp/Prefs.cpp
GpApp/RectUtils.cpp
GpApp/Render.cpp
GpApp/Room.cpp
GpApp/RoomGraphics.cpp
GpApp/RoomInfo.cpp
GpApp/RubberBands.cpp
GpApp/SavedGames.cpp
GpApp/Scoreboard.cpp
GpApp/Scrap.cpp
GpApp/SelectHouse.cpp
GpApp/Settings.cpp
GpApp/Sound.cpp
GpApp/SoundSync_Cpp11.cpp
GpApp/SourceExport.cpp
GpApp/StringUtils.cpp
GpApp/StructuresInit.cpp
GpApp/StructuresInit2.cpp
GpApp/Tools.cpp
GpApp/Transit.cpp
GpApp/Transitions.cpp
GpApp/Triggers.cpp
GpApp/Trip.cpp
GpApp/Utilities.cpp
GpApp/WindowUtils.cpp
)
target_compile_options(GpApp PRIVATE -Wno-multichar)
target_include_directories(GpApp PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/Common>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/GpCommon>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/PortabilityLayer>
)
target_link_libraries(GpApp PortabilityLayer)
if(CMAKE_HOST_UNIX)
add_executable(AerofoilX
AerofoilPortable/GpSystemServices_POSIX.cpp
AerofoilPortable/GpThreadEvent_Cpp11.cpp
AerofoilSDL/GpAudioDriver_SDL2.cpp
AerofoilSDL/GpDisplayDriver_SDL_GL2.cpp
AerofoilSDL/GpInputDriver_SDL_Gamepad.cpp
AerofoilSDL/ShaderCode/CopyQuadP.cpp
AerofoilSDL/ShaderCode/DrawQuad32P.cpp
AerofoilSDL/ShaderCode/DrawQuadPaletteP.cpp
AerofoilSDL/ShaderCode/DrawQuadV.cpp
AerofoilSDL/ShaderCode/ScaleQuadP.cpp
AerofoilX/GpMain_SDL_X.cpp
AerofoilX/GpLogDriver_X.cpp
AerofoilX/GpSystemServices_X.cpp
AerofoilX/GpFileSystem_X.cpp
)
target_include_directories(AerofoilX PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/Common>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/GpCommon>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/GpShell>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/AerofoilSDL>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/AerofoilPortable>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/PortabilityLayer>
${SDL2_INCLUDE_DIRS}
)
target_link_libraries(AerofoilX ${SDL2_LIBRARIES} GpApp GpShell)
endif()
install (TARGETS AerofoilX)

View File

@@ -1,6 +1,7 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#if __cplusplus >= 199711L
#define GP_IS_CPP11 1
@@ -52,3 +53,19 @@ static const size_t GP_SYSTEM_MEMORY_ALIGNMENT = 16;
#if !defined(GP_DEBUG_CONFIG)
#error "GP_DEBUG_CONFIG was not set"
#endif
#ifdef __EMSCRIPTEN__
#define GP_ASYNCIFY_PARANOID 1
#else
#define GP_ASYNCIFY_PARANOID 0
#endif
#if GP_ASYNCIFY_PARANOID
#define GP_ASYNCIFY_PARANOID_VIRTUAL
#define GP_ASYNCIFY_PARANOID_PURE
#define GP_ASYNCIFY_PARANOID_OVERRIDE
#else
#define GP_ASYNCIFY_PARANOID_VIRTUAL virtual
#define GP_ASYNCIFY_PARANOID_PURE = 0
#define GP_ASYNCIFY_PARANOID_OVERRIDE override
#endif

View File

@@ -4,12 +4,23 @@ mkdir Packaged
mkdir Packaged\Houses
x64\Release\MiniRez.exe "GliderProData\Glider PRO.r" Packaged\ApplicationResources.gpr
x64\Release\gpr2gpa.exe "Packaged\ApplicationResources.gpr" "DefaultTimestamp.timestamp" "Packaged\ApplicationResources.gpa" "ApplicationResourcePatches\manifest.json"
x64\Release\FTagData.exe "DefaultTimestamp.timestamp" "Packaged\ApplicationResources.gpf" data ozm5 0 0 locked
x64\Release\MergeGPF.exe "Packaged\ApplicationResources.gpf"
x64\Release\GenerateFonts.exe
x64\Release\MiniRez.exe "Empty.r" Packaged\Fonts.gpr
x64\Release\gpr2gpa.exe "Packaged\Fonts.gpr" "DefaultTimestamp.timestamp" "Packaged\Fonts.gpa" "Packaged\FontCacheManifest.json"
x64\Release\FTagData.exe "DefaultTimestamp.timestamp" "Packaged\Fonts.gpf" data ozm5 0 0 locked
x64\Release\MergeGPF.exe "Packaged\Fonts.gpf"
del /Q Packaged\CachedFont*.bin
del Packaged\FontCacheCatalog.bin
del Packaged\FontCacheManifest.json
del Packaged\Fonts.gpr
del Packaged\Fonts.gpa
x64\Release\ConvertColorCursors.exe
attrib -R Packaged\ApplicationResources.gpf

0
Empty.r Normal file
View File

View File

@@ -5,7 +5,9 @@
#include "CFileStream.h"
#include "CombinedTimestamp.h"
int main(int argc, const char **argv)
#include "WindowsUnicodeToolShim.h"
int toolMain(int argc, const char **argv)
{
if (argc < 7)
{
@@ -28,12 +30,11 @@ int main(int argc, const char **argv)
return -3;
}
FILE *tsF = nullptr;
errno_t ferr = fopen_s(&tsF, timestampPath.c_str(), "rb");
FILE *tsF = fopen_utf8(timestampPath.c_str(), "rb");
int64_t timestamp = 0;
PortabilityLayer::CombinedTimestamp ts;
if (!ferr)
if (tsF)
{
if (fread(&ts, 1, sizeof(ts), tsF) != sizeof(ts))
{
@@ -77,9 +78,8 @@ int main(int argc, const char **argv)
PortabilityLayer::MacFilePropertiesSerialized mps;
mps.Serialize(mfp);
FILE *file = nullptr;
errno_t err = fopen_s(&file, outPath.c_str(), "wb");
if (!err)
FILE *file = fopen_utf8(outPath.c_str(), "wb");
if (file)
{
PortabilityLayer::CFileStream stream(file);

View File

@@ -41,6 +41,7 @@
<Import Project="..\GpCommon.props" />
<Import Project="..\Common.props" />
<Import Project="..\Debug.props" />
<Import Project="..\WindowsUnicodeToolShim.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
@@ -48,6 +49,7 @@
<Import Project="..\GpCommon.props" />
<Import Project="..\Common.props" />
<Import Project="..\Release.props" />
<Import Project="..\WindowsUnicodeToolShim.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
@@ -77,6 +79,9 @@
<ProjectReference Include="..\PortabilityLayer\PortabilityLayer.vcxproj">
<Project>{6ec62b0f-9353-40a4-a510-3788f1368b33}</Project>
</ProjectReference>
<ProjectReference Include="..\WindowsUnicodeToolShim\WindowsUnicodeToolShim.vcxproj">
<Project>{15009625-1120-405e-8bba-69a16cd6713d}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClCompile Include="FTagData.cpp" />

View File

@@ -1,38 +0,0 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := FreeType
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/freetype/include
# Add your application source files here...
LOCAL_SRC_FILES := \
$(LOCAL_PATH)/freetype/src/base/ftbase.c \
$(LOCAL_PATH)/freetype/src/base/ftbitmap.c \
$(LOCAL_PATH)/freetype/src/base/ftdebug.c \
$(LOCAL_PATH)/freetype/src/base/ftinit.c \
$(LOCAL_PATH)/freetype/src/base/ftsystem.c \
$(LOCAL_PATH)/freetype/src/winfonts/winfnt.c \
$(LOCAL_PATH)/freetype/src/autofit/autofit.c \
$(LOCAL_PATH)/freetype/src/bdf/bdf.c \
$(LOCAL_PATH)/freetype/src/cff/cff.c \
$(LOCAL_PATH)/freetype/src/gzip/ftgzip.c \
$(LOCAL_PATH)/freetype/src/lzw/ftlzw.c \
$(LOCAL_PATH)/freetype/src/pcf/pcf.c \
$(LOCAL_PATH)/freetype/src/pfr/pfr.c \
$(LOCAL_PATH)/freetype/src/psaux/psaux.c \
$(LOCAL_PATH)/freetype/src/pshinter/pshinter.c \
$(LOCAL_PATH)/freetype/src/psnames/psnames.c \
$(LOCAL_PATH)/freetype/src/raster/raster.c \
$(LOCAL_PATH)/freetype/src/sfnt/sfnt.c \
$(LOCAL_PATH)/freetype/src/smooth/smooth.c \
$(LOCAL_PATH)/freetype/src/truetype/truetype.c \
$(LOCAL_PATH)/freetype/src/type1/type1.c \
$(LOCAL_PATH)/freetype/src/cid/type1cid.c \
$(LOCAL_PATH)/freetype/src/type42/type42.c
LOCAL_CFLAGS := -DFT2_BUILD_LIBRARY
include $(BUILD_SHARED_LIBRARY)

View File

@@ -0,0 +1,313 @@
#include "FontFamily.h"
#include "FontManager.h"
#include "FontRenderer.h"
#include "IGpFont.h"
#include "IGpFontHandler.h"
#include "GpAppInterface.h"
#include "GpDriverIndex.h"
#include "GpFontHandlerProperties.h"
#include "GpFileSystem_Win32.h"
#include "GpSystemServices_Win32.h"
#include "CFileStream.h"
#include "PLDrivers.h"
#include "RenderedFont.h"
#include "RenderedFontCatalog.h"
#include "WindowsUnicodeToolShim.h"
extern "C" __declspec(dllimport) IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties);
class MemBufferStream final : public GpIOStream
{
public:
size_t Read(void *bytesOut, size_t size) override;
size_t Write(const void *bytes, size_t size) override;
bool IsSeekable() const override;
bool IsReadOnly() const override;
bool IsWriteOnly() const override;
bool SeekStart(GpUFilePos_t loc) override;
bool SeekCurrent(GpFilePos_t loc) override;
bool SeekEnd(GpUFilePos_t loc) override;
GpUFilePos_t Size() const override;
GpUFilePos_t Tell() const override;
void Close() override;
void Flush() override;
const uint8_t *GetBytes() const;
private:
size_t m_writeOffset;
std::vector<uint8_t> m_buffer;
};
size_t MemBufferStream::Read(void *bytesOut, size_t size)
{
return 0;
}
size_t MemBufferStream::Write(const void *bytes, size_t size)
{
const uint8_t *bytesUInt8 = static_cast<const uint8_t*>(bytes);
for (size_t i = 0; i < size; i++)
{
if (m_writeOffset == m_buffer.size())
m_buffer.push_back(bytesUInt8[i]);
else
m_buffer[m_writeOffset] = bytesUInt8[i];
m_writeOffset++;
}
return size;
}
bool MemBufferStream::IsSeekable() const
{
return true;
}
bool MemBufferStream::IsReadOnly() const
{
return false;
}
bool MemBufferStream::IsWriteOnly() const
{
return true;
}
bool MemBufferStream::SeekStart(GpUFilePos_t loc)
{
m_writeOffset = static_cast<size_t>(loc);
return true;
}
bool MemBufferStream::SeekCurrent(GpFilePos_t loc)
{
m_writeOffset = static_cast<size_t>(static_cast<GpFilePos_t>(m_writeOffset) + loc);
return true;
}
bool MemBufferStream::SeekEnd(GpUFilePos_t loc)
{
m_writeOffset = this->Size() - loc;
return true;
}
GpUFilePos_t MemBufferStream::Size() const
{
return m_buffer.size();
}
GpUFilePos_t MemBufferStream::Tell() const
{
return m_writeOffset;
}
void MemBufferStream::Close()
{
}
void MemBufferStream::Flush()
{
}
const uint8_t *MemBufferStream::GetBytes() const
{
return &m_buffer[0];
}
struct KnownFontSpec
{
public:
KnownFontSpec();
KnownFontSpec(const char *path, int size, bool aa, PortabilityLayer::FontHacks hacks);
bool operator==(const KnownFontSpec &other) const;
bool operator!=(const KnownFontSpec &other) const;
private:
std::string m_path;
int m_size;
bool m_aa;
PortabilityLayer::FontHacks m_hacks;
};
KnownFontSpec::KnownFontSpec()
: m_size(0)
, m_aa(false)
, m_hacks(PortabilityLayer::FontHacks_None)
{
}
KnownFontSpec::KnownFontSpec(const char *path, int size, bool aa, PortabilityLayer::FontHacks hacks)
: m_path(path)
, m_size(size)
, m_aa(aa)
, m_hacks(hacks)
{
}
bool KnownFontSpec::operator==(const KnownFontSpec &other) const
{
return !((*this) != other);
}
bool KnownFontSpec::operator!=(const KnownFontSpec &other) const
{
return m_path != other.m_path ||
m_size != other.m_size ||
m_aa != other.m_aa ||
m_hacks != other.m_hacks;
}
int toolMain(int argc, const char **argv)
{
GpFontHandlerProperties fhProperties;
fhProperties.m_type = EGpFontHandlerType_FreeType2;
IGpFontHandler *ft2Handler = GpDriver_CreateFontHandler_FreeType2(fhProperties);
PortabilityLayer::FontManager *fontManager = PortabilityLayer::FontManager::GetInstance();
PortabilityLayer::FontRenderer *fontRenderer = PortabilityLayer::FontRenderer::GetInstance();
fontManager->Init();
std::vector<std::string> paths;
std::vector<PortabilityLayer::RenderedFontCatalogRFontEntry> catalog;
std::vector<KnownFontSpec> fontSpecs;
FILE *manifestF = fopen_utf8("Packaged/FontCacheManifest.json", "wb");
fprintf(manifestF, "{\n");
fprintf(manifestF, "\t\"add\" :\n");
fprintf(manifestF, "\t{\n");
fprintf(manifestF, "\t\t\"RFCT/1000.bin\" : \"Packaged/FontCacheCatalog.bin\"");
int numFontsEmitted = 0;
for (int presetIndex = 0; presetIndex < PortabilityLayer::FontPresets::kCount; presetIndex++)
{
int size = 0;
int flags = 0;
bool aa = false;
PortabilityLayer::FontFamilyID_t fontFamilyID;
fontManager->GetFontPreset(static_cast<PortabilityLayer::FontPreset_t>(presetIndex), &fontFamilyID, &size, &flags, &aa);
PortabilityLayer::FontFamily *fontFamily = fontManager->GetFont(fontFamilyID);
int variation = fontFamily->GetVariationForFlags(flags);
PortabilityLayer::FontHacks hacks;
const char *path = nullptr;
fontFamily->GetFontSpec(variation, hacks, path);
KnownFontSpec spec(path, size, aa, hacks);
if (std::find(fontSpecs.begin(), fontSpecs.end(), spec) != fontSpecs.end())
continue;
fontSpecs.push_back(spec);
std::string resPath = std::string("Resources/") + path;
FILE *fontFile = fopen_utf8(resPath.c_str(), "rb");
if (fontFile)
{
PortabilityLayer::CFileStream stream(fontFile);
IGpFont *font = ft2Handler->LoadFont(&stream);
if (!ft2Handler->KeepStreamOpen())
stream.Close();
PortabilityLayer::RenderedFont *rfont = fontRenderer->RenderFont(font, size, aa, hacks);
{
char fontPath[1024];
sprintf(fontPath, "Packaged/CachedFont%i.bin", numFontsEmitted);
FILE *cachedFontF = fopen_utf8(fontPath, "wb");
PortabilityLayer::CFileStream cacheStream(cachedFontF);
fontRenderer->SaveCache(rfont, &cacheStream);
cacheStream.Close();
fprintf(manifestF, ",\n\t\t\"RFNT/%i.bin\" : \"%s\"", 1000 + numFontsEmitted, fontPath);
}
rfont->Destroy();
font->Destroy();
PortabilityLayer::RenderedFontCatalogRFontEntry catEntry;
catEntry.m_fontSize = static_cast<uint8_t>(size);
catEntry.m_hacks = static_cast<uint8_t>(hacks);
catEntry.m_isAA = aa ? 1 : 0;
catEntry.m_pathIndex = 0;
bool foundPath = false;
for (size_t i = 0; i < paths.size(); i++)
{
if (paths[i] == path)
{
catEntry.m_pathIndex = static_cast<uint8_t>(i);
foundPath = true;
break;
}
}
if (!foundPath)
{
catEntry.m_pathIndex = static_cast<uint8_t>(paths.size());
paths.push_back(std::string(path));
}
catalog.push_back(catEntry);
numFontsEmitted++;
}
}
fprintf(manifestF, "\n\t},\n");
fprintf(manifestF, "\t\"delete\" :\n");
fprintf(manifestF, "\t[\n");
fprintf(manifestF, "\t]\n");
fprintf(manifestF, "}\n");
PortabilityLayer::RenderedFontCatalogHeader catHeader;
FILE *catF = fopen_utf8("Packaged/FontCacheCatalog.bin", "wb");
catHeader.m_version = PortabilityLayer::RenderedFontCatalogHeader::kVersion;
catHeader.m_pathsOffset = static_cast<uint32_t>(sizeof(PortabilityLayer::RenderedFontCatalogHeader) + paths.size() * sizeof(PortabilityLayer::RenderedFontCatalogPathEntry) + numFontsEmitted * sizeof(PortabilityLayer::RenderedFontCatalogRFontEntry));
catHeader.m_numPaths = static_cast<uint16_t>(paths.size());
catHeader.m_numRFonts = static_cast<uint16_t>(numFontsEmitted);
fwrite(&catHeader, sizeof(catHeader), 1, catF);
PortabilityLayer::RenderedFontCatalogPathEntry pathEntry;
pathEntry.m_pathOffset = 0;
pathEntry.m_pathSize = 0;
for (size_t i = 0; i < paths.size(); i++)
{
pathEntry.m_pathOffset = static_cast<uint16_t>(pathEntry.m_pathOffset) + pathEntry.m_pathSize;
pathEntry.m_pathSize = static_cast<uint16_t>(paths[i].size());
fwrite(&pathEntry, sizeof(pathEntry), 1, catF);
}
fwrite(&catalog[0], sizeof(PortabilityLayer::RenderedFontCatalogRFontEntry), catalog.size(), catF);
for (size_t i = 0; i < paths.size(); i++)
{
const std::string &str = paths[i];
fwrite(&str[0], str.size(), 1, catF);
}
fclose(catF);
return 0;
}

View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{3B7FD18D-7A50-4DF5-AC25-543E539BFACE}</ProjectGuid>
<RootNamespace>GenerateFonts</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\Common.props" />
<Import Project="..\GpCommon.props" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\AerofoilWin.props" />
<Import Project="..\Debug.props" />
<Import Project="..\WindowsUnicodeToolShim.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\Common.props" />
<Import Project="..\GpCommon.props" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\AerofoilWin.props" />
<Import Project="..\Release.props" />
<Import Project="..\WindowsUnicodeToolShim.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="..\GpFontHandler_FreeType2\GpFontHandler_FreeType2.vcxproj">
<Project>{4b564030-8985-4975-91e1-e1b2c16ae2a1}</Project>
</ProjectReference>
<ProjectReference Include="..\PortabilityLayer\PortabilityLayer.vcxproj">
<Project>{6ec62b0f-9353-40a4-a510-3788f1368b33}</Project>
</ProjectReference>
<ProjectReference Include="..\WindowsUnicodeToolShim\WindowsUnicodeToolShim.vcxproj">
<Project>{15009625-1120-405e-8bba-69a16cd6713d}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClCompile Include="GenerateFonts.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="GenerateFonts.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -136,7 +136,7 @@ void DoAbout (void)
do // Loop until user wants to exit
{
hit = aboutDialog->ExecuteModal(nullptr, AboutFilter);
hit = aboutDialog->ExecuteModal(nullptr, PL_FILTER_FUNC(AboutFilter));
}
while (hit != kOkayButton);
@@ -218,7 +218,7 @@ void DoLicenseReader(int resID)
do
{
hit = dialog->ExecuteModal(nullptr, LicenseReaderFilter);
hit = dialog->ExecuteModal(nullptr, PL_FILTER_FUNC(LicenseReaderFilter));
} while (hit != kOkayButton);
dialog->Destroy();
@@ -265,7 +265,7 @@ void DoAboutOpenSource(void)
do
{
hit = dialog->ExecuteModal(nullptr, AboutFrameworkFilter);
hit = dialog->ExecuteModal(nullptr, PL_FILTER_FUNC(AboutFrameworkFilter));
switch (hit)
{
@@ -314,8 +314,8 @@ void DoAboutFramework (void)
PortabilityLayer::WindowDef wdef = PortabilityLayer::WindowDef::Create(windowRect, PortabilityLayer::WindowStyleFlags::kAlert, true, 0, 0, PSTR(""));
PortabilityLayer::ResolveCachingColor blackColor = StdColors::Black();
PortabilityLayer::RenderedFont *font = GetApplicationFont(12, PortabilityLayer::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *fontLight = GetApplicationFont(8, PortabilityLayer::FontFamilyFlag_None, true);
PortabilityLayer::RenderedFont *font = GetFont(PortabilityLayer::FontPresets::kApplication12Bold);
PortabilityLayer::RenderedFont *fontLight = GetFont(PortabilityLayer::FontPresets::kApplication8);
int16_t verticalPoint = 16 + font->GetMetrics().m_ascent;
int16_t horizontalOffset = 16;
@@ -359,7 +359,7 @@ void DoAboutFramework (void)
do
{
hit = dialog->ExecuteModal(nullptr, AboutFrameworkFilter);
hit = dialog->ExecuteModal(nullptr, PL_FILTER_FUNC(AboutFrameworkFilter));
if (hit == kAboutOpenSourceButton)
DoAboutOpenSource();
@@ -578,7 +578,7 @@ static int16_t AboutFrameworkFilter(void *context, Dialog *dialog, const TimeTag
void DrawLicenseReader(Window *window)
{
PortabilityLayer::RenderedFont *rfont = GetMonospaceFont(10, PortabilityLayer::FontFamilyFlag_None, true);
PortabilityLayer::RenderedFont *rfont = GetFont(PortabilityLayer::FontPresets::kMono10);
if (!rfont)
return;
@@ -766,3 +766,6 @@ static int16_t LicenseReaderFilter(void *context, Dialog *dialog, const TimeTagg
return hit;
}
PL_IMPLEMENT_FILTER_FUNCTION(AboutFilter)
PL_IMPLEMENT_FILTER_FUNCTION(LicenseReaderFilter)
PL_IMPLEMENT_FILTER_FUNCTION(AboutFrameworkFilter)

View File

@@ -12,9 +12,10 @@
#include "MemoryManager.h"
#include "ResourceManager.h"
#include "PLBigEndian.h"
#include "PLDrivers.h"
#include "PLResources.h"
#include "PLBigEndian.h"
#include "PLSysCalls.h"
#include <assert.h>
@@ -375,6 +376,8 @@ void DecrementCursor (void)
void SpinCursor (short incrementIndex)
{
PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE();
UInt32 dummyLong;
short i;

View File

@@ -21,6 +21,7 @@
#include "Utilities.h"
#include "WindowDef.h"
#include "WindowManager.h"
#include "PLSysCalls.h"
#define kBannerPageTopPICT 1993
@@ -118,7 +119,7 @@ void DrawBannerMessage (Point topLeft)
PasStringCopy((*thisHouse)->banner, bannerStr);
PortabilityLayer::RenderedFont *appFont = GetApplicationFont(12, PortabilityLayer::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12Bold);
PortabilityLayer::ResolveCachingColor blackColor = StdColors::Black();
@@ -179,11 +180,13 @@ void BringUpBanner (void)
(BitMap *)*GetGWorldPixMap(workSrcMap),
&wholePage, &wholePage, srcCopy);
if (demoGoing)
WaitForInputEvent(4);
else
WaitForInputEvent(15);
{
PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE();
if (demoGoing)
WaitForInputEvent(4);
else
WaitForInputEvent(15);
}
// if (quickerTransitions)
// DissBitsChunky(&justRoomsRect);
@@ -221,7 +224,7 @@ void DisplayStarsRemaining(void)
DrawSurface *surface = starsWindow->GetDrawSurface();
PortabilityLayer::RenderedFont *appFont = GetApplicationFont(12, PortabilityLayer::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12Bold);
NumToString((long)numStarsRemaining, theStr);
@@ -237,8 +240,11 @@ void DisplayStarsRemaining(void)
if (doZooms)
wm->FlickerWindowIn(starsWindow, 32);
DelayTicks(60);
WaitForInputEvent(30);
{
PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE();
DelayTicks(60);
WaitForInputEvent(30);
}
if (doZooms)
wm->FlickerWindowOut(starsWindow, 32);

View File

@@ -7,7 +7,6 @@
#include "Externs.h"
#include "PLPalettes.h"
#include "PLPasStr.h"
#include "QDStandardPalette.h"
#include "ResolveCachingColor.h"

View File

@@ -75,7 +75,7 @@ void UpdateCoordWindow (void)
PortabilityLayer::ResolveCachingColor whiteColor = StdColors::White();
PortabilityLayer::ResolveCachingColor blueColor = StdColors::Blue();
PortabilityLayer::RenderedFont *appFont = GetApplicationFont(9, 0, true);
PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication9);
DrawSurface *surface = coordWindow->GetDrawSurface();

View File

@@ -11,6 +11,7 @@
#include "PLNumberFormatting.h"
#include "PLPasStr.h"
#include "PLStandardColors.h"
#include "PLSysCalls.h"
#include "PLWidgets.h"
#include "QDStandardPalette.h"
#include "DialogUtils.h"
@@ -341,6 +342,8 @@ void ZoomOutAlertRect (short alertID)
void FlashDialogButton (Dialog *theDialog, short itemNumber)
{
PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE();
ControlHandle itemHandle;
UInt32 dummyLong;
@@ -568,7 +571,7 @@ void DrawDialogUserText (Dialog *dial, short item, StringPtr text, Boolean inver
DrawSurface *surface = dial->GetWindow()->GetDrawSurface();
PortabilityLayer::RenderedFont *appFont = GetApplicationFont(9, PortabilityLayer::FontFamilyFlag_None, true);
PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication9);
PasStringCopy(text, stringCopy);
@@ -619,7 +622,7 @@ void DrawDialogUserText2 (Dialog *dial, short item, StringPtr text)
Str255 stringCopy;
DrawSurface *surface = dial->GetWindow()->GetDrawSurface();
PortabilityLayer::RenderedFont *appFont = GetApplicationFont(9, PortabilityLayer::FontFamilyFlag_None, true);
PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication9);
PasStringCopy(text, stringCopy);
const Rect iRect = dial->GetItems()[item - 1].GetWidget()->GetRect();

View File

@@ -19,6 +19,7 @@
#include "PLPasStr.h"
#include <algorithm>
#include <cmath>
#define kSwitchDepthAlert 130
#define kSetMemoryAlert 180

View File

@@ -3,7 +3,7 @@
// Environ.h
//----------------------------------------------------------------------------
//============================================================================
#pragma once
#include "PLQDraw.h"

View File

@@ -19,6 +19,7 @@
#include "Rect2i.h"
#include "WindowManager.h"
#include "PLSysCalls.h"
void HandleMouseEvent (const GpMouseInputEvent &, uint32_t);
void HandleKeyEvent (const KeyDownStates &keyStates, const GpKeyboardInputEvent &);
@@ -419,7 +420,10 @@ void HandleEvent (void)
SelectTool(kSelectTool);
}
itHappened = WaitForEvent(&theEvent, sleep);
{
PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE();
itHappened = WaitForEvent(&theEvent, sleep);
}
if (itHappened)
{

View File

@@ -21,6 +21,7 @@
#include "RenderedFont.h"
#include "ResolveCachingColor.h"
#include "Utilities.h"
#include "PLSysCalls.h"
#define kNumCountDownFrames 16
@@ -107,7 +108,7 @@ void SetUpFinalScreen (void)
{
GetLineOfText(tempStr, count, subStr);
PortabilityLayer::RenderedFont *appFont = GetApplicationFont(12, PortabilityLayer::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12Bold);
offset = ((thisMac.constrainedScreen.right - thisMac.constrainedScreen.left) -
appFont->MeasurePStr(subStr)) / 2;
@@ -489,6 +490,7 @@ void DoDiedGameOver (void)
}
}
PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE();
Delay(1, nullptr);
}
while (TickCount() < nextLoop);

View File

@@ -14,13 +14,12 @@ void gpAppInit();
class GpAppInterfaceImpl final : public GpAppInterface
{
public:
void ApplicationInit() override;
int ApplicationMain() override;
void ApplicationInit() GP_ASYNCIFY_PARANOID_OVERRIDE;
int ApplicationMain() GP_ASYNCIFY_PARANOID_OVERRIDE;
void PL_IncrementTickCounter(uint32_t count) override;
void PL_Render(IGpDisplayDriver *displayDriver) override;
GpDriverCollection *PL_GetDriverCollection() override;
void PL_InstallHostSuspendHook(PortabilityLayer::HostSuspendHook_t hook, void *context) override;
bool PL_AdjustRequestedResolution(uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualheight, float &pixelScaleX, float &pixelScaleY) override;
};
@@ -31,7 +30,11 @@ void GpAppInterfaceImpl::ApplicationInit()
int GpAppInterfaceImpl::ApplicationMain()
{
#if GP_ASYNCIFY_PARANOID
return gpAppMain();
#else
return PLSysCalls::MainExitWrapper(gpAppMain);
#endif
}
void GpAppInterfaceImpl::PL_IncrementTickCounter(uint32_t count)
@@ -50,11 +53,6 @@ GpDriverCollection *GpAppInterfaceImpl::PL_GetDriverCollection()
return PLDrivers::GetDriverCollection();
}
void GpAppInterfaceImpl::PL_InstallHostSuspendHook(PortabilityLayer::HostSuspendHook_t hook, void *context)
{
PortabilityLayer::InstallHostSuspendHook(hook, context);
}
bool GpAppInterfaceImpl::PL_AdjustRequestedResolution(uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualheight, float &pixelScaleX, float &pixelScaleY)
{
PortabilityLayer::DisplayDeviceManager::IResolutionChangeHandler *handler = PortabilityLayer::DisplayDeviceManager::GetInstance()->GetResolutionChangeHandler();
@@ -75,3 +73,15 @@ GP_APP_DLL_EXPORT_API GpAppInterface *GpAppInterface_Get()
{
return &gs_application;
}
#if GP_ASYNCIFY_PARANOID
void GpAppInterface::ApplicationInit()
{
static_cast<GpAppInterfaceImpl*>(this)->ApplicationInit();
}
int GpAppInterface::ApplicationMain()
{
return static_cast<GpAppInterfaceImpl*>(this)->ApplicationMain();
}
#endif

69
GpApp/GpApp_Combined.cpp Normal file
View File

@@ -0,0 +1,69 @@
#include "About.cpp"
#include "AnimCursor.cpp"
#include "AppleEvents.cpp"
#include "Banner.cpp"
#include "ColorUtils.cpp"
#include "Coordinates.cpp"
#include "DialogUtils.cpp"
#include "DynamicMaps.cpp"
#include "Dynamics.cpp"
#include "Dynamics2.cpp"
#include "Dynamics3.cpp"
#include "Environ.cpp"
#include "Events.cpp"
#include "FileError.cpp"
#include "GameOver.cpp"
#include "GpAppInterface.cpp"
#include "Grease.cpp"
#include "HighScores.cpp"
#include "House.cpp"
#include "HouseInfo.cpp"
#include "HouseIO.cpp"
#include "HouseLegal.cpp"
#include "Input.cpp"
#include "Interactions.cpp"
#include "InterfaceInit.cpp"
#include "Link.cpp"
#include "Main.cpp"
#include "MainMenuUI.cpp"
#include "MainWindow.cpp"
#include "Map.cpp"
#include "Marquee.cpp"
#include "Menu.cpp"
#include "Modes.cpp"
#include "Music.cpp"
#include "ObjectAdd.cpp"
#include "ObjectDraw.cpp"
#include "ObjectDraw2.cpp"
#include "ObjectDrawAll.cpp"
#include "ObjectEdit.cpp"
#include "ObjectInfo.cpp"
#include "ObjectRects.cpp"
#include "Objects.cpp"
#include "Play.cpp"
#include "Player.cpp"
#include "Prefs.cpp"
#include "RectUtils.cpp"
#include "Render.cpp"
#include "Room.cpp"
#include "RoomGraphics.cpp"
#include "RoomInfo.cpp"
#include "RubberBands.cpp"
#include "SavedGames.cpp"
#include "Scoreboard.cpp"
#include "Scrap.cpp"
#include "SelectHouse.cpp"
#include "Settings.cpp"
#include "Sound.cpp"
#include "SoundSync_Cpp11.cpp"
#include "SourceExport.cpp"
#include "StringUtils.cpp"
#include "StructuresInit.cpp"
#include "StructuresInit2.cpp"
#include "Tools.cpp"
#include "Transit.cpp"
#include "Transitions.cpp"
#include "Triggers.cpp"
#include "Trip.cpp"
#include "Utilities.cpp"
#include "WindowUtils.cpp"

View File

@@ -96,8 +96,12 @@ void DoHighScores (void)
// DissBits(&workSrcRect);
InitCursor();
DelayTicks(60);
WaitForInputEvent(30);
{
PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE();
DelayTicks(60);
WaitForInputEvent(30);
}
RedrawSplashScreen();
}
@@ -145,7 +149,7 @@ void DrawHighScores (DrawSurface *surface)
DisposeGWorld(tempMap);
DisposeGWorld(tempMask);
PortabilityLayer::RenderedFont *appFont14 = GetApplicationFont(14, PortabilityLayer::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *appFont14 = GetFont(PortabilityLayer::FontPresets::kApplication14Bold);
PasStringCopy(PSTR("\xa5 "), tempStr);
PasStringConcat(tempStr, thisHouseName);
@@ -157,7 +161,7 @@ void DrawHighScores (DrawSurface *surface)
const Point scoreTextPoint = Point::Create(scoreLeft + ((kScoreWide - appFont14->MeasurePStr(tempStr)) / 2), dropIt - 65);
surface->DrawString(scoreTextPoint, tempStr, cyanColor, appFont14);
PortabilityLayer::RenderedFont *appFont12 = GetApplicationFont(12, PortabilityLayer::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *appFont12 = GetFont(PortabilityLayer::FontPresets::kApplication12Bold);
thisHousePtr = *thisHouse;
// message for score #1
@@ -264,7 +268,7 @@ void DrawHighScores (DrawSurface *surface)
}
}
PortabilityLayer::RenderedFont *appFont9 = GetApplicationFont(9, PortabilityLayer::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *appFont9 = GetFont(PortabilityLayer::FontPresets::kApplication9Bold);
const Point textPos = Point::Create(scoreLeft + 80, dropIt - 1 + (10 * kScoreSpacing));
GetLocalizedString(8, tempStr);
@@ -553,7 +557,7 @@ void GetHighScoreName (short place)
while (!leaving)
{
item = theDial->ExecuteModal(nullptr, NameFilter);
item = theDial->ExecuteModal(nullptr, PL_FILTER_FUNC(NameFilter));
if (item == kOkayButton)
{
@@ -666,7 +670,7 @@ void GetHighScoreBanner (void)
while (!leaving)
{
item = theDial->ExecuteModal(nullptr, BannerFilter);
item = theDial->ExecuteModal(nullptr, PL_FILTER_FUNC(BannerFilter));
if (item == kOkayButton)
{
@@ -789,3 +793,5 @@ Boolean ReadScoresFromDisk (void)
return (true);
}
PL_IMPLEMENT_FILTER_FUNCTION(NameFilter)
PL_IMPLEMENT_FILTER_FUNCTION(BannerFilter)

View File

@@ -52,24 +52,24 @@ extern Boolean houseOpen, noRoomAtAll;
extern Boolean twoPlayerGame, wardBitSet, phoneBitSet;
static void FBUI_DrawLabels(DrawSurface *surface, const Point &basePoint)
static void FBUI_House_DrawLabels(DrawSurface *surface, const Point &basePoint)
{
}
static void FBUI_DrawFileDetails(DrawSurface *surface, const Point &basePoint, const Rect &constraintRect, void *fileDetails)
static void FBUI_House_DrawFileDetails(DrawSurface *surface, const Point &basePoint, const Rect &constraintRect, void *fileDetails)
{
}
static void *FBUI_LoadFileDetails(PortabilityLayer::VirtualDirectory_t dirID, const PLPasStr &filename)
static void *FBUI_House_LoadFileDetails(PortabilityLayer::VirtualDirectory_t dirID, const PLPasStr &filename)
{
return nullptr;
}
static void FBUI_FreeFileDetails(void *fileDetails)
static void FBUI_House_FreeFileDetails(void *fileDetails)
{
}
static bool FBUI_FilterFile(PortabilityLayer::VirtualDirectory_t dirID, const PLPasStr &filename)
static bool FBUI_House_FilterFile(PortabilityLayer::VirtualDirectory_t dirID, const PLPasStr &filename)
{
PortabilityLayer::CompositeFile *cfile = PortabilityLayer::FileManager::GetInstance()->OpenCompositeFile(dirID, filename);
@@ -80,11 +80,11 @@ static PortabilityLayer::FileBrowserUI_DetailsCallbackAPI GetHouseDetailsAPI()
{
PortabilityLayer::FileBrowserUI_DetailsCallbackAPI api;
api.m_drawLabelsCallback = FBUI_DrawLabels;
api.m_drawFileDetailsCallback = FBUI_DrawFileDetails;
api.m_loadFileDetailsCallback = FBUI_LoadFileDetails;
api.m_freeFileDetailsCallback = FBUI_FreeFileDetails;
api.m_filterFileCallback = FBUI_FilterFile;
api.m_drawLabelsCallback = FBUI_House_DrawLabels;
api.m_drawFileDetailsCallback = FBUI_House_DrawFileDetails;
api.m_loadFileDetailsCallback = FBUI_House_LoadFileDetails;
api.m_freeFileDetailsCallback = FBUI_House_FreeFileDetails;
api.m_filterFileCallback = FBUI_House_FilterFile;
return api;
}
@@ -707,7 +707,7 @@ int16_t GoToFilter(void *context, Dialog *dial, const TimeTaggedVOSEvent *evt)
while (!leaving)
{
item = theDialog->ExecuteModal(nullptr, GoToFilter);
item = theDialog->ExecuteModal(nullptr, PL_FILTER_FUNC(GoToFilter));
if (item == kOkayButton)
{
@@ -863,3 +863,4 @@ void ShiftWholeHouse (short howFar)
CloseMessageWindow();
}
PL_IMPLEMENT_FILTER_FUNCTION(GoToFilter)

View File

@@ -12,6 +12,7 @@
#include "FileManager.h"
#include "GpIOStream.h"
#include "House.h"
#include "IGpLogDriver.h"
#include "IGpSystemServices.h"
#include "ObjectEdit.h"
#include "ResourceManager.h"
@@ -858,6 +859,11 @@ Boolean QuerySaveChanges (void)
void YellowAlert (short whichAlert, short identifier)
{
IGpLogDriver *logger = PLDrivers::GetLogDriver();
if (logger)
logger->Printf(IGpLogDriver::Category_Warning, "Yellow alert %i identifier %i", static_cast<int>(whichAlert), static_cast<int>(identifier));
#define kYellowAlert 1006
Str255 errStr, errNumStr;
short whoCares;

View File

@@ -249,7 +249,7 @@ void DoHouseInfo (void)
while (!leaving)
{
item = houseInfoDialog->ExecuteModal(nullptr, HouseFilter);
item = houseInfoDialog->ExecuteModal(nullptr, PL_FILTER_FUNC(HouseFilter));
if (item == kOkayButton)
{
@@ -334,3 +334,4 @@ void HowToZeroScores (void)
#endif
PL_IMPLEMENT_FILTER_FUNCTION(HouseFilter)

View File

@@ -158,7 +158,7 @@ void DrawTouchScreenMenu (DrawSurface *surface, const THandle<BitmapImage> &back
const int numItems = sizeof(itemTexts) / sizeof(itemTexts[0]);
PortabilityLayer::RenderedFont *rfont = GetHandwritingFont(48, PortabilityLayer::FontFamilyFlag_None, true);
PortabilityLayer::RenderedFont *rfont = GetFont(PortabilityLayer::FontPresets::kHandwriting48);
if (!rfont)
return;

View File

@@ -15,6 +15,7 @@
#include "FontManager.h"
#include "GpApplicationName.h"
#include "GpRenderedFontMetrics.h"
#include "IGpLogDriver.h"
#include "IGpMutex.h"
#include "IGpThreadEvent.h"
#include "IGpDisplayDriver.h"
@@ -43,14 +44,6 @@
#include <atomic>
int loadScreenWindowPhase;
int loadScreenRingStep;
WindowPtr loadScreenWindow;
Rect loadScreenProgressBarRect;
int loadScreenProgress;
DrawSurface *loadScreenRingSurface;
#define kPrefsVersion 0x0039
@@ -364,545 +357,6 @@ void WriteOutPrefs (void)
modulePrefs.Dispose();
}
void StepLoadScreenRing()
{
if (loadScreenWindow)
{
const int loadScreenStepGranularity = 2;
loadScreenRingStep++;
if (loadScreenRingStep == 24 * loadScreenStepGranularity)
loadScreenRingStep = 0;
Rect ringDestRect = Rect::Create(8, 8, 24, 24);
Rect ringSrcRect = Rect::Create(0, 0, 16, 16) + Point::Create((loadScreenRingStep / loadScreenStepGranularity) * 16, 0);
if (loadScreenWindowPhase == 0)
{
ringDestRect = Rect::Create(0, 0, 64, 64);
const int progression = (loadScreenRingStep / loadScreenStepGranularity);
ringSrcRect = Rect::Create(0, 0, 64, 64) + Point::Create((progression % 6) * 64, (progression / 6) * 64);
}
CopyBits(*loadScreenRingSurface->m_port.GetPixMap(), *loadScreenWindow->GetDrawSurface()->m_port.GetPixMap(), &ringSrcRect, &ringDestRect, srcCopy);
loadScreenWindow->GetDrawSurface()->m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents);
}
}
void CreateLoadScreenWindow(int phase)
{
FlushResolutionChange();
if (loadScreenRingSurface)
{
DisposeGWorld(loadScreenRingSurface);
loadScreenRingSurface = nullptr;
}
if (loadScreenWindow)
{
PortabilityLayer::WindowManager::GetInstance()->DestroyWindow(loadScreenWindow);
loadScreenWindow = nullptr;
}
if (phase == 0)
{
static const int kLoadScreenHeight = 64;
static const int kLoadScreenWidth = 64;
static const int kLoadRingResource = 1303;
ForceSyncFrame();
PLSysCalls::Sleep(1);
THandle<BitmapImage> loadRingImageH = PortabilityLayer::ResourceManager::GetInstance()->GetAppResource('PICT', kLoadRingResource).StaticCast<BitmapImage>();
BitmapImage *loadRingImage = *loadRingImageH;
DrawSurface *loadRingSurface = nullptr;
Rect loadRingRect = loadRingImage->GetRect();
loadRingRect.right *= 2;
loadRingRect.bottom *= 2;
CreateOffScreenGWorld(&loadRingSurface, &loadRingRect);
loadRingSurface->DrawPicture(loadRingImageH, loadRingRect, false);
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::kBorderless, 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());
surface->FillRect(loadScreenLocalRect, blackColor);
loadScreenProgressBarRect = Rect::Create(0, 0, 0, 0);
loadScreenProgress = 0;
Rect ringDestRect = Rect::Create(0, 0, 64, 64);
Rect ringSrcRect = Rect::Create(0, 0, 64, 64);
CopyBits(*loadRingSurface->m_port.GetPixMap(), *surface->m_port.GetPixMap(), &ringSrcRect, &ringDestRect, srcCopy);
loadRingImageH.Dispose();
loadScreenRingSurface = loadRingSurface;
}
else if (phase == 1)
{
static const int kLoadScreenHeight = 32;
static const int kLoadRingResource = 1302;
int kLoadScreenWidth = 296;
PLPasStr loadingText = PSTR("Loading...");
if (!isPrefsLoaded)
{
loadingText = PSTR("Getting some things ready...");
kLoadScreenWidth = 440;
}
ForceSyncFrame();
PLSysCalls::Sleep(1);
THandle<BitmapImage> loadRingImageH = PortabilityLayer::ResourceManager::GetInstance()->GetAppResource('PICT', kLoadRingResource).StaticCast<BitmapImage>();
BitmapImage *loadRingImage = *loadRingImageH;
DrawSurface *loadRingSurface = nullptr;
Rect loadRingRect = loadRingImage->GetRect();
CreateOffScreenGWorld(&loadRingSurface, &loadRingRect);
loadRingSurface->DrawPicture(loadRingImageH, loadRingRect, false);
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);
PortabilityLayer::RenderedFont *font = GetApplicationFont(18, PortabilityLayer::FontFamilyFlag_None, true);
int32_t textY = (kLoadScreenHeight + font->GetMetrics().m_ascent) / 2;
surface->DrawString(Point::Create(4 + 16 + 8, textY), loadingText, blackColor, font);
static const int32_t loadBarPadding = 16;
static const int32_t loadBarHeight = 10;
int32_t loadBarStartX = static_cast<int32_t>(font->MeasureString(loadingText.UChars(), loadingText.Length())) + 4 + 16 + 8 + loadBarPadding;
int32_t loadBarEndX = loadScreenLocalRect.right - loadBarPadding;
loadScreenProgressBarRect = Rect::Create((loadScreenLocalRect.Height() - loadBarHeight) / 2, loadBarStartX, (loadScreenLocalRect.Height() + loadBarHeight) / 2, loadBarEndX);
PortabilityLayer::ResolveCachingColor partialFillColor(PortabilityLayer::RGBAColor::Create(255, 255, 204, 255));
surface->FrameRect(loadScreenProgressBarRect, blackColor);
surface->FillRect(loadScreenProgressBarRect.Inset(1, 1), partialFillColor);
Rect ringDestRect = Rect::Create(8, 8, 24, 24);
Rect ringSrcRect = Rect::Create(0, 0, 16, 16);
CopyBits(*loadRingSurface->m_port.GetPixMap(), *surface->m_port.GetPixMap(), &ringSrcRect, &ringDestRect, srcCopy);
loadRingImageH.Dispose();
loadScreenRingSurface = loadRingSurface;
}
}
void StepLoadScreen(int steps, bool insertDelay)
{
if (loadScreenWindow)
{
static const int kLoadScreenPhaseSwitchBreakpoint = 20;
int oldProgress = loadScreenProgress;
if (loadScreenProgress + steps >= kLoadScreenPhaseSwitchBreakpoint && loadScreenWindowPhase == 0)
{
loadScreenWindowPhase = 1;
CreateLoadScreenWindow(loadScreenWindowPhase);
// Reset old progress since the progress bar was redrawn
oldProgress = 0;
}
const Rect loadScreenProgressBarFillRect = loadScreenProgressBarRect.Inset(1, 1);
int loadScreenMax = 43;
loadScreenProgress = loadScreenProgress + steps;
if (loadScreenProgress > loadScreenMax)
loadScreenProgress = loadScreenMax;
PortabilityLayer::ResolveCachingColor fillColor(PortabilityLayer::RGBAColor::Create(51, 51, 51, 255));
int prevStep = oldProgress * loadScreenProgressBarFillRect.Width() / loadScreenMax;
int thisStep = loadScreenProgress * loadScreenProgressBarFillRect.Width() / loadScreenMax;
loadScreenWindow->GetDrawSurface()->FillRect(Rect::Create(loadScreenProgressBarFillRect.top, loadScreenProgressBarFillRect.left + prevStep, loadScreenProgressBarFillRect.bottom, loadScreenProgressBarFillRect.left + thisStep), fillColor);
ForceSyncFrame();
if (insertDelay)
{
StepLoadScreenRing();
Delay(1, nullptr);
}
}
else
SpinCursor(steps);
}
void InitLoadingWindow()
{
// Only phones are slow enough for this to matter
if (!thisMac.isTouchscreen)
return;
if (isPrefsLoaded)
loadScreenWindowPhase = 1;
else
loadScreenWindowPhase = 0;
CreateLoadScreenWindow(loadScreenWindowPhase);
}
enum PreloadFontCategory
{
FontCategory_System,
FontCategory_Application,
FontCategory_Handwriting,
FontCategory_Monospace,
};
struct PreloadFontSpec
{
PreloadFontCategory m_category;
int m_size;
int m_flags;
bool m_aa;
};
struct PreloadFontWorkSlot
{
IGpThreadEvent *m_completedEvent;
PortabilityLayer::WorkerThread *m_workerThread;
std::atomic<int> m_singleJobCompleted;
const PreloadFontSpec *m_spec;
bool m_queued;
PreloadFontWorkSlot();
~PreloadFontWorkSlot();
};
PreloadFontWorkSlot::PreloadFontWorkSlot()
: m_completedEvent(nullptr)
, m_workerThread(nullptr)
, m_spec(nullptr)
, m_queued(false)
{
}
PreloadFontWorkSlot::~PreloadFontWorkSlot()
{
if (m_workerThread)
m_workerThread->Destroy();
}
void PreloadSingleFont (const PreloadFontSpec &spec)
{
switch (spec.m_category)
{
case FontCategory_Application:
GetApplicationFont(spec.m_size, spec.m_flags, spec.m_aa);
break;
case FontCategory_System:
GetSystemFont(spec.m_size, spec.m_flags, spec.m_aa);
break;
case FontCategory_Handwriting:
GetHandwritingFont(spec.m_size, spec.m_flags, spec.m_aa);
break;
case FontCategory_Monospace:
GetMonospaceFont(spec.m_size, spec.m_flags, spec.m_aa);
break;
default:
break;
}
}
void PreloadFontThreadFunc(void *context)
{
PreloadFontWorkSlot *wSlot = static_cast<PreloadFontWorkSlot*>(context);
PreloadSingleFont(*wSlot->m_spec);
wSlot->m_singleJobCompleted.fetch_add(1, std::memory_order_release);
wSlot->m_completedEvent->Signal();
}
void PreloadFonts()
{
static PreloadFontSpec specs[] =
{
// First entry should be the one needed to show the load screen
{ FontCategory_Application, 18, PortabilityLayer::FontFamilyFlag_None, true },
{ FontCategory_System, 9, PortabilityLayer::FontFamilyFlag_Bold, true },
{ FontCategory_System, 10, PortabilityLayer::FontFamilyFlag_Bold, true },
{ FontCategory_System, 12, PortabilityLayer::FontFamilyFlag_None, true },
{ FontCategory_System, 12, PortabilityLayer::FontFamilyFlag_Bold, true },
{ FontCategory_Application, 8, PortabilityLayer::FontFamilyFlag_None, true },
{ FontCategory_Application, 9, PortabilityLayer::FontFamilyFlag_None, true },
{ FontCategory_Application, 12, PortabilityLayer::FontFamilyFlag_Bold, true },
{ FontCategory_Application, 14, PortabilityLayer::FontFamilyFlag_Bold, true },
{ FontCategory_Application, 14, PortabilityLayer::FontFamilyFlag_None, true },
{ FontCategory_Application, 40, PortabilityLayer::FontFamilyFlag_None, true },
{ FontCategory_Handwriting, 24, PortabilityLayer::FontFamilyFlag_None, true },
{ FontCategory_Handwriting, 48, PortabilityLayer::FontFamilyFlag_None, true },
{ FontCategory_Monospace, 10, PortabilityLayer::FontFamilyFlag_None, true },
};
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
const int numFontSpecs = sizeof(specs) / sizeof(specs[0]);
int queuedSpecs = 0;
int completedSpecs = 0;
// We can't actually slot these because FT isn't thread-safe when accessing the same font,
// but we can do this to unclog the render thread.
PreloadFontWorkSlot slot;
slot.m_workerThread = PortabilityLayer::WorkerThread::Create();
slot.m_completedEvent = PLDrivers::GetSystemServices()->CreateThreadEvent(true, false);
while (completedSpecs < numFontSpecs)
{
if (slot.m_queued)
{
if (slot.m_singleJobCompleted.load(std::memory_order_acquire) != 0)
{
slot.m_completedEvent->Wait();
slot.m_queued = false;
completedSpecs++;
StepLoadScreen(1, false);
}
}
if (!slot.m_queued)
{
if (queuedSpecs < numFontSpecs)
{
slot.m_queued = true;
slot.m_spec = specs + queuedSpecs;
slot.m_singleJobCompleted.store(0, std::memory_order_release);
slot.m_workerThread->AsyncExecuteTask(PreloadFontThreadFunc, &slot);
queuedSpecs++;
}
}
StepLoadScreenRing();
Delay(1, nullptr);
}
PortabilityLayer::FontManager::GetInstance()->PurgeCache();
}
struct PreloadAATableSpec
{
PortabilityLayer::RGBAColor m_color;
bool m_isTone;
};
struct PreloadAATableWorkSlot
{
IGpThreadEvent *m_completedEvent;
IGpMutex *m_mutex;
PortabilityLayer::WorkerThread *m_workerThread;
std::atomic<int> m_singleJobCompleted;
const PreloadAATableSpec *m_spec;
bool m_queued;
PreloadAATableWorkSlot();
~PreloadAATableWorkSlot();
};
PreloadAATableWorkSlot::PreloadAATableWorkSlot()
: m_completedEvent(nullptr)
, m_workerThread(nullptr)
, m_spec(nullptr)
, m_queued(false)
{
}
PreloadAATableWorkSlot::~PreloadAATableWorkSlot()
{
if (m_workerThread)
m_workerThread->Destroy();
}
void PreloadAATableThreadFunc(void *context)
{
PreloadAATableWorkSlot *wSlot = static_cast<PreloadAATableWorkSlot*>(context);
PortabilityLayer::StandardPalette *sp = PortabilityLayer::StandardPalette::GetInstance();
if (wSlot->m_spec->m_isTone)
sp->GetCachedToneAATable(wSlot->m_spec->m_color.r, wSlot->m_mutex);
else
sp->GetCachedPaletteAATable(wSlot->m_spec->m_color, wSlot->m_mutex);
wSlot->m_singleJobCompleted.fetch_add(1, std::memory_order_release);
wSlot->m_completedEvent->Signal();
}
void PreloadAATables()
{
PortabilityLayer::StandardPalette *sp = PortabilityLayer::StandardPalette::GetInstance();
PortabilityLayer::RGBAColor preloadColors[] =
{
PortabilityLayer::RGBAColor::Create(255, 255, 255, 255),
PortabilityLayer::RGBAColor::Create(255, 51, 51, 255),
PortabilityLayer::RGBAColor::Create(255, 0, 0, 255),
PortabilityLayer::RGBAColor::Create(255, 255, 0, 255),
PortabilityLayer::RGBAColor::Create(0, 255, 255, 255),
PortabilityLayer::RGBAColor::Create(0, 0, 255, 255),
PortabilityLayer::RGBAColor::Create(204, 102, 51, 255),
};
const size_t numPalettePreloads = sizeof(preloadColors) / sizeof(preloadColors[0]);
const size_t maxTonePreloads = numPalettePreloads * 3;
PreloadAATableSpec specs[numPalettePreloads + maxTonePreloads];
for (size_t i = 0; i < numPalettePreloads; i++)
{
specs[i].m_color = preloadColors[i];
specs[i].m_isTone = false;
}
size_t numTonePreloads = 0;
for (size_t i = 0; i < numPalettePreloads; i++)
{
const uint8_t rgb[3] = { preloadColors[i].r, preloadColors[i].g, preloadColors[i].b };
for (int ch = 0; ch < 3; ch++)
{
uint8_t tone = rgb[ch];
bool toneAlreadyQueued = false;
for (size_t j = 0; j < numTonePreloads; j++)
{
if (specs[numPalettePreloads + j].m_color.r == tone)
{
toneAlreadyQueued = true;
break;
}
}
if (!toneAlreadyQueued)
{
PreloadAATableSpec &spec = specs[i + numTonePreloads];
numTonePreloads++;
spec.m_color = PortabilityLayer::RGBAColor::Create(tone, tone, tone, 255);
spec.m_isTone = true;
}
}
}
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
const int numAASpecs = numPalettePreloads + numTonePreloads;
unsigned int cpus = PLDrivers::GetSystemServices()->GetCPUCount();
if (cpus < 2)
{
for (size_t i = 0; i < numAASpecs; i++)
{
PreloadAATableThreadFunc(specs + i);
StepLoadScreen(1, false);
}
}
else
{
cpus -= 1;
int queuedSpecs = 0;
int completedSpecs = 0;
PreloadAATableWorkSlot *slots = static_cast<PreloadAATableWorkSlot*>(mm->Alloc(sizeof(PreloadAATableWorkSlot) * cpus));
IGpMutex *mutex = PLDrivers::GetSystemServices()->CreateMutex();
for (unsigned int i = 0; i < cpus; i++)
{
PreloadAATableWorkSlot *slot = new (slots + i) PreloadAATableWorkSlot();
slot->m_workerThread = PortabilityLayer::WorkerThread::Create();
slot->m_completedEvent = PLDrivers::GetSystemServices()->CreateThreadEvent(true, false);
slot->m_mutex = mutex;
}
while (completedSpecs < numAASpecs)
{
int completedThisStep = 0;
for (unsigned int i = 0; i < cpus; i++)
{
PreloadAATableWorkSlot &slot = slots[i];
if (slot.m_queued)
{
if (slot.m_singleJobCompleted.load(std::memory_order_acquire) != 0)
{
slot.m_completedEvent->Wait();
slot.m_queued = false;
completedSpecs++;
completedThisStep++;
}
}
if (!slot.m_queued)
{
if (queuedSpecs < numAASpecs)
{
slot.m_queued = true;
slot.m_spec = specs + queuedSpecs;
slot.m_singleJobCompleted.store(0, std::memory_order_release);
slot.m_workerThread->AsyncExecuteTask(PreloadAATableThreadFunc, &slot);
queuedSpecs++;
}
}
}
if (completedThisStep > 0)
StepLoadScreen(completedThisStep, false);
StepLoadScreenRing();
Delay(1, nullptr);
}
for (unsigned int i = 0; i < cpus; i++)
slots[i].~PreloadAATableWorkSlot();
mm->Release(slots);
mutex->Destroy();
}
}
void ShowInitialLaunchDisclaimer()
{
const char *disclaimerLines[] =
@@ -930,8 +384,8 @@ void ShowInitialLaunchDisclaimer()
const size_t numLines = sizeof(disclaimerLines) / sizeof(disclaimerLines[0]);
PortabilityLayer::RenderedFont *rfont = GetApplicationFont(14, PortabilityLayer::FontFamilyFlag_None, true);
PortabilityLayer::RenderedFont *buttonFont = GetApplicationFont(18, PortabilityLayer::FontFamilyFlag_None, true);
PortabilityLayer::RenderedFont *rfont = GetFont(PortabilityLayer::FontPresets::kApplication14);
PortabilityLayer::RenderedFont *buttonFont = GetFont(PortabilityLayer::FontPresets::kApplication18);
const int kButtonSpacing = 16;
const int kButtonHeight = 32;
@@ -1066,15 +520,20 @@ void gpAppInit()
//-------------------------------------------------------------- main
// Here is main(). The first function called when Glider PRO comes up.
int gpAppMain()
int AppStartup()
{
// long wasSeed;
// long wasSeed;
long theErr;
PLError_t fileErr;
Boolean whoCares, copyGood;
PL_Init();
IGpLogDriver *logger = PLDrivers::GetLogDriver();
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Init phase 1...");
ToolBoxInit();
CheckOurEnvirons();
@@ -1087,23 +546,24 @@ int gpAppMain()
RedAlert(kErrNeedSystem7);
if (thisMac.numScreens == 0)
RedAlert(kErrNeed16Or256Colors);
// dataResFile = OpenResFile("\pMermaid");
// dataResFile = OpenResFile("\pMermaid");
SetUpAppleEvents();
LoadCursors();
ReadInPrefs();
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Init phase 2...");
SpinCursor(2); // Tick once to let the display driver flush any resolution changes from prefs
FlushResolutionChange();
InitLoadingWindow(); StepLoadScreen(2, true);
PreloadAATables();
assert(isPrefsLoaded || loadScreenWindowPhase == 0);
PreloadFonts(); StepLoadScreen(2, true);
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Init phase 3...");
#if defined COMPILEDEMO
copyGood = true;
#elif defined COMPILENOCP
// didValidation = false;
// didValidation = false;
copyGood = true;
#else
didValidation = false;
@@ -1114,28 +574,18 @@ int gpAppMain()
WriteOutPrefs(); SpinCursor(3);
#endif
// if ((thisMac.numScreens > 1) && (isUseSecondScreen))
// ReflectSecondMonitorEnvirons(false, true, true);
// if ((thisMac.numScreens > 1) && (isUseSecondScreen))
// ReflectSecondMonitorEnvirons(false, true, true);
HandleDepthSwitching();
VariableInit(); StepLoadScreen(2, true);
GetExtraCursors(); StepLoadScreen(2, true);
VariableInit();
GetExtraCursors();
InitMarquee();
CreatePointers(); StepLoadScreen(2, true);
CreatePointers();
InitSrcRects();
CreateOffscreens(); StepLoadScreen(2, true);
CreateOffscreens();
if (loadScreenWindow)
{
PortabilityLayer::WindowManager::GetInstance()->FlickerWindowOut(loadScreenWindow, 32);
PortabilityLayer::WindowManager::GetInstance()->DestroyWindow(loadScreenWindow);
PLSysCalls::Sleep(15);
}
if (loadScreenRingSurface)
{
DisposeGWorld(loadScreenRingSurface);
loadScreenRingSurface = nullptr;
}
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Init phase 3...");
bool resolutionChanged = false;
@@ -1149,7 +599,7 @@ int gpAppMain()
FlushResolutionChange();
}
ShowInitialLaunchDisclaimer();
//ShowInitialLaunchDisclaimer();
}
if (thisMac.isResolutionDirty)
@@ -1163,19 +613,32 @@ int gpAppMain()
if (isDoColorFade)
PortabilityLayer::WindowManager::GetInstance()->SetWindowDesaturation(mainWindow, 1.0);
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Init phase 4...");
InitSound(); SpinCursor(2);
InitMusic(); SpinCursor(2);
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Init phase 5...");
BuildHouseList();
OpenHouse(true);
PlayPrioritySound(kBirdSound, kBirdPriority);
DelayTicks(6);
{
PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE();
DelayTicks(6);
}
InitializeMenus(); InitCursor();
#if BUILD_ARCADE_VERSION
// HideMenuBarOld();
// HideMenuBarOld();
#endif
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Initialization completed");
if (isDoColorFade)
WashColorIn();
@@ -1184,14 +647,16 @@ int gpAppMain()
if (thisMac.isTouchscreen)
StartMainMenuUI();
while (!quitting) // this is the main loop
HandleEvent();
return 0;
}
/*
#if BUILD_ARCADE_VERSION
ShowMenuBarOld();
#endif
*/
int AppShutdown()
{
/*
#if BUILD_ARCADE_VERSION
ShowMenuBarOld();
#endif
*/
KillMusic();
KillSound();
if (houseOpen)
@@ -1206,8 +671,19 @@ int gpAppMain()
}
WriteOutPrefs();
PL_DEAD(FlushEvents());
// theErr = LoadScrap();
// theErr = LoadScrap();
return 0;
}
int gpAppMain()
{
int returnCode = AppStartup();
if (returnCode != 0)
return returnCode;
while (!quitting) // this is the main loop
HandleEvent();
return AppShutdown();
}

View File

@@ -64,13 +64,13 @@ struct MainMenuUIState
ControlID m_activeControl;
static const unsigned int kControlHeight = 40;
static const unsigned int kControlFontSize = 24;
static const unsigned int kControlLeftSpacing = 20;
static const unsigned int kControlBottomSpacing = 20;
static const unsigned int kControlIntermediateSpacing = 16;
static const unsigned int kControlInteriorSpacing = 6;
static const unsigned int kControlScrollInDecay = 32;
static const unsigned int kControlScrollInDecayFalloffBits = 0;
static const PortabilityLayer::FontPreset_t kControlFontPreset = PortabilityLayer::FontPresets::kHandwriting24;
};
static MainMenuUIState mainMenu;
@@ -135,7 +135,7 @@ static void DrawMainMenuControl(DrawSurface *surface, MainMenuUIState::ControlID
{
case MainMenuUIState::ControlStyle_Text:
{
PortabilityLayer::RenderedFont *rfont = GetHandwritingFont(MainMenuUIState::kControlFontSize, PortabilityLayer::FontFamilyFlag_None, true);
PortabilityLayer::RenderedFont *rfont = GetFont(MainMenuUIState::kControlFontPreset);
if (!rfont)
return;
@@ -219,7 +219,7 @@ void StartMainMenuUI()
{
DismissMainMenuUI();
PortabilityLayer::RenderedFont *rfont = GetHandwritingFont(MainMenuUIState::kControlFontSize, PortabilityLayer::FontFamilyFlag_None, true);
PortabilityLayer::RenderedFont *rfont = GetFont(MainMenuUIState::kControlFontPreset);
if (!rfont)
return;

View File

@@ -23,6 +23,7 @@
#include "PLDrivers.h"
#include "PLNumberFormatting.h"
#include "PLPasStr.h"
#include "PLSysCalls.h"
#define kMainWindowID 128
#define kEditWindowID 129
@@ -52,6 +53,7 @@ extern short toolSelected;
extern Boolean noRoomAtAll, isUseSecondScreen;
extern Boolean quickerTransitions, houseIsReadOnly;
extern Boolean menusUp;
extern Boolean houseOpen;
//============================================================== Functions
//-------------------------------------------------------------- DrawOnSplash
@@ -61,13 +63,16 @@ extern Boolean menusUp;
void DrawOnSplash(DrawSurface *surface)
{
Str255 houseLoadedStr;
if (!houseOpen)
return;
PasStringCopy(PSTR("House: "), houseLoadedStr);
PasStringConcat(houseLoadedStr, thisHouseName);
if ((thisMac.hasQT) && (hasMovie))
PasStringConcat(houseLoadedStr, PSTR(" (TV)"));
PortabilityLayer::RenderedFont *appFont = GetApplicationFont(9, PortabilityLayer::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication9Bold);
const Point textPoint = Point::Create(splashOriginH + 436, splashOriginV + 314);
if (thisMac.isDepth == 4)
@@ -260,14 +265,14 @@ void OpenMainWindow (void)
// fadeGraysOut = false;
// ForceCTSeed((CGrafPtr)mainWindow, wasSeed);
// }
UpdateMainWindow();
}
CopyBits((BitMap *)*GetGWorldPixMap(workSrcMap),
GetPortBitMapForCopyBits(mainWindow->GetDrawSurface()),
&mainWindowRect, &mainWindowRect, srcCopy);
UpdateMainWindow();
mainWindow->GetDrawSurface()->m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents);
}
@@ -567,6 +572,8 @@ void HardDrawMainWindow (void)
// palette. In this way, color appears to slowly wash in.
void WashColorIn (void)
{
PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE();
#define kGray2ColorSteps 180
long longDelta;
short i, c;

View File

@@ -1057,7 +1057,7 @@ void DrawCalendar (Rect *theRect)
backSrcMap->DrawPicture(thePicture, bounds);
thePicture.Dispose();
PortabilityLayer::RenderedFont *appFont = GetApplicationFont(9, PortabilityLayer::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication9Bold);
GetTime(&timeRec);
GetIndString(monthStr, kMonthStringID, timeRec.month);

View File

@@ -785,7 +785,7 @@ void DoBlowerObjectInfo (short what)
{
bool redrawMain = false;
item = infoDial->ExecuteModal(nullptr, BlowerFilter);
item = infoDial->ExecuteModal(nullptr, PL_FILTER_FUNC(BlowerFilter));
if (item == kOkayButton)
{
@@ -937,7 +937,7 @@ void DoFurnitureObjectInfo (void)
while (!leaving)
{
item = infoDial->ExecuteModal(nullptr, FurnitureFilter);
item = infoDial->ExecuteModal(nullptr, PL_FILTER_FUNC(FurnitureFilter));
if (item == kOkayButton)
leaving = true;
@@ -997,7 +997,7 @@ void DoCustPictObjectInfo (void)
{
bool redrawMain = false;
item = infoDial->ExecuteModal(nullptr, CustPictFilter);
item = infoDial->ExecuteModal(nullptr, PL_FILTER_FUNC(CustPictFilter));
if (item == kOkayButton)
{
@@ -1106,7 +1106,7 @@ void DoSwitchObjectInfo (void)
while (!leaving)
{
item = infoDial->ExecuteModal(nullptr, SwitchFilter);
item = infoDial->ExecuteModal(nullptr, PL_FILTER_FUNC(SwitchFilter));
if (item == kOkayButton)
{
@@ -1231,7 +1231,7 @@ void DoTriggerObjectInfo (void)
while (!leaving)
{
item = infoDial->ExecuteModal(nullptr, TriggerFilter);
item = infoDial->ExecuteModal(nullptr, PL_FILTER_FUNC(TriggerFilter));
if (item == kOkayButton)
{
@@ -1371,7 +1371,7 @@ void DoLightObjectInfo (void)
while (!leaving)
{
bool redrawMain = false;
item = infoDial->ExecuteModal(nullptr, LightFilter);
item = infoDial->ExecuteModal(nullptr, PL_FILTER_FUNC(LightFilter));
if (item == kOkayButton)
{
@@ -1465,7 +1465,7 @@ void DoApplianceObjectInfo (short what)
while (!leaving)
{
bool redrawMain = false;
item = infoDial->ExecuteModal(nullptr, ApplianceFilter);
item = infoDial->ExecuteModal(nullptr, PL_FILTER_FUNC(ApplianceFilter));
if (item == kOkayButton)
{
@@ -1585,7 +1585,7 @@ void DoMicrowaveObjectInfo (void)
while (!leaving)
{
bool redrawMain = false;
item = infoDial->ExecuteModal(nullptr, MicrowaveFilter);
item = infoDial->ExecuteModal(nullptr, PL_FILTER_FUNC(MicrowaveFilter));
if (item == kOkayButton)
{
@@ -1695,7 +1695,7 @@ void DoGreaseObjectInfo (void)
{
bool redrawMain = false;
item = infoDial->ExecuteModal(nullptr, GreaseFilter);
item = infoDial->ExecuteModal(nullptr, PL_FILTER_FUNC(GreaseFilter));
if (item == kOkayButton)
{
@@ -1783,7 +1783,7 @@ void DoInvisBonusObjectInfo (void)
while (!leaving)
{
item = infoDial->ExecuteModal(nullptr, InvisBonusFilter);
item = infoDial->ExecuteModal(nullptr, PL_FILTER_FUNC(InvisBonusFilter));
if (item == kOkayButton)
{
@@ -1907,7 +1907,7 @@ void DoTransObjectInfo (short what)
while (!leaving)
{
item = infoDial->ExecuteModal(nullptr, TransFilter);
item = infoDial->ExecuteModal(nullptr, PL_FILTER_FUNC(TransFilter));
if (item == kOkayButton)
{
@@ -2017,7 +2017,7 @@ void DoEnemyObjectInfo (short what)
while (!leaving)
{
item = infoDial->ExecuteModal(nullptr, EnemyFilter);
item = infoDial->ExecuteModal(nullptr, PL_FILTER_FUNC(EnemyFilter));
if (item == kOkayButton)
{
@@ -2113,7 +2113,7 @@ void DoFlowerObjectInfo (void)
{
bool redrawMain = false;
item = infoDial->ExecuteModal(nullptr, FlowerFilter);
item = infoDial->ExecuteModal(nullptr, PL_FILTER_FUNC(FlowerFilter));
if (item == kOkayButton)
{
@@ -2361,3 +2361,17 @@ void DoObjectInfo (void)
#endif
PL_IMPLEMENT_FILTER_FUNCTION(BlowerFilter)
PL_IMPLEMENT_FILTER_FUNCTION(FurnitureFilter)
PL_IMPLEMENT_FILTER_FUNCTION(CustPictFilter)
PL_IMPLEMENT_FILTER_FUNCTION(SwitchFilter)
PL_IMPLEMENT_FILTER_FUNCTION(TriggerFilter)
PL_IMPLEMENT_FILTER_FUNCTION(LightFilter)
PL_IMPLEMENT_FILTER_FUNCTION(ApplianceFilter)
PL_IMPLEMENT_FILTER_FUNCTION(MicrowaveFilter)
PL_IMPLEMENT_FILTER_FUNCTION(GreaseFilter)
PL_IMPLEMENT_FILTER_FUNCTION(InvisBonusFilter)
PL_IMPLEMENT_FILTER_FUNCTION(TransFilter)
PL_IMPLEMENT_FILTER_FUNCTION(EnemyFilter)
PL_IMPLEMENT_FILTER_FUNCTION(FlowerFilter)

View File

@@ -16,7 +16,7 @@
#include "RectUtils.h"
#include "Room.h"
#include "RubberBands.h"
#include "PLSysCalls.h"
#define kMaxGarbageRects 48
@@ -739,6 +739,7 @@ void RenderFrame (void)
while (TickCount() < nextFrame)
{
PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE();
Delay(1, nullptr);
}
nextFrame = TickCount() + kTicksPerFrame;

Some files were not shown because too many files have changed in this diff Show More