Add mouse cursor handling

This commit is contained in:
elasota
2019-12-22 00:35:30 -05:00
parent 8354d13a84
commit eed82e2960
32 changed files with 835 additions and 72 deletions

View File

@@ -0,0 +1,252 @@
#include "CFileStream.h"
#include "MMHandleBlock.h"
#include "ResourceCompiledTypeList.h"
#include "ResourceFile.h"
#include "SharedTypes.h"
#include "PLBigEndian.h"
#include <assert.h>
#include <string>
#include "stb_image_write.h"
// This extracts all of the color cursors from a resource file and converts them to
// Windows cursor format.
//
// Windows only supports loading color cursors by loading them from an executable or DLL resource,
// or by loading them from a file, so we can't just do the conversion/construction at runtime.
//
// Also, classic Mac cursor features are not fully supported by newer operating systems.
// The classic Mac cursor function is basically (existing ^ color) where the mask bit isn't set,
// so it supports inversion masking and colors with the same cursor.
//
// Fortunately, none of the Glider PRO cursors use this combination.
//
// The color cursor format is not fully documented. Appears to be:
// Header
// CursorPixMapPrefix (at pixMapOffset)
// BEPixMap
// Pixel data
// BEColorTableHeader
// BEColorTableItem[...]
struct CursorPixMapPrefix
{
BEUInt32_t m_unknown; // Seems to always be zero
BEUInt16_t m_subFormat; // 0x8002 = 2 colors, 0x8004 = 4 colors, 0x8008 = 16 colors, 0x8010 = 256 colors
};
struct CursorHeader
{
BEUInt16_t m_cursorType;
BEUInt32_t m_pixMapOffset;
BEUInt32_t m_pixDataOffset;
BEUInt32_t m_expandedData;
BEUInt16_t m_expandedDataDepth;
BEUInt32_t m_unused;
uint8_t m_bwCursor[32];
uint8_t m_mask[32];
BEUInt16_t m_hotSpotY;
BEUInt16_t m_hotSpotX;
BEUInt32_t m_colorTableResourceID;
BEUInt32_t m_cursorResourceID;
};
struct IconDir
{
uint16_t m_reserved;
uint16_t m_type;
uint16_t m_numImages;
};
struct IconDirEntry
{
uint8_t m_width;
uint8_t m_height;
uint8_t m_numColors;
uint8_t m_reserved;
uint16_t m_numPlanes_HotSpotX;
uint16_t m_bpp_HotSpotY;
uint32_t m_imageDataSize;
uint32_t m_imageDataOffset;
};
uint8_t CompactChannel(const uint8_t *doublet)
{
unsigned int doubletValue = (doublet[0] << 8) + doublet[1];
return (doubletValue * 2 + 0x101) / 0x202;
}
void WriteToFileCallback(void *context, void *data, int size)
{
fwrite(data, 1, size, static_cast<FILE*>(context));
}
int main(int argc, const char **argv)
{
FILE *f = nullptr;
errno_t err = fopen_s(&f, "Packaged\\ApplicationResources.gpr", "rb");
if (err)
return err;
PortabilityLayer::CFileStream stream(f);
PortabilityLayer::ResourceFile *resFile = new PortabilityLayer::ResourceFile();
if (!resFile->Load(&stream))
return -1;
stream.Close();
const PortabilityLayer::ResourceCompiledTypeList *typeList = resFile->GetResourceTypeList('crsr');
if (!typeList)
return -1;
const size_t numRefs = typeList->m_numRefs;
for (size_t i = 0; i < numRefs; i++)
{
const int resID = typeList->m_firstRef[i].m_resID;
const PortabilityLayer::MMHandleBlock *hBlock = resFile->GetResource('crsr', resID, true);
const void *cursorDataBase = hBlock->m_contents;
const void *cursorData = cursorDataBase;
const CursorHeader *cursorHeader = static_cast<const CursorHeader *>(cursorData);
cursorData = cursorHeader + 1;
cursorData = static_cast<const void*>(reinterpret_cast<const uint8_t*>(cursorDataBase) + cursorHeader->m_pixMapOffset);
const CursorPixMapPrefix *cursorPixMapPrefix = static_cast<const CursorPixMapPrefix *>(cursorData);
cursorData = cursorPixMapPrefix + 1;
const BEPixMap *pixMap = reinterpret_cast<const BEPixMap*>(reinterpret_cast<const uint8_t*>(cursorData));
cursorData = pixMap + 1;
cursorData = static_cast<const void*>(reinterpret_cast<const uint8_t*>(cursorDataBase) + cursorHeader->m_pixDataOffset);
const uint8_t *pixMapDataBytes = static_cast<const uint8_t*>(cursorData);
const Rect rect = pixMap->m_bounds.ToRect();
const int width = rect.right - rect.left;
const int height = rect.bottom - rect.top;
const int componentSize = static_cast<int>(pixMap->m_componentSize);
switch (componentSize)
{
case 1:
case 2:
case 4:
case 8:
break;
default:
assert(false);
break;
}
const int bitsRequired = width * height * componentSize;
const int bytesRequired = (bitsRequired + 7) / 8;
uint8_t *colorValues = new uint8_t[width * height];
const int numPixels = width * height;
switch (componentSize)
{
case 1:
for (int i = 0; i < numPixels; i++)
colorValues[i] = (pixMapDataBytes[i / 8] >> (7 - (i & 7) * 1)) & 0x1;
break;
case 2:
for (int i = 0; i < numPixels; i++)
colorValues[i] = (pixMapDataBytes[i / 4] >> (6 - (i & 3) * 2)) & 0x3;
break;
case 4:
for (int i = 0; i < numPixels; i++)
colorValues[i] = (pixMapDataBytes[i / 2] >> (4 - (i & 1) * 4)) & 0xf;
break;
case 8:
for (int i = 0; i < numPixels; i++)
colorValues[i] = pixMapDataBytes[i];
break;
default:
assert(false);
break;
}
cursorData = static_cast<const void*>(pixMapDataBytes + bytesRequired);
const BEColorTableHeader *colorTableHeader = static_cast<const BEColorTableHeader *>(cursorData);
cursorData = colorTableHeader + 1;
const BEColorTableItem *ctabItems = static_cast<const BEColorTableItem *>(cursorData);
uint32_t decodedCTabItems[256];
const int numCTabItems = colorTableHeader->m_numItemsMinusOne + 1;
for (int i = 0; i < numCTabItems; i++)
{
const BEColorTableItem &item = ctabItems[i];
unsigned char rgba[4];
rgba[0] = CompactChannel(item.m_red);
rgba[1] = CompactChannel(item.m_green);
rgba[2] = CompactChannel(item.m_blue);
rgba[3] = 255;
int index = item.m_index;
assert(index >= 0 && index < 256);
memcpy(decodedCTabItems + index, rgba, 4);
}
uint32_t *pixelDataRGBA = new uint32_t[width * height * 4];
for (int i = 0; i < numPixels; i++)
{
const uint8_t ctabIndex = colorValues[i];
pixelDataRGBA[i] = decodedCTabItems[ctabIndex];
if (((cursorHeader->m_mask[i / 8] >> (7 - (i & 7))) & 1) == 0)
reinterpret_cast<uint8_t*>(pixelDataRGBA + i)[3] = 0;
}
char outPath[64];
sprintf_s(outPath, "Packaged\\WinCursors\\%i.cur", resID);
FILE *outF = nullptr;
errno_t outErr = fopen_s(&outF, outPath, "wb");
if (!outErr)
{
IconDir iconDir;
iconDir.m_reserved = 0;
iconDir.m_type = 2;
iconDir.m_numImages = 1;
IconDirEntry iconDirEntry;
iconDirEntry.m_width = width;
iconDirEntry.m_height = height;
iconDirEntry.m_numColors = 0;
iconDirEntry.m_reserved = 0;
iconDirEntry.m_numPlanes_HotSpotX = cursorHeader->m_hotSpotX;
iconDirEntry.m_bpp_HotSpotY = cursorHeader->m_hotSpotY;
iconDirEntry.m_imageDataSize = 0;
iconDirEntry.m_imageDataOffset = sizeof(IconDir) + sizeof(IconDirEntry);
fwrite(&iconDir, 1, sizeof(IconDir), outF);
fwrite(&iconDirEntry, 1, sizeof(IconDirEntry), outF);
long imageDataStart = ftell(outF);
stbi_write_png_to_func(WriteToFileCallback, outF, width, height, 4, pixelDataRGBA, width * 4);
long imageDataEnd = ftell(outF);
fseek(outF, sizeof(IconDir), SEEK_SET);
iconDirEntry.m_imageDataSize = static_cast<uint32_t>(imageDataEnd - imageDataStart);
fwrite(&iconDirEntry, 1, sizeof(IconDirEntry), outF);
fclose(outF);
}
delete[] colorValues;
delete[] pixelDataRGBA;
}
return 0;
}

