Rename projects to Aerofoil

This commit is contained in:
elasota
2020-01-03 00:30:09 -05:00
parent 3642f0c045
commit ec7e511cdd
61 changed files with 14 additions and 153 deletions

217
Aerofoil/Aerofoil.filters Normal file
View File

@@ -0,0 +1,217 @@
<?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="GpMain_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpMain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpDisplayDriverFactory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpGlobalConfig.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpAppEnvironment.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpFileSystem_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpMemoryBuffer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpPLGlueDisplayDriver.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpFileStream_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpSystemServices_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpFiberStarter_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpFiber_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpPLGlueAudioDriver.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpAudioDriverFactory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpPLGlueAudioChannel.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpMutex_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpThreadEvent_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpFontHandlerFactory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpFontHandler_FreeType2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpVOSEventQueue.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpColorCursor_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpInputDriverFactory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GpWindows.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpDisplayDriverFactory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="IGpDisplayDriver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpMain.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpGlobalConfig.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpAppEnvironment.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpCoreDefs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpRingBuffer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpFileSystem_Win32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpMemoryBuffer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpPLGlueDisplayDriver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpFileStream_Win32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpSystemServices_Win32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpFiberStarter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpFiber_Win32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpFiber.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="IGpAudioDriver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpAudioDriverFactory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpPLGlueAudioDriver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpPLGlueAudioChannel.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="IGpAudioChannel.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpMutex_Win32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpThreadEvent_Win32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\IGpAudioChannelCallbacks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpFontHandlerFactory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpFontHandler_FreeType2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpVOSEventQueue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\IGpDisplayDriverSurface.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpComPtr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\IGpColorCursor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\GpColorCursor_Win32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\EGpStandardCursor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpInputDriverFactory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\EGpInputDriverType.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\GpInputDriverProperties.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\GpDisplayDriverTickStatus.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\GpFileCreationDisposition.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\GpApplicationName.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Aerofoil.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="ConvertedResources\Large128.ico">
<Filter>Resource Files</Filter>
</Image>
<Image Include="ConvertedResources\Small128.ico">
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
</Project>

BIN
Aerofoil/Aerofoil.rc Normal file

Binary file not shown.

237
Aerofoil/Aerofoil.vcxproj Normal file
View File

@@ -0,0 +1,237 @@
<?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|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<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>{0E383EF0-CEF7-4733-87C6-5AC9844AA1EF}</ProjectGuid>
<RootNamespace>Aerofoil</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<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|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\GpCommon.props" />
<Import Project="..\GpMainApp.props" />
<Import Project="..\FreeTypePublic.props" />
<Import Project="..\FreeTypeImport.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\GpCommon.props" />
<Import Project="..\GpMainApp.props" />
<Import Project="..\FreeTypePublic.props" />
<Import Project="..\FreeTypeImport.props" />
</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="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\GpCommon.props" />
<Import Project="..\GpMainApp.props" />
<Import Project="..\FreeTypePublic.props" />
<Import Project="..\FreeTypeImport.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="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\GpCommon.props" />
<Import Project="..\GpMainApp.props" />
<Import Project="..\FreeTypePublic.props" />
<Import Project="..\FreeTypeImport.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<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>
</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>
<ClCompile Include="GpAppEnvironment.cpp" />
<ClCompile Include="GpAudioDriverFactory.cpp" />
<ClCompile Include="GpColorCursor_Win32.cpp" />
<ClCompile Include="GpDisplayDriverFactory.cpp" />
<ClCompile Include="GpFiber_Win32.cpp" />
<ClCompile Include="GpFileStream_Win32.cpp" />
<ClCompile Include="GpFileSystem_Win32.cpp" />
<ClCompile Include="GpFontHandlerFactory.cpp" />
<ClCompile Include="GpFontHandler_FreeType2.cpp" />
<ClCompile Include="GpGlobalConfig.cpp" />
<ClCompile Include="GpInputDriverFactory.cpp" />
<ClCompile Include="GpMain.cpp" />
<ClCompile Include="GpMain_Win32.cpp" />
<ClCompile Include="GpMemoryBuffer.cpp" />
<ClCompile Include="GpMutex_Win32.cpp" />
<ClCompile Include="GpPLGlueAudioChannel.cpp" />
<ClCompile Include="GpPLGlueAudioDriver.cpp" />
<ClCompile Include="GpPLGlueDisplayDriver.cpp" />
<ClCompile Include="GpSystemServices_Win32.cpp" />
<ClCompile Include="GpFiberStarter_Win32.cpp" />
<ClCompile Include="GpThreadEvent_Win32.cpp" />
<ClCompile Include="GpVOSEventQueue.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\GpCommon\EGpInputDriverType.h" />
<ClInclude Include="..\GpCommon\EGpStandardCursor.h" />
<ClInclude Include="..\GpCommon\GpApplicationName.h" />
<ClInclude Include="..\GpCommon\GpDisplayDriverTickStatus.h" />
<ClInclude Include="..\GpCommon\GpFileCreationDisposition.h" />
<ClInclude Include="..\GpCommon\GpInputDriverProperties.h" />
<ClInclude Include="..\GpCommon\IGpColorCursor.h" />
<ClInclude Include="..\GpCommon\IGpAudioChannelCallbacks.h" />
<ClInclude Include="..\GpCommon\GpColorCursor_Win32.h" />
<ClInclude Include="..\GpCommon\IGpDisplayDriverSurface.h" />
<ClInclude Include="GpAppEnvironment.h" />
<ClInclude Include="GpAudioDriverFactory.h" />
<ClInclude Include="GpComPtr.h" />
<ClInclude Include="GpCoreDefs.h" />
<ClInclude Include="GpDisplayDriverFactory.h" />
<ClInclude Include="GpFiber.h" />
<ClInclude Include="GpFiber_Win32.h" />
<ClInclude Include="GpFileStream_Win32.h" />
<ClInclude Include="GpFileSystem_Win32.h" />
<ClInclude Include="GpFontHandler_FreeType2.h" />
<ClInclude Include="GpFontHandlerFactory.h" />
<ClInclude Include="GpGlobalConfig.h" />
<ClInclude Include="GpInputDriverFactory.h" />
<ClInclude Include="GpMain.h" />
<ClInclude Include="GpMemoryBuffer.h" />
<ClInclude Include="GpMutex_Win32.h" />
<ClInclude Include="GpPLGlueAudioChannel.h" />
<ClInclude Include="GpPLGlueAudioDriver.h" />
<ClInclude Include="GpPLGlueDisplayDriver.h" />
<ClInclude Include="GpRingBuffer.h" />
<ClInclude Include="GpSystemServices_Win32.h" />
<ClInclude Include="GpFiberStarter.h" />
<ClInclude Include="GpThreadEvent_Win32.h" />
<ClInclude Include="GpVOSEventQueue.h" />
<ClInclude Include="GpWindows.h" />
<ClInclude Include="IGpAudioChannel.h" />
<ClInclude Include="IGpAudioDriver.h" />
<ClInclude Include="IGpDisplayDriver.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FreeType\FreeType.vcxproj">
<Project>{487216d8-16ba-4b4c-b5bf-43feedfee03a}</Project>
</ProjectReference>
<ProjectReference Include="..\GpApp\GpApp.vcxproj">
<Project>{6233c3f2-5781-488e-b190-4fa8836f5a77}</Project>
</ProjectReference>
<ProjectReference Include="..\GpAudioDriver_XAudio2\GpAudioDriver_XAudio2.vcxproj">
<Project>{e3bdc783-8646-433e-adf0-8b6390d36669}</Project>
</ProjectReference>
<ProjectReference Include="..\GpDisplayDriver_D3D11\GpDisplayDriver_D3D11.vcxproj">
<Project>{ffc961ac-55b4-4a38-a83e-06ae98f59acc}</Project>
</ProjectReference>
<ProjectReference Include="..\GpInputDriver_XInput\GpInputDriver_XInput.vcxproj">
<Project>{17b96f07-ef92-47cd-95a5-8e6ee38ab564}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Aerofoil.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="ConvertedResources\Large128.ico" />
<Image Include="ConvertedResources\Small128.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 765 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 826 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

View File

