diff --git a/Aerofoil/Aerofoil.vcxproj b/Aerofoil/Aerofoil.vcxproj
index c64673e..3b3db1c 100644
--- a/Aerofoil/Aerofoil.vcxproj
+++ b/Aerofoil/Aerofoil.vcxproj
@@ -156,6 +156,7 @@
+
@@ -175,6 +176,7 @@
+
@@ -185,6 +187,7 @@
+
diff --git a/Aerofoil/Aerofoil.vcxproj.filters b/Aerofoil/Aerofoil.vcxproj.filters
index 4d80d30..8a15760 100644
--- a/Aerofoil/Aerofoil.vcxproj.filters
+++ b/Aerofoil/Aerofoil.vcxproj.filters
@@ -58,6 +58,9 @@
Source Files
+
+ Source Files
+
@@ -141,6 +144,10 @@
Resource Files
+
+ Header Files
+
+
diff --git a/Aerofoil/GpFileStream_Win32.cpp b/Aerofoil/GpFileStream_Win32.cpp
index 66c7b51..ed042cb 100644
--- a/Aerofoil/GpFileStream_Win32.cpp
+++ b/Aerofoil/GpFileStream_Win32.cpp
@@ -142,3 +142,8 @@ void GpFileStream_Win32::Close()
{
CloseHandle(m_handle);
}
+
+void GpFileStream_Win32::Flush()
+{
+ FlushFileBuffers(m_handle);
+}
diff --git a/Aerofoil/GpFileStream_Win32.h b/Aerofoil/GpFileStream_Win32.h
index 95130b5..9a8be6d 100644
--- a/Aerofoil/GpFileStream_Win32.h
+++ b/Aerofoil/GpFileStream_Win32.h
@@ -20,7 +20,8 @@ public:
bool Truncate(PortabilityLayer::UFilePos_t loc) override;
PortabilityLayer::UFilePos_t Size() const override;
PortabilityLayer::UFilePos_t Tell() const override;
- void Close() override;
+ void Close() override;
+ void Flush() override;
private:
HANDLE m_handle;
diff --git a/Aerofoil/GpFileSystem_Win32.cpp b/Aerofoil/GpFileSystem_Win32.cpp
index eb27b22..b723e21 100644
--- a/Aerofoil/GpFileSystem_Win32.cpp
+++ b/Aerofoil/GpFileSystem_Win32.cpp
@@ -122,16 +122,19 @@ GpFileSystem_Win32::GpFileSystem_Win32()
m_userHousesDir = m_prefsDir + L"\\Houses";
m_userSavesDir = m_prefsDir + L"\\SavedGames";
m_scoresDir = m_prefsDir + L"\\Scores";
+ m_logsDir = m_prefsDir + L"\\Logs";
CreateDirectoryW(m_prefsDir.c_str(), nullptr);
CreateDirectoryW(m_scoresDir.c_str(), nullptr);
CreateDirectoryW(m_userHousesDir.c_str(), nullptr);
CreateDirectoryW(m_userSavesDir.c_str(), nullptr);
+ CreateDirectoryW(m_logsDir.c_str(), nullptr);
m_prefsDir.append(L"\\");
m_scoresDir.append(L"\\");
m_userHousesDir.append(L"\\");
m_userSavesDir.append(L"\\");
+ m_logsDir.append(L"\\");
}
DWORD modulePathSize = GetModuleFileNameW(nullptr, m_executablePath, MAX_PATH);
@@ -514,6 +517,9 @@ bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtua
case PortabilityLayer::VirtualDirectories::kHighScores:
baseDir = m_scoresDir.c_str();
break;
+ case PortabilityLayer::VirtualDirectories::kLogs:
+ baseDir = m_logsDir.c_str();
+ break;
default:
return false;
}
diff --git a/Aerofoil/GpFileSystem_Win32.h b/Aerofoil/GpFileSystem_Win32.h
index 247c93a..42864d8 100644
--- a/Aerofoil/GpFileSystem_Win32.h
+++ b/Aerofoil/GpFileSystem_Win32.h
@@ -34,6 +34,7 @@ private:
std::wstring m_scoresDir;
std::wstring m_packagedDir;
std::wstring m_housesDir;
+ std::wstring m_logsDir;
std::wstring m_userHousesDir;
std::wstring m_userSavesDir;
std::wstring m_resourcesDir;
diff --git a/Aerofoil/GpGlobalConfig.h b/Aerofoil/GpGlobalConfig.h
index 7df0ff6..cec63b5 100644
--- a/Aerofoil/GpGlobalConfig.h
+++ b/Aerofoil/GpGlobalConfig.h
@@ -2,7 +2,9 @@
#include "EGpDisplayDriverType.h"
#include "EGpAudioDriverType.h"
-#include "EGpInputDriverType.h"
+#include "EGpInputDriverType.h"
+
+struct IGpLogDriver;
struct GpGlobalConfig
{
@@ -11,6 +13,7 @@ struct GpGlobalConfig
const EGpInputDriverType *m_inputDriverTypes;
size_t m_numInputDrivers;
+ IGpLogDriver *m_logger;
void *m_osGlobals;
};
diff --git a/Aerofoil/GpLogDriver_Win32.cpp b/Aerofoil/GpLogDriver_Win32.cpp
new file mode 100644
index 0000000..83a40af
--- /dev/null
+++ b/Aerofoil/GpLogDriver_Win32.cpp
@@ -0,0 +1,113 @@
+#include "GpLogDriver_Win32.h"
+#include "GpFileSystem_Win32.h"
+
+#include "GpApplicationName.h"
+#include "IOStream.h"
+
+GpLogDriver_Win32::GpLogDriver_Win32()
+ : m_stream(nullptr)
+ , m_isInitialized(false)
+{
+}
+
+void GpLogDriver_Win32::Init()
+{
+ ms_instance.InitInternal();
+}
+
+void GpLogDriver_Win32::VPrintf(Category category, const char *fmt, va_list args)
+{
+ size_t fmtSize = 0;
+ bool hasFormatting = false;
+ for (const char *fmtCheck = fmt; *fmtCheck; fmtCheck++)
+ {
+ if (*fmtCheck == '%')
+ hasFormatting = true;
+
+ fmtSize++;
+ }
+
+ SYSTEMTIME sysTime;
+ GetSystemTime(&sysTime);
+
+ char timestampBuffer[64];
+ sprintf(timestampBuffer, "[%02d:%02d:%02d:%03d] ", sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds);
+
+ m_stream->Write(timestampBuffer, strlen(timestampBuffer));
+
+ const char *debugTag = "";
+
+ switch (category)
+ {
+ case Category_Warning:
+ debugTag = "[WARNING] ";
+ break;
+ case Category_Error:
+ debugTag = "[ERROR] ";
+ break;
+ };
+
+ if (debugTag[0])
+ m_stream->Write(debugTag, strlen(debugTag));
+
+ if (!hasFormatting)
+ m_stream->Write(fmt, fmtSize);
+ else
+ {
+ int formattedSize = vsnprintf(nullptr, 0, fmt, args);
+ if (formattedSize <= 0)
+ return;
+
+ char *charBuff = static_cast(malloc(formattedSize + 1));
+ if (!charBuff)
+ return;
+
+ vsnprintf(charBuff, formattedSize + 1, fmt, args);
+
+ m_stream->Write(charBuff, formattedSize);
+ free(charBuff);
+ }
+
+ m_stream->Write("\n", 1);
+
+ m_stream->Flush();
+}
+
+void GpLogDriver_Win32::Shutdown()
+{
+ if (m_stream)
+ m_stream->Close();
+}
+
+GpLogDriver_Win32 *GpLogDriver_Win32::GetInstance()
+{
+ if (ms_instance.m_isInitialized)
+ return &ms_instance;
+ else
+ return nullptr;
+}
+
+void GpLogDriver_Win32::InitInternal()
+{
+ SYSTEMTIME utcTime;
+ GetSystemTime(&utcTime);
+
+ char logFileName[256];
+
+ sprintf(logFileName, GP_APPLICATION_NAME "-%04d-%02d-%02d_%02d-%02d_%02d.txt", utcTime.wYear, utcTime.wMonth, utcTime.wDay, utcTime.wHour, utcTime.wMinute, utcTime.wSecond);
+
+ m_stream = GpFileSystem_Win32::GetInstance()->OpenFile(PortabilityLayer::VirtualDirectories::kLogs, logFileName, true, GpFileCreationDispositions::kCreateOrOverwrite);
+ if (m_stream)
+ {
+ this->Printf(IGpLogDriver::Category_Information, GP_APPLICATION_NAME " build " __TIMESTAMP__);
+#ifdef NDEBUG
+ this->Printf(IGpLogDriver::Category_Information, "Configuration: Release");
+#else
+ this->Printf(IGpLogDriver::Category_Information, "Configuration: Debug");
+#endif
+
+ m_isInitialized = true;
+ }
+}
+
+GpLogDriver_Win32 GpLogDriver_Win32::ms_instance;
diff --git a/Aerofoil/GpLogDriver_Win32.h b/Aerofoil/GpLogDriver_Win32.h
new file mode 100644
index 0000000..5272c8c
--- /dev/null
+++ b/Aerofoil/GpLogDriver_Win32.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "IGpLogDriver.h"
+
+namespace PortabilityLayer
+{
+ class IOStream;
+}
+
+class GpLogDriver_Win32 : public IGpLogDriver
+{
+public:
+ GpLogDriver_Win32();
+
+ static void Init();
+
+ void VPrintf(Category category, const char *fmt, va_list args) override;
+ void Shutdown() override;
+
+ static GpLogDriver_Win32 *GetInstance();
+
+private:
+ void InitInternal();
+
+ PortabilityLayer::IOStream *m_stream;
+ bool m_isInitialized;
+
+ static GpLogDriver_Win32 ms_instance;
+};
diff --git a/Aerofoil/GpMain.cpp b/Aerofoil/GpMain.cpp
index 0ff86b2..bc04ced 100644
--- a/Aerofoil/GpMain.cpp
+++ b/Aerofoil/GpMain.cpp
@@ -63,6 +63,7 @@ int GpMain::Run()
ddProps.m_type = g_gpGlobalConfig.m_displayDriverType;
ddProps.m_osGlobals = g_gpGlobalConfig.m_osGlobals;
ddProps.m_eventQueue = eventQueue;
+ ddProps.m_logger = g_gpGlobalConfig.m_logger;
GpAudioDriverProperties adProps;
memset(&adProps, 0, sizeof(adProps));
@@ -72,10 +73,11 @@ int GpMain::Run()
adProps.m_type = g_gpGlobalConfig.m_audioDriverType;
adProps.m_sampleRate = (244800 * 2 + 11) / (11 * 2);
#ifdef NDEBUG
- adProps.m_debug = true;
-#else
adProps.m_debug = false;
+#else
+ adProps.m_debug = true;
#endif
+ adProps.m_logger = g_gpGlobalConfig.m_logger;
IGpInputDriver **inputDrivers = static_cast(malloc(sizeof(IGpInputDriver*) * g_gpGlobalConfig.m_numInputDrivers));
diff --git a/Aerofoil/GpMain_Win32.cpp b/Aerofoil/GpMain_Win32.cpp
index 94175d4..b37af5e 100644
--- a/Aerofoil/GpMain_Win32.cpp
+++ b/Aerofoil/GpMain_Win32.cpp
@@ -5,6 +5,7 @@
#include "GpGlobalConfig.h"
#include "GpFiber_Win32.h"
#include "GpFileSystem_Win32.h"
+#include "GpLogDriver_Win32.h"
#include "GpInputDriverFactory.h"
#include "GpAppInterface.h"
#include "GpSystemServices_Win32.h"
@@ -17,6 +18,7 @@
#include "resource.h"
+#include
#include
#include
@@ -394,12 +396,28 @@ static void TranslateWindowsMessage(const MSG *msg, IGpVOSEventQueue *eventQueue
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
+ LPWSTR cmdLine = GetCommandLineW();
+
+ int nArgs;
+ LPWSTR *cmdLineArgs = CommandLineToArgvW(cmdLine, &nArgs);
+
+ for (int i = 1; i < nArgs; i++)
+ {
+ if (!wcscmp(cmdLineArgs[i], L"-diagnostics"))
+ GpLogDriver_Win32::Init();
+ }
+
+ IGpLogDriver *logger = GpLogDriver_Win32::GetInstance();
+
GpAppInterface_Get()->PL_HostFileSystem_SetInstance(GpFileSystem_Win32::GetInstance());
GpAppInterface_Get()->PL_HostSystemServices_SetInstance(GpSystemServices_Win32::GetInstance());
+ GpAppInterface_Get()->PL_HostLogDriver_SetInstance(GpLogDriver_Win32::GetInstance());
g_gpWindowsGlobals.m_hInstance = hInstance;
g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance;
- g_gpWindowsGlobals.m_cmdLine = lpCmdLine;
+ g_gpWindowsGlobals.m_cmdLine = cmdLine;
+ g_gpWindowsGlobals.m_cmdLineArgc = nArgs;
+ g_gpWindowsGlobals.m_cmdLineArgv = cmdLineArgs;
g_gpWindowsGlobals.m_nCmdShow = nCmdShow;
g_gpWindowsGlobals.m_baseDir = GpFileSystem_Win32::GetInstance()->GetBasePath();
g_gpWindowsGlobals.m_hwnd = nullptr;
@@ -422,10 +440,21 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
g_gpGlobalConfig.m_numInputDrivers = sizeof(inputDrivers) / sizeof(inputDrivers[0]);
g_gpGlobalConfig.m_osGlobals = &g_gpWindowsGlobals;
+ g_gpGlobalConfig.m_logger = logger;
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_D3D11, GpDriver_CreateDisplayDriver_D3D11);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_XAudio2, GpDriver_CreateAudioDriver_XAudio2);
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_XInput, GpDriver_CreateInputDriver_XInput);
- return GpMain::Run();
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Information, "Windows environment configured, starting up");
+
+ int returnCode = GpMain::Run();
+
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Information, "Windows environment exited with code %i, cleaning up", returnCode);
+
+ LocalFree(cmdLineArgs);
+
+ return returnCode;
}
diff --git a/GpApp/GpAppInterface.cpp b/GpApp/GpAppInterface.cpp
index df6c90c..e1369e5 100644
--- a/GpApp/GpAppInterface.cpp
+++ b/GpApp/GpAppInterface.cpp
@@ -5,6 +5,7 @@
#include "HostFileSystem.h"
#include "HostFontHandler.h"
#include "HostDisplayDriver.h"
+#include "HostLogDriver.h"
#include "HostSystemServices.h"
#include "HostVOSEventQueue.h"
#include "MenuManager.h"
@@ -22,6 +23,7 @@ public:
void PL_HostDisplayDriver_SetInstance(IGpDisplayDriver *instance) override;
void PL_HostSystemServices_SetInstance(PortabilityLayer::HostSystemServices *instance) override;
void PL_HostAudioDriver_SetInstance(IGpAudioDriver *instance) override;
+ void PL_HostLogDriver_SetInstance(IGpLogDriver *instance) override;
void PL_HostFontHandler_SetInstance(PortabilityLayer::HostFontHandler *instance) override;
void PL_HostVOSEventQueue_SetInstance(PortabilityLayer::HostVOSEventQueue *instance) override;
void PL_InstallHostSuspendHook(PortabilityLayer::HostSuspendHook_t hook, void *context) override;
@@ -55,6 +57,11 @@ void GpAppInterfaceImpl::PL_HostDisplayDriver_SetInstance(IGpDisplayDriver *inst
PortabilityLayer::HostDisplayDriver::SetInstance(instance);
}
+void GpAppInterfaceImpl::PL_HostLogDriver_SetInstance(IGpLogDriver *instance)
+{
+ PortabilityLayer::HostLogDriver::SetInstance(instance);
+}
+
void GpAppInterfaceImpl::PL_HostSystemServices_SetInstance(PortabilityLayer::HostSystemServices *instance)
{
PortabilityLayer::HostSystemServices::SetInstance(instance);
diff --git a/GpAudioDriver_XAudio2/GpAudioChannelXAudio2.cpp b/GpAudioDriver_XAudio2/GpAudioChannelXAudio2.cpp
index fc5df4c..54a13d0 100644
--- a/GpAudioDriver_XAudio2/GpAudioChannelXAudio2.cpp
+++ b/GpAudioDriver_XAudio2/GpAudioChannelXAudio2.cpp
@@ -1,19 +1,30 @@
#include "GpAudioChannelXAudio2.h"
#include "GpAudioDriverXAudio2.h"
#include "IGpAudioChannelCallbacks.h"
+#include "IGpLogDriver.h"
#include
#include
GpAudioChannelXAudio2 *GpAudioChannelXAudio2::Create(GpAudioDriverXAudio2 *driver)
{
+ IGpLogDriver *logger = driver->GetProperties().m_logger;
+
void *storage = malloc(sizeof(GpAudioChannelXAudio2));
if (!storage)
+ {
+ if (!logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpAudioChannelXAudio2::Create failed, malloc failed");
+
return nullptr;
+ }
GpAudioChannelXAudio2 *channel = new (storage) GpAudioChannelXAudio2(driver);
if (!channel->Init())
{
+ if (!logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpAudioChannelXAudio2::Init failed");
+
channel->Destroy();
return nullptr;
}
@@ -23,6 +34,8 @@ GpAudioChannelXAudio2 *GpAudioChannelXAudio2::Create(GpAudioDriverXAudio2 *drive
bool GpAudioChannelXAudio2::Init()
{
+ IGpLogDriver *logger = m_driver->GetProperties().m_logger;
+
const unsigned int sampleRate = m_driver->GetRealSampleRate();
IXAudio2 *const xa2 = m_driver->GetXA2();
@@ -49,7 +62,12 @@ bool GpAudioChannelXAudio2::Init()
HRESULT hr = xa2->CreateSourceVoice(&m_sourceVoice, &format, XAUDIO2_VOICE_NOPITCH | XAUDIO2_VOICE_NOSRC, 1.0f, &m_xAudioCallbacks, nullptr, nullptr);
if (hr != S_OK)
+ {
+ if (!logger)
+ logger->Printf(IGpLogDriver::Category_Error, "CreateSourceVoice failed with code %lx", hr);
+
return false;
+ }
return true;
}
diff --git a/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.cpp b/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.cpp
index fb2a8ac..5fabe56 100644
--- a/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.cpp
+++ b/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.cpp
@@ -1,5 +1,6 @@
#include "GpAudioDriverXAudio2.h"
+#include "IGpLogDriver.h"
#include "GpAudioChannelXAudio2.h"
#include
@@ -31,34 +32,62 @@ unsigned int GpAudioDriverXAudio2::GetRealSampleRate() const
GpAudioDriverXAudio2 *GpAudioDriverXAudio2::Create(const GpAudioDriverProperties &properties)
{
+ IGpLogDriver *logger = properties.m_logger;
+
IXAudio2 *xa = nullptr;
IXAudio2MasteringVoice *mv = nullptr;
const unsigned int realSampleRate = (properties.m_sampleRate + 50) / XAUDIO2_QUANTUM_DENOMINATOR * XAUDIO2_QUANTUM_DENOMINATOR;
- if (CoInitializeEx(nullptr, COINIT_MULTITHREADED) != S_OK)
+ if (logger)
{
+ logger->Printf(IGpLogDriver::Category_Information, "XAudio2 Driver starting");
+ logger->Printf(IGpLogDriver::Category_Information, "Real sample rate: %u", realSampleRate);
+ }
+
+ HRESULT result = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
+ if (result != S_OK)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "CoInitializeEx failed with code %lx", result);
+
CoUninitialize();
return nullptr;
}
UINT flags = 0;
if (properties.m_debug)
- flags |= XAUDIO2_DEBUG_ENGINE;
-
- if (FAILED(XAudio2Create(&xa, flags, XAUDIO2_DEFAULT_PROCESSOR)))
{
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Information, "Starting XAudio in debug mode");
+
+ flags |= XAUDIO2_DEBUG_ENGINE;
+ }
+
+ result = XAudio2Create(&xa, flags, XAUDIO2_DEFAULT_PROCESSOR);
+ if (FAILED(result))
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "XAudio2Create failed with code %lx", result);
+
CoUninitialize();
return nullptr;
}
- if (FAILED(xa->CreateMasteringVoice(&mv, 2, realSampleRate, 0, nullptr, nullptr, AudioCategory_GameEffects)))
+ result = xa->CreateMasteringVoice(&mv, 2, realSampleRate, 0, nullptr, nullptr, AudioCategory_GameEffects);
+ if (FAILED(result))
{
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "CreateMasteringVoice failed with code %lx", result);
+
CoUninitialize();
xa->Release();
return nullptr;
}
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Information, "XAudio2 started OK", result);
+
return new GpAudioDriverXAudio2(properties, realSampleRate, xa, mv);
}
diff --git a/GpCommon/GpAudioDriverProperties.h b/GpCommon/GpAudioDriverProperties.h
index 72904db..9f802cd 100644
--- a/GpCommon/GpAudioDriverProperties.h
+++ b/GpCommon/GpAudioDriverProperties.h
@@ -3,6 +3,7 @@
#include "EGpAudioDriverType.h"
struct IGpAudioDriver;
+struct IGpLogDriver;
struct GpAudioDriverProperties
{
@@ -10,4 +11,6 @@ struct GpAudioDriverProperties
unsigned int m_sampleRate;
bool m_debug;
+
+ IGpLogDriver *m_logger;
};
diff --git a/GpCommon/GpDisplayDriverProperties.h b/GpCommon/GpDisplayDriverProperties.h
index 24d3ab7..77c8f2d 100644
--- a/GpCommon/GpDisplayDriverProperties.h
+++ b/GpCommon/GpDisplayDriverProperties.h
@@ -8,6 +8,7 @@
struct IGpDisplayDriver;
struct IGpFiber;
struct IGpVOSEventQueue;
+struct IGpLogDriver;
struct GpDisplayDriverProperties
{
@@ -39,4 +40,5 @@ struct GpDisplayDriverProperties
void *m_adjustRequestedResolutionFuncContext;
IGpVOSEventQueue *m_eventQueue;
+ IGpLogDriver *m_logger;
};
diff --git a/GpCommon/GpWindows.h b/GpCommon/GpWindows.h
index a9d05fd..e7b8672 100644
--- a/GpCommon/GpWindows.h
+++ b/GpCommon/GpWindows.h
@@ -19,7 +19,9 @@ struct GpWindowsGlobals
{
HINSTANCE m_hInstance;
HINSTANCE m_hPrevInstance;
- LPCSTR m_cmdLine;
+ LPCWSTR m_cmdLine;
+ int m_cmdLineArgc;
+ LPWSTR *m_cmdLineArgv;
LPCWSTR m_baseDir;
HWND m_hwnd;
HICON m_hIcon;
diff --git a/GpCommon/IGpLogDriver.h b/GpCommon/IGpLogDriver.h
new file mode 100644
index 0000000..a369765
--- /dev/null
+++ b/GpCommon/IGpLogDriver.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include
+#include
+
+struct IGpLogDriver
+{
+ enum Category
+ {
+ Category_Information,
+ Category_Warning,
+ Category_Error,
+ };
+
+ virtual void VPrintf(Category category, const char *fmt, va_list args) = 0;
+ virtual void Shutdown() = 0;
+
+ void Printf(Category category, const char *fmt, ...);
+};
+
+
+inline void IGpLogDriver::Printf(Category category, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ this->VPrintf(category, fmt, args);
+ va_end(args);
+}
diff --git a/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp b/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp
index 176d259..f6aa34a 100644
--- a/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp
+++ b/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp
@@ -7,6 +7,8 @@
#include "IGpFiber.h"
#include "IGpVOSEventQueue.h"
+#include "IGpLogDriver.h"
+
#include
#include
#include
@@ -125,7 +127,7 @@ bool ResizeSwapChain(IDXGISwapChain1 *swapChain, UINT width, UINT height)
return true;
}
-void StartD3DForWindow(HWND hWnd, GpComPtr& outSwapChain, GpComPtr& outDevice, GpComPtr& outContext)
+void StartD3DForWindow(HWND hWnd, GpComPtr& outSwapChain, GpComPtr& outDevice, GpComPtr& outContext, IGpLogDriver *logger)
{
DXGI_SWAP_CHAIN_FULLSCREEN_DESC swapChainFullscreenDesc;
@@ -153,6 +155,14 @@ void StartD3DForWindow(HWND hWnd, GpComPtr& outSwapChain, GpCom
HRESULT result = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, featureLevels, sizeof(featureLevels) / sizeof(featureLevels[0]),
D3D11_SDK_VERSION, &device, &selectedFeatureLevel, &context);
+ if (logger)
+ {
+ if (result == S_OK)
+ logger->Printf(IGpLogDriver::Category_Information, "StartD3DForWindow: D3D11CreateDevice succeeded. Selected feature level is %i", static_cast(selectedFeatureLevel));
+ else
+ logger->Printf(IGpLogDriver::Category_Error, "StartD3DForWindow: D3D11CreateDevice failed with code %lx", result);
+ }
+
InitSwapChainForWindow(hWnd, device, outSwapChain);
// GP TODO: Fix the error handling here, it's bad...
@@ -160,8 +170,11 @@ void StartD3DForWindow(HWND hWnd, GpComPtr& outSwapChain, GpCom
outContext = context;
}
-bool ResizeD3DWindow(HWND hWnd, DWORD &windowWidth, DWORD &windowHeight, LONG desiredWidth, LONG desiredHeight, DWORD windowStyle, HMENU menus)
+bool ResizeD3DWindow(HWND hWnd, DWORD &windowWidth, DWORD &windowHeight, LONG desiredWidth, LONG desiredHeight, DWORD windowStyle, HMENU menus, IGpLogDriver *logger)
{
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Information, "ResizeD3DWindow: %i x %i", static_cast(desiredWidth), static_cast(desiredHeight));
+
if (desiredWidth < 640)
desiredWidth = 640;
else if (desiredWidth > MAXDWORD)
@@ -172,6 +185,9 @@ bool ResizeD3DWindow(HWND hWnd, DWORD &windowWidth, DWORD &windowHeight, LONG de
else if (desiredHeight > MAXDWORD)
desiredHeight = MAXDWORD;
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Information, "ResizeD3DWindow: Adjusted dimensions: %i x %i", static_cast(desiredWidth), static_cast(desiredHeight));
+
RECT windowRect;
GetClientRect(hWnd, &windowRect);
windowRect.right = windowRect.left + desiredWidth;
@@ -180,9 +196,20 @@ bool ResizeD3DWindow(HWND hWnd, DWORD &windowWidth, DWORD &windowHeight, LONG de
LONG_PTR style = GetWindowLongPtrA(hWnd, GWL_STYLE);
if (!AdjustWindowRect(&windowRect, static_cast(style), menus != nullptr))
- return false;
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "ResizeD3DWindow: AdjustWindowRect failed");
- SetWindowPos(hWnd, HWND_TOP, windowRect.left, windowRect.top, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, SWP_NOZORDER | SWP_NOMOVE);
+ return false;
+ }
+
+ if (!SetWindowPos(hWnd, HWND_TOP, windowRect.left, windowRect.top, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, SWP_NOZORDER | SWP_NOMOVE))
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "ResizeD3DWindow: SetWindowPos failed");
+
+ return false;
+ }
windowWidth = desiredWidth;
windowHeight = desiredHeight;
@@ -192,6 +219,11 @@ bool ResizeD3DWindow(HWND hWnd, DWORD &windowWidth, DWORD &windowHeight, LONG de
bool GpDisplayDriverD3D11::DetachSwapChain()
{
+ IGpLogDriver *logger = m_properties.m_logger;
+
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Information, "GpDisplayDriverD3D11::DetachSwapChain");
+
m_deviceContext->OMSetRenderTargets(0, nullptr, nullptr);
m_backBufferRTV = nullptr;
m_backBufferTexture = nullptr;
@@ -204,6 +236,11 @@ bool GpDisplayDriverD3D11::DetachSwapChain()
bool GpDisplayDriverD3D11::InitBackBuffer(uint32_t virtualWidth, uint32_t virtualHeight)
{
+ IGpLogDriver *logger = m_properties.m_logger;
+
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Information, "GpDisplayDriverD3D11::InitBackBuffer");
+
m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast(m_backBufferTexture.GetMutablePtr()));
{
@@ -216,8 +253,14 @@ bool GpDisplayDriverD3D11::InitBackBuffer(uint32_t virtualWidth, uint32_t virtua
rtvDesc.Texture2D.MipSlice = 0;
m_backBufferRTV = nullptr;
- if (m_device->CreateRenderTargetView(m_backBufferTexture, &rtvDesc, m_backBufferRTV.GetMutablePtr()) != S_OK)
+ HRESULT result = m_device->CreateRenderTargetView(m_backBufferTexture, &rtvDesc, m_backBufferRTV.GetMutablePtr());
+ if (result != S_OK)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::InitBackBuffer: CreateRenderTargetView for back buffer failed with code %lx", result);
+
return false;
+ }
}
DXGI_FORMAT vbbFormat = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
@@ -237,8 +280,14 @@ bool GpDisplayDriverD3D11::InitBackBuffer(uint32_t virtualWidth, uint32_t virtua
vbbTextureDesc.MiscFlags = 0;
m_virtualScreenTexture = nullptr;
- if (m_device->CreateTexture2D(&vbbTextureDesc, nullptr, m_virtualScreenTexture.GetMutablePtr()) != S_OK)
+ HRESULT result = m_device->CreateTexture2D(&vbbTextureDesc, nullptr, m_virtualScreenTexture.GetMutablePtr());
+ if (result != S_OK)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::InitBackBuffer: CreateTexture2D for virtual screen texture failed with code %lx", result);
+
return false;
+ }
}
{
@@ -248,8 +297,14 @@ bool GpDisplayDriverD3D11::InitBackBuffer(uint32_t virtualWidth, uint32_t virtua
rtvDesc.Texture2D.MipSlice = 0;
m_virtualScreenTextureRTV = nullptr;
- if (m_device->CreateRenderTargetView(m_virtualScreenTexture, &rtvDesc, m_virtualScreenTextureRTV.GetMutablePtr()) != S_OK)
+ HRESULT result = m_device->CreateRenderTargetView(m_virtualScreenTexture, &rtvDesc, m_virtualScreenTextureRTV.GetMutablePtr());
+ if (result != S_OK)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::InitBackBuffer: CreateRenderTargetView for virtual screen texture failed with code %lx", result);
+
return false;
+ }
}
{
@@ -260,8 +315,14 @@ bool GpDisplayDriverD3D11::InitBackBuffer(uint32_t virtualWidth, uint32_t virtua
srvDesc.Texture2D.MostDetailedMip = 0;
m_virtualScreenTextureSRV = nullptr;
- if (m_device->CreateShaderResourceView(m_virtualScreenTexture, &srvDesc, m_virtualScreenTextureSRV.GetMutablePtr()) != S_OK)
+ HRESULT result = m_device->CreateShaderResourceView(m_virtualScreenTexture, &srvDesc, m_virtualScreenTextureSRV.GetMutablePtr());
+ if (result != S_OK)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::InitBackBuffer: CreateRenderTargetView for virtual screen texture failed with code %lx", result);
+
return false;
+ }
}
return true;
@@ -269,6 +330,11 @@ bool GpDisplayDriverD3D11::InitBackBuffer(uint32_t virtualWidth, uint32_t virtua
bool GpDisplayDriverD3D11::InitResources(uint32_t virtualWidth, uint32_t virtualHeight)
{
+ IGpLogDriver *logger = m_properties.m_logger;
+
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Information, "GpDisplayDriverD3D11::InitResources");
+
if (!InitBackBuffer(virtualWidth, virtualHeight))
return false;
@@ -282,8 +348,14 @@ bool GpDisplayDriverD3D11::InitResources(uint32_t virtualWidth, uint32_t virtual
bufferDesc.MiscFlags = 0;
bufferDesc.StructureByteStride = 0;
- if (m_device->CreateBuffer(&bufferDesc, nullptr, m_drawQuadVertexConstantBuffer.GetMutablePtr()) != S_OK)
+ HRESULT result = m_device->CreateBuffer(&bufferDesc, nullptr, m_drawQuadVertexConstantBuffer.GetMutablePtr());
+ if (result != S_OK)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::InitResources: CreateBuffer for draw quad vertex constant buffer failed with code %lx", result);
+
return false;
+ }
}
// Quad pixel constant buffer
@@ -296,8 +368,14 @@ bool GpDisplayDriverD3D11::InitResources(uint32_t virtualWidth, uint32_t virtual
bufferDesc.MiscFlags = 0;
bufferDesc.StructureByteStride = 0;
- if (m_device->CreateBuffer(&bufferDesc, nullptr, m_drawQuadPixelConstantBuffer.GetMutablePtr()) != S_OK)
+ HRESULT result = m_device->CreateBuffer(&bufferDesc, nullptr, m_drawQuadPixelConstantBuffer.GetMutablePtr());
+ if (result != S_OK)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::InitResources: CreateBuffer for draw quad pixel constant buffer failed with code %lx", result);
+
return false;
+ }
}
// Quad index buffer
@@ -317,8 +395,14 @@ bool GpDisplayDriverD3D11::InitResources(uint32_t virtualWidth, uint32_t virtual
initialData.SysMemPitch = 0;
initialData.SysMemSlicePitch = 0;
- if (m_device->CreateBuffer(&bufferDesc, &initialData, m_quadIndexBuffer.GetMutablePtr()) != S_OK)
+ HRESULT result = m_device->CreateBuffer(&bufferDesc, &initialData, m_quadIndexBuffer.GetMutablePtr());
+ if (result != S_OK)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::InitResources: CreateBuffer for draw quad index buffer failed with code %lx", result);
+
return false;
+ }
}
// Quad vertex buffer
@@ -344,8 +428,14 @@ bool GpDisplayDriverD3D11::InitResources(uint32_t virtualWidth, uint32_t virtual
initialData.SysMemPitch = 0;
initialData.SysMemSlicePitch = 0;
- if (m_device->CreateBuffer(&bufferDesc, &initialData, m_quadVertexBuffer.GetMutablePtr()) != S_OK)
+ HRESULT result = m_device->CreateBuffer(&bufferDesc, &initialData, m_quadVertexBuffer.GetMutablePtr());
+ if (result != S_OK)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::InitResources: CreateBuffer for draw quad vertex buffer failed with code %lx", result);
+
return false;
+ }
}
{
@@ -357,8 +447,14 @@ bool GpDisplayDriverD3D11::InitResources(uint32_t virtualWidth, uint32_t virtual
bufferDesc.MiscFlags = 0;
bufferDesc.StructureByteStride = 0;
- if (m_device->CreateBuffer(&bufferDesc, nullptr, m_scaleQuadPixelConstantBuffer.GetMutablePtr()) != S_OK)
+ HRESULT result = m_device->CreateBuffer(&bufferDesc, nullptr, m_scaleQuadPixelConstantBuffer.GetMutablePtr());
+ if (result != S_OK)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::InitResources: CreateBuffer for scale quad pixel constant buffer failed with code %lx", result);
+
return false;
+ }
}
const GpShaderCodeBlob drawQuadVBlob = GetBinarizedShader(GpBinarizedShaders::g_drawQuadV_D3D11);
@@ -386,7 +482,14 @@ bool GpDisplayDriverD3D11::InitResources(uint32_t virtualWidth, uint32_t virtual
0 // Instance data step rate
};
- m_device->CreateInputLayout(descs, sizeof(descs) / sizeof(descs[0]), drawQuadVBlob.m_data, drawQuadVBlob.m_size, m_drawQuadInputLayout.GetMutablePtr());
+ HRESULT result = m_device->CreateInputLayout(descs, sizeof(descs) / sizeof(descs[0]), drawQuadVBlob.m_data, drawQuadVBlob.m_size, m_drawQuadInputLayout.GetMutablePtr());
+ if (result != S_OK)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::InitResources: CreateInputLayout for draw quad input failed with code %lx", result);
+
+ return false;
+ }
}
// Quad depth stencil state
@@ -407,8 +510,14 @@ bool GpDisplayDriverD3D11::InitResources(uint32_t virtualWidth, uint32_t virtual
desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
- if (m_device->CreateDepthStencilState(&desc, m_drawQuadDepthStencilState.GetMutablePtr()) != S_OK)
+ HRESULT result = m_device->CreateDepthStencilState(&desc, m_drawQuadDepthStencilState.GetMutablePtr());
+ if (result != S_OK)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::InitResources: CreateDepthStencilState for draw quad with code %lx", result);
+
return false;
+ }
}
// Nearest neighbor sampler desc
@@ -425,8 +534,14 @@ bool GpDisplayDriverD3D11::InitResources(uint32_t virtualWidth, uint32_t virtual
samplerDesc.MinLOD = -FLT_MAX;
samplerDesc.MaxLOD = FLT_MAX;
- if (m_device->CreateSamplerState(&samplerDesc, m_nearestNeighborSamplerState.GetMutablePtr()) != S_OK)
+ HRESULT result = m_device->CreateSamplerState(&samplerDesc, m_nearestNeighborSamplerState.GetMutablePtr());
+ if (result != S_OK)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::InitResources: CreateSamplerState for nearest neighbor failed with code %lx", result);
+
return false;
+ }
}
DXGI_FORMAT paletteTextureFormat = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
@@ -455,8 +570,14 @@ bool GpDisplayDriverD3D11::InitResources(uint32_t virtualWidth, uint32_t virtual
initialData.SysMemPitch = 256 * 4;
initialData.SysMemSlicePitch = 256 * 4;
- if (m_device->CreateTexture1D(&desc, &initialData, m_paletteTexture.GetMutablePtr()) != S_OK)
+ HRESULT result = m_device->CreateTexture1D(&desc, &initialData, m_paletteTexture.GetMutablePtr());
+ if (result != S_OK)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::InitResources: CreateTexture1D for palette failed with code %lx", result);
+
return false;
+ }
}
// Palette texture SRV
@@ -467,8 +588,14 @@ bool GpDisplayDriverD3D11::InitResources(uint32_t virtualWidth, uint32_t virtual
desc.Texture1D.MostDetailedMip = 0;
desc.Texture1D.MipLevels = 1;
- if (m_device->CreateShaderResourceView(m_paletteTexture, &desc, m_paletteTextureSRV.GetMutablePtr()) != S_OK)
+ HRESULT result = m_device->CreateShaderResourceView(m_paletteTexture, &desc, m_paletteTextureSRV.GetMutablePtr());
+ if (result != S_OK)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::InitResources: CreateShaderResourceView for palette failed with code %lx", result);
+
return false;
+ }
}
return true;
@@ -791,11 +918,21 @@ void GpDisplayDriverD3D11::ChangeToStandardCursor(EGpStandardCursor_t cursor)
void GpDisplayDriverD3D11::BecomeFullScreen(LONG &windowStyle)
{
+ IGpLogDriver *logger = m_properties.m_logger;
+
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Information, "GpDisplayDriverD3D11::BecomeFullScreen");
+
assert(!m_isFullScreen);
RECT windowRect;
if (!GetWindowRect(m_osGlobals->m_hwnd, &windowRect))
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::BecomeFullScreen: GetWindowRect failed");
+
return; // ???
+ }
HMONITOR monitor = MonitorFromRect(&windowRect, MONITOR_DEFAULTTONULL);
if (!monitor)
@@ -810,17 +947,31 @@ void GpDisplayDriverD3D11::BecomeFullScreen(LONG &windowStyle)
}
if (!monitor)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::BecomeFullScreen: Couldn't find any monitors");
+
return; // No monitor?
+ }
MONITORINFO monitorInfo;
monitorInfo.cbSize = sizeof(monitorInfo);
if (!GetMonitorInfoA(monitor, &monitorInfo))
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::BecomeFullScreen: GetMonitorInfoA failed");
+
return;
+ }
m_windowModeRevertRect = windowRect;
SetWindowLongPtr(m_osGlobals->m_hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
- SetWindowPos(m_osGlobals->m_hwnd, HWND_TOP, monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top, monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top, SWP_FRAMECHANGED);
+ if (!SetWindowPos(m_osGlobals->m_hwnd, HWND_TOP, monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top, monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top, SWP_FRAMECHANGED))
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::BecomeFullScreen: SetWindowPos failed");
+ }
m_isFullScreen = true;
windowStyle = (WS_VISIBLE | WS_POPUP);
@@ -828,6 +979,11 @@ void GpDisplayDriverD3D11::BecomeFullScreen(LONG &windowStyle)
void GpDisplayDriverD3D11::BecomeWindowed(LONG &windowStyle)
{
+ IGpLogDriver *logger = m_properties.m_logger;
+
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Information, "GpDisplayDriverD3D11::BecomeWindowed");
+
assert(m_isFullScreen);
RECT revertRect = m_windowModeRevertRect;
@@ -838,12 +994,22 @@ void GpDisplayDriverD3D11::BecomeWindowed(LONG &windowStyle)
// If the window is off-screen, use the primary monitor
monitor = MonitorFromRect(&revertRect, MONITOR_DEFAULTTOPRIMARY);
if (!monitor)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::BecomeWindowed: MonitorFromRect fallback failed");
+
return;
+ }
MONITORINFO monitorInfo;
monitorInfo.cbSize = sizeof(monitorInfo);
if (!GetMonitorInfoA(monitor, &monitorInfo))
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::BecomeWindowed: GetMonitorInfoA failed");
+
return;
+ }
RECT monitorRect = monitorInfo.rcWork;
LONG monitorWidth = monitorRect.right - monitorRect.left;
@@ -880,9 +1046,13 @@ void GpDisplayDriverD3D11::BecomeWindowed(LONG &windowStyle)
revertRect.right = revertRect.right + revertWidth;
}
- SetWindowLongPtr(m_osGlobals->m_hwnd, GWL_STYLE, WS_VISIBLE | WS_OVERLAPPEDWINDOW);
+ SetWindowLongPtrW(m_osGlobals->m_hwnd, GWL_STYLE, WS_VISIBLE | WS_OVERLAPPEDWINDOW);
- SetWindowPos(m_osGlobals->m_hwnd, HWND_TOP, revertRect.left, revertRect.top, revertRect.right - revertRect.left, revertRect.bottom - revertRect.top, SWP_FRAMECHANGED);
+ if (!SetWindowPos(m_osGlobals->m_hwnd, HWND_TOP, revertRect.left, revertRect.top, revertRect.right - revertRect.left, revertRect.bottom - revertRect.top, SWP_FRAMECHANGED))
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriverD3D11::BecomeWindowed: SetWindowPos failed");
+ }
m_isFullScreen = false;
windowStyle = (WS_VISIBLE | WS_OVERLAPPEDWINDOW);
@@ -890,11 +1060,18 @@ void GpDisplayDriverD3D11::BecomeWindowed(LONG &windowStyle)
void GpDisplayDriverD3D11::Run()
{
+ IGpLogDriver *logger = m_properties.m_logger;
+
WNDCLASSEX wc;
LPVOID fiber = ConvertThreadToFiberEx(this, 0);
if (!fiber)
+ {
+ if (logger)
+ logger->Printf(IGpLogDriver::Category_Error, "ConvertThreadToFiberEx failed");
+
return; // ???
+ }
m_vosFiber = m_osGlobals->m_createFiberFunc(fiber);
@@ -923,7 +1100,7 @@ void GpDisplayDriverD3D11::Run()
ShowWindow(m_osGlobals->m_hwnd, m_osGlobals->m_nCmdShow);
- StartD3DForWindow(m_osGlobals->m_hwnd, m_swapChain, m_device, m_deviceContext);
+ StartD3DForWindow(m_osGlobals->m_hwnd, m_swapChain, m_device, m_deviceContext, logger);
InitResources(m_windowWidthVirtual, m_windowHeightVirtual);
@@ -988,7 +1165,7 @@ void GpDisplayDriverD3D11::Run()
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
{
- bool resizedOK = ResizeD3DWindow(m_osGlobals->m_hwnd, m_windowWidthPhysical, m_windowHeightPhysical, desiredWidth, desiredHeight, windowStyle, menus);
+ bool resizedOK = ResizeD3DWindow(m_osGlobals->m_hwnd, m_windowWidthPhysical, m_windowHeightPhysical, desiredWidth, desiredHeight, windowStyle, menus, logger);
resizedOK = resizedOK && DetachSwapChain();
resizedOK = resizedOK && ResizeSwapChain(m_swapChain, m_windowWidthPhysical, m_windowHeightPhysical);
resizedOK = resizedOK && InitBackBuffer(virtualWidth, virtualHeight);
diff --git a/PortabilityLayer/CFileStream.cpp b/PortabilityLayer/CFileStream.cpp
index 11cc4f5..e7fae06 100644
--- a/PortabilityLayer/CFileStream.cpp
+++ b/PortabilityLayer/CFileStream.cpp
@@ -93,8 +93,15 @@ namespace PortabilityLayer
fclose(m_file);
m_file = nullptr;
}
+ }
+
+ void CFileStream::Flush()
+ {
+ if (m_file)
+ fflush(m_file);
}
+
UFilePos_t CFileStream::Size() const
{
if (!m_file || !m_seekable)
diff --git a/PortabilityLayer/CFileStream.h b/PortabilityLayer/CFileStream.h
index 9a42584..2ee6386 100644
--- a/PortabilityLayer/CFileStream.h
+++ b/PortabilityLayer/CFileStream.h
@@ -27,7 +27,8 @@ namespace PortabilityLayer
bool Truncate(UFilePos_t loc) override;
UFilePos_t Size() const override;
UFilePos_t Tell() const override;
- void Close() override;
+ void Close() override;
+ void Flush() override;
private:
CFileStream(const CFileStream &other) GP_DELETED;
diff --git a/PortabilityLayer/GpAppInterface.h b/PortabilityLayer/GpAppInterface.h
index 82a0d67..347742e 100644
--- a/PortabilityLayer/GpAppInterface.h
+++ b/PortabilityLayer/GpAppInterface.h
@@ -20,6 +20,7 @@
#endif
struct IGpAudioDriver;
+struct IGpLogDriver;
namespace PortabilityLayer
{
@@ -41,6 +42,7 @@ public:
virtual void PL_HostAudioDriver_SetInstance(IGpAudioDriver *instance) = 0;
virtual void PL_HostFileSystem_SetInstance(PortabilityLayer::HostFileSystem *instance) = 0;
virtual void PL_HostDisplayDriver_SetInstance(IGpDisplayDriver *instance) = 0;
+ virtual void PL_HostLogDriver_SetInstance(IGpLogDriver *instance) = 0;
virtual void PL_HostSystemServices_SetInstance(PortabilityLayer::HostSystemServices *instance) = 0;
virtual void PL_HostFontHandler_SetInstance(PortabilityLayer::HostFontHandler *instance) = 0;
virtual void PL_HostVOSEventQueue_SetInstance(PortabilityLayer::HostVOSEventQueue *instance) = 0;
diff --git a/PortabilityLayer/HostLogDriver.cpp b/PortabilityLayer/HostLogDriver.cpp
new file mode 100644
index 0000000..1a97863
--- /dev/null
+++ b/PortabilityLayer/HostLogDriver.cpp
@@ -0,0 +1,16 @@
+#include "HostLogDriver.h"
+
+namespace PortabilityLayer
+{
+ void HostLogDriver::SetInstance(IGpLogDriver *instance)
+ {
+ ms_instance = instance;
+ }
+
+ IGpLogDriver *HostLogDriver::GetInstance()
+ {
+ return ms_instance;
+ }
+
+ IGpLogDriver *HostLogDriver::ms_instance;
+}
diff --git a/PortabilityLayer/HostLogDriver.h b/PortabilityLayer/HostLogDriver.h
new file mode 100644
index 0000000..2825d3c
--- /dev/null
+++ b/PortabilityLayer/HostLogDriver.h
@@ -0,0 +1,16 @@
+#pragma once
+
+struct IGpLogDriver;
+
+namespace PortabilityLayer
+{
+ class HostLogDriver
+ {
+ public:
+ static void SetInstance(IGpLogDriver *instance);
+ static IGpLogDriver *GetInstance();
+
+ private:
+ static IGpLogDriver *ms_instance;
+ };
+}
diff --git a/PortabilityLayer/IOStream.h b/PortabilityLayer/IOStream.h
index 6fceee8..df3756d 100644
--- a/PortabilityLayer/IOStream.h
+++ b/PortabilityLayer/IOStream.h
@@ -23,6 +23,7 @@ namespace PortabilityLayer
virtual UFilePos_t Size() const = 0;
virtual UFilePos_t Tell() const = 0;
virtual void Close() = 0;
+ virtual void Flush() = 0;
};
}
diff --git a/PortabilityLayer/MemReaderStream.cpp b/PortabilityLayer/MemReaderStream.cpp
index 651fb71..ac46fef 100644
--- a/PortabilityLayer/MemReaderStream.cpp
+++ b/PortabilityLayer/MemReaderStream.cpp
@@ -107,4 +107,8 @@ namespace PortabilityLayer
void MemReaderStream::Close()
{
}
+
+ void MemReaderStream::Flush()
+ {
+ }
}
diff --git a/PortabilityLayer/MemReaderStream.h b/PortabilityLayer/MemReaderStream.h
index da85259..06476f4 100644
--- a/PortabilityLayer/MemReaderStream.h
+++ b/PortabilityLayer/MemReaderStream.h
@@ -24,6 +24,7 @@ namespace PortabilityLayer
UFilePos_t Size() const override;
UFilePos_t Tell() const override;
void Close() override;
+ void Flush() override;
private:
MemReaderStream() GP_DELETED;
diff --git a/PortabilityLayer/PortabilityLayer.vcxproj b/PortabilityLayer/PortabilityLayer.vcxproj
index 59a7612..398047c 100644
--- a/PortabilityLayer/PortabilityLayer.vcxproj
+++ b/PortabilityLayer/PortabilityLayer.vcxproj
@@ -176,6 +176,7 @@
+
@@ -321,6 +322,7 @@
+
diff --git a/PortabilityLayer/PortabilityLayer.vcxproj.filters b/PortabilityLayer/PortabilityLayer.vcxproj.filters
index a31cc02..3c054e7 100644
--- a/PortabilityLayer/PortabilityLayer.vcxproj.filters
+++ b/PortabilityLayer/PortabilityLayer.vcxproj.filters
@@ -483,6 +483,9 @@
Header Files
+
+ Header Files
+
@@ -758,5 +761,8 @@
Source Files
+
+ Source Files
+
\ No newline at end of file
diff --git a/PortabilityLayer/VirtualDirectory.h b/PortabilityLayer/VirtualDirectory.h
index a29ece5..344b1cc 100644
--- a/PortabilityLayer/VirtualDirectory.h
+++ b/PortabilityLayer/VirtualDirectory.h
@@ -16,6 +16,7 @@ namespace PortabilityLayer
kFonts,
kCursors,
kHighScores,
+ kLogs,
};
}