mirror of
https://github.com/elasota/Aerofoil.git
synced 2026-03-01 13:25:23 +00:00
Compare commits
78 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b90d0c303c | ||
|
|
7842e721e5 | ||
|
|
93195207dc | ||
|
|
59741dd966 | ||
|
|
1ac69c2c75 | ||
|
|
69f59f769d | ||
|
|
bb2af5abb3 | ||
|
|
3692a966bf | ||
|
|
7916c72fc4 | ||
|
|
7951f579e0 | ||
|
|
b64c904558 | ||
|
|
a6f6ffcdcc | ||
|
|
6fb45f480b | ||
|
|
9ba0e9f13d | ||
|
|
0df94405f8 | ||
|
|
ae69696cbd | ||
|
|
50f420d2b1 | ||
|
|
c87f238563 | ||
|
|
48fe83bb33 | ||
|
|
b2b27ef335 | ||
|
|
89831f0ff6 | ||
|
|
99fd71196d | ||
|
|
7060676b73 | ||
|
|
184f867f79 | ||
|
|
cbd759c754 | ||
|
|
2ada8029d0 | ||
|
|
8e0d8e261e | ||
|
|
20b9eef64d | ||
|
|
c147e1100e | ||
|
|
0a2e730d26 | ||
|
|
922cd0fd06 | ||
|
|
b8bf6be44f | ||
|
|
2897c4ffab | ||
|
|
35c174984b | ||
|
|
da16edea8d | ||
|
|
2fe1ea2ee7 | ||
|
|
0931f25f23 | ||
|
|
7f4d782c0d | ||
|
|
f2cda23b0f | ||
|
|
6292705968 | ||
|
|
6931b3f505 | ||
|
|
d70a5b3bfc | ||
|
|
f0913d0d6a | ||
|
|
80584eb781 | ||
|
|
fe4a8a55c6 | ||
|
|
55ec6c516c | ||
|
|
3917e1a370 | ||
|
|
6715bcb030 | ||
|
|
c981a97a20 | ||
|
|
a5562f96e0 | ||
|
|
d97bd8ad1c | ||
|
|
a43f32ab88 | ||
|
|
e94d1511b1 | ||
|
|
95e4eb4e34 | ||
|
|
15bdb97c38 | ||
|
|
e7246c1444 | ||
|
|
35b8e922d7 | ||
|
|
3090f70ee6 | ||
|
|
484e18a9af | ||
|
|
83d37a7c94 | ||
|
|
fc043af3a1 | ||
|
|
2ebd3f2cf3 | ||
|
|
ebab2ee188 | ||
|
|
032e44d981 | ||
|
|
7961ca3af7 | ||
|
|
6851025147 | ||
|
|
f0b1d6fff9 | ||
|
|
70e0948847 | ||
|
|
a698286087 | ||
|
|
b75313fd7b | ||
|
|
cab862ed8b | ||
|
|
553e343abe | ||
|
|
0aa36b27a9 | ||
|
|
f6185b1c78 | ||
|
|
ff29d5b92c | ||
|
|
964c9b8858 | ||
|
|
8a48726b2e | ||
|
|
de06669239 |
13
.gitignore
vendored
13
.gitignore
vendored
@@ -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
|
||||
|
||||
21
Aerofoil.sln
21
Aerofoil.sln
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1
AerofoilAndroid/app/jni/.gitignore
vendored
1
AerofoilAndroid/app/jni/.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
AerofoilSDL
|
||||
AerofoilPortable
|
||||
Common
|
||||
FreeType
|
||||
GpApp
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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" /> -->
|
||||
|
||||
@@ -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 ..
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
8
AerofoilPortable.props
Normal 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>
|
||||
@@ -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)
|
||||
66
AerofoilPortable/GpMutex_Cpp11.h
Normal file
66
AerofoilPortable/GpMutex_Cpp11.h
Normal 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;
|
||||
50
AerofoilPortable/GpSystemServices_POSIX.cpp
Normal file
50
AerofoilPortable/GpSystemServices_POSIX.cpp
Normal 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;
|
||||
}
|
||||
17
AerofoilPortable/GpSystemServices_POSIX.h
Normal file
17
AerofoilPortable/GpSystemServices_POSIX.h
Normal 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;
|
||||
};
|
||||
82
AerofoilPortable/GpThreadEvent_Cpp11.cpp
Normal file
82
AerofoilPortable/GpThreadEvent_Cpp11.cpp
Normal 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);
|
||||
}
|
||||
|
||||
28
AerofoilPortable/GpThreadEvent_Cpp11.h
Normal file
28
AerofoilPortable/GpThreadEvent_Cpp11.h
Normal 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;
|
||||
};
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
8
AerofoilSDL/AerofoilSDL_Combined.cpp
Normal file
8
AerofoilSDL/AerofoilSDL_Combined.cpp
Normal 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"
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
308
AerofoilSDL/GpInputDriver_SDL_Gamepad.cpp
Normal file
308
AerofoilSDL/GpInputDriver_SDL_Gamepad.cpp
Normal 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);
|
||||
}
|
||||
14
AerofoilSDL/GpInputDriver_SDL_Gamepad.h
Normal file
14
AerofoilSDL/GpInputDriver_SDL_Gamepad.h
Normal 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();
|
||||
};
|
||||
@@ -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
5
AerofoilSDL/GpSDL.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#ifdef __CYGWIN__
|
||||
#define GP_SDL_DIRECTORY_PREFIX "SDL2/"
|
||||
#else
|
||||
#define GP_SDL_DIRECTORY_PREFIX
|
||||
#endif
|
||||
35
AerofoilSDL/ShaderCode/DrawQuad32P.cpp
Normal file
35
AerofoilSDL/ShaderCode/DrawQuad32P.cpp
Normal 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
3
AerofoilWeb/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
obj
|
||||
res
|
||||
bin
|
||||
4
AerofoilWeb/AerofoilWeb_Combined.cpp
Normal file
4
AerofoilWeb/AerofoilWeb_Combined.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "GpFileSystem_Web.cpp"
|
||||
#include "GpLogDriver_Web.cpp"
|
||||
#include "GpMain_SDL_Web.cpp"
|
||||
#include "GpSystemServices_Web.cpp"
|
||||
15
AerofoilWeb/AerofoilWeb_Resources.cpp
Normal file
15
AerofoilWeb/AerofoilWeb_Resources.cpp
Normal 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"
|
||||
}
|
||||
}
|
||||
7
AerofoilWeb/BuildAerofoilSDL.bat
Normal file
7
AerofoilWeb/BuildAerofoilSDL.bat
Normal 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
|
||||
7
AerofoilWeb/BuildAerofoilWeb.bat
Normal file
7
AerofoilWeb/BuildAerofoilWeb.bat
Normal 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
|
||||
7
AerofoilWeb/BuildGpApp.bat
Normal file
7
AerofoilWeb/BuildGpApp.bat
Normal 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
|
||||
7
AerofoilWeb/BuildGpShell.bat
Normal file
7
AerofoilWeb/BuildGpShell.bat
Normal 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
|
||||
7
AerofoilWeb/BuildMacRomanConversion.bat
Normal file
7
AerofoilWeb/BuildMacRomanConversion.bat
Normal 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
|
||||
7
AerofoilWeb/BuildPortabilityLayer.bat
Normal file
7
AerofoilWeb/BuildPortabilityLayer.bat
Normal 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
|
||||
10
AerofoilWeb/BuildResources.bat
Normal file
10
AerofoilWeb/BuildResources.bat
Normal 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
|
||||
626
AerofoilWeb/GpFileSystem_Web.cpp
Normal file
626
AerofoilWeb/GpFileSystem_Web.cpp
Normal 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;
|
||||
62
AerofoilWeb/GpFileSystem_Web.h
Normal file
62
AerofoilWeb/GpFileSystem_Web.h
Normal 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;
|
||||
};
|
||||
28
AerofoilWeb/GpFileSystem_Web_Resources.h
Normal file
28
AerofoilWeb/GpFileSystem_Web_Resources.h
Normal 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();
|
||||
}
|
||||
}
|
||||
89
AerofoilWeb/GpLogDriver_Web.cpp
Normal file
89
AerofoilWeb/GpLogDriver_Web.cpp
Normal 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;
|
||||
25
AerofoilWeb/GpLogDriver_Web.h
Normal file
25
AerofoilWeb/GpLogDriver_Web.h
Normal 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;
|
||||
};
|
||||
91
AerofoilWeb/GpMain_SDL_Web.cpp
Normal file
91
AerofoilWeb/GpMain_SDL_Web.cpp
Normal 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;
|
||||
}
|
||||
209
AerofoilWeb/GpSystemServices_Web.cpp
Normal file
209
AerofoilWeb/GpSystemServices_Web.cpp
Normal 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;
|
||||
41
AerofoilWeb/GpSystemServices_Web.h
Normal file
41
AerofoilWeb/GpSystemServices_Web.h
Normal 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
5
AerofoilWeb/Link.bat
Normal 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%
|
||||
3
AerofoilWeb/MakeBuildDirs.bat
Normal file
3
AerofoilWeb/MakeBuildDirs.bat
Normal file
@@ -0,0 +1,3 @@
|
||||
mkdir obj
|
||||
mkdir bin
|
||||
mkdir res
|
||||
9
AerofoilWeb/Rebuild.bat
Normal file
9
AerofoilWeb/Rebuild.bat
Normal 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
1
AerofoilWeb/Run.bat
Normal file
@@ -0,0 +1 @@
|
||||
emrun bin/aerofoil.html
|
||||
12
AerofoilWin.props
Normal file
12
AerofoilWin.props
Normal 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>
|
||||
488
AerofoilX/GpFileSystem_X.cpp
Normal file
488
AerofoilX/GpFileSystem_X.cpp
Normal 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;
|
||||
42
AerofoilX/GpFileSystem_X.h
Normal file
42
AerofoilX/GpFileSystem_X.h
Normal 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
127
AerofoilX/GpLogDriver_X.cpp
Normal 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
28
AerofoilX/GpLogDriver_X.h
Normal 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;
|
||||
};
|
||||
77
AerofoilX/GpMain_SDL_X.cpp
Normal file
77
AerofoilX/GpMain_SDL_X.cpp
Normal 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;
|
||||
}
|
||||
137
AerofoilX/GpSystemServices_X.cpp
Normal file
137
AerofoilX/GpSystemServices_X.cpp
Normal 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;
|
||||
35
AerofoilX/GpSystemServices_X.h
Normal file
35
AerofoilX/GpSystemServices_X.h
Normal 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;
|
||||
};
|
||||
@@ -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 |
@@ -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
265
CMakeLists.txt
Normal 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)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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)
|
||||
313
GenerateFonts/GenerateFonts.cpp
Normal file
313
GenerateFonts/GenerateFonts.cpp
Normal 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;
|
||||
}
|
||||
101
GenerateFonts/GenerateFonts.vcxproj
Normal file
101
GenerateFonts/GenerateFonts.vcxproj
Normal 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>
|
||||
22
GenerateFonts/GenerateFonts.vcxproj.filters
Normal file
22
GenerateFonts/GenerateFonts.vcxproj.filters
Normal 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>
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
|
||||
#include "Externs.h"
|
||||
#include "PLPalettes.h"
|
||||
#include "PLPasStr.h"
|
||||
#include "QDStandardPalette.h"
|
||||
#include "ResolveCachingColor.h"
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user