@@ -0,0 +1,181 @@
#include "GpAppEnvironment.h"
#include "GpFiberStarter.h"
#include "GpAppInterface.h"
#include "GpDisplayDriverTickStatus.h"
#include "GpFontHandlerFactory.h"
#include "GpPLGlueAudioDriver.h"
#include "GpPLGlueDisplayDriver.h"
#include "HostSuspendCallArgument.h"
#include "IGpDisplayDriver.h"
#include "IGpFiber.h"
#include "IGpInputDriver.h"
#include <assert.h>
GpAppEnvironment::GpAppEnvironment()
: m_applicationState(ApplicationState_NotStarted)
, m_displayDriver(nullptr)
, m_audioDriver(nullptr)
, m_inputDrivers(nullptr)
, m_numInputDrivers(0)
, m_fontHandler(nullptr)
, m_vosEventQueue(nullptr)
, m_applicationFiber(nullptr)
, m_vosFiber(nullptr)
, m_suspendCallID(PortabilityLayer::HostSuspendCallID_Unknown)
, m_suspendArgs(nullptr)
, m_suspendReturnValue(nullptr)
{
}
GpAppEnvironment::~GpAppEnvironment()
{
assert(m_applicationFiber == nullptr);
}
void GpAppEnvironment::Init()
{
}
GpDisplayDriverTickStatus_t GpAppEnvironment::Tick(IGpFiber *vosFiber)
{
GpAppInterface_Get()->PL_IncrementTickCounter(1);
m_vosFiber = vosFiber;
if (m_applicationState == ApplicationState_WaitingForEvents)
m_applicationState = ApplicationState_Running;
for (;;)
{
switch (m_applicationState)
{
case ApplicationState_NotStarted:
InitializeApplicationState();
m_applicationFiber = GpFiberStarter::StartFiber(GpAppEnvironment::StaticAppThreadFunc, this, vosFiber);
m_applicationState = ApplicationState_Running;
break;
case ApplicationState_WaitingForEvents:
return GpDisplayDriverTickStatuses::kOK;
case ApplicationState_Running:
SynchronizeState();
m_applicationFiber->YieldTo();
break;
case ApplicationState_SystemCall:
{
PortabilityLayer::HostSuspendCallID callID = m_suspendCallID;
const PortabilityLayer::HostSuspendCallArgument *args = m_suspendArgs;
PortabilityLayer::HostSuspendCallArgument *returnValue = m_suspendReturnValue;
DispatchSystemCall(callID, args, returnValue);
assert(m_applicationState != ApplicationState_SystemCall);
}
break;
case ApplicationState_TimedSuspend:
if (m_delaySuspendTicks == 0)
m_applicationState = ApplicationState_Running;
else
{
m_delaySuspendTicks--;
return GpDisplayDriverTickStatuses::kOK;
}
break;
case ApplicationState_Terminated:
m_applicationFiber->Destroy();
m_applicationFiber = nullptr;
return GpDisplayDriverTickStatuses::kApplicationTerminated;
default:
assert(false);
break;
};
}
}
void GpAppEnvironment::Render()
{
GpAppInterface_Get()->PL_Render(m_displayDriver);
}
void GpAppEnvironment::SetDisplayDriver(IGpDisplayDriver *displayDriver)
{
m_displayDriver = displayDriver;
}
void GpAppEnvironment::SetAudioDriver(IGpAudioDriver *audioDriver)
{
m_audioDriver = audioDriver;
}
void GpAppEnvironment::SetInputDrivers(IGpInputDriver *const* inputDrivers, size_t numDrivers)
{
m_inputDrivers = inputDrivers;
m_numInputDrivers = numDrivers;
}
void GpAppEnvironment::SetFontHandler(PortabilityLayer::HostFontHandler *fontHandler)
{
m_fontHandler = fontHandler;
}
void GpAppEnvironment::SetVOSEventQueue(GpVOSEventQueue *eventQueue)
{
m_vosEventQueue = eventQueue;
}
void GpAppEnvironment::StaticAppThreadFunc(void *context)
{
static_cast<GpAppEnvironment*>(context)->AppThreadFunc();
}
void GpAppEnvironment::AppThreadFunc()
{
GpAppInterface_Get()->ApplicationMain();
m_applicationState = ApplicationState_Terminated;
m_vosFiber->YieldTo();
}
void GpAppEnvironment::InitializeApplicationState()
{
GpAppInterface_Get()->PL_HostDisplayDriver_SetInstance(GpPLGlueDisplayDriver::GetInstance());
GpAppInterface_Get()->PL_HostAudioDriver_SetInstance(GpPLGlueAudioDriver::GetInstance());
GpAppInterface_Get()->PL_InstallHostSuspendHook(GpAppEnvironment::StaticSuspendHookFunc, this);
GpAppInterface_Get()->PL_HostFontHandler_SetInstance(m_fontHandler);
GpAppInterface_Get()->PL_HostVOSEventQueue_SetInstance(m_vosEventQueue);
GpPLGlueDisplayDriver::GetInstance()->SetGpDisplayDriver(m_displayDriver);
GpPLGlueAudioDriver::GetInstance()->SetGpAudioDriver(m_audioDriver);
}
void GpAppEnvironment::SynchronizeState()
{
const size_t numInputDrivers = m_numInputDrivers;
for (size_t i = 0; i < numInputDrivers; i++)
m_inputDrivers[i]->ProcessInput();
}
void GpAppEnvironment::StaticSuspendHookFunc(void *context, PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue)
{
GpAppEnvironment *appEnv = static_cast<GpAppEnvironment*>(context);
appEnv->m_suspendCallID = callID;
appEnv->m_suspendArgs = args;
appEnv->m_suspendReturnValue = returnValue;
appEnv->m_applicationState = ApplicationState_SystemCall;
appEnv->m_vosFiber->YieldTo();
}
void GpAppEnvironment::DispatchSystemCall(PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue)
{
switch (callID)
{
case PortabilityLayer::HostSuspendCallID_Delay:
m_applicationState = ApplicationState_TimedSuspend;
m_delaySuspendTicks = args[0].m_uint;
break;
default:
assert(false);
}
}

View File

@@ -0,0 +1,72 @@
#pragma once
#include "GpDisplayDriverTickStatus.h"
#include "GpVOSEventQueue.h"
#include "HostSuspendCallID.h"
#include <stdint.h>
namespace PortabilityLayer
{
union HostSuspendCallArgument;
class HostFontHandler;
class HostVOSEventQueue;
}
struct IGpDisplayDriver;
struct IGpAudioDriver;
struct IGpInputDriver;
struct IGpFiber;
class GpAppEnvironment
{
public:
GpAppEnvironment();
~GpAppEnvironment();
void Init();
GpDisplayDriverTickStatus_t Tick(IGpFiber *vosFiber);
void Render();
void SetDisplayDriver(IGpDisplayDriver *displayDriver);
void SetAudioDriver(IGpAudioDriver *audioDriver);
void SetInputDrivers(IGpInputDriver *const* inputDrivers, size_t numDrivers);
void SetFontHandler(PortabilityLayer::HostFontHandler *fontHandler);
void SetVOSEventQueue(GpVOSEventQueue *eventQueue);
private:
enum ApplicationState
{
ApplicationState_NotStarted,
ApplicationState_WaitingForEvents,
ApplicationState_Running,
ApplicationState_Terminated,
ApplicationState_SystemCall,
ApplicationState_TimedSuspend,
};
static void StaticAppThreadFunc(void *context);
void AppThreadFunc();
void InitializeApplicationState();
void SynchronizeState();
static void StaticSuspendHookFunc(void *context, PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue);
void DispatchSystemCall(PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue);
ApplicationState m_applicationState;
IGpDisplayDriver *m_displayDriver;
IGpAudioDriver *m_audioDriver;
IGpInputDriver *const* m_inputDrivers;
PortabilityLayer::HostFontHandler *m_fontHandler;
GpVOSEventQueue *m_vosEventQueue;
IGpFiber *m_applicationFiber;
IGpFiber *m_vosFiber;
uint32_t m_delaySuspendTicks;
size_t m_numInputDrivers;
PortabilityLayer::HostSuspendCallID m_suspendCallID;
const PortabilityLayer::HostSuspendCallArgument *m_suspendArgs;
PortabilityLayer::HostSuspendCallArgument *m_suspendReturnValue;
};

View File

@@ -0,0 +1,23 @@
#include "GpAudioDriverFactory.h"
#include "GpAudioDriverProperties.h"
#include <assert.h>
IGpAudioDriver *GpAudioDriverFactory::CreateAudioDriver(const GpAudioDriverProperties &properties)
{
assert(properties.m_type < EGpAudioDriverType_Count);
if (ms_registry[properties.m_type])
return ms_registry[properties.m_type](properties);
else
return nullptr;
}
void GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType type, FactoryFunc_t func)
{
assert(type < EGpAudioDriverType_Count);
ms_registry[type] = func;
}
GpAudioDriverFactory::FactoryFunc_t GpAudioDriverFactory::ms_registry[EGpAudioDriverType_Count];

View File

@@ -0,0 +1,18 @@
#pragma once
#include "EGpAudioDriverType.h"
struct IGpAudioDriver;
struct GpAudioDriverProperties;
class GpAudioDriverFactory
{
public:
typedef IGpAudioDriver *(*FactoryFunc_t)(const GpAudioDriverProperties &properties);
static IGpAudioDriver *CreateAudioDriver(const GpAudioDriverProperties &properties);
static void RegisterAudioDriverFactory(EGpAudioDriverType type, FactoryFunc_t func);
private:
static FactoryFunc_t ms_registry[EGpAudioDriverType_Count];
};

View File

@@ -0,0 +1,58 @@
#include "GpColorCursor_Win32.h"
#include <stdlib.h>
#include <new>
void GpColorCursor_Win32::Destroy()
{
this->DecRef();
}
IGpColorCursor_Win32 *GpColorCursor_Win32::Load(const wchar_t *path)
{
HANDLE imageH = LoadImageW(nullptr, path, IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
if (imageH == nullptr)
return nullptr;
HCURSOR cursor = reinterpret_cast<HCURSOR>(imageH);
void *storage = malloc(sizeof(GpColorCursor_Win32));
if (!storage)
{
DestroyCursor(cursor);
return nullptr;
}
return new (storage) GpColorCursor_Win32(reinterpret_cast<HCURSOR>(cursor));
}
GpColorCursor_Win32::GpColorCursor_Win32(HCURSOR cursor)
: m_cursor(cursor)
, m_refCount(1)
{
}
GpColorCursor_Win32::~GpColorCursor_Win32()
{
DestroyCursor(m_cursor);
}
const HCURSOR &GpColorCursor_Win32::GetHCursor() const
{
return m_cursor;
}
void GpColorCursor_Win32::IncRef()
{
m_refCount++;
}
void GpColorCursor_Win32::DecRef()
{
m_refCount--;
if (m_refCount == 0)
{
this->~GpColorCursor_Win32();
free(this);
}
}

View File

@@ -0,0 +1,33 @@
#pragma once
#include "IGpColorCursor.h"
#include "GpWindows.h"
struct IGpColorCursor_Win32 : public IGpColorCursor
{
virtual const HCURSOR &GetHCursor() const = 0;
virtual void IncRef() = 0;
virtual void DecRef() = 0;
};
class GpColorCursor_Win32 final : public IGpColorCursor_Win32
{
public:
void Destroy() override;
const HCURSOR &GetHCursor() const override;
void IncRef() override;
void DecRef() override;
static IGpColorCursor_Win32 *Load(const wchar_t *path);
private:
GpColorCursor_Win32(HCURSOR cursor);
~GpColorCursor_Win32();
HCURSOR m_cursor;
int m_refCount;
};

View File

@@ -0,0 +1,23 @@
#include "GpDisplayDriverFactory.h"
#include "GpDisplayDriverProperties.h"
#include <assert.h>
IGpDisplayDriver *GpDisplayDriverFactory::CreateDisplayDriver(const GpDisplayDriverProperties &properties)
{
assert(properties.m_type < EGpDisplayDriverType_Count);
if (ms_registry[properties.m_type])
return ms_registry[properties.m_type](properties);
else
return nullptr;
}
void GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType type, FactoryFunc_t func)
{
assert(type < EGpDisplayDriverType_Count);
ms_registry[type] = func;
}
GpDisplayDriverFactory::FactoryFunc_t GpDisplayDriverFactory::ms_registry[EGpDisplayDriverType_Count];

View File

@@ -0,0 +1,18 @@
#pragma once
#include "EGpDisplayDriverType.h"
struct IGpDisplayDriver;
struct GpDisplayDriverProperties;
class GpDisplayDriverFactory
{
public:
typedef IGpDisplayDriver *(*FactoryFunc_t)(const GpDisplayDriverProperties &properties);
static IGpDisplayDriver *CreateDisplayDriver(const GpDisplayDriverProperties &properties);
static void RegisterDisplayDriverFactory(EGpDisplayDriverType type, FactoryFunc_t func);
private:
static FactoryFunc_t ms_registry[EGpDisplayDriverType_Count];
};

11
Aerofoil/GpFiberStarter.h Normal file
View File

@@ -0,0 +1,11 @@
#pragma once
struct IGpFiber;
class GpFiberStarter
{
public:
typedef void(*ThreadFunc_t)(void *context);
static IGpFiber *StartFiber(ThreadFunc_t threadFunc, void *context, IGpFiber *creatingFiber);
};

View File

