Rename projects to Aerofoil
217
Aerofoil/Aerofoil.filters
Normal 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
237
Aerofoil/Aerofoil.vcxproj
Normal 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>
|
||||
BIN
Aerofoil/ConvertedResources/Large128.ico
Normal file
|
After Width: | Height: | Size: 597 B |
BIN
Aerofoil/ConvertedResources/Large129.ico
Normal file
|
After Width: | Height: | Size: 721 B |
BIN
Aerofoil/ConvertedResources/Large130.ico
Normal file
|
After Width: | Height: | Size: 670 B |
BIN
Aerofoil/ConvertedResources/Large131.ico
Normal file
|
After Width: | Height: | Size: 765 B |
BIN
Aerofoil/ConvertedResources/Large132.ico
Normal file
|
After Width: | Height: | Size: 826 B |
BIN
Aerofoil/ConvertedResources/Large133.ico
Normal file
|
After Width: | Height: | Size: 339 B |
BIN
Aerofoil/ConvertedResources/Small128.ico
Normal file
|
After Width: | Height: | Size: 342 B |
BIN
Aerofoil/ConvertedResources/Small129.ico
Normal file
|
After Width: | Height: | Size: 345 B |
BIN
Aerofoil/ConvertedResources/Small130.ico
Normal file
|
After Width: | Height: | Size: 356 B |
BIN
Aerofoil/ConvertedResources/Small133.ico
Normal file
|
After Width: | Height: | Size: 205 B |
181
Aerofoil/GpAppEnvironment.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
72
Aerofoil/GpAppEnvironment.h
Normal 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;
|
||||
};
|
||||
23
Aerofoil/GpAudioDriverFactory.cpp
Normal 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];
|
||||
18
Aerofoil/GpAudioDriverFactory.h
Normal 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];
|
||||
};
|
||||
58
Aerofoil/GpColorCursor_Win32.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
33
Aerofoil/GpColorCursor_Win32.h
Normal 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;
|
||||
};
|
||||
23
Aerofoil/GpDisplayDriverFactory.cpp
Normal 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];
|
||||
18
Aerofoil/GpDisplayDriverFactory.h
Normal 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
@@ -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);
|
||||
};
|
||||
52
Aerofoil/GpFiberStarter_Win32.cpp
Normal 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);
|
||||
}
|
||||
32
Aerofoil/GpFiber_Win32.cpp
Normal 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
@@ -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;
|
||||
};
|
||||
141
Aerofoil/GpFileStream_Win32.cpp
Normal 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);
|
||||
}
|
||||
30
Aerofoil/GpFileStream_Win32.h
Normal 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;
|
||||
};
|
||||
454
Aerofoil/GpFileSystem_Win32.cpp
Normal 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;
|
||||
41
Aerofoil/GpFileSystem_Win32.h
Normal 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;
|
||||
};
|
||||
9
Aerofoil/GpFontHandlerFactory.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "GpFontHandlerFactory.h"
|
||||
#include "GpFontHandler_FreeType2.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
PortabilityLayer::HostFontHandler *GpFontHandlerFactory::Create()
|
||||
{
|
||||
return GpFontHandler_FreeType2::Create();
|
||||
}
|
||||
12
Aerofoil/GpFontHandlerFactory.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
class HostFontHandler;
|
||||
}
|
||||
|
||||
class GpFontHandlerFactory final
|
||||
{
|
||||
public:
|
||||
static PortabilityLayer::HostFontHandler *Create();
|
||||
};
|
||||
375
Aerofoil/GpFontHandler_FreeType2.cpp
Normal 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;
|
||||
}
|
||||
46
Aerofoil/GpFontHandler_FreeType2.h
Normal 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;
|
||||
};
|
||||
3
Aerofoil/GpGlobalConfig.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#include "GpGlobalConfig.h"
|
||||
|
||||
GpGlobalConfig g_gpGlobalConfig;
|
||||
17
Aerofoil/GpGlobalConfig.h
Normal 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;
|
||||
23
Aerofoil/GpInputDriverFactory.cpp
Normal 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];
|
||||
18
Aerofoil/GpInputDriverFactory.h
Normal 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
@@ -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
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace GpMain
|
||||
{
|
||||
int Run();
|
||||
}
|
||||
394
Aerofoil/GpMain_Win32.cpp
Normal 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();
|
||||
}
|
||||
49
Aerofoil/GpMemoryBuffer.cpp
Normal 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
@@ -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;
|
||||
};
|
||||
42
Aerofoil/GpMutex_Win32.cpp
Normal 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
@@ -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;
|
||||
};
|
||||
54
Aerofoil/GpPLGlueAudioChannel.cpp
Normal 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();
|
||||
}
|
||||
26
Aerofoil/GpPLGlueAudioChannel.h
Normal 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;
|
||||
};
|
||||
38
Aerofoil/GpPLGlueAudioDriver.cpp
Normal 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;
|
||||
22
Aerofoil/GpPLGlueAudioDriver.h
Normal 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;
|
||||
};
|
||||
40
Aerofoil/GpPLGlueDisplayDriver.cpp
Normal 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;
|
||||
25
Aerofoil/GpPLGlueDisplayDriver.h
Normal 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;
|
||||
};
|
||||
85
Aerofoil/GpSystemServices_Win32.cpp
Normal 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(¤tTime);
|
||||
|
||||
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")
|
||||
30
Aerofoil/GpSystemServices_Win32.h
Normal 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")
|
||||
51
Aerofoil/GpThreadEvent_Win32.cpp
Normal 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);
|
||||
}
|
||||
22
Aerofoil/GpThreadEvent_Win32.h
Normal 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;
|
||||
};
|
||||
45
Aerofoil/GpVOSEventQueue.cpp
Normal 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;
|
||||
}
|
||||
25
Aerofoil/GpVOSEventQueue.h
Normal 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
@@ -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
|
||||