Compare commits

...

78 Commits
1.0.10 ... 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
elasota
2fe1ea2ee7 Fix objects being draggable when there is no room 2021-03-08 21:59:11 -05:00
elasota
0931f25f23 Fix wrong house sort order 2021-03-08 21:58:46 -05:00
elasota
7f4d782c0d Fix room count mismatch 2021-03-08 21:58:34 -05:00
elasota
f2cda23b0f Bump version to 1.0.15 2021-03-08 19:08:12 -05:00
elasota
6292705968 Fix insensitive compare not working properly with strings of different length 2021-03-08 19:07:31 -05:00
elasota
6931b3f505 EOL fix 2021-03-08 19:07:06 -05:00
elasota
d70a5b3bfc Add more optimizations 2021-03-07 05:45:24 -05:00
elasota
f0913d0d6a Add MergeGPF to installer project 2021-03-07 05:37:29 -05:00
elasota
80584eb781 Fix California or Bust! house on Android 2021-03-07 05:16:15 -05:00
elasota
fe4a8a55c6 Don't partially delete house when overwriting the current house 2021-03-07 05:08:01 -05:00
elasota
55ec6c516c Fix overwrite warnings not working 2021-03-07 05:07:23 -05:00
elasota
3917e1a370 File system refactor, bug fixes 2021-03-07 04:31:05 -05:00
elasota
6715bcb030 Fix music playing in the editor 2021-03-06 11:34:47 -05:00
elasota
c981a97a20 Fix fullscreen prefs not working in SDL. Add SDL GameController support. 2021-03-05 01:56:32 -05:00
elasota
a5562f96e0 Move portable things to AerofoilPortable. 2021-03-05 00:35:43 -05:00
elasota
d97bd8ad1c Move some C++11 types from Android to AerofoilSDL. 2021-03-01 01:06:56 -05:00
elasota
a43f32ab88 Fix trademark usage 2021-03-01 00:40:30 -05:00
elasota
e94d1511b1 Add 32-bit support to SDL version 2021-02-28 23:31:13 -05:00
elasota
95e4eb4e34 Bump version to 1.0.14, update copyright year 2021-02-28 23:01:53 -05:00
elasota
15bdb97c38 Add volume control to SDL audio driver. 2021-02-28 22:58:01 -05:00
elasota
e7246c1444 Reduce marquee speed 2021-02-20 15:26:44 -05:00
elasota
35b8e922d7 Fix Windows size minimum not working correctly 2021-02-20 15:16:47 -05:00
elasota
3090f70ee6 Bump version to 1.0.13 2021-02-20 15:16:31 -05:00
elasota
484e18a9af Fix resolution desync if resize occurs during the loading screen. 2021-02-20 15:11:31 -05:00
elasota
83d37a7c94 Add system clipboard support to Windows 2020-12-18 00:07:21 -05:00
elasota
fc043af3a1 Bump version to 1.0.12 2020-12-18 00:02:52 -05:00
elasota
2ebd3f2cf3 Whole-word selection in editboxes 2020-12-17 19:49:09 -05:00
elasota
ebab2ee188 Fix incorrect carat pulse timing 2020-12-17 19:48:57 -05:00
elasota
032e44d981 Fix some missing dependencies of ReleasePackageInstaller necessary to import resources. 2020-11-30 23:32:50 -05:00
elasota
7961ca3af7 Fixed some more cases where the screen resolution could become desynced during startup. 2020-11-30 19:02:42 -05:00
elasota
6851025147 Preload entire font file if the font file isn't efficiently seekable, which should fix very slow startup times on Android. 2020-11-30 18:43:17 -05:00
elasota
f0b1d6fff9 Add memory buffer stream 2020-11-30 18:42:35 -05:00
elasota
70e0948847 Log initial resolution 2020-11-30 18:42:22 -05:00
elasota
a698286087 Adjust disclaimer 2020-11-30 10:27:01 -05:00
elasota
b75313fd7b Commit resolution changes 2020-11-30 03:50:57 -05:00
elasota
cab862ed8b Fix exit to shell not working 2020-11-30 03:18:09 -05:00
elasota
553e343abe Fix display resolution desynchronizing with auto-position 2020-11-30 02:59:02 -05:00
elasota
0aa36b27a9 Remove Bluetooth and vibrate permissions 2020-11-30 00:24:58 -05:00
elasota
f6185b1c78 Bump version to 1.0.11 2020-11-30 00:24:23 -05:00
elasota
ff29d5b92c Updated disclaimer 2020-11-30 00:11:21 -05:00
elasota
964c9b8858 Reduce load ring images to grayscale 2020-11-28 11:46:07 -05:00
elasota
8a48726b2e Compress cached fonts 2020-11-28 11:45:51 -05:00
elasota
de06669239 Fix read overrun 2020-11-28 11:45:29 -05:00
279 changed files with 9748 additions and 3804 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

@@ -46,6 +46,9 @@ EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "ReleasePackageInstaller", "ReleasePackageInstaller\ReleasePackageInstaller.wixproj", "{D26BD501-28A7-4849-8130-FB5EA0A2B82F}"
ProjectSection(ProjectDependencies) = postProject
{7EFF1E21-C375-45EA-A069-4E2232C8A72B} = {7EFF1E21-C375-45EA-A069-4E2232C8A72B}
{B852D549-4020-4477-8BFB-E199FF78B047} = {B852D549-4020-4477-8BFB-E199FF78B047}
{2FF15659-5C72-48B8-B55B-3C658E4125B5} = {2FF15659-5C72-48B8-B55B-3C658E4125B5}
{36DAF5FA-6ADB-4F20-9810-1610DE0AE653} = {36DAF5FA-6ADB-4F20-9810-1610DE0AE653}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsUnicodeToolShim", "WindowsUnicodeToolShim\WindowsUnicodeToolShim.vcxproj", "{15009625-1120-405E-8BBA-69A16CD6713D}"
@@ -58,6 +61,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GpFontHandler_FreeType2", "
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AerofoilSDL", "AerofoilSDL\AerofoilSDL.vcxproj", "{33542FF0-0473-4802-BC79-3B8261790F65}"
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
@@ -166,6 +175,18 @@ Global
{33542FF0-0473-4802-BC79-3B8261790F65}.Debug|x64.Build.0 = Debug|x64
{33542FF0-0473-4802-BC79-3B8261790F65}.Release|x64.ActiveCfg = Release|x64
{33542FF0-0473-4802-BC79-3B8261790F65}.Release|x64.Build.0 = Release|x64
{36DAF5FA-6ADB-4F20-9810-1610DE0AE653}.Debug|x64.ActiveCfg = Debug|x64
{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

@@ -99,24 +99,6 @@ bool GpFileStream_Win32::SeekEnd(GpUFilePos_t loc)
return SetFilePointerEx(m_handle, li, nullptr, FILE_END) != 0;
}
bool GpFileStream_Win32::Truncate(GpUFilePos_t loc)
{
if (!m_writeable)
return false;
GpUFilePos_t oldPos = Tell();
if (!SeekStart(loc))
return false;
if (!SetEndOfFile(m_handle))
return false;
if (!SeekStart(oldPos))
return false;
return true;
}
GpUFilePos_t GpFileStream_Win32::Size() const
{
LARGE_INTEGER fsize;

View File

@@ -17,7 +17,6 @@ public:
bool SeekStart(GpUFilePos_t loc) override;
bool SeekCurrent(GpFilePos_t loc) override;
bool SeekEnd(GpUFilePos_t loc) override;
bool Truncate(GpUFilePos_t loc) override;
GpUFilePos_t Size() const override;
GpUFilePos_t Tell() const override;
void Close() override;

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\\";
}
}
@@ -191,24 +190,24 @@ bool GpFileSystem_Win32::FileExists(PortabilityLayer::VirtualDirectory_t virtual
return PathFileExistsW(winPath) != 0;
}
bool GpFileSystem_Win32::FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists)
bool GpFileSystem_Win32::FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &exists)
{
wchar_t winPath[MAX_PATH + 1];
if (!ResolvePath(virtualDirectory, &path, 1, winPath))
{
*exists = false;
exists = false;
return false;
}
DWORD attribs = GetFileAttributesW(winPath);
if (attribs == INVALID_FILE_ATTRIBUTES)
{
*exists = false;
exists = false;
return false;
}
*exists = true;
exists = true;
return (attribs & FILE_ATTRIBUTE_READONLY) != 0;
}
@@ -319,16 +318,6 @@ bool GpFileSystem_Win32::ValidateFilePathUnicodeChar(uint32_t c) const
return false;
}
bool GpFileSystem_Win32::IsVirtualDirectoryLooseResources(PortabilityLayer::VirtualDirectory_t virtualDir) const
{
return false;
}
void GpFileSystem_Win32::SetMainThreadRelay(IGpThreadRelay *relay)
{
(void)relay;
}
void GpFileSystem_Win32::SetDelayCallback(GpFileSystem_Win32::DelayCallback_t delayCallback)
{
}
@@ -341,7 +330,7 @@ bool GpFileSystem_Win32::ValidateFilePath(const char *str, size_t length) const
if (c >= '0' && c <= '9')
continue;
if (c == '_' || c == '.' || c == '\'')
if (c == '_' || c == '.' || c == '\'' || c == '!')
continue;
if (c == ' ' && i != 0 && i != length - 1)