@@ -0,0 +1,52 @@
#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;
creatingFiber->YieldTo();
threadFunc(context);
assert(!"Fiber function exited");
}
}
IGpFiber *GpFiberStarter::StartFiber(ThreadFunc_t threadFunc, void *context, IGpFiber *creatingFiber)
{
ULONG_PTR lowLimit;
ULONG_PTR highLimit;
GetCurrentThreadStackLimits(&lowLimit, &highLimit);
ULONG_PTR stackSize = highLimit - lowLimit;
GpFiberStarter_Win32::FiberStartState startState;
startState.m_context = context;
startState.m_creatingFiber = creatingFiber;
startState.m_threadFunc = threadFunc;
void *fiber = CreateFiber(static_cast<SIZE_T>(stackSize), GpFiberStarter_Win32::FiberStartRoutine, &startState);
if (!fiber)
return nullptr;
SwitchToFiber(fiber);
return GpFiber_Win32::Create(fiber);
}

View File

@@ -0,0 +1,32 @@
#include "GpFiber_Win32.h"
#include <new>
GpFiber_Win32::GpFiber_Win32(LPVOID fiber)
: m_fiber(fiber)
{
}
void GpFiber_Win32::YieldTo()
{
SwitchToFiber(m_fiber);
}
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);
}

18
Aerofoil/GpFiber_Win32.h Normal file
View File

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

View File

@@ -0,0 +1,141 @@
#include "GpFileStream_Win32.h"
GpFileStream_Win32::GpFileStream_Win32(HANDLE handle, bool readable, bool writeable, bool seekable)
: m_handle(handle)
, m_readable(readable)
, m_writeable(writeable)
, m_seekable(seekable)
{
}
size_t GpFileStream_Win32::Read(void *bytesOut, size_t size)
{
if (!m_readable)
return 0;
size_t totalRead = 0;
while (size)
{
const DWORD chunkSizeToRead = (size > MAXDWORD) ? MAXDWORD : size;
DWORD numRead = 0;
BOOL readSucceeded = ReadFile(m_handle, bytesOut, chunkSizeToRead, &numRead, nullptr);
if (!readSucceeded)
return totalRead;
totalRead += static_cast<size_t>(numRead);
size -= static_cast<size_t>(numRead);
bytesOut = static_cast<void*>(static_cast<uint8_t*>(bytesOut) + numRead);
if (numRead != chunkSizeToRead)
return totalRead;
}
return totalRead;
}
size_t GpFileStream_Win32::Write(const void *bytes, size_t size)
{
if (!m_writeable)
return 0;
size_t totalWritten = 0;
while (size)
{
const DWORD chunkSizeToWrite = (size > MAXDWORD) ? MAXDWORD : size;
DWORD numWritten = 0;
BOOL writeSucceeded = WriteFile(m_handle, bytes, chunkSizeToWrite, &numWritten, nullptr);
if (!writeSucceeded)
return totalWritten;
totalWritten += static_cast<size_t>(numWritten);
size -= static_cast<size_t>(numWritten);
bytes = static_cast<const void*>(static_cast<const uint8_t*>(bytes) + numWritten);
if (numWritten != chunkSizeToWrite)
return totalWritten;
}
return totalWritten;
}
bool GpFileStream_Win32::IsSeekable() const
{
return m_seekable;
}
bool GpFileStream_Win32::IsReadOnly() const
{
return !m_writeable;
}
bool GpFileStream_Win32::IsWriteOnly() const
{
return !m_readable;
}
bool GpFileStream_Win32::SeekStart(PortabilityLayer::UFilePos_t loc)
{
LARGE_INTEGER li;
li.QuadPart = static_cast<LONGLONG>(loc);
return SetFilePointerEx(m_handle, li, nullptr, FILE_BEGIN) != 0;
}
bool GpFileStream_Win32::SeekCurrent(PortabilityLayer::FilePos_t loc)
{
LARGE_INTEGER li;
li.QuadPart = static_cast<LONGLONG>(loc);
return SetFilePointerEx(m_handle, li, nullptr, FILE_CURRENT) != 0;
}
bool GpFileStream_Win32::SeekEnd(PortabilityLayer::UFilePos_t loc)
{
LARGE_INTEGER li;
li.QuadPart = static_cast<LONGLONG>(loc);
return SetFilePointerEx(m_handle, li, nullptr, FILE_END) != 0;
}
bool GpFileStream_Win32::Truncate(PortabilityLayer::UFilePos_t loc)
{
if (!m_writeable)
return false;
PortabilityLayer::UFilePos_t oldPos = Tell();
if (!SeekStart(loc))
return false;
if (!SetEndOfFile(m_handle))
return false;
if (!SeekStart(oldPos))
return false;
return true;
}
PortabilityLayer::UFilePos_t GpFileStream_Win32::Size() const
{
LARGE_INTEGER fsize;
if (!GetFileSizeEx(m_handle, &fsize))
return 0;
return static_cast<PortabilityLayer::UFilePos_t>(fsize.QuadPart);
}
PortabilityLayer::UFilePos_t GpFileStream_Win32::Tell() const
{
LARGE_INTEGER zero;
zero.QuadPart = 0;
LARGE_INTEGER fpos;
if (!SetFilePointerEx(m_handle, zero, &fpos, FILE_CURRENT))
return 0;
return static_cast<PortabilityLayer::UFilePos_t>(fpos.QuadPart);
}
void GpFileStream_Win32::Close()
{
CloseHandle(m_handle);
}

View File

@@ -0,0 +1,30 @@
#pragma once
#include "GpCoreDefs.h"
#include "GpWindows.h"
#include "IOStream.h"
class GpFileStream_Win32 final : public PortabilityLayer::IOStream
{
public:
explicit GpFileStream_Win32(HANDLE handle, bool readable, bool writeable, bool seekable);
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(PortabilityLayer::UFilePos_t loc) override;
bool SeekCurrent(PortabilityLayer::FilePos_t loc) override;
bool SeekEnd(PortabilityLayer::UFilePos_t loc) override;
bool Truncate(PortabilityLayer::UFilePos_t loc) override;
PortabilityLayer::UFilePos_t Size() const override;
PortabilityLayer::UFilePos_t Tell() const override;
void Close() override;
private:
HANDLE m_handle;
bool m_readable;
bool m_writeable;
bool m_seekable;
};

View File