View File

@@ -0,0 +1,145 @@
<?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>{B852D549-4020-4477-8BFB-E199FF78B047}</ProjectGuid>
<RootNamespace>ConvertColorCursors</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="..\GpCommon.props" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\stb.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="..\GpCommon.props" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\stb.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="..\GpCommon.props" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\stb.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="..\GpCommon.props" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\stb.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
</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>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="..\PortabilityLayer\PortabilityLayer.vcxproj">
<Project>{6ec62b0f-9353-40a4-a510-3788f1368b33}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\stb\stb_image_write.c" />
<ClCompile Include="ConvertColorCursors.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,25 @@
<?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="ConvertColorCursors.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\stb\stb_image_write.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -1,4 +1,7 @@
x64\Release\MiniRez.exe "GpApp2\Glider PRO.r" Packaged\ApplicationResources.gpr x64\Release\MiniRez.exe "GpApp2\Glider PRO.r" Packaged\ApplicationResources.gpr
x64\Release\ConvertColorCursors.exe
x64\Release\hqx2gp.exe "GpApp2\Houses\Art Museum.binhex" "Packaged\Houses\Art Museum" x64\Release\hqx2gp.exe "GpApp2\Houses\Art Museum.binhex" "Packaged\Houses\Art Museum"
x64\Release\hqx2gp.exe "GpApp2\Houses\California or Bust!.binhex" "Packaged\Houses\California or Bust!" x64\Release\hqx2gp.exe "GpApp2\Houses\California or Bust!.binhex" "Packaged\Houses\California or Bust!"
x64\Release\hqx2gp.exe "GpApp2\Houses\Castle o' the Air.binhex" "Packaged\Houses\Castle o' the Air" x64\Release\hqx2gp.exe "GpApp2\Houses\Castle o' the Air.binhex" "Packaged\Houses\Castle o' the Air"

View File