View File

@@ -13,7 +13,7 @@ public:
GpFileSystem_Win32();
bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override;
bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists) override;
bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &exists) override;
GpIOStream *OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, 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;
@@ -21,9 +21,6 @@ public:
bool ValidateFilePath(const char *path, size_t sz) const override;
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
bool IsVirtualDirectoryLooseResources(PortabilityLayer::VirtualDirectory_t virtualDir) 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

@@ -1,14 +1,117 @@
#include "GpSystemServices_Win32.h"
#include "GpMutex_Win32.h"
#include "GpThreadEvent_Win32.h"
#include "GpWindows.h"
#include "IGpClipboardContents.h"
#include "UTF16.h"
#include "UTF8.h"
#include <assert.h>
#include <vector>
#pragma push_macro("CreateMutex")
#ifdef CreateMutex
#undef CreateMutex
#endif
extern GpWindowsGlobals g_gpWindowsGlobals;
namespace GpSystemServices_Win32_Private
{
class RefCountedClipboard
{
public:
RefCountedClipboard();
protected:
virtual ~RefCountedClipboard();
void AddRef();
void DecRef();
unsigned int m_refCount;
};
class TextClipboard : public RefCountedClipboard, public IGpClipboardContentsText
{
public:
TextClipboard(const uint8_t *utf8Text, size_t utf8Size);
~TextClipboard() override;
GpClipboardContentsType_t GetContentsType() const override;
void Destroy() override;
IGpClipboardContents *Clone() const override;
const uint8_t *GetBytes() const override;
size_t GetSize() const override;
private:
std::vector<uint8_t> m_utf8Text;
};
RefCountedClipboard::RefCountedClipboard()
: m_refCount(1)
{
}
RefCountedClipboard::~RefCountedClipboard()
{
}
void RefCountedClipboard::AddRef()
{
m_refCount++;
}
void RefCountedClipboard::DecRef()
{
unsigned int rc = --m_refCount;
if (rc == 0)
delete this;
}
TextClipboard::TextClipboard(const uint8_t *utf8Text, size_t utf8Size)
{
m_utf8Text.resize(utf8Size);
if (utf8Size > 0)
memcpy(&m_utf8Text[0], utf8Text, utf8Size);
}
TextClipboard::~TextClipboard()
{
}
GpClipboardContentsType_t TextClipboard::GetContentsType() const
{
return GpClipboardContentsTypes::kText;
}
void TextClipboard::Destroy()
{
this->DecRef();
}
IGpClipboardContents *TextClipboard::Clone() const
{
const_cast<TextClipboard*>(this)->AddRef();
return const_cast<TextClipboard*>(this);
}
const uint8_t *TextClipboard::GetBytes() const
{
if (m_utf8Text.size() == 0)
return nullptr;
return &m_utf8Text[0];
}
size_t TextClipboard::GetSize() const
{
return m_utf8Text.size();
}
}
struct GpSystemServices_Win32_ThreadStartParams
{
GpSystemServices_Win32::ThreadFunc_t m_threadFunc;
@@ -34,6 +137,10 @@ GpSystemServices_Win32::GpSystemServices_Win32()
{
}
GpSystemServices_Win32::~GpSystemServices_Win32()
{
}
int64_t GpSystemServices_Win32::GetTime() const
{
SYSTEMTIME epochStart;
@@ -149,6 +256,11 @@ bool GpSystemServices_Win32::IsFullscreenPreferred() const
return !m_isTouchscreenSimulation;
}
bool GpSystemServices_Win32::IsFullscreenOnStartup() const
{
return false;
}
unsigned int GpSystemServices_Win32::GetCPUCount() const
{
SYSTEM_INFO sysInfo;
@@ -166,6 +278,95 @@ bool GpSystemServices_Win32::IsTextInputEnabled() const
return true;
}
bool GpSystemServices_Win32::AreFontResourcesSeekable() const
{
return true;
}
IGpClipboardContents *GpSystemServices_Win32::GetClipboardContents() const
{
IGpClipboardContents *cbObject = nullptr;
if (IsClipboardFormatAvailable(CF_UNICODETEXT))
{
if (OpenClipboard(g_gpWindowsGlobals.m_hwnd))
{
HGLOBAL textHandle = GetClipboardData(CF_UNICODETEXT);
if (textHandle)
{
const wchar_t *str = static_cast<const wchar_t*>(GlobalLock(textHandle));
if (str)
{
if (str[0] == 0)
cbObject = new GpSystemServices_Win32_Private::TextClipboard(nullptr, 0);
else
{
int bytesRequired = WideCharToMultiByte(CP_UTF8, 0, str, -1, nullptr, 0, nullptr, nullptr);
if (bytesRequired > 0)
{
std::vector<char> decodedText;
decodedText.resize(bytesRequired);
WideCharToMultiByte(CP_UTF8, 0, str, -1, &decodedText[0], bytesRequired, nullptr, nullptr);
cbObject = new GpSystemServices_Win32_Private::TextClipboard(reinterpret_cast<const uint8_t*>(&decodedText[0]), decodedText.size() - 1);
}
}
GlobalUnlock(textHandle);
}
}
CloseClipboard();
}
}
return cbObject;
}
void GpSystemServices_Win32::SetClipboardContents(IGpClipboardContents *contents)
{
if (!contents)
return;
if (contents->GetContentsType() == GpClipboardContentsTypes::kText)
{
IGpClipboardContentsText *textContents = static_cast<IGpClipboardContentsText*>(contents);
if (OpenClipboard(g_gpWindowsGlobals.m_hwnd))
{
if (EmptyClipboard())
{
int wcharsRequired = MultiByteToWideChar(CP_UTF8, 0, reinterpret_cast<const char*>(textContents->GetBytes()), textContents->GetSize(), nullptr, 0);
std::vector<wchar_t> wideChars;
if (wcharsRequired)
{
wideChars.resize(wcharsRequired + 1);
MultiByteToWideChar(CP_UTF8, 0, reinterpret_cast<const char*>(textContents->GetBytes()), textContents->GetSize(), &wideChars[0], wcharsRequired);
}
else
wideChars.resize(1);
wideChars[wideChars.size() - 1] = static_cast<wchar_t>(0);
HGLOBAL textObject = GlobalAlloc(GMEM_MOVEABLE, wideChars.size() * sizeof(wchar_t));
if (textObject)
{
wchar_t *buffer = static_cast<wchar_t*>(GlobalLock(textObject));
memcpy(buffer, &wideChars[0], wideChars.size() * sizeof(wchar_t));
GlobalUnlock(textObject);
SetClipboardData(CF_UNICODETEXT, textObject);
}
}
CloseClipboard();
}
}
}
void GpSystemServices_Win32::SetTouchscreenSimulation(bool isTouchscreenSimulation)
{
m_isTouchscreenSimulation = isTouchscreenSimulation;

View File

@@ -19,6 +19,7 @@ class GpSystemServices_Win32 final : public IGpSystemServices
{
public:
GpSystemServices_Win32();
~GpSystemServices_Win32();
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;
@@ -32,9 +33,13 @@ public:
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;
void SetTouchscreenSimulation(bool isTouchscreenSimulation);

View File

@@ -15,8 +15,8 @@ android {
}
minSdkVersion 16
targetSdkVersion 29
versionCode 6
versionName "1.0.10"
versionCode 14
versionName "1.1.0"
externalNativeBuild {
ndkBuild {
arguments "APP_PLATFORM=android-16"
@@ -66,7 +66,7 @@ android {
}
aaptOptions {
noCompress 'gpa'
noCompress 'gpf'
}
}

View File

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

View File

@@ -9,6 +9,7 @@ SDL_PATH := ../SDL
LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include \
$(LOCAL_PATH)/../GpShell \
$(LOCAL_PATH)/../GpCommon \
$(LOCAL_PATH)/../AerofoilPortable \
$(LOCAL_PATH)/../AerofoilSDL \
$(LOCAL_PATH)/../Common \
$(LOCAL_PATH)/../PortabilityLayer
@@ -23,7 +24,7 @@ LOCAL_SRC_FILES := \
LOCAL_SHARED_LIBRARIES := SDL2
LOCAL_STATIC_LIBRARIES := GpShell GpFontHandler_FreeType2 AerofoilSDL GpApp
LOCAL_STATIC_LIBRARIES := GpShell AerofoilPortable AerofoilSDL GpApp
LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -llog

View File

@@ -42,7 +42,6 @@ public:
bool SeekStart(GpUFilePos_t loc) override;
bool SeekCurrent(GpFilePos_t loc) override;
bool SeekEnd(GpUFilePos_t loc) override;
bool Truncate(GpUFilePos_t loc) override;
GpUFilePos_t Size() const override;
GpUFilePos_t Tell() const override;
void Close() override;
@@ -70,7 +69,6 @@ public:
bool SeekStart(GpUFilePos_t loc) override;
bool SeekCurrent(GpFilePos_t loc) override;
bool SeekEnd(GpUFilePos_t loc) override;
bool Truncate(GpUFilePos_t loc) override;
GpUFilePos_t Size() const override;
GpUFilePos_t Tell() const override;
void Close() override;
@@ -96,7 +94,6 @@ public:
bool SeekStart(GpUFilePos_t loc) override;
bool SeekCurrent(GpFilePos_t loc) override;
bool SeekEnd(GpUFilePos_t loc) override;
bool Truncate(GpUFilePos_t loc) override;
GpUFilePos_t Size() const override;
GpUFilePos_t Tell() const override;
void Close() override;
@@ -168,11 +165,6 @@ bool GpFileStream_PFD::SeekEnd(GpUFilePos_t loc)
return lseek64(m_fd, loc, SEEK_END) >= 0;
}
bool GpFileStream_PFD::Truncate(GpUFilePos_t loc)
{
return ftruncate64(m_fd, static_cast<off64_t>(loc)) >= 0;
}
GpUFilePos_t GpFileStream_PFD::Size() const
{
struct stat64 s;
@@ -251,11 +243,6 @@ bool GpFileStream_SDLRWops::SeekEnd(GpUFilePos_t loc)
return m_rw->seek(m_rw, -static_cast<Sint64>(loc), RW_SEEK_END) >= 0;
}
bool GpFileStream_SDLRWops::Truncate(GpUFilePos_t loc)
{
return false;
}
GpUFilePos_t GpFileStream_SDLRWops::Size() const
{
return m_rw->size(m_rw);
@@ -346,12 +333,6 @@ bool GpFileStream_Android_File::SeekEnd(GpUFilePos_t loc)
return lseek64(m_fd, -static_cast<off64_t>(loc), SEEK_END) >= 0;
}
bool GpFileStream_Android_File::Truncate(GpUFilePos_t loc)
{
fflush(m_f);
return ftruncate64(m_fd, static_cast<off64_t>(loc)) >= 0;
}
GpUFilePos_t GpFileStream_Android_File::Size() const
{
fflush(m_f);
@@ -469,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)
@@ -552,26 +532,26 @@ bool GpFileSystem_Android::FileExists(PortabilityLayer::VirtualDirectory_t virtu
return stat(resolvedPath.c_str(), &s) == 0;
}
bool GpFileSystem_Android::FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists)
bool GpFileSystem_Android::FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &exists)
{
std::string resolvedPath;
bool isAsset;
if (!ResolvePath(virtualDirectory, &path, 1, resolvedPath, isAsset))
{
if (exists)
*exists = false;
exists = false;
return false;
}
if (isAsset)
{
if (exists)
*exists = this->FileExists(virtualDirectory, path);
exists = this->FileExists(virtualDirectory, path);
return true;
}
int permissions = access(resolvedPath.c_str(), W_OK | F_OK);
*exists = ((permissions & F_OK) != 0);
exists = ((permissions & F_OK) != 0);
return ((permissions & W_OK) != 0);
}
@@ -699,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);
@@ -733,7 +694,7 @@ bool GpFileSystem_Android::ValidateFilePath(const char *path, size_t length) con
if (c >= '0' && c <= '9')
continue;
if (c == '_' || c == '.' || c == '\'')
if (c == '_' || c == '.' || c == '\'' || c == '!')
continue;
if (c == ' ' && i != 0 && i != length - 1)
@@ -771,16 +732,6 @@ bool GpFileSystem_Android::ValidateFilePathUnicodeChar(uint32_t c) const
return false;
}
bool GpFileSystem_Android::IsVirtualDirectoryLooseResources(PortabilityLayer::VirtualDirectory_t virtualDir) const
{
return false;
}
void GpFileSystem_Android::SetMainThreadRelay(IGpThreadRelay *relay)
{
m_relay = relay;
}
void GpFileSystem_Android::SetDelayCallback(DelayCallback_t delayCallback)
{
m_delayCallback = delayCallback;

View File

@@ -19,7 +19,7 @@ public:
void ShutdownJNI();
bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override;
bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists) 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;
@@ -27,9 +27,6 @@ public:
bool ValidateFilePath(const char *path, size_t pathLen) const override;
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
bool IsVirtualDirectoryLooseResources(PortabilityLayer::VirtualDirectory_t virtualDir) const override;
void SetMainThreadRelay(IGpThreadRelay *relay) override;
void SetDelayCallback(DelayCallback_t delayCallback) override;
void PostSourceExportRequest(bool cancelled, int fd, jobject pfd);
@@ -38,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,10 +4,10 @@
#include "GpAudioDriverFactory.h"
#include "GpDisplayDriverFactory.h"
#include "GpGlobalConfig.h"
#include "GpFiber_SDL.h"
#include "GpFileSystem_Android.h"
#include "GpFontHandlerFactory.h"
#include "GpInputDriverFactory.h"
#include "GpInputDriver_SDL_Gamepad.h"
#include "GpAppInterface.h"
#include "GpSystemServices_Android.h"
#include "GpVOSEvent.h"
@@ -23,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);
@@ -90,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;
@@ -101,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();
@@ -116,3 +113,8 @@ int main(int argc, char* argv[])
return returnCode;
}
IGpInputDriverSDLGamepad *IGpInputDriverSDLGamepad::GetInstance()
{
return nullptr;
}