@@ -0,0 +1,454 @@
#include "GpFileSystem_Win32.h"
#include "GpApplicationName.h"
#include "GpFileStream_Win32.h"
#include "GpWindows.h"
#include "GpMemoryBuffer.h"
#include "HostDirectoryCursor.h"
#include <string>
#include <Shlwapi.h>
#include <ShlObj.h>
#include <commdlg.h>
#include <assert.h>
class GpDirectoryCursor_Win32 final : public PortabilityLayer::HostDirectoryCursor
{
public:
static GpDirectoryCursor_Win32 *Create(const HANDLE &handle, const WIN32_FIND_DATAW &findData);
bool GetNext(const char *&outFileName) override;
void Destroy() override;
private:
GpDirectoryCursor_Win32(const HANDLE &handle, const WIN32_FIND_DATAW &findData);
~GpDirectoryCursor_Win32();
HANDLE m_handle;
WIN32_FIND_DATAW m_findData;
char m_chars[MAX_PATH + 1];
bool m_haveNext;
};
GpDirectoryCursor_Win32 *GpDirectoryCursor_Win32::Create(const HANDLE &handle, const WIN32_FIND_DATAW &findData)
{
void *storage = malloc(sizeof(GpDirectoryCursor_Win32));
if (!storage)
return nullptr;
return new (storage) GpDirectoryCursor_Win32(handle, findData);
}
bool GpDirectoryCursor_Win32::GetNext(const char *&outFileName)
{
while (m_haveNext)
{
bool haveResult = false;
bool hasInvalidChars = false;
for (const wchar_t *fnameScan = m_findData.cFileName; *fnameScan; fnameScan++)
{
const int32_t asInt = static_cast<int32_t>(*fnameScan);
if (asInt < 1 || asInt >= 128)
{
hasInvalidChars = true;
break;
}
}
if (!hasInvalidChars && wcscmp(m_findData.cFileName, L".") && wcscmp(m_findData.cFileName, L".."))
{
const size_t len = wcslen(m_findData.cFileName);
haveResult = true;
for (size_t i = 0; i <= len; i++)
m_chars[i] = static_cast<char>(m_findData.cFileName[i]);
}
m_haveNext = (FindNextFileW(m_handle, &m_findData) != FALSE);
if (haveResult)
{
outFileName = m_chars;
return true;
}
}
return false;
}
void GpDirectoryCursor_Win32::Destroy()
{
this->~GpDirectoryCursor_Win32();
free(this);
}
GpDirectoryCursor_Win32::GpDirectoryCursor_Win32(const HANDLE &handle, const WIN32_FIND_DATAW &findData)
: m_handle(handle)
, m_findData(findData)
, m_haveNext(true)
{
}
GpDirectoryCursor_Win32::~GpDirectoryCursor_Win32()
{
FindClose(m_handle);
}
GpFileSystem_Win32::GpFileSystem_Win32()
{
// GP TODO: This shouldn't be static init since it allocates memory
m_executablePath[0] = 0;
PWSTR docsPath;
if (!FAILED(SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, nullptr, &docsPath)))
{
try
{
m_prefsDir = docsPath;
}
catch(...)
{
CoTaskMemFree(docsPath);
throw;
}
m_prefsDir.append(L"\\GlidePort");
m_userHousesDir = m_prefsDir + L"\\Houses";
m_scoresDir = m_prefsDir + L"\\Scores";
CreateDirectoryW(m_prefsDir.c_str(), nullptr);
CreateDirectoryW(m_scoresDir.c_str(), nullptr);
CreateDirectoryW(m_userHousesDir.c_str(), nullptr);
m_prefsDir.append(L"\\");
m_scoresDir.append(L"\\");
m_userHousesDir.append(L"\\");
}
DWORD modulePathSize = GetModuleFileNameW(nullptr, m_executablePath, MAX_PATH);
if (modulePathSize == MAX_PATH || modulePathSize == 0)
m_executablePath[0] = 0;
size_t currentPathLength = wcslen(m_executablePath);
for (;;)
{
while (currentPathLength > 0 && m_executablePath[currentPathLength - 1] != '\\')
currentPathLength--;
m_executablePath[currentPathLength] = 0;
if (currentPathLength + 11 > MAX_PATH)
{
// "Resources" append is a longer path than the executable
continue;
}
if (wcscat_s(m_executablePath, L"Resources"))
{
currentPathLength = 0;
break;
}
if (PathFileExistsW(m_executablePath) && PathIsDirectoryW(m_executablePath))
{
m_executablePath[currentPathLength] = 0;
break;
}
else
currentPathLength--;
}
if (currentPathLength > 0)
{
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\\";
}
}
bool GpFileSystem_Win32::FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path)
{
wchar_t winPath[MAX_PATH + 1];
if (!ResolvePath(virtualDirectory, path, winPath))
return false;
return PathFileExistsW(winPath) != 0;
}
bool GpFileSystem_Win32::FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists)
{
wchar_t winPath[MAX_PATH + 1];
if (!ResolvePath(virtualDirectory, path, winPath))
{
*exists = false;
return false;
}
DWORD attribs = GetFileAttributesW(winPath);
if (attribs == INVALID_FILE_ATTRIBUTES)
{
*exists = false;
return false;
}
return (attribs & FILE_ATTRIBUTE_READONLY) != 0;
}
PortabilityLayer::IOStream *GpFileSystem_Win32::OpenFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition)
{
wchar_t winPath[MAX_PATH + 1];
if (!ResolvePath(virtualDirectory, path, winPath))
return false;
const DWORD desiredAccess = writeAccess ? (GENERIC_WRITE | GENERIC_READ) : GENERIC_READ;
DWORD winCreationDisposition = 0;
switch (createDisposition)
{
case GpFileCreationDispositions::kCreateOrOverwrite:
winCreationDisposition = CREATE_ALWAYS;
break;
case GpFileCreationDispositions::kCreateNew:
winCreationDisposition = CREATE_NEW;
break;
case GpFileCreationDispositions::kCreateOrOpen:
winCreationDisposition = OPEN_ALWAYS;
break;
case GpFileCreationDispositions::kOpenExisting:
winCreationDisposition = OPEN_EXISTING;
break;
case GpFileCreationDispositions::kOverwriteExisting:
winCreationDisposition = TRUNCATE_EXISTING;
break;
default:
return false;
}
HANDLE h = CreateFileW(winPath, desiredAccess, FILE_SHARE_READ, nullptr, winCreationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr);
if (h == INVALID_HANDLE_VALUE)
return false;
return new GpFileStream_Win32(h, true, writeAccess, true);
}
bool GpFileSystem_Win32::DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed)
{
wchar_t winPath[MAX_PATH + 1];
if (!ResolvePath(virtualDirectory, path, winPath))
return false;
if (DeleteFileW(winPath))
{
existed = true;
return true;
}
DWORD err = GetLastError();
if (err == ERROR_FILE_NOT_FOUND)
existed = false;
else
existed = true;
return false;
}
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Win32::ScanDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory)
{
wchar_t winPath[MAX_PATH + 2];
if (!ResolvePath(virtualDirectory, "*", winPath))
return nullptr;
WIN32_FIND_DATAW findData;
HANDLE ff = FindFirstFileW(winPath, &findData);
if (ff == INVALID_HANDLE_VALUE)
return nullptr;
return GpDirectoryCursor_Win32::Create(ff, findData);
}
bool GpFileSystem_Win32::PromptSaveFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, char *path, size_t &outPathLength, size_t pathCapacity, const char *initialFileName)
{
wchar_t baseFN[MAX_PATH + 5];
wchar_t baseDir[MAX_PATH + 5];
const size_t existingPathLen = strlen(initialFileName);
if (existingPathLen >= MAX_PATH)
return false;
for (size_t i = 0; i < existingPathLen; i++)
baseFN[i] = static_cast<wchar_t>(initialFileName[i]);
baseFN[existingPathLen] = 0;
if (!ResolvePath(virtualDirectory, "", baseDir))
return false;
OPENFILENAMEW ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFilter = GP_APPLICATION_NAME_W L" File (*.gpf)\0*.gpf\0";
ofn.lpstrFile = baseFN;
ofn.lpstrDefExt = L"gpf";
ofn.nMaxFile = MAX_PATH;
ofn.lpstrInitialDir = baseDir;
ofn.Flags = OFN_EXPLORER | OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT;
if (!GetSaveFileNameW(&ofn))
return false;
if (ofn.Flags & OFN_EXTENSIONDIFFERENT)
{
MessageBeep(MB_ICONERROR);
MessageBoxW(nullptr, L"Save file failed: Saved files must have the '.gpf' extension", L"Invalid file path", MB_OK);
return false;
}
const wchar_t *fn = ofn.lpstrFile + ofn.nFileOffset;
size_t fnLengthWithoutExt = wcslen(fn);
if (ofn.nFileExtension - 1 > ofn.nFileOffset) // Off by 1 because extension doesn't include .
fnLengthWithoutExt = ofn.nFileExtension - ofn.nFileOffset - 1;
if (fnLengthWithoutExt >= pathCapacity)
{
wchar_t msg[256];
wsprintfW(msg, L"Save file failed: File name is too long. Limit is %i characters.", static_cast<int>(pathCapacity));
MessageBeep(MB_ICONERROR);
MessageBoxW(nullptr, msg, L"Invalid file path", MB_OK);
return false;
}
if (ofn.nFileOffset != wcslen(baseDir) || memcmp(ofn.lpstrFile, baseDir, ofn.nFileOffset * sizeof(wchar_t)))
{
wchar_t msg[256 + MAX_PATH];
wsprintfW(msg, L"Save file failed: File can't be saved here, it must be saved in %s", baseDir);
MessageBeep(MB_ICONERROR);
MessageBoxW(nullptr, msg, L"Invalid file path", MB_OK);
return false;
}
const wchar_t *unsupportedCharMsg = L"File name contains unsupported characters.";
for (size_t i = 0; i < fnLengthWithoutExt; i++)
{
if (fn[i] < static_cast<wchar_t>(0) || fn[i] >= static_cast<wchar_t>(128))
{
MessageBeep(MB_ICONERROR);
MessageBoxW(nullptr, unsupportedCharMsg, L"Invalid file path", MB_OK);
return false;
}
path[i] = static_cast<char>(fn[i]);
}
if (!ValidateFilePath(path, fnLengthWithoutExt))
{
MessageBeep(MB_ICONERROR);
MessageBoxW(nullptr, unsupportedCharMsg, L"Invalid file path", MB_OK);
return false;
}
outPathLength = fnLengthWithoutExt;
return true;
}
bool GpFileSystem_Win32::ValidateFilePath(const char *str, size_t length) const
{
for (size_t i = 0; i < length; i++)
{
const char c = str[i];
if (c >= '0' && c <= '9')
continue;
if (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;
}
const wchar_t *GpFileSystem_Win32::GetBasePath() const
{
return m_executablePath;
}
GpFileSystem_Win32 *GpFileSystem_Win32::GetInstance()
{
return &ms_instance;
}
bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, wchar_t *outPath)
{
const wchar_t *baseDir = nullptr;
switch (virtualDirectory)
{
case PortabilityLayer::VirtualDirectories::kApplicationData:
baseDir = m_packagedDir.c_str();
break;
case PortabilityLayer::VirtualDirectories::kGameData:
baseDir = m_housesDir.c_str();
break;
case PortabilityLayer::VirtualDirectories::kUserData:
baseDir = m_userHousesDir.c_str();
break;
case PortabilityLayer::VirtualDirectories::kPrefs:
baseDir = m_prefsDir.c_str();
break;
case PortabilityLayer::VirtualDirectories::kFonts:
baseDir = m_resourcesDir.c_str();
break;
case PortabilityLayer::VirtualDirectories::kHighScores:
baseDir = m_scoresDir.c_str();
break;
default:
return false;
}
if (baseDir == nullptr)
return false;
const size_t baseDirLen = wcslen(baseDir);
const size_t pathLen = strlen(path);
if (baseDirLen >= MAX_PATH || MAX_PATH - baseDirLen < pathLen)
return false;
memcpy(outPath, baseDir, sizeof(wchar_t) * baseDirLen);
for (size_t i = 0; i < pathLen; i++)
{
char c = path[i];
if (c == '/')
c = '\\';
outPath[baseDirLen + i] = static_cast<wchar_t>(c);
}
outPath[baseDirLen + pathLen] = static_cast<wchar_t>(0);
return true;
}
GpFileSystem_Win32 GpFileSystem_Win32::ms_instance;

View File

@@ -0,0 +1,41 @@
#pragma once
#include "HostFileSystem.h"
#include "GpCoreDefs.h"
#include "GpWindows.h"
#include <string>
class GpFileSystem_Win32 final : public PortabilityLayer::HostFileSystem
{
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;
PortabilityLayer::IOStream *OpenFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition) override;
bool DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) override;
PortabilityLayer::HostDirectoryCursor *ScanDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory) override;
bool PromptSaveFile(PortabilityLayer::VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity, const char *initialFileName) override;
bool ValidateFilePath(const char *path, size_t sz) const override;
const wchar_t *GetBasePath() const;
static GpFileSystem_Win32 *GetInstance();
private:
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, wchar_t *outPath);
std::wstring m_prefsDir;
std::wstring m_scoresDir;
std::wstring m_packagedDir;
std::wstring m_housesDir;
std::wstring m_userHousesDir;
std::wstring m_resourcesDir;
wchar_t m_executablePath[MAX_PATH];
static GpFileSystem_Win32 ms_instance;
};

View File

@@ -0,0 +1,9 @@
#include "GpFontHandlerFactory.h"
#include "GpFontHandler_FreeType2.h"
#include <stdlib.h>
PortabilityLayer::HostFontHandler *GpFontHandlerFactory::Create()
{
return GpFontHandler_FreeType2::Create();
}

View File

@@ -0,0 +1,12 @@
#pragma once
namespace PortabilityLayer
{
class HostFontHandler;
}
class GpFontHandlerFactory final
{
public:
static PortabilityLayer::HostFontHandler *Create();
};

View File