@@ -25,6 +25,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeType", "FreeType\FreeTy
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CompileShadersD3D11", "CompileShadersD3D11\CompileShadersD3D11.vcxproj", "{ED2F91E1-673A-4590-82B2-EB157927D3E3}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CompileShadersD3D11", "CompileShadersD3D11\CompileShadersD3D11.vcxproj", "{ED2F91E1-673A-4590-82B2-EB157927D3E3}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConvertColorCursors", "ConvertColorCursors\ConvertColorCursors.vcxproj", "{B852D549-4020-4477-8BFB-E199FF78B047}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64 Debug|x64 = Debug|x64
@@ -121,6 +123,14 @@ Global
{ED2F91E1-673A-4590-82B2-EB157927D3E3}.Release|x64.Build.0 = Release|x64 {ED2F91E1-673A-4590-82B2-EB157927D3E3}.Release|x64.Build.0 = Release|x64
{ED2F91E1-673A-4590-82B2-EB157927D3E3}.Release|x86.ActiveCfg = Release|Win32 {ED2F91E1-673A-4590-82B2-EB157927D3E3}.Release|x86.ActiveCfg = Release|Win32
{ED2F91E1-673A-4590-82B2-EB157927D3E3}.Release|x86.Build.0 = Release|Win32 {ED2F91E1-673A-4590-82B2-EB157927D3E3}.Release|x86.Build.0 = Release|Win32
{B852D549-4020-4477-8BFB-E199FF78B047}.Debug|x64.ActiveCfg = Debug|x64
{B852D549-4020-4477-8BFB-E199FF78B047}.Debug|x64.Build.0 = Debug|x64
{B852D549-4020-4477-8BFB-E199FF78B047}.Debug|x86.ActiveCfg = Debug|Win32
{B852D549-4020-4477-8BFB-E199FF78B047}.Debug|x86.Build.0 = Debug|Win32
{B852D549-4020-4477-8BFB-E199FF78B047}.Release|x64.ActiveCfg = Release|x64
{B852D549-4020-4477-8BFB-E199FF78B047}.Release|x64.Build.0 = Release|x64
{B852D549-4020-4477-8BFB-E199FF78B047}.Release|x86.ActiveCfg = Release|Win32
{B852D549-4020-4477-8BFB-E199FF78B047}.Release|x86.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@@ -0,0 +1,12 @@
#pragma once
namespace EGpStandardCursors
{
enum EGpStandardCursor
{
kArrow,
kHidden,
};
}
typedef EGpStandardCursors::EGpStandardCursor EGpStandardCursor_t;

View File

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

View File

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

View File

@@ -21,6 +21,8 @@ struct GpDisplayDriverProperties
unsigned int m_frameTimeLockMaxNumerator; unsigned int m_frameTimeLockMaxNumerator;
unsigned int m_frameTimeLockMaxDenominator; unsigned int m_frameTimeLockMaxDenominator;
void *m_osGlobals;
// Tick function and context to call when a frame needs to be served. // Tick function and context to call when a frame needs to be served.
TickFunc_t m_tickFunc; TickFunc_t m_tickFunc;
void *m_tickFuncContext; void *m_tickFuncContext;

View File

@@ -1,18 +1,20 @@
#pragma once #pragma once
#define NOMINMAX #define NOMINMAX
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#define OEMRESOURCE
#include <Windows.h>
#include <Windows.h>
struct GPWindowsGlobals
{ struct GpWindowsGlobals
HINSTANCE m_hInstance; {
HINSTANCE m_hPrevInstance; HINSTANCE m_hInstance;
LPSTR m_cmdLine; HINSTANCE m_hPrevInstance;
int m_nCmdShow; LPCSTR m_cmdLine;
}; LPCWSTR m_baseDir;
int m_nCmdShow;
extern GPWindowsGlobals g_gpWindowsGlobals; };
extern GpWindowsGlobals g_gpWindowsGlobals;
#undef CreateMutex #undef CreateMutex

View File

@@ -0,0 +1,6 @@
#pragma once
struct IGpColorCursor
{
virtual void Destroy() = 0;
};

View File

@@ -1,8 +1,10 @@
#pragma once #pragma once
#include "PixelFormat.h" #include "PixelFormat.h"
#include "EGpStandardCursor.h"
struct IGpDisplayDriverSurface; struct IGpDisplayDriverSurface;
struct IGpColorCursor;
// Display drivers are responsible for timing and calling the game tick function. // Display drivers are responsible for timing and calling the game tick function.
struct IGpDisplayDriver struct IGpDisplayDriver
@@ -16,5 +18,9 @@ public:
virtual IGpDisplayDriverSurface *CreateSurface(size_t width, size_t height, PortabilityLayer::PixelFormat pixelFormat) = 0; virtual IGpDisplayDriverSurface *CreateSurface(size_t width, size_t height, PortabilityLayer::PixelFormat pixelFormat) = 0;
virtual void DrawSurface(IGpDisplayDriverSurface *surface, size_t x, size_t y, size_t width, size_t height) = 0; virtual void DrawSurface(IGpDisplayDriverSurface *surface, size_t x, size_t y, size_t width, size_t height) = 0;
virtual IGpColorCursor *LoadColorCursor(int cursorID) = 0;
virtual void SetColorCursor(IGpColorCursor *colorCursor) = 0;
virtual void SetStandardCursor(EGpStandardCursor_t standardCursor) = 0;
virtual void UpdatePalette(const void *paletteData) = 0; virtual void UpdatePalette(const void *paletteData) = 0;
}; };

View File

@@ -143,6 +143,7 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\GpCommon\GpColorCursor_Win32.cpp" />
<ClCompile Include="GpAppEnvironment.cpp" /> <ClCompile Include="GpAppEnvironment.cpp" />
<ClCompile Include="GpAudioDriverFactory.cpp" /> <ClCompile Include="GpAudioDriverFactory.cpp" />
<ClCompile Include="GpDisplayDriverFactory.cpp" /> <ClCompile Include="GpDisplayDriverFactory.cpp" />
@@ -172,7 +173,10 @@
<ClCompile Include="ShadersD3D11\DrawQuadV_D3D11.cpp" /> <ClCompile Include="ShadersD3D11\DrawQuadV_D3D11.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\GpCommon\EGpStandardCursor.h" />
<ClInclude Include="..\GpCommon\IGpColorCursor.h" />
<ClInclude Include="..\GpCommon\IGpAudioChannelCallbacks.h" /> <ClInclude Include="..\GpCommon\IGpAudioChannelCallbacks.h" />
<ClInclude Include="..\GpCommon\GpColorCursor_Win32.h" />
<ClInclude Include="..\GpCommon\IGpDisplayDriverSurface.h" /> <ClInclude Include="..\GpCommon\IGpDisplayDriverSurface.h" />
<ClInclude Include="EGpAudioDriverType.h" /> <ClInclude Include="EGpAudioDriverType.h" />
<ClInclude Include="EGpDisplayDriverType.h" /> <ClInclude Include="EGpDisplayDriverType.h" />

