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, }; }