@@ -0,0 +1,375 @@
#include "GpFontHandler_FreeType2.h"
#include "CoreDefs.h"
#include "IOStream.h"
#include "HostFont.h"
#include "HostFontRenderedGlyph.h"
#include "RenderedGlyphMetrics.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_MODULE_H
#include <stdint.h>
#include <stdlib.h>
#include <new>
#include <assert.h>
class GpFontRenderedGlyph_FreeType2 final : public PortabilityLayer::HostFontRenderedGlyph
{
public:
const PortabilityLayer::RenderedGlyphMetrics &GetMetrics() const override;
const void *GetData() const override;
void Destroy() override;
static GpFontRenderedGlyph_FreeType2 *Create(size_t dataSize, const PortabilityLayer::RenderedGlyphMetrics &metrics);
void *GetMutableData();
private:
GpFontRenderedGlyph_FreeType2(void *data, const PortabilityLayer::RenderedGlyphMetrics &metrics);
~GpFontRenderedGlyph_FreeType2();
void *m_data;
PortabilityLayer::RenderedGlyphMetrics m_metrics;
};
class GpFont_FreeType2 final : public PortabilityLayer::HostFont
{
public:
void Destroy() override;
GpFontRenderedGlyph_FreeType2 *Render(uint32_t unicodeCodePoint, unsigned int size) override;
bool GetLineSpacing(unsigned int size, int32_t &outSpacing) override;
static GpFont_FreeType2 *Create(const FT_StreamRec_ &streamRec, PortabilityLayer::IOStream *stream);
bool FTLoad(const FT_Library &library);
private:
explicit GpFont_FreeType2(const FT_StreamRec_ &streamRec, PortabilityLayer::IOStream *stream);
~GpFont_FreeType2();
FT_StreamRec_ m_ftStream;
FT_Face m_face;
PortabilityLayer::IOStream *m_stream;
unsigned int m_currentSize;
};
const PortabilityLayer::RenderedGlyphMetrics &GpFontRenderedGlyph_FreeType2::GetMetrics() const
{
return m_metrics;
}
const void *GpFontRenderedGlyph_FreeType2::GetData() const
{
return m_data;
}
void GpFontRenderedGlyph_FreeType2::Destroy()
{
this->~GpFontRenderedGlyph_FreeType2();
free(this);
}
GpFontRenderedGlyph_FreeType2 *GpFontRenderedGlyph_FreeType2::Create(size_t dataSize, const PortabilityLayer::RenderedGlyphMetrics &metrics)
{
size_t alignedPrefixSize = (sizeof(GpFontRenderedGlyph_FreeType2) + GP_SYSTEM_MEMORY_ALIGNMENT - 1);
alignedPrefixSize -= alignedPrefixSize % GP_SYSTEM_MEMORY_ALIGNMENT;
void *storage = malloc(alignedPrefixSize + dataSize);
if (!storage)
return nullptr;
return new (storage) GpFontRenderedGlyph_FreeType2(static_cast<uint8_t*>(storage) + alignedPrefixSize, metrics);
}
void *GpFontRenderedGlyph_FreeType2::GetMutableData()
{
return m_data;
}
GpFontRenderedGlyph_FreeType2::GpFontRenderedGlyph_FreeType2(void *data, const PortabilityLayer::RenderedGlyphMetrics &metrics)
: m_metrics(metrics)
, m_data(data)
{
}
GpFontRenderedGlyph_FreeType2::~GpFontRenderedGlyph_FreeType2()
{
}
void GpFont_FreeType2::Destroy()
{
this->~GpFont_FreeType2();
free(this);
}
GpFontRenderedGlyph_FreeType2 *GpFont_FreeType2::Render(uint32_t unicodeCodePoint, unsigned int size)
{
if (m_currentSize != size)
{
if (FT_Set_Pixel_Sizes(m_face, 0, size) != 0)
return nullptr;
m_currentSize = size;
}
FT_UInt glyphIndex = FT_Get_Char_Index(m_face, unicodeCodePoint);
if (!glyphIndex)
return nullptr;
if (FT_Load_Glyph(m_face, glyphIndex, FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO) != 0)
return nullptr;
if (FT_Render_Glyph(m_face->glyph, FT_RENDER_MODE_MONO) != 0)
return nullptr;
const FT_GlyphSlot glyph = m_face->glyph;
if (glyph->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
return nullptr; // ????
PortabilityLayer::RenderedGlyphMetrics metrics;
memset(&metrics, 0, sizeof(metrics));
metrics.m_bearingX = glyph->metrics.horiBearingX / 64;
metrics.m_bearingY = glyph->metrics.horiBearingY / 64;
metrics.m_glyphWidth = glyph->bitmap.width;
metrics.m_glyphHeight = glyph->bitmap.rows;
metrics.m_advanceX = glyph->metrics.horiAdvance / 64;
const size_t numRowsRequired = glyph->bitmap.rows;
size_t pitchRequired = (glyph->bitmap.width + 7) / 8;
pitchRequired = pitchRequired + (GP_SYSTEM_MEMORY_ALIGNMENT - 1);
pitchRequired -= pitchRequired % GP_SYSTEM_MEMORY_ALIGNMENT;
const size_t glyphDataSize = numRowsRequired * pitchRequired;
metrics.m_glyphDataPitch = pitchRequired;
GpFontRenderedGlyph_FreeType2 *renderedGlyph = GpFontRenderedGlyph_FreeType2::Create(glyphDataSize, metrics);
if (!renderedGlyph)
return nullptr;
uint8_t *fillData = static_cast<uint8_t*>(renderedGlyph->GetMutableData());
unsigned int bmWidth = glyph->bitmap.width;
unsigned int bmHeight = glyph->bitmap.rows;
unsigned int bmPitch = glyph->bitmap.pitch;
unsigned int copyableBytesPerRow = (bmWidth + 7) / 8;
const uint8_t *bmBytes = glyph->bitmap.buffer;
size_t fillOffset = 0;
for (unsigned int row = 0; row < bmHeight; row++)
{
const uint8_t *bmReadStart = bmBytes + bmPitch * row;
uint8_t *bmWriteStart = fillData + pitchRequired * row;
for (unsigned int i = 0; i < copyableBytesPerRow; i++)
{
const uint8_t b = bmReadStart[i];
uint8_t fillByte = 0;
for (int bit = 0; bit < 8; bit++)
fillByte |= ((b >> (7 - bit)) & 1) << bit;
bmWriteStart[i] = fillByte;
}
}
return renderedGlyph;
}
bool GpFont_FreeType2::GetLineSpacing(unsigned int size, int32_t &outSpacing)
{
if (m_currentSize != size)
{
if (FT_Set_Pixel_Sizes(m_face, 0, size) != 0)
return false;
m_currentSize = size;
}
outSpacing = m_face->size->metrics.height / 64;
return true;
}
GpFont_FreeType2 *GpFont_FreeType2::Create(const FT_StreamRec_ &streamRec, PortabilityLayer::IOStream *stream)
{
void *storage = malloc(sizeof(GpFont_FreeType2));
if (!storage)
return nullptr;
return new (storage) GpFont_FreeType2(streamRec, stream);
}
bool GpFont_FreeType2::FTLoad(const FT_Library &library)
{
FT_Open_Args openArgs;
memset(&openArgs, 0, sizeof(openArgs));
openArgs.flags = FT_OPEN_STREAM;
openArgs.stream = &m_ftStream;
FT_Error errorCode = FT_Open_Face(library, &openArgs, 0, &m_face);
if (errorCode != 0)
return false;
return true;
}
GpFont_FreeType2::GpFont_FreeType2(const FT_StreamRec_ &streamRec, PortabilityLayer::IOStream *stream)
: m_face(nullptr)
, m_ftStream(streamRec)
, m_stream(stream)
, m_currentSize(0)
{
assert(stream);
}
GpFont_FreeType2::~GpFont_FreeType2()
{
if (m_face)
FT_Done_Face(m_face);
m_stream->Close();
}
GpFontHandler_FreeType2 *GpFontHandler_FreeType2::Create()
{
void *storage = malloc(sizeof(GpFontHandler_FreeType2));
if (!storage)
return nullptr;
GpFontHandler_FreeType2 *fh = new (storage) GpFontHandler_FreeType2();
if (!fh->Init())
{
fh->Shutdown();
return nullptr;
}
return fh;
}
PortabilityLayer::HostFont *GpFontHandler_FreeType2::LoadFont(PortabilityLayer::IOStream *stream)
{
FT_StreamRec_ ftStream;
memset(&ftStream, 0, sizeof(ftStream));
ftStream.size = 0x7fffffff;
ftStream.pos = 0;
ftStream.descriptor.pointer = stream;
ftStream.read = FTStreamIo;
ftStream.close = FTStreamClose;
GpFont_FreeType2 *font = GpFont_FreeType2::Create(ftStream, stream);
if (!font)
{
stream->Close();
return nullptr;
}
if (!font->FTLoad(m_library))
{
font->Destroy();
return nullptr;
}
return font;
}
bool GpFontHandler_FreeType2::KeepStreamOpen() const
{
return true;
}
void GpFontHandler_FreeType2::Shutdown()
{
this->~GpFontHandler_FreeType2();
free(this);
}
GpFontHandler_FreeType2::GpFontHandler_FreeType2()
: m_ftIsInitialized(false)
, m_library(nullptr)
, m_currentSize(0)
{
}
GpFontHandler_FreeType2::~GpFontHandler_FreeType2()
{
if (m_ftIsInitialized)
FT_Done_Library(m_library);
}
void *GpFontHandler_FreeType2::FTAllocThunk(FT_Memory memory, long size)
{
return static_cast<GpFontHandler_FreeType2*>(memory->user)->FTAlloc(size);
}
void GpFontHandler_FreeType2::FTFreeThunk(FT_Memory memory, void* block)
{
static_cast<GpFontHandler_FreeType2*>(memory->user)->FTFree(block);
}
void *GpFontHandler_FreeType2::FTReallocThunk(FT_Memory memory, long curSize, long newSize, void *block)
{
return static_cast<GpFontHandler_FreeType2*>(memory->user)->FTRealloc(curSize, newSize, block);
}
unsigned long GpFontHandler_FreeType2::FTStreamIo(FT_Stream stream, unsigned long offset, unsigned char* buffer, unsigned long count)
{
PortabilityLayer::IOStream *ioStream = static_cast<PortabilityLayer::IOStream*>(stream->descriptor.pointer);
if (count == 0)
{
if (!ioStream->SeekStart(static_cast<PortabilityLayer::UFilePos_t>(offset)))
return 1;
return 0;
}
const size_t bytesRead = ioStream->Read(buffer, count);
return static_cast<unsigned long>(bytesRead);
}
void GpFontHandler_FreeType2::FTStreamClose(FT_Stream stream)
{
(void)stream;
}
void *GpFontHandler_FreeType2::FTAlloc(long size)
{
return malloc(static_cast<size_t>(size));
}
void GpFontHandler_FreeType2::FTFree(void* block)
{
free(block);
}
void *GpFontHandler_FreeType2::FTRealloc(long curSize, long newSize, void *block)
{
(void)curSize;
return realloc(block, static_cast<size_t>(newSize));
}
bool GpFontHandler_FreeType2::Init()
{
m_mem.user = this;
m_mem.alloc = FTAllocThunk;
m_mem.free = FTFreeThunk;
m_mem.realloc = FTReallocThunk;
if (FT_New_Library(&m_mem, &m_library) != 0)
return false;
m_ftIsInitialized = true;
FT_Add_Default_Modules(m_library);
return true;
}

View File

@@ -0,0 +1,46 @@
#pragma once
#include "HostFontHandler.h"
#include <ft2build.h>
#include FT_SYSTEM_H
#include FT_FREETYPE_H
namespace PortabilityLayer
{
class IOStream;
class HostFont;
}
class GpFontHandler_FreeType2 final : public PortabilityLayer::HostFontHandler
{
public:
PortabilityLayer::HostFont *LoadFont(PortabilityLayer::IOStream *stream) override;
void Shutdown() override;
bool KeepStreamOpen() const override;
static GpFontHandler_FreeType2 *Create();
private:
GpFontHandler_FreeType2();
~GpFontHandler_FreeType2();
static void *FTAllocThunk(FT_Memory memory, long size);
static void FTFreeThunk(FT_Memory memory, void* block);
static void *FTReallocThunk(FT_Memory memory, long curSize, long newSize, void *block);
static unsigned long FTStreamIo(FT_Stream stream, unsigned long offset, unsigned char* buffer, unsigned long count);
static void FTStreamClose(FT_Stream stream);
void *FTAlloc(long size);
void FTFree(void* block);
void *FTRealloc(long curSize, long newSize, void *block);
bool Init();
FT_MemoryRec_ m_mem;
FT_Library m_library;
unsigned int m_currentSize;
bool m_ftIsInitialized;
};

View File

@@ -0,0 +1,3 @@
#include "GpGlobalConfig.h"
GpGlobalConfig g_gpGlobalConfig;

17
Aerofoil/GpGlobalConfig.h Normal file
View File

@@ -0,0 +1,17 @@
#pragma once
#include "EGpDisplayDriverType.h"
#include "EGpAudioDriverType.h"
#include "EGpInputDriverType.h"
struct GpGlobalConfig
{
EGpDisplayDriverType m_displayDriverType;
EGpAudioDriverType m_audioDriverType;
const EGpInputDriverType *m_inputDriverTypes;
size_t m_numInputDrivers;
void *m_osGlobals;
};
extern GpGlobalConfig g_gpGlobalConfig;

View File

@@ -0,0 +1,23 @@
#include "GpInputDriverFactory.h"
#include "GpInputDriverProperties.h"
#include <assert.h>
IGpInputDriver *GpInputDriverFactory::CreateInputDriver(const GpInputDriverProperties &properties)
{
assert(properties.m_type < EGpInputDriverType_Count);
if (ms_registry[properties.m_type])
return ms_registry[properties.m_type](properties);
else
return nullptr;
}
void GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType type, FactoryFunc_t func)
{
assert(type < EGpInputDriverType_Count);
ms_registry[type] = func;
}
GpInputDriverFactory::FactoryFunc_t GpInputDriverFactory::ms_registry[EGpInputDriverType_Count];