View File

@@ -99,6 +99,9 @@
<ClCompile Include="ShadersD3D11\DrawQuadRGBP_D3D11.cpp"> <ClCompile Include="ShadersD3D11\DrawQuadRGBP_D3D11.cpp">
<Filter>Source Files\CompiledShaders</Filter> <Filter>Source Files\CompiledShaders</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\GpCommon\GpColorCursor_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="GpWindows.h"> <ClInclude Include="GpWindows.h">
@@ -212,5 +215,14 @@
<ClInclude Include="GpComPtr.h"> <ClInclude Include="GpComPtr.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </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>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,6 +1,8 @@
#define _CRT_SECURE_NO_WARNINGS
#include "GpDisplayDriverD3D11.h" #include "GpDisplayDriverD3D11.h"
#include "GpDisplayDriverSurfaceD3D11.h" #include "GpDisplayDriverSurfaceD3D11.h"
#include "GpWindows.h" #include "GpWindows.h"
#include "GpColorCursor_Win32.h"
#include "GpFiber_Win32.h" #include "GpFiber_Win32.h"
#include <d3d11.h> #include <d3d11.h>
@@ -308,6 +310,8 @@ bool GpDisplayDriverD3D11::InitResources()
bool GpDisplayDriverD3D11::PresentFrameAndSync() bool GpDisplayDriverD3D11::PresentFrameAndSync()
{ {
SynchronizeCursors();
float clearColor[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; float clearColor[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
m_deviceContext->ClearRenderTargetView(m_backBufferRTV, clearColor); m_deviceContext->ClearRenderTargetView(m_backBufferRTV, clearColor);
@@ -443,9 +447,74 @@ bool GpDisplayDriverD3D11::PresentFrameAndSync()
return true; return true;
} }
void GpDisplayDriverD3D11::SynchronizeCursors()
{
HCURSOR replacementCursor = nullptr;
if (m_activeCursor)
{
if (m_pendingCursor != m_activeCursor)
{
if (m_pendingCursor == nullptr)
{
m_currentStandardCursor = m_pendingStandardCursor;
ChangeToStandardCursor(m_currentStandardCursor);
m_activeCursor->DecRef();
m_activeCursor = nullptr;
}
else
{
ChangeToCursor(m_pendingCursor->GetHCursor());
m_pendingCursor->IncRef();
m_activeCursor->DecRef();
m_activeCursor = m_pendingCursor;
}
}
}
else
{
if (m_pendingCursor)
{
m_pendingCursor->IncRef();
m_activeCursor = m_pendingCursor;
ChangeToCursor(m_activeCursor->GetHCursor());
}
else
{
if (m_pendingStandardCursor != m_currentStandardCursor)
{
ChangeToStandardCursor(m_pendingStandardCursor);
m_currentStandardCursor = m_pendingStandardCursor;
}
}
}
}
void GpDisplayDriverD3D11::ChangeToCursor(HCURSOR cursor)
{
if (m_mouseIsInClientArea)
SetCursor(cursor);
SetClassLongPtrW(m_hwnd, GCLP_HCURSOR, reinterpret_cast<LONG_PTR>(cursor));
}
void GpDisplayDriverD3D11::ChangeToStandardCursor(EGpStandardCursor_t cursor)
{
switch (cursor)
{
case EGpStandardCursors::kArrow:
default:
ChangeToCursor(m_arrowCursor);
break;
}
}
void GpDisplayDriverD3D11::Run() void GpDisplayDriverD3D11::Run()
{ {
HWND hWnd;
WNDCLASSEX wc; WNDCLASSEX wc;
LPVOID fiber = ConvertThreadToFiberEx(this, 0); LPVOID fiber = ConvertThreadToFiberEx(this, 0);
@@ -460,7 +529,7 @@ void GpDisplayDriverD3D11::Run()
wc.style = CS_HREDRAW | CS_VREDRAW; wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WinProc; wc.lpfnWndProc = WinProc;
wc.hInstance = g_gpWindowsGlobals.m_hInstance; wc.hInstance = g_gpWindowsGlobals.m_hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hCursor = m_arrowCursor;
wc.hbrBackground = (HBRUSH)COLOR_WINDOW; wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = "GPD3D11WindowClass"; wc.lpszClassName = "GPD3D11WindowClass";
@@ -473,11 +542,11 @@ void GpDisplayDriverD3D11::Run()
RECT wr = { 0, 0, m_windowWidth, m_windowHeight }; RECT wr = { 0, 0, m_windowWidth, m_windowHeight };
AdjustWindowRect(&wr, windowStyle, menus != NULL); AdjustWindowRect(&wr, windowStyle, menus != NULL);
hWnd = CreateWindowExW(NULL, L"GPD3D11WindowClass", L"GlidePort (Direct3D 11)", WS_OVERLAPPEDWINDOW, 300, 300, wr.right - wr.left, wr.bottom - wr.top, NULL, menus, g_gpWindowsGlobals.m_hInstance, NULL); m_hwnd = CreateWindowExW(NULL, L"GPD3D11WindowClass", L"GlidePort (Direct3D 11)", WS_OVERLAPPEDWINDOW, 300, 300, wr.right - wr.left, wr.bottom - wr.top, NULL, menus, g_gpWindowsGlobals.m_hInstance, NULL);
ShowWindow(hWnd, g_gpWindowsGlobals.m_nCmdShow); ShowWindow(m_hwnd, g_gpWindowsGlobals.m_nCmdShow);
StartD3DForWindow(hWnd, m_swapChain, m_device, m_deviceContext); StartD3DForWindow(m_hwnd, m_swapChain, m_device, m_deviceContext);
InitResources(); InitResources();
@@ -495,6 +564,10 @@ void GpDisplayDriverD3D11::Run()
if (msg.message == WM_QUIT) if (msg.message == WM_QUIT)
break; break;
else if (msg.message == WM_MOUSEMOVE)
m_mouseIsInClientArea = true;
else if (msg.message == WM_MOUSELEAVE)
m_mouseIsInClientArea = false;
} }
else else
{ {
@@ -612,6 +685,44 @@ void GpDisplayDriverD3D11::DrawSurface(IGpDisplayDriverSurface *surface, size_t
m_deviceContext->DrawIndexed(6, 0, 0); m_deviceContext->DrawIndexed(6, 0, 0);
} }
IGpColorCursor *GpDisplayDriverD3D11::LoadColorCursor(int cursorID)
{
const size_t bufSize = MAX_PATH;
wchar_t path[bufSize];
int sz = _snwprintf(path, bufSize, L"%sPackaged\\WinCursors\\%i.cur", m_osGlobals->m_baseDir, cursorID);
if (sz < 0 || static_cast<size_t>(sz) >= bufSize)
return nullptr;
return GpColorCursor_Win32::Load(path);
}
// We can't just set the cursor because we want to post WM_SETCURSOR to keep it limited
// to the game window area, but depending on the fiber implementation, this may not be
// the window thread.
void GpDisplayDriverD3D11::SetColorCursor(IGpColorCursor *colorCursor)
{
GpColorCursor_Win32 *winCursor = static_cast<GpColorCursor_Win32*>(colorCursor);
winCursor->IncRef();
if (m_pendingCursor)
m_pendingCursor->DecRef();
m_pendingCursor = winCursor;
}
void GpDisplayDriverD3D11::SetStandardCursor(EGpStandardCursor_t standardCursor)
{
if (m_pendingCursor)
{
m_pendingCursor->DecRef();
m_pendingCursor = nullptr;
}
m_pendingStandardCursor = standardCursor;
}
void GpDisplayDriverD3D11::UpdatePalette(const void *paletteData) void GpDisplayDriverD3D11::UpdatePalette(const void *paletteData)
{ {
const size_t dataSize = 256 * 4; const size_t dataSize = 256 * 4;
@@ -643,14 +754,23 @@ GpDisplayDriverD3D11::GpDisplayDriverD3D11(const GpDisplayDriverProperties &prop
, m_windowWidth(640) , m_windowWidth(640)
, m_windowHeight(480) , m_windowHeight(480)
, m_vosFiber(nullptr) , m_vosFiber(nullptr)
, m_osGlobals(static_cast<GpWindowsGlobals*>(properties.m_osGlobals))
, m_pendingCursor(nullptr)
, m_activeCursor(nullptr)
, m_currentStandardCursor(EGpStandardCursors::kArrow)
, m_pendingStandardCursor(EGpStandardCursors::kArrow)
, m_mouseIsInClientArea(false)
{ {
memset(&m_syncTimeBase, 0, sizeof(m_syncTimeBase)); memset(&m_syncTimeBase, 0, sizeof(m_syncTimeBase));
QueryPerformanceFrequency(&m_QPFrequency); QueryPerformanceFrequency(&m_QPFrequency);
m_frameTimeSliceSize = m_QPFrequency.QuadPart * static_cast<LONGLONG>(properties.m_frameTimeLockNumerator) / static_cast<LONGLONG>(properties.m_frameTimeLockDenominator); m_frameTimeSliceSize = m_QPFrequency.QuadPart * static_cast<LONGLONG>(properties.m_frameTimeLockNumerator) / static_cast<LONGLONG>(properties.m_frameTimeLockDenominator);
m_arrowCursor = reinterpret_cast<HCURSOR>(LoadImageW(nullptr, MAKEINTRESOURCEW(OCR_NORMAL), IMAGE_CURSOR, 0, 0, LR_SHARED));
} }
GpDisplayDriverD3D11::~GpDisplayDriverD3D11() GpDisplayDriverD3D11::~GpDisplayDriverD3D11()
{ {
// GP TODO: Sloppy cleanup... Close the window!!
} }

View File

@@ -10,6 +10,9 @@
#include "PixelFormat.h" #include "PixelFormat.h"
struct GpWindowsGlobals;
class GpColorCursor_Win32;
struct IDXGISwapChain1; struct IDXGISwapChain1;
struct ID3D11Buffer; struct ID3D11Buffer;
struct ID3D11DepthStencilState; struct ID3D11DepthStencilState;
@@ -35,6 +38,10 @@ public:
IGpDisplayDriverSurface *CreateSurface(size_t width, size_t height, PortabilityLayer::PixelFormat pixelFormat) override; IGpDisplayDriverSurface *CreateSurface(size_t width, size_t height, PortabilityLayer::PixelFormat pixelFormat) override;
void DrawSurface(IGpDisplayDriverSurface *surface, size_t x, size_t y, size_t width, size_t height) override; void DrawSurface(IGpDisplayDriverSurface *surface, size_t x, size_t y, size_t width, size_t height) override;
IGpColorCursor *LoadColorCursor(int cursorID) override;
void SetColorCursor(IGpColorCursor *colorCursor) override;
void SetStandardCursor(EGpStandardCursor_t standardCursor) override;
void UpdatePalette(const void *paletteData) override; void UpdatePalette(const void *paletteData) override;
static GpDisplayDriverD3D11 *Create(const GpDisplayDriverProperties &properties); static GpDisplayDriverD3D11 *Create(const GpDisplayDriverProperties &properties);
@@ -52,12 +59,22 @@ private:
float m_unused[2]; float m_unused[2];
}; };
struct CompactedPresentHistoryItem
{
LARGE_INTEGER m_timestamp;
unsigned int m_numFrames;
};
GpDisplayDriverD3D11(const GpDisplayDriverProperties &properties); GpDisplayDriverD3D11(const GpDisplayDriverProperties &properties);
~GpDisplayDriverD3D11(); ~GpDisplayDriverD3D11();
bool InitResources(); bool InitResources();
bool PresentFrameAndSync(); bool PresentFrameAndSync();
void SynchronizeCursors();
void ChangeToCursor(HCURSOR cursor);
void ChangeToStandardCursor(EGpStandardCursor_t cursor);
GpComPtr<IDXGISwapChain1> m_swapChain; GpComPtr<IDXGISwapChain1> m_swapChain;
GpComPtr<ID3D11Device> m_device; GpComPtr<ID3D11Device> m_device;
GpComPtr<ID3D11DeviceContext> m_deviceContext; GpComPtr<ID3D11DeviceContext> m_deviceContext;
@@ -77,12 +94,6 @@ private:
GpComPtr<ID3D11Texture2D> m_backBufferTexture; GpComPtr<ID3D11Texture2D> m_backBufferTexture;
GpComPtr<ID3D11RenderTargetView> m_backBufferRTV; GpComPtr<ID3D11RenderTargetView> m_backBufferRTV;
struct CompactedPresentHistoryItem
{
LARGE_INTEGER m_timestamp;
unsigned int m_numFrames;
};
GpRingBuffer<CompactedPresentHistoryItem, 60> m_presentHistory; GpRingBuffer<CompactedPresentHistoryItem, 60> m_presentHistory;
GpDisplayDriverProperties m_properties; GpDisplayDriverProperties m_properties;
@@ -97,5 +108,15 @@ private:
DWORD m_windowWidth; DWORD m_windowWidth;
DWORD m_windowHeight; DWORD m_windowHeight;
GpColorCursor_Win32 *m_activeCursor;
GpColorCursor_Win32 *m_pendingCursor;
EGpStandardCursor_t m_currentStandardCursor;
EGpStandardCursor_t m_pendingStandardCursor;
bool m_mouseIsInClientArea;
GpFiber *m_vosFiber; GpFiber *m_vosFiber;
GpWindowsGlobals *m_osGlobals;
HCURSOR m_arrowCursor;
HWND m_hwnd;
}; };

View File

@@ -95,6 +95,7 @@ GpDirectoryCursor_Win32::~GpDirectoryCursor_Win32()
GpFileSystem_Win32::GpFileSystem_Win32() GpFileSystem_Win32::GpFileSystem_Win32()
{ {
// GP TODO: This shouldn't be static init since it allocates memory
m_executablePath[0] = 0; m_executablePath[0] = 0;
PWSTR docsPath; PWSTR docsPath;
@@ -201,6 +202,11 @@ PortabilityLayer::HostDirectoryCursor *GpFileSystem_Win32::ScanDirectory(Portabi
return GpDirectoryCursor_Win32::Create(ff, findData); return GpDirectoryCursor_Win32::Create(ff, findData);
} }
const wchar_t *GpFileSystem_Win32::GetBasePath() const
{
return m_executablePath;
}
GpFileSystem_Win32 *GpFileSystem_Win32::GetInstance() GpFileSystem_Win32 *GpFileSystem_Win32::GetInstance()
{ {
return &ms_instance; return &ms_instance;

View File

@@ -1,31 +1,33 @@
#pragma once #pragma once
#include "HostFileSystem.h" #include "HostFileSystem.h"
#include "GpCoreDefs.h" #include "GpCoreDefs.h"
#include "GpWindows.h" #include "GpWindows.h"
#include <string> #include <string>
class GpFileSystem_Win32 final : public PortabilityLayer::HostFileSystem class GpFileSystem_Win32 final : public PortabilityLayer::HostFileSystem
{ {
public: public:
GpFileSystem_Win32(); GpFileSystem_Win32();
bool FileExists(PortabilityLayer::EVirtualDirectory virtualDirectory, const char *path) override; bool FileExists(PortabilityLayer::EVirtualDirectory virtualDirectory, const char *path) override;
PortabilityLayer::IOStream *OpenFile(PortabilityLayer::EVirtualDirectory virtualDirectory, const char *path, bool writeAccess, bool create) override; PortabilityLayer::IOStream *OpenFile(PortabilityLayer::EVirtualDirectory virtualDirectory, const char *path, bool writeAccess, bool create) override;
PortabilityLayer::HostDirectoryCursor *ScanDirectory(PortabilityLayer::EVirtualDirectory virtualDirectory) override; PortabilityLayer::HostDirectoryCursor *ScanDirectory(PortabilityLayer::EVirtualDirectory virtualDirectory) override;
static GpFileSystem_Win32 *GetInstance(); const wchar_t *GetBasePath() const;
private: static GpFileSystem_Win32 *GetInstance();
bool ResolvePath(PortabilityLayer::EVirtualDirectory virtualDirectory, const char *path, wchar_t *outPath);
private:
std::wstring m_prefsDir; bool ResolvePath(PortabilityLayer::EVirtualDirectory virtualDirectory, const char *path, wchar_t *outPath);
std::wstring m_packagedDir;
std::wstring m_prefsDir;
std::wstring m_packagedDir;
std::wstring m_housesDir; std::wstring m_housesDir;
std::wstring m_resourcesDir; std::wstring m_resourcesDir;
wchar_t m_executablePath[MAX_PATH]; wchar_t m_executablePath[MAX_PATH];
static GpFileSystem_Win32 ms_instance; static GpFileSystem_Win32 ms_instance;
}; };

View File

@@ -4,7 +4,8 @@
struct GpGlobalConfig struct GpGlobalConfig
{ {
EGpDisplayDriverType m_displayDriverType; EGpDisplayDriverType m_displayDriverType;
void *m_osGlobals;
}; };
extern GpGlobalConfig g_gpGlobalConfig; extern GpGlobalConfig g_gpGlobalConfig;

View File

@@ -49,6 +49,7 @@ int GpMain::Run()
ddProps.m_renderFuncContext = appEnvironment; ddProps.m_renderFuncContext = appEnvironment;
ddProps.m_type = g_gpGlobalConfig.m_displayDriverType; ddProps.m_type = g_gpGlobalConfig.m_displayDriverType;
ddProps.m_osGlobals = g_gpGlobalConfig.m_osGlobals;
GpAudioDriverProperties adProps; GpAudioDriverProperties adProps;
memset(&adProps, 0, sizeof(adProps)); memset(&adProps, 0, sizeof(adProps));

View File

@@ -13,7 +13,7 @@
#include <stdio.h> #include <stdio.h>
GPWindowsGlobals g_gpWindowsGlobals; GpWindowsGlobals g_gpWindowsGlobals;
extern "C" __declspec(dllimport) IGpAudioDriver *GpDriver_CreateAudioDriver_XAudio2(const GpAudioDriverProperties &properties); extern "C" __declspec(dllimport) IGpAudioDriver *GpDriver_CreateAudioDriver_XAudio2(const GpAudioDriverProperties &properties);
@@ -26,8 +26,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance; g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance;
g_gpWindowsGlobals.m_cmdLine = lpCmdLine; g_gpWindowsGlobals.m_cmdLine = lpCmdLine;
g_gpWindowsGlobals.m_nCmdShow = nCmdShow; g_gpWindowsGlobals.m_nCmdShow = nCmdShow;
g_gpWindowsGlobals.m_baseDir = GpFileSystem_Win32::GetInstance()->GetBasePath();
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_D3D11; g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_D3D11;
g_gpGlobalConfig.m_osGlobals = &g_gpWindowsGlobals;
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_D3D11, GpDisplayDriverFactoryD3D11::Create); GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_D3D11, GpDisplayDriverFactoryD3D11::Create);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_XAudio2, GpDriver_CreateAudioDriver_XAudio2); GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_XAudio2, GpDriver_CreateAudioDriver_XAudio2);

View File

@@ -1,4 +1,5 @@
#include "GpPLGlueDisplayDriver.h" #include "GpPLGlueDisplayDriver.h"
#include "VirtualDirectory.h"
#include "IGpDisplayDriver.h" #include "IGpDisplayDriver.h"
GpPLGlueDisplayDriver::GpPLGlueDisplayDriver() GpPLGlueDisplayDriver::GpPLGlueDisplayDriver()
@@ -9,10 +10,21 @@ GpPLGlueDisplayDriver::GpPLGlueDisplayDriver()
void GpPLGlueDisplayDriver::GetDisplayResolution(unsigned int *width, unsigned int *height, PortabilityLayer::PixelFormat *bpp) void GpPLGlueDisplayDriver::GetDisplayResolution(unsigned int *width, unsigned int *height, PortabilityLayer::PixelFormat *bpp)
{ {
m_displayDriver->GetDisplayResolution(width, height, bpp); m_displayDriver->GetDisplayResolution(width, height, bpp);
}
IGpColorCursor *GpPLGlueDisplayDriver::LoadColorCursor(int cursorID)
{
return m_displayDriver->LoadColorCursor(cursorID);
} }
void GpPLGlueDisplayDriver::HideCursor() void GpPLGlueDisplayDriver::SetColorCursor(IGpColorCursor *colorCursor)
{ {
m_displayDriver->SetColorCursor(colorCursor);
}
void GpPLGlueDisplayDriver::SetStandardCursor(EGpStandardCursor_t standardCursor)
{
m_displayDriver->SetStandardCursor(standardCursor);
} }
GpPLGlueDisplayDriver *GpPLGlueDisplayDriver::GetInstance() GpPLGlueDisplayDriver *GpPLGlueDisplayDriver::GetInstance()

View File

@@ -10,7 +10,9 @@ public:
GpPLGlueDisplayDriver(); GpPLGlueDisplayDriver();
void GetDisplayResolution(unsigned int *width, unsigned int *height, PortabilityLayer::PixelFormat *bpp) override; void GetDisplayResolution(unsigned int *width, unsigned int *height, PortabilityLayer::PixelFormat *bpp) override;
void HideCursor() override; IGpColorCursor *LoadColorCursor(int id) override;
void SetColorCursor(IGpColorCursor *colorCursor) override;
void SetStandardCursor(EGpStandardCursor_t standardCursor) override;
void SetGpDisplayDriver(IGpDisplayDriver *displayDriver); void SetGpDisplayDriver(IGpDisplayDriver *displayDriver);

View File

@@ -60,21 +60,25 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\Common.props" /> <Import Project="..\Common.props" />
<Import Project="..\PortabilityLayer.props" /> <Import Project="..\PortabilityLayer.props" />
<Import Project="..\stb.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <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="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\Common.props" /> <Import Project="..\Common.props" />
<Import Project="..\PortabilityLayer.props" /> <Import Project="..\PortabilityLayer.props" />
<Import Project="..\stb.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <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="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\Common.props" /> <Import Project="..\Common.props" />
<Import Project="..\PortabilityLayer.props" /> <Import Project="..\PortabilityLayer.props" />
<Import Project="..\stb.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <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="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\Common.props" /> <Import Project="..\Common.props" />
<Import Project="..\PortabilityLayer.props" /> <Import Project="..\PortabilityLayer.props" />
<Import Project="..\stb.props" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup /> <PropertyGroup />
@@ -123,8 +127,8 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\stb\stb_image_write.c" />
<ClCompile Include="PictChecker.cpp" /> <ClCompile Include="PictChecker.cpp" />
<ClCompile Include="stb_image_write.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\PortabilityLayer\PortabilityLayer.vcxproj"> <ProjectReference Include="..\PortabilityLayer\PortabilityLayer.vcxproj">

View File

@@ -18,7 +18,7 @@
<ClCompile Include="PictChecker.cpp"> <ClCompile Include="PictChecker.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="stb_image_write.c"> <ClCompile Include="..\stb\stb_image_write.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>

View File

@@ -3,6 +3,9 @@
#define __PL_HOST_DISPLAY_DRIVER_H__ #define __PL_HOST_DISPLAY_DRIVER_H__
#include "PixelFormat.h" #include "PixelFormat.h"
#include "EGpStandardCursor.h"
struct IGpColorCursor;
namespace PortabilityLayer namespace PortabilityLayer
{ {
@@ -10,7 +13,9 @@ namespace PortabilityLayer
{ {
public: public:
virtual void GetDisplayResolution(unsigned int *width, unsigned int *height, PixelFormat *pixelFormat) = 0; virtual void GetDisplayResolution(unsigned int *width, unsigned int *height, PixelFormat *pixelFormat) = 0;
virtual void HideCursor() = 0; virtual IGpColorCursor *LoadColorCursor(int id) = 0;
virtual void SetColorCursor(IGpColorCursor *colorCursor) = 0;
virtual void SetStandardCursor(EGpStandardCursor_t standardCursor) = 0;
static void SetInstance(HostDisplayDriver *instance); static void SetInstance(HostDisplayDriver *instance);
static HostDisplayDriver *GetInstance(); static HostDisplayDriver *GetInstance();

View File

@@ -14,6 +14,7 @@
#include "HostDisplayDriver.h" #include "HostDisplayDriver.h"
#include "HostSystemServices.h" #include "HostSystemServices.h"
#include "HostVOSEventQueue.h" #include "HostVOSEventQueue.h"
#include "IGpColorCursor.h"
#include "InputManager.h" #include "InputManager.h"
#include "ResourceManager.h" #include "ResourceManager.h"
#include "MacFileInfo.h" #include "MacFileInfo.h"
@@ -64,6 +65,7 @@ static void ImportVOSEvents()
void InitCursor() void InitCursor()
{ {
PortabilityLayer::HostDisplayDriver::GetInstance()->SetStandardCursor(EGpStandardCursors::kArrow);
} }
Rect BERect::ToRect() const Rect BERect::ToRect() const
@@ -90,26 +92,34 @@ CursHandle GetCursor(int cursorID)
CCrsrHandle GetCCursor(int cursorID) CCrsrHandle GetCCursor(int cursorID)
{ {
PortabilityLayer::ResourceManager *resManager = PortabilityLayer::ResourceManager::GetInstance(); PortabilityLayer::HostDisplayDriver *driver = PortabilityLayer::HostDisplayDriver::GetInstance();
PortabilityLayer::MMHandleBlock *ccRes = resManager->GetResource('crsr', cursorID); IGpColorCursor *hwCursor = driver->LoadColorCursor(cursorID);
if (!ccRes) if (!hwCursor)
return nullptr; return nullptr;
PortabilityLayer::MMHandleBlock *copy = PortabilityLayer::MemoryManager::GetInstance()->AllocHandle(ccRes->m_size); CCrsrHandle hdl = PortabilityLayer::MemoryManager::GetInstance()->NewHandle<CCursor>();
memcpy(copy->m_contents, ccRes->m_contents, ccRes->m_size); if (!hdl)
{
hwCursor->Destroy();
return nullptr;
}
return reinterpret_cast<CCrsrHandle>(copy); CCursor *ccursor = *hdl;
ccursor->hwCursor = hwCursor;
return hdl;
} }
void SetCCursor(CCrsrHandle handle) void SetCCursor(CCrsrHandle handle)
{ {
PL_NotYetImplemented_Minor(); assert(handle);
PortabilityLayer::HostDisplayDriver::GetInstance()->SetColorCursor((*handle)->hwCursor);
} }
void HideCursor() void HideCursor()
{ {
PortabilityLayer::HostDisplayDriver::GetInstance()->HideCursor(); PortabilityLayer::HostDisplayDriver::GetInstance()->SetStandardCursor(EGpStandardCursors::kHidden);
} }
void SetCursor(CursPtr cursor) void SetCursor(CursPtr cursor)
@@ -124,7 +134,9 @@ void SetBuiltinCursor(int builtinCursor)
void DisposeCCursor(CCrsrHandle handle) void DisposeCCursor(CCrsrHandle handle)
{ {
PL_NotYetImplemented(); (*handle)->hwCursor->Destroy();
PortabilityLayer::MemoryManager::GetInstance()->ReleaseHandle(reinterpret_cast<PortabilityLayer::MMHandleBlock*>(handle));
} }
void Delay(int ticks, UInt32 *endTickCount) void Delay(int ticks, UInt32 *endTickCount)

View File

@@ -12,6 +12,8 @@
#pragma warning(error:4311) // Pointer truncation to int #pragma warning(error:4311) // Pointer truncation to int
#endif #endif
struct IGpColorCursor;
namespace PortabilityLayer namespace PortabilityLayer
{ {
struct MMHandleBlock; struct MMHandleBlock;
@@ -92,6 +94,7 @@ struct Cursor
struct CCursor struct CCursor
{ {
IGpColorCursor *hwCursor;
}; };
struct Window struct Window

View File

@@ -11,5 +11,6 @@ namespace PortabilityLayer
EVirtualDirectory_UserData, EVirtualDirectory_UserData,
EVirtualDirectory_Prefs, EVirtualDirectory_Prefs,
EVirtualDirectory_Fonts, EVirtualDirectory_Fonts,
EVirtualDirectory_Cursors,
}; };
} }

10
stb.props Normal file
View File

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