View File

@@ -1,11 +1,9 @@
#include "GpSystemServices_Android.h"
#include "IGpMutex.h"
#include "IGpThreadEvent.h"
#include "SDL.h"
#include <time.h>
#include <mutex>
#include <condition_variable>
#include <unistd.h>
struct GpSystemServices_Android_ThreadStartParams
@@ -28,175 +26,11 @@ static int SDLCALL StaticStartThread(void *lpThreadParameter)
return threadFunc(threadContext);
}
template<class TMutex>
class GpMutex_Cpp11 final : public IGpMutex
{
public:
GpMutex_Cpp11();
~GpMutex_Cpp11();
void Destroy() override;
void Lock() override;
void Unlock() override;
private:
TMutex m_mutex;
};
template<class TMutex>
GpMutex_Cpp11<TMutex>::GpMutex_Cpp11()
{
}
template<class TMutex>
GpMutex_Cpp11<TMutex>::~GpMutex_Cpp11()
{
}
template<class TMutex>
void GpMutex_Cpp11<TMutex>::Destroy()
{
this->~GpMutex_Cpp11();
free(this);
}
template<class TMutex>
void GpMutex_Cpp11<TMutex>::Lock()
{
m_mutex.lock();
}
template<class TMutex>
void GpMutex_Cpp11<TMutex>::Unlock()
{
m_mutex.unlock();
}
typedef GpMutex_Cpp11<std::mutex> GpMutex_Cpp11_Vanilla;
typedef GpMutex_Cpp11<std::recursive_mutex> GpMutex_Cpp11_Recursive;
class GpThreadEvent_Cpp11 final : public IGpThreadEvent
{
public:
GpThreadEvent_Cpp11(bool autoReset, bool startSignaled);
~GpThreadEvent_Cpp11();
void Wait() override;
bool WaitTimed(uint32_t msec) override;
void Signal() override;
void Destroy() override;
private:
std::mutex m_mutex;
std::condition_variable m_cvar;
bool m_flag;
bool m_autoReset;
};
GpThreadEvent_Cpp11::GpThreadEvent_Cpp11(bool autoReset, bool startSignaled)
: m_flag(startSignaled)
, m_autoReset(autoReset)
{
}
GpThreadEvent_Cpp11::~GpThreadEvent_Cpp11()
{
}
void GpThreadEvent_Cpp11::Wait()
{
std::unique_lock<std::mutex> lock(m_mutex);
if (m_autoReset)
{
m_cvar.wait(lock,[&]()->bool{
if (m_flag)
{
m_flag = false;
return true;
}
else
return false;
});
}
else
m_cvar.wait(lock,[&]()->bool{ return m_flag; });
}
bool GpThreadEvent_Cpp11::WaitTimed(uint32_t msec)
{
std::unique_lock<std::mutex> lock(m_mutex);
if (m_autoReset)
{
if (!m_cvar.wait_for(lock, std::chrono::milliseconds(msec), [&]()->bool{
if (m_flag)
{
m_flag = false;
return true;
}
else
return false;
}))
return false;
}
else
{
if (!m_cvar.wait_for(lock, std::chrono::milliseconds(msec), [&]()->bool{ return m_flag; }))
return false;
}
return true;
}
void GpThreadEvent_Cpp11::Signal()
{
m_mutex.lock();
m_flag = true;
m_mutex.unlock();
if (m_autoReset)
m_cvar.notify_one();
else
m_cvar.notify_all();
}
void GpThreadEvent_Cpp11::Destroy()
{
this->~GpThreadEvent_Cpp11();
free(this);
}
GpSystemServices_Android::GpSystemServices_Android()
: m_textInputEnabled(false)
{
}
int64_t GpSystemServices_Android::GetTime() const
{
time_t t = time(nullptr);
return static_cast<int64_t>(t) - 2082844800;
}
void GpSystemServices_Android::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_Android::CreateMutex()
{
GpMutex_Cpp11_Vanilla *mutex = static_cast<GpMutex_Cpp11_Vanilla*>(malloc(sizeof(GpMutex_Cpp11_Vanilla)));
if (!mutex)
return nullptr;
return new (mutex) GpMutex_Cpp11_Vanilla();
}
void *GpSystemServices_Android::CreateThread(ThreadFunc_t threadFunc, void *context)
{
IGpThreadEvent *evt = CreateThreadEvent(true, false);
@@ -221,31 +55,6 @@ void *GpSystemServices_Android::CreateThread(ThreadFunc_t threadFunc, void *cont
return thread;
}
IGpMutex *GpSystemServices_Android::CreateRecursiveMutex()
{
GpMutex_Cpp11_Recursive *mutex = static_cast<GpMutex_Cpp11_Recursive*>(malloc(sizeof(GpMutex_Cpp11_Recursive)));
if (!mutex)
return nullptr;
return new (mutex) GpMutex_Cpp11_Recursive();
}
IGpThreadEvent *GpSystemServices_Android::CreateThreadEvent(bool autoReset, bool startSignaled)
{
GpThreadEvent_Cpp11 *evt = static_cast<GpThreadEvent_Cpp11*>(malloc(sizeof(GpThreadEvent_Cpp11)));
if (!evt)
return nullptr;
return new (evt) GpThreadEvent_Cpp11(autoReset, startSignaled);
}
uint64_t GpSystemServices_Android::GetFreeMemoryCosmetic() const
{
long pages = sysconf(_SC_AVPHYS_PAGES);
long pageSize = sysconf(_SC_PAGE_SIZE);
return pages * pageSize;
}
void GpSystemServices_Android::Beep() const
{
}
@@ -270,6 +79,11 @@ bool GpSystemServices_Android::IsFullscreenPreferred() const
return true;
}
bool GpSystemServices_Android::IsFullscreenOnStartup() const
{
return true;
}
unsigned int GpSystemServices_Android::GetCPUCount() const
{
return SDL_GetCPUCount();
@@ -285,6 +99,20 @@ bool GpSystemServices_Android::IsTextInputEnabled() const
return m_textInputEnabled;
}
bool GpSystemServices_Android::AreFontResourcesSeekable() const
{
return false;
}
IGpClipboardContents *GpSystemServices_Android::GetClipboardContents() const
{
return nullptr;
}
void GpSystemServices_Android::SetClipboardContents(IGpClipboardContents *contents)
{
}
GpSystemServices_Android *GpSystemServices_Android::GetInstance()
{
return &ms_instance;

View File

@@ -1,28 +1,26 @@
#pragma once
#include "IGpSystemServices.h"
#include "GpSystemServices_POSIX.h"
#include "GpCoreDefs.h"
class GpSystemServices_Android final : public IGpSystemServices
class GpSystemServices_Android final : public GpSystemServices_POSIX
{
public:
GpSystemServices_Android();
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;
void *CreateThread(ThreadFunc_t threadFunc, void *context) override;
IGpThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) override;
uint64_t GetFreeMemoryCosmetic() const 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;
void FlushTextInputEnabled();

View File

@@ -41,9 +41,13 @@
<!-- Allow writing to external storage -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Allow access to Bluetooth devices -->
<!--
<uses-permission android:name="android.permission.BLUETOOTH" />
-->
<!-- Allow access to the vibrator -->
<!--
<uses-permission android:name="android.permission.VIBRATE" />
-->
<!-- if you want to capture audio, uncomment this. -->
<!-- <uses-permission android:name="android.permission.RECORD_AUDIO" /> -->

View File

@@ -7,6 +7,6 @@ mkdir Packaged
cd Packaged
rmdir /S /Q Houses
mkdir Houses
copy ..\..\..\..\..\..\Packaged\*.gpa .\
copy ..\..\..\..\..\..\Packaged\*.gpf .\
copy ..\..\..\..\..\..\Packaged\Houses\* Houses\
cd ..

View File

@@ -5,17 +5,15 @@ call remove_symlinks.bat
mklink /D app\jni\AerofoilSDL ..\..\..\AerofoilSDL
mklink /D app\jni\AerofoilPortable ..\..\..\AerofoilPortable
mklink /D app\jni\Common ..\..\..\Common
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

@@ -2,16 +2,13 @@
@cd /d "%~dp0"
rmdir app\jni\AerofoilSDL
rmdir app\jni\AerofoilPortable
rmdir app\jni\Common
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

@@ -2,19 +2,20 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := GpFontHandler_FreeType2
LOCAL_MODULE := AerofoilPortable
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/../Common \
$(LOCAL_PATH)/../GpCommon \
$(LOCAL_PATH)/../FreeType/freetype/include
$(LOCAL_PATH)/../GpShell \
$(LOCAL_PATH)/../Common \
$(LOCAL_PATH)/../PortabilityLayer
LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0
# Add your application source files here...
LOCAL_SRC_FILES := \
GpFontHandler_FreeType2.cpp
GpThreadEvent_Cpp11.cpp \
GpSystemServices_POSIX.cpp
LOCAL_SHARED_LIBRARIES := FreeType
include $(BUILD_STATIC_LIBRARY)

View File

@@ -0,0 +1,66 @@
#pragma once
#include "IGpMutex.h"
#include <mutex>
template<class TMutex>
class GpMutex_Cpp11 final : public IGpMutex
{
public:
~GpMutex_Cpp11();
void Destroy() override;
static GpMutex_Cpp11<TMutex> *Create();
void Lock() override;
void Unlock() override;
private:
GpMutex_Cpp11();
TMutex m_mutex;
};
#include <stdlib.h>
template<class TMutex>
GpMutex_Cpp11<TMutex>::GpMutex_Cpp11()
{
}
template<class TMutex>
GpMutex_Cpp11<TMutex>::~GpMutex_Cpp11()
{
}
template<class TMutex>
void GpMutex_Cpp11<TMutex>::Destroy()
{
this->~GpMutex_Cpp11();
free(this);
}
template<class TMutex>
GpMutex_Cpp11<TMutex> *GpMutex_Cpp11<TMutex>::Create()
{
GpMutex_Cpp11<TMutex> *mutex = static_cast<GpMutex_Cpp11<TMutex>*>(malloc(sizeof(GpMutex_Cpp11<TMutex>)));
if (!mutex)
return nullptr;
return new (mutex) GpMutex_Cpp11<TMutex>();
}
template<class TMutex>
void GpMutex_Cpp11<TMutex>::Lock()
{
m_mutex.lock();
}
template<class TMutex>
void GpMutex_Cpp11<TMutex>::Unlock()
{
m_mutex.unlock();
}
typedef GpMutex_Cpp11<std::mutex> GpMutex_Cpp11_NonRecursive;
typedef GpMutex_Cpp11<std::recursive_mutex> GpMutex_Cpp11_Recursive;

View File

@@ -0,0 +1,50 @@
#include "GpSystemServices_POSIX.h"
#include "GpMutex_Cpp11.h"
#include "GpThreadEvent_Cpp11.h"
#include <time.h>
#include <unistd.h>
GpSystemServices_POSIX::GpSystemServices_POSIX()
{
}
int64_t GpSystemServices_POSIX::GetTime() const
{
time_t t = time(nullptr);
return static_cast<int64_t>(t) - 2082844800;
}
void GpSystemServices_POSIX::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_POSIX::CreateMutex()
{
return GpMutex_Cpp11_NonRecursive::Create();
}
IGpMutex *GpSystemServices_POSIX::CreateRecursiveMutex()
{
return GpMutex_Cpp11_Recursive::Create();
}
IGpThreadEvent *GpSystemServices_POSIX::CreateThreadEvent(bool autoReset, bool startSignaled)
{
return GpThreadEvent_Cpp11::Create(autoReset, startSignaled);
}
uint64_t GpSystemServices_POSIX::GetFreeMemoryCosmetic() const
{
long pages = sysconf(_SC_AVPHYS_PAGES);
long pageSize = sysconf(_SC_PAGE_SIZE);
return pages * pageSize;
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include "IGpSystemServices.h"
#include "GpCoreDefs.h"
class GpSystemServices_POSIX : public IGpSystemServices
{
public:
GpSystemServices_POSIX();
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;
};

View File

@@ -0,0 +1,82 @@
#include "GpThreadEvent_Cpp11.h"
GpThreadEvent_Cpp11::GpThreadEvent_Cpp11(bool autoReset, bool startSignaled)
: m_flag(startSignaled)
, m_autoReset(autoReset)
{
}
GpThreadEvent_Cpp11::~GpThreadEvent_Cpp11()
{
}
void GpThreadEvent_Cpp11::Wait()
{
std::unique_lock<std::mutex> lock(m_mutex);
if (m_autoReset)
{
m_cvar.wait(lock,[&]()->bool{
if (m_flag)
{
m_flag = false;
return true;
}
else
return false;
});
}
else
m_cvar.wait(lock,[&]()->bool{ return m_flag; });
}
bool GpThreadEvent_Cpp11::WaitTimed(uint32_t msec)
{
std::unique_lock<std::mutex> lock(m_mutex);
if (m_autoReset)
{
if (!m_cvar.wait_for(lock, std::chrono::milliseconds(msec), [&]()->bool{
if (m_flag)
{
m_flag = false;
return true;
}
else
return false;
}))
return false;
}
else
{
if (!m_cvar.wait_for(lock, std::chrono::milliseconds(msec), [&]()->bool{ return m_flag; }))
return false;
}
return true;
}
void GpThreadEvent_Cpp11::Signal()
{
m_mutex.lock();
m_flag = true;
m_mutex.unlock();
if (m_autoReset)
m_cvar.notify_one();
else
m_cvar.notify_all();
}
void GpThreadEvent_Cpp11::Destroy()
{
this->~GpThreadEvent_Cpp11();
free(this);
}
GpThreadEvent_Cpp11 *GpThreadEvent_Cpp11::Create(bool autoReset, bool startSignaled)
{
GpThreadEvent_Cpp11 *evt = static_cast<GpThreadEvent_Cpp11*>(malloc(sizeof(GpThreadEvent_Cpp11)));
if (!evt)
return nullptr;
return new (evt) GpThreadEvent_Cpp11(autoReset, startSignaled);
}

View File

@@ -0,0 +1,28 @@
#pragma once
#include "IGpThreadEvent.h"
#include <mutex>
#include <condition_variable>
class GpThreadEvent_Cpp11 final : public IGpThreadEvent
{
public:
~GpThreadEvent_Cpp11();
void Wait() override;
bool WaitTimed(uint32_t msec) override;
void Signal() override;
void Destroy() override;
static GpThreadEvent_Cpp11 *Create(bool autoReset, bool startSignaled);
private:
GpThreadEvent_Cpp11(bool autoReset, bool startSignaled);
GpThreadEvent_Cpp11() = delete;
std::mutex m_mutex;
std::condition_variable m_cvar;
bool m_flag;
bool m_autoReset;
};

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,10 +93,10 @@
<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" />
<ClCompile Include="ShaderCode\DrawQuad32P.cpp" />
<ClCompile Include="ShaderCode\DrawQuadPaletteP.cpp" />
<ClCompile Include="ShaderCode\DrawQuadV.cpp" />
<ClCompile Include="ShaderCode\ScaleQuadP.cpp" />
@@ -111,15 +111,13 @@
<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>
<ProjectReference Include="..\GpShell\GpShell.vcxproj">
<Project>{10cf9b5f-61d0-4b5b-89f4-810b58fc053d}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GpFiber_SDL.h" />
<ClInclude Include="GpInputDriver_SDL_Gamepad.h" />
<ClInclude Include="ShaderCode\DrawQuadPixelConstants.h" />
<ClInclude Include="ShaderCode\Functions.h" />
</ItemGroup>

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>
@@ -66,6 +60,12 @@
<ClCompile Include="ShaderCode\CopyQuadP.cpp">
<Filter>Source Files\ShaderCode</Filter>
</ClCompile>
<ClCompile Include="ShaderCode\DrawQuad32P.cpp">
<Filter>Source Files\ShaderCode</Filter>
</ClCompile>
<ClCompile Include="GpInputDriver_SDL_Gamepad.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ShaderCode\Functions.h">
@@ -77,5 +77,8 @@
<ClInclude Include="GpFiber_SDL.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpInputDriver_SDL_Gamepad.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

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,10 +20,9 @@ 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 \
ShaderCode/DrawQuadV.cpp \
ShaderCode/ScaleQuadP.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"
@@ -136,6 +136,7 @@ private:
static const size_t kMaxChannels = 16;
static const size_t kMixChunkSize = 256;
static const int16_t kMaxAudioVolumeScale = 25;
GpAudioChannel_SDL2 *m_channels[kMaxChannels];
size_t m_numChannels;
@@ -144,6 +145,8 @@ private:
GP_ALIGNED(GP_SYSTEM_MEMORY_ALIGNMENT) int16_t m_mixChunk[kMixChunkSize];
size_t m_mixChunkReadOffset;
int16_t m_audioVolumeScale;
};
GpAudioChannelBufferChain_SDL2::GpAudioChannelBufferChain_SDL2()
@@ -353,6 +356,7 @@ GpAudioDriver_SDL2::GpAudioDriver_SDL2(const GpAudioDriverProperties &properties
, m_numChannels(0)
, m_sdlAudioRunning(false)
, m_mixChunkReadOffset(kMixChunkSize)
, m_audioVolumeScale(kMaxAudioVolumeScale)
{
for (size_t i = 0; i < kMaxChannels; i++)
@@ -395,6 +399,9 @@ IGpAudioChannel *GpAudioDriver_SDL2::CreateChannel()
void GpAudioDriver_SDL2::SetMasterVolume(uint32_t vol, uint32_t maxVolume)
{
double scale = vol * static_cast<uint64_t>(kMaxAudioVolumeScale) / maxVolume;
m_audioVolumeScale = static_cast<int16_t>(scale);
}
void GpAudioDriver_SDL2::Shutdown()
@@ -430,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))
@@ -527,6 +534,8 @@ void GpAudioDriver_SDL2::RefillMixChunk(GpAudioChannel_SDL2 *const*channels, siz
bool noAudio = true;
const int16_t audioVolumeScale = m_audioVolumeScale;
for (size_t i = 0; i < numChannels; i++)
{
channels[i]->Consume(audioMixBuffer, kMixChunkSize);
@@ -535,12 +544,12 @@ void GpAudioDriver_SDL2::RefillMixChunk(GpAudioChannel_SDL2 *const*channels, siz
{
noAudio = false;
for (size_t j = 0; j < kMixChunkSize; j++)
m_mixChunk[j] = (audioMixBuffer[j] - 0x80) * 25;
m_mixChunk[j] = (static_cast<int16_t>(audioMixBuffer[j]) - 0x80) * audioVolumeScale;
}
else
{
for (size_t j = 0; j < kMixChunkSize; j++)
m_mixChunk[j] += (audioMixBuffer[j] - 0x80) * 25;
m_mixChunk[j] += (static_cast<int16_t>(audioMixBuffer[j]) - 0x80) * audioVolumeScale;
}
}

View File

@@ -1,11 +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"
@@ -27,6 +29,9 @@
#include <vector>
#include <algorithm>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#pragma push_macro("LoadCursor")
#ifdef LoadCursor
@@ -39,6 +44,13 @@ class GpDisplayDriver_SDL_GL2;
static GpDisplayDriverSurfaceEffects gs_defaultEffects;
static const char *kPrefsIdentifier = "GpDisplayDriverSDL_GL2";
static uint32_t kPrefsVersion = 1;
struct GpDisplayDriver_SDL_GL2_Prefs
{
bool m_isFullScreen;
};
namespace DeleteMe
{
@@ -108,17 +120,13 @@ namespace GpBinarizedShaders
extern const char *g_drawQuadPalettePF_GL2;
extern const char *g_drawQuadPalettePNF_GL2;
extern const char *g_drawQuadRGBPF_GL2;
extern const char *g_drawQuadRGBPNF_GL2;
extern const char *g_drawQuad15BitPF_GL2;
extern const char *g_drawQuad15BitPNF_GL2;
extern const char *g_drawQuad32PF_GL2;
extern const char *g_drawQuad32PNF_GL2;
extern const char *g_drawQuadPaletteICCPF_GL2;
extern const char *g_drawQuadPaletteICCPNF_GL2;
extern const char *g_drawQuadRGBICCPF_GL2;
extern const char *g_drawQuadRGBICCPNF_GL2;
extern const char *g_drawQuad15BitICCPF_GL2;
extern const char *g_drawQuad15BitICCPNF_GL2;
extern const char *g_drawQuad32ICCPF_GL2;
extern const char *g_drawQuad32ICCPNF_GL2;
extern const char *g_copyQuadP_GL2;
extern const char *g_scaleQuadP_GL2;
@@ -210,6 +218,7 @@ struct GpGLFunctions
static void CheckGLError(const GpGLFunctions &gl, IGpLogDriver *logger)
{
#if GP_DEBUG_CONFIG
GLenum errorCode = gl.GetError();
if (errorCode != 0)
{
@@ -218,6 +227,7 @@ static void CheckGLError(const GpGLFunctions &gl, IGpLogDriver *logger)
}
assert(errorCode == 0);
#endif
}
class GpGLObject
@@ -725,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 GetDisplayResolution(unsigned int *width, unsigned int *height) 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;
@@ -793,7 +804,7 @@ private:
void ScaleVirtualScreen();
GpDisplayDriverTickStatus_t PresentFrameAndSync();
bool SyncRender();
GpGLFunctions m_gl;
GpDisplayDriverProperties m_properties;
@@ -849,12 +860,16 @@ private:
DrawQuadProgram m_drawQuadPaletteNoFlickerProgram;
DrawQuadProgram m_drawQuadPaletteFlickerProgram;
DrawQuadProgram m_drawQuadRGBProgram;
DrawQuadProgram m_drawQuad15BitProgram;
DrawQuadProgram m_drawQuad15NoFlickerProgram;
DrawQuadProgram m_drawQuad15FlickerProgram;
DrawQuadProgram m_drawQuad32NoFlickerProgram;
DrawQuadProgram m_drawQuad32FlickerProgram;
DrawQuadProgram m_drawQuadPaletteICCNoFlickerProgram;
DrawQuadProgram m_drawQuadPaletteICCFlickerProgram;
DrawQuadProgram m_drawQuadRGBICCProgram;
DrawQuadProgram m_drawQuad15BitICCProgram;
DrawQuadProgram m_drawQuad15ICCNoFlickerProgram;
DrawQuadProgram m_drawQuad15ICCFlickerProgram;
DrawQuadProgram m_drawQuad32ICCNoFlickerProgram;
DrawQuadProgram m_drawQuad32ICCFlickerProgram;
};
InstancedResources m_res;
@@ -886,6 +901,8 @@ private:
uint32_t m_windowHeightPhysical;
uint32_t m_windowWidthVirtual; // Virtual resolution is the resolution reported to the game
uint32_t m_windowHeightVirtual;
uint32_t m_initialWidthVirtual; // Virtual resolution is the resolution reported to the game
uint32_t m_initialHeightVirtual;
float m_pixelScaleX;
float m_pixelScaleY;
bool m_useUpscaleFilter;
@@ -896,9 +913,6 @@ private:
EGpStandardCursor_t m_pendingStandardCursor;
bool m_mouseIsInClientArea;
IGpFiber *m_vosFiber;
IGpThreadEvent *m_vosEvent;
float m_bgColor[4];
bool m_bgIsDark;
@@ -1178,11 +1192,11 @@ GpDisplayDriver_SDL_GL2::GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties
, m_windowHeightPhysical(480)
, m_windowWidthVirtual(640)
, m_windowHeightVirtual(480)
, m_initialWidthVirtual(640)
, m_initialHeightVirtual(480)
, 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)
@@ -1215,7 +1229,7 @@ GpDisplayDriver_SDL_GL2::GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties
m_bgColor[3] = 1.f;
// Stupid hack to detect mobile...
m_isFullScreenDesired = m_properties.m_systemServices->IsFullscreenPreferred();
m_isFullScreenDesired = m_properties.m_systemServices->IsFullscreenOnStartup();
const intmax_t periodNum = std::chrono::high_resolution_clock::period::num;
const intmax_t periodDen = std::chrono::high_resolution_clock::period::den;
@@ -1327,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())
@@ -1367,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)
{
@@ -1823,242 +2075,19 @@ 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_isFullScreenDesired)
{
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;
for (;;)
{
SDL_Event msg;
if (SDL_PollEvent(&msg) != 0)
{
if (msg.type == SDL_MOUSEMOTION)
{
if (!m_mouseIsInClientArea)
m_mouseIsInClientArea = true;
}
//else if (msg.type == SDL_MOUSELEAVE) // Does SDL support this??
// m_mouseIsInClientArea = false;
else if (msg.type == SDL_RENDER_DEVICE_RESET || msg.type == 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;
}
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();
free(this);
}
void GpDisplayDriver_SDL_GL2::GetDisplayResolution(unsigned int *width, unsigned int *height)
void GpDisplayDriver_SDL_GL2::GetInitialDisplayResolution(unsigned int *width, unsigned int *height)
{
if (width)
*width = m_windowWidthVirtual;
*width = m_initialWidthVirtual;
if (height)
*height = m_windowHeightVirtual;
*height = m_initialHeightVirtual;
}
IGpDisplayDriverSurface *GpDisplayDriver_SDL_GL2::CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat, SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext)
@@ -2110,7 +2139,20 @@ void GpDisplayDriver_SDL_GL2::DrawSurface(IGpDisplayDriverSurface *surface, int3
}
else if (pixelFormat == GpPixelFormats::kRGB32)
{
return;
if (m_useICCProfile)
{
if (effects->m_flicker)
program = &m_res.m_drawQuad32ICCFlickerProgram;
else
program = &m_res.m_drawQuad32ICCNoFlickerProgram;
}
else
{
if (effects->m_flicker)
program = &m_res.m_drawQuad32FlickerProgram;
else
program = &m_res.m_drawQuad32NoFlickerProgram;
}
}
else
{
@@ -2338,11 +2380,19 @@ bool GpDisplayDriver_SDL_GL2::SupportsSizedFormats() const
void GpDisplayDriver_SDL_GL2::ApplyPrefs(const void *identifier, size_t identifierSize, const void *contents, size_t contentsSize, uint32_t version)
{
if (version == kPrefsVersion && identifierSize == strlen(kPrefsIdentifier) && !memcmp(identifier, kPrefsIdentifier, identifierSize))
{
const GpDisplayDriver_SDL_GL2_Prefs *prefs = static_cast<const GpDisplayDriver_SDL_GL2_Prefs *>(contents);
m_isFullScreenDesired = prefs->m_isFullScreen;
}
}
bool GpDisplayDriver_SDL_GL2::SavePrefs(void *context, WritePrefsFunc_t writeFunc)
bool GpDisplayDriver_SDL_GL2::SavePrefs(void *context, IGpPrefsHandler::WritePrefsFunc_t writeFunc)
{
return true;
GpDisplayDriver_SDL_GL2_Prefs prefs;
prefs.m_isFullScreen = m_isFullScreenDesired;
return writeFunc(context, kPrefsIdentifier, strlen(kPrefsIdentifier), &prefs, sizeof(prefs), kPrefsVersion);
}
void GpDisplayDriver_SDL_GL2::UnlinkSurface(GpDisplayDriverSurface_GL2 *surface, GpDisplayDriverSurface_GL2 *prev, GpDisplayDriverSurface_GL2 *next)
@@ -2489,23 +2539,29 @@ bool GpDisplayDriver_SDL_GL2::InitResources(uint32_t physicalWidth, uint32_t phy
}
GpComPtr<GpGLShader<GL_VERTEX_SHADER>> drawQuadVertexShader = CreateShader<GL_VERTEX_SHADER>(GpBinarizedShaders::g_drawQuadV_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuadPaletteFlickerPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuadPalettePF_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuadPaletteNoFlickerPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuadPalettePNF_GL2);
//m_drawQuadRGBPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuadRGBP_GL2);
//m_drawQuad15BitPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuad15BitP_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuad32FlickerPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuad32PF_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuad32NoFlickerPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuad32PNF_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuadPaletteICCFPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuadPaletteICCPF_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuadPaletteICCNFPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuadPaletteICCPNF_GL2);
//m_drawQuadRGBICCPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuadRGBICCP_GL2);
//m_drawQuad15BitICCPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuad15BitICCP_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuad32ICCFPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuad32ICCPF_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuad32ICCNFPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuad32ICCPNF_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> scaleQuadPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_scaleQuadP_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> copyQuadPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_copyQuadP_GL2);
if (!m_res.m_drawQuadPaletteFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteFlickerPixelShader)
|| !m_res.m_drawQuadPaletteNoFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteFlickerPixelShader)
//|| !m_drawQuadRGBProgram.Link(this, drawQuadVertexShader, drawQuadRGBPixelShader)
//|| !m_drawQuad15BitProgram.Link(this, drawQuadVertexShader, drawQuad15BitPixelShader)
|| !m_res.m_drawQuadPaletteNoFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteNoFlickerPixelShader)
|| !m_res.m_drawQuad32FlickerProgram.Link(this, drawQuadVertexShader, drawQuad32FlickerPixelShader)
|| !m_res.m_drawQuad32NoFlickerProgram.Link(this, drawQuadVertexShader, drawQuad32NoFlickerPixelShader)
|| !m_res.m_drawQuadPaletteICCFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteICCFPixelShader)
|| !m_res.m_drawQuadPaletteICCNoFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteICCNFPixelShader)
|| !m_res.m_drawQuad32ICCFlickerProgram.Link(this, drawQuadVertexShader, drawQuad32ICCFPixelShader)
|| !m_res.m_drawQuad32ICCNoFlickerProgram.Link(this, drawQuadVertexShader, drawQuad32ICCNFPixelShader)
//|| !m_drawQuadRGBICCProgram.Link(this, drawQuadVertexShader, drawQuadRGBICCPixelShader)
//|| !m_drawQuad15BitICCProgram.Link(this, drawQuadVertexShader, drawQuad15BitICCPixelShader)
|| !m_res.m_scaleQuadProgram.Link(this, drawQuadVertexShader, scaleQuadPixelShader)
@@ -3000,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];
@@ -3033,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;
@@ -3123,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)
@@ -3147,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)
{
@@ -3179,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

@@ -0,0 +1,308 @@
#include "GpInputDriver_SDL_Gamepad.h"
#include "GpVOSEvent.h"
#include "IGpVOSEventQueue.h"
#include "SDL_events.h"
#include "SDL_joystick.h"
#include "SDL_gamecontroller.h"
#include <stdlib.h>
#include <algorithm>
#include <new>
#include <vector>
class GpInputDriverSDLGamepad final : public IGpInputDriverSDLGamepad
{
public:
void ProcessInput() override;
void Shutdown() override;
IGpPrefsHandler *GetPrefsHandler() const override;
static GpInputDriverSDLGamepad *Create(const GpInputDriverProperties &props);
void ProcessSDLEvent(const SDL_Event &evt) override;
private:
static const int kMaxPlayers = 2;
GpInputDriverSDLGamepad(const GpInputDriverProperties &props);
~GpInputDriverSDLGamepad();
bool FindJoystickPlayer(uint8_t &playerNum, SDL_JoystickID joystickID);
void HandleDeviceAdded(SDL_JoystickID joystickID);
void HandleDeviceRemoved(SDL_JoystickID joystickID);
std::vector<GpVOSEvent> m_pendingEvents;
GpInputDriverProperties m_properties;
SDL_JoystickID m_playerJoystickIDs[kMaxPlayers];
SDL_GameController *m_playerControllers[kMaxPlayers];
bool m_playerButtonDown[kMaxPlayers][GpGamepadButtons::kCount];
};
static GpInputDriverSDLGamepad *gs_instance = nullptr;
IGpInputDriverSDLGamepad *IGpInputDriverSDLGamepad::GetInstance()
{
return gs_instance;
}
void GpInputDriverSDLGamepad::ProcessInput()
{
for (size_t i = 0; i < m_pendingEvents.size(); i++)
{
if (GpVOSEvent *evt = m_properties.m_eventQueue->QueueEvent())
*evt = m_pendingEvents[i];
}
m_pendingEvents.clear();
}
void GpInputDriverSDLGamepad::Shutdown()
{
this->~GpInputDriverSDLGamepad();
free(this);
gs_instance = nullptr;
}
IGpPrefsHandler *GpInputDriverSDLGamepad::GetPrefsHandler() const
{
return nullptr;
}
GpInputDriverSDLGamepad *GpInputDriverSDLGamepad::Create(const GpInputDriverProperties &props)
{
void *storage = malloc(sizeof(GpInputDriverSDLGamepad));
if (!storage)
return nullptr;
GpInputDriverSDLGamepad *driver = new (storage) GpInputDriverSDLGamepad(props);
gs_instance = driver;
return driver;
}
GpInputDriverSDLGamepad::GpInputDriverSDLGamepad(const GpInputDriverProperties &props)
: m_properties(props)
{
for (int i = 0; i < kMaxPlayers; i++)
{
m_playerJoystickIDs[i] = -1;
m_playerControllers[i] = nullptr;
for (int j = 0; j < GpGamepadButtons::kCount; j++)
m_playerButtonDown[i][j] = false;
}
}
GpInputDriverSDLGamepad::~GpInputDriverSDLGamepad()
{
for (int i = 0; i < kMaxPlayers; i++)
{
if (m_playerControllers[i])
SDL_GameControllerClose(m_playerControllers[i]);
}
}
bool GpInputDriverSDLGamepad::FindJoystickPlayer(uint8_t &playerNum, SDL_JoystickID joystickID)
{
for (int i = 0; i < kMaxPlayers; i++)
{
if (m_playerJoystickIDs[i] == joystickID)
{
playerNum = static_cast<uint8_t>(i);
return true;
}
}
return false;
}
void GpInputDriverSDLGamepad::HandleDeviceAdded(SDL_JoystickID joystickID)
{
for (int i = 0; i < kMaxPlayers; i++)
{
if (m_playerJoystickIDs[i] == -1)
{
SDL_GameController *controller = SDL_GameControllerOpen(joystickID);
if (controller)
{
m_playerJoystickIDs[i] = joystickID;
m_playerControllers[i] = controller;
}
return;
}
}
}
void GpInputDriverSDLGamepad::HandleDeviceRemoved(SDL_JoystickID joystickID)
{
int playerNum = 0;
bool foundPlayer = false;
for (int i = 0; i < kMaxPlayers; i++)
{
if (m_playerJoystickIDs[i] == joystickID)
{
SDL_GameControllerClose(m_playerControllers[i]);
m_playerJoystickIDs[i] = -1;
m_playerControllers[i] = nullptr;
playerNum = i;
foundPlayer = true;
}
}
if (!foundPlayer)
return;
for (int axis = 0; axis < GpGamepadAxes::kCount; axis++)
{
GpVOSEvent evt;
evt.m_eventType = GpVOSEventTypes::kGamepadInput;
evt.m_event.m_gamepadInputEvent.m_eventType = GpGamepadInputEventTypes::kAnalogAxisChanged;
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_axis = static_cast<GpGamepadAxis_t>(axis);
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_player = playerNum;
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_state = 0;
m_pendingEvents.push_back(evt);
}
for (int button = 0; button < GpGamepadButtons::kCount; button++)
{
if (m_playerButtonDown[playerNum][button])
{
m_playerButtonDown[playerNum][button] = false;
GpVOSEvent evt;
evt.m_eventType = GpVOSEventTypes::kKeyboardInput;
evt.m_event.m_keyboardInputEvent.m_eventType = GpKeyboardInputEventTypes::kUp;
evt.m_event.m_keyboardInputEvent.m_keyIDSubset = GpKeyIDSubsets::kGamepadButton;
evt.m_event.m_keyboardInputEvent.m_key.m_gamepadKey.m_player = playerNum;
evt.m_event.m_keyboardInputEvent.m_key.m_gamepadKey.m_button = static_cast<GpGamepadButton_t>(button);
evt.m_event.m_keyboardInputEvent.m_repeatCount = 0;
m_pendingEvents.push_back(evt);
}
}
}
void GpInputDriverSDLGamepad::ProcessSDLEvent(const SDL_Event &msg)
{
IGpVOSEventQueue *evtQueue = m_properties.m_eventQueue;
switch (msg.type)
{
case SDL_CONTROLLERAXISMOTION:
{
const SDL_ControllerAxisEvent &axisMsg = msg.caxis;
GpGamepadAxis_t axis = GpGamepadAxes::kCount;
uint8_t playerNumber = 0;
if (!FindJoystickPlayer(playerNumber, axisMsg.which))
break;
if (axisMsg.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT)
axis = GpGamepadAxes::kLeftTrigger;
else if (axisMsg.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT)
axis = GpGamepadAxes::kRightTrigger;
else if (axisMsg.axis == SDL_CONTROLLER_AXIS_LEFTX)
axis = GpGamepadAxes::kLeftStickX;
else if (axisMsg.axis == SDL_CONTROLLER_AXIS_LEFTY)
axis = GpGamepadAxes::kLeftStickY;
else if (axisMsg.axis == SDL_CONTROLLER_AXIS_RIGHTX)
axis = GpGamepadAxes::kRightStickX;
else if (axisMsg.axis == SDL_CONTROLLER_AXIS_RIGHTY)
axis = GpGamepadAxes::kRightStickY;
else
break;
GpVOSEvent evt;
evt.m_eventType = GpVOSEventTypes::kGamepadInput;
evt.m_event.m_gamepadInputEvent.m_eventType = GpGamepadInputEventTypes::kAnalogAxisChanged;
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_axis = axis;
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_player = playerNumber;
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_state = std::max<int16_t>(-32767, axisMsg.value);
m_pendingEvents.push_back(evt);
}
break;
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
{
const bool isDown = (msg.type == SDL_CONTROLLERBUTTONDOWN);
const SDL_ControllerButtonEvent &buttonMsg = msg.cbutton;
GpGamepadButton_t gpButton = GpGamepadButtons::kCount;
uint8_t playerNumber = 0;
if (!FindJoystickPlayer(playerNumber, buttonMsg.which))
break;
if (buttonMsg.button == SDL_CONTROLLER_BUTTON_A)
gpButton = GpGamepadButtons::kFaceRight;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_B)
gpButton = GpGamepadButtons::kFaceDown;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_X)
gpButton = GpGamepadButtons::kFaceUp;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_Y)
gpButton = GpGamepadButtons::kFaceLeft;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_START)
gpButton = GpGamepadButtons::kMisc1;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_BACK)
gpButton = GpGamepadButtons::kMisc2;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_LEFTSTICK)
gpButton = GpGamepadButtons::kLeftStick;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_RIGHTSTICK)
gpButton = GpGamepadButtons::kRightStick;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER)
gpButton = GpGamepadButtons::kLeftBumper;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
gpButton = GpGamepadButtons::kRightBumper;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
gpButton = GpGamepadButtons::kDPadUp;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
gpButton = GpGamepadButtons::kDPadDown;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
gpButton = GpGamepadButtons::kDPadLeft;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
gpButton = GpGamepadButtons::kDPadRight;
else
break;
m_playerButtonDown[playerNumber][gpButton] = isDown;
GpVOSEvent evt;
evt.m_eventType = GpVOSEventTypes::kKeyboardInput;
evt.m_event.m_keyboardInputEvent.m_eventType = (isDown ? GpKeyboardInputEventTypes::kDown : GpKeyboardInputEventTypes::kUp);
evt.m_event.m_keyboardInputEvent.m_keyIDSubset = GpKeyIDSubsets::kGamepadButton;
evt.m_event.m_keyboardInputEvent.m_key.m_gamepadKey.m_player = playerNumber;
evt.m_event.m_keyboardInputEvent.m_key.m_gamepadKey.m_button = gpButton;
evt.m_event.m_keyboardInputEvent.m_repeatCount = 0;
m_pendingEvents.push_back(evt);
}
break;
case SDL_CONTROLLERDEVICEADDED:
HandleDeviceAdded(msg.cdevice.which);
break;
case SDL_CONTROLLERDEVICEREMOVED:
HandleDeviceRemoved(msg.cdevice.which);
break;
case SDL_CONTROLLERDEVICEREMAPPED:
// Not really sure what to do here, just re-add it
HandleDeviceRemoved(msg.cdevice.which);
HandleDeviceAdded(msg.cdevice.which);
break;
}
}
IGpInputDriver *GpDriver_CreateInputDriver_SDL2_Gamepad(const GpInputDriverProperties &properties)
{
return GpInputDriverSDLGamepad::Create(properties);
}

View File

@@ -0,0 +1,14 @@
#pragma once
#include "IGpInputDriver.h"
#include "GpInputDriverProperties.h"
#include "GpVOSEvent.h"
union SDL_Event;
struct IGpInputDriverSDLGamepad : public IGpInputDriver
{
virtual void ProcessSDLEvent(const SDL_Event &evt) = 0;
static IGpInputDriverSDLGamepad *GetInstance();
};

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"
@@ -29,16 +27,16 @@
GpWindowsGlobals g_gpWindowsGlobals;
extern "C" __declspec(dllimport) IGpInputDriver *GpDriver_CreateInputDriver_XInput(const GpInputDriverProperties &properties);
extern "C" __declspec(dllimport) 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 WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0)
return -1;
LPWSTR cmdLine = GetCommandLineW();
@@ -79,7 +77,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
EGpInputDriverType inputDrivers[] =
{
EGpInputDriverType_XInput
EGpInputDriverType_SDL2_Gamepad
};
g_gpGlobalConfig.m_inputDriverTypes = inputDrivers;
@@ -91,7 +89,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_SDL_GL2, GpDriver_CreateDisplayDriver_SDL_GL2);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_SDL2, GpDriver_CreateAudioDriver_SDL);
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_XInput, GpDriver_CreateInputDriver_XInput);
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_SDL2_Gamepad, GpDriver_CreateInputDriver_SDL2_Gamepad);
GpFontHandlerFactory::RegisterFontHandlerFactory(EGpFontHandlerType_FreeType2, GpDriver_CreateFontHandler_FreeType2);
if (logger)

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

View File

@@ -0,0 +1,35 @@
#include "Functions.h"
#include "DrawQuadPixelConstants.h"
#define GP_GL_SHADER_CODE_DRAWQUAD32P_GLSL \
"\n"\
"varying vec4 texCoord;\n"\
"uniform sampler2D surfaceTexture;\n"\
"uniform sampler2D paletteTexture;\n"\
"\n"\
"vec3 SamplePixel(vec2 tc)\n"\
"{\n"\
" return texture2D(surfaceTexture, tc).rgb;\n"\
"}\n"\
"\n"\
"void main()\n"\
"{\n"\
" vec4 resultColor = vec4(SamplePixel(texCoord.xy), 1.0);\n"\
" resultColor *= constants_Modulation;\n"\
"#ifdef ENABLE_FLICKER\n"\
" resultColor = ApplyFlicker(constants_FlickerAxis, texCoord.zw, constants_FlickerStartThreshold, constants_FlickerEndThreshold, resultColor * constants_Modulation);\n"\
" if (resultColor.a < 1.0)\n"\
" discard;\n"\
"#endif\n"\
" resultColor = ApplyDesaturation(constants_Desaturation, resultColor);\n"\
"\n"\
" gl_FragColor = vec4(ApplyColorSpaceTransform(resultColor.rgb), resultColor.a);\n"\
"}\n"
namespace GpBinarizedShaders
{
const char *g_drawQuad32PF_GL2 = "#define ENABLE_FLICKER\n" GP_GL_SHADER_CODE_MEDIUM_PRECISION_PREFIX GP_GL_SHADER_CODE_DRAWQUADPIXELCONSTANTS_H GP_GL_SHADER_CODE_FUNCTIONS_H GP_GL_SHADER_CODE_DRAWQUAD32P_GLSL;
const char *g_drawQuad32PNF_GL2 = GP_GL_SHADER_CODE_MEDIUM_PRECISION_PREFIX GP_GL_SHADER_CODE_DRAWQUADPIXELCONSTANTS_H GP_GL_SHADER_CODE_FUNCTIONS_H GP_GL_SHADER_CODE_DRAWQUAD32P_GLSL;
const char *g_drawQuad32ICCPF_GL2 = "#define USE_ICC_PROFILE\n" "#define ENABLE_FLICKER\n" GP_GL_SHADER_CODE_MEDIUM_PRECISION_PREFIX GP_GL_SHADER_CODE_DRAWQUADPIXELCONSTANTS_H GP_GL_SHADER_CODE_FUNCTIONS_H GP_GL_SHADER_CODE_DRAWQUAD32P_GLSL;
const char *g_drawQuad32ICCPNF_GL2 = "#define USE_ICC_PROFILE\n" GP_GL_SHADER_CODE_MEDIUM_PRECISION_PREFIX GP_GL_SHADER_CODE_DRAWQUADPIXELCONSTANTS_H GP_GL_SHADER_CODE_FUNCTIONS_H GP_GL_SHADER_CODE_DRAWQUAD32P_GLSL;
}

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

View File

@@ -18,7 +18,7 @@
"enabled" : false
},
{
"name" : "Aerofoil ©2019-2020 Eric Lasota",
"name" : "Aerofoil ©2019-2021 Eric Lasota",
"itemType" : "Label",
"pos" : [ 16, 21 ],
"size" : [ 406, 20 ],

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 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

@@ -2,14 +2,28 @@ rmdir /S /Q Packaged
mkdir Packaged
mkdir Packaged\Houses
mkdir Packaged\WinCursors
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
attrib -R Packaged\Houses\*
x64\Release\hqx2gp.exe "GliderProData\Houses\Art Museum.binhex" "DefaultTimestamp.timestamp" "Packaged\Houses\Art Museum"
@@ -70,11 +84,52 @@ x64\Release\FTagData.exe "DefaultTimestamp.timestamp" "Packaged\Houses\SpacePods
x64\Release\FTagData.exe "DefaultTimestamp.timestamp" "Packaged\Houses\Teddy World.mov.gpf" MooV ozm5 0 0 locked
x64\Release\FTagData.exe "DefaultTimestamp.timestamp" "Packaged\Houses\Titanic.mov.gpf" MooV ozm5 0 0 locked
del /Q Packaged\Houses\*.gpr
del /Q Packaged\ApplicationResources.gpr
copy /Y GliderProData\ConvertedMovies\*.mov.gpa Packaged\Houses\
x64\Release\MergeGPF.exe "Packaged\Houses\Art Museum.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\California or Bust!.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Castle o' the Air.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\CD Demo House.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Davis Station.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Demo House.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Fun House.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Grand Prix.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\ImagineHouse PRO II.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\In The Mirror.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Land of Illusion.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Leviathan.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Metropolis.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Nemo's Market.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Rainbow's End.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Slumberland.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\SpacePods.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Teddy World.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\The Asylum Pro.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Titanic.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Art Museum.mov.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Castle o' the Air.mov.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\CD Demo House.mov.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Davis Station.mov.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Demo House.mov.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Grand Prix.mov.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\ImagineHouse PRO II.mov.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Land of Illusion.mov.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Leviathan.mov.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Nemo's Market.mov.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Rainbow's End.mov.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Slumberland.mov.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\SpacePods.mov.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Teddy World.mov.gpf"
x64\Release\MergeGPF.exe "Packaged\Houses\Titanic.mov.gpf"
del /Q Packaged\Houses\*.gpr
del /Q Packaged\Houses\*.gpa
del /Q Packaged\Houses\*.gpd
del /Q Packaged\ApplicationResources.gpr
del /Q Packaged\ApplicationResources.gpa
attrib +R Packaged\Houses\*
attrib +R Packaged\ApplicationResources.gpf
pause

0
Empty.r Normal file
View File

View File

@@ -2,8 +2,12 @@
#include <string>
#include <Windows.h>
#include "MacFileInfo.h"
#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)
{
@@ -26,22 +30,18 @@ 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)
{
uint8_t encodedTimestamp[8];
if (fread(encodedTimestamp, 1, 8, tsF) != 8)
if (fread(&ts, 1, sizeof(ts), tsF) != sizeof(ts))
{
fprintf(stderr, "Error reading timestamp file");
return -1;
}
for (int i = 0; i < 8; i++)
timestamp |= static_cast<int64_t>(encodedTimestamp[i]) << (i * 8);
fclose(tsF);
}
@@ -52,7 +52,7 @@ int main(int argc, const char **argv)
mfp.m_yPos = atoi(argv[6]);
mfp.m_finderFlags = 0;
mfp.m_protected = 0;
mfp.m_modifiedDate = mfp.m_creationDate = timestamp;
mfp.m_modifiedTimeMacEpoch = mfp.m_createdTimeMacEpoch = timestamp;
for (int i = 7; i < argc; i++)
{
@@ -78,12 +78,14 @@ 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)
{
fwrite(mps.m_data, PortabilityLayer::MacFilePropertiesSerialized::kSize, 1, file);
fclose(file);
PortabilityLayer::CFileStream stream(file);
mps.WriteAsPackage(stream, ts);
stream.Close();
}
return 0;

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

@@ -11,6 +11,7 @@
#include "MenuManager.h"
#include "IGpDisplayDriver.h"
#include "IGpSystemServices.h"
#include "Vec2i.h"
#include "WindowManager.h"
#include "PLDrivers.h"
@@ -18,6 +19,7 @@
#include "PLPasStr.h"
#include <algorithm>
#include <cmath>
#define kSwitchDepthAlert 130
#define kSetMemoryAlert 180
@@ -420,11 +422,9 @@ void HandleDepthSwitching (void)
void GetDeviceRect(Rect *rect)
{
unsigned int width;
unsigned int height;
PLDrivers::GetDisplayDriver()->GetDisplayResolution(&width, &height);
PortabilityLayer::Vec2i displayResolution = PortabilityLayer::WindowManager::GetInstance()->GetDisplayResolution();
SetRect(rect, 0, 0, static_cast<short>(width), static_cast<short>(height));
SetRect(rect, 0, 0, static_cast<short>(displayResolution.m_x), static_cast<short>(displayResolution.m_y));
}
Boolean AreWeColorOrGrayscale()

View File

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

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