View File

@@ -0,0 +1,18 @@
#pragma once
#include "EGpInputDriverType.h"
struct IGpInputDriver;
struct GpInputDriverProperties;
class GpInputDriverFactory
{
public:
typedef IGpInputDriver *(*FactoryFunc_t)(const GpInputDriverProperties &properties);
static IGpInputDriver *CreateInputDriver(const GpInputDriverProperties &properties);
static void RegisterInputDriverFactory(EGpInputDriverType type, FactoryFunc_t func);
private:
static FactoryFunc_t ms_registry[EGpInputDriverType_Count];
};

113
Aerofoil/GpMain.cpp Normal file
View File

@@ -0,0 +1,113 @@
#include "GpMain.h"
#include "GpAudioDriverFactory.h"
#include "GpAudioDriverProperties.h"
#include "GpFontHandlerFactory.h"
#include "GpDisplayDriverFactory.h"
#include "GpDisplayDriverProperties.h"
#include "GpDisplayDriverTickStatus.h"
#include "GpInputDriverFactory.h"
#include "GpInputDriverProperties.h"
#include "GpGlobalConfig.h"
#include "GpAppEnvironment.h"
#include "IGpAudioDriver.h"
#include "IGpDisplayDriver.h"
#include "IGpInputDriver.h"
#include <string.h>
#include <stdlib.h>
namespace
{
GpDisplayDriverTickStatus_t TickAppEnvironment(void *context, IGpFiber *vosFiber)
{
return static_cast<GpAppEnvironment*>(context)->Tick(vosFiber);
}
void RenderAppEnvironment(void *context)
{
static_cast<GpAppEnvironment*>(context)->Render();
}
}
int GpMain::Run()
{
GpVOSEventQueue *eventQueue = new GpVOSEventQueue();
GpAppEnvironment *appEnvironment = new GpAppEnvironment();
GpDisplayDriverProperties ddProps;
memset(&ddProps, 0, sizeof(ddProps));
ddProps.m_frameTimeLockNumerator = 1;
ddProps.m_frameTimeLockDenominator = 60;
// +/- 1% tolerance for frame time variance
ddProps.m_frameTimeLockMinNumerator = 99;
ddProps.m_frameTimeLockMinDenominator = 6000;
ddProps.m_frameTimeLockMaxNumerator = 101;
ddProps.m_frameTimeLockMaxDenominator = 6000;
ddProps.m_tickFunc = TickAppEnvironment;
ddProps.m_tickFuncContext = appEnvironment;
ddProps.m_renderFunc = RenderAppEnvironment;
ddProps.m_renderFuncContext = appEnvironment;
ddProps.m_type = g_gpGlobalConfig.m_displayDriverType;
ddProps.m_osGlobals = g_gpGlobalConfig.m_osGlobals;
ddProps.m_eventQueue = eventQueue;
GpAudioDriverProperties adProps;
memset(&adProps, 0, sizeof(adProps));
// The sample rate used in all of Glider PRO's sound is 0x56ee8ba3
// This appears to be the "standard" Mac sample rate, probably rounded from 244800/11.
adProps.m_type = g_gpGlobalConfig.m_audioDriverType;
adProps.m_sampleRate = (244800 * 2 + 11) / (11 * 2);
adProps.m_debug = true;
IGpInputDriver **inputDrivers = static_cast<IGpInputDriver**>(malloc(sizeof(IGpInputDriver*) * g_gpGlobalConfig.m_numInputDrivers));
size_t numCreatedInputDrivers = 0;
if (inputDrivers)
{
for (size_t i = 0; i < g_gpGlobalConfig.m_numInputDrivers; i++)
{
GpInputDriverProperties inputProps;
memset(&inputProps, 0, sizeof(inputProps));
inputProps.m_type = g_gpGlobalConfig.m_inputDriverTypes[i];
inputProps.m_eventQueue = eventQueue;
if (IGpInputDriver *driver = GpInputDriverFactory::CreateInputDriver(inputProps))
inputDrivers[numCreatedInputDrivers++] = driver;
}
}
IGpDisplayDriver *displayDriver = GpDisplayDriverFactory::CreateDisplayDriver(ddProps);
IGpAudioDriver *audioDriver = GpAudioDriverFactory::CreateAudioDriver(adProps);
PortabilityLayer::HostFontHandler *fontHandler = GpFontHandlerFactory::Create();
appEnvironment->Init();
appEnvironment->SetDisplayDriver(displayDriver);
appEnvironment->SetAudioDriver(audioDriver);
appEnvironment->SetInputDrivers(inputDrivers, numCreatedInputDrivers);
appEnvironment->SetFontHandler(fontHandler);
appEnvironment->SetVOSEventQueue(eventQueue);
// Start the display loop
displayDriver->Run();
// Clean up
if (inputDrivers)
{
for (size_t i = 0; i < numCreatedInputDrivers; i++)
inputDrivers[i]->Shutdown();
free(inputDrivers);
}
// GP TODO: Cleanup
return 0;
}

6
Aerofoil/GpMain.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
namespace GpMain
{
int Run();
}

394
Aerofoil/GpMain_Win32.cpp Normal file
View File

@@ -0,0 +1,394 @@
#include "GpMain.h"
#include "GpAudioDriverFactory.h"
#include "GpColorCursor_Win32.h"
#include "GpDisplayDriverFactory.h"
#include "GpGlobalConfig.h"
#include "GpFiber_Win32.h"
#include "GpFileSystem_Win32.h"
#include "GpInputDriverFactory.h"
#include "GpAppInterface.h"
#include "GpSystemServices_Win32.h"
#include "GpVOSEvent.h"
#include "IGpVOSEventQueue.h"
#include "HostFileSystem.h"
#include "GpWindows.h"
#include <stdio.h>
#include <windowsx.h>
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);
static void PostMouseEvent(IGpVOSEventQueue *eventQueue, GpMouseEventType_t eventType, GpMouseButton_t button, int32_t x, int32_t y)
{
if (GpVOSEvent *evt = eventQueue->QueueEvent())
{
evt->m_eventType = GpVOSEventTypes::kMouseInput;
GpMouseInputEvent &mEvent = evt->m_event.m_mouseInputEvent;
mEvent.m_button = button;
mEvent.m_x = x;
mEvent.m_y = y;
mEvent.m_eventType = eventType;
}
}
static bool IdentifyVKey(const WPARAM &wparam, const LPARAM &lparam, GpKeyIDSubset_t &outSubset, GpKeyboardInputEvent::KeyUnion &outKey)
{
switch (wparam)
{
case VK_ESCAPE:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kEscape;
break;
case VK_PRINT:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kPrintScreen;
break;
case VK_SCROLL:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kScrollLock;
break;
case VK_PAUSE:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kPause;
break;
case VK_INSERT:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kInsert;
break;
case VK_HOME:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kHome;
break;
case VK_PRIOR:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kPageUp;
break;
case VK_NEXT:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kPageDown;
break;
case VK_DELETE:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kDelete;
break;
case VK_TAB:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kTab;
break;
case VK_END:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kEnd;
break;
case VK_BACK:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kBackspace;
break;
case VK_CAPITAL:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kCapsLock;
break;
case VK_RETURN:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kEnter;
break;
case VK_SHIFT:
{
UINT vkey = MapVirtualKeyW((lparam >> 16) & 0xff, MAPVK_VSC_TO_VK_EX);
if (vkey == VK_LSHIFT || vkey == VK_SHIFT)
{
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kLeftShift;
}
else if (vkey == VK_RSHIFT)
{
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kRightShift;
}
else
return false;
}
break;
case VK_RSHIFT:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kRightShift;
break;
case VK_CONTROL:
outSubset = GpKeyIDSubsets::kSpecial;
if (lparam & 0x01000000)
outKey.m_specialKey = GpKeySpecials::kRightCtrl;
else
outKey.m_specialKey = GpKeySpecials::kLeftCtrl;
break;
case VK_MENU:
outSubset = GpKeyIDSubsets::kSpecial;
if (lparam & 0x01000000)
outKey.m_specialKey = GpKeySpecials::kRightAlt;
else
outKey.m_specialKey = GpKeySpecials::kLeftAlt;
break;
case VK_NUMLOCK:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kNumLock;
break;
case VK_NUMPAD0:
case VK_NUMPAD1:
case VK_NUMPAD2:
case VK_NUMPAD3:
case VK_NUMPAD4:
case VK_NUMPAD5:
case VK_NUMPAD6:
case VK_NUMPAD7:
case VK_NUMPAD8:
case VK_NUMPAD9:
outSubset = GpKeyIDSubsets::kNumPadNumber;
outKey.m_numPadNumber = static_cast<uint8_t>(wparam - VK_NUMPAD0);
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
outSubset = GpKeyIDSubsets::kASCII;
outKey.m_asciiChar = static_cast<char>(wparam);
break;
case VK_F1:
case VK_F2:
case VK_F3:
case VK_F4:
case VK_F5:
case VK_F6:
case VK_F7:
case VK_F8:
case VK_F9:
case VK_F10:
case VK_F11:
case VK_F12:
case VK_F13:
case VK_F14:
case VK_F15:
case VK_F16:
case VK_F17:
case VK_F18:
case VK_F19:
case VK_F20:
case VK_F21:
case VK_F22:
case VK_F23:
case VK_F24:
outSubset = GpKeyIDSubsets::kFKey;
outKey.m_fKey = static_cast<uint8_t>(wparam - VK_F1 + 1);
break;
case VK_OEM_COMMA:
outSubset = GpKeyIDSubsets::kASCII;
outKey.m_asciiChar = ',';
break;
case VK_OEM_MINUS:
outSubset = GpKeyIDSubsets::kASCII;
outKey.m_asciiChar = '-';
break;
case VK_OEM_PERIOD:
outSubset = GpKeyIDSubsets::kASCII;
outKey.m_asciiChar = '.';
break;
case VK_OEM_PLUS:
outSubset = GpKeyIDSubsets::kASCII;
outKey.m_asciiChar = '+';
break;
case VK_UP:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kUpArrow;
break;
case VK_DOWN:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kDownArrow;
break;
case VK_LEFT:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kLeftArrow;
break;
case VK_RIGHT:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kRightArrow;
break;
default:
{
if (wparam >= VK_OEM_1 && wparam <= VK_OEM_102)
{
UINT charCode = MapVirtualKeyW(static_cast<UINT>(wparam), MAPVK_VK_TO_CHAR);
if (charCode == 0)
return false;
if (charCode < 128)
{
outSubset = GpKeyIDSubsets::kASCII;
outKey.m_asciiChar = static_cast<char>(charCode);
break;
}
else
{
outSubset = GpKeyIDSubsets::kUnicode;
outKey.m_unicodeChar = charCode;;
break;
}
}
}
return false;
}
return true;
}
static void PostKeyboardEvent(IGpVOSEventQueue *eventQueue, GpKeyboardInputEventType_t eventType, GpKeyIDSubset_t subset, const GpKeyboardInputEvent::KeyUnion &key)
{
if (GpVOSEvent *evt = eventQueue->QueueEvent())
{
evt->m_eventType = GpVOSEventTypes::kKeyboardInput;
GpKeyboardInputEvent &mEvent = evt->m_event.m_keyboardInputEvent;
mEvent.m_key = key;
mEvent.m_eventType = eventType;
mEvent.m_keyIDSubset = subset;
}
}
static void TranslateWindowsMessage(const MSG *msg, IGpVOSEventQueue *eventQueue)
{
WPARAM wParam = msg->wParam;
LPARAM lParam = msg->lParam;
switch (msg->message)
{
case WM_LBUTTONDOWN:
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kLeft, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_LBUTTONUP:
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kLeft, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_MBUTTONDOWN:
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kMiddle, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_MBUTTONUP:
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kMiddle, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_RBUTTONDOWN:
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kRight, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_RBUTTONUP:
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kRight, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_XBUTTONDOWN:
if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1)
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kX1, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
else if (GET_XBUTTON_WPARAM(wParam) == XBUTTON2)
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kX2, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_XBUTTONUP:
if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1)
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kX1, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
else if (GET_XBUTTON_WPARAM(wParam) == XBUTTON2)
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kX2, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_MOUSEMOVE:
PostMouseEvent(eventQueue, GpMouseEventTypes::kMove, GpMouseButtons::kNone, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_MOUSELEAVE:
PostMouseEvent(eventQueue, GpMouseEventTypes::kLeave, GpMouseButtons::kNone, 0, 0);
break;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
{
GpKeyIDSubset_t subset;
GpKeyboardInputEvent::KeyUnion key;
if (IdentifyVKey(wParam, lParam, subset, key))
PostKeyboardEvent(eventQueue, GpKeyboardInputEventTypes::kDown, subset, key);
}
break;
case WM_KEYUP:
case WM_SYSKEYUP:
{
GpKeyIDSubset_t subset;
GpKeyboardInputEvent::KeyUnion key;
if (IdentifyVKey(wParam, lParam, subset, key))
PostKeyboardEvent(eventQueue, GpKeyboardInputEventTypes::kUp, subset, key);
}
break;
case WM_CHAR:
break;
default:
break;
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
GpAppInterface_Get()->PL_HostFileSystem_SetInstance(GpFileSystem_Win32::GetInstance());
GpAppInterface_Get()->PL_HostSystemServices_SetInstance(GpSystemServices_Win32::GetInstance());
g_gpWindowsGlobals.m_hInstance = hInstance;
g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance;
g_gpWindowsGlobals.m_cmdLine = lpCmdLine;
g_gpWindowsGlobals.m_nCmdShow = nCmdShow;
g_gpWindowsGlobals.m_baseDir = GpFileSystem_Win32::GetInstance()->GetBasePath();
g_gpWindowsGlobals.m_createFiberFunc = GpFiber_Win32::Create;
g_gpWindowsGlobals.m_loadColorCursorFunc = GpColorCursor_Win32::Load;
g_gpWindowsGlobals.m_translateWindowsMessageFunc = TranslateWindowsMessage;
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_D3D11;
g_gpGlobalConfig.m_audioDriverType = EGpAudioDriverType_XAudio2;
EGpInputDriverType inputDrivers[] =
{
EGpInputDriverType_XInput
};
g_gpGlobalConfig.m_inputDriverTypes = inputDrivers;
g_gpGlobalConfig.m_numInputDrivers = sizeof(inputDrivers) / sizeof(inputDrivers[0]);
g_gpGlobalConfig.m_osGlobals = &g_gpWindowsGlobals;
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_D3D11, GpDriver_CreateDisplayDriver_D3D11);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_XAudio2, GpDriver_CreateAudioDriver_XAudio2);
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_XInput, GpDriver_CreateInputDriver_XInput);
return GpMain::Run();
}

View File

@@ -0,0 +1,49 @@
#include "GpMemoryBuffer.h"
#include <new>
void *GpMemoryBuffer::Contents()
{
return reinterpret_cast<uint8_t*>(this) + AlignedSize();
}
size_t GpMemoryBuffer::Size()
{
return m_size;
}
void GpMemoryBuffer::Destroy()
{
delete[] reinterpret_cast<uint8_t*>(this);
}
GpMemoryBuffer *GpMemoryBuffer::Create(size_t sz)
{
const size_t allowedSize = SIZE_MAX - AlignedSize();
if (sz > allowedSize)
return nullptr;
const size_t bufferSize = GpMemoryBuffer::AlignedSize() + sz;
uint8_t *buffer = new uint8_t[bufferSize];
new (buffer) GpMemoryBuffer(sz);
return reinterpret_cast<GpMemoryBuffer*>(buffer);
}
GpMemoryBuffer::GpMemoryBuffer(size_t sz)
: m_size(sz)
{
}
GpMemoryBuffer::~GpMemoryBuffer()
{
}
size_t GpMemoryBuffer::AlignedSize()
{
const size_t paddedSize = (sizeof(GpMemoryBuffer) + GP_SYSTEM_MEMORY_ALIGNMENT - 1);
const size_t sz = paddedSize - paddedSize % GP_SYSTEM_MEMORY_ALIGNMENT;
return sz;
}

21
Aerofoil/GpMemoryBuffer.h Normal file
View File

@@ -0,0 +1,21 @@
#pragma once
#include "HostMemoryBuffer.h"
class GpMemoryBuffer final : public PortabilityLayer::HostMemoryBuffer
{
public:
void *Contents() override;
size_t Size() override;
void Destroy() override;
static GpMemoryBuffer *Create(size_t sz);
private:
explicit GpMemoryBuffer(size_t sz);
~GpMemoryBuffer();
static size_t AlignedSize();
size_t m_size;
};

View File

@@ -0,0 +1,42 @@
#include "GpMutex_Win32.h"
#include "GpWindows.h"
#include <stdlib.h>
#include <new>
void GpMutex_Win32::Destroy()
{
this->~GpMutex_Win32();
free(this);
}
void GpMutex_Win32::Lock()
{
EnterCriticalSection(&m_critSection);
}
void GpMutex_Win32::Unlock()
{
LeaveCriticalSection(&m_critSection);
}
GpMutex_Win32 *GpMutex_Win32::Create()
{
void *storage = malloc(sizeof(GpMutex_Win32));
if (!storage)
return nullptr;
return new (storage) GpMutex_Win32();
}
GpMutex_Win32::GpMutex_Win32()
{
InitializeCriticalSection(&m_critSection);
}
GpMutex_Win32::~GpMutex_Win32()
{
DeleteCriticalSection(&m_critSection);
}

21
Aerofoil/GpMutex_Win32.h Normal file
View File

@@ -0,0 +1,21 @@
#pragma once
#include "HostMutex.h"
#include "GpWindows.h"
class GpMutex_Win32 final : public PortabilityLayer::HostMutex
{
public:
void Destroy() override;
void Lock() override;
void Unlock() override;
static GpMutex_Win32 *Create();
private:
const GpMutex_Win32();
~GpMutex_Win32();
CRITICAL_SECTION m_critSection;
};

View File

@@ -0,0 +1,54 @@
#include "GpPLGlueAudioChannel.h"
#include "ClientAudioChannelContext.h"
#include "IGpAudioChannel.h"
#include <stdlib.h>
#include <new>
void GpPLGlueAudioChannel::SetClientAudioChannelContext(PortabilityLayer::ClientAudioChannelContext *context)
{
m_clientContext = context;
m_audioChannel->SetAudioChannelContext(this);
}
void GpPLGlueAudioChannel::PostBuffer(const void *buffer, size_t bufferSize)
{
m_audioChannel->PostBuffer(buffer, bufferSize);
}
void GpPLGlueAudioChannel::Stop()
{
m_audioChannel->Stop();
}
void GpPLGlueAudioChannel::Destroy()
{
this->~GpPLGlueAudioChannel();
free(this);
}
void GpPLGlueAudioChannel::NotifyBufferFinished()
{
if (m_clientContext)
m_clientContext->NotifyBufferFinished();
}
GpPLGlueAudioChannel *GpPLGlueAudioChannel::Create(IGpAudioChannel *audioChannel)
{
void *storage = malloc(sizeof(GpPLGlueAudioChannel));
if (!storage)
return nullptr;
return new (storage) GpPLGlueAudioChannel(audioChannel);
}
GpPLGlueAudioChannel::GpPLGlueAudioChannel(IGpAudioChannel *audioChannel)
: m_audioChannel(audioChannel)
, m_clientContext(nullptr)
{
}
GpPLGlueAudioChannel::~GpPLGlueAudioChannel()
{
m_audioChannel->Destroy();
}

View File

@@ -0,0 +1,26 @@
#pragma once
#include "HostAudioChannel.h"
#include "IGpAudioChannelCallbacks.h"
struct IGpAudioChannel;
class GpPLGlueAudioChannel final : public PortabilityLayer::HostAudioChannel, public IGpAudioChannelCallbacks
{
public:
void SetClientAudioChannelContext(PortabilityLayer::ClientAudioChannelContext *context) override;
void PostBuffer(const void *buffer, size_t bufferSize) override;
void Stop() override;
void Destroy() override;
void NotifyBufferFinished() override;
static GpPLGlueAudioChannel *Create(IGpAudioChannel *audioChannel);
private:
explicit GpPLGlueAudioChannel(IGpAudioChannel *audioChannel);
~GpPLGlueAudioChannel();
PortabilityLayer::ClientAudioChannelContext *m_clientContext;
IGpAudioChannel *m_audioChannel;
};

View File

@@ -0,0 +1,38 @@
#include "GpPLGlueAudioDriver.h"
#include "GpPLGlueAudioChannel.h"
#include "IGpAudioChannel.h"
#include "IGpAudioDriver.h"
GpPLGlueAudioDriver::GpPLGlueAudioDriver()
: m_audioDriver(nullptr)
{
}
PortabilityLayer::HostAudioChannel *GpPLGlueAudioDriver::CreateChannel()
{
IGpAudioChannel *channel = m_audioDriver->CreateChannel();
if (!channel)
return nullptr;
PortabilityLayer::HostAudioChannel *glueChannel = GpPLGlueAudioChannel::Create(channel);
if (!glueChannel)
{
channel->Destroy();
return nullptr;
}
return glueChannel;
}
GpPLGlueAudioDriver *GpPLGlueAudioDriver::GetInstance()
{
return &ms_instance;
}
void GpPLGlueAudioDriver::SetGpAudioDriver(IGpAudioDriver *audioDriver)
{
m_audioDriver = audioDriver;
}
GpPLGlueAudioDriver GpPLGlueAudioDriver::ms_instance;

View File

@@ -0,0 +1,22 @@
#pragma once
#include "HostAudioDriver.h"
struct IGpAudioDriver;
class GpPLGlueAudioDriver final : public PortabilityLayer::HostAudioDriver
{
public:
GpPLGlueAudioDriver();
PortabilityLayer::HostAudioChannel *CreateChannel() override;
void SetGpAudioDriver(IGpAudioDriver *audioDriver);
static GpPLGlueAudioDriver *GetInstance();
private:
IGpAudioDriver *m_audioDriver;
static GpPLGlueAudioDriver ms_instance;
};

View File

@@ -0,0 +1,40 @@
#include "GpPLGlueDisplayDriver.h"
#include "VirtualDirectory.h"
#include "IGpDisplayDriver.h"
GpPLGlueDisplayDriver::GpPLGlueDisplayDriver()
: m_displayDriver(nullptr)
{
}
void GpPLGlueDisplayDriver::GetDisplayResolution(unsigned int *width, unsigned int *height, GpPixelFormat_t *bpp)
{
m_displayDriver->GetDisplayResolution(width, height, bpp);
}
IGpColorCursor *GpPLGlueDisplayDriver::LoadColorCursor(int cursorID)
{
return m_displayDriver->LoadColorCursor(cursorID);
}
void GpPLGlueDisplayDriver::SetColorCursor(IGpColorCursor *colorCursor)
{
m_displayDriver->SetColorCursor(colorCursor);
}
void GpPLGlueDisplayDriver::SetStandardCursor(EGpStandardCursor_t standardCursor)
{
m_displayDriver->SetStandardCursor(standardCursor);
}
GpPLGlueDisplayDriver *GpPLGlueDisplayDriver::GetInstance()
{
return &ms_instance;
}
void GpPLGlueDisplayDriver::SetGpDisplayDriver(IGpDisplayDriver *displayDriver)
{
m_displayDriver = displayDriver;
}
GpPLGlueDisplayDriver GpPLGlueDisplayDriver::ms_instance;

View File

@@ -0,0 +1,25 @@
#pragma once
#include "HostDisplayDriver.h"
struct IGpDisplayDriver;
class GpPLGlueDisplayDriver final : public PortabilityLayer::HostDisplayDriver
{
public:
GpPLGlueDisplayDriver();
void GetDisplayResolution(unsigned int *width, unsigned int *height, GpPixelFormat_t *bpp) override;
IGpColorCursor *LoadColorCursor(int id) override;
void SetColorCursor(IGpColorCursor *colorCursor) override;
void SetStandardCursor(EGpStandardCursor_t standardCursor) override;
void SetGpDisplayDriver(IGpDisplayDriver *displayDriver);
static GpPLGlueDisplayDriver *GetInstance();
private:
IGpDisplayDriver *m_displayDriver;
static GpPLGlueDisplayDriver ms_instance;
};

View File

@@ -0,0 +1,85 @@
#include "GpSystemServices_Win32.h"
#include "GpMutex_Win32.h"
#include "GpThreadEvent_Win32.h"
#include <assert.h>
#pragma push_macro("CreateMutex")
#ifdef CreateMutex
#undef CreateMutex
#endif
GpSystemServices_Win32::GpSystemServices_Win32()
{
}
int64_t GpSystemServices_Win32::GetTime() const
{
SYSTEMTIME epochStart;
epochStart.wYear = 1904;
epochStart.wMonth = 1;
epochStart.wDayOfWeek = 5;
epochStart.wDay = 1;
epochStart.wHour = 0;
epochStart.wMinute = 0;
epochStart.wSecond = 0;
epochStart.wMilliseconds = 0;
FILETIME epochStartFT;
if (!SystemTimeToFileTime(&epochStart, &epochStartFT))
return 0;
FILETIME currentTime;
GetSystemTimeAsFileTime(&currentTime);
int64_t epochStart64 = (static_cast<int64_t>(epochStartFT.dwLowDateTime) & 0xffffffff) | (static_cast<int64_t>(epochStartFT.dwHighDateTime) << 32);
int64_t currentTime64 = (static_cast<int64_t>(currentTime.dwLowDateTime) & 0xffffffff) | (static_cast<int64_t>(currentTime.dwHighDateTime) << 32);
return currentTime64 - epochStart64;
}
void GpSystemServices_Win32::GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const
{
SYSTEMTIME localTime;
GetLocalTime(&localTime);
year = localTime.wYear;
month = localTime.wMonth;
day = localTime.wDay;
hour = localTime.wHour;
minute = localTime.wMinute;
second = localTime.wSecond;
}
PortabilityLayer::HostMutex *GpSystemServices_Win32::CreateMutex()
{
return GpMutex_Win32::Create();
}
PortabilityLayer::HostThreadEvent *GpSystemServices_Win32::CreateThreadEvent(bool autoReset, bool startSignaled)
{
return GpThreadEvent_Win32::Create(autoReset, startSignaled);
}
uint64_t GpSystemServices_Win32::GetFreeMemoryCosmetic() const
{
MEMORYSTATUSEX memStatus;
memset(&memStatus, 0, sizeof(memStatus));
memStatus.dwLength = sizeof(memStatus);
if (!GlobalMemoryStatusEx(&memStatus))
return 0;
return memStatus.ullAvailPhys;
}
GpSystemServices_Win32 *GpSystemServices_Win32::GetInstance()
{
return &ms_instance;
}
GpSystemServices_Win32 GpSystemServices_Win32::ms_instance;
#pragma pop_macro("CreateMutex")

View File

@@ -0,0 +1,30 @@
#pragma once
#include "HostSystemServices.h"
#include "GpCoreDefs.h"
#include "GpWindows.h"
#pragma push_macro("CreateMutex")
#ifdef CreateMutex
#undef CreateMutex
#endif
class GpSystemServices_Win32 final : public PortabilityLayer::HostSystemServices
{
public:
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;
PortabilityLayer::HostMutex *CreateMutex() override;
PortabilityLayer::HostThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) override;
uint64_t GetFreeMemoryCosmetic() const override;
static GpSystemServices_Win32 *GetInstance();
private:
static GpSystemServices_Win32 ms_instance;
};
#pragma pop_macro("CreateMutex")

View File

@@ -0,0 +1,51 @@
#include "GpThreadEvent_Win32.h"
#include <stdlib.h>
#include <new>
void GpThreadEvent_Win32::Wait()
{
WaitForSingleObject(m_event, INFINITE);
}
void GpThreadEvent_Win32::WaitTimed(uint32_t msec)
{
WaitForSingleObject(m_event, static_cast<DWORD>(msec));
}
void GpThreadEvent_Win32::Signal()
{
SetEvent(m_event);
}
void GpThreadEvent_Win32::Destroy()
{
this->~GpThreadEvent_Win32();
free(this);
}
GpThreadEvent_Win32 *GpThreadEvent_Win32::Create(bool autoReset, bool startSignaled)
{
HANDLE handle = CreateEventA(nullptr, autoReset ? FALSE : TRUE, startSignaled ? TRUE : FALSE, nullptr);
if (handle == nullptr)
return nullptr;
void *storage = malloc(sizeof(GpThreadEvent_Win32));
if (!storage)
{
CloseHandle(handle);
return nullptr;
}
return new (storage) GpThreadEvent_Win32(handle);
}
GpThreadEvent_Win32::GpThreadEvent_Win32(const HANDLE &handle)
: m_event(handle)
{
}
GpThreadEvent_Win32::~GpThreadEvent_Win32()
{
CloseHandle(m_event);
}

View File

@@ -0,0 +1,22 @@
#pragma once
#include "HostThreadEvent.h"
#include "GpWindows.h"
class GpThreadEvent_Win32 final : public PortabilityLayer::HostThreadEvent
{
public:
void Wait() override;
void WaitTimed(uint32_t msec) override;
void Signal() override;
void Destroy() override;
static GpThreadEvent_Win32 *Create(bool autoReset, bool startSignaled);
private:
explicit GpThreadEvent_Win32(const HANDLE &handle);
~GpThreadEvent_Win32();
HANDLE m_event;
};

View File

@@ -0,0 +1,45 @@
#include "GpVOSEventQueue.h"
#include <assert.h>
GpVOSEventQueue::GpVOSEventQueue()
: m_firstEvent(0)
, m_numEventsQueued(0)
{
}
GpVOSEventQueue::~GpVOSEventQueue()
{
}
const GpVOSEvent *GpVOSEventQueue::GetNext()
{
if (m_numEventsQueued)
return m_events + m_firstEvent;
return nullptr;
}
void GpVOSEventQueue::DischargeOne()
{
assert(m_numEventsQueued > 0);
m_numEventsQueued--;
m_firstEvent++;
if (m_firstEvent == kMaxEvents)
m_firstEvent = 0;
}
GpVOSEvent *GpVOSEventQueue::QueueEvent()
{
if (m_numEventsQueued == kMaxEvents)
return nullptr;
size_t nextEvent = m_firstEvent + m_numEventsQueued;
if (nextEvent >= kMaxEvents)
nextEvent -= kMaxEvents;
m_numEventsQueued++;
return m_events + nextEvent;
}

View File

@@ -0,0 +1,25 @@
#pragma once
#include <stdint.h>
#include "HostVOSEventQueue.h"
#include "GpVOSEvent.h"
class GpVOSEventQueue final : public PortabilityLayer::HostVOSEventQueue
{
public:
GpVOSEventQueue();
~GpVOSEventQueue();
const GpVOSEvent *GetNext() override;
void DischargeOne() override;
GpVOSEvent *QueueEvent() override;
private:
static const size_t kMaxEvents = 10000;
GpVOSEvent m_events[kMaxEvents];
size_t m_firstEvent;
size_t m_numEventsQueued;
};

17
Aerofoil/resource.h Normal file
View File

@@ -0,0 +1,17 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by GpD3D.rc
//
#define IDI_ICON1 101
#define IDI_ICON2 102
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif