diff --git a/Aerofoil.sln b/Aerofoil.sln index 29fe237..f40e54d 100644 --- a/Aerofoil.sln +++ b/Aerofoil.sln @@ -49,6 +49,7 @@ Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "ReleasePackageInstaller", " {B852D549-4020-4477-8BFB-E199FF78B047} = {B852D549-4020-4477-8BFB-E199FF78B047} {2FF15659-5C72-48B8-B55B-3C658E4125B5} = {2FF15659-5C72-48B8-B55B-3C658E4125B5} {3B7FD18D-7A50-4DF5-AC25-543E539BFACE} = {3B7FD18D-7A50-4DF5-AC25-543E539BFACE} + {B31BFF9D-2D14-4B1A-A625-8348CC3D8D67} = {B31BFF9D-2D14-4B1A-A625-8348CC3D8D67} {36DAF5FA-6ADB-4F20-9810-1610DE0AE653} = {36DAF5FA-6ADB-4F20-9810-1610DE0AE653} EndProjectSection EndProject @@ -68,6 +69,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GenerateFonts", "GenerateFo EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bin2h", "bin2h\bin2h.vcxproj", "{D045F28D-F245-44DD-B576-CC91BF3BE6E9}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HouseTool", "HouseTool\HouseTool.vcxproj", "{B31BFF9D-2D14-4B1A-A625-8348CC3D8D67}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -188,6 +191,10 @@ Global {D045F28D-F245-44DD-B576-CC91BF3BE6E9}.Debug|x64.Build.0 = Debug|x64 {D045F28D-F245-44DD-B576-CC91BF3BE6E9}.Release|x64.ActiveCfg = Release|x64 {D045F28D-F245-44DD-B576-CC91BF3BE6E9}.Release|x64.Build.0 = Release|x64 + {B31BFF9D-2D14-4B1A-A625-8348CC3D8D67}.Debug|x64.ActiveCfg = Debug|x64 + {B31BFF9D-2D14-4B1A-A625-8348CC3D8D67}.Debug|x64.Build.0 = Debug|x64 + {B31BFF9D-2D14-4B1A-A625-8348CC3D8D67}.Release|x64.ActiveCfg = Release|x64 + {B31BFF9D-2D14-4B1A-A625-8348CC3D8D67}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Aerofoil/Aerofoil.vcxproj b/Aerofoil/Aerofoil.vcxproj index 074ea6e..9a46344 100644 --- a/Aerofoil/Aerofoil.vcxproj +++ b/Aerofoil/Aerofoil.vcxproj @@ -43,6 +43,7 @@ + @@ -52,6 +53,7 @@ + @@ -82,6 +84,7 @@ + diff --git a/Aerofoil/Aerofoil.vcxproj.filters b/Aerofoil/Aerofoil.vcxproj.filters index ded91bd..6e8d027 100644 --- a/Aerofoil/Aerofoil.vcxproj.filters +++ b/Aerofoil/Aerofoil.vcxproj.filters @@ -28,6 +28,9 @@ Source Files + + Source Files + diff --git a/Aerofoil/GpBWCursor_Win32.cpp b/Aerofoil/GpBWCursor_Win32.cpp index da4a07e..01d1cd9 100644 --- a/Aerofoil/GpBWCursor_Win32.cpp +++ b/Aerofoil/GpBWCursor_Win32.cpp @@ -21,6 +21,7 @@ #include "GpBWCursor_Win32.h" #include "GpWindows.h" +#include "IGpAllocator.h" #include #include @@ -34,19 +35,19 @@ void GpBWCursor_Win32::Destroy() this->DecRef(); } -IGpCursor_Win32 *GpBWCursor_Win32::Create(size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY) +IGpCursor_Win32 *GpBWCursor_Win32::Create(IGpAllocator *alloc, size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY) { size_t numBits = width * height; - size_t numBytes = (width * height + 7) / 8; - uint8_t *convertedAndData = static_cast(malloc(numBytes)); - uint8_t *convertedXorData = static_cast(malloc(numBytes)); + size_t numBytes = (numBits + 7) / 8; + uint8_t *convertedAndData = static_cast(alloc->Alloc(numBytes)); + uint8_t *convertedXorData = static_cast(alloc->Alloc(numBytes)); if (!convertedAndData || !convertedXorData) { if (convertedAndData) - free(convertedAndData); + alloc->Release(convertedAndData); if (convertedXorData) - free(convertedXorData); + alloc->Release(convertedXorData); return nullptr; } @@ -62,25 +63,26 @@ IGpCursor_Win32 *GpBWCursor_Win32::Create(size_t width, size_t height, const voi HCURSOR hcursor = CreateCursor(g_gpWindowsGlobals.m_hInstance, static_cast(hotSpotX), static_cast(hotSpotY), static_cast(width), static_cast(height), convertedAndData, convertedXorData); - free(convertedAndData); - free(convertedXorData); + alloc->Release(convertedAndData); + alloc->Release(convertedXorData); if (!hcursor) return nullptr; - void *storage = malloc(sizeof(GpBWCursor_Win32)); + void *storage = alloc->Alloc(sizeof(GpBWCursor_Win32)); if (!storage) { DestroyCursor(hcursor); return nullptr; } - return new (storage) GpBWCursor_Win32(hcursor); + return new (storage) GpBWCursor_Win32(hcursor, alloc); } -GpBWCursor_Win32::GpBWCursor_Win32(HCURSOR cursor) +GpBWCursor_Win32::GpBWCursor_Win32(HCURSOR cursor, IGpAllocator *alloc) : m_cursor(cursor) , m_refCount(1) + , m_alloc(alloc) { } @@ -104,7 +106,8 @@ void GpBWCursor_Win32::DecRef() m_refCount--; if (m_refCount == 0) { + IGpAllocator *alloc = m_alloc; this->~GpBWCursor_Win32(); - free(this); + alloc->Release(this); } } diff --git a/Aerofoil/GpBWCursor_Win32.h b/Aerofoil/GpBWCursor_Win32.h index 070bb7b..92958d8 100644 --- a/Aerofoil/GpBWCursor_Win32.h +++ b/Aerofoil/GpBWCursor_Win32.h @@ -3,6 +3,8 @@ #include "IGpCursor_Win32.h" #include "GpWindows.h" +struct IGpAllocator; + class GpBWCursor_Win32 final : public IGpCursor_Win32 { public: @@ -13,12 +15,13 @@ public: void IncRef() override; void DecRef() override; - static IGpCursor_Win32 *Create(size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY); + static IGpCursor_Win32 *Create(IGpAllocator *alloc, size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY); private: - GpBWCursor_Win32(HCURSOR cursor); + GpBWCursor_Win32(HCURSOR cursor, IGpAllocator *alloc); ~GpBWCursor_Win32(); HCURSOR m_cursor; int m_refCount; + IGpAllocator *m_alloc; }; diff --git a/Aerofoil/GpColorCursor_Win32.cpp b/Aerofoil/GpColorCursor_Win32.cpp index 5dbfd84..07dc4be 100644 --- a/Aerofoil/GpColorCursor_Win32.cpp +++ b/Aerofoil/GpColorCursor_Win32.cpp @@ -20,6 +20,7 @@ */ #include "GpColorCursor_Win32.h" +#include "IGpAllocator.h" #include #include @@ -31,7 +32,7 @@ void GpColorCursor_Win32::Destroy() this->DecRef(); } -IGpCursor_Win32 *GpColorCursor_Win32::Create(size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY) +IGpCursor_Win32 *GpColorCursor_Win32::Create(IGpAllocator *alloc, size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY) { const size_t paddingBits = (sizeof(void*) * 8); @@ -52,7 +53,7 @@ IGpCursor_Win32 *GpColorCursor_Win32::Create(size_t width, size_t height, const size_t maskPitch = width + paddingBits - 1; maskPitch -= maskPitch % paddingBits; - LPVOID maskBits = malloc(maskPitch * height); + LPVOID maskBits = alloc->Alloc(maskPitch * height); if (!maskBits) return nullptr; @@ -71,6 +72,8 @@ IGpCursor_Win32 *GpColorCursor_Win32::Create(size_t width, size_t height, const ii.hbmMask = CreateBitmap(width, height, 1, 1, maskBits); ReleaseDC(NULL, hdc); + alloc->Release(maskBits); + size_t cursorPitch = width * 4; size_t numPixels = width * height; @@ -90,19 +93,20 @@ IGpCursor_Win32 *GpColorCursor_Win32::Create(size_t width, size_t height, const if (!hicon) return nullptr; - void *storage = malloc(sizeof(GpColorCursor_Win32)); + void *storage = alloc->Alloc(sizeof(GpColorCursor_Win32)); if (!storage) { DestroyIcon(hicon); return nullptr; } - return new (storage) GpColorCursor_Win32(reinterpret_cast(hicon)); + return new (storage) GpColorCursor_Win32(alloc, reinterpret_cast(hicon)); } -GpColorCursor_Win32::GpColorCursor_Win32(HCURSOR cursor) +GpColorCursor_Win32::GpColorCursor_Win32(IGpAllocator *alloc, HCURSOR cursor) : m_cursor(cursor) , m_refCount(1) + , m_alloc(alloc) { } @@ -126,7 +130,8 @@ void GpColorCursor_Win32::DecRef() m_refCount--; if (m_refCount == 0) { + IGpAllocator *alloc = m_alloc; this->~GpColorCursor_Win32(); - free(this); + alloc->Release(this); } } diff --git a/Aerofoil/GpColorCursor_Win32.h b/Aerofoil/GpColorCursor_Win32.h index a451ea2..b030f60 100644 --- a/Aerofoil/GpColorCursor_Win32.h +++ b/Aerofoil/GpColorCursor_Win32.h @@ -3,6 +3,7 @@ #include "IGpCursor_Win32.h" #include "GpWindows.h" +struct IGpAllocator; class GpColorCursor_Win32 final : public IGpCursor_Win32 { @@ -14,12 +15,13 @@ public: void IncRef() override; void DecRef() override; - static IGpCursor_Win32 *Create(size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY); + static IGpCursor_Win32 *Create(IGpAllocator *alloc, size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY); private: - GpColorCursor_Win32(HCURSOR cursor); + GpColorCursor_Win32(IGpAllocator *alloc, HCURSOR cursor); ~GpColorCursor_Win32(); HCURSOR m_cursor; int m_refCount; + IGpAllocator *m_alloc; }; diff --git a/Aerofoil/GpFileStream_Win32.h b/Aerofoil/GpFileStream_Win32.h index fdedf17..9a2767b 100644 --- a/Aerofoil/GpFileStream_Win32.h +++ b/Aerofoil/GpFileStream_Win32.h @@ -19,9 +19,13 @@ public: bool SeekEnd(GpUFilePos_t loc) override; GpUFilePos_t Size() const override; GpUFilePos_t Tell() const override; - void Close() override; + void GP_ASYNCIFY_PARANOID_NAMED(Close)() override; void Flush() override; +#if GP_ASYNCIFY_PARANOID + void Close(); +#endif + private: HANDLE m_handle; bool m_readable; diff --git a/Aerofoil/GpFileSystem_Win32.cpp b/Aerofoil/GpFileSystem_Win32.cpp index 5cdb345..485fbcc 100644 --- a/Aerofoil/GpFileSystem_Win32.cpp +++ b/Aerofoil/GpFileSystem_Win32.cpp @@ -1,8 +1,10 @@ #include "GpFileSystem_Win32.h" +#include "GpAllocator_C.h" #include "GpApplicationName.h" #include "GpFileStream_Win32.h" #include "GpWindows.h" +#include "IGpAllocator.h" #include "IGpDirectoryCursor.h" #include @@ -12,33 +14,36 @@ #include +struct IGpAllocator; + extern GpWindowsGlobals g_gpWindowsGlobals; class GpDirectoryCursor_Win32 final : public IGpDirectoryCursor { public: - static GpDirectoryCursor_Win32 *Create(const HANDLE &handle, const WIN32_FIND_DATAW &findData); + static GpDirectoryCursor_Win32 *Create(IGpAllocator *alloc, const HANDLE &handle, const WIN32_FIND_DATAW &findData); bool GetNext(const char *&outFileName) override; void Destroy() override; private: - GpDirectoryCursor_Win32(const HANDLE &handle, const WIN32_FIND_DATAW &findData); + GpDirectoryCursor_Win32(IGpAllocator *alloc, const HANDLE &handle, const WIN32_FIND_DATAW &findData); ~GpDirectoryCursor_Win32(); + IGpAllocator *m_alloc; HANDLE m_handle; WIN32_FIND_DATAW m_findData; char m_chars[MAX_PATH + 1]; bool m_haveNext; }; -GpDirectoryCursor_Win32 *GpDirectoryCursor_Win32::Create(const HANDLE &handle, const WIN32_FIND_DATAW &findData) +GpDirectoryCursor_Win32 *GpDirectoryCursor_Win32::Create(IGpAllocator *alloc, const HANDLE &handle, const WIN32_FIND_DATAW &findData) { - void *storage = malloc(sizeof(GpDirectoryCursor_Win32)); + void *storage = alloc->Alloc(sizeof(GpDirectoryCursor_Win32)); if (!storage) return nullptr; - return new (storage) GpDirectoryCursor_Win32(handle, findData); + return new (storage) GpDirectoryCursor_Win32(alloc, handle, findData); } bool GpDirectoryCursor_Win32::GetNext(const char *&outFileName) @@ -82,14 +87,16 @@ bool GpDirectoryCursor_Win32::GetNext(const char *&outFileName) void GpDirectoryCursor_Win32::Destroy() { + IGpAllocator *alloc = m_alloc; this->~GpDirectoryCursor_Win32(); - free(this); + alloc->Release(this); } -GpDirectoryCursor_Win32::GpDirectoryCursor_Win32(const HANDLE &handle, const WIN32_FIND_DATAW &findData) +GpDirectoryCursor_Win32::GpDirectoryCursor_Win32(IGpAllocator *alloc, const HANDLE &handle, const WIN32_FIND_DATAW &findData) : m_handle(handle) , m_findData(findData) , m_haveNext(true) + , m_alloc(alloc) { } @@ -99,6 +106,7 @@ GpDirectoryCursor_Win32::~GpDirectoryCursor_Win32() } GpFileSystem_Win32::GpFileSystem_Win32() + : m_alloc(GpAllocator_C::GetInstance()) { // GP TODO: This shouldn't be static init since it allocates memory m_executablePath[0] = 0; @@ -137,6 +145,7 @@ GpFileSystem_Win32::GpFileSystem_Win32() m_userSavesDir.append(L"\\"); m_logsDir.append(L"\\"); m_fontCacheDir.append(L"\\"); + m_resourcesDir.append(L"\\"); } DWORD modulePathSize = GetModuleFileNameW(nullptr, m_executablePath, MAX_PATH); @@ -177,6 +186,7 @@ GpFileSystem_Win32::GpFileSystem_Win32() { m_packagedDir = std::wstring(m_executablePath) + L"Packaged\\"; m_housesDir = std::wstring(m_executablePath) + L"Packaged\\Houses\\"; + m_resourcesDir = std::wstring(m_executablePath) + L"Resources\\"; } } @@ -275,7 +285,7 @@ IGpDirectoryCursor *GpFileSystem_Win32::ScanDirectoryNested(PortabilityLayer::Vi { wchar_t winPath[MAX_PATH + 2]; - const char **expandedPaths = static_cast(malloc(sizeof(const char*) * (numPaths + 1))); + const char **expandedPaths = static_cast(m_alloc->Alloc(sizeof(const char*) * (numPaths + 1))); if (!expandedPaths) return nullptr; @@ -284,7 +294,7 @@ IGpDirectoryCursor *GpFileSystem_Win32::ScanDirectoryNested(PortabilityLayer::Vi expandedPaths[numPaths] = "*"; const bool isPathResolved = ResolvePath(virtualDirectory, expandedPaths, numPaths + 1, winPath); - free(expandedPaths); + m_alloc->Release(expandedPaths); if (!isPathResolved) return nullptr; @@ -295,7 +305,7 @@ IGpDirectoryCursor *GpFileSystem_Win32::ScanDirectoryNested(PortabilityLayer::Vi if (ff == INVALID_HANDLE_VALUE) return nullptr; - return GpDirectoryCursor_Win32::Create(ff, findData); + return GpDirectoryCursor_Win32::Create(m_alloc, ff, findData); } bool GpFileSystem_Win32::ValidateFilePathUnicodeChar(uint32_t c) const @@ -453,9 +463,6 @@ bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtua case PortabilityLayer::VirtualDirectories::kLogs: baseDir = m_logsDir.c_str(); break; - case PortabilityLayer::VirtualDirectories::kFontCache: - baseDir = m_fontCacheDir.c_str(); - break; default: return false; } diff --git a/Aerofoil/GpFileSystem_Win32.h b/Aerofoil/GpFileSystem_Win32.h index 6deff90..45acb89 100644 --- a/Aerofoil/GpFileSystem_Win32.h +++ b/Aerofoil/GpFileSystem_Win32.h @@ -41,5 +41,7 @@ private: std::wstring m_fontCacheDir; wchar_t m_executablePath[MAX_PATH]; + IGpAllocator *m_alloc; + static GpFileSystem_Win32 ms_instance; }; diff --git a/Aerofoil/GpLogDriver_Win32.cpp b/Aerofoil/GpLogDriver_Win32.cpp index 3ac6ea1..1ab20f4 100644 --- a/Aerofoil/GpLogDriver_Win32.cpp +++ b/Aerofoil/GpLogDriver_Win32.cpp @@ -1,3 +1,4 @@ +#include "GpAllocator_C.h" #include "GpLogDriver_Win32.h" #include "GpFileSystem_Win32.h" @@ -7,6 +8,7 @@ GpLogDriver_Win32::GpLogDriver_Win32() : m_stream(nullptr) , m_isInitialized(false) + , m_alloc(GpAllocator_C::GetInstance()) { } @@ -58,14 +60,14 @@ void GpLogDriver_Win32::VPrintf(Category category, const char *fmt, va_list args if (formattedSize <= 0) return; - char *charBuff = static_cast(malloc(formattedSize + 1)); + char *charBuff = static_cast(m_alloc->Alloc(formattedSize + 1)); if (!charBuff) return; vsnprintf(charBuff, formattedSize + 1, fmt, args); m_stream->Write(charBuff, formattedSize); - free(charBuff); + m_alloc->Release(charBuff); } m_stream->Write("\n", 1); diff --git a/Aerofoil/GpLogDriver_Win32.h b/Aerofoil/GpLogDriver_Win32.h index fe7f9a2..b607cd7 100644 --- a/Aerofoil/GpLogDriver_Win32.h +++ b/Aerofoil/GpLogDriver_Win32.h @@ -3,6 +3,7 @@ #include "IGpLogDriver.h" class GpIOStream; +struct IGpAllocator; class GpLogDriver_Win32 : public IGpLogDriver { @@ -20,6 +21,7 @@ private: void InitInternal(); GpIOStream *m_stream; + IGpAllocator *m_alloc; bool m_isInitialized; static GpLogDriver_Win32 ms_instance; diff --git a/Aerofoil/GpMain_Win32.cpp b/Aerofoil/GpMain_Win32.cpp index 6a5fc5c..2343ac7 100644 --- a/Aerofoil/GpMain_Win32.cpp +++ b/Aerofoil/GpMain_Win32.cpp @@ -1,4 +1,5 @@ #include "GpMain.h" +#include "GpAllocator_C.h" #include "GpAudioDriverFactory.h" #include "GpBWCursor_Win32.h" #include "GpColorCursor_Win32.h" @@ -410,12 +411,15 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine } IGpLogDriver *logger = GpLogDriver_Win32::GetInstance(); + IGpAllocator *alloc = GpAllocator_C::GetInstance(); + IGpSystemServices *sysServices = GpSystemServices_Win32::GetInstance(); GpDriverCollection *drivers = GpAppInterface_Get()->PL_GetDriverCollection(); drivers->SetDriver(GpFileSystem_Win32::GetInstance()); - drivers->SetDriver(GpSystemServices_Win32::GetInstance()); - drivers->SetDriver(GpLogDriver_Win32::GetInstance()); + drivers->SetDriver(sysServices); + drivers->SetDriver(logger); + drivers->SetDriver(alloc); g_gpWindowsGlobals.m_hInstance = hInstance; g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance; @@ -448,7 +452,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine g_gpGlobalConfig.m_osGlobals = &g_gpWindowsGlobals; g_gpGlobalConfig.m_logger = logger; - g_gpGlobalConfig.m_systemServices = GpSystemServices_Win32::GetInstance(); + g_gpGlobalConfig.m_systemServices = sysServices; + g_gpGlobalConfig.m_allocator = alloc; GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_D3D11, GpDriver_CreateDisplayDriver_D3D11); GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_XAudio2, GpDriver_CreateAudioDriver_XAudio2); diff --git a/Aerofoil/GpMutex_Win32.cpp b/Aerofoil/GpMutex_Win32.cpp index 849fc4f..a5acb2b 100644 --- a/Aerofoil/GpMutex_Win32.cpp +++ b/Aerofoil/GpMutex_Win32.cpp @@ -1,5 +1,6 @@ #include "GpMutex_Win32.h" +#include "IGpAllocator.h" #include "GpWindows.h" #include @@ -7,8 +8,9 @@ void GpMutex_Win32::Destroy() { + IGpAllocator *alloc = m_alloc; this->~GpMutex_Win32(); - free(this); + alloc->Release(this); } void GpMutex_Win32::Lock() @@ -22,16 +24,17 @@ void GpMutex_Win32::Unlock() } -GpMutex_Win32 *GpMutex_Win32::Create() +GpMutex_Win32 *GpMutex_Win32::Create(IGpAllocator *alloc) { - void *storage = malloc(sizeof(GpMutex_Win32)); + void *storage = alloc->Alloc(sizeof(GpMutex_Win32)); if (!storage) return nullptr; - return new (storage) GpMutex_Win32(); + return new (storage) GpMutex_Win32(alloc); } -GpMutex_Win32::GpMutex_Win32() +GpMutex_Win32::GpMutex_Win32(IGpAllocator *alloc) + : m_alloc(alloc) { InitializeCriticalSection(&m_critSection); } diff --git a/Aerofoil/GpMutex_Win32.h b/Aerofoil/GpMutex_Win32.h index 6b7ca86..d9bf6fb 100644 --- a/Aerofoil/GpMutex_Win32.h +++ b/Aerofoil/GpMutex_Win32.h @@ -4,6 +4,8 @@ #include "GpWindows.h" +struct IGpAllocator; + class GpMutex_Win32 final : public IGpMutex { public: @@ -11,11 +13,12 @@ public: void Lock() override; void Unlock() override; - static GpMutex_Win32 *Create(); + static GpMutex_Win32 *Create(IGpAllocator *alloc); private: - const GpMutex_Win32(); + explicit GpMutex_Win32(IGpAllocator *alloc); ~GpMutex_Win32(); CRITICAL_SECTION m_critSection; + IGpAllocator *m_alloc; }; diff --git a/Aerofoil/GpSystemServices_Win32.cpp b/Aerofoil/GpSystemServices_Win32.cpp index 8758638..f1e5f86 100644 --- a/Aerofoil/GpSystemServices_Win32.cpp +++ b/Aerofoil/GpSystemServices_Win32.cpp @@ -2,11 +2,11 @@ #include "GpMutex_Win32.h" #include "GpThreadEvent_Win32.h" #include "GpWindows.h" +#include "GpAllocator_C.h" #include "IGpClipboardContents.h" -#include "UTF16.h" -#include "UTF8.h" +#include "GpUnicode.h" #include #include @@ -134,6 +134,7 @@ static DWORD WINAPI StaticStartThread(LPVOID lpThreadParameter) GpSystemServices_Win32::GpSystemServices_Win32() : m_isTouchscreenSimulation(false) + , m_alloc(GpAllocator_C::GetInstance()) { } @@ -181,17 +182,17 @@ void GpSystemServices_Win32::GetLocalDateTime(unsigned int &year, unsigned int & IGpMutex *GpSystemServices_Win32::CreateMutex() { - return GpMutex_Win32::Create(); + return GpMutex_Win32::Create(m_alloc); } IGpMutex *GpSystemServices_Win32::CreateRecursiveMutex() { - return GpMutex_Win32::Create(); + return GpMutex_Win32::Create(m_alloc); } IGpThreadEvent *GpSystemServices_Win32::CreateThreadEvent(bool autoReset, bool startSignaled) { - return GpThreadEvent_Win32::Create(autoReset, startSignaled); + return GpThreadEvent_Win32::Create(m_alloc, autoReset, startSignaled); } void *GpSystemServices_Win32::CreateThread(ThreadFunc_t threadFunc, void *context) diff --git a/Aerofoil/GpSystemServices_Win32.h b/Aerofoil/GpSystemServices_Win32.h index 90b26b2..d72e2b8 100644 --- a/Aerofoil/GpSystemServices_Win32.h +++ b/Aerofoil/GpSystemServices_Win32.h @@ -48,6 +48,8 @@ public: private: bool m_isTouchscreenSimulation; + IGpAllocator *m_alloc; + static GpSystemServices_Win32 ms_instance; }; diff --git a/Aerofoil/GpThreadEvent_Win32.cpp b/Aerofoil/GpThreadEvent_Win32.cpp index 1497d10..52d38ee 100644 --- a/Aerofoil/GpThreadEvent_Win32.cpp +++ b/Aerofoil/GpThreadEvent_Win32.cpp @@ -1,4 +1,5 @@ #include "GpThreadEvent_Win32.h" +#include "IGpAllocator.h" #include #include @@ -20,28 +21,30 @@ void GpThreadEvent_Win32::Signal() void GpThreadEvent_Win32::Destroy() { + IGpAllocator *alloc = m_alloc; this->~GpThreadEvent_Win32(); - free(this); + alloc->Release(this); } -GpThreadEvent_Win32 *GpThreadEvent_Win32::Create(bool autoReset, bool startSignaled) +GpThreadEvent_Win32 *GpThreadEvent_Win32::Create(IGpAllocator *alloc, bool autoReset, bool startSignaled) { HANDLE handle = CreateEventA(nullptr, autoReset ? FALSE : TRUE, startSignaled ? TRUE : FALSE, nullptr); if (handle == nullptr) return nullptr; - void *storage = malloc(sizeof(GpThreadEvent_Win32)); + void *storage = alloc->Alloc(sizeof(GpThreadEvent_Win32)); if (!storage) { CloseHandle(handle); return nullptr; } - return new (storage) GpThreadEvent_Win32(handle); + return new (storage) GpThreadEvent_Win32(alloc, handle); } -GpThreadEvent_Win32::GpThreadEvent_Win32(const HANDLE &handle) +GpThreadEvent_Win32::GpThreadEvent_Win32(IGpAllocator *alloc, const HANDLE &handle) : m_event(handle) + , m_alloc(alloc) { } diff --git a/Aerofoil/GpThreadEvent_Win32.h b/Aerofoil/GpThreadEvent_Win32.h index 20454de..dd6d3f3 100644 --- a/Aerofoil/GpThreadEvent_Win32.h +++ b/Aerofoil/GpThreadEvent_Win32.h @@ -12,11 +12,12 @@ public: void Signal() override; void Destroy() override; - static GpThreadEvent_Win32 *Create(bool autoReset, bool startSignaled); + static GpThreadEvent_Win32 *Create(IGpAllocator *alloc, bool autoReset, bool startSignaled); private: - explicit GpThreadEvent_Win32(const HANDLE &handle); + explicit GpThreadEvent_Win32(IGpAllocator *alloc, const HANDLE &handle); ~GpThreadEvent_Win32(); HANDLE m_event; + IGpAllocator *m_alloc; }; diff --git a/AerofoilAndroid/app/jni/main/GpFileSystem_Android.cpp b/AerofoilAndroid/app/jni/main/GpFileSystem_Android.cpp index b6cb544..a04600c 100644 --- a/AerofoilAndroid/app/jni/main/GpFileSystem_Android.cpp +++ b/AerofoilAndroid/app/jni/main/GpFileSystem_Android.cpp @@ -424,9 +424,6 @@ bool GpFileSystem_Android::ResolvePath(PortabilityLayer::VirtualDirectory_t virt case PortabilityLayer::VirtualDirectories::kPrefs: prefsAppend = "Prefs"; break; - case PortabilityLayer::VirtualDirectories::kFontCache: - prefsAppend = "FontCache"; - break; default: return false; }; diff --git a/AerofoilPortable.props b/AerofoilPortable.props index 08b2b3e..5412b99 100644 --- a/AerofoilPortable.props +++ b/AerofoilPortable.props @@ -1,8 +1,10 @@ - + - + + $(SolutionDir)AerofoilPortable;$(IncludePath) + - + \ No newline at end of file diff --git a/AerofoilPortable/GpAllocator_C.cpp b/AerofoilPortable/GpAllocator_C.cpp new file mode 100644 index 0000000..247bfb5 --- /dev/null +++ b/AerofoilPortable/GpAllocator_C.cpp @@ -0,0 +1,115 @@ +#include "GpAllocator_C.h" +#include "CoreDefs.h" + +#include +#include +#include + +struct GpAllocator_C_MMBlock +{ + uint8_t m_offsetFromAllocLocation; + + static size_t AlignedSize(); +}; + +size_t GpAllocator_C_MMBlock::AlignedSize() +{ + const size_t paddedSize = sizeof(GpAllocator_C_MMBlock) + GP_SYSTEM_MEMORY_ALIGNMENT - 1; + const size_t paddedSizeTruncated = paddedSize - (paddedSize % GP_SYSTEM_MEMORY_ALIGNMENT); + + return paddedSizeTruncated; +} + +void *GpAllocator_C::Realloc(void *buf, size_t newSize) +{ + if (buf == nullptr) + { + if (newSize == 0) + return nullptr; + + return this->Alloc(newSize); + } + + if (newSize == 0) + { + this->Free(buf); + return nullptr; + } + + assert(buf != nullptr); + + const size_t mmBlockSize = GpAllocator_C_MMBlock::AlignedSize(); + uint8_t *oldBufBytes = static_cast(buf); + const GpAllocator_C_MMBlock *oldBufMMBlock = reinterpret_cast(oldBufBytes - GpAllocator_C_MMBlock::AlignedSize()); + + const size_t oldBufOffsetFromAlignLoc = oldBufMMBlock->m_offsetFromAllocLocation; + uint8_t *oldBufBase = oldBufBytes - GpAllocator_C_MMBlock::AlignedSize() - oldBufOffsetFromAlignLoc; + + const size_t mmBlockSizeWithMaxPadding = GpAllocator_C_MMBlock::AlignedSize() + GP_SYSTEM_MEMORY_ALIGNMENT - 1; + if (SIZE_MAX - newSize < mmBlockSizeWithMaxPadding) + return nullptr; + + const size_t newBufferSize = newSize + mmBlockSizeWithMaxPadding; + uint8_t *newBuffer = static_cast(realloc(oldBufBase, newSize + mmBlockSizeWithMaxPadding)); + if (!newBuffer) + return nullptr; + + const intptr_t offsetFromAlignPoint = reinterpret_cast(newBuffer) & static_cast(GP_SYSTEM_MEMORY_ALIGNMENT - 1); + intptr_t alignPadding = 0; + if (offsetFromAlignPoint != 0) + alignPadding = static_cast(GP_SYSTEM_MEMORY_ALIGNMENT) - offsetFromAlignPoint; + + // Check if the alignment changed, if so relocate + if (static_cast(alignPadding) != oldBufOffsetFromAlignLoc) + memmove(newBuffer + alignPadding, newBuffer + oldBufOffsetFromAlignLoc, GpAllocator_C_MMBlock::AlignedSize() + newSize); + + GpAllocator_C_MMBlock *newMMBlock = reinterpret_cast(newBuffer + alignPadding); + newMMBlock->m_offsetFromAllocLocation = static_cast(alignPadding); + + return newBuffer + alignPadding + GpAllocator_C_MMBlock::AlignedSize(); +} + +void *GpAllocator_C::Alloc(size_t size) +{ + if (size == 0) + return nullptr; + + const size_t mmBlockSizeWithMaxPadding = GpAllocator_C_MMBlock::AlignedSize() + GP_SYSTEM_MEMORY_ALIGNMENT - 1; + if (SIZE_MAX - size < mmBlockSizeWithMaxPadding) + return nullptr; + + uint8_t *buffer = static_cast(realloc(nullptr, size + mmBlockSizeWithMaxPadding)); + if (!buffer) + return nullptr; + + const intptr_t offsetFromAlignPoint = reinterpret_cast(buffer) & static_cast(GP_SYSTEM_MEMORY_ALIGNMENT - 1); + intptr_t alignPadding = 0; + if (offsetFromAlignPoint != 0) + alignPadding = static_cast(GP_SYSTEM_MEMORY_ALIGNMENT) - offsetFromAlignPoint; + + GpAllocator_C_MMBlock *mmBlock = reinterpret_cast(buffer + alignPadding); + mmBlock->m_offsetFromAllocLocation = static_cast(alignPadding); + + return buffer + alignPadding + GpAllocator_C_MMBlock::AlignedSize(); +} + +void GpAllocator_C::Free(void *buf) +{ + if (!buf) + return; + + const size_t mmBlockSize = GpAllocator_C_MMBlock::AlignedSize(); + + uint8_t *bytes = static_cast(buf); + const GpAllocator_C_MMBlock *mmBlock = reinterpret_cast(bytes - GpAllocator_C_MMBlock::AlignedSize()); + + void *freeLoc = bytes - GpAllocator_C_MMBlock::AlignedSize() - mmBlock->m_offsetFromAllocLocation; + realloc(freeLoc, 0); +} + +GpAllocator_C *GpAllocator_C::GetInstance() +{ + return &ms_instance; +} + +GpAllocator_C GpAllocator_C::ms_instance; diff --git a/AerofoilPortable/GpAllocator_C.h b/AerofoilPortable/GpAllocator_C.h new file mode 100644 index 0000000..8325f31 --- /dev/null +++ b/AerofoilPortable/GpAllocator_C.h @@ -0,0 +1,17 @@ +#pragma once + +#include "IGpAllocator.h" + +class GpAllocator_C final : public IGpAllocator +{ +public: + void *Realloc(void *buf, size_t newSize) override; + + static GpAllocator_C *GetInstance(); + +private: + void *Alloc(size_t size); + void Free(void *ptr); + + static GpAllocator_C ms_instance; +}; diff --git a/AerofoilSDL/AerofoilSDL.vcxproj b/AerofoilSDL/AerofoilSDL.vcxproj index d674526..071b61d 100644 --- a/AerofoilSDL/AerofoilSDL.vcxproj +++ b/AerofoilSDL/AerofoilSDL.vcxproj @@ -84,6 +84,7 @@ + diff --git a/AerofoilSDL/AerofoilSDL.vcxproj.filters b/AerofoilSDL/AerofoilSDL.vcxproj.filters index 3c86551..d5a22b0 100644 --- a/AerofoilSDL/AerofoilSDL.vcxproj.filters +++ b/AerofoilSDL/AerofoilSDL.vcxproj.filters @@ -66,6 +66,9 @@ Source Files + + Source Files + diff --git a/AerofoilSDL/GpAudioDriver_SDL2.cpp b/AerofoilSDL/GpAudioDriver_SDL2.cpp index 4255fe1..070697d 100644 --- a/AerofoilSDL/GpAudioDriver_SDL2.cpp +++ b/AerofoilSDL/GpAudioDriver_SDL2.cpp @@ -1,4 +1,5 @@ #include "CoreDefs.h" +#include "IGpAudioBuffer.h" #include "IGpAudioDriver.h" #include "IGpAudioChannel.h" #include "IGpAudioChannelCallbacks.h" @@ -13,13 +14,21 @@ #include "SDL_atomic.h" +#include +#include #include #include #include #include +#include class GpAudioDriver_SDL2; +typedef std::chrono::high_resolution_clock::duration GpAudioDriver_SDL2_Duration_t; +typedef std::chrono::high_resolution_clock::time_point GpAudioDriver_SDL2_TimePoint_t; +typedef std::chrono::high_resolution_clock::period GpAudioDriver_SDL2_Period_t; +typedef std::chrono::high_resolution_clock::rep GpAudioDriver_SDL2_Rep_t; + static void *AlignedAlloc(size_t size, size_t alignment) { void *storage = malloc(size + alignment); @@ -46,65 +55,130 @@ static void AlignedFree(void *ptr) free(storageLoc); } -struct GpAudioChannelBufferChain_SDL2 final -{ - GpAudioChannelBufferChain_SDL2(); - - static GpAudioChannelBufferChain_SDL2 *Alloc(); - void Release(); - - static const size_t kMaxCapacity = 65536; - - size_t m_consumed; - size_t m_used; - uint8_t m_data[kMaxCapacity]; - GpAudioChannelBufferChain_SDL2 *m_next; - bool m_hasTrigger; -}; - -class GP_ALIGNED(GP_SYSTEM_MEMORY_ALIGNMENT) GpAudioChannel_SDL2 final : public IGpAudioChannel +class GpAudioBuffer_SDL2 final : public IGpAudioBuffer { public: - enum ChannelState - { - ChannelState_Idle, - ChannelState_Playing, - ChannelState_Stopped, - }; + static GpAudioBuffer_SDL2 *Create(const void *data, size_t size); + void AddRef() override; + void Release() override; + + const void *GetData() const; + size_t GetSize() const; + +private: + GpAudioBuffer_SDL2(const void *data, size_t size); + ~GpAudioBuffer_SDL2(); + + void Destroy(); + + const void *m_data; + size_t m_size; + SDL_atomic_t m_count; +}; + +GpAudioBuffer_SDL2 *GpAudioBuffer_SDL2::Create(const void *data, size_t size) +{ + void *storage = malloc(size + sizeof(GpAudioBuffer_SDL2)); + if (!storage) + return nullptr; + + void *dataPos = static_cast(storage) + sizeof(GpAudioBuffer_SDL2); + memcpy(dataPos, data, size); + + return new (storage) GpAudioBuffer_SDL2(dataPos, size); +} + + +void GpAudioBuffer_SDL2::AddRef() +{ + SDL_AtomicAdd(&m_count, 1); +} + +void GpAudioBuffer_SDL2::Release() +{ + int prevCount = SDL_AtomicAdd(&m_count, -1); + if (prevCount == 1) + this->Destroy(); +} + +const void *GpAudioBuffer_SDL2::GetData() const +{ + return m_data; +} + +size_t GpAudioBuffer_SDL2::GetSize() const +{ + return m_size; +} + + +GpAudioBuffer_SDL2::GpAudioBuffer_SDL2(const void *data, size_t size) + : m_data(data) + , m_size(size) +{ + SDL_AtomicSet(&m_count, 1); +} + +GpAudioBuffer_SDL2::~GpAudioBuffer_SDL2() +{ +} + +void GpAudioBuffer_SDL2::Destroy() +{ + this->~GpAudioBuffer_SDL2(); + free(this); +} + + +class GpAudioChannel_SDL2 final : public IGpAudioChannel +{ +public: friend class GpAudioDriver_SDL2; - GpAudioChannel_SDL2(); + GpAudioChannel_SDL2(GpAudioDriver_SDL2_Duration_t latency, GpAudioDriver_SDL2_Duration_t bufferTime, size_t bufferSamplesMax, uint16_t sampleRate); ~GpAudioChannel_SDL2(); void AddRef(); void Release(); void SetAudioChannelContext(IGpAudioChannelCallbacks *callbacks) override; - void PostBuffer(const void *buffer, size_t bufferSize) override; + bool PostBuffer(IGpAudioBuffer *buffer) override; void Stop() override; void Destroy() override; - void Consume(uint8_t *output, size_t sz); + void Consume(uint8_t *output, size_t sz, GpAudioDriver_SDL2_TimePoint_t mixStartTime, GpAudioDriver_SDL2_TimePoint_t mixEndTime); - static GpAudioChannel_SDL2 *Alloc(GpAudioDriver_SDL2 *driver); + static GpAudioChannel_SDL2 *Alloc(GpAudioDriver_SDL2 *driver, GpAudioDriver_SDL2_Duration_t latency, GpAudioDriver_SDL2_Duration_t bufferTime, size_t bufferSamplesMax, uint16_t sampleRate); private: bool Init(GpAudioDriver_SDL2 *driver); + static const size_t kMaxBuffers = 16; + IGpAudioChannelCallbacks *m_callbacks; IGpMutex *m_mutex; GpAudioDriver_SDL2 *m_owner; SDL_atomic_t m_refCount; - GpAudioChannelBufferChain_SDL2 *m_firstPendingBuffer; - GpAudioChannelBufferChain_SDL2 *m_lastPendingBuffer; + GpAudioBuffer_SDL2 *m_pendingBuffers[kMaxBuffers]; + size_t m_nextPendingBufferConsumePos; + size_t m_nextPendingBufferInsertionPos; + size_t m_numQueuedBuffers; + size_t m_firstBufferSamplesConsumed; - ChannelState m_channelState; + GpAudioDriver_SDL2_TimePoint_t m_timestamp; // Time that audio will be consumed if posted to the channel, if m_hasTimestamp is true. + GpAudioDriver_SDL2_Duration_t m_latency; + GpAudioDriver_SDL2_Duration_t m_bufferTime; + size_t m_bufferSamplesMax; + size_t m_leadingSilence; + uint16_t m_sampleRate; + bool m_isMixing; + bool m_hasTimestamp; }; -class GP_ALIGNED(GP_SYSTEM_MEMORY_ALIGNMENT) GpAudioDriver_SDL2 final : public IGpAudioDriver, public IGpPrefsHandler +class GpAudioDriver_SDL2 final : public IGpAudioDriver, public IGpPrefsHandler { public: friend class GpAudioChannel_SDL2; @@ -112,6 +186,7 @@ public: explicit GpAudioDriver_SDL2(const GpAudioDriverProperties &properties); ~GpAudioDriver_SDL2(); + IGpAudioBuffer *CreateBuffer(const void *data, size_t size) override; IGpAudioChannel *CreateChannel() override; void SetMasterVolume(uint32_t vol, uint32_t maxVolume) override; void Shutdown() override; @@ -122,25 +197,32 @@ public: bool Init(); + static GpAudioDriver_SDL2_TimePoint_t GetCurrentTime(); + private: void DetachAudioChannel(GpAudioChannel_SDL2 *channel); static void SDLCALL StaticMixAudio(void *userdata, Uint8 *stream, int len); void MixAudio(void *stream, size_t len); - void RefillMixChunk(GpAudioChannel_SDL2 *const*channels, size_t numChannels); + void RefillMixChunk(GpAudioChannel_SDL2 *const*channels, size_t numChannels, size_t maxSamplesToFill, GpAudioDriver_SDL2_TimePoint_t mixStartTime, GpAudioDriver_SDL2_TimePoint_t mixEndTime); GpAudioDriverProperties m_properties; IGpMutex *m_mutex; IGpMutex *m_mixState; static const size_t kMaxChannels = 16; - static const size_t kMixChunkSize = 256; - static const int16_t kMaxAudioVolumeScale = 25; + static const size_t kMixChunkSize = 512; + static const int16_t kMaxAudioVolumeScale = 64; GpAudioChannel_SDL2 *m_channels[kMaxChannels]; size_t m_numChannels; + unsigned int m_sampleRate; + GpAudioDriver_SDL2_Duration_t m_latency; + GpAudioDriver_SDL2_Duration_t m_bufferTime; + size_t m_bufferSamples; + bool m_sdlAudioRunning; GP_ALIGNED(GP_SYSTEM_MEMORY_ALIGNMENT) int16_t m_mixChunk[kMixChunkSize]; @@ -149,36 +231,24 @@ private: int16_t m_audioVolumeScale; }; -GpAudioChannelBufferChain_SDL2::GpAudioChannelBufferChain_SDL2() - : m_used(0) - , m_consumed(0) - , m_next(nullptr) - , m_hasTrigger(false) -{ -} - - -GpAudioChannelBufferChain_SDL2 *GpAudioChannelBufferChain_SDL2::Alloc() -{ - void *storage = AlignedAlloc(sizeof(GpAudioChannelBufferChain_SDL2), GP_SYSTEM_MEMORY_ALIGNMENT); - return new (storage) GpAudioChannelBufferChain_SDL2(); -} - -void GpAudioChannelBufferChain_SDL2::Release() -{ - this->~GpAudioChannelBufferChain_SDL2(); - AlignedFree(this); -} - ///////////////////////////////////////////////////////////////////////////////////////// // GpAudioChannel -GpAudioChannel_SDL2::GpAudioChannel_SDL2() +GpAudioChannel_SDL2::GpAudioChannel_SDL2(GpAudioDriver_SDL2_Duration_t latency, GpAudioDriver_SDL2_Duration_t bufferTime, size_t bufferSamplesMax, uint16_t sampleRate) : m_callbacks(nullptr) , m_mutex(nullptr) , m_owner(nullptr) - , m_firstPendingBuffer(nullptr) - , m_lastPendingBuffer(nullptr) + , m_latency(latency) + , m_bufferTime(bufferTime) + , m_bufferSamplesMax(bufferSamplesMax) + , m_leadingSilence(0) + , m_sampleRate(sampleRate) + , m_isMixing(false) + , m_hasTimestamp(false) + , m_nextPendingBufferConsumePos(0) + , m_nextPendingBufferInsertionPos(0) + , m_numQueuedBuffers(0) + , m_firstBufferSamplesConsumed(0) { SDL_AtomicSet(&m_refCount, 1); } @@ -190,12 +260,7 @@ GpAudioChannel_SDL2::~GpAudioChannel_SDL2() if (m_mutex) m_mutex->Destroy(); - while (m_firstPendingBuffer) - { - GpAudioChannelBufferChain_SDL2 *buffer = m_firstPendingBuffer; - m_firstPendingBuffer = buffer->m_next; - buffer->Release(); - } + assert(m_numQueuedBuffers == 0); } void GpAudioChannel_SDL2::AddRef() @@ -218,54 +283,70 @@ void GpAudioChannel_SDL2::SetAudioChannelContext(IGpAudioChannelCallbacks *callb m_callbacks = callbacks; } -void GpAudioChannel_SDL2::PostBuffer(const void *buffer, size_t bufferSize) +bool GpAudioChannel_SDL2::PostBuffer(IGpAudioBuffer *buffer) { + buffer->AddRef(); + m_mutex->Lock(); - while (bufferSize > 0) + if (m_numQueuedBuffers == kMaxBuffers) { - GpAudioChannelBufferChain_SDL2 *newBuffer = GpAudioChannelBufferChain_SDL2::Alloc(); - if (newBuffer == nullptr) - break; - - if (m_lastPendingBuffer == nullptr) - m_firstPendingBuffer = newBuffer; - else - m_lastPendingBuffer->m_next = newBuffer; - m_lastPendingBuffer = newBuffer; - - size_t bufferable = newBuffer->kMaxCapacity; - if (bufferSize < bufferable) - bufferable = bufferSize; - - memcpy(newBuffer->m_data, buffer, bufferable); - - buffer = static_cast(buffer) + bufferable; - bufferSize -= bufferable; - m_lastPendingBuffer->m_used = bufferable; - m_lastPendingBuffer->m_hasTrigger = (bufferSize == 0); + m_mutex->Unlock(); + buffer->Release(); + return false; } + size_t leadingSilence = 0; + if (m_numQueuedBuffers == 0 && m_hasTimestamp && !m_isMixing) + { + GpAudioDriver_SDL2_TimePoint_t queueTime = GpAudioDriver_SDL2::GetCurrentTime() + m_latency; + if (queueTime > m_timestamp) + { + const GpAudioDriver_SDL2_Duration_t leadTime = queueTime - m_timestamp; + + if (leadTime > m_bufferTime) + leadingSilence = m_bufferSamplesMax; + else + { + const GpAudioDriver_SDL2_Rep_t leadTimeRep = leadTime.count(); + leadingSilence = leadTimeRep * static_cast(m_sampleRate) * GpAudioDriver_SDL2_Period_t::num / GpAudioDriver_SDL2_Period_t::den; + } + } + } + + m_leadingSilence = leadingSilence; + + m_pendingBuffers[m_nextPendingBufferInsertionPos++] = static_cast(buffer); + m_numQueuedBuffers++; + + m_nextPendingBufferInsertionPos = m_nextPendingBufferInsertionPos % kMaxBuffers; + m_mutex->Unlock(); + + return true; } void GpAudioChannel_SDL2::Stop() { m_mutex->Lock(); - GpAudioChannelBufferChain_SDL2 *buffer = m_firstPendingBuffer; - m_firstPendingBuffer = nullptr; - m_lastPendingBuffer = nullptr; + m_leadingSilence = 0; - while (buffer) + size_t numBuffersToDischarge = m_numQueuedBuffers; + + for (size_t i = 0; i < numBuffersToDischarge; i++) { - if (buffer->m_hasTrigger && m_callbacks) + GpAudioBuffer_SDL2 *buffer = m_pendingBuffers[m_nextPendingBufferConsumePos]; + + m_nextPendingBufferConsumePos = (m_nextPendingBufferConsumePos + 1) % kMaxBuffers; + m_numQueuedBuffers--; + + m_firstBufferSamplesConsumed = 0; + + if (m_callbacks) m_callbacks->NotifyBufferFinished(); - GpAudioChannelBufferChain_SDL2 *nextBuffer = buffer->m_next; buffer->Release(); - - buffer = nextBuffer; } m_mutex->Unlock(); @@ -289,25 +370,57 @@ bool GpAudioChannel_SDL2::Init(GpAudioDriver_SDL2 *driver) return true; } -void GpAudioChannel_SDL2::Consume(uint8_t *output, size_t sz) +void GpAudioChannel_SDL2::Consume(uint8_t *output, size_t sz, GpAudioDriver_SDL2_TimePoint_t mixStartTime, GpAudioDriver_SDL2_TimePoint_t mixEndTime) { m_mutex->Lock(); - while (m_firstPendingBuffer != nullptr) + m_isMixing = true; + m_hasTimestamp = true; + m_timestamp = mixEndTime; + + if (sz <= m_leadingSilence) { - GpAudioChannelBufferChain_SDL2 *buffer = m_firstPendingBuffer; - const size_t available = (buffer->m_used - buffer->m_consumed); + memset(output, 0x80, sz); + m_leadingSilence -= sz; + + m_isMixing = false; + m_mutex->Unlock(); + return; + } + else + { + size_t leadingSilence = m_leadingSilence; + if (leadingSilence > 0) + { + memset(output, 0x80, leadingSilence); + output += leadingSilence; + sz -= leadingSilence; + + m_leadingSilence = 0; + } + } + + while (m_numQueuedBuffers > 0) + { + GpAudioBuffer_SDL2 *buffer = m_pendingBuffers[m_nextPendingBufferConsumePos]; + const void *bufferData = buffer->GetData(); + const size_t bufferSize = buffer->GetSize(); + + assert(m_firstBufferSamplesConsumed < bufferSize); + + const size_t available = (bufferSize - m_firstBufferSamplesConsumed); if (available <= sz) { - memcpy(output, buffer->m_data + buffer->m_consumed, available); + memcpy(output, static_cast(bufferData) + m_firstBufferSamplesConsumed, available); sz -= available; output += available; - m_firstPendingBuffer = buffer->m_next; - if (m_firstPendingBuffer == nullptr) - m_lastPendingBuffer = nullptr; + m_nextPendingBufferConsumePos = (m_nextPendingBufferConsumePos + 1) % kMaxBuffers; + m_numQueuedBuffers--; - if (buffer->m_hasTrigger && m_callbacks) + m_firstBufferSamplesConsumed = 0; + + if (m_callbacks) m_callbacks->NotifyBufferFinished(); buffer->Release(); @@ -317,26 +430,28 @@ void GpAudioChannel_SDL2::Consume(uint8_t *output, size_t sz) } else { - memcpy(output, buffer->m_data + buffer->m_consumed, sz); - buffer->m_consumed += sz; - buffer += sz; + memcpy(output, static_cast(bufferData) + m_firstBufferSamplesConsumed, sz); + m_firstBufferSamplesConsumed += sz; + output += sz; sz = 0; break; } } + m_isMixing = false; + m_mutex->Unlock(); memset(output, 0x80, sz); } -GpAudioChannel_SDL2 *GpAudioChannel_SDL2::Alloc(GpAudioDriver_SDL2 *driver) +GpAudioChannel_SDL2 *GpAudioChannel_SDL2::Alloc(GpAudioDriver_SDL2 *driver, GpAudioDriver_SDL2_Duration_t latency, GpAudioDriver_SDL2_Duration_t bufferTime, size_t bufferSamplesMax, uint16_t sampleRate) { void *storage = AlignedAlloc(sizeof(GpAudioChannel_SDL2), GP_SYSTEM_MEMORY_ALIGNMENT); if (!storage) return nullptr; - GpAudioChannel_SDL2 *channel = new (storage) GpAudioChannel_SDL2(); + GpAudioChannel_SDL2 *channel = new (storage) GpAudioChannel_SDL2(latency, bufferTime, bufferSamplesMax, sampleRate); if (!channel->Init(driver)) { channel->Destroy(); @@ -354,6 +469,9 @@ GpAudioDriver_SDL2::GpAudioDriver_SDL2(const GpAudioDriverProperties &properties : m_properties(properties) , m_mutex(nullptr) , m_numChannels(0) + , m_sampleRate(0) + , m_latency(GpAudioDriver_SDL2_Duration_t::zero()) + , m_bufferTime(GpAudioDriver_SDL2_Duration_t::zero()) , m_sdlAudioRunning(false) , m_mixChunkReadOffset(kMixChunkSize) , m_audioVolumeScale(kMaxAudioVolumeScale) @@ -375,9 +493,14 @@ GpAudioDriver_SDL2::~GpAudioDriver_SDL2() m_mutex->Destroy(); } +IGpAudioBuffer *GpAudioDriver_SDL2::CreateBuffer(const void *data, size_t size) +{ + return GpAudioBuffer_SDL2::Create(data, size); +} + IGpAudioChannel *GpAudioDriver_SDL2::CreateChannel() { - GpAudioChannel_SDL2 *newChannel = GpAudioChannel_SDL2::Alloc(this); + GpAudioChannel_SDL2 *newChannel = GpAudioChannel_SDL2::Alloc(this, m_latency, m_bufferTime, m_bufferSamples, m_sampleRate); if (!newChannel) return nullptr; @@ -437,7 +560,7 @@ bool GpAudioDriver_SDL2::Init() requestedSpec.channels = 1; requestedSpec.format = AUDIO_S16; requestedSpec.freq = m_properties.m_sampleRate; - requestedSpec.samples = 1024; + requestedSpec.samples = kMixChunkSize; requestedSpec.userdata = this; if (SDL_OpenAudio(&requestedSpec, nullptr)) @@ -450,6 +573,10 @@ bool GpAudioDriver_SDL2::Init() SDL_PauseAudio(0); m_sdlAudioRunning = true; + m_sampleRate = requestedSpec.freq; + m_latency = GpAudioDriver_SDL2_Duration_t(static_cast(GpAudioDriver_SDL2_Period_t::den * requestedSpec.samples / GpAudioDriver_SDL2_Period_t::num / m_sampleRate)); + m_bufferTime = GpAudioDriver_SDL2_Duration_t(static_cast(GpAudioDriver_SDL2_Period_t::den * requestedSpec.samples / GpAudioDriver_SDL2_Period_t::num / m_sampleRate)); + m_bufferSamples = requestedSpec.samples; return true; } @@ -492,8 +619,13 @@ void GpAudioDriver_SDL2::MixAudio(void *stream, size_t len) } m_mutex->Unlock(); - size_t samplesRemaining = len / sizeof(int16_t); + const size_t totalSamples = len / sizeof(int16_t); + size_t samplesRemaining = totalSamples; + GpAudioDriver_SDL2_TimePoint_t audioMixStartTime = GpAudioDriver_SDL2::GetCurrentTime(); + GpAudioDriver_SDL2_TimePoint_t audioMixBlockStartTime = audioMixStartTime; + + size_t samplesSinceStart = 0; for (;;) { size_t availableInMixChunk = kMixChunkSize - m_mixChunkReadOffset; @@ -510,10 +642,17 @@ void GpAudioDriver_SDL2::MixAudio(void *stream, size_t len) memcpy(stream, m_mixChunk + m_mixChunkReadOffset, availableInMixChunk * sizeof(int16_t)); stream = static_cast(stream) + availableInMixChunk; - samplesRemaining -= availableInMixChunk; + + samplesSinceStart += availableInMixChunk; + + GpAudioDriver_SDL2_Duration_t audioMixDurationSinceStart = GpAudioDriver_SDL2_Duration_t(static_cast(GpAudioDriver_SDL2_Period_t::den * samplesSinceStart / GpAudioDriver_SDL2_Period_t::num / m_sampleRate)); + GpAudioDriver_SDL2_TimePoint_t audioMixBlockEndTime = audioMixStartTime + audioMixDurationSinceStart; m_mixChunkReadOffset = 0; - RefillMixChunk(mixingChannels, numChannels); + RefillMixChunk(mixingChannels, numChannels, samplesRemaining, audioMixBlockStartTime, audioMixBlockEndTime); + audioMixBlockStartTime = audioMixBlockEndTime; + + samplesRemaining -= availableInMixChunk; } } @@ -521,7 +660,7 @@ void GpAudioDriver_SDL2::MixAudio(void *stream, size_t len) mixingChannels[i]->Release(); } -void GpAudioDriver_SDL2::RefillMixChunk(GpAudioChannel_SDL2 *const*channels, size_t numChannels) +void GpAudioDriver_SDL2::RefillMixChunk(GpAudioChannel_SDL2 *const*channels, size_t numChannels, size_t maxSamplesToFill, GpAudioDriver_SDL2_TimePoint_t mixStartTime, GpAudioDriver_SDL2_TimePoint_t mixEndTime) { uint8_t audioMixBufferUnaligned[kMixChunkSize + GP_SYSTEM_MEMORY_ALIGNMENT]; uint8_t *audioMixBuffer = audioMixBufferUnaligned; @@ -536,28 +675,52 @@ void GpAudioDriver_SDL2::RefillMixChunk(GpAudioChannel_SDL2 *const*channels, siz const int16_t audioVolumeScale = m_audioVolumeScale; + size_t samplesToFill = kMixChunkSize; + if (samplesToFill > maxSamplesToFill) + { + m_mixChunkReadOffset += samplesToFill - maxSamplesToFill; + samplesToFill = maxSamplesToFill; + } + else + m_mixChunkReadOffset = 0; + + int16_t *mixChunkStart = m_mixChunk + m_mixChunkReadOffset; + int16_t audioNormalizeShift = 0; + for (size_t i = 0; i < numChannels; i++) { - channels[i]->Consume(audioMixBuffer, kMixChunkSize); + channels[i]->Consume(audioMixBuffer, samplesToFill, mixStartTime, mixEndTime); if (i == 0) { noAudio = false; - for (size_t j = 0; j < kMixChunkSize; j++) - m_mixChunk[j] = (static_cast(audioMixBuffer[j]) - 0x80) * audioVolumeScale; + audioNormalizeShift = 0x80; + for (size_t j = 0; j < samplesToFill; j++) + mixChunkStart[j] = static_cast(audioMixBuffer[j]); } else { - for (size_t j = 0; j < kMixChunkSize; j++) - m_mixChunk[j] += (static_cast(audioMixBuffer[j]) - 0x80) * audioVolumeScale; + audioNormalizeShift += 0x80; + for (size_t j = 0; j < samplesToFill; j++) + mixChunkStart[j] += static_cast(audioMixBuffer[j]); } } if (noAudio) - memset(m_mixChunk, 0, kMixChunkSize * sizeof(m_mixChunk[0])); + memset(mixChunkStart, 0, samplesToFill * sizeof(mixChunkStart[0])); + else + { + for (size_t i = 0; i < samplesToFill; i++) + mixChunkStart[i] = (mixChunkStart[i] - audioNormalizeShift) * audioVolumeScale; + } } +GpAudioDriver_SDL2_TimePoint_t GpAudioDriver_SDL2::GetCurrentTime() +{ + return std::chrono::high_resolution_clock::now(); +} + IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties) { void *storage = AlignedAlloc(sizeof(GpAudioDriver_SDL2), GP_SYSTEM_MEMORY_ALIGNMENT); diff --git a/AerofoilSDL/GpDisplayDriver_SDL_GL2.cpp b/AerofoilSDL/GpDisplayDriver_SDL_GL2.cpp index 56d93c6..fb4873f 100644 --- a/AerofoilSDL/GpDisplayDriver_SDL_GL2.cpp +++ b/AerofoilSDL/GpDisplayDriver_SDL_GL2.cpp @@ -8,6 +8,7 @@ #include "GpRingBuffer.h" #include "GpInputDriver_SDL_Gamepad.h" #include "GpSDL.h" +#include "GpUnicode.h" #include "IGpCursor.h" #include "IGpDisplayDriverSurface.h" #include "IGpLogDriver.h" @@ -52,68 +53,6 @@ struct GpDisplayDriver_SDL_GL2_Prefs bool m_isFullScreen; }; -namespace DeleteMe -{ - bool DecodeCodePoint(const uint8_t *characters, size_t availableCharacters, size_t &outCharactersDigested, uint32_t &outCodePoint) - { - if (availableCharacters <= 0) - return false; - - if ((characters[0] & 0x80) == 0x00) - { - outCharactersDigested = 1; - outCodePoint = characters[0]; - return true; - } - - size_t sz = 0; - uint32_t codePoint = 0; - uint32_t minCodePoint = 0; - if ((characters[0] & 0xe0) == 0xc0) - { - sz = 2; - minCodePoint = 0x80; - codePoint = (characters[0] & 0x1f); - } - else if ((characters[0] & 0xf0) == 0xe0) - { - sz = 3; - minCodePoint = 0x800; - codePoint = (characters[0] & 0x0f); - } - else if ((characters[0] & 0xf8) == 0xf0) - { - sz = 4; - minCodePoint = 0x10000; - codePoint = (characters[0] & 0x07); - } - else - return false; - - if (availableCharacters < sz) - return false; - - for (size_t auxByte = 1; auxByte < sz; auxByte++) - { - if ((characters[auxByte] & 0xc0) != 0x80) - return false; - - codePoint = (codePoint << 6) | (characters[auxByte] & 0x3f); - } - - if (codePoint < minCodePoint || codePoint > 0x10ffff) - return false; - - if (codePoint >= 0xd800 && codePoint <= 0xdfff) - return false; - - outCodePoint = codePoint; - outCharactersDigested = sz; - - return true; - } -} - namespace GpBinarizedShaders { extern const char *g_drawQuadV_GL2; @@ -846,9 +785,6 @@ private: GpComPtr m_upscaleTextureRTV; GpComPtr m_upscaleTexture; - uint32_t m_upscaleTextureWidth; - uint32_t m_upscaleTextureHeight; - GpComPtr m_quadVertexArray; GpComPtr m_quadVertexBufferKeepalive; GpComPtr m_quadIndexBuffer; @@ -905,7 +841,10 @@ private: uint32_t m_initialHeightVirtual; float m_pixelScaleX; float m_pixelScaleY; + bool m_useUpscaleFilter; + uint32_t m_upscaleTextureWidth; + uint32_t m_upscaleTextureHeight; GpCursor_SDL2 *m_activeCursor; GpCursor_SDL2 *m_pendingCursor; @@ -1197,6 +1136,8 @@ GpDisplayDriver_SDL_GL2::GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties , m_pixelScaleX(1.0f) , m_pixelScaleY(1.0f) , m_useUpscaleFilter(false) + , m_upscaleTextureWidth(0) + , m_upscaleTextureHeight(0) , m_pendingCursor(nullptr) , m_activeCursor(nullptr) , m_currentStandardCursor(EGpStandardCursors::kArrow) @@ -1531,8 +1472,7 @@ void GpDisplayDriver_SDL_GL2::ServeTicks(int ticks) logger->Printf(IGpLogDriver::Category_Information, "Resetting OpenGL context. Physical: %i x %i Virtual %i x %i", static_cast(m_windowWidthPhysical), static_cast(m_windowHeightPhysical), static_cast(m_windowWidthVirtual), static_cast(m_windowHeightVirtual)); // Drop everything and reset - m_res.~InstancedResources(); - new (&m_res) InstancedResources(); + m_res = InstancedResources(); if (m_firstSurface) m_firstSurface->DestroyAll(); @@ -2040,7 +1980,7 @@ void GpDisplayDriver_SDL_GL2::TranslateSDLMessage(const SDL_Event *msg, IGpVOSEv { uint32_t codePoint; size_t numDigested; - DeleteMe::DecodeCodePoint(reinterpret_cast(teEvt->text) + parseOffset, lenUTF8 - parseOffset, numDigested, codePoint); + GpUnicode::UTF8::Decode(reinterpret_cast(teEvt->text) + parseOffset, lenUTF8 - parseOffset, numDigested, codePoint); parseOffset += numDigested; @@ -2458,11 +2398,6 @@ bool GpDisplayDriver_SDL_GL2::InitResources(uint32_t physicalWidth, uint32_t phy if (logger) logger->Printf(IGpLogDriver::Category_Information, "GpDisplayDriver_SDL_GL2::InitResources"); - if ((m_pixelScaleX < 2.0f && m_pixelScaleX > 1.0f) || (m_pixelScaleY < 2.0f && m_pixelScaleY > 1.0f)) - m_useUpscaleFilter = true; - else - m_useUpscaleFilter = false; - CheckGLError(m_gl, logger); if (!InitBackBuffer(virtualWidth, virtualHeight)) @@ -2776,8 +2711,9 @@ bool GpDisplayDriver_SDL_GL2::InitBackBuffer(uint32_t width, uint32_t height) m_gl.BindFramebuffer(GL_FRAMEBUFFER, 0); } + m_useUpscaleFilter = ((m_pixelScaleX < 2.0f && m_pixelScaleX > 1.0f) || (m_pixelScaleY < 2.0f && m_pixelScaleY > 1.0f)); - if (m_pixelScaleX != floor(m_pixelScaleX) || m_pixelScaleY != floor(m_pixelScaleY)) + if (m_useUpscaleFilter) { uint32_t upscaleX = ceil(m_pixelScaleX); uint32_t upscaleY = ceil(m_pixelScaleY); @@ -2792,8 +2728,8 @@ bool GpDisplayDriver_SDL_GL2::InitBackBuffer(uint32_t width, uint32_t height) return false; } - m_res.m_upscaleTextureWidth = width * upscaleX; - m_res.m_upscaleTextureHeight = height * upscaleY; + m_upscaleTextureWidth = width * upscaleX; + m_upscaleTextureHeight = height * upscaleY; GLenum internalFormat = SupportsSizedFormats() ? GL_RGBA8 : GL_RGBA; @@ -2803,7 +2739,7 @@ bool GpDisplayDriver_SDL_GL2::InitBackBuffer(uint32_t width, uint32_t height) m_gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); m_gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); m_gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - m_gl.TexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_res.m_upscaleTextureWidth, m_res.m_upscaleTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + m_gl.TexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_upscaleTextureWidth, m_upscaleTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); m_gl.BindTexture(GL_TEXTURE_2D, 0); CheckGLError(m_gl, logger); @@ -2848,7 +2784,7 @@ void GpDisplayDriver_SDL_GL2::ScaleVirtualScreen() { m_gl.BindFramebuffer(GL_FRAMEBUFFER, m_res.m_upscaleTextureRTV->GetID()); - m_gl.Viewport(0, 0, m_res.m_upscaleTextureWidth, m_res.m_upscaleTextureHeight); + m_gl.Viewport(0, 0, m_upscaleTextureWidth, m_upscaleTextureHeight); const BlitQuadProgram &program = m_res.m_scaleQuadProgram; diff --git a/AerofoilSDL/GpMain_SDL_Win32.cpp b/AerofoilSDL/GpMain_SDL_Win32.cpp index d492b13..39a0198 100644 --- a/AerofoilSDL/GpMain_SDL_Win32.cpp +++ b/AerofoilSDL/GpMain_SDL_Win32.cpp @@ -1,6 +1,7 @@ #include "SDL.h" #include "GpMain.h" +#include "GpAllocator_C.h" #include "GpAudioDriverFactory.h" #include "GpDisplayDriverFactory.h" #include "GpGlobalConfig.h" @@ -59,6 +60,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine drivers->SetDriver(GpFileSystem_Win32::GetInstance()); drivers->SetDriver(GpSystemServices_Win32::GetInstance()); drivers->SetDriver(GpLogDriver_Win32::GetInstance()); + drivers->SetDriver(GpAllocator_C::GetInstance()); g_gpWindowsGlobals.m_hInstance = hInstance; g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance; @@ -86,6 +88,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine g_gpGlobalConfig.m_osGlobals = &g_gpWindowsGlobals; g_gpGlobalConfig.m_logger = logger; g_gpGlobalConfig.m_systemServices = GpSystemServices_Win32::GetInstance(); + g_gpGlobalConfig.m_allocator = GpAllocator_C::GetInstance(); GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_SDL_GL2, GpDriver_CreateDisplayDriver_SDL_GL2); GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_SDL2, GpDriver_CreateAudioDriver_SDL); diff --git a/AerofoilSDL/ShaderCode/DrawQuad32P.cpp b/AerofoilSDL/ShaderCode/DrawQuad32P.cpp index 2ae17df..1422afe 100644 --- a/AerofoilSDL/ShaderCode/DrawQuad32P.cpp +++ b/AerofoilSDL/ShaderCode/DrawQuad32P.cpp @@ -17,7 +17,7 @@ " vec4 resultColor = vec4(SamplePixel(texCoord.xy), 1.0);\n"\ " resultColor *= constants_Modulation;\n"\ "#ifdef ENABLE_FLICKER\n"\ -" resultColor = ApplyFlicker(constants_FlickerAxis, texCoord.zw, constants_FlickerStartThreshold, constants_FlickerEndThreshold, resultColor * constants_Modulation);\n"\ +" resultColor = ApplyFlicker(constants_FlickerAxis, texCoord.zw, constants_FlickerStartThreshold, constants_FlickerEndThreshold, resultColor);\n"\ " if (resultColor.a < 1.0)\n"\ " discard;\n"\ "#endif\n"\ diff --git a/AerofoilSDL/ShaderCode/DrawQuadPaletteP.cpp b/AerofoilSDL/ShaderCode/DrawQuadPaletteP.cpp index bd485f1..d9111d3 100644 --- a/AerofoilSDL/ShaderCode/DrawQuadPaletteP.cpp +++ b/AerofoilSDL/ShaderCode/DrawQuadPaletteP.cpp @@ -18,7 +18,7 @@ " vec4 resultColor = vec4(SamplePixel(texCoord.xy), 1.0);\n"\ " resultColor *= constants_Modulation;\n"\ "#ifdef ENABLE_FLICKER\n"\ -" resultColor = ApplyFlicker(constants_FlickerAxis, texCoord.zw, constants_FlickerStartThreshold, constants_FlickerEndThreshold, resultColor * constants_Modulation);\n"\ +" resultColor = ApplyFlicker(constants_FlickerAxis, texCoord.zw, constants_FlickerStartThreshold, constants_FlickerEndThreshold, resultColor);\n"\ " if (resultColor.a < 1.0)\n"\ " discard;\n"\ "#endif\n"\ diff --git a/AerofoilWeb/GpFileSystem_Web.cpp b/AerofoilWeb/GpFileSystem_Web.cpp index a9f2870..a5da4b6 100644 --- a/AerofoilWeb/GpFileSystem_Web.cpp +++ b/AerofoilWeb/GpFileSystem_Web.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "UTF8.h" @@ -29,6 +30,111 @@ typedef off_t off64_t; #define stat64 stat #endif +EM_JS(void, FlushFileSystem, (), { + Asyncify.handleSleep(wakeUp => { + FS.syncfs(false, function (err) { + assert(!err); + wakeUp(); + }); + }); +}); + + +class GpDirectoryCursor_Web final : public IGpDirectoryCursor +{ +public: + explicit GpDirectoryCursor_Web(DIR *dir, const std::string &prefix); + ~GpDirectoryCursor_Web(); + + bool GetNext(const char *&outFileName) override; + void Destroy() override; + +private: + DIR *m_dir; + std::string m_prefix; + std::string m_decodedFileName; +}; + +GpDirectoryCursor_Web::GpDirectoryCursor_Web(DIR *dir, const std::string &prefix) + : m_dir(dir) + , m_prefix(prefix) +{ +} + +GpDirectoryCursor_Web::~GpDirectoryCursor_Web() +{ + closedir(m_dir); +} + +bool GpDirectoryCursor_Web::GetNext(const char *&outFileName) +{ + const size_t prefixLength = m_prefix.size(); + + for (;;) + { + struct dirent *dir = readdir(m_dir); + if (!dir) + return false; + + const char *fname = dir->d_name; + + const size_t fnameLen = strlen(fname); + if (fnameLen > prefixLength && (prefixLength == 0 || !memcmp(&m_prefix[0], fname, prefixLength))) + { + const char *encodedResult = fname + prefixLength; + + m_decodedFileName.clear(); + for (size_t i = 0; encodedResult[i] != 0; i++) + { + char c = encodedResult[i]; + if (c == '%') + { + char highNibble = encodedResult[i + 1]; + if ((highNibble >= '0' && highNibble <= '9') || (highNibble >= 'a' && highNibble <= 'f') || (highNibble >= 'A' && highNibble <= 'F')) + { + char lowNibble = encodedResult[i + 2]; + + if ((lowNibble >= '0' && lowNibble <= '9') || (lowNibble >= 'a' && lowNibble <= 'f') || (lowNibble >= 'A' && lowNibble <= 'F')) + { + bool failedNibble = false; + char nibbles[2] = { highNibble, lowNibble }; + int decNibbles[2]; + for (int ni = 0; ni < 2; ni++) + { + char nc = nibbles[ni]; + if (nc >= '0' && nc <= '9') + decNibbles[ni] = nc - '0'; + else if (nc >= 'a' && nc <= 'f') + decNibbles[ni] = 0xa + (nc - 'a'); + else if (nc >= 'A' && nc <= 'F') + decNibbles[ni] = 0xa + (nc - 'A'); + else + failedNibble = true; + } + + if (!failedNibble) + { + c = static_cast((decNibbles[0] << 4) + decNibbles[1]); + i += 2; + } + } + } + } + + m_decodedFileName += c; + } + + outFileName = m_decodedFileName.c_str(); + return true; + } + } + return true; +} + +void GpDirectoryCursor_Web::Destroy() +{ + delete this; +} class GpFileStream_Web_StaticMemFile final : public GpIOStream { @@ -46,7 +152,7 @@ public: bool SeekEnd(GpUFilePos_t loc) override; GpUFilePos_t Size() const override; GpUFilePos_t Tell() const override; - void Close() override; + void GP_ASYNCIFY_PARANOID_NAMED(Close)() override; void Flush() override; private: @@ -136,7 +242,7 @@ GpUFilePos_t GpFileStream_Web_StaticMemFile::Tell() const return m_offset; } -void GpFileStream_Web_StaticMemFile::Close() +void GpFileStream_Web_StaticMemFile::GP_ASYNCIFY_PARANOID_NAMED(Close)() { delete this; } @@ -149,7 +255,7 @@ void GpFileStream_Web_StaticMemFile::Flush() class GpFileStream_Web_File final : public GpIOStream { public: - GpFileStream_Web_File(FILE *f, bool readOnly, bool writeOnly); + GpFileStream_Web_File(FILE *f, bool readOnly, bool writeOnly, bool synchronizeOnClose); ~GpFileStream_Web_File(); size_t Read(void *bytesOut, size_t size) override; @@ -162,7 +268,7 @@ public: bool SeekEnd(GpUFilePos_t loc) override; GpUFilePos_t Size() const override; GpUFilePos_t Tell() const override; - void Close() override; + void GP_ASYNCIFY_PARANOID_NAMED(Close)() override; void Flush() override; private: @@ -170,13 +276,15 @@ private: bool m_seekable; bool m_isReadOnly; bool m_isWriteOnly; + bool m_synchronizeOnClose; }; -GpFileStream_Web_File::GpFileStream_Web_File(FILE *f, bool readOnly, bool writeOnly) +GpFileStream_Web_File::GpFileStream_Web_File(FILE *f, bool readOnly, bool writeOnly, bool synchronizeOnClose) : m_f(f) , m_isReadOnly(readOnly) , m_isWriteOnly(writeOnly) + , m_synchronizeOnClose(synchronizeOnClose) { m_seekable = (fseek(m_f, 0, SEEK_CUR) == 0); } @@ -184,6 +292,9 @@ GpFileStream_Web_File::GpFileStream_Web_File(FILE *f, bool readOnly, bool writeO GpFileStream_Web_File::~GpFileStream_Web_File() { fclose(m_f); + + if (m_synchronizeOnClose) + GpFileSystem_Web::MarkFSStateDirty(); } size_t GpFileStream_Web_File::Read(void *bytesOut, size_t size) @@ -258,7 +369,7 @@ GpUFilePos_t GpFileStream_Web_File::Tell() const return static_cast(ftell(m_f)); } -void GpFileStream_Web_File::Close() +void GpFileStream_Web_File::GP_ASYNCIFY_PARANOID_NAMED(Close)() { this->~GpFileStream_Web_File(); free(this); @@ -269,20 +380,25 @@ void GpFileStream_Web_File::Flush() fflush(m_f); } -bool GpFileSystem_Web::ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution) + +bool GpFileSystem_Web::ms_fsStateDirty; + + +bool GpFileSystem_Web::ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, bool trailingSlash, std::string &resolution) { const char *prefsAppend = nullptr; + std::string unsanitized; switch (virtualDirectory) { case PortabilityLayer::VirtualDirectories::kApplicationData: - resolution = std::string("Packaged"); + unsanitized = std::string("Packaged"); break; case PortabilityLayer::VirtualDirectories::kGameData: - resolution = std::string("Packaged/Houses"); + unsanitized = std::string("Packaged/Houses"); break; case PortabilityLayer::VirtualDirectories::kFonts: - resolution = std::string("Resources"); + unsanitized = std::string("Resources"); break; case PortabilityLayer::VirtualDirectories::kHighScores: prefsAppend = "HighScores"; @@ -296,22 +412,55 @@ bool GpFileSystem_Web::ResolvePath(PortabilityLayer::VirtualDirectory_t virtualD case PortabilityLayer::VirtualDirectories::kPrefs: prefsAppend = "Prefs"; break; - case PortabilityLayer::VirtualDirectories::kFontCache: - prefsAppend = "FontCache"; - break; default: return false; }; if (prefsAppend) - resolution = m_prefsPath + prefsAppend; - else - resolution = m_basePath + resolution; - - for (size_t i = 0; i < numPaths; i++) { - resolution += "/"; - resolution += paths[i]; + unsanitized = prefsAppend; + + for (size_t i = 0; i < numPaths; i++) + { + unsanitized += "/"; + unsanitized += paths[i]; + } + + if (trailingSlash) + unsanitized += "/"; + + std::string sanitized; + for (size_t i = 0; i < unsanitized.size(); i++) + { + char c = unsanitized[i]; + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_') + sanitized += c; + else + { + const char *nibbles = "0123456789abcdef"; + char subPath[4]; + subPath[0] = '%'; + subPath[1] = nibbles[(c >> 4) & 0xf]; + subPath[2] = nibbles[c & 0xf]; + subPath[3] = 0; + + sanitized += subPath; + } + } + + resolution = m_prefsPath + "/" + sanitized; + } + else + { + std::string sanitized = m_basePath + unsanitized; + + for (size_t i = 0; i < numPaths; i++) + { + sanitized += "/"; + sanitized += paths[i]; + } + + resolution = sanitized; } return true; @@ -328,8 +477,7 @@ GpFileSystem_Web::~GpFileSystem_Web() void GpFileSystem_Web::Init() { - char *prefsDir = SDL_GetPrefPath("aerofoil", "aerofoil"); - m_prefsPath = prefsDir; + m_prefsPath = "/aerofoil"; char *baseDir = SDL_GetBasePath(); m_basePath = baseDir; @@ -338,14 +486,6 @@ void GpFileSystem_Web::Init() char baseDirSeparator = m_basePath[m_basePath.size() - 1]; if (m_basePath.size() >= 4 && m_basePath.substr(m_basePath.size() - 4, 3) == "bin") m_basePath = m_basePath.substr(0, m_basePath.size() - 4) + "lib" + baseDirSeparator + "aerofoil" + baseDirSeparator; - - const char *extensions[] = { "HighScores", "Houses", "SavedGames", "Prefs", "FontCache" }; - for (size_t i = 0; i < sizeof(extensions) / sizeof(extensions[0]); i++) - { - std::string prefsPath = std::string(prefsDir) + extensions[i]; - int created = mkdir(prefsPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - } - SDL_free(prefsDir); } bool GpFileSystem_Web::FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) @@ -363,7 +503,7 @@ bool GpFileSystem_Web::FileExists(PortabilityLayer::VirtualDirectory_t virtualDi } std::string resolvedPath; - if (!ResolvePath(virtualDirectory, &path, 1, resolvedPath)) + if (!ResolvePath(virtualDirectory, &path, 1, false, resolvedPath)) return false; struct stat s; @@ -389,7 +529,7 @@ bool GpFileSystem_Web::FileLocked(PortabilityLayer::VirtualDirectory_t virtualDi } std::string resolvedPath; - if (!ResolvePath(virtualDirectory, &path, 1, resolvedPath)) + if (!ResolvePath(virtualDirectory, &path, 1, false, resolvedPath)) { if (exists) exists = false; @@ -448,7 +588,7 @@ GpIOStream *GpFileSystem_Web::OpenFileNested(PortabilityLayer::VirtualDirectory_ return nullptr; std::string resolvedPath; - if (!ResolvePath(virtualDirectory, subPaths, numSubPaths, resolvedPath)) + if (!ResolvePath(virtualDirectory, subPaths, numSubPaths, false, resolvedPath)) return nullptr; void *objStorage = malloc(sizeof(GpFileStream_Web_File)); @@ -475,7 +615,7 @@ GpIOStream *GpFileSystem_Web::OpenFileNested(PortabilityLayer::VirtualDirectory_ } } - return new (objStorage) GpFileStream_Web_File(f, !writeAccess, false); + return new (objStorage) GpFileStream_Web_File(f, !writeAccess, false, writeAccess); } bool GpFileSystem_Web::DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) @@ -484,7 +624,7 @@ bool GpFileSystem_Web::DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDi return false; std::string resolvedPath; - if (!ResolvePath(virtualDirectory, &path, 1, resolvedPath)) + if (!ResolvePath(virtualDirectory, &path, 1, false, resolvedPath)) { existed = false; return false; @@ -493,6 +633,9 @@ bool GpFileSystem_Web::DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDi if (unlink(resolvedPath.c_str()) < 0) { existed = (errno != ENOENT); + if (existed) + FlushFileSystem(); + return false; } existed = true; @@ -599,7 +742,17 @@ IGpDirectoryCursor *GpFileSystem_Web::ScanDirectoryNested(PortabilityLayer::Virt if (const GpFileSystem_Web_Resources::FileCatalog *catalog = GetCatalogForVirtualDirectory(virtualDirectory)) return ScanCatalog(*catalog); - return nullptr; + std::string resolvedPrefix; + if (!ResolvePath(virtualDirectory, paths, numPaths, true, resolvedPrefix)) + return nullptr; + + std::string trimmedPrefix = resolvedPrefix.substr(m_prefsPath.size() + 1); + + DIR *d = opendir(m_prefsPath.c_str()); + if (!d) + return nullptr; + + return new GpDirectoryCursor_Web(d, trimmedPrefix); } const GpFileSystem_Web_Resources::FileCatalog *GpFileSystem_Web::GetCatalogForVirtualDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory) @@ -622,5 +775,33 @@ IGpDirectoryCursor *GpFileSystem_Web::ScanCatalog(const GpFileSystem_Web_Resourc return new GpDirectoryCursor_StringList(paths); } +void GpFileSystem_Web::MarkFSStateDirty() +{ + ms_fsStateDirty = true; +} + +void GpFileSystem_Web::FlushFS() +{ + if (ms_fsStateDirty) + { + ms_fsStateDirty = false; + FlushFileSystem(); + } +} + + +#if GP_ASYNCIFY_PARANOID +void GpIOStream::Close() +{ + this->GP_ASYNCIFY_PARANOID_NAMED(Close)(); + GpFileSystem_Web::FlushFS(); +} + +bool IGpFileSystem::DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) +{ + return static_cast(this)->DeleteFile(virtualDirectory, path, existed); +} + +#endif GpFileSystem_Web GpFileSystem_Web::ms_instance; diff --git a/AerofoilWeb/GpFileSystem_Web.h b/AerofoilWeb/GpFileSystem_Web.h index 236a10a..3eb7b81 100644 --- a/AerofoilWeb/GpFileSystem_Web.h +++ b/AerofoilWeb/GpFileSystem_Web.h @@ -21,7 +21,7 @@ public: bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override; bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &exists) override; GpIOStream *OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* subPaths, size_t numSubPaths, bool writeAccess, GpFileCreationDisposition_t createDisposition) override; - bool DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) override; + bool DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) GP_ASYNCIFY_PARANOID_OVERRIDE; IGpDirectoryCursor *ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths) override; bool ValidateFilePath(const char *path, size_t pathLen) const override; @@ -29,6 +29,9 @@ public: void SetDelayCallback(DelayCallback_t delayCallback) override; + static void MarkFSStateDirty(); + static void FlushFS(); + static GpFileSystem_Web *GetInstance(); private: @@ -51,12 +54,13 @@ private: static IGpDirectoryCursor *ScanCatalog(const GpFileSystem_Web_Resources::FileCatalog &catalog); - bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution); + bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, bool trailingSlash, std::string &resolution); DelayCallback_t m_delayCallback; std::string m_prefsPath; std::string m_basePath; + static bool ms_fsStateDirty; static GpFileSystem_Web ms_instance; }; diff --git a/AerofoilWeb/GpMain_SDL_Web.cpp b/AerofoilWeb/GpMain_SDL_Web.cpp index a424a87..6ca001c 100644 --- a/AerofoilWeb/GpMain_SDL_Web.cpp +++ b/AerofoilWeb/GpMain_SDL_Web.cpp @@ -19,18 +19,29 @@ #include "IGpVOSEventQueue.h" #include +#include GpXGlobals g_gpXGlobals; -extern "C" IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties); - IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties); IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties); IGpInputDriver *GpDriver_CreateInputDriver_SDL2_Gamepad(const GpInputDriverProperties &properties); +EM_JS(void, InitFileSystem, (), { + Asyncify.handleSleep(wakeUp => { + FS.mkdir('/aerofoil'); + FS.mount(IDBFS, {}, '/aerofoil'); + FS.syncfs(true, function (err) { + assert(!err); + wakeUp(); + }); + }); +}); int main(int argc, char* argv[]) { + InitFileSystem(); + GpLogDriver_Web::Init(); IGpLogDriver *logger = GpLogDriver_Web::GetInstance(); diff --git a/AerofoilWeb/Link.bat b/AerofoilWeb/Link.bat index 9950709..5ea6d17 100644 --- a/AerofoilWeb/Link.bat +++ b/AerofoilWeb/Link.bat @@ -1,5 +1,4 @@ set INPUT_DIR=. set OUTPUT_DIR=bin -set FLAGS=-flto -O3 -s USE_SDL=2 -s USE_ZLIB=1 -s ASYNCIFY -s ASYNCIFY_IGNORE_INDIRECT -s INITIAL_MEMORY=33554432 -s ASYNCIFY_ADVISE - +set FLAGS=-flto -O3 -s USE_SDL=2 -s USE_ZLIB=1 -s ASYNCIFY -s ASYNCIFY_IGNORE_INDIRECT -s INITIAL_MEMORY=33554432 -s ASYNCIFY_ADVISE -lidbfs.js -s ASYNCIFY_IMPORTS=['InitFileSystem','FlushFileSystem'] --shell-file shell_minimal.html emcc obj/AerofoilWeb_Combined.o obj/AerofoilWeb_Resources.o obj/GpShell_Combined.o obj/AerofoilSDL_Combined.o obj/GpApp_Combined.o obj/PortabilityLayer_Combined.o obj/MacRomanConversion.o -o %OUTPUT_DIR%/aerofoil.html %FLAGS% diff --git a/AerofoilWeb/shell_minimal.html b/AerofoilWeb/shell_minimal.html new file mode 100644 index 0000000..d7b8edb --- /dev/null +++ b/AerofoilWeb/shell_minimal.html @@ -0,0 +1,140 @@ + + + + + + Aerofoil Web Pre-Release + + + +
+
emscripten
+
Downloading...
+
+ +
+
+ +
+
+ + {{{ SCRIPT }}} + + diff --git a/AerofoilX/GpFileSystem_X.cpp b/AerofoilX/GpFileSystem_X.cpp index d81ca25..cae7130 100644 --- a/AerofoilX/GpFileSystem_X.cpp +++ b/AerofoilX/GpFileSystem_X.cpp @@ -185,8 +185,8 @@ bool GpFileSystem_X::ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDir case PortabilityLayer::VirtualDirectories::kPrefs: prefsAppend = "Prefs"; break; - case PortabilityLayer::VirtualDirectories::kFontCache: - prefsAppend = "FontCache"; + case PortabilityLayer::VirtualDirectories::kLogs: + prefsAppend = "Logs"; break; case PortabilityLayer::VirtualDirectories::kLogs: prefsAppend = ".."; @@ -231,7 +231,7 @@ void GpFileSystem_X::Init() if (m_basePath.size() >= 4 && m_basePath.substr(m_basePath.size() - 4, 3) == "bin") m_basePath = m_basePath.substr(0, m_basePath.size() - 4) + "lib" + baseDirSeparator + "aerofoil" + baseDirSeparator; - const char *extensions[] = { "HighScores", "Houses", "SavedGames", "Prefs", "FontCache" }; + const char *extensions[] = { "HighScores", "Houses", "SavedGames", "Prefs", "Logs" }; for (size_t i = 0; i < sizeof(extensions) / sizeof(extensions[0]); i++) { std::string prefsPath = std::string(prefsDir) + extensions[i]; diff --git a/AerofoilX/GpMain_SDL_X.cpp b/AerofoilX/GpMain_SDL_X.cpp index 7f76d72..4d78b8f 100644 --- a/AerofoilX/GpMain_SDL_X.cpp +++ b/AerofoilX/GpMain_SDL_X.cpp @@ -32,13 +32,26 @@ int main(int argc, char *argv[]) SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[]) #endif { + bool enableLogging = false; + for (int i = 1; i < argc; i++) + { + if (!strcmp(argv[i], "-diagnostics")) + enableLogging = true; + } + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0) return -1; GpFileSystem_X::GetInstance()->Init(); - GpLogDriver_X::Init(); - IGpLogDriver *logger = GpLogDriver_X::GetInstance(); + IGpLogDriver *logger = nullptr; + + if (enableLogging) + { + GpLogDriver_X::Init(); + logger = GpLogDriver_X::GetInstance(); + } + GpDriverCollection *drivers = GpAppInterface_Get()->PL_GetDriverCollection(); drivers->SetDriver(GpFileSystem_X::GetInstance()); diff --git a/ApplicationResourcePatches/STR/1006.txt b/ApplicationResourcePatches/STR/1006.txt new file mode 100644 index 0000000..413ecb7 --- /dev/null +++ b/ApplicationResourcePatches/STR/1006.txt @@ -0,0 +1,26 @@ +A never-before-seen error has arisen. Proceed with caution! (Save and Quit immediately.) +I failed to open the house's resource fork. Any unique room backgrounds are not accessible. +I failed to add a resource to the house's resource fork. See error number. +I failed to create a new resource fork for the house. See error number for problem. +There are no houses on this drive! About your only option is to create your own new house with the Editor. +This house is incompatible with us! You'll need to upgrade Glider PRO to use this house. Do not attempt to play/edit this house! +The background specified by this room was not found! Try re-selecting a new background (the Room Info menu). +The room number is out of bounds. I suspect the house file is corrupt. Try deleting this "illegal" room though. +The data is missing that specifies where the openings in this room are. The house may be damaged. Try selecting a new background though. +There was a problem with the clipboard (Cut, Copy and Paste commands). I couldn't guess why. +I think we just ran out of memory. Quit now and give Glider PROª more memory. +We failed to write the house to disk. (That shouldn't have happened.) +Well, the music didn't load. Glider PROª will still run, you'll just be musically challenged. +Wow, there was a problem bringing sounds up. You might try giving Glider PROª more memory - otherwise ... silence. +Some kind of strange Apple Event error. I think I would just ignore it. Or call Casady & Greene with the error number. +Did you save the house on the same volume Glider PRO is on? I saved the house but had to re-open the old house because I couldn't find the new one. +Wow, I couldn't find the old or new house. Go to the Select House menu item and see if it's there. If not, make sure they're on the same volume as Glider PRO. +Couldn't create a saved game structure. Memory is probably too low. +The saved game doesn't match the house. Either this game was saved for a different house or the house was modified recently. +This saved game is an old version. We cannot use this game with this house. +The number of rooms saved doesn't match the number of house rooms. We cannot use this game with this house. +The QuickTimeª movie that goes with this house will not be used. Glider PROª must have enough memory to easily load the entire movie into RAM. +This house has no rooms! Do not attempt to play this house! Select a new house to play. +There was an error generating or parsing a links list. Memory may be tight. +This house contains invalid data that couldn't be repaired. Select a new house to play. +This house contained invalid data, which was repaired. Some things may be missing or not work correctly. \ No newline at end of file diff --git a/ApplicationResourcePatches/manifest.json b/ApplicationResourcePatches/manifest.json index b403f5a..fb2e19e 100644 --- a/ApplicationResourcePatches/manifest.json +++ b/ApplicationResourcePatches/manifest.json @@ -37,7 +37,8 @@ "LICS/1003.txt" : "ApplicationResourcePatches/LICS/1003.txt", "LICS/1004.txt" : "ApplicationResourcePatches/LICS/1004.txt", "LICS/1005.txt" : "ApplicationResourcePatches/LICS/1005.txt", - "LICS/1006.txt" : "ApplicationResourcePatches/LICS/1006.txt" + "LICS/1006.txt" : "ApplicationResourcePatches/LICS/1006.txt", + "STR$23/1006.txt" : "ApplicationResourcePatches/STR/1006.txt" }, "delete" : [ diff --git a/CMakeLists.txt b/CMakeLists.txt index ed16c19..e6e9c93 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,7 +118,6 @@ add_library(PortabilityLayer STATIC PortabilityLayer/SimpleGraphic.cpp PortabilityLayer/TextPlacer.cpp PortabilityLayer/UTF8.cpp - PortabilityLayer/UTF16.cpp PortabilityLayer/WindowDef.cpp PortabilityLayer/WindowManager.cpp PortabilityLayer/WorkerThread.cpp diff --git a/Common/CoreDefs.h b/Common/CoreDefs.h index 55fa0c4..8e597ed 100644 --- a/Common/CoreDefs.h +++ b/Common/CoreDefs.h @@ -60,12 +60,16 @@ static const size_t GP_SYSTEM_MEMORY_ALIGNMENT = 16; #define GP_ASYNCIFY_PARANOID 0 #endif +#define GP_ASYNCIFY_PARANOID_VALIDATION 0 + #if GP_ASYNCIFY_PARANOID #define GP_ASYNCIFY_PARANOID_VIRTUAL #define GP_ASYNCIFY_PARANOID_PURE #define GP_ASYNCIFY_PARANOID_OVERRIDE +#define GP_ASYNCIFY_PARANOID_NAMED(n) GpAsyncifyParanoid##n #else #define GP_ASYNCIFY_PARANOID_VIRTUAL virtual #define GP_ASYNCIFY_PARANOID_PURE = 0 #define GP_ASYNCIFY_PARANOID_OVERRIDE override +#define GP_ASYNCIFY_PARANOID_NAMED(n) n #endif diff --git a/ConvertColorCursors/ConvertColorCursors.cpp b/ConvertColorCursors/ConvertColorCursors.cpp index a35b39e..4d8ee7e 100644 --- a/ConvertColorCursors/ConvertColorCursors.cpp +++ b/ConvertColorCursors/ConvertColorCursors.cpp @@ -1,11 +1,13 @@ #include "CFileStream.h" #include "BMPFormat.h" +#include "GpAllocator_C.h" #include "MMHandleBlock.h" #include "ResourceCompiledTypeList.h" #include "ResourceFile.h" #include "SharedTypes.h" #include "QDStandardPalette.h" #include "PLBigEndian.h" +#include "PLDrivers.h" #include #include @@ -141,6 +143,9 @@ int main(int argc, const char **argv) PortabilityLayer::CFileStream stream(f); + GpDriverCollection *drivers = PLDrivers::GetDriverCollection(); + drivers->SetDriver(GpAllocator_C::GetInstance()); + PortabilityLayer::ResourceFile *resFile = PortabilityLayer::ResourceFile::Create(); if (!resFile->Load(&stream)) return -1; diff --git a/ConvertColorCursors/ConvertColorCursors.vcxproj b/ConvertColorCursors/ConvertColorCursors.vcxproj index 803089b..930df10 100644 --- a/ConvertColorCursors/ConvertColorCursors.vcxproj +++ b/ConvertColorCursors/ConvertColorCursors.vcxproj @@ -42,6 +42,7 @@ + @@ -50,6 +51,7 @@ + @@ -81,6 +83,7 @@
+ diff --git a/ConvertColorCursors/ConvertColorCursors.vcxproj.filters b/ConvertColorCursors/ConvertColorCursors.vcxproj.filters index 310100b..d12c435 100644 --- a/ConvertColorCursors/ConvertColorCursors.vcxproj.filters +++ b/ConvertColorCursors/ConvertColorCursors.vcxproj.filters @@ -21,5 +21,8 @@ Source Files + + Source Files +
\ No newline at end of file diff --git a/ConvertResources.bat b/ConvertResources.bat index 86f8bf5..f42e531 100644 --- a/ConvertResources.bat +++ b/ConvertResources.bat @@ -86,6 +86,9 @@ x64\Release\FTagData.exe "DefaultTimestamp.timestamp" "Packaged\Houses\Titanic.m copy /Y GliderProData\ConvertedMovies\*.mov.gpa Packaged\Houses\ +rem Patch bad Castle 'o the Air start room +x64\Release\HouseTool.exe patch "Packaged\Houses\Castle o' the Air.gpd" .firstRoom 77 + x64\Release\MergeGPF.exe "Packaged\Houses\Art Museum.gpf" x64\Release\MergeGPF.exe "Packaged\Houses\California or Bust!.gpf" x64\Release\MergeGPF.exe "Packaged\Houses\Castle o' the Air.gpf" diff --git a/GenerateFonts/GenerateFonts.cpp b/GenerateFonts/GenerateFonts.cpp index 7534a47..d425ddb 100644 --- a/GenerateFonts/GenerateFonts.cpp +++ b/GenerateFonts/GenerateFonts.cpp @@ -3,6 +3,7 @@ #include "FontRenderer.h" #include "IGpFont.h" #include "IGpFontHandler.h" +#include "GpAllocator_C.h" #include "GpAppInterface.h" #include "GpDriverIndex.h" #include "GpFontHandlerProperties.h" @@ -31,7 +32,7 @@ public: bool SeekEnd(GpUFilePos_t loc) override; GpUFilePos_t Size() const override; GpUFilePos_t Tell() const override; - void Close() override; + void GP_ASYNCIFY_PARANOID_NAMED(Close)() override; void Flush() override; const uint8_t *GetBytes() const; @@ -167,8 +168,14 @@ bool KnownFontSpec::operator!=(const KnownFontSpec &other) const int toolMain(int argc, const char **argv) { + IGpAllocator *alloc = GpAllocator_C::GetInstance(); + GpFontHandlerProperties fhProperties; fhProperties.m_type = EGpFontHandlerType_FreeType2; + fhProperties.m_alloc = alloc; + + GpDriverCollection *drivers = PLDrivers::GetDriverCollection(); + drivers->SetDriver(alloc); IGpFontHandler *ft2Handler = GpDriver_CreateFontHandler_FreeType2(fhProperties); @@ -201,8 +208,10 @@ int toolMain(int argc, const char **argv) int variation = fontFamily->GetVariationForFlags(flags); PortabilityLayer::FontHacks hacks; + PortabilityLayer::VirtualDirectory_t vDir; const char *path = nullptr; - fontFamily->GetFontSpec(variation, hacks, path); + int typeFaceIndex = 0; + fontFamily->GetFontSpec(variation, hacks, vDir, path, typeFaceIndex); KnownFontSpec spec(path, size, aa, hacks); @@ -218,7 +227,7 @@ int toolMain(int argc, const char **argv) { PortabilityLayer::CFileStream stream(fontFile); - IGpFont *font = ft2Handler->LoadFont(&stream); + IGpFont *font = ft2Handler->LoadFont(&stream, typeFaceIndex); if (!ft2Handler->KeepStreamOpen()) stream.Close(); diff --git a/GenerateFonts/GenerateFonts.vcxproj b/GenerateFonts/GenerateFonts.vcxproj index 2a6530b..57a1326 100644 --- a/GenerateFonts/GenerateFonts.vcxproj +++ b/GenerateFonts/GenerateFonts.vcxproj @@ -43,6 +43,7 @@ + @@ -52,6 +53,7 @@ + @@ -93,6 +95,7 @@ + diff --git a/GenerateFonts/GenerateFonts.vcxproj.filters b/GenerateFonts/GenerateFonts.vcxproj.filters index 9e43b4f..e46cc5f 100644 --- a/GenerateFonts/GenerateFonts.vcxproj.filters +++ b/GenerateFonts/GenerateFonts.vcxproj.filters @@ -18,5 +18,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/GpApp/Android.mk b/GpApp/Android.mk index 6225bb7..3359f87 100644 --- a/GpApp/Android.mk +++ b/GpApp/Android.mk @@ -15,75 +15,7 @@ LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0 -DGP_ZLIB_BUILTIN=1 # Add your application source files here... LOCAL_SRC_FILES := \ - About.cpp \ - AnimCursor.cpp \ - AppleEvents.cpp \ - Banner.cpp \ - ColorUtils.cpp \ - Coordinates.cpp \ - DialogUtils.cpp \ - DynamicMaps.cpp \ - Dynamics.cpp \ - Dynamics2.cpp \ - Dynamics3.cpp \ - Environ.cpp \ - Events.cpp \ - FileError.cpp \ - GameOver.cpp \ - GpAppInterface.cpp \ - Grease.cpp \ - HighScores.cpp \ - House.cpp \ - HouseInfo.cpp \ - HouseIO.cpp \ - HouseLegal.cpp \ - Input.cpp \ - Interactions.cpp \ - InterfaceInit.cpp \ - Link.cpp \ - Main.cpp \ - MainMenuUI.cpp \ - MainWindow.cpp \ - Map.cpp \ - Marquee.cpp \ - Menu.cpp \ - Modes.cpp \ - Music.cpp \ - ObjectAdd.cpp \ - ObjectDraw.cpp \ - ObjectDraw2.cpp \ - ObjectDrawAll.cpp \ - ObjectEdit.cpp \ - ObjectInfo.cpp \ - ObjectRects.cpp \ - Objects.cpp \ - Play.cpp \ - Player.cpp \ - Prefs.cpp \ - RectUtils.cpp \ - Render.cpp \ - Room.cpp \ - RoomGraphics.cpp \ - RoomInfo.cpp \ - RubberBands.cpp \ - SavedGames.cpp \ - Scoreboard.cpp \ - Scrap.cpp \ - SelectHouse.cpp \ - Settings.cpp \ - Sound.cpp \ - SoundSync_Cpp11.cpp \ - SourceExport.cpp \ - StringUtils.cpp \ - StructuresInit.cpp \ - StructuresInit2.cpp \ - Tools.cpp \ - Transit.cpp \ - Transitions.cpp \ - Triggers.cpp \ - Trip.cpp \ - Utilities.cpp \ - WindowUtils.cpp + GpApp_Combined.cpp LOCAL_STATIC_LIBRARIES := PortabilityLayer diff --git a/GpApp/Banner.cpp b/GpApp/Banner.cpp index 2c224b5..0bdcc5d 100644 --- a/GpApp/Banner.cpp +++ b/GpApp/Banner.cpp @@ -119,7 +119,7 @@ void DrawBannerMessage (Point topLeft) PasStringCopy((*thisHouse)->banner, bannerStr); - PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12Bold); + PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12SyntheticBold); PortabilityLayer::ResolveCachingColor blackColor = StdColors::Black(); @@ -224,7 +224,7 @@ void DisplayStarsRemaining(void) DrawSurface *surface = starsWindow->GetDrawSurface(); - PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12Bold); + PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12SyntheticBold); NumToString((long)numStarsRemaining, theStr); diff --git a/GpApp/Events.cpp b/GpApp/Events.cpp index 8e94c1e..b6f109c 100644 --- a/GpApp/Events.cpp +++ b/GpApp/Events.cpp @@ -339,6 +339,8 @@ void KeepWindowInBounds(Window *window) void HandleEditorResolutionChange(void) { + int oldRoom = thisRoomNumber; + FlushResolutionChange(); RecomputeInterfaceRects(); @@ -353,6 +355,9 @@ void HandleEditorResolutionChange(void) //RefreshScoreboard(wasScoreboardTitleMode); //DumpScreenOn(&justRoomsRect); + CopyRoomToThisRoom(oldRoom); + ReflectCurrentRoom(false); + if (toolsWindow) PortabilityLayer::WindowManager::GetInstance()->PutWindowBehind(toolsWindow, PortabilityLayer::WindowManager::GetInstance()->GetPutInFrontSentinel()); diff --git a/GpApp/GameOver.cpp b/GpApp/GameOver.cpp index b5beec7..d7e28da 100644 --- a/GpApp/GameOver.cpp +++ b/GpApp/GameOver.cpp @@ -108,7 +108,7 @@ void SetUpFinalScreen (void) { GetLineOfText(tempStr, count, subStr); - PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12Bold); + PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12SyntheticBold); offset = ((thisMac.constrainedScreen.right - thisMac.constrainedScreen.left) - appFont->MeasurePStr(subStr)) / 2; diff --git a/GpApp/GliderDefines.h b/GpApp/GliderDefines.h index 6925196..5e167a0 100644 --- a/GpApp/GliderDefines.h +++ b/GpApp/GliderDefines.h @@ -39,6 +39,8 @@ #define kYellowQTMovieNotLoaded 22 #define kYellowNoRooms 23 #define kYellowCantOrderLinks 24 +#define kYellowHouseDamaged 25 +#define kYellowHouseRepaired 26 #define kSwitchIfNeeded 0 @@ -261,6 +263,8 @@ #define kMaxStars 4 #define kMaxShredded 4 #define kMaxDynamicObs 18 +#define kMaxSoundTriggers 1 +#define kMaxStairs 1 #define kMaxMasterObjects 216 // kMaxRoomObs * 9 #define kMaxViewWidth 1536 #define kMaxViewHeight (kTileHigh*3+20) @@ -626,3 +630,13 @@ static const Boolean kFaceLeft = FALSE; // Conflicts with GP input driver #define kBBQCoalsComponent 1 #define kPendulumComponent 1 #define kStarComponent 1 + + +#define kMapGroundValue 56 +#define kUpwardVentMinY 36 + +#define kMouseholeBottom 295 +#define kFireplaceBottom 297 +#define kManholeSits 322 +#define kGrecoVentTop 303 +#define kSewerBlowerTop 292 diff --git a/GpApp/GliderProtos.h b/GpApp/GliderProtos.h index b09caf5..a40734a 100644 --- a/GpApp/GliderProtos.h +++ b/GpApp/GliderProtos.h @@ -9,6 +9,7 @@ #include "GliderStructs.h" struct GpMouseInputEvent; +struct houseType; //-------------------------------------------------------------- Prototypes @@ -124,7 +125,7 @@ void DoHouseInfo (void); // --- HouseInfo.c Boolean OpenHouse (Boolean load); // --- HouseIO.c Boolean OpenSpecificHouse (const VFileSpec &); Boolean SaveHouseAs (void); -Boolean ReadHouse (GpIOStream *houseStream); +Boolean ReadHouse (GpIOStream *houseStream, bool untrusted); Boolean WriteHouse (Boolean); Boolean CloseHouse (void); void OpenHouseResFork (void); @@ -149,7 +150,7 @@ void GetDemoInput (gliderPtr); // --- Input.c void GetInput (gliderPtr); SInt16 MergeFloorSuite (SInt16, SInt16); // --- Link.c -void ExtractFloorSuite (SInt16, SInt16 *, SInt16 *); +void ExtractFloorSuite (const houseType *house, SInt16, SInt16 *, SInt16 *); void UpdateLinkControl (void); void UpdateLinkWindow (void); void OpenLinkWindow (void); @@ -321,6 +322,7 @@ void DuplicateObject (void); void MoveObject (SInt16, Boolean); void DeselectObject (void); Boolean ObjectHasHandle (SInt16 *, SInt16 *); +Boolean BlowerTypeHasUpperLimit (SInt16); void HandleBlowerGlider (void); void SelectNextObject (void); void SelectPrevObject (void); diff --git a/GpApp/GliderStructs.h b/GpApp/GliderStructs.h index 328c595..1323aa9 100644 --- a/GpApp/GliderStructs.h +++ b/GpApp/GliderStructs.h @@ -191,7 +191,7 @@ struct houseType Str255 banner; // 256 Str255 trailer; // 256 scoresType highScores; // 292 - gameType savedGame; // 40 + gameType savedGame_Unused; // 40 Boolean hasGame; // 1 Boolean unusedBoolean; // 1 int16_t firstRoom; // 2 diff --git a/GpApp/HighScores.cpp b/GpApp/HighScores.cpp index c033ad9..aa84ddc 100644 --- a/GpApp/HighScores.cpp +++ b/GpApp/HighScores.cpp @@ -149,7 +149,7 @@ void DrawHighScores (DrawSurface *surface) DisposeGWorld(tempMap); DisposeGWorld(tempMask); - PortabilityLayer::RenderedFont *appFont14 = GetFont(PortabilityLayer::FontPresets::kApplication14Bold); + PortabilityLayer::RenderedFont *appFont14 = GetFont(PortabilityLayer::FontPresets::kApplication14SyntheticBold); PasStringCopy(PSTR("\xa5 "), tempStr); PasStringConcat(tempStr, thisHouseName); @@ -161,7 +161,7 @@ void DrawHighScores (DrawSurface *surface) const Point scoreTextPoint = Point::Create(scoreLeft + ((kScoreWide - appFont14->MeasurePStr(tempStr)) / 2), dropIt - 65); surface->DrawString(scoreTextPoint, tempStr, cyanColor, appFont14); - PortabilityLayer::RenderedFont *appFont12 = GetFont(PortabilityLayer::FontPresets::kApplication12Bold); + PortabilityLayer::RenderedFont *appFont12 = GetFont(PortabilityLayer::FontPresets::kApplication12SyntheticBold); thisHousePtr = *thisHouse; // message for score #1 @@ -268,7 +268,7 @@ void DrawHighScores (DrawSurface *surface) } } - PortabilityLayer::RenderedFont *appFont9 = GetFont(PortabilityLayer::FontPresets::kApplication9Bold); + PortabilityLayer::RenderedFont *appFont9 = GetFont(PortabilityLayer::FontPresets::kApplication9SyntheticBold); const Point textPos = Point::Create(scoreLeft + 80, dropIt - 1 + (10 * kScoreSpacing)); GetLocalizedString(8, tempStr); diff --git a/GpApp/House.cpp b/GpApp/House.cpp index 78042ed..94da04a 100644 --- a/GpApp/House.cpp +++ b/GpApp/House.cpp @@ -385,7 +385,7 @@ void GenerateLinksList (void) thisObject = thisHousePtr->rooms[r].objects[i]; if (thisObject.data.e.where != -1) { - ExtractFloorSuite(thisObject.data.e.where, &floor, &suite); + ExtractFloorSuite(*thisHouse, thisObject.data.e.where, &floor, &suite); roomLinked = GetRoomNumber(floor, suite); objectLinked = (short)thisObject.data.e.who; linksList[numLinks].srcRoom = r; @@ -405,7 +405,7 @@ void GenerateLinksList (void) thisObject = thisHousePtr->rooms[r].objects[i]; if (thisObject.data.d.where != -1) { - ExtractFloorSuite(thisObject.data.d.where, &floor, &suite); + ExtractFloorSuite(*thisHouse, thisObject.data.d.where, &floor, &suite); roomLinked = GetRoomNumber(floor, suite); objectLinked = (short)thisObject.data.d.who; linksList[numLinks].srcRoom = r; @@ -597,7 +597,7 @@ void GenerateRetroLinks (void) thisObject = thisHousePtr->rooms[r].objects[i]; if (thisObject.data.e.where != -1) { - ExtractFloorSuite(thisObject.data.e.where, &floor, &suite); + ExtractFloorSuite(*thisHouse, thisObject.data.e.where, &floor, &suite); roomLinked = GetRoomNumber(floor, suite); if (roomLinked == thisRoomNumber) { @@ -620,7 +620,7 @@ void GenerateRetroLinks (void) thisObject = thisHousePtr->rooms[r].objects[i]; if (thisObject.data.d.where != -1) { - ExtractFloorSuite(thisObject.data.d.where, &floor, &suite); + ExtractFloorSuite(*thisHouse, thisObject.data.d.where, &floor, &suite); roomLinked = GetRoomNumber(floor, suite); if (roomLinked == thisRoomNumber) { @@ -794,7 +794,7 @@ void ConvertHouseVer1To2 (void) case kDeluxeTrans: if (thisRoom->objects[h].data.d.where != -1) { - ExtractFloorSuite(thisRoom->objects[h].data.d.where, &floor, &suite); + ExtractFloorSuite(*thisHouse, thisRoom->objects[h].data.d.where, &floor, &suite); floor += kNumUndergroundFloors; thisRoom->objects[h].data.d.where = MergeFloorSuite(floor, suite); } @@ -810,7 +810,7 @@ void ConvertHouseVer1To2 (void) case kLgTrigger: if (thisRoom->objects[h].data.e.where != -1) { - ExtractFloorSuite(thisRoom->objects[h].data.e.where, &floor, &suite); + ExtractFloorSuite(*thisHouse, thisRoom->objects[h].data.e.where, &floor, &suite); floor += kNumUndergroundFloors; thisRoom->objects[h].data.e.where = MergeFloorSuite(floor, suite); } diff --git a/GpApp/HouseIO.cpp b/GpApp/HouseIO.cpp index 16a433a..e0cb0f7 100644 --- a/GpApp/HouseIO.cpp +++ b/GpApp/HouseIO.cpp @@ -15,6 +15,7 @@ #include "IGpLogDriver.h" #include "IGpSystemServices.h" #include "ObjectEdit.h" +#include "RectUtils.h" #include "ResourceManager.h" #include "PLDialogs.h" @@ -158,7 +159,7 @@ Boolean OpenHouse (Boolean read) if (read) { - Boolean readOK = ReadHouse(houseStream); + Boolean readOK = ReadHouse(houseStream, theHousesSpecs[thisHouseIndex].m_dir != PortabilityLayer::VirtualDirectories::kGameData); houseStream->Close(); return readOK; @@ -523,7 +524,7 @@ bool ByteSwapHouse(housePtr house, size_t sizeInBytes, bool isSwappedAfter) SanitizePascalStr(house->banner); SanitizePascalStr(house->trailer); ByteSwapScores(&house->highScores); - ByteSwapSavedGame(&house->savedGame); + ByteSwapSavedGame(&house->savedGame_Unused); PortabilityLayer::ByteSwap::BigInt16(house->firstRoom); PortabilityLayer::ByteSwap::BigInt16(house->nRooms); @@ -542,10 +543,1402 @@ bool ByteSwapHouse(housePtr house, size_t sizeInBytes, bool isSwappedAfter) return true; } -Boolean ReadHouse (GpIOStream *houseStream) +static bool FailCheck(bool value) +{ + return value; +} + +static bool SucceedCheck(bool value) +{ + return value; +} + +static bool LCheck(bool value) +{ + if (!value) + return FailCheck(value); + + return value; +} + +static bool RCheck(bool value) +{ + if (value) + return SucceedCheck(value); + + return value; +} + +template +bool LegalizePascalStr(uint8_t(&chars)[TSize], bool &anyRepairs) +{ + const size_t maxLength = TSize - 1; + if (chars[0] > maxLength) + { + chars[0] = static_cast(maxLength); + anyRepairs = RCheck(true); + return true; + } + + return true; +} + +static void LegalizeBoolean(Boolean &b) +{ + if (b < 0 || b > 1) + b = 1; +} + +static bool LegalizeScores(scoresType *scores, bool &anyRepairs) +{ + if (!LegalizePascalStr(scores->banner, anyRepairs)) + return LCheck(false); + + for (int i = 0; i < kMaxScores; i++) + if (!LegalizePascalStr(scores->names[i], anyRepairs)) + return LCheck(false); + + return true; +} + +static bool LegalizeRoomLayout(houseType *house, size_t roomNum, bool &anyRepairs) +{ + roomType *room = house->rooms + roomNum; + if (room->suite == kRoomIsEmpty) + return true; + + if (room->suite < 0 || room->suite >= kMaxNumRoomsH) + { + room->suite = kRoomIsEmpty; + anyRepairs = RCheck(true); + return true; + } + + if (room->floor > (kMaxNumRoomsV - kNumUndergroundFloors) || room->floor <= -kNumUndergroundFloors) + { + room->suite = kRoomIsEmpty; + anyRepairs = RCheck(true); + return true; + } + + for (size_t ori = 0; ori < roomNum; ori++) + { + const roomType *otherRoom = house->rooms + ori; + if (otherRoom->floor == room->floor && otherRoom->suite == room->suite) + { + room->suite = kRoomIsEmpty; + anyRepairs = RCheck(true); + return true; + } + } + + return true; +} + +static void LegalizeTopLeft(Point &topLeft, bool &anyRepairs) +{ + if (topLeft.h < 0) + { + anyRepairs = RCheck(true); + topLeft.h = 0; + } + else if (topLeft.h >= kRoomWide) + { + anyRepairs = RCheck(true); + topLeft.h = kRoomWide - 1; + } + + if (topLeft.v < 0) + { + anyRepairs = RCheck(true); + topLeft.v = 0; + } + else if (topLeft.v >= kTileHigh) + { + anyRepairs = RCheck(true); + topLeft.v = kTileHigh - 1; + } +} + +template +void LegalizeExpect(const TCondA &condA, const TCondB &condB, TSet &set, const TSetTo &setTo, bool &anyRepairs) +{ + if (condA == condB && set != setTo) + { + set = setTo; + anyRepairs = RCheck(true); + } +} + +static Boolean ForceRectInRoomRect(Rect &rect) +{ + Rect roomRect; + QSetRect(&roomRect, 0, 0, kRoomWide, kTileHigh); + + return ForceRectInRect(&rect, &roomRect); +} + + +static bool LegalizeBlower(houseType *house, size_t roomNum, size_t objectNum, bool &anyRepairs) +{ + roomType *room = house->rooms + roomNum; + objectType *obj = room->objects + objectNum; + blowerType *blower = &obj->data.a; + + LegalizeBoolean(blower->initial); + LegalizeBoolean(blower->state); + + int direction = -1; + for (int i = 0; i < 4; i++) + { + if (blower->vector & (1 << i)) + { + if (direction >= 0) + anyRepairs = RCheck(true); + else + direction = i; + } + } + + static const int kDirectionUp = 0; + static const int kDirectionRight = 1; + static const int kDirectionDown = 2; + static const int kDirectionLeft = 3; + + if (direction < 0 || direction > 3) + direction = kDirectionUp; + + LegalizeTopLeft(blower->topLeft, anyRepairs); + + switch (obj->what) + { + case kFloorVent: + case kFloorBlower: + case kSewerGrate: + case kTaper: + case kCandle: + case kStubby: + case kTiki: + case kBBQ: + case kGrecoVent: + case kSewerBlower: + if (direction != kDirectionUp) + direction = kDirectionUp; + break; + case kCeilingVent: + case kCeilingBlower: + if (direction != kDirectionDown) + direction = kDirectionDown; + break; + case kRightFan: + if (direction != kDirectionRight) + direction = kDirectionRight; + break; + case kLeftFan: + if (direction != kDirectionLeft) + direction = kDirectionLeft; + break; + case kInvisBlower: + case kLiftArea: + break; + default: + return LCheck(false); + } + + LegalizeExpect(obj->what, kFloorVent, blower->topLeft.v, kFloorVentTop, anyRepairs); + LegalizeExpect(obj->what, kFloorBlower, blower->topLeft.v, kFloorBlowerTop, anyRepairs); + LegalizeExpect(obj->what, kSewerGrate, blower->topLeft.v, kSewerGrateTop, anyRepairs); + LegalizeExpect(obj->what, kCeilingVent, blower->topLeft.v, kCeilingVentTop, anyRepairs); + LegalizeExpect(obj->what, kCeilingBlower, blower->topLeft.v, kCeilingBlowerTop, anyRepairs); + + if (blower->vector != (1 << direction)) + { + blower->vector = static_cast(1 << direction); + + // Unfortunately there's a lot of invalid directional data with fans, but because of how the code works, it has no effect + //anyRepairs = RCheck(true); + } + + if (blower->distance < 0) + { + blower->distance = 0; + anyRepairs = RCheck(true); + } + + if (obj->what == kLiftArea) + { + int maxWidth = kRoomWide - blower->topLeft.h; + int maxHeight = kTileHigh - blower->topLeft.v; + + if (blower->distance > maxWidth) + { + blower->distance = maxWidth; + anyRepairs = RCheck(true); + } + + if (blower->tall * 2 > maxHeight) + { + blower->tall = static_cast(maxHeight / 2); + anyRepairs = RCheck(true); + } + + return true; + } + + Rect positionedRect = srcRects[obj->what]; + ZeroRectCorner(&positionedRect); + OffsetRect(&positionedRect, blower->topLeft.h, blower->topLeft.v); + + const Rect basePositionedRect = positionedRect; + + if (ForceRectInRoomRect(positionedRect)) + { + anyRepairs = RCheck(true); + blower->topLeft.h = positionedRect.left; + blower->topLeft.v = positionedRect.top; + } + + int maxDistance = 0; + switch (direction) + { + case kDirectionUp: + { + int highestAllowed = BlowerTypeHasUpperLimit(obj->what) ? kUpwardVentMinY : 0; + maxDistance = blower->topLeft.v - highestAllowed; + } + break; + case kDirectionRight: + maxDistance = kRoomWide - positionedRect.right; + break; + case kDirectionDown: + maxDistance = kTileHigh - positionedRect.bottom; + break; + case kDirectionLeft: + maxDistance = positionedRect.left; + break; + default: + assert(false); + return LCheck(false); + } + + if (blower->distance > maxDistance) + { + blower->distance = maxDistance; + anyRepairs = RCheck(true); + } + + return true; +} + +static bool LegalizeFurniture(houseType *house, size_t roomNum, size_t objectNum, bool &anyRepairs) +{ + roomType *room = house->rooms + roomNum; + objectType *obj = room->objects + objectNum; + furnitureType *furniture = &obj->data.b; + + bool isVertConstrained = false; + bool isHorizConstrained = false; + bool isBottomConstrained = false; + + int bottomConstraint = 0; + + switch (obj->what) + { + default: + assert(false); + return LCheck(false); + + case kTable: + case kShelf: + case kDeckTable: + isVertConstrained = true; + break; + case kBooks: + case kFilingCabinet: + case kWasteBasket: + case kMilkCrate: + case kStool: + case kTrunk: + isVertConstrained = true; + isHorizConstrained = true; + break; + case kCabinet: + case kInvisObstacle: + case kInvisBounce: + // No constraints + break; + case kCounter: + isBottomConstrained = true; + bottomConstraint = kCounterBottom; + break; + case kDresser: + isBottomConstrained = true; + bottomConstraint = kDresserBottom; + break; + case kManhole: + isVertConstrained = true; + isHorizConstrained = true; + isBottomConstrained = true; + bottomConstraint = kManholeSits; + break; + }; + + const Rect baseRect = srcRects[obj->what]; + + if (NormalizeRect(&furniture->bounds)) + anyRepairs = RCheck(true); + + Point topLeft = Point::Create(furniture->bounds.left, furniture->bounds.top); + LegalizeTopLeft(topLeft, anyRepairs); + + if (obj->what == kManhole) + { + if (((topLeft.h - 3) % 64) != 0) + { + topLeft.h = (((topLeft.h + 29) / 64) * 64) + 3; + anyRepairs = RCheck(true); + } + } + + uint16_t width = furniture->bounds.Width(); + uint16_t height = furniture->bounds.Height(); + + if (width > kRoomWide) + { + width = kRoomWide; + anyRepairs = RCheck(true); + } + + if (height > kTileHigh) + { + height = kTileHigh; + anyRepairs = RCheck(true); + } + + LegalizeExpect(isVertConstrained, true, height, baseRect.Height(), anyRepairs); + LegalizeExpect(isHorizConstrained, true, width, baseRect.Width(), anyRepairs); + + furniture->bounds.left = topLeft.h; + furniture->bounds.top = topLeft.v; + furniture->bounds.bottom = topLeft.v + static_cast(height); + furniture->bounds.right = topLeft.h + static_cast(width); + + if (ForceRectInRoomRect(furniture->bounds)) + anyRepairs = RCheck(true); + + if (isBottomConstrained && furniture->bounds.bottom != bottomConstraint) + { + if (furniture->bounds.top > bottomConstraint) + furniture->bounds.top = bottomConstraint; + + furniture->bounds.bottom = bottomConstraint; + anyRepairs = RCheck(true); + } + + return true; +} + +static bool LegalizeBonus(houseType *house, size_t roomNum, size_t objectNum, bool &anyRepairs) +{ + roomType *room = house->rooms + roomNum; + objectType *obj = room->objects + objectNum; + bonusType *bonus = &obj->data.c; + + LegalizeBoolean(bonus->state); + LegalizeBoolean(bonus->initial); + + if (obj->what == kInvisBonus && bonus->points < 0) + { + anyRepairs = RCheck(true); + bonus->points = 0; + } + + LegalizeTopLeft(bonus->topLeft, anyRepairs); + + switch (obj->what) + { + default: + return LCheck(false); + + case kRedClock: + case kBlueClock: + case kYellowClock: + case kCuckoo: + case kPaper: + case kBattery: + case kBands: + case kGreaseRt: + case kGreaseLf: + case kFoil: + case kInvisBonus: + case kStar: + case kSparkle: + case kHelium: + case kSlider: + break; + }; + + Rect objRect = srcRects[obj->what]; + ZeroRectCorner(&objRect); + + if (obj->what == kSlider) + { + if (bonus->length < 0) + { + anyRepairs = RCheck(true); + bonus->length = 0; + } + else if (bonus->length > kRoomWide) + { + anyRepairs = RCheck(true); + bonus->length = kRoomWide; + } + + objRect.right = bonus->length; + } + + QOffsetRect(&objRect, bonus->topLeft.h, bonus->topLeft.v); + + if (ForceRectInRoomRect(objRect)) + { + anyRepairs = RCheck(true); + bonus->topLeft.h = objRect.left; + bonus->topLeft.v = objRect.top; + } + + int maxLength = -1; + if (obj->what == kGreaseRt) + maxLength = kRoomWide - objRect.right; + + if (obj->what == kGreaseLf) + maxLength = objRect.left; + + if (obj->what == kSlider) + maxLength = kRoomWide - bonus->topLeft.h; + + if (maxLength >= 0) + { + if (bonus->length < 0) + { + anyRepairs = RCheck(true); + bonus->length = 0; + } + else if (bonus->length > maxLength) + { + anyRepairs = RCheck(true); + bonus->length = maxLength; + } + } + + return true; +} + +static void LegalizeRoomLink(houseType *house, int16_t &where, bool &anyRepairs) +{ + // Leftover -1 from version conversion, these are generally valid + if (where == -100) + where = -1; + + if (where < -1) + { + anyRepairs = RCheck(true); + where = -1; + } + else if (where >= 0) + { + SInt16 floor, suite; + ExtractFloorSuite(house, where, &floor, &suite); + + if (suite < 0 || suite >= kMaxNumRoomsH) + { + anyRepairs = RCheck(true); + where = -1; + } + + if (floor > (kMaxNumRoomsV - kNumUndergroundFloors) || floor <= -kNumUndergroundFloors) + { + anyRepairs = RCheck(true); + where = -1; + } + } +} + +static bool LegalizeTransport(houseType *house, size_t roomNum, size_t objectNum, bool &anyRepairs) +{ + roomType *room = house->rooms + roomNum; + objectType *obj = room->objects + objectNum; + transportType *transport = &obj->data.d; + + LegalizeTopLeft(transport->topLeft, anyRepairs); + LegalizeRoomLink(house, transport->where, anyRepairs); + + Rect objRect = srcRects[obj->what]; + ZeroRectCorner(&objRect); + + if (obj->what == kInvisTrans) + { + if (transport->tall < 0) + { + anyRepairs = RCheck(true); + transport->tall = 0; + } + else if (transport->tall > kTileHigh) + { + anyRepairs = RCheck(true); + transport->tall = kTileHigh; + } + + objRect.right = transport->wide; + objRect.bottom = transport->tall; + } + + + if (obj->what == kDeluxeTrans) + { + uint8_t codedWidth = static_cast((transport->tall >> 8) & 0xff); + uint8_t codedHeight = static_cast((transport->tall) & 0xff); + + objRect.right = codedWidth * 4; + objRect.bottom = codedHeight * 4; + } + + QOffsetRect(&objRect, transport->topLeft.h, transport->topLeft.v); + + if (ForceRectInRoomRect(objRect)) + { + anyRepairs = RCheck(true); + transport->topLeft.h = objRect.left; + transport->topLeft.v = objRect.top; + + if (obj->what == kDeluxeTrans) + transport->tall = static_cast(((objRect.Width() / 4) << 8) + objRect.Height() / 4); + else if (obj->what == kInvisTrans) + { + transport->wide = objRect.Width(); + transport->tall = objRect.Height(); + } + } + + switch (obj->what) + { + default: + return LCheck(false); + + case kUpStairs: + case kDownStairs: + if (transport->topLeft.v != kStairsTop) + { + anyRepairs = RCheck(true); + transport->topLeft.v = kStairsTop; + } + break; + case kFloorTrans: + if (transport->topLeft.v != kFloorTransTop) + { + anyRepairs = RCheck(true); + transport->topLeft.v = kFloorTransTop; + } + break; + case kCeilingTrans: + if (transport->topLeft.v != kCeilingTransTop) + { + anyRepairs = RCheck(true); + transport->topLeft.v = kCeilingTransTop; + } + break; + case kDoorInLf: + if (transport->topLeft.h != kDoorInLfLeft) + { + anyRepairs = RCheck(true); + transport->topLeft.h = kCeilingTransTop; + } + if (transport->topLeft.v != kDoorInTop) + { + anyRepairs = RCheck(true); + transport->topLeft.v = kDoorInTop; + } + break; + case kDoorInRt: + if (transport->topLeft.h != kDoorInRtLeft) + { + anyRepairs = RCheck(true); + transport->topLeft.h = kDoorInRtLeft; + } + if (transport->topLeft.v != kDoorInTop) + { + anyRepairs = RCheck(true); + transport->topLeft.v = kDoorInTop; + } + break; + case kDoorExRt: + if (transport->topLeft.h != kDoorExRtLeft) + { + anyRepairs = RCheck(true); + transport->topLeft.h = kDoorExRtLeft; + } + if (transport->topLeft.v != kDoorExTop) + { + anyRepairs = RCheck(true); + transport->topLeft.v = kDoorExTop; + } + break; + case kDoorExLf: + if (transport->topLeft.h != kDoorExLfLeft) + { + anyRepairs = RCheck(true); + transport->topLeft.h = kDoorExLfLeft; + } + if (transport->topLeft.v != kDoorExTop) + { + anyRepairs = RCheck(true); + transport->topLeft.v = kDoorExTop; + } + break; + case kWindowInLf: + if (transport->topLeft.h != kWindowInLfLeft) + { + anyRepairs = RCheck(true); + transport->topLeft.h = kWindowInLfLeft; + } + if (transport->topLeft.v != kWindowInTop) + { + anyRepairs = RCheck(true); + transport->topLeft.v = kWindowInTop; + } + break; + case kWindowInRt: + if (transport->topLeft.h != kWindowInRtLeft) + { + anyRepairs = RCheck(true); + transport->topLeft.h = kWindowInRtLeft; + } + if (transport->topLeft.v != kWindowInTop) + { + anyRepairs = RCheck(true); + transport->topLeft.v = kWindowInTop; + } + break; + case kWindowExRt: + if (transport->topLeft.h != kWindowExRtLeft) + { + anyRepairs = RCheck(true); + transport->topLeft.h = kWindowExRtLeft; + } + if (transport->topLeft.v != kWindowExTop) + { + anyRepairs = RCheck(true); + transport->topLeft.v = kWindowExTop; + } + break; + case kWindowExLf: + if (transport->topLeft.h != kWindowExLfLeft) + { + anyRepairs = RCheck(true); + transport->topLeft.h = kWindowExLfLeft; + } + if (transport->topLeft.v != kWindowExTop) + { + anyRepairs = RCheck(true); + transport->topLeft.v = kWindowExTop; + } + break; + case kInvisTrans: + case kDeluxeTrans: + case kMailboxLf: + case kMailboxRt: + break; + } + + return true; +} + +static bool LegalizeSwitch(houseType *house, size_t roomNum, size_t objectNum, bool &anyRepairs) +{ + roomType *room = house->rooms + roomNum; + objectType *obj = room->objects + objectNum; + switchType *sw = &obj->data.e; + + if (sw->delay < 0) + { + sw->delay = 0; + anyRepairs = RCheck(true); + } + + bool isSwitch = false; + bool isTrigger = false; + + switch (obj->what) + { + default: + return RCheck(false); + + case kLightSwitch: + case kMachineSwitch: + case kThermostat: + case kPowerSwitch: + case kKnifeSwitch: + case kInvisSwitch: + isSwitch = true; + LegalizeRoomLink(house, sw->where, anyRepairs); + break; + case kTrigger: + case kLgTrigger: + LegalizeRoomLink(house, sw->where, anyRepairs); + break; + case kSoundTrigger: + break; + }; + + if (isSwitch) + { + switch (sw->type) + { + case kToggle: + case kForceOn: + case kForceOff: + break; + default: + anyRepairs = RCheck(true); + sw->type = kToggle; + break; + } + } + + if (isTrigger) + { + if (sw->type != kOneShot) + { + anyRepairs = RCheck(true); + sw->type = kOneShot; + } + } + + LegalizeTopLeft(sw->topLeft, anyRepairs); + + Rect bounds = srcRects[obj->what]; + ZeroRectCorner(&bounds); + QOffsetRect(&bounds, sw->topLeft.h, sw->topLeft.v); + + if (ForceRectInRoomRect(bounds)) + { + anyRepairs = RCheck(true); + sw->topLeft.h = bounds.left; + sw->topLeft.v = bounds.top; + } + + return true; +} + +static bool LegalizeLight(houseType *house, size_t roomNum, size_t objectNum, bool &anyRepairs) +{ + roomType *room = house->rooms + roomNum; + objectType *obj = room->objects + objectNum; + lightType *light = &obj->data.f; + + LegalizeBoolean(light->initial); + LegalizeBoolean(light->state); + + LegalizeTopLeft(light->topLeft, anyRepairs); + + Rect bounds = srcRects[obj->what]; + ZeroRectCorner(&bounds); + + if (obj->what == kTrackLight || obj->what == kFlourescent) + { + if (light->length < 0) + { + anyRepairs = RCheck(true); + light->length = 0; + } + else if (light->length > kRoomWide) + { + anyRepairs = RCheck(true); + light->length = kRoomWide; + } + + bounds.right = light->length; + } + + QOffsetRect(&bounds, light->topLeft.h, light->topLeft.v); + + if (ForceRectInRoomRect(bounds)) + { + anyRepairs = RCheck(true); + light->topLeft.h = bounds.left; + light->topLeft.v = bounds.top; + } + + switch (obj->what) + { + case kCeilingLight: + if (light->topLeft.v != kCeilingLightTop) + { + anyRepairs = RCheck(true); + light->topLeft.v = kCeilingLightTop; + } + break; + case kHipLamp: + if (light->topLeft.v != kHipLampTop) + { + anyRepairs = RCheck(true); + light->topLeft.v = kHipLampTop; + } + break; + case kDecoLamp: + if (light->topLeft.v != kDecoLampTop) + { + anyRepairs = RCheck(true); + light->topLeft.v = kDecoLampTop; + } + break; + case kFlourescent: + if (light->topLeft.v != kFlourescentTop) + { + anyRepairs = RCheck(true); + light->topLeft.v = kFlourescentTop; + } + break; + case kTrackLight: + if (light->topLeft.v != kTrackLightTop) + { + anyRepairs = RCheck(true); + light->topLeft.v = kTrackLightTop; + } + break; + case kLightBulb: + case kTableLamp: + case kInvisLight: + break; + } + + return true; +} + +static bool LegalizeAppliance(houseType *house, size_t roomNum, size_t objectNum, bool &anyRepairs) +{ + roomType *room = house->rooms + roomNum; + objectType *obj = room->objects + objectNum; + applianceType *appl = &obj->data.g; + + LegalizeBoolean(appl->initial); + LegalizeBoolean(appl->state); + + LegalizeTopLeft(appl->topLeft, anyRepairs); + + if (obj->what != kCustomPict) + { + Rect bounds = srcRects[obj->what]; + ZeroRectCorner(&bounds); + QOffsetRect(&bounds, appl->topLeft.h, appl->topLeft.v); + + if (ForceRectInRoomRect(bounds)) + { + anyRepairs = RCheck(true); + appl->topLeft.h = bounds.left; + appl->topLeft.v = bounds.top; + } + + switch (obj->what) + { + case kToaster: + { + int maxHeight = bounds.top; + if (appl->height < 0) + { + anyRepairs = RCheck(true); + appl->height = 0; + } + else if (appl->height > maxHeight) + { + anyRepairs = RCheck(true); + appl->height = maxHeight; + } + } + break; + case kShredder: + case kMacPlus: + case kGuitar: + case kTV: + case kCoffee: + case kOutlet: + case kVCR: + case kStereo: + case kMicrowave: + case kCinderBlock: + case kFlowerBox: + case kCDs: + break; + } + } + + return true; +} + +static bool LegalizeEnemy(houseType *house, size_t roomNum, size_t objectNum, bool &anyRepairs) +{ + roomType *room = house->rooms + roomNum; + objectType *obj = room->objects + objectNum; + enemyType *enemy = &obj->data.h; + + LegalizeBoolean(enemy->initial); + LegalizeBoolean(enemy->state); + + LegalizeTopLeft(enemy->topLeft, anyRepairs); + + Rect bounds = srcRects[obj->what]; + ZeroRectCorner(&bounds); + QOffsetRect(&bounds, enemy->topLeft.h, enemy->topLeft.v); + + if (ForceRectInRoomRect(bounds)) + { + anyRepairs = RCheck(true); + enemy->topLeft.h = bounds.left; + enemy->topLeft.v = bounds.top; + } + + switch (obj->what) + { + case kBalloon: + case kCopterLf: + case kCopterRt: + { + int expectedV = (kTileHigh / 2) - HalfRectTall(&bounds); + if (enemy->topLeft.v != expectedV) + { + anyRepairs = RCheck(true); + enemy->topLeft.v = expectedV; + } + } + break; + case kDartLf: + { + int expectedH = kRoomWide - RectWide(&bounds); + if (enemy->topLeft.h != expectedH) + { + anyRepairs = RCheck(true); + enemy->topLeft.h = expectedH; + } + } + break; + case kDartRt: + if (enemy->topLeft.h != 0) + { + anyRepairs = RCheck(true); + enemy->topLeft.h = 0; + } + break; + case kBall: + case kFish: + { + int maxLength = bounds.top; + if (enemy->length < 0) + { + anyRepairs = RCheck(true); + enemy->length = 0; + } + else if (enemy->length > maxLength) + { + anyRepairs = RCheck(true); + enemy->length = maxLength; + } + } + break; + case kDrip: + { + int maxLength = kTileHigh - bounds.bottom; + if (enemy->length < 0) + { + anyRepairs = RCheck(true); + enemy->length = 0; + } + else if (enemy->length > maxLength) + { + anyRepairs = RCheck(true); + enemy->length = maxLength; + } + } + break; + case kCobweb: + break; + } + + return true; +} + +static bool LegalizeClutter(houseType *house, size_t roomNum, size_t objectNum, bool &anyRepairs) +{ + roomType *room = house->rooms + roomNum; + objectType *obj = room->objects + objectNum; + clutterType *blower = &obj->data.i; + + PL_NotYetImplemented_TODO("Validate"); + return true; +} + + +static bool LegalizeObject(houseType *house, size_t roomNum, size_t objectNum, bool &anyRepairs) +{ + roomType *room = house->rooms + roomNum; + objectType *obj = room->objects + objectNum; + + switch (obj->what) + { + default: + obj->what = kObjectIsEmpty; + anyRepairs = RCheck(true); + break; + case kObjectIsEmpty: + break; + + case kFloorVent: + case kCeilingVent: + case kFloorBlower: + case kCeilingBlower: + case kSewerGrate: + case kLeftFan: + case kRightFan: + case kTaper: + case kCandle: + case kStubby: + case kTiki: + case kBBQ: + case kInvisBlower: + case kGrecoVent: + case kSewerBlower: + case kLiftArea: + return LegalizeBlower(house, roomNum, objectNum, anyRepairs); + + case kTable: + case kShelf: + case kCabinet: + case kFilingCabinet: + case kWasteBasket: + case kMilkCrate: + case kCounter: + case kDresser: + case kDeckTable: + case kStool: + case kTrunk: + case kInvisObstacle: + case kManhole: + case kBooks: + case kInvisBounce: + return LegalizeFurniture(house, roomNum, objectNum, anyRepairs); + + case kRedClock: + case kBlueClock: + case kYellowClock: + case kCuckoo: + case kPaper: + case kBattery: + case kBands: + case kGreaseRt: + case kGreaseLf: + case kFoil: + case kInvisBonus: + case kStar: + case kSparkle: + case kHelium: + case kSlider: + return LegalizeBonus(house, roomNum, objectNum, anyRepairs); + + case kUpStairs: + case kDownStairs: + case kMailboxLf: + case kMailboxRt: + case kFloorTrans: + case kCeilingTrans: + case kDoorInLf: + case kDoorInRt: + case kDoorExRt: + case kDoorExLf: + case kWindowInLf: + case kWindowInRt: + case kWindowExRt: + case kWindowExLf: + case kInvisTrans: + case kDeluxeTrans: + return LegalizeTransport(house, roomNum, objectNum, anyRepairs); + + case kLightSwitch: + case kMachineSwitch: + case kThermostat: + case kPowerSwitch: + case kKnifeSwitch: + case kInvisSwitch: + case kTrigger: + case kLgTrigger: + case kSoundTrigger: + return LegalizeSwitch(house, roomNum, objectNum, anyRepairs); + + case kCeilingLight: + case kLightBulb: + case kTableLamp: + case kHipLamp: + case kDecoLamp: + case kFlourescent: + case kTrackLight: + case kInvisLight: + return LegalizeLight(house, roomNum, objectNum, anyRepairs); + + case kShredder: + case kToaster: + case kMacPlus: + case kGuitar: + case kTV: + case kCoffee: + case kOutlet: + case kVCR: + case kStereo: + case kMicrowave: + case kCinderBlock: + case kFlowerBox: + case kCDs: + case kCustomPict: + return LegalizeAppliance(house, roomNum, objectNum, anyRepairs); + + case kBalloon: + case kCopterLf: + case kCopterRt: + case kDartLf: + case kDartRt: + case kBall: + case kDrip: + case kFish: + case kCobweb: + return LegalizeEnemy(house, roomNum, objectNum, anyRepairs); + + case kOzma: + case kMirror: + case kMousehole: + case kFireplace: + case kFlower: + case kWallWindow: + case kBear: + case kCalendar: + case kVase1: + case kVase2: + case kBulletin: + case kCloud: + case kFaucet: + case kRug: + case kChimes: + return LegalizeClutter(house, roomNum, objectNum, anyRepairs); + } + + return true; +} + +static bool LegalizeRoom(houseType *house, size_t roomNum, bool &anyRepairs) +{ + roomType *room = house->rooms + roomNum; + if (room->suite == kRoomIsEmpty) + return true; + + if (!LegalizePascalStr(room->name, anyRepairs)) + return LCheck(false); + + LegalizeBoolean(room->visited); + + for (int i = 0; i < kNumTiles; i++) + { + if (room->tiles[i] < 0) + { + room->tiles[i] = 0; + anyRepairs = RCheck(true); + } + else if (room->tiles[i] >= kNumTiles) + { + room->tiles[i] = kNumTiles - 1; + anyRepairs = RCheck(true); + } + } + + // Enforce object type caps + enum CapType + { + CapType_Candle, + CapType_Tiki, + CapType_Coals, + CapType_Pendulum, + CapType_RubberBands, + CapType_Star, + CapType_DynamicObj, + CapType_SoundTrigger, + CapType_UpStairs, + CapType_DownStairs, + CapType_Grease, + + CapType_Count, + }; + + int caps[CapType_Count]; + caps[CapType_Candle] = kMaxCandles; + caps[CapType_Tiki] = kMaxTikis; + caps[CapType_Coals] = kMaxCoals; + caps[CapType_Pendulum] = kMaxPendulums; + caps[CapType_RubberBands] = kMaxRubberBands; + caps[CapType_Star] = kMaxStars; + caps[CapType_DynamicObj] = kMaxDynamicObs; + caps[CapType_SoundTrigger] = kMaxSoundTriggers; + caps[CapType_UpStairs] = kMaxStairs; + caps[CapType_DownStairs] = kMaxStairs; + caps[CapType_Grease] = kMaxGrease; + + int counts[CapType_Count]; + for (int i = 0; i < CapType_Count; i++) + counts[i] = 0; + + for (size_t i = 0; i < kMaxRoomObs; i++) + { + CapType capType = CapType_Count; + + objectType *obj = room->objects + i; + switch (obj->what) + { + case kTaper: + case kCandle: + case kStubby: + capType = CapType_Candle; + break; + case kTiki: + capType = CapType_Tiki; + break; + case kBBQ: + capType = CapType_Coals; + break; + case kCuckoo: + capType = CapType_Pendulum; + break; + case kBands: + capType = CapType_RubberBands; + break; + case kStar: + capType = CapType_Star; + break; + case kSparkle: + case kToaster: + case kMacPlus: + case kTV: + case kCoffee: + case kOutlet: + case kVCR: + case kStereo: + case kMicrowave: + case kBalloon: + case kCopterLf: + case kCopterRt: + case kDartLf: + case kDartRt: + case kBall: + case kDrip: + case kFish: + capType = CapType_DynamicObj; + break; + case kSoundTrigger: + capType = CapType_SoundTrigger; + break; + case kUpStairs: + capType = CapType_UpStairs; + break; + case kDownStairs: + capType = CapType_DownStairs; + break; + case kGreaseLf: + case kGreaseRt: + capType = CapType_Grease; + break; + default: + break; + }; + + if (capType != CapType_Count) + { + if (counts[capType] == caps[capType]) + { + obj->what = kObjectIsEmpty; + anyRepairs = RCheck(true); + } + else + counts[capType]++; + } + } + + // Check all objects + for (size_t i = 0; i < kMaxRoomObs; i++) + { + if (!LegalizeObject(house, roomNum, i, anyRepairs)) + return LCheck(false); + } + + int16_t numObjects = kMaxRoomObs; + for (size_t i = 0; i < kMaxRoomObs; i++) + { + objectType *obj = room->objects + i; + + if (obj->what == kObjectIsEmpty) + numObjects--; + } + + if (numObjects != room->numObjects) + { + anyRepairs = RCheck(true); + room->numObjects = numObjects; + } + + return true; +} + +static bool LegalizeHouse(houseType *house, bool &anyRepairs) +{ + size_t nRooms = house->nRooms; + + if (!LegalizeScores(&house->highScores, anyRepairs)) + return false; + + PL_NotYetImplemented_TODO("Validate initial pos"); + + // Repair room layout + for (size_t i = 0; i < nRooms; i++) + { + if (!LegalizeRoomLayout(house, i, anyRepairs)) + return LCheck(false); + } + + // Repair firstRoom + if (house->firstRoom < 0 || house->firstRoom >= house->nRooms || house->rooms[house->firstRoom].suite == kRoomIsEmpty) + { + if (nRooms != 0) + { + bool repairedOK = false; + for (size_t i = 0; i < nRooms; i++) + { + if (house->rooms[i].suite == kRoomIsEmpty) + continue; + + house->firstRoom = static_cast(i); + repairedOK = true; + anyRepairs = RCheck(true); + } + + if (!repairedOK) + return LCheck(false); + } + } + + for (size_t i = 0; i < nRooms; i++) + { + if (!LegalizeRoom(house, i, anyRepairs)) + return LCheck(false); + } + + return true; +} + +Boolean ReadHouse (GpIOStream *houseStream, bool untrusted) { long byteCount; - PLError_t theErr; + PLError_t theErr; short whichRoom; // There should be no padding remaining the house type @@ -567,6 +1960,21 @@ Boolean ReadHouse (GpIOStream *houseStream) if (thisHouse != nil) thisHouse.Dispose(); + if (byteCount < houseType::kBinaryDataSize) + { + YellowAlert(kYellowHouseDamaged, 1); + return (false); + } + + const size_t roomDataSize = static_cast(byteCount) - houseType::kBinaryDataSize; + if (roomDataSize % sizeof(roomType) != 0) + { + YellowAlert(kYellowHouseDamaged, 2); + return (false); + } + + const size_t roomCountFromDataSize = roomDataSize / sizeof(roomType); + // GP: Correct for padding const size_t alignmentPadding = sizeof(houseType) - sizeof(roomType) - houseType::kBinaryDataSize; @@ -602,6 +2010,25 @@ Boolean ReadHouse (GpIOStream *houseStream) ByteSwapHouse(*thisHouse, static_cast(byteCount), false); numberRooms = (*thisHouse)->nRooms; + if (numberRooms < 0 || static_cast(numberRooms) > roomCountFromDataSize) + { + YellowAlert(kYellowHouseDamaged, 3); + return (false); + } + + bool anyRepairs = false; + if (untrusted) + { + if (!LegalizeHouse(*thisHouse, anyRepairs)) + { + YellowAlert(kYellowHouseDamaged, 4); + return (false); + } + + if (anyRepairs) + YellowAlert(kYellowHouseRepaired, 0); + } + #ifdef COMPILEDEMO if (numberRooms != 45) return (false); @@ -651,7 +2078,7 @@ Boolean ReadHouse (GpIOStream *houseStream) { } } - + objActive = kNoObjectSelected; ReflectCurrentRoom(true); fileDirty = false; @@ -685,7 +2112,7 @@ Boolean WriteHouse (Boolean checkIt) } GpIOStream *houseStream = nil; - theErr = houseCFile->OpenData(PortabilityLayer::EFilePermission_Write, GpFileCreationDispositions::kCreateOrOpen, houseStream); + theErr = houseCFile->OpenData(PortabilityLayer::EFilePermission_Write, GpFileCreationDispositions::kCreateOrOverwrite, houseStream); if (theErr != PLErrors::kNone) return (false); diff --git a/GpApp/HouseLegal.cpp b/GpApp/HouseLegal.cpp index 94e328c..2c18927 100644 --- a/GpApp/HouseLegal.cpp +++ b/GpApp/HouseLegal.cpp @@ -9,6 +9,7 @@ #include "PLNumberFormatting.h" #include "PLStringCompare.h" #include "PLStandardColors.h" +#include "PLSysCalls.h" #include "Externs.h" #include "ObjectEdit.h" #include "PLStandardColors.h" @@ -128,27 +129,17 @@ Boolean KeepObjectLegal (void) theObject->data.a.topLeft.v = kSewerGrateTop; theObject->data.a.distance += 2; } - if ((theObject->what == kFloorTrans) && - (theObject->data.a.topLeft.v != kFloorTransTop)) - { - theObject->data.a.topLeft.v = kFloorTransTop; - theObject->data.a.distance += 2; - } if (ObjectHasHandle(&direction, &dist)) { switch (direction) { case kAbove: dist = bounds.top - dist; - if ((theObject->what == kFloorVent) || - (theObject->what == kFloorBlower) || - (theObject->what == kTaper) || - (theObject->what == kCandle) || - (theObject->what == kStubby)) + if (BlowerTypeHasUpperLimit(theObject->what)) { - if (dist < 36) + if (dist < kUpwardVentMinY) { - theObject->data.a.distance += dist - 36; + theObject->data.a.distance += dist - kUpwardVentMinY; unchanged = false; } } @@ -874,6 +865,7 @@ void KeepAllObjectsLegal (void) GetLocalizedString(19, message); SetMessageWindowMessage(message, StdColors::Red()); houseErrors++; + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); DelayTicks(60); } } @@ -908,6 +900,7 @@ void CheckForStaircasePairs (void) { GetLocalizedString(20, message); SetMessageWindowMessage(message, StdColors::Red()); + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); DelayTicks(60); } else @@ -923,6 +916,7 @@ void CheckForStaircasePairs (void) { GetLocalizedString(21, message); SetMessageWindowMessage(message, StdColors::Red()); + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); DelayTicks(60); } } @@ -935,6 +929,7 @@ void CheckForStaircasePairs (void) { GetLocalizedString(22, message); SetMessageWindowMessage(message, StdColors::Red()); + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); DelayTicks(60); } else @@ -950,6 +945,7 @@ void CheckForStaircasePairs (void) { GetLocalizedString(23, message); SetMessageWindowMessage(message, StdColors::Red()); + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); DelayTicks(60); } } @@ -992,6 +988,7 @@ void CheckHouseForProblems (void) { GetLocalizedString(27, message); SetMessageWindowMessage(message, StdColors::Black()); + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); DelayTicks(60); houseErrors = 0; } @@ -1008,6 +1005,7 @@ void CheckHouseForProblems (void) GetLocalizedString(28, message2); PasStringConcat(message, message2); SetMessageWindowMessage(message, StdColors::Red()); + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); DelayTicks(45); } } @@ -1027,6 +1025,7 @@ void CheckHouseForProblems (void) GetLocalizedString(29, message2); PasStringConcat(message, message2); SetMessageWindowMessage(message, StdColors::Red()); + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); DelayTicks(60); } } @@ -1042,6 +1041,7 @@ void CheckHouseForProblems (void) GetLocalizedString(30, message2); PasStringConcat(message, message2); SetMessageWindowMessage(message, StdColors::Blue()); + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); DelayTicks(45); } } @@ -1057,6 +1057,7 @@ void CheckHouseForProblems (void) GetLocalizedString(31, message2); PasStringConcat(message, message2); SetMessageWindowMessage(message, StdColors::Blue()); + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); DelayTicks(45); } } @@ -1072,6 +1073,7 @@ void CheckHouseForProblems (void) GetLocalizedString(32, message2); PasStringConcat(message, message2); SetMessageWindowMessage(message, StdColors::Red()); + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); DelayTicks(60); } } @@ -1089,6 +1091,7 @@ void CheckHouseForProblems (void) GetLocalizedString(34, message2); PasStringConcat(message, message2); SetMessageWindowMessage(message, StdColors::Red()); + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); DelayTicks(60); } } @@ -1107,6 +1110,7 @@ void CheckHouseForProblems (void) { GetLocalizedString(35, message); SetMessageWindowMessage(message, StdColors::Red()); + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); DelayTicks(60); } } diff --git a/GpApp/Link.cpp b/GpApp/Link.cpp index b7a48c7..cccf8a8 100644 --- a/GpApp/Link.cpp +++ b/GpApp/Link.cpp @@ -42,9 +42,9 @@ short MergeFloorSuite (short floor, short suite) //-------------------------------------------------------------- ExtractFloorSuite -void ExtractFloorSuite (short combo, short *floor, short *suite) +void ExtractFloorSuite (const houseType *house, SInt16 combo, SInt16 *floor, SInt16 *suite) { - if ((*thisHouse)->version < 0x0200) // old floor/suite combo + if (house->version < 0x0200) // old floor/suite combo { *floor = (combo / 100) - kNumUndergroundFloors; *suite = combo % 100; diff --git a/GpApp/MainWindow.cpp b/GpApp/MainWindow.cpp index bd274de..8c01cf8 100644 --- a/GpApp/MainWindow.cpp +++ b/GpApp/MainWindow.cpp @@ -72,7 +72,7 @@ void DrawOnSplash(DrawSurface *surface) if ((thisMac.hasQT) && (hasMovie)) PasStringConcat(houseLoadedStr, PSTR(" (TV)")); - PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication9Bold); + PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication9SyntheticBold); const Point textPoint = Point::Create(splashOriginH + 436, splashOriginV + 314); if (thisMac.isDepth == 4) diff --git a/GpApp/Map.cpp b/GpApp/Map.cpp index 44d0fc7..0122e83 100644 --- a/GpApp/Map.cpp +++ b/GpApp/Map.cpp @@ -28,7 +28,6 @@ #define kMapScrollBarWidth 16 #define kHScrollRef 5L #define kVScrollRef 27L -#define kMapGroundValue 56 #define kNewRoomAlert 1004 #define kYesDoNewRoom 1 #define kThumbnailPictID 1010 diff --git a/GpApp/Marquee.cpp b/GpApp/Marquee.cpp index cd74b41..6405c64 100644 --- a/GpApp/Marquee.cpp +++ b/GpApp/Marquee.cpp @@ -208,7 +208,7 @@ void DragOutMarqueeRect (Window *window, Point start, Rect *theRect) surface->InvertFrameRect(*theRect, pattern); wasPt = start; - while (WaitMouseUp()) + while (WaitMouseUp_DisarmAsyncify()) { GetMouse(window, &newPt); if (wasPt != newPt) @@ -238,7 +238,7 @@ void DragMarqueeRect (Window *window, DrawSurface *surface, Point start, Rect *t surface->InvertFrameRect(theMarquee.bounds, pattern); wasPt = start; - while (WaitMouseUp()) + while (WaitMouseUp_DisarmAsyncify()) { GetMouse(window, &newPt); if (wasPt != newPt) @@ -283,7 +283,7 @@ void DragMarqueeHandle (Window *window, DrawSurface *surface, Point start, short surface->InvertFillRect(theMarquee.handle, pattern); wasPt = start; - while (WaitMouseUp()) + while (WaitMouseUp_DisarmAsyncify()) { GetMouse(window, &newPt); if (wasPt != newPt) @@ -365,7 +365,7 @@ void DragMarqueeCorner (Window *window, DrawSurface *surface, Point start, short surface->InvertFillRect(theMarquee.handle, pattern); wasPt = start; - while (WaitMouseUp()) + while (WaitMouseUp_DisarmAsyncify()) { GetMouse(window, &newPt); if (wasPt != newPt) diff --git a/GpApp/Music.cpp b/GpApp/Music.cpp index bb29136..a6ae546 100644 --- a/GpApp/Music.cpp +++ b/GpApp/Music.cpp @@ -8,6 +8,7 @@ #include "Environ.h" #include "Externs.h" #include "SoundSync.h" +#include "IGpAudioBuffer.h" #include "IGpMutex.h" #include "IGpSystemServices.h" #include "MemoryManager.h" @@ -29,11 +30,11 @@ PLError_t DumpMusicSounds (void); PLError_t OpenMusicChannel (void); PLError_t CloseMusicChannel (void); -THandle ParseAndConvertSound(const THandle &handle); +IGpAudioBuffer *ParseAndConvertSound(const THandle &handle); PortabilityLayer::AudioChannel *musicChannel; -Ptr theMusicData[kMaxMusic]; +IGpAudioBuffer *theMusicData[kMaxMusic]; short musicScore[kLastMusicPiece]; short gameScore[kLastGamePiece]; Boolean isMusicOn, isPlayMusicIdle, isPlayMusicGame; @@ -208,22 +209,23 @@ PLError_t LoadMusicSounds (void) theErr = PLErrors::kNone; for (i = 0; i < kMaxMusic; i++) - theMusicData[i] = nil; + { + assert(theMusicData[i] == nil); + } for (i = 0; i < kMaxMusic; i++) { - theSound = ParseAndConvertSound(PortabilityLayer::ResourceManager::GetInstance()->GetAppResource('snd ', i + kBaseBufferMusicID)); + theSound = PortabilityLayer::ResourceManager::GetInstance()->GetAppResource('snd ', i + kBaseBufferMusicID); if (theSound == nil) return PLErrors::kOutOfMemory; - soundDataSize = GetHandleSize(theSound); + IGpAudioBuffer *buffer = ParseAndConvertSound(theSound); + theSound.Dispose(); - theMusicData[i] = PortabilityLayer::MemoryManager::GetInstance()->Alloc(soundDataSize); - if (theMusicData[i] == nil) + if (buffer == nil) return PLErrors::kOutOfMemory; - memcpy(theMusicData[i], static_cast(*theSound), soundDataSize); - theSound.Dispose(); + theMusicData[i] = buffer; } return (theErr); } @@ -240,7 +242,7 @@ PLError_t DumpMusicSounds (void) for (i = 0; i < kMaxMusic; i++) { if (theMusicData[i] != nil) - PortabilityLayer::MemoryManager::GetInstance()->Release(theMusicData[i]); + theMusicData[i]->Release(); theMusicData[i] = nil; } diff --git a/GpApp/ObjectAdd.cpp b/GpApp/ObjectAdd.cpp index be32d60..e7da40f 100644 --- a/GpApp/ObjectAdd.cpp +++ b/GpApp/ObjectAdd.cpp @@ -16,13 +16,6 @@ #define kNoMoreObjectsAlert 1008 #define kNoMoreSpecialAlert 1028 -#define kMaxSoundTriggers 1 -#define kMaxStairs 1 -#define kMouseholeBottom 295 -#define kFireplaceBottom 297 -#define kManholeSits 322 -#define kGrecoVentTop 303 -#define kSewerBlowerTop 292 short FindEmptyObjectSlot (void); diff --git a/GpApp/ObjectDraw2.cpp b/GpApp/ObjectDraw2.cpp index 45749b0..402ec14 100644 --- a/GpApp/ObjectDraw2.cpp +++ b/GpApp/ObjectDraw2.cpp @@ -1057,7 +1057,7 @@ void DrawCalendar (Rect *theRect) backSrcMap->DrawPicture(thePicture, bounds); thePicture.Dispose(); - PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication9Bold); + PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication9SyntheticBold); GetTime(&timeRec); GetIndString(monthStr, kMonthStringID, timeRec.month); diff --git a/GpApp/ObjectDrawAll.cpp b/GpApp/ObjectDrawAll.cpp index 924950d..9285bbc 100644 --- a/GpApp/ObjectDrawAll.cpp +++ b/GpApp/ObjectDrawAll.cpp @@ -534,7 +534,7 @@ void DrawARoomsObjects (short neighbor, Boolean redraw) OffsetRectRoomRelative(&itsRect, neighbor); if (SectRect(&itsRect, &testRect, &whoCares)) { - ExtractFloorSuite(thisObject.data.e.where, &floor, &suite); + ExtractFloorSuite(*thisHouse, thisObject.data.e.where, &floor, &suite); room = GetRoomNumber(floor, suite); obj = (short)thisObject.data.e.who; DrawLightSwitch(&itsRect, GetObjectState(room, obj)); @@ -547,7 +547,7 @@ void DrawARoomsObjects (short neighbor, Boolean redraw) OffsetRectRoomRelative(&itsRect, neighbor); if (SectRect(&itsRect, &testRect, &whoCares)) { - ExtractFloorSuite(thisObject.data.e.where, &floor, &suite); + ExtractFloorSuite(*thisHouse, thisObject.data.e.where, &floor, &suite); room = GetRoomNumber(floor, suite); obj = (short)thisObject.data.e.who; DrawMachineSwitch(&itsRect, GetObjectState(room, obj)); @@ -560,7 +560,7 @@ void DrawARoomsObjects (short neighbor, Boolean redraw) OffsetRectRoomRelative(&itsRect, neighbor); if (SectRect(&itsRect, &testRect, &whoCares)) { - ExtractFloorSuite(thisObject.data.e.where, &floor, &suite); + ExtractFloorSuite(*thisHouse, thisObject.data.e.where, &floor, &suite); room = GetRoomNumber(floor, suite); obj = (short)thisObject.data.e.who; DrawThermostat(&itsRect, GetObjectState(room, obj)); @@ -573,7 +573,7 @@ void DrawARoomsObjects (short neighbor, Boolean redraw) OffsetRectRoomRelative(&itsRect, neighbor); if (SectRect(&itsRect, &testRect, &whoCares)) { - ExtractFloorSuite(thisObject.data.e.where, &floor, &suite); + ExtractFloorSuite(*thisHouse, thisObject.data.e.where, &floor, &suite); room = GetRoomNumber(floor, suite); obj = (short)thisObject.data.e.who; DrawPowerSwitch(&itsRect, GetObjectState(room, obj)); @@ -586,7 +586,7 @@ void DrawARoomsObjects (short neighbor, Boolean redraw) OffsetRectRoomRelative(&itsRect, neighbor); if (SectRect(&itsRect, &testRect, &whoCares)) { - ExtractFloorSuite(thisObject.data.e.where, &floor, &suite); + ExtractFloorSuite(*thisHouse, thisObject.data.e.where, &floor, &suite); room = GetRoomNumber(floor, suite); obj = (short)thisObject.data.e.who; DrawKnifeSwitch(&itsRect, GetObjectState(room, obj)); diff --git a/GpApp/ObjectEdit.cpp b/GpApp/ObjectEdit.cpp index 28225b7..065e1df 100644 --- a/GpApp/ObjectEdit.cpp +++ b/GpApp/ObjectEdit.cpp @@ -1680,6 +1680,24 @@ void DeselectObject (void) #endif } + +//-------------------------------------------------------------- ObjectHasHandle + +Boolean BlowerTypeHasUpperLimit (SInt16 what) +{ + switch (what) + { + case kFloorVent: + case kFloorBlower: + case kTaper: + case kCandle: + case kStubby: + return true; + default: + return false; + } +} + //-------------------------------------------------------------- ObjectHasHandle #ifndef COMPILEDEMO diff --git a/GpApp/ObjectInfo.cpp b/GpApp/ObjectInfo.cpp index bedff3c..1cb7d63 100644 --- a/GpApp/ObjectInfo.cpp +++ b/GpApp/ObjectInfo.cpp @@ -1075,7 +1075,7 @@ void DoSwitchObjectInfo (void) PasStringCopy(PSTR("none"), roomStr); else { - ExtractFloorSuite(thisRoom->objects[objActive].data.e.where, &floor, &suite); + ExtractFloorSuite(*thisHouse, thisRoom->objects[objActive].data.e.where, &floor, &suite); NumToString((long)floor, roomStr); PasStringConcat(roomStr, PSTR(" / ")); NumToString((long)suite, tempStr); @@ -1196,7 +1196,7 @@ void DoTriggerObjectInfo (void) PasStringCopy(PSTR("none"), roomStr); else { - ExtractFloorSuite(thisRoom->objects[objActive].data.e.where, &floor, &suite); + ExtractFloorSuite(*thisHouse, thisRoom->objects[objActive].data.e.where, &floor, &suite); NumToString((long)floor, roomStr); PasStringConcat(roomStr, PSTR(" / ")); NumToString((long)suite, tempStr); @@ -1869,7 +1869,7 @@ void DoTransObjectInfo (short what) PasStringCopy(PSTR("none"), roomStr); else { - ExtractFloorSuite(thisRoom->objects[objActive].data.d.where, &floor, &suite); + ExtractFloorSuite(*thisHouse, thisRoom->objects[objActive].data.d.where, &floor, &suite); NumToString((long)floor, roomStr); PasStringConcat(roomStr, PSTR(" / ")); NumToString((long)suite, tempStr); diff --git a/GpApp/ObjectRects.cpp b/GpApp/ObjectRects.cpp index 8e45ce3..19d9e71 100644 --- a/GpApp/ObjectRects.cpp +++ b/GpApp/ObjectRects.cpp @@ -36,6 +36,7 @@ void GetObjectRect (objectPtr who, Rect *itsRect) switch (who->what) { + default: case kObjectIsEmpty: QSetRect(itsRect, 0, 0, 0, 0); break; diff --git a/GpApp/Objects.cpp b/GpApp/Objects.cpp index 3f249ee..d3f61aa 100644 --- a/GpApp/Objects.cpp +++ b/GpApp/Objects.cpp @@ -136,7 +136,7 @@ short GetRoomLinked (objectType *who) compoundRoomNumber = who->data.d.where; if (compoundRoomNumber != -1) // is object linked { - ExtractFloorSuite(compoundRoomNumber, &floor, &suite); + ExtractFloorSuite(*thisHouse, compoundRoomNumber, &floor, &suite); whereLinked = GetRoomNumber(floor, suite); } else @@ -154,7 +154,7 @@ short GetRoomLinked (objectType *who) compoundRoomNumber = who->data.e.where; if (compoundRoomNumber != -1) // is object linked { - ExtractFloorSuite(compoundRoomNumber, &floor, &suite); + ExtractFloorSuite(*thisHouse, compoundRoomNumber, &floor, &suite); whereLinked = GetRoomNumber(floor, suite); } else @@ -352,7 +352,7 @@ void AddTempManholeRect (Rect *manHole) //-------------------------------------------------------------- SetObjectState -Boolean SetObjectState (short room, short object, short action, short local) +Boolean SetObjectState (SInt16 room, SInt16 object, SInt16 action, SInt16 local) { char wasState; Boolean changed = false; diff --git a/GpApp/RectUtils.cpp b/GpApp/RectUtils.cpp index bc3f0ea..a7079a6 100644 --- a/GpApp/RectUtils.cpp +++ b/GpApp/RectUtils.cpp @@ -31,15 +31,17 @@ void FrameWHRect (DrawSurface *surface, short left, short top, short wide, short // This function ensures that a rect's top is less than it's bottomÉ // and that left is less than right. -void NormalizeRect (Rect *theRect) +Boolean NormalizeRect (Rect *theRect) { short tempSide; + Boolean changed = false; if (theRect->left > theRect->right) { tempSide = theRect->left; theRect->left = theRect->right; theRect->right = tempSide; + changed = true; } if (theRect->top > theRect->bottom) @@ -47,7 +49,10 @@ void NormalizeRect (Rect *theRect) tempSide = theRect->top; theRect->top = theRect->bottom; theRect->bottom = tempSide; + changed = true; } + + return changed; } //-------------------------------------------------------------- ZeroRectCorner @@ -198,7 +203,8 @@ Boolean ForceRectInRect (Rect *small, Rect *large) changed = false; - NormalizeRect(small); + if (NormalizeRect(small)) + changed = true; if ((small->bottom - small->top) > (large->bottom - large->top)) { diff --git a/GpApp/RectUtils.h b/GpApp/RectUtils.h index 5affd19..8c3c9eb 100644 --- a/GpApp/RectUtils.h +++ b/GpApp/RectUtils.h @@ -17,7 +17,7 @@ namespace PortabilityLayer void FrameWHRect (short, short, short, short, PortabilityLayer::ResolveCachingColor &color); -void NormalizeRect (Rect *); +Boolean NormalizeRect (Rect *); void ZeroRectCorner (Rect *); void CenterRectOnPoint (Rect *, Point); short HalfRectWide (Rect *); diff --git a/GpApp/RoomInfo.cpp b/GpApp/RoomInfo.cpp index 122ecec..d66dca3 100644 --- a/GpApp/RoomInfo.cpp +++ b/GpApp/RoomInfo.cpp @@ -153,9 +153,9 @@ void DragMiniTile (Window *window, DrawSurface *surface, Point mouseIs, short *n surface->InvertFrameRect(dragRect, pattern); mouseWas = mouseIs; - while (WaitMouseUp()) // loop until mouse button let up + while (WaitMouseUp_DisarmAsyncify()) // loop until mouse button let up { - GetMouse(window, &mouseIs); // get mouse coords + GetMouse(window, &mouseIs); // get mouse coords if (mouseWas != mouseIs) // the mouse has moved { surface->InvertFrameRect(dragRect, pattern); diff --git a/GpApp/Scoreboard.cpp b/GpApp/Scoreboard.cpp index 16351b4..7d70f12 100644 --- a/GpApp/Scoreboard.cpp +++ b/GpApp/Scoreboard.cpp @@ -176,7 +176,7 @@ void RefreshRoomTitle (short mode) const Point strShadowPoint = Point::Create(1, 10); const Point strPoint = Point::Create(0, 9); - PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12Bold); + PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12SyntheticBold); switch (mode) { @@ -221,7 +221,7 @@ void RefreshNumGliders (void) long displayMortals; DrawSurface *surface = boardGSrcMap; - PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12Bold); + PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12SyntheticBold); PortabilityLayer::ResolveCachingColor theRGBColor = PortabilityLayer::ResolveCachingColor::FromStandardColor(kGrayBackgroundColor); PortabilityLayer::ResolveCachingColor blackColor = StdColors::Black(); @@ -256,7 +256,7 @@ void RefreshPoints (void) PortabilityLayer::ResolveCachingColor blackColor = StdColors::Black(); PortabilityLayer::ResolveCachingColor whiteColor = StdColors::White(); - PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12Bold); + PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12SyntheticBold); surface->FillRect(boardPSrcRect, theRGBColor); @@ -286,7 +286,7 @@ void QuickGlidersRefresh (void) PortabilityLayer::ResolveCachingColor blackColor = StdColors::Black(); PortabilityLayer::ResolveCachingColor whiteColor = StdColors::White(); - PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12Bold); + PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12SyntheticBold); surface->FillRect(boardGSrcRect, theRGBColor); @@ -316,7 +316,7 @@ void QuickScoreRefresh (void) PortabilityLayer::ResolveCachingColor blackColor = StdColors::Black(); PortabilityLayer::ResolveCachingColor whiteColor = StdColors::White(); - PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12Bold); + PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication12SyntheticBold); surface->FillRect(boardPSrcRect, theRGBColor); diff --git a/GpApp/Sound.cpp b/GpApp/Sound.cpp index c69b0dc..8475d31 100644 --- a/GpApp/Sound.cpp +++ b/GpApp/Sound.cpp @@ -10,6 +10,8 @@ #include "PLSound.h" #include "DialogManager.h" #include "Externs.h" +#include "IGpAudioBuffer.h" +#include "IGpAudioDriver.h" #include "IGpLogDriver.h" #include "MemoryManager.h" #include "ResourceManager.h" @@ -31,10 +33,10 @@ PLError_t LoadBufferSounds (void); void DumpBufferSounds (void); PLError_t OpenSoundChannels (void); void CloseSoundChannels (void); -THandle ParseAndConvertSound(const THandle &handle); +IGpAudioBuffer *ParseAndConvertSound(const THandle &handle); PortabilityLayer::AudioChannel *channel0, *channel1, *channel2; -Ptr theSoundData[kMaxSounds]; +IGpAudioBuffer *theSoundData[kMaxSounds]; short numSoundsLoaded; Boolean soundLoaded[kMaxSounds], dontLoadSounds; Boolean channelOpen, isSoundOn, failedSound; @@ -192,24 +194,20 @@ PLError_t LoadTriggerSound (short soundID) theErr = PLErrors::kNone; - theSound = ParseAndConvertSound(LoadHouseResource('snd ', soundID)); + theSound = LoadHouseResource('snd ', soundID); if (theSound == nil) - { - theErr = PLErrors::kFileNotFound; - } + theErr = PLErrors::kResourceError; else { - soundDataSize = GetHandleSize(theSound); - theSoundData[kMaxSounds - 1] = PortabilityLayer::MemoryManager::GetInstance()->Alloc(soundDataSize); - if (theSoundData[kMaxSounds - 1] == nil) - { - theSound.Dispose(); - theErr = PLErrors::kOutOfMemory; - } + IGpAudioBuffer *buffer = ParseAndConvertSound(theSound); + theSound.Dispose(); + + if (buffer == nil) + theErr = PLErrors::kResourceError; else { - memcpy(theSoundData[kMaxSounds - 1], (Byte*)(*theSound), soundDataSize); - theSound.Dispose(); + assert(theSoundData[kMaxSounds - 1] == nil); + theSoundData[kMaxSounds - 1] = buffer; } } } @@ -222,7 +220,7 @@ PLError_t LoadTriggerSound (short soundID) void DumpTriggerSound (void) { if (theSoundData[kMaxSounds - 1] != nil) - PortabilityLayer::MemoryManager::GetInstance()->Release(theSoundData[kMaxSounds - 1]); + theSoundData[kMaxSounds - 1]->Release(); theSoundData[kMaxSounds - 1] = nil; } @@ -239,21 +237,21 @@ PLError_t LoadBufferSounds (void) for (i = 0; i < kMaxSounds - 1; i++) { - theSound = ParseAndConvertSound(PortabilityLayer::ResourceManager::GetInstance()->GetAppResource('snd ', i + kBaseBufferSoundID)); + theSound = PortabilityLayer::ResourceManager::GetInstance()->GetAppResource('snd ', i + kBaseBufferSoundID); if (theSound == nil) - return (PLErrors::kOutOfMemory); - - soundDataSize = GetHandleSize(theSound); - - theSoundData[i] = PortabilityLayer::MemoryManager::GetInstance()->Alloc(soundDataSize); - if (theSoundData[i] == nil) - return (PLErrors::kOutOfMemory); - - memcpy(theSoundData[i], *theSound, soundDataSize); + return (PLErrors::kResourceError); + + IGpAudioBuffer *buffer = ParseAndConvertSound(theSound); theSound.Dispose(); + + if (!buffer) + return PLErrors::kResourceError; + + assert(theSoundData[i] == nil); + theSoundData[i] = buffer; } - - theSoundData[kMaxSounds - 1] = nil; + + assert(theSoundData[kMaxSounds - 1] == nil); return (theErr); } @@ -267,7 +265,7 @@ void DumpBufferSounds (void) for (i = 0; i < kMaxSounds; i++) { if (theSoundData[i] != nil) - PortabilityLayer::MemoryManager::GetInstance()->Release(theSoundData[i]); + theSoundData[i]->Release(); theSoundData[i] = nil; } } @@ -406,23 +404,23 @@ void TellHerNoSounds (void) //-------------------------------------------------------------- ParseAndConvertSound -THandle ParseAndConvertSoundChecked(const THandle &handle) +IGpAudioBuffer *ParseAndConvertSoundChecked(const THandle &handle) { const uint8_t *dataStart = static_cast(*handle); const size_t size = handle.MMBlock()->m_size; if (size < sizeof(PortabilityLayer::RIFFTag)) - return THandle(); + return nullptr; PortabilityLayer::RIFFTag mainRiffTag; memcpy(&mainRiffTag, dataStart, sizeof(PortabilityLayer::RIFFTag)); if (mainRiffTag.m_tag != PortabilityLayer::WaveConstants::kRiffChunkID) - return THandle(); + return nullptr; const uint32_t riffSize = mainRiffTag.m_chunkSize; if (riffSize < 4 || riffSize - 4 > size - sizeof(PortabilityLayer::RIFFTag)) - return THandle(); + return nullptr; const uint8_t *riffStart = dataStart + sizeof(PortabilityLayer::RIFFTag); const uint8_t *riffEnd = riffStart + riffSize; @@ -434,7 +432,7 @@ THandle ParseAndConvertSoundChecked(const THandle &handle) memcpy(&waveMarker, riffStart, 4); if (waveMarker != PortabilityLayer::WaveConstants::kWaveChunkID) - return THandle(); + return nullptr; const uint8_t *tagSearchLoc = riffStart + 4; @@ -442,7 +440,7 @@ THandle ParseAndConvertSoundChecked(const THandle &handle) while (tagSearchLoc != riffEnd) { if (riffEnd - tagSearchLoc < sizeof(PortabilityLayer::RIFFTag)) - return THandle(); + return nullptr; PortabilityLayer::RIFFTag riffTag; memcpy(&riffTag, tagSearchLoc, sizeof(PortabilityLayer::RIFFTag)); @@ -455,20 +453,20 @@ THandle ParseAndConvertSoundChecked(const THandle &handle) const uint32_t riffTagSizeUnpadded = riffTag.m_chunkSize; if (riffTagSizeUnpadded == 0xffffffffU) - return THandle(); + return nullptr; const uint32_t riffTagSizePadded = riffTagSizeUnpadded + (riffTagSizeUnpadded & 1); tagSearchLoc += sizeof(PortabilityLayer::RIFFTag); if (riffEnd - tagSearchLoc < riffTagSizePadded) - return THandle(); + return nullptr; tagSearchLoc += riffTagSizePadded; } if (formatTagLoc == nullptr || dataTagLoc == nullptr) - return THandle(); + return nullptr; PortabilityLayer::RIFFTag fmtTag; memcpy(&fmtTag, formatTagLoc, sizeof(PortabilityLayer::RIFFTag)); @@ -502,7 +500,7 @@ THandle ParseAndConvertSoundChecked(const THandle &handle) copyableSize = sizeof(PortabilityLayer::WaveFormatChunkV1); } else - return THandle(); + return nullptr; memcpy(&formatChunkV3, formatContents, copyableSize); @@ -510,35 +508,30 @@ THandle ParseAndConvertSoundChecked(const THandle &handle) const PortabilityLayer::WaveFormatChunkV1 formatChunkV1 = formatChunkV2.m_v1; if (formatChunkV1.m_bitsPerSample != 8) - return THandle(); + return nullptr; if (formatChunkV1.m_formatCode != PortabilityLayer::WaveConstants::kFormatPCM || formatChunkV1.m_numChannels != 1 || formatChunkV1.m_blockAlignmentBytes != 1 || formatChunkV1.m_bitsPerSample != 8) - return THandle(); - - THandle convertedHandle = THandle(PortabilityLayer::MemoryManager::GetInstance()->AllocHandle(4 + dataTag.m_chunkSize)); - if (!convertedHandle) - return THandle(); - - uint8_t *handleData = static_cast(*convertedHandle); + return nullptr; uint32_t dataSize = dataTag.m_chunkSize; - memcpy(handleData, &dataSize, 4); + if (dataSize > 0x1000000 || dataSize < 1) + return nullptr; - memcpy(handleData + 4, dataContents, dataSize); + IGpAudioDriver *audioDriver = PLDrivers::GetAudioDriver(); + if (!audioDriver) + return nullptr; - return convertedHandle; + return audioDriver->CreateBuffer(dataContents, dataSize); } -THandle ParseAndConvertSound(const THandle &handle) +IGpAudioBuffer *ParseAndConvertSound(const THandle &handle) { if (!handle) - return THandle(); + return nullptr; - THandle converted = ParseAndConvertSoundChecked(handle); - handle.Dispose(); - - return converted; + IGpAudioBuffer *buffer = ParseAndConvertSoundChecked(handle); + return buffer; } diff --git a/GpApp/Tools.cpp b/GpApp/Tools.cpp index abe82f8..234292c 100644 --- a/GpApp/Tools.cpp +++ b/GpApp/Tools.cpp @@ -156,7 +156,7 @@ void DrawToolName (DrawSurface *surface) const Point textPoint = Point::Create(toolTextRect.left + 3, toolTextRect.bottom - 6); - PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication9Bold); + PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication9SyntheticBold); ColorText(surface, textPoint, theString, 171L, appFont); } #endif diff --git a/GpAudioDriver_XAudio2/GpAudioBufferXAudio2.cpp b/GpAudioDriver_XAudio2/GpAudioBufferXAudio2.cpp new file mode 100644 index 0000000..6f4e76d --- /dev/null +++ b/GpAudioDriver_XAudio2/GpAudioBufferXAudio2.cpp @@ -0,0 +1,69 @@ +#include "GpAudioBufferXAudio2.h" +#include "CoreDefs.h" +#include "GpWindows.h" +#include "IGpAllocator.h" + +#include +#include + +GpAudioBufferXAudio2 *GpAudioBufferXAudio2::Create(IGpAllocator *alloc, const void *buffer, size_t size) +{ + size_t baseSize = sizeof(GpAudioBufferXAudio2); + baseSize = baseSize + GP_SYSTEM_MEMORY_ALIGNMENT - 1; + baseSize -= baseSize % GP_SYSTEM_MEMORY_ALIGNMENT; + + size_t totalSize = baseSize + size; + + void *storage = alloc->Realloc(nullptr, totalSize); + if (!storage) + return nullptr; + + void *dataPos = static_cast(storage) + baseSize; + + memcpy(dataPos, buffer, size); + return new (storage) GpAudioBufferXAudio2(alloc, dataPos, size); +} + +void GpAudioBufferXAudio2::AddRef() +{ + InterlockedIncrement(&m_count); +} + +void GpAudioBufferXAudio2::Release() +{ + if (InterlockedDecrement(&m_count) == 0) + this->Destroy(); +} + +const XAUDIO2_BUFFER *GpAudioBufferXAudio2::GetXA2Buffer() const +{ + return &m_xa2Buffer; +} + +GpAudioBufferXAudio2::GpAudioBufferXAudio2(IGpAllocator *alloc, const void *data, size_t size) + : m_alloc(alloc) + , m_data(data) + , m_size(size) + , m_count(1) +{ + m_xa2Buffer.Flags = 0; + m_xa2Buffer.AudioBytes = static_cast(size); + m_xa2Buffer.pAudioData = static_cast(data); + m_xa2Buffer.PlayBegin = 0; + m_xa2Buffer.PlayLength = 0; + m_xa2Buffer.LoopBegin = 0; + m_xa2Buffer.LoopLength = 0; + m_xa2Buffer.LoopCount = 0; + m_xa2Buffer.pContext = this; +} + +GpAudioBufferXAudio2::~GpAudioBufferXAudio2() +{ +} + +void GpAudioBufferXAudio2::Destroy() +{ + IGpAllocator *alloc = m_alloc; + this->~GpAudioBufferXAudio2(); + m_alloc->Realloc(this, 0); +} diff --git a/GpAudioDriver_XAudio2/GpAudioBufferXAudio2.h b/GpAudioDriver_XAudio2/GpAudioBufferXAudio2.h new file mode 100644 index 0000000..ad5ac06 --- /dev/null +++ b/GpAudioDriver_XAudio2/GpAudioBufferXAudio2.h @@ -0,0 +1,32 @@ +#pragma once + +#include "IGpAudioBuffer.h" + +#include + +struct IGpAllocator; + +class GpAudioBufferXAudio2 final : public IGpAudioBuffer +{ +public: + static GpAudioBufferXAudio2 *Create(IGpAllocator *alloc, const void *buffer, size_t size); + + void AddRef() override; + void Release() override; + + const XAUDIO2_BUFFER *GetXA2Buffer() const; + +private: + GpAudioBufferXAudio2(IGpAllocator *alloc, const void *data, size_t size); + ~GpAudioBufferXAudio2(); + + void Destroy(); + + const void *m_data; + size_t m_size; + IGpAllocator *m_alloc; + + XAUDIO2_BUFFER m_xa2Buffer; + + volatile unsigned int m_count; +}; diff --git a/GpAudioDriver_XAudio2/GpAudioChannelXAudio2.cpp b/GpAudioDriver_XAudio2/GpAudioChannelXAudio2.cpp index 54a13d0..36ccaeb 100644 --- a/GpAudioDriver_XAudio2/GpAudioChannelXAudio2.cpp +++ b/GpAudioDriver_XAudio2/GpAudioChannelXAudio2.cpp @@ -1,25 +1,27 @@ +#include "GpAudioBufferXAudio2.h" #include "GpAudioChannelXAudio2.h" #include "GpAudioDriverXAudio2.h" +#include "IGpAllocator.h" #include "IGpAudioChannelCallbacks.h" #include "IGpLogDriver.h" #include #include -GpAudioChannelXAudio2 *GpAudioChannelXAudio2::Create(GpAudioDriverXAudio2 *driver) +GpAudioChannelXAudio2 *GpAudioChannelXAudio2::Create(IGpAllocator *alloc, GpAudioDriverXAudio2 *driver) { IGpLogDriver *logger = driver->GetProperties().m_logger; - void *storage = malloc(sizeof(GpAudioChannelXAudio2)); + void *storage = alloc->Realloc(nullptr, sizeof(GpAudioChannelXAudio2)); if (!storage) { if (!logger) - logger->Printf(IGpLogDriver::Category_Error, "GpAudioChannelXAudio2::Create failed, malloc failed"); + logger->Printf(IGpLogDriver::Category_Error, "GpAudioChannelXAudio2::Create failed, alloc failed"); return nullptr; } - GpAudioChannelXAudio2 *channel = new (storage) GpAudioChannelXAudio2(driver); + GpAudioChannelXAudio2 *channel = new (storage) GpAudioChannelXAudio2(alloc, driver); if (!channel->Init()) { if (!logger) @@ -77,25 +79,25 @@ void GpAudioChannelXAudio2::SetAudioChannelContext(IGpAudioChannelCallbacks *cal m_contextCallbacks = callbacks; } -void GpAudioChannelXAudio2::PostBuffer(const void *buffer, size_t bufferSize) +bool GpAudioChannelXAudio2::PostBuffer(IGpAudioBuffer *buffer) { - XAUDIO2_BUFFER xa2Buffer; - xa2Buffer.Flags = 0; - xa2Buffer.AudioBytes = static_cast(bufferSize); - xa2Buffer.pAudioData = static_cast(buffer); - xa2Buffer.PlayBegin = 0; - xa2Buffer.PlayLength = 0; - xa2Buffer.LoopBegin = 0; - xa2Buffer.LoopLength = 0; - xa2Buffer.LoopCount = 0; - xa2Buffer.pContext = nullptr; + GpAudioBufferXAudio2 *xa2Buffer = static_cast(buffer); + xa2Buffer->AddRef(); + + HRESULT result = m_sourceVoice->SubmitSourceBuffer(xa2Buffer->GetXA2Buffer(), nullptr); + if (result != S_OK) + { + xa2Buffer->Release(); + return false; + } - m_sourceVoice->SubmitSourceBuffer(&xa2Buffer, nullptr); if (m_voiceState == VoiceState_Idle) { m_voiceState = VoiceState_Active; m_sourceVoice->Start(0, 0); } + + return true; } void GpAudioChannelXAudio2::Stop() @@ -109,8 +111,9 @@ void GpAudioChannelXAudio2::Stop() void GpAudioChannelXAudio2::Destroy() { + IGpAllocator *alloc = m_alloc; this->~GpAudioChannelXAudio2(); - free(this); + alloc->Realloc(this, 0); } void GpAudioChannelXAudio2::OnBufferEnd() @@ -119,12 +122,13 @@ void GpAudioChannelXAudio2::OnBufferEnd() m_contextCallbacks->NotifyBufferFinished(); } -GpAudioChannelXAudio2::GpAudioChannelXAudio2(GpAudioDriverXAudio2 *driver) +GpAudioChannelXAudio2::GpAudioChannelXAudio2(IGpAllocator *alloc, GpAudioDriverXAudio2 *driver) : m_driver(driver) , m_xAudioCallbacks(this) , m_sourceVoice(nullptr) , m_contextCallbacks(nullptr) , m_voiceState(VoiceState_Idle) + , m_alloc(alloc) { } diff --git a/GpAudioDriver_XAudio2/GpAudioChannelXAudio2.h b/GpAudioDriver_XAudio2/GpAudioChannelXAudio2.h index b9317b2..1c0c9b7 100644 --- a/GpAudioDriver_XAudio2/GpAudioChannelXAudio2.h +++ b/GpAudioDriver_XAudio2/GpAudioChannelXAudio2.h @@ -7,16 +7,17 @@ class GpAudioDriverXAudio2; class GpAudioChannelXAudio2Callbacks; struct IXAudio2SourceVoice; +struct IGpAllocator; class GpAudioChannelXAudio2 final : public IGpAudioChannel { public: friend class GpAudioChannelXAudio2Callbacks; - static GpAudioChannelXAudio2 *Create(GpAudioDriverXAudio2 *driver); + static GpAudioChannelXAudio2 *Create(IGpAllocator *alloc, GpAudioDriverXAudio2 *driver); void SetAudioChannelContext(IGpAudioChannelCallbacks *callbacks) override; - void PostBuffer(const void *buffer, size_t bufferSize) override; + bool PostBuffer(IGpAudioBuffer *buffer) override; void Stop() override; void Destroy() override; @@ -32,12 +33,13 @@ private: VoiceState_Active, }; - explicit GpAudioChannelXAudio2(GpAudioDriverXAudio2 *driver); + explicit GpAudioChannelXAudio2(IGpAllocator *alloc, GpAudioDriverXAudio2 *driver); ~GpAudioChannelXAudio2(); GpAudioDriverXAudio2 *m_driver; IXAudio2SourceVoice *m_sourceVoice; GpAudioChannelXAudio2Callbacks m_xAudioCallbacks; IGpAudioChannelCallbacks *m_contextCallbacks; + IGpAllocator *m_alloc; VoiceState m_voiceState; }; diff --git a/GpAudioDriver_XAudio2/GpAudioChannelXAudio2Callbacks.cpp b/GpAudioDriver_XAudio2/GpAudioChannelXAudio2Callbacks.cpp index 0291043..8016f28 100644 --- a/GpAudioDriver_XAudio2/GpAudioChannelXAudio2Callbacks.cpp +++ b/GpAudioDriver_XAudio2/GpAudioChannelXAudio2Callbacks.cpp @@ -1,3 +1,4 @@ +#include "GpAudioBufferXAudio2.h" #include "GpAudioChannelXAudio2Callbacks.h" #include "GpAudioChannelXAudio2.h" @@ -24,6 +25,7 @@ void GpAudioChannelXAudio2Callbacks::OnBufferStart(void* pBufferContext) void GpAudioChannelXAudio2Callbacks::OnBufferEnd(void* pBufferContext) { + static_cast(pBufferContext)->Release(); m_owner->OnBufferEnd(); } diff --git a/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.cpp b/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.cpp index dfdb0ef..5fe3986 100644 --- a/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.cpp +++ b/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.cpp @@ -1,7 +1,9 @@ #include "GpAudioDriverXAudio2.h" #include "IGpLogDriver.h" +#include "GpAudioBufferXAudio2.h" #include "GpAudioChannelXAudio2.h" +#include "CoreDefs.h" #include @@ -96,9 +98,14 @@ GpAudioDriverXAudio2 *GpAudioDriverXAudio2::Create(const GpAudioDriverProperties return new GpAudioDriverXAudio2(properties, realSampleRate, xa, mv); } +IGpAudioBuffer *GpAudioDriverXAudio2::CreateBuffer(const void *buffer, size_t bufferSize) +{ + return GpAudioBufferXAudio2::Create(m_properties.m_alloc, buffer, bufferSize); +} + IGpAudioChannel *GpAudioDriverXAudio2::CreateChannel() { - return GpAudioChannelXAudio2::Create(this); + return GpAudioChannelXAudio2::Create(m_properties.m_alloc, this); } void GpAudioDriverXAudio2::SetMasterVolume(uint32_t vol, uint32_t maxVolume) diff --git a/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.h b/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.h index 4a9c070..563034f 100644 --- a/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.h +++ b/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.h @@ -10,6 +10,7 @@ struct IXAudio2MasteringVoice; class GpAudioDriverXAudio2 : public IGpAudioDriver { public: + IGpAudioBuffer *CreateBuffer(const void *buffer, size_t bufferSize) override; IGpAudioChannel *CreateChannel() override; void SetMasterVolume(uint32_t vol, uint32_t maxVolume) override; void Shutdown() override; diff --git a/GpAudioDriver_XAudio2/GpAudioDriver_XAudio2.vcxproj b/GpAudioDriver_XAudio2/GpAudioDriver_XAudio2.vcxproj index 4af8dee..44a373a 100644 --- a/GpAudioDriver_XAudio2/GpAudioDriver_XAudio2.vcxproj +++ b/GpAudioDriver_XAudio2/GpAudioDriver_XAudio2.vcxproj @@ -38,11 +38,14 @@ + + + @@ -69,12 +72,14 @@ + + diff --git a/GpAudioDriver_XAudio2/GpAudioDriver_XAudio2.vcxproj.filters b/GpAudioDriver_XAudio2/GpAudioDriver_XAudio2.vcxproj.filters index 26eedc7..cc33b93 100644 --- a/GpAudioDriver_XAudio2/GpAudioDriver_XAudio2.vcxproj.filters +++ b/GpAudioDriver_XAudio2/GpAudioDriver_XAudio2.vcxproj.filters @@ -27,6 +27,9 @@ Header Files + + Header Files + @@ -41,6 +44,9 @@ Source Files + + Source Files + diff --git a/GpCommon/GpAudioDriverProperties.h b/GpCommon/GpAudioDriverProperties.h index 1372270..7643463 100644 --- a/GpCommon/GpAudioDriverProperties.h +++ b/GpCommon/GpAudioDriverProperties.h @@ -5,6 +5,7 @@ struct IGpSystemServices; struct IGpAudioDriver; struct IGpLogDriver; +struct IGpAllocator; struct GpAudioDriverProperties { @@ -15,4 +16,5 @@ struct GpAudioDriverProperties IGpLogDriver *m_logger; IGpSystemServices *m_systemServices; + IGpAllocator *m_alloc; }; diff --git a/GpCommon/GpComPtr.h b/GpCommon/GpComPtr.h index 6f42d3d..4ea5aac 100644 --- a/GpCommon/GpComPtr.h +++ b/GpCommon/GpComPtr.h @@ -1,11 +1,16 @@ #pragma once +#include "CoreDefs.h" + template class GpComPtr final { public: GpComPtr(); GpComPtr(const GpComPtr &other); +#if GP_IS_CPP11 + GpComPtr(GpComPtr &&other); +#endif explicit GpComPtr(T *ptr); ~GpComPtr(); @@ -41,6 +46,23 @@ inline GpComPtr::GpComPtr(const GpComPtr &other) m_ptr->AddRef(); } +#if GP_IS_CPP11 +template +inline GpComPtr::GpComPtr(GpComPtr &&other) + : m_ptr(other.m_ptr) +{ + if (m_ptr) + m_ptr->AddRef(); + + if (other.m_ptr) + { + other.m_ptr->Release(); + other.m_ptr = nullptr; + } +} +#endif + + template inline GpComPtr::GpComPtr(T *ptr) : m_ptr(ptr) diff --git a/GpCommon/GpDisplayDriverProperties.h b/GpCommon/GpDisplayDriverProperties.h index 733aa4c..1ffb639 100644 --- a/GpCommon/GpDisplayDriverProperties.h +++ b/GpCommon/GpDisplayDriverProperties.h @@ -10,6 +10,7 @@ struct IGpFiber; struct IGpVOSEventQueue; struct IGpLogDriver; struct IGpSystemServices; +struct IGpAllocator; struct GpDisplayDriverProperties { @@ -43,4 +44,5 @@ struct GpDisplayDriverProperties IGpVOSEventQueue *m_eventQueue; IGpLogDriver *m_logger; IGpSystemServices *m_systemServices; + IGpAllocator *m_alloc; }; diff --git a/GpCommon/GpDriverIndex.h b/GpCommon/GpDriverIndex.h index 6664218..9d346a2 100644 --- a/GpCommon/GpDriverIndex.h +++ b/GpCommon/GpDriverIndex.h @@ -16,6 +16,7 @@ namespace GpDriverIDs kSystemServices, kFont, kEventQueue, + kAlloc, kCount }; @@ -54,6 +55,7 @@ GP_DEFINE_MULTI_DRIVER(kInput, IGpInputDriver); GP_DEFINE_DRIVER(kSystemServices, IGpSystemServices); GP_DEFINE_DRIVER(kFont, IGpFontHandler); GP_DEFINE_DRIVER(kEventQueue, IGpVOSEventQueue); +GP_DEFINE_DRIVER(kAlloc, IGpAllocator); struct GpDriverCollection { diff --git a/GpCommon/GpFontHandlerProperties.h b/GpCommon/GpFontHandlerProperties.h index 2ca1355..413c3d0 100644 --- a/GpCommon/GpFontHandlerProperties.h +++ b/GpCommon/GpFontHandlerProperties.h @@ -2,7 +2,11 @@ #include "EGpFontHandlerType.h" +struct IGpAllocator; + struct GpFontHandlerProperties { EGpFontHandlerType m_type; + + IGpAllocator *m_alloc; }; diff --git a/GpCommon/GpIOStream.h b/GpCommon/GpIOStream.h index 302a3a5..e246e1f 100644 --- a/GpCommon/GpIOStream.h +++ b/GpCommon/GpIOStream.h @@ -3,6 +3,7 @@ #include #include "GpFilePos.h" +#include "CoreDefs.h" class GpIOStream { @@ -17,11 +18,15 @@ public: virtual bool SeekEnd(GpUFilePos_t loc) = 0; virtual GpUFilePos_t Size() const = 0; virtual GpUFilePos_t Tell() const = 0; - virtual void Close() = 0; + virtual void GP_ASYNCIFY_PARANOID_NAMED(Close)() = 0; virtual void Flush() = 0; bool ReadExact(void *bytesOut, size_t size); bool WriteExact(const void *bytesOut, size_t size); + +#if GP_ASYNCIFY_PARANOID + void Close(); +#endif }; inline bool GpIOStream::ReadExact(void *bytesOut, size_t size) diff --git a/GpCommon/GpInputDriverProperties.h b/GpCommon/GpInputDriverProperties.h index 0e13548..e8d003d 100644 --- a/GpCommon/GpInputDriverProperties.h +++ b/GpCommon/GpInputDriverProperties.h @@ -4,10 +4,12 @@ struct IGpAudioDriver; struct IGpVOSEventQueue; +struct IGpAllocator; struct GpInputDriverProperties { EGpInputDriverType m_type; IGpVOSEventQueue *m_eventQueue; + IGpAllocator *m_alloc; }; diff --git a/GpCommon/GpRenderedGlyphMetrics.h b/GpCommon/GpRenderedGlyphMetrics.h index b797cc5..91415a8 100644 --- a/GpCommon/GpRenderedGlyphMetrics.h +++ b/GpCommon/GpRenderedGlyphMetrics.h @@ -12,4 +12,6 @@ struct GpRenderedGlyphMetrics int16_t m_bearingX; int16_t m_bearingY; int16_t m_advanceX; + int16_t m_bitmapOffsetX; + int16_t m_bitmapOffsetY; }; diff --git a/GpCommon/GpUnicode.h b/GpCommon/GpUnicode.h new file mode 100644 index 0000000..786b4b5 --- /dev/null +++ b/GpCommon/GpUnicode.h @@ -0,0 +1,165 @@ +#pragma once + +#include +#include + +namespace GpUnicode +{ + namespace UTF8 + { + static const unsigned int kMaxEncodedBytes = 4; + + inline bool Decode(const uint8_t *characters, size_t availableCharacters, size_t &outCharactersDigested, uint32_t &outCodePoint) + { + if (availableCharacters <= 0) + return false; + + if ((characters[0] & 0x80) == 0x00) + { + outCharactersDigested = 1; + outCodePoint = characters[0]; + return true; + } + + size_t sz = 0; + uint32_t codePoint = 0; + uint32_t minCodePoint = 0; + if ((characters[0] & 0xe0) == 0xc0) + { + sz = 2; + minCodePoint = 0x80; + codePoint = (characters[0] & 0x1f); + } + else if ((characters[0] & 0xf0) == 0xe0) + { + sz = 3; + minCodePoint = 0x800; + codePoint = (characters[0] & 0x0f); + } + else if ((characters[0] & 0xf8) == 0xf0) + { + sz = 4; + minCodePoint = 0x10000; + codePoint = (characters[0] & 0x07); + } + else + return false; + + if (availableCharacters < sz) + return false; + + for (size_t auxByte = 1; auxByte < sz; auxByte++) + { + if ((characters[auxByte] & 0xc0) != 0x80) + return false; + + codePoint = (codePoint << 6) | (characters[auxByte] & 0x3f); + } + + if (codePoint < minCodePoint || codePoint > 0x10ffff) + return false; + + if (codePoint >= 0xd800 && codePoint <= 0xdfff) + return false; + + outCodePoint = codePoint; + outCharactersDigested = sz; + + return true; + } + + inline void Encode(uint8_t *characters, size_t &outCharactersEmitted, uint32_t codePoint) + { + codePoint &= 0x1fffff; + + uint8_t signalBits = 0; + size_t numBytes = 0; + if (codePoint < 0x0080) + { + numBytes = 1; + signalBits = 0; + } + else if (codePoint < 0x0800) + { + numBytes = 2; + signalBits = 0xc0; + } + else if (codePoint < 0x10000) + { + numBytes = 3; + signalBits = 0xe0; + } + else + { + numBytes = 4; + signalBits = 0xf0; + } + + characters[0] = static_cast((codePoint >> (6 * (numBytes - 1))) | signalBits); + + for (size_t i = 1; i < numBytes; i++) + { + const uint32_t isolate = ((codePoint >> (6 * (numBytes - 1 - i))) & 0x3f) | 0x80; + characters[i] = static_cast(isolate); + } + + outCharactersEmitted = numBytes; + } + } + + namespace UTF16 + { + inline bool Decode(const uint16_t *characters, size_t availableCharacters, size_t &outCharactersDigested, uint32_t &outCodePoint) + { + if (availableCharacters <= 0) + return false; + + if ((characters[0] & 0xff80) == 0x00) + { + outCharactersDigested = 1; + outCodePoint = characters[0]; + return true; + } + + if (characters[0] <= 0xd7ff || characters[0] >= 0xe000) + { + outCharactersDigested = 1; + outCodePoint = characters[0]; + return true; + } + + // Surrogate pair + if (characters[0] >= 0xdc00 || availableCharacters < 2) + return false; + + if (characters[1] < 0xdc00 || characters[1] >= 0xe000) + return false; + + uint16_t highBits = (characters[0] & 0x3ff); + uint16_t lowBits = (characters[1] & 0x3ff); + + outCharactersDigested = 2; + outCodePoint = (highBits << 10) + lowBits + 0x10000; + + return true; + } + + inline void Encode(uint16_t *characters, size_t &outCharactersEmitted, uint32_t codePoint) + { + if (codePoint <= 0xd7ff || codePoint >= 0xe000) + { + outCharactersEmitted = 1; + characters[0] = static_cast(codePoint); + return; + } + + uint32_t codePointBits = (codePoint - 0x10000) & 0xfffff; + uint16_t lowBits = (codePointBits & 0x3ff); + uint16_t highBits = ((codePointBits >> 10) & 0x3ff); + + outCharactersEmitted = 2; + characters[0] = (0xd800 + highBits); + characters[1] = (0xdc00 + lowBits); + } + } +} diff --git a/GpCommon/GpWindows.h b/GpCommon/GpWindows.h index bc53aac..8857d87 100644 --- a/GpCommon/GpWindows.h +++ b/GpCommon/GpWindows.h @@ -13,6 +13,7 @@ struct IGpBWCursor_Win32; struct IGpCursor_Win32; +struct IGpAllocator; struct IGpVOSEventQueue; struct GpWindowsGlobals @@ -28,7 +29,7 @@ struct GpWindowsGlobals HICON m_hIconSm; int m_nCmdShow; - IGpCursor_Win32 *(*m_createColorCursorFunc)(size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY); - IGpCursor_Win32 *(*m_createBWCursorFunc)(size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY); + IGpCursor_Win32 *(*m_createColorCursorFunc)(IGpAllocator *alloc, size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY); + IGpCursor_Win32 *(*m_createBWCursorFunc)(IGpAllocator *alloc, size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY); void (*m_translateWindowsMessageFunc)(const MSG *msg, IGpVOSEventQueue *eventQueue, float pixelScaleX, float pixelScaleY); }; diff --git a/GpCommon/IGpAllocator.h b/GpCommon/IGpAllocator.h new file mode 100644 index 0000000..9cc0703 --- /dev/null +++ b/GpCommon/IGpAllocator.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +struct IGpAllocator +{ + virtual void *Realloc(void *buf, size_t newSize) = 0; + + inline void *Alloc(size_t size) { return this->Realloc(nullptr, size); } + inline void Release(void *ptr) { this->Realloc(ptr, 0); } +}; diff --git a/GpCommon/IGpAudioBuffer.h b/GpCommon/IGpAudioBuffer.h new file mode 100644 index 0000000..89be8de --- /dev/null +++ b/GpCommon/IGpAudioBuffer.h @@ -0,0 +1,8 @@ +#pragma once + +struct IGpAudioBuffer +{ +public: + virtual void AddRef() = 0; + virtual void Release() = 0; +}; diff --git a/GpCommon/IGpAudioChannel.h b/GpCommon/IGpAudioChannel.h index 15a8699..3e18dd3 100644 --- a/GpCommon/IGpAudioChannel.h +++ b/GpCommon/IGpAudioChannel.h @@ -3,11 +3,12 @@ #include struct IGpAudioChannelCallbacks; +struct IGpAudioBuffer; struct IGpAudioChannel { virtual void SetAudioChannelContext(IGpAudioChannelCallbacks *callbacks) = 0; - virtual void PostBuffer(const void *buffer, size_t bufferSize) = 0; + virtual bool PostBuffer(IGpAudioBuffer *buffer) = 0; virtual void Stop() = 0; virtual void Destroy() = 0; }; diff --git a/GpCommon/IGpAudioDriver.h b/GpCommon/IGpAudioDriver.h index 9f77acb..31c086a 100644 --- a/GpCommon/IGpAudioDriver.h +++ b/GpCommon/IGpAudioDriver.h @@ -4,10 +4,12 @@ struct IGpAudioChannel; struct IGpPrefsHandler; +struct IGpAudioBuffer; struct IGpAudioDriver { public: + virtual IGpAudioBuffer *CreateBuffer(const void *buffer, size_t bufferSize) = 0; virtual IGpAudioChannel *CreateChannel() = 0; virtual void SetMasterVolume(uint32_t vol, uint32_t maxVolume) = 0; diff --git a/GpCommon/IGpFileSystem.h b/GpCommon/IGpFileSystem.h index 72ad02a..f3ea479 100644 --- a/GpCommon/IGpFileSystem.h +++ b/GpCommon/IGpFileSystem.h @@ -1,6 +1,7 @@ #pragma once #include "GpFileCreationDisposition.h" +#include "CoreDefs.h" #include "VirtualDirectory.h" #include @@ -17,7 +18,7 @@ public: virtual bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) = 0; virtual bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &exists) = 0; virtual GpIOStream *OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* subPaths, size_t numSubPaths, bool writeAccess, GpFileCreationDisposition_t createDisposition) = 0; - virtual bool DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) = 0; + GP_ASYNCIFY_PARANOID_VIRTUAL bool DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) GP_ASYNCIFY_PARANOID_PURE; virtual IGpDirectoryCursor *ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths) = 0; virtual bool ValidateFilePath(const char *path, size_t pathLen) const = 0; diff --git a/GpCommon/IGpFont.h b/GpCommon/IGpFont.h index a1f8157..50caa1f 100644 --- a/GpCommon/IGpFont.h +++ b/GpCommon/IGpFont.h @@ -8,6 +8,7 @@ struct GpRenderedFontMetrics; struct IGpFont { virtual void Destroy() = 0; - virtual IGpFontRenderedGlyph *Render(uint32_t unicodeCodePoint, unsigned int size, bool aa) = 0; + virtual IGpFontRenderedGlyph *Render(uint32_t unicodeCodePoint, unsigned int size, unsigned int xScale, unsigned int yScale, bool aa) = 0; virtual bool GetLineSpacing(unsigned int size, int32_t &outSpacing) = 0; + virtual bool SupportScaling() const = 0; }; diff --git a/GpCommon/IGpFontHandler.h b/GpCommon/IGpFontHandler.h index c7cd345..f3007f6 100644 --- a/GpCommon/IGpFontHandler.h +++ b/GpCommon/IGpFontHandler.h @@ -7,6 +7,6 @@ struct IGpFontHandler { virtual void Shutdown() = 0; - virtual IGpFont *LoadFont(GpIOStream *stream) = 0; + virtual IGpFont *LoadFont(GpIOStream *stream, int typeFaceIndex) = 0; virtual bool KeepStreamOpen() const = 0; }; diff --git a/GpDisplayDriver_D3D11/CompiledShaders/DrawQuadPaletteP_D3D11.cpp b/GpDisplayDriver_D3D11/CompiledShaders/DrawQuadPaletteP_D3D11.cpp index 3bab0c0..e612160 100644 --- a/GpDisplayDriver_D3D11/CompiledShaders/DrawQuadPaletteP_D3D11.cpp +++ b/GpDisplayDriver_D3D11/CompiledShaders/DrawQuadPaletteP_D3D11.cpp @@ -1,8 +1,8 @@ static unsigned char gs_shaderData[] = { - 68, 88, 66, 67, 167, 218, 15, 90, 211, 69, 240, 219, 76, 79, 17, - 242, 61, 175, 125, 206, 1, 0, 0, 0, 44, 8, 0, 0, 5, 0, + 68, 88, 66, 67, 200, 182, 33, 104, 202, 4, 76, 179, 221, 223, 225, + 247, 101, 77, 248, 3, 1, 0, 0, 0, 12, 8, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 2, 0, 0, 4, 3, 0, 0, 56, - 3, 0, 0, 176, 7, 0, 0, 82, 68, 69, 70, 112, 2, 0, 0, + 3, 0, 0, 144, 7, 0, 0, 82, 68, 69, 70, 112, 2, 0, 0, 1, 0, 0, 0, 180, 0, 0, 0, 3, 0, 0, 0, 28, 0, 0, 0, 0, 4, 255, 255, 0, 137, 0, 0, 72, 2, 0, 0, 124, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 255, @@ -54,7 +54,7 @@ static unsigned char gs_shaderData[] = { 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, - 72, 68, 82, 112, 4, 0, 0, 64, 0, 0, 0, 28, 1, 0, 0, + 72, 68, 82, 80, 4, 0, 0, 64, 0, 0, 0, 20, 1, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 3, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 68, 68, 0, 0, 88, 16, 0, 4, 0, 112, 16, 0, 1, 0, 0, 0, 85, @@ -71,74 +71,72 @@ static unsigned char gs_shaderData[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 1, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 1, 0, 0, 0, - 56, 0, 0, 9, 242, 0, 16, 0, 2, 0, 0, 0, 70, 142, 32, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 142, 32, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 1, - 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, 56, 0, 0, 7, - 242, 0, 16, 0, 1, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, - 0, 70, 14, 16, 0, 2, 0, 0, 0, 38, 0, 0, 9, 0, 208, - 0, 0, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, - 0, 0, 0, 70, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 30, 0, 0, 7, 18, 0, 16, 0, 0, 0, 0, 0, 26, 0, 16, - 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 34, 0, - 0, 8, 34, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, - 0, 0, 0, 42, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 33, 0, 0, 8, 18, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, - 0, 0, 0, 0, 0, 58, 128, 32, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 55, 0, 0, 12, 242, 0, 16, 0, 1, 0, 0, 0, 86, - 5, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 14, 16, - 0, 1, 0, 0, 0, 60, 0, 0, 7, 18, 0, 16, 0, 0, 0, - 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 26, 0, 16, 0, 0, - 0, 0, 0, 55, 0, 0, 12, 242, 0, 16, 0, 0, 0, 0, 0, - 6, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, - 0, 2, 64, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, - 128, 63, 0, 0, 128, 63, 29, 0, 0, 7, 18, 0, 16, 0, 1, - 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, - 0, 0, 0, 0, 13, 0, 4, 3, 10, 0, 16, 0, 1, 0, 0, - 0, 57, 0, 0, 8, 18, 0, 16, 0, 1, 0, 0, 0, 10, 128, - 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 64, 0, 0, 0, - 0, 0, 0, 16, 0, 0, 10, 34, 0, 16, 0, 1, 0, 0, 0, - 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 154, 153, 153, - 62, 154, 153, 25, 63, 205, 204, 204, 61, 0, 0, 0, 0, 0, 0, - 0, 9, 66, 0, 16, 0, 1, 0, 0, 0, 10, 128, 32, 128, 65, - 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 64, 0, 0, - 0, 0, 128, 63, 56, 0, 0, 8, 34, 0, 16, 0, 1, 0, 0, - 0, 26, 0, 16, 0, 1, 0, 0, 0, 10, 128, 32, 0, 0, 0, - 0, 0, 2, 0, 0, 0, 50, 0, 0, 9, 226, 0, 16, 0, 1, - 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 166, 10, 16, 0, - 1, 0, 0, 0, 86, 5, 16, 0, 1, 0, 0, 0, 55, 0, 0, - 9, 114, 0, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, - 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, - 0, 0, 0, 29, 0, 0, 10, 114, 0, 16, 0, 1, 0, 0, 0, - 2, 64, 0, 0, 230, 174, 37, 61, 230, 174, 37, 61, 230, 174, 37, - 61, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, - 0, 10, 114, 0, 16, 0, 2, 0, 0, 0, 70, 2, 16, 0, 0, - 0, 0, 0, 2, 64, 0, 0, 145, 131, 158, 61, 145, 131, 158, 61, - 145, 131, 158, 61, 0, 0, 0, 0, 0, 0, 0, 10, 114, 0, 16, - 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, - 0, 0, 174, 71, 97, 61, 174, 71, 97, 61, 174, 71, 97, 61, 0, - 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, - 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 110, 167, 114, - 63, 110, 167, 114, 63, 110, 167, 114, 63, 0, 0, 0, 0, 47, 0, - 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, - 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, - 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 154, 153, 25, - 64, 154, 153, 25, 64, 154, 153, 25, 64, 0, 0, 0, 0, 25, 0, - 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, - 0, 0, 0, 55, 0, 0, 9, 114, 32, 16, 0, 0, 0, 0, 0, - 70, 2, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 2, 0, 0, - 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, - 16, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 62, - 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 34, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 16, 0, 0, - 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, + 0, 0, 0, 128, 63, 56, 0, 0, 8, 242, 0, 16, 0, 1, 0, + 0, 0, 70, 14, 16, 0, 1, 0, 0, 0, 70, 142, 32, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 9, 0, 208, 0, 0, + 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, + 0, 70, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, 0, 0, 0, 0, 26, 0, 16, 0, 0, + 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 34, 0, 0, 8, + 34, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, + 0, 42, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 33, 0, + 0, 8, 18, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, + 0, 0, 0, 58, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 55, 0, 0, 12, 242, 0, 16, 0, 1, 0, 0, 0, 86, 5, 16, + 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 14, 16, 0, 1, + 0, 0, 0, 60, 0, 0, 7, 18, 0, 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, 0, 0, 26, 0, 16, 0, 0, 0, 0, + 0, 55, 0, 0, 12, 242, 0, 16, 0, 0, 0, 0, 0, 6, 0, + 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, 0, 2, + 64, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 29, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, + 0, 1, 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, + 0, 0, 13, 0, 4, 3, 10, 0, 16, 0, 1, 0, 0, 0, 57, + 0, 0, 8, 18, 0, 16, 0, 1, 0, 0, 0, 10, 128, 32, 0, + 0, 0, 0, 0, 2, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, + 0, 16, 0, 0, 10, 34, 0, 16, 0, 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 154, 153, 153, 62, 154, + 153, 25, 63, 205, 204, 204, 61, 0, 0, 0, 0, 0, 0, 0, 9, + 66, 0, 16, 0, 1, 0, 0, 0, 10, 128, 32, 128, 65, 0, 0, + 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 64, 0, 0, 0, 0, + 128, 63, 56, 0, 0, 8, 34, 0, 16, 0, 1, 0, 0, 0, 26, + 0, 16, 0, 1, 0, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 50, 0, 0, 9, 226, 0, 16, 0, 1, 0, 0, + 0, 6, 9, 16, 0, 0, 0, 0, 0, 166, 10, 16, 0, 1, 0, + 0, 0, 86, 5, 16, 0, 1, 0, 0, 0, 55, 0, 0, 9, 114, + 0, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, + 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, + 0, 29, 0, 0, 10, 114, 0, 16, 0, 1, 0, 0, 0, 2, 64, + 0, 0, 230, 174, 37, 61, 230, 174, 37, 61, 230, 174, 37, 61, 0, + 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, + 114, 0, 16, 0, 2, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, + 0, 2, 64, 0, 0, 145, 131, 158, 61, 145, 131, 158, 61, 145, 131, + 158, 61, 0, 0, 0, 0, 0, 0, 0, 10, 114, 0, 16, 0, 0, + 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, + 174, 71, 97, 61, 174, 71, 97, 61, 174, 71, 97, 61, 0, 0, 0, + 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 110, 167, 114, 63, 110, + 167, 114, 63, 110, 167, 114, 63, 0, 0, 0, 0, 47, 0, 0, 5, + 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, + 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 154, 153, 25, 64, 154, + 153, 25, 64, 154, 153, 25, 64, 0, 0, 0, 0, 25, 0, 0, 5, + 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, + 0, 55, 0, 0, 9, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 2, 0, 0, 0, 70, + 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, + 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 62, 0, 0, + 1, 83, 84, 65, 84, 116, 0, 0, 0, 33, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0, 4, + 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, - 0, 4, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, + 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, }; namespace GpBinarizedShaders diff --git a/GpDisplayDriver_D3D11/CompiledShaders/DrawQuadPaletteP_ICC_D3D11.cpp b/GpDisplayDriver_D3D11/CompiledShaders/DrawQuadPaletteP_ICC_D3D11.cpp index ac4ab75..668b1a9 100644 --- a/GpDisplayDriver_D3D11/CompiledShaders/DrawQuadPaletteP_ICC_D3D11.cpp +++ b/GpDisplayDriver_D3D11/CompiledShaders/DrawQuadPaletteP_ICC_D3D11.cpp @@ -1,8 +1,8 @@ static unsigned char gs_shaderData[] = { - 68, 88, 66, 67, 63, 150, 199, 197, 210, 83, 220, 166, 163, 78, 42, - 252, 31, 18, 160, 91, 1, 0, 0, 0, 240, 7, 0, 0, 5, 0, + 68, 88, 66, 67, 124, 220, 109, 55, 227, 43, 211, 66, 26, 106, 247, + 85, 84, 5, 208, 10, 1, 0, 0, 0, 208, 7, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 2, 0, 0, 4, 3, 0, 0, 56, - 3, 0, 0, 116, 7, 0, 0, 82, 68, 69, 70, 112, 2, 0, 0, + 3, 0, 0, 84, 7, 0, 0, 82, 68, 69, 70, 112, 2, 0, 0, 1, 0, 0, 0, 180, 0, 0, 0, 3, 0, 0, 0, 28, 0, 0, 0, 0, 4, 255, 255, 0, 137, 0, 0, 72, 2, 0, 0, 124, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 255, @@ -54,13 +54,13 @@ static unsigned char gs_shaderData[] = { 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, - 72, 68, 82, 52, 4, 0, 0, 64, 0, 0, 0, 13, 1, 0, 0, + 72, 68, 82, 20, 4, 0, 0, 64, 0, 0, 0, 5, 1, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 3, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 68, 68, 0, 0, 88, 16, 0, 4, 0, 112, 16, 0, 1, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, - 2, 3, 0, 0, 0, 65, 0, 0, 5, 50, 0, 16, 0, 0, 0, + 2, 2, 0, 0, 0, 65, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 27, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 8, 194, 0, 16, 0, 0, 0, 0, 0, 2, 64, 0, @@ -71,70 +71,68 @@ static unsigned char gs_shaderData[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 1, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 1, 0, 0, 0, - 56, 0, 0, 9, 242, 0, 16, 0, 2, 0, 0, 0, 70, 142, 32, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 142, 32, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 1, - 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, 56, 0, 0, 7, - 242, 0, 16, 0, 1, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, - 0, 70, 14, 16, 0, 2, 0, 0, 0, 38, 0, 0, 9, 0, 208, - 0, 0, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, - 0, 0, 0, 70, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 30, 0, 0, 7, 18, 0, 16, 0, 0, 0, 0, 0, 26, 0, 16, - 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 34, 0, - 0, 8, 34, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, - 0, 0, 0, 42, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 33, 0, 0, 8, 18, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, - 0, 0, 0, 0, 0, 58, 128, 32, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 55, 0, 0, 12, 242, 0, 16, 0, 1, 0, 0, 0, 86, - 5, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 14, 16, - 0, 1, 0, 0, 0, 60, 0, 0, 7, 18, 0, 16, 0, 0, 0, - 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 26, 0, 16, 0, 0, - 0, 0, 0, 55, 0, 0, 12, 242, 0, 16, 0, 0, 0, 0, 0, - 6, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, - 0, 2, 64, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, - 128, 63, 0, 0, 128, 63, 29, 0, 0, 7, 18, 0, 16, 0, 1, - 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, - 0, 0, 0, 0, 13, 0, 4, 3, 10, 0, 16, 0, 1, 0, 0, - 0, 57, 0, 0, 8, 18, 0, 16, 0, 1, 0, 0, 0, 10, 128, - 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 64, 0, 0, 0, - 0, 0, 0, 16, 0, 0, 10, 34, 0, 16, 0, 1, 0, 0, 0, - 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 154, 153, 153, - 62, 154, 153, 25, 63, 205, 204, 204, 61, 0, 0, 0, 0, 0, 0, - 0, 9, 66, 0, 16, 0, 1, 0, 0, 0, 10, 128, 32, 128, 65, - 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 64, 0, 0, - 0, 0, 128, 63, 56, 0, 0, 8, 34, 0, 16, 0, 1, 0, 0, - 0, 26, 0, 16, 0, 1, 0, 0, 0, 10, 128, 32, 0, 0, 0, - 0, 0, 2, 0, 0, 0, 50, 0, 0, 9, 226, 0, 16, 0, 1, - 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 166, 10, 16, 0, - 1, 0, 0, 0, 86, 5, 16, 0, 1, 0, 0, 0, 55, 32, 0, - 9, 114, 0, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, - 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, - 0, 0, 0, 47, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, - 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, - 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, - 0, 0, 102, 102, 230, 63, 102, 102, 230, 63, 102, 102, 230, 63, 0, - 0, 0, 0, 25, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, - 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, - 0, 1, 0, 0, 0, 86, 5, 16, 0, 0, 0, 0, 0, 2, 64, - 0, 0, 150, 246, 160, 189, 43, 199, 117, 63, 40, 177, 243, 60, 0, - 0, 0, 0, 50, 0, 0, 12, 114, 0, 16, 0, 1, 0, 0, 0, - 6, 0, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 87, 203, 136, - 63, 86, 131, 197, 60, 225, 104, 227, 58, 0, 0, 0, 0, 70, 2, - 16, 0, 1, 0, 0, 0, 50, 32, 0, 12, 114, 32, 16, 0, 0, - 0, 0, 0, 166, 10, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, - 5, 9, 34, 60, 158, 151, 129, 60, 194, 240, 119, 63, 0, 0, 0, - 0, 70, 2, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 130, 32, - 16, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 62, - 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 32, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, - 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, + 0, 0, 0, 128, 63, 56, 0, 0, 8, 242, 0, 16, 0, 1, 0, + 0, 0, 70, 14, 16, 0, 1, 0, 0, 0, 70, 142, 32, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 9, 0, 208, 0, 0, + 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, + 0, 70, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, 0, 0, 0, 0, 26, 0, 16, 0, 0, + 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 34, 0, 0, 8, + 34, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, + 0, 42, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 33, 0, + 0, 8, 18, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, + 0, 0, 0, 58, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 55, 0, 0, 12, 242, 0, 16, 0, 1, 0, 0, 0, 86, 5, 16, + 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 14, 16, 0, 1, + 0, 0, 0, 60, 0, 0, 7, 18, 0, 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, 0, 0, 26, 0, 16, 0, 0, 0, 0, + 0, 55, 0, 0, 12, 242, 0, 16, 0, 0, 0, 0, 0, 6, 0, + 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, 0, 2, + 64, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 29, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, + 0, 1, 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, + 0, 0, 13, 0, 4, 3, 10, 0, 16, 0, 1, 0, 0, 0, 57, + 0, 0, 8, 18, 0, 16, 0, 1, 0, 0, 0, 10, 128, 32, 0, + 0, 0, 0, 0, 2, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, + 0, 16, 0, 0, 10, 34, 0, 16, 0, 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 154, 153, 153, 62, 154, + 153, 25, 63, 205, 204, 204, 61, 0, 0, 0, 0, 0, 0, 0, 9, + 66, 0, 16, 0, 1, 0, 0, 0, 10, 128, 32, 128, 65, 0, 0, + 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 64, 0, 0, 0, 0, + 128, 63, 56, 0, 0, 8, 34, 0, 16, 0, 1, 0, 0, 0, 26, + 0, 16, 0, 1, 0, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 50, 0, 0, 9, 226, 0, 16, 0, 1, 0, 0, + 0, 6, 9, 16, 0, 0, 0, 0, 0, 166, 10, 16, 0, 1, 0, + 0, 0, 86, 5, 16, 0, 1, 0, 0, 0, 55, 32, 0, 9, 114, + 0, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, + 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, + 0, 47, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, + 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, + 102, 102, 230, 63, 102, 102, 230, 63, 102, 102, 230, 63, 0, 0, 0, + 0, 25, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 1, + 0, 0, 0, 86, 5, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, + 150, 246, 160, 189, 43, 199, 117, 63, 40, 177, 243, 60, 0, 0, 0, + 0, 50, 0, 0, 12, 114, 0, 16, 0, 1, 0, 0, 0, 6, 0, + 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 87, 203, 136, 63, 86, + 131, 197, 60, 225, 104, 227, 58, 0, 0, 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 32, 0, 12, 114, 32, 16, 0, 0, 0, 0, + 0, 166, 10, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 5, 9, + 34, 60, 158, 151, 129, 60, 194, 240, 119, 63, 0, 0, 0, 0, 70, + 2, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, + 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 62, 0, 0, + 1, 83, 84, 65, 84, 116, 0, 0, 0, 31, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 14, 0, 0, 0, 4, + 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, - 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 3, + 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, }; namespace GpBinarizedShaders diff --git a/GpDisplayDriver_D3D11/CompiledShaders/DrawQuadRGBP_D3D11.cpp b/GpDisplayDriver_D3D11/CompiledShaders/DrawQuadRGBP_D3D11.cpp index 261990f..887a0bb 100644 --- a/GpDisplayDriver_D3D11/CompiledShaders/DrawQuadRGBP_D3D11.cpp +++ b/GpDisplayDriver_D3D11/CompiledShaders/DrawQuadRGBP_D3D11.cpp @@ -1,8 +1,8 @@ static unsigned char gs_shaderData[] = { - 68, 88, 66, 67, 55, 11, 130, 121, 223, 86, 90, 24, 177, 20, 124, - 204, 5, 205, 68, 19, 1, 0, 0, 0, 176, 7, 0, 0, 5, 0, + 68, 88, 66, 67, 70, 73, 170, 202, 197, 249, 120, 87, 61, 204, 7, + 189, 64, 34, 147, 57, 1, 0, 0, 0, 144, 7, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 124, 2, 0, 0, 212, 2, 0, 0, 8, - 3, 0, 0, 52, 7, 0, 0, 82, 68, 69, 70, 64, 2, 0, 0, + 3, 0, 0, 20, 7, 0, 0, 82, 68, 69, 70, 64, 2, 0, 0, 1, 0, 0, 0, 132, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0, 0, 4, 255, 255, 0, 137, 0, 0, 24, 2, 0, 0, 92, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 255, @@ -51,7 +51,7 @@ static unsigned char gs_shaderData[] = { 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, - 36, 4, 0, 0, 64, 0, 0, 0, 9, 1, 0, 0, 89, 0, 0, + 4, 4, 0, 0, 64, 0, 0, 0, 1, 1, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 3, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, @@ -62,75 +62,73 @@ static unsigned char gs_shaderData[] = { 194, 0, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 1, 0, 0, 0, 70, 14, 16, 0, 0, - 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 56, 0, 0, 9, - 242, 0, 16, 0, 2, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 1, 0, 0, 0, 1, - 64, 0, 0, 0, 0, 128, 63, 56, 0, 0, 7, 242, 0, 16, 0, - 1, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, 0, 70, 14, 16, - 0, 2, 0, 0, 0, 38, 0, 0, 9, 0, 208, 0, 0, 50, 0, - 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, - 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 30, 0, 0, 7, - 18, 0, 16, 0, 0, 0, 0, 0, 26, 0, 16, 0, 0, 0, 0, - 0, 10, 0, 16, 0, 0, 0, 0, 0, 34, 0, 0, 8, 34, 0, - 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 42, - 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 33, 0, 0, 8, - 18, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, - 0, 58, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 55, 0, - 0, 12, 242, 0, 16, 0, 1, 0, 0, 0, 86, 5, 16, 0, 0, - 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, - 0, 60, 0, 0, 7, 18, 0, 16, 0, 0, 0, 0, 0, 10, 0, - 16, 0, 0, 0, 0, 0, 26, 0, 16, 0, 0, 0, 0, 0, 55, - 0, 0, 12, 242, 0, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, - 0, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, 0, 2, 64, 0, - 0, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, - 128, 63, 29, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, - 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, - 13, 0, 4, 3, 10, 0, 16, 0, 1, 0, 0, 0, 57, 0, 0, - 8, 18, 0, 16, 0, 1, 0, 0, 0, 10, 128, 32, 0, 0, 0, - 0, 0, 2, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 16, - 0, 0, 10, 34, 0, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, - 0, 0, 0, 0, 2, 64, 0, 0, 154, 153, 153, 62, 154, 153, 25, - 63, 205, 204, 204, 61, 0, 0, 0, 0, 0, 0, 0, 9, 66, 0, - 16, 0, 1, 0, 0, 0, 10, 128, 32, 128, 65, 0, 0, 0, 0, - 0, 0, 0, 2, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, - 56, 0, 0, 8, 34, 0, 16, 0, 1, 0, 0, 0, 26, 0, 16, - 0, 1, 0, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 2, 0, - 0, 0, 50, 0, 0, 9, 226, 0, 16, 0, 1, 0, 0, 0, 6, - 9, 16, 0, 0, 0, 0, 0, 166, 10, 16, 0, 1, 0, 0, 0, - 86, 5, 16, 0, 1, 0, 0, 0, 55, 0, 0, 9, 114, 0, 16, - 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, 150, 7, - 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 29, - 0, 0, 10, 114, 0, 16, 0, 1, 0, 0, 0, 2, 64, 0, 0, - 230, 174, 37, 61, 230, 174, 37, 61, 230, 174, 37, 61, 0, 0, 0, - 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, - 16, 0, 2, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, - 64, 0, 0, 145, 131, 158, 61, 145, 131, 158, 61, 145, 131, 158, 61, - 0, 0, 0, 0, 0, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, - 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 174, 71, - 97, 61, 174, 71, 97, 61, 174, 71, 97, 61, 0, 0, 0, 0, 56, - 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, - 0, 0, 0, 0, 2, 64, 0, 0, 110, 167, 114, 63, 110, 167, 114, - 63, 110, 167, 114, 63, 0, 0, 0, 0, 47, 0, 0, 5, 114, 0, - 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, - 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, - 0, 0, 0, 0, 2, 64, 0, 0, 154, 153, 25, 64, 154, 153, 25, - 64, 154, 153, 25, 64, 0, 0, 0, 0, 25, 0, 0, 5, 114, 0, - 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 55, - 0, 0, 9, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, - 1, 0, 0, 0, 70, 2, 16, 0, 2, 0, 0, 0, 70, 2, 16, - 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, - 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, - 84, 65, 84, 116, 0, 0, 0, 32, 0, 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 2, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, - 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, + 63, 56, 0, 0, 8, 242, 0, 16, 0, 1, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 38, 0, 0, 9, 0, 208, 0, 0, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, 128, 32, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 30, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, 26, 0, 16, 0, 0, 0, 0, 0, 10, + 0, 16, 0, 0, 0, 0, 0, 34, 0, 0, 8, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 42, 128, 32, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 33, 0, 0, 8, 18, 0, + 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 58, + 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 55, 0, 0, 12, + 242, 0, 16, 0, 1, 0, 0, 0, 86, 5, 16, 0, 0, 0, 0, + 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, 0, 60, + 0, 0, 7, 18, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 26, 0, 16, 0, 0, 0, 0, 0, 55, 0, 0, + 12, 242, 0, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, 1, 0, 0, 0, 2, 64, 0, 0, 0, + 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, + 29, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, + 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 13, 0, + 4, 3, 10, 0, 16, 0, 1, 0, 0, 0, 57, 0, 0, 8, 18, + 0, 16, 0, 1, 0, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 16, 0, 0, + 10, 34, 0, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, 154, 153, 153, 62, 154, 153, 25, 63, 205, + 204, 204, 61, 0, 0, 0, 0, 0, 0, 0, 9, 66, 0, 16, 0, + 1, 0, 0, 0, 10, 128, 32, 128, 65, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, 56, 0, + 0, 8, 34, 0, 16, 0, 1, 0, 0, 0, 26, 0, 16, 0, 1, + 0, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 50, 0, 0, 9, 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, + 0, 0, 0, 0, 0, 166, 10, 16, 0, 1, 0, 0, 0, 86, 5, + 16, 0, 1, 0, 0, 0, 55, 0, 0, 9, 114, 0, 16, 0, 0, + 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, + 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 29, 0, 0, + 10, 114, 0, 16, 0, 1, 0, 0, 0, 2, 64, 0, 0, 230, 174, + 37, 61, 230, 174, 37, 61, 230, 174, 37, 61, 0, 0, 0, 0, 70, + 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, + 0, 145, 131, 158, 61, 145, 131, 158, 61, 145, 131, 158, 61, 0, 0, + 0, 0, 0, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, + 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 174, 71, 97, 61, + 174, 71, 97, 61, 174, 71, 97, 61, 0, 0, 0, 0, 56, 0, 0, + 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, 110, 167, 114, 63, 110, 167, 114, 63, 110, + 167, 114, 63, 0, 0, 0, 0, 47, 0, 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, + 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, 154, 153, 25, 64, 154, 153, 25, 64, 154, + 153, 25, 64, 0, 0, 0, 0, 25, 0, 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 55, 0, 0, + 9, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, 2, 0, 0, 0, 70, 2, 16, 0, 0, + 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, + 84, 116, 0, 0, 0, 31, 0, 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, 15, 0, 0, 0, 4, 0, 0, 0, 1, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, - 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, }; namespace GpBinarizedShaders diff --git a/GpDisplayDriver_D3D11/CompiledShaders/DrawQuadRGBP_ICC_D3D11.cpp b/GpDisplayDriver_D3D11/CompiledShaders/DrawQuadRGBP_ICC_D3D11.cpp index eba0649..7c4c9b8 100644 --- a/GpDisplayDriver_D3D11/CompiledShaders/DrawQuadRGBP_ICC_D3D11.cpp +++ b/GpDisplayDriver_D3D11/CompiledShaders/DrawQuadRGBP_ICC_D3D11.cpp @@ -1,8 +1,8 @@ static unsigned char gs_shaderData[] = { - 68, 88, 66, 67, 59, 168, 168, 88, 76, 243, 83, 77, 18, 124, 254, - 1, 241, 101, 79, 130, 1, 0, 0, 0, 116, 7, 0, 0, 5, 0, + 68, 88, 66, 67, 108, 52, 221, 105, 109, 174, 81, 46, 155, 29, 71, + 86, 93, 178, 121, 166, 1, 0, 0, 0, 84, 7, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 124, 2, 0, 0, 212, 2, 0, 0, 8, - 3, 0, 0, 248, 6, 0, 0, 82, 68, 69, 70, 64, 2, 0, 0, + 3, 0, 0, 216, 6, 0, 0, 82, 68, 69, 70, 64, 2, 0, 0, 1, 0, 0, 0, 132, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0, 0, 4, 255, 255, 0, 137, 0, 0, 24, 2, 0, 0, 92, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 255, @@ -51,82 +51,80 @@ static unsigned char gs_shaderData[] = { 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, - 232, 3, 0, 0, 64, 0, 0, 0, 250, 0, 0, 0, 89, 0, 0, + 200, 3, 0, 0, 64, 0, 0, 0, 242, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 3, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, - 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 3, 0, 0, + 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 2, 0, 0, 0, 65, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 27, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 8, 194, 0, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 1, 0, 0, 0, 70, 14, 16, 0, 0, - 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 56, 0, 0, 9, - 242, 0, 16, 0, 2, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 1, 0, 0, 0, 1, - 64, 0, 0, 0, 0, 128, 63, 56, 0, 0, 7, 242, 0, 16, 0, - 1, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, 0, 70, 14, 16, - 0, 2, 0, 0, 0, 38, 0, 0, 9, 0, 208, 0, 0, 50, 0, - 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, - 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 30, 0, 0, 7, - 18, 0, 16, 0, 0, 0, 0, 0, 26, 0, 16, 0, 0, 0, 0, - 0, 10, 0, 16, 0, 0, 0, 0, 0, 34, 0, 0, 8, 34, 0, - 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 42, - 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 33, 0, 0, 8, - 18, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, - 0, 58, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 55, 0, - 0, 12, 242, 0, 16, 0, 1, 0, 0, 0, 86, 5, 16, 0, 0, - 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, - 0, 60, 0, 0, 7, 18, 0, 16, 0, 0, 0, 0, 0, 10, 0, - 16, 0, 0, 0, 0, 0, 26, 0, 16, 0, 0, 0, 0, 0, 55, - 0, 0, 12, 242, 0, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, - 0, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, 0, 2, 64, 0, - 0, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, - 128, 63, 29, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, - 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, - 13, 0, 4, 3, 10, 0, 16, 0, 1, 0, 0, 0, 57, 0, 0, - 8, 18, 0, 16, 0, 1, 0, 0, 0, 10, 128, 32, 0, 0, 0, - 0, 0, 2, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 16, - 0, 0, 10, 34, 0, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, - 0, 0, 0, 0, 2, 64, 0, 0, 154, 153, 153, 62, 154, 153, 25, - 63, 205, 204, 204, 61, 0, 0, 0, 0, 0, 0, 0, 9, 66, 0, - 16, 0, 1, 0, 0, 0, 10, 128, 32, 128, 65, 0, 0, 0, 0, - 0, 0, 0, 2, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, - 56, 0, 0, 8, 34, 0, 16, 0, 1, 0, 0, 0, 26, 0, 16, - 0, 1, 0, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 2, 0, - 0, 0, 50, 0, 0, 9, 226, 0, 16, 0, 1, 0, 0, 0, 6, - 9, 16, 0, 0, 0, 0, 0, 166, 10, 16, 0, 1, 0, 0, 0, - 86, 5, 16, 0, 1, 0, 0, 0, 55, 32, 0, 9, 114, 0, 16, - 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, 150, 7, - 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 47, - 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, - 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, - 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 102, 102, - 230, 63, 102, 102, 230, 63, 102, 102, 230, 63, 0, 0, 0, 0, 25, - 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, - 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 1, 0, 0, - 0, 86, 5, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 150, 246, - 160, 189, 43, 199, 117, 63, 40, 177, 243, 60, 0, 0, 0, 0, 50, - 0, 0, 12, 114, 0, 16, 0, 1, 0, 0, 0, 6, 0, 16, 0, - 0, 0, 0, 0, 2, 64, 0, 0, 87, 203, 136, 63, 86, 131, 197, - 60, 225, 104, 227, 58, 0, 0, 0, 0, 70, 2, 16, 0, 1, 0, - 0, 0, 50, 32, 0, 12, 114, 32, 16, 0, 0, 0, 0, 0, 166, - 10, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 5, 9, 34, 60, - 158, 151, 129, 60, 194, 240, 119, 63, 0, 0, 0, 0, 70, 2, 16, - 0, 1, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, - 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, - 84, 65, 84, 116, 0, 0, 0, 30, 0, 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0, 4, 0, 0, - 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, + 63, 56, 0, 0, 8, 242, 0, 16, 0, 1, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 38, 0, 0, 9, 0, 208, 0, 0, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, 128, 32, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 30, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, 26, 0, 16, 0, 0, 0, 0, 0, 10, + 0, 16, 0, 0, 0, 0, 0, 34, 0, 0, 8, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 42, 128, 32, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 33, 0, 0, 8, 18, 0, + 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 58, + 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 55, 0, 0, 12, + 242, 0, 16, 0, 1, 0, 0, 0, 86, 5, 16, 0, 0, 0, 0, + 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, 0, 60, + 0, 0, 7, 18, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 26, 0, 16, 0, 0, 0, 0, 0, 55, 0, 0, + 12, 242, 0, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, 1, 0, 0, 0, 2, 64, 0, 0, 0, + 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, + 29, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, + 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 13, 0, + 4, 3, 10, 0, 16, 0, 1, 0, 0, 0, 57, 0, 0, 8, 18, + 0, 16, 0, 1, 0, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 16, 0, 0, + 10, 34, 0, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, 154, 153, 153, 62, 154, 153, 25, 63, 205, + 204, 204, 61, 0, 0, 0, 0, 0, 0, 0, 9, 66, 0, 16, 0, + 1, 0, 0, 0, 10, 128, 32, 128, 65, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, 56, 0, + 0, 8, 34, 0, 16, 0, 1, 0, 0, 0, 26, 0, 16, 0, 1, + 0, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 50, 0, 0, 9, 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, + 0, 0, 0, 0, 0, 166, 10, 16, 0, 1, 0, 0, 0, 86, 5, + 16, 0, 1, 0, 0, 0, 55, 32, 0, 9, 114, 0, 16, 0, 0, + 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, + 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 47, 0, 0, + 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, + 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 102, 102, 230, 63, + 102, 102, 230, 63, 102, 102, 230, 63, 0, 0, 0, 0, 25, 0, 0, + 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 1, 0, 0, 0, 86, + 5, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 150, 246, 160, 189, + 43, 199, 117, 63, 40, 177, 243, 60, 0, 0, 0, 0, 50, 0, 0, + 12, 114, 0, 16, 0, 1, 0, 0, 0, 6, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, 87, 203, 136, 63, 86, 131, 197, 60, 225, + 104, 227, 58, 0, 0, 0, 0, 70, 2, 16, 0, 1, 0, 0, 0, + 50, 32, 0, 12, 114, 32, 16, 0, 0, 0, 0, 0, 166, 10, 16, + 0, 0, 0, 0, 0, 2, 64, 0, 0, 5, 9, 34, 60, 158, 151, + 129, 60, 194, 240, 119, 63, 0, 0, 0, 0, 70, 2, 16, 0, 1, + 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, + 84, 116, 0, 0, 0, 29, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, 14, 0, 0, 0, 4, 0, 0, 0, 1, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, - 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, }; namespace GpBinarizedShaders diff --git a/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp b/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp index 0990779..d182a29 100644 --- a/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp +++ b/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp @@ -1,8 +1,10 @@ #include "GpApplicationName.h" #include "GpDisplayDriverD3D11.h" +#include "GpDisplayDriverProperties.h" #include "GpDisplayDriverSurfaceD3D11.h" #include "GpVOSEvent.h" #include "GpWindows.h" +#include "IGpAllocator.h" #include "IGpCursor_Win32.h" #include "IGpVOSEventQueue.h" @@ -1243,8 +1245,9 @@ void GpDisplayDriverD3D11::ServeTicks(int tickCount) void GpDisplayDriverD3D11::Shutdown() { + IGpAllocator *alloc = m_properties.m_alloc; this->~GpDisplayDriverD3D11(); - free(this); + alloc->Release(this); } void GpDisplayDriverD3D11::GetInitialDisplayResolution(unsigned int *width, unsigned int *height) @@ -1257,7 +1260,7 @@ void GpDisplayDriverD3D11::GetInitialDisplayResolution(unsigned int *width, unsi IGpDisplayDriverSurface *GpDisplayDriverD3D11::CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat, IGpDisplayDriver::SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext) { - return GpDisplayDriverSurfaceD3D11::Create(m_device, m_deviceContext, width, height, pixelFormat); + return GpDisplayDriverSurfaceD3D11::Create(m_device, m_deviceContext, width, height, pixelFormat, m_properties.m_alloc); } void GpDisplayDriverD3D11::DrawSurface(IGpDisplayDriverSurface *surface, int32_t x, int32_t y, size_t width, size_t height, const GpDisplayDriverSurfaceEffects *effects) @@ -1385,12 +1388,12 @@ void GpDisplayDriverD3D11::DrawSurface(IGpDisplayDriverSurface *surface, int32_t IGpCursor *GpDisplayDriverD3D11::CreateColorCursor(size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY) { - return m_osGlobals->m_createColorCursorFunc(width, height, pixelDataRGBA, hotSpotX, hotSpotY); + return m_osGlobals->m_createColorCursorFunc(m_properties.m_alloc, width, height, pixelDataRGBA, hotSpotX, hotSpotY); } IGpCursor *GpDisplayDriverD3D11::CreateBWCursor(size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY) { - return m_osGlobals->m_createBWCursorFunc(width, height, pixelData, maskData, hotSpotX, hotSpotY); + return m_osGlobals->m_createBWCursorFunc(m_properties.m_alloc, width, height, pixelData, maskData, hotSpotX, hotSpotY); } // We can't just set the cursor because we want to post WM_SETCURSOR to keep it limited @@ -1507,7 +1510,7 @@ bool GpDisplayDriverD3D11::SavePrefs(void *context, IGpPrefsHandler::WritePrefsF GpDisplayDriverD3D11 *GpDisplayDriverD3D11::Create(const GpDisplayDriverProperties &properties) { - void *storage = malloc(sizeof(GpDisplayDriverD3D11)); + void *storage = properties.m_alloc->Alloc(sizeof(GpDisplayDriverD3D11)); if (!storage) return nullptr; diff --git a/GpDisplayDriver_D3D11/GpDisplayDriverSurfaceD3D11.cpp b/GpDisplayDriver_D3D11/GpDisplayDriverSurfaceD3D11.cpp index 9f2f3d2..cd17fbd 100644 --- a/GpDisplayDriver_D3D11/GpDisplayDriverSurfaceD3D11.cpp +++ b/GpDisplayDriver_D3D11/GpDisplayDriverSurfaceD3D11.cpp @@ -1,5 +1,6 @@ #include "GpDisplayDriverSurfaceD3D11.h" #include "GpComPtr.h" +#include "IGpAllocator.h" #include #include @@ -55,8 +56,9 @@ void GpDisplayDriverSurfaceD3D11::UploadEntire(const void *data, size_t pitch) void GpDisplayDriverSurfaceD3D11::Destroy() { + IGpAllocator *alloc = m_alloc; this->~GpDisplayDriverSurfaceD3D11(); - free(this); + alloc->Release(this); } ID3D11ShaderResourceView *GpDisplayDriverSurfaceD3D11::GetSRV() const @@ -79,7 +81,7 @@ size_t GpDisplayDriverSurfaceD3D11::GetHeight() const return m_height; } -GpDisplayDriverSurfaceD3D11 *GpDisplayDriverSurfaceD3D11::Create(ID3D11Device *device, ID3D11DeviceContext *deviceContext, size_t width, size_t height, GpPixelFormat_t pixelFormat) +GpDisplayDriverSurfaceD3D11 *GpDisplayDriverSurfaceD3D11::Create(ID3D11Device *device, ID3D11DeviceContext *deviceContext, size_t width, size_t height, GpPixelFormat_t pixelFormat, IGpAllocator *alloc) { DXGI_FORMAT dxgiFormat = DXGI_FORMAT_R8_UNORM; @@ -127,17 +129,17 @@ GpDisplayDriverSurfaceD3D11 *GpDisplayDriverSurfaceD3D11::Create(ID3D11Device *d if (device->CreateShaderResourceView(texture, &srvDesc, srv.GetMutablePtr()) != S_OK) return nullptr; - void *storage = malloc(sizeof(GpDisplayDriverSurfaceD3D11)); + void *storage = alloc->Alloc(sizeof(GpDisplayDriverSurfaceD3D11)); if (!storage) { texture->Release(); return nullptr; } - return new (storage) GpDisplayDriverSurfaceD3D11(device, deviceContext, texture, srv, width, height, pixelFormat); + return new (storage) GpDisplayDriverSurfaceD3D11(device, deviceContext, texture, srv, width, height, pixelFormat, alloc); } -GpDisplayDriverSurfaceD3D11::GpDisplayDriverSurfaceD3D11(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Texture2D *texture, ID3D11ShaderResourceView *srv, size_t width, size_t height, GpPixelFormat_t pixelFormat) +GpDisplayDriverSurfaceD3D11::GpDisplayDriverSurfaceD3D11(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Texture2D *texture, ID3D11ShaderResourceView *srv, size_t width, size_t height, GpPixelFormat_t pixelFormat, IGpAllocator *alloc) : m_width(width) , m_height(height) , m_pixelFormat(pixelFormat) @@ -145,6 +147,7 @@ GpDisplayDriverSurfaceD3D11::GpDisplayDriverSurfaceD3D11(ID3D11Device *device, I , m_deviceContext(deviceContext) , m_texture(texture) , m_srv(srv) + , m_alloc(alloc) { } diff --git a/GpDisplayDriver_D3D11/GpDisplayDriverSurfaceD3D11.h b/GpDisplayDriver_D3D11/GpDisplayDriverSurfaceD3D11.h index a7d7a9c..afbb050 100644 --- a/GpDisplayDriver_D3D11/GpDisplayDriverSurfaceD3D11.h +++ b/GpDisplayDriver_D3D11/GpDisplayDriverSurfaceD3D11.h @@ -8,6 +8,7 @@ struct ID3D11Device; struct ID3D11DeviceContext; struct ID3D11ShaderResourceView; struct ID3D11Texture2D; +struct IGpAllocator; class GpDisplayDriverSurfaceD3D11 final : public IGpDisplayDriverSurface { @@ -21,10 +22,10 @@ public: size_t GetWidth() const; size_t GetHeight() const; - static GpDisplayDriverSurfaceD3D11 *Create(ID3D11Device *device, ID3D11DeviceContext *deviceContext, size_t width, size_t height, GpPixelFormat_t pixelFormat); + static GpDisplayDriverSurfaceD3D11 *Create(ID3D11Device *device, ID3D11DeviceContext *deviceContext, size_t width, size_t height, GpPixelFormat_t pixelFormat, IGpAllocator *alloc); private: - GpDisplayDriverSurfaceD3D11(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Texture2D *texture, ID3D11ShaderResourceView *srv, size_t width, size_t height, GpPixelFormat_t pixelFormat); + GpDisplayDriverSurfaceD3D11(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Texture2D *texture, ID3D11ShaderResourceView *srv, size_t width, size_t height, GpPixelFormat_t pixelFormat, IGpAllocator *alloc); ~GpDisplayDriverSurfaceD3D11(); size_t m_width; @@ -32,6 +33,7 @@ private: GpPixelFormat_t m_pixelFormat; ID3D11Device *m_device; ID3D11DeviceContext *m_deviceContext; + IGpAllocator *m_alloc; GpComPtr m_texture; GpComPtr m_srv; diff --git a/GpFontHandler_FreeType2/GpFontHandler_FreeType2.cpp b/GpFontHandler_FreeType2/GpFontHandler_FreeType2.cpp index 1ee56aa..270861a 100644 --- a/GpFontHandler_FreeType2/GpFontHandler_FreeType2.cpp +++ b/GpFontHandler_FreeType2/GpFontHandler_FreeType2.cpp @@ -3,6 +3,7 @@ #include "CoreDefs.h" #include "GpIOStream.h" +#include "IGpAllocator.h" #include "IGpFont.h" #include "IGpFontRenderedGlyph.h" #include "GpRenderedGlyphMetrics.h" @@ -17,6 +18,8 @@ #include #include +struct IGpAllocator; + class GpFontRenderedGlyph_FreeType2 final : public IGpFontRenderedGlyph { public: @@ -24,14 +27,15 @@ public: const void *GetData() const override; void Destroy() override; - static GpFontRenderedGlyph_FreeType2 *Create(size_t dataSize, const GpRenderedGlyphMetrics &metrics); + static GpFontRenderedGlyph_FreeType2 *Create(IGpAllocator *alloc, size_t dataSize, const GpRenderedGlyphMetrics &metrics); void *GetMutableData(); private: - GpFontRenderedGlyph_FreeType2(void *data, const GpRenderedGlyphMetrics &metrics); + GpFontRenderedGlyph_FreeType2(IGpAllocator *alloc, void *data, const GpRenderedGlyphMetrics &metrics); ~GpFontRenderedGlyph_FreeType2(); + IGpAllocator *m_alloc; void *m_data; GpRenderedGlyphMetrics m_metrics; }; @@ -40,20 +44,22 @@ class GpFont_FreeType2 final : public IGpFont { public: void Destroy() override; - IGpFontRenderedGlyph *Render(uint32_t unicodeCodePoint, unsigned int size, bool aa) override; + IGpFontRenderedGlyph *Render(uint32_t unicodeCodePoint, unsigned int size, unsigned int xScale, unsigned int yScale, bool aa) override; bool GetLineSpacing(unsigned int size, int32_t &outSpacing) override; + bool SupportScaling() const override; - static GpFont_FreeType2 *Create(const FT_StreamRec_ &streamRec, GpIOStream *stream); + static GpFont_FreeType2 *Create(IGpAllocator *alloc, const FT_StreamRec_ &streamRec, GpIOStream *stream); - bool FTLoad(const FT_Library &library); + bool FTLoad(const FT_Library &library, int typeFaceIndex); private: - explicit GpFont_FreeType2(const FT_StreamRec_ &streamRec, GpIOStream *stream); + GpFont_FreeType2(IGpAllocator *alloc, const FT_StreamRec_ &streamRec, GpIOStream *stream); ~GpFont_FreeType2(); FT_StreamRec_ m_ftStream; FT_Face m_face; GpIOStream *m_stream; + IGpAllocator *m_alloc; unsigned int m_currentSize; }; @@ -69,20 +75,21 @@ const void *GpFontRenderedGlyph_FreeType2::GetData() const void GpFontRenderedGlyph_FreeType2::Destroy() { + IGpAllocator *alloc = m_alloc; this->~GpFontRenderedGlyph_FreeType2(); - free(this); + alloc->Release(this); } -GpFontRenderedGlyph_FreeType2 *GpFontRenderedGlyph_FreeType2::Create(size_t dataSize, const GpRenderedGlyphMetrics &metrics) +GpFontRenderedGlyph_FreeType2 *GpFontRenderedGlyph_FreeType2::Create(IGpAllocator *alloc, size_t dataSize, const GpRenderedGlyphMetrics &metrics) { size_t alignedPrefixSize = (sizeof(GpFontRenderedGlyph_FreeType2) + GP_SYSTEM_MEMORY_ALIGNMENT - 1); alignedPrefixSize -= alignedPrefixSize % GP_SYSTEM_MEMORY_ALIGNMENT; - void *storage = malloc(alignedPrefixSize + dataSize); + void *storage = alloc->Alloc(alignedPrefixSize + dataSize); if (!storage) return nullptr; - return new (storage) GpFontRenderedGlyph_FreeType2(static_cast(storage) + alignedPrefixSize, metrics); + return new (storage) GpFontRenderedGlyph_FreeType2(alloc, static_cast(storage) + alignedPrefixSize, metrics); } void *GpFontRenderedGlyph_FreeType2::GetMutableData() @@ -91,9 +98,10 @@ void *GpFontRenderedGlyph_FreeType2::GetMutableData() } -GpFontRenderedGlyph_FreeType2::GpFontRenderedGlyph_FreeType2(void *data, const GpRenderedGlyphMetrics &metrics) +GpFontRenderedGlyph_FreeType2::GpFontRenderedGlyph_FreeType2(IGpAllocator *alloc, void *data, const GpRenderedGlyphMetrics &metrics) : m_metrics(metrics) , m_data(data) + , m_alloc(alloc) { } @@ -103,11 +111,12 @@ GpFontRenderedGlyph_FreeType2::~GpFontRenderedGlyph_FreeType2() void GpFont_FreeType2::Destroy() { + IGpAllocator *alloc = m_alloc; this->~GpFont_FreeType2(); - free(this); + alloc->Release(this); } -IGpFontRenderedGlyph *GpFont_FreeType2::Render(uint32_t unicodeCodePoint, unsigned int size, bool aa) +IGpFontRenderedGlyph *GpFont_FreeType2::Render(uint32_t unicodeCodePoint, unsigned int size, unsigned int xScale, unsigned int yScale, bool aa) { if (m_currentSize != size) { @@ -117,6 +126,14 @@ IGpFontRenderedGlyph *GpFont_FreeType2::Render(uint32_t unicodeCodePoint, unsign m_currentSize = size; } + FT_Matrix transform; + transform.xx = xScale << 16; + transform.xy = 0; + transform.yx = 0; + transform.yy = yScale << 16; + + FT_Set_Transform(m_face, &transform, nullptr); + FT_UInt glyphIndex = FT_Get_Char_Index(m_face, unicodeCodePoint); if (!glyphIndex) return nullptr; @@ -163,6 +180,8 @@ IGpFontRenderedGlyph *GpFont_FreeType2::Render(uint32_t unicodeCodePoint, unsign metrics.m_glyphWidth = glyph->bitmap.width; metrics.m_glyphHeight = glyph->bitmap.rows; metrics.m_advanceX = glyph->metrics.horiAdvance / 64; + metrics.m_bitmapOffsetX = glyph->bitmap_left; + metrics.m_bitmapOffsetY = glyph->bitmap_top; const size_t numRowsRequired = glyph->bitmap.rows; size_t pitchRequired = 0; @@ -179,7 +198,7 @@ IGpFontRenderedGlyph *GpFont_FreeType2::Render(uint32_t unicodeCodePoint, unsign metrics.m_glyphDataPitch = pitchRequired; - GpFontRenderedGlyph_FreeType2 *renderedGlyph = GpFontRenderedGlyph_FreeType2::Create(glyphDataSize, metrics); + GpFontRenderedGlyph_FreeType2 *renderedGlyph = GpFontRenderedGlyph_FreeType2::Create(m_alloc, glyphDataSize, metrics); if (!renderedGlyph) return nullptr; @@ -247,35 +266,42 @@ bool GpFont_FreeType2::GetLineSpacing(unsigned int size, int32_t &outSpacing) return true; } - -GpFont_FreeType2 *GpFont_FreeType2::Create(const FT_StreamRec_ &streamRec, GpIOStream *stream) +bool GpFont_FreeType2::SupportScaling() const { - void *storage = malloc(sizeof(GpFont_FreeType2)); + return true; +} + +GpFont_FreeType2 *GpFont_FreeType2::Create(IGpAllocator *alloc, const FT_StreamRec_ &streamRec, GpIOStream *stream) +{ + void *storage = alloc->Alloc(sizeof(GpFont_FreeType2)); if (!storage) return nullptr; - return new (storage) GpFont_FreeType2(streamRec, stream); + return new (storage) GpFont_FreeType2(alloc, streamRec, stream); } -bool GpFont_FreeType2::FTLoad(const FT_Library &library) +bool GpFont_FreeType2::FTLoad(const FT_Library &library, int typeFaceIndex) { FT_Open_Args openArgs; memset(&openArgs, 0, sizeof(openArgs)); openArgs.flags = FT_OPEN_STREAM; openArgs.stream = &m_ftStream; - FT_Error errorCode = FT_Open_Face(library, &openArgs, 0, &m_face); + FT_Error errorCode = FT_Open_Face(library, &openArgs, typeFaceIndex, &m_face); if (errorCode != 0) return false; + FT_Matrix transform; + return true; } -GpFont_FreeType2::GpFont_FreeType2(const FT_StreamRec_ &streamRec, GpIOStream *stream) +GpFont_FreeType2::GpFont_FreeType2(IGpAllocator *alloc, const FT_StreamRec_ &streamRec, GpIOStream *stream) : m_face(nullptr) , m_ftStream(streamRec) , m_stream(stream) , m_currentSize(0) + , m_alloc(alloc) { assert(stream); } @@ -288,13 +314,13 @@ GpFont_FreeType2::~GpFont_FreeType2() m_stream->Close(); } -GpFontHandler_FreeType2 *GpFontHandler_FreeType2::Create() +GpFontHandler_FreeType2 *GpFontHandler_FreeType2::Create(IGpAllocator *alloc) { - void *storage = malloc(sizeof(GpFontHandler_FreeType2)); + void *storage = alloc->Alloc(sizeof(GpFontHandler_FreeType2)); if (!storage) return nullptr; - GpFontHandler_FreeType2 *fh = new (storage) GpFontHandler_FreeType2(); + GpFontHandler_FreeType2 *fh = new (storage) GpFontHandler_FreeType2(alloc); if (!fh->Init()) { fh->Shutdown(); @@ -304,7 +330,7 @@ GpFontHandler_FreeType2 *GpFontHandler_FreeType2::Create() return fh; } -IGpFont *GpFontHandler_FreeType2::LoadFont(GpIOStream *stream) +IGpFont *GpFontHandler_FreeType2::LoadFont(GpIOStream *stream, int typeFaceIndex) { FT_StreamRec_ ftStream; memset(&ftStream, 0, sizeof(ftStream)); @@ -314,14 +340,14 @@ IGpFont *GpFontHandler_FreeType2::LoadFont(GpIOStream *stream) ftStream.read = FTStreamIo; ftStream.close = FTStreamClose; - GpFont_FreeType2 *font = GpFont_FreeType2::Create(ftStream, stream); + GpFont_FreeType2 *font = GpFont_FreeType2::Create(m_alloc, ftStream, stream); if (!font) { stream->Close(); return nullptr; } - if (!font->FTLoad(m_library)) + if (!font->FTLoad(m_library, typeFaceIndex)) { font->Destroy(); return nullptr; @@ -337,14 +363,16 @@ bool GpFontHandler_FreeType2::KeepStreamOpen() const void GpFontHandler_FreeType2::Shutdown() { + IGpAllocator *alloc = m_alloc; this->~GpFontHandler_FreeType2(); - free(this); + alloc->Release(this); } -GpFontHandler_FreeType2::GpFontHandler_FreeType2() +GpFontHandler_FreeType2::GpFontHandler_FreeType2(IGpAllocator *alloc) : m_ftIsInitialized(false) , m_library(nullptr) , m_currentSize(0) + , m_alloc(alloc) { } @@ -394,18 +422,18 @@ void GpFontHandler_FreeType2::FTStreamClose(FT_Stream stream) void *GpFontHandler_FreeType2::FTAlloc(long size) { - return malloc(static_cast(size)); + return m_alloc->Alloc(static_cast(size)); } void GpFontHandler_FreeType2::FTFree(void* block) { - free(block); + m_alloc->Release(block); } void *GpFontHandler_FreeType2::FTRealloc(long curSize, long newSize, void *block) { (void)curSize; - return realloc(block, static_cast(newSize)); + return m_alloc->Realloc(block, static_cast(newSize)); } bool GpFontHandler_FreeType2::Init() @@ -431,5 +459,5 @@ __declspec(dllexport) #endif IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties) { - return GpFontHandler_FreeType2::Create(); + return GpFontHandler_FreeType2::Create(properties.m_alloc); } diff --git a/GpFontHandler_FreeType2/GpFontHandler_FreeType2.h b/GpFontHandler_FreeType2/GpFontHandler_FreeType2.h index 3d5c033..d190082 100644 --- a/GpFontHandler_FreeType2/GpFontHandler_FreeType2.h +++ b/GpFontHandler_FreeType2/GpFontHandler_FreeType2.h @@ -7,6 +7,7 @@ #include FT_FREETYPE_H class GpIOStream; +struct IGpAllocator; namespace PortabilityLayer { @@ -16,15 +17,15 @@ namespace PortabilityLayer class GpFontHandler_FreeType2 final : public IGpFontHandler { public: - IGpFont *LoadFont(GpIOStream *stream) override; + IGpFont *LoadFont(GpIOStream *stream, int typeFaceIndex) override; void Shutdown() override; bool KeepStreamOpen() const override; - static GpFontHandler_FreeType2 *Create(); + static GpFontHandler_FreeType2 *Create(IGpAllocator *alloc); private: - GpFontHandler_FreeType2(); + explicit GpFontHandler_FreeType2(IGpAllocator *alloc); ~GpFontHandler_FreeType2(); static void *FTAllocThunk(FT_Memory memory, long size); @@ -44,4 +45,5 @@ private: FT_Library m_library; unsigned int m_currentSize; bool m_ftIsInitialized; + IGpAllocator *m_alloc; }; diff --git a/GpInputDriver_XInput/GpInputDriverXInput.cpp b/GpInputDriver_XInput/GpInputDriverXInput.cpp index b3ccf41..4fefd05 100644 --- a/GpInputDriver_XInput/GpInputDriverXInput.cpp +++ b/GpInputDriver_XInput/GpInputDriverXInput.cpp @@ -2,6 +2,7 @@ #include "GpVOSEvent.h" #include "GpWindows.h" #include "IGpVOSEventQueue.h" +#include "IGpAllocator.h" #include #include @@ -72,8 +73,9 @@ void GpInputDriverXInput::ProcessInput() void GpInputDriverXInput::Shutdown() { + IGpAllocator *alloc = m_properties.m_alloc; this->~GpInputDriverXInput(); - free(this); + alloc->Release(this); } IGpPrefsHandler *GpInputDriverXInput::GetPrefsHandler() const @@ -83,7 +85,7 @@ IGpPrefsHandler *GpInputDriverXInput::GetPrefsHandler() const GpInputDriverXInput *GpInputDriverXInput::Create(const GpInputDriverProperties &props) { - void *storage = malloc(sizeof(GpInputDriverXInput)); + void *storage = props.m_alloc->Alloc(sizeof(GpInputDriverXInput)); if (!storage) return nullptr; diff --git a/GpShell/Android.mk b/GpShell/Android.mk index d45af9c..ea38797 100644 --- a/GpShell/Android.mk +++ b/GpShell/Android.mk @@ -13,13 +13,6 @@ LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0 # Add your application source files here... LOCAL_SRC_FILES := \ - GpAppEnvironment.cpp \ - GpAudioDriverFactory.cpp \ - GpDisplayDriverFactory.cpp \ - GpFontHandlerFactory.cpp \ - GpGlobalConfig.cpp \ - GpInputDriverFactory.cpp \ - GpMain.cpp \ - GpVOSEventQueue.cpp + GpShell_Combined.cpp include $(BUILD_STATIC_LIBRARY) diff --git a/GpShell/GpGlobalConfig.h b/GpShell/GpGlobalConfig.h index d37849d..09d5ae6 100644 --- a/GpShell/GpGlobalConfig.h +++ b/GpShell/GpGlobalConfig.h @@ -10,6 +10,7 @@ struct IGpLogDriver; struct IGpSystemServices; +struct IGpAllocator; struct GpGlobalConfig { @@ -22,6 +23,7 @@ struct GpGlobalConfig IGpLogDriver *m_logger; IGpSystemServices *m_systemServices; + IGpAllocator *m_allocator; void *m_osGlobals; }; diff --git a/GpShell/GpMain.cpp b/GpShell/GpMain.cpp index b30f3b3..9488181 100644 --- a/GpShell/GpMain.cpp +++ b/GpShell/GpMain.cpp @@ -11,6 +11,7 @@ #include "GpInputDriverProperties.h" #include "GpGlobalConfig.h" #include "GpAppEnvironment.h" +#include "IGpAllocator.h" #include "IGpAudioDriver.h" #include "IGpDisplayDriver.h" #include "IGpFontHandler.h" @@ -36,6 +37,7 @@ int GpMain::Run() { GpVOSEventQueue *eventQueue = new GpVOSEventQueue(); GpAppEnvironment *appEnvironment = new GpAppEnvironment(); + IGpAllocator *alloc = g_gpGlobalConfig.m_allocator; GpDisplayDriverProperties ddProps; memset(&ddProps, 0, sizeof(ddProps)); @@ -60,6 +62,7 @@ int GpMain::Run() ddProps.m_eventQueue = eventQueue; ddProps.m_logger = g_gpGlobalConfig.m_logger; ddProps.m_systemServices = g_gpGlobalConfig.m_systemServices; + ddProps.m_alloc = g_gpGlobalConfig.m_allocator; GpAudioDriverProperties adProps; memset(&adProps, 0, sizeof(adProps)); @@ -68,6 +71,7 @@ int GpMain::Run() memset(&fontProps, 0, sizeof(fontProps)); fontProps.m_type = g_gpGlobalConfig.m_fontHandlerType; + fontProps.m_alloc = g_gpGlobalConfig.m_allocator; // The sample rate used in all of Glider PRO's sound is 0x56ee8ba3 // This appears to be the "standard" Mac sample rate, probably rounded from 244800/11. @@ -80,8 +84,9 @@ int GpMain::Run() #endif adProps.m_logger = g_gpGlobalConfig.m_logger; adProps.m_systemServices = g_gpGlobalConfig.m_systemServices; + adProps.m_alloc = g_gpGlobalConfig.m_allocator; - IGpInputDriver **inputDrivers = static_cast(malloc(sizeof(IGpInputDriver*) * g_gpGlobalConfig.m_numInputDrivers)); + IGpInputDriver **inputDrivers = static_cast(alloc->Alloc(sizeof(IGpInputDriver*) * g_gpGlobalConfig.m_numInputDrivers)); size_t numCreatedInputDrivers = 0; if (inputDrivers) @@ -93,6 +98,7 @@ int GpMain::Run() inputProps.m_type = g_gpGlobalConfig.m_inputDriverTypes[i]; inputProps.m_eventQueue = eventQueue; + inputProps.m_alloc = g_gpGlobalConfig.m_allocator; if (IGpInputDriver *driver = GpInputDriverFactory::CreateInputDriver(inputProps)) inputDrivers[numCreatedInputDrivers++] = driver; @@ -123,7 +129,7 @@ int GpMain::Run() for (size_t i = 0; i < numCreatedInputDrivers; i++) inputDrivers[i]->Shutdown(); - free(inputDrivers); + alloc->Release(inputDrivers); } return 0; diff --git a/HouseTool/HouseTool.cpp b/HouseTool/HouseTool.cpp new file mode 100644 index 0000000..4278ad4 --- /dev/null +++ b/HouseTool/HouseTool.cpp @@ -0,0 +1,1813 @@ +#include +#include "PLCore.h" +#include "PLBigEndian.h" +#include "MacRomanConversion.h" +#include "GpUnicode.h" +#include "WindowsUnicodeToolShim.h" + +#include + +typedef uint8_t Boolean; + +#define kMaxScores 10 +#define kMaxRoomObs 24 +#define kNumTiles 8 + +// Object types + +#define kFloorVent 0x01 // Blowers +#define kCeilingVent 0x02 +#define kFloorBlower 0x03 +#define kCeilingBlower 0x04 +#define kSewerGrate 0x05 +#define kLeftFan 0x06 +#define kRightFan 0x07 +#define kTaper 0x08 +#define kCandle 0x09 +#define kStubby 0x0A +#define kTiki 0x0B +#define kBBQ 0x0C +#define kInvisBlower 0x0D +#define kGrecoVent 0x0E +#define kSewerBlower 0x0F +#define kLiftArea 0x10 + +#define kTable 0x11 // Furniture +#define kShelf 0x12 +#define kCabinet 0x13 +#define kFilingCabinet 0x14 +#define kWasteBasket 0x15 +#define kMilkCrate 0x16 +#define kCounter 0x17 +#define kDresser 0x18 +#define kDeckTable 0x19 +#define kStool 0x1A +#define kTrunk 0x1B +#define kInvisObstacle 0x1C +#define kManhole 0x1D +#define kBooks 0x1E +#define kInvisBounce 0x1F + +#define kRedClock 0x21 // Prizes +#define kBlueClock 0x22 +#define kYellowClock 0x23 +#define kCuckoo 0x24 +#define kPaper 0x25 +#define kBattery 0x26 +#define kBands 0x27 +#define kGreaseRt 0x28 +#define kGreaseLf 0x29 +#define kFoil 0x2A +#define kInvisBonus 0x2B +#define kStar 0x2C +#define kSparkle 0x2D +#define kHelium 0x2E +#define kSlider 0x2F + +#define kUpStairs 0x31 // Transport +#define kDownStairs 0x32 +#define kMailboxLf 0x33 +#define kMailboxRt 0x34 +#define kFloorTrans 0x35 +#define kCeilingTrans 0x36 +#define kDoorInLf 0x37 +#define kDoorInRt 0x38 +#define kDoorExRt 0x39 +#define kDoorExLf 0x3A +#define kWindowInLf 0x3B +#define kWindowInRt 0x3C +#define kWindowExRt 0x3D +#define kWindowExLf 0x3E +#define kInvisTrans 0x3F +#define kDeluxeTrans 0x40 + +#define kLightSwitch 0x41 // Switches +#define kMachineSwitch 0x42 +#define kThermostat 0x43 +#define kPowerSwitch 0x44 +#define kKnifeSwitch 0x45 +#define kInvisSwitch 0x46 +#define kTrigger 0x47 +#define kLgTrigger 0x48 +#define kSoundTrigger 0x49 + +#define kCeilingLight 0x51 // Lights +#define kLightBulb 0x52 +#define kTableLamp 0x53 +#define kHipLamp 0x54 +#define kDecoLamp 0x55 +#define kFlourescent 0x56 +#define kTrackLight 0x57 +#define kInvisLight 0x58 + +#define kShredder 0x61 // Appliances +#define kToaster 0x62 +#define kMacPlus 0x63 +#define kGuitar 0x64 +#define kTV 0x65 +#define kCoffee 0x66 +#define kOutlet 0x67 +#define kVCR 0x68 +#define kStereo 0x69 +#define kMicrowave 0x6A +#define kCinderBlock 0x6B +#define kFlowerBox 0x6C +#define kCDs 0x6D +#define kCustomPict 0x6E + +#define kBalloon 0x71 // Enemies +#define kCopterLf 0x72 +#define kCopterRt 0x73 +#define kDartLf 0x74 +#define kDartRt 0x75 +#define kBall 0x76 +#define kDrip 0x77 +#define kFish 0x78 +#define kCobweb 0x79 + +#define kOzma 0x81 // Clutter +#define kMirror 0x82 +#define kMousehole 0x83 +#define kFireplace 0x84 +#define kFlower 0x85 +#define kWallWindow 0x86 +#define kBear 0x87 +#define kCalendar 0x88 +#define kVase1 0x89 +#define kVase2 0x8A +#define kBulletin 0x8B +#define kCloud 0x8C +#define kFaucet 0x8D +#define kRug 0x8E +#define kChimes 0x8F + + +struct EnumDef +{ + int m_value; + const char *m_name; +}; + +struct Bool8 +{ + uint8_t m_value; +}; + +template +struct StaticArray +{ + static const int kSize = TSize; + + T m_data[TSize]; +}; + + +template +struct PascalStr +{ + static const int kSize = TSize; + + uint8_t m_length; + uint8_t m_chars[TSize]; +}; + +typedef PascalStr<15> PStr15_t; +typedef PascalStr<27> PStr27_t; +typedef PascalStr<31> PStr31_t; +typedef PascalStr<255> PStr255_t; + + + +typedef struct +{ + BEPoint topLeft; // 4 + BEInt16_t distance; // 2 + Bool8 initial; // 1 + Bool8 state; // 1 F. lf. dn. rt. up + uint8_t vector; // 1 | x | x | x | x | 8 | 4 | 2 | 1 | + uint8_t tall; // 1 +} blowerType; // total = 10 + +typedef struct +{ + BERect bounds; // 8 + BEInt16_t pict; // 2 +} furnitureType; // total = 10 + +typedef struct +{ + BEPoint topLeft; // 4 + BEInt16_t length; // 2 grease spill + BEInt16_t points; // 2 invis bonus + Bool8 state; // 1 + Bool8 initial; // 1 +} bonusType; // total = 10 + +typedef struct +{ + BEPoint topLeft; // 4 + BEInt16_t tall; // 2 invis transport + BEInt16_t where; // 2 + uint8_t who; // 1 + uint8_t wide; // 1 +} transportType; // total = 10 + +typedef struct +{ + BEPoint topLeft; // 4 + BEInt16_t delay; // 2 + BEInt16_t where; // 2 + uint8_t who; // 1 + uint8_t type; // 1 +} switchType; // total = 10 + +typedef struct +{ + BEPoint topLeft; // 4 + BEInt16_t length; // 2 + uint8_t byte0; // 1 + uint8_t byte1; // 1 + Bool8 initial; // 1 + Bool8 state; // 1 +} lightType; // total = 10 + +typedef struct +{ + BEPoint topLeft; // 4 + BEInt16_t height; // 2 toaster, pict ID + uint8_t byte0; // 1 + uint8_t delay; // 1 + Bool8 initial; // 1 + Bool8 state; // 1 +} applianceType; // total = 10 + +typedef struct +{ + BEPoint topLeft; // 4 + BEInt16_t length; // 2 + uint8_t delay; // 1 + uint8_t byte0; // 1 + Bool8 initial; // 1 + Bool8 state; // 1 +} enemyType; // total = 10 + +typedef struct +{ + BERect bounds; // 8 + BEInt16_t pict; // 2 +} clutterType; // total = 10 + +struct objectType +{ + union u + { + blowerType a; + furnitureType b; + bonusType c; + transportType d; + switchType e; + lightType f; + applianceType g; + enemyType h; + clutterType i; + StaticArray pad; + + u(); + u(const u &other); + ~u(); + }; + + BEInt16_t what; // 2 + u data; // 10 +}; // total = 12 + +objectType::u::u() +{ + static_assert(sizeof(*this) == 10, "Wrong size"); +} + +objectType::u::~u() +{ +} + +objectType::u::u(const u &other) +{ + memcpy(this, &other, sizeof(*this)); +} + +typedef objectType *objectPtr; + +typedef struct +{ + PStr31_t banner; // 32 = 32 + StaticArray names; // 16 * 10 = 160 + StaticArray scores; // 4 * 10 = 40 + StaticArray timeStamps; // 4 * 10 = 40 + StaticArray levels; // 2 * 10 = 20 +} scoresType; // total = 292 + +typedef struct +{ + BEInt16_t version; // 2 + BEInt16_t wasStarsLeft; // 2 + BEUInt32_t timeStamp; // 4 + BEPoint where; // 4 + BEInt32_t score; // 4 + BEInt32_t unusedLong; // 4 + BEInt32_t unusedLong2; // 4 + BEInt16_t energy; // 2 + BEInt16_t bands; // 2 + BEInt16_t roomNumber; // 2 + BEInt16_t gliderState; // 2 + BEInt16_t numGliders; // 2 + BEInt16_t foil; // 2 + BEInt16_t unusedShort; // 2 + Bool8 facing; // 1 + Bool8 showFoil; // 1 +} gameType; // total = 40 + +typedef struct +{ + BEInt16_t unusedShort; // 2 + uint8_t unusedByte; // 1 + Bool8 visited; // 1 + objectType objects[kMaxRoomObs]; // 24 * 12 +} savedRoom, *saveRoomPtr; // total = 292 + +typedef struct +{ + PStr27_t name; // 28 + BEInt16_t bounds; // 2 + uint8_t leftStart; // 1 + uint8_t rightStart; // 1 + uint8_t unusedByte; // 1 + Bool8 visited; // 1 + BEInt16_t background; // 2 + StaticArray tiles; // 2 * 8 + BEInt16_t floor, suite; // 2 + 2 + BEInt16_t openings; // 2 + BEInt16_t numObjects; // 2 + StaticArray objects; // 24 * 12 +} roomType, *roomPtr; // total = 348 + +struct houseType +{ + BEInt16_t version; // 2 + BEInt16_t unusedShort; // 2 + BEInt32_t timeStamp; // 4 + BEInt32_t flags; // 4 (bit 0 = wardBit) + BEPoint initial; // 4 + PStr255_t banner; // 256 + PStr255_t trailer; // 256 + scoresType highScores; // 292 + gameType savedGame_Unused; // 40 + Bool8 hasGame; // 1 + Bool8 unusedBoolean; // 1 + BEInt16_t firstRoom; // 2 + BEInt16_t nRooms; // 2 + + static const size_t kBinaryDataSize = 866; +}; + +static const size_t houseSize = sizeof(houseType); + +#define ENUM_VALUE_DEF(k) { k, #k } + +EnumDef g_objectTypeEnum[] = +{ + { -1, "kObjectIsEmpty" }, + ENUM_VALUE_DEF(kFloorVent), + ENUM_VALUE_DEF(kCeilingVent), + ENUM_VALUE_DEF(kFloorBlower), + ENUM_VALUE_DEF(kCeilingBlower), + ENUM_VALUE_DEF(kSewerGrate), + ENUM_VALUE_DEF(kLeftFan), + ENUM_VALUE_DEF(kRightFan), + ENUM_VALUE_DEF(kTaper), + ENUM_VALUE_DEF(kCandle), + ENUM_VALUE_DEF(kStubby), + ENUM_VALUE_DEF(kTiki), + ENUM_VALUE_DEF(kBBQ), + ENUM_VALUE_DEF(kInvisBlower), + ENUM_VALUE_DEF(kGrecoVent), + ENUM_VALUE_DEF(kSewerBlower), + ENUM_VALUE_DEF(kLiftArea), + ENUM_VALUE_DEF(kTable), + ENUM_VALUE_DEF(kShelf), + ENUM_VALUE_DEF(kCabinet), + ENUM_VALUE_DEF(kFilingCabinet), + ENUM_VALUE_DEF(kWasteBasket), + ENUM_VALUE_DEF(kMilkCrate), + ENUM_VALUE_DEF(kCounter), + ENUM_VALUE_DEF(kDresser), + ENUM_VALUE_DEF(kDeckTable), + ENUM_VALUE_DEF(kStool), + ENUM_VALUE_DEF(kTrunk), + ENUM_VALUE_DEF(kInvisObstacle), + ENUM_VALUE_DEF(kManhole), + ENUM_VALUE_DEF(kBooks), + ENUM_VALUE_DEF(kInvisBounce), + ENUM_VALUE_DEF(kRedClock), + ENUM_VALUE_DEF(kBlueClock), + ENUM_VALUE_DEF(kYellowClock), + ENUM_VALUE_DEF(kCuckoo), + ENUM_VALUE_DEF(kPaper), + ENUM_VALUE_DEF(kBattery), + ENUM_VALUE_DEF(kBands), + ENUM_VALUE_DEF(kGreaseRt), + ENUM_VALUE_DEF(kGreaseLf), + ENUM_VALUE_DEF(kFoil), + ENUM_VALUE_DEF(kInvisBonus), + ENUM_VALUE_DEF(kStar), + ENUM_VALUE_DEF(kSparkle), + ENUM_VALUE_DEF(kHelium), + ENUM_VALUE_DEF(kSlider), + ENUM_VALUE_DEF(kUpStairs), + ENUM_VALUE_DEF(kDownStairs), + ENUM_VALUE_DEF(kMailboxLf), + ENUM_VALUE_DEF(kMailboxRt), + ENUM_VALUE_DEF(kFloorTrans), + ENUM_VALUE_DEF(kCeilingTrans), + ENUM_VALUE_DEF(kDoorInLf), + ENUM_VALUE_DEF(kDoorInRt), + ENUM_VALUE_DEF(kDoorExRt), + ENUM_VALUE_DEF(kDoorExLf), + ENUM_VALUE_DEF(kWindowInLf), + ENUM_VALUE_DEF(kWindowInRt), + ENUM_VALUE_DEF(kWindowExRt), + ENUM_VALUE_DEF(kWindowExLf), + ENUM_VALUE_DEF(kInvisTrans), + ENUM_VALUE_DEF(kDeluxeTrans), + ENUM_VALUE_DEF(kLightSwitch), + ENUM_VALUE_DEF(kMachineSwitch), + ENUM_VALUE_DEF(kThermostat), + ENUM_VALUE_DEF(kPowerSwitch), + ENUM_VALUE_DEF(kKnifeSwitch), + ENUM_VALUE_DEF(kInvisSwitch), + ENUM_VALUE_DEF(kTrigger), + ENUM_VALUE_DEF(kLgTrigger), + ENUM_VALUE_DEF(kSoundTrigger), + ENUM_VALUE_DEF(kCeilingLight), + ENUM_VALUE_DEF(kLightBulb), + ENUM_VALUE_DEF(kTableLamp), + ENUM_VALUE_DEF(kHipLamp), + ENUM_VALUE_DEF(kDecoLamp), + ENUM_VALUE_DEF(kFlourescent), + ENUM_VALUE_DEF(kTrackLight), + ENUM_VALUE_DEF(kInvisLight), + ENUM_VALUE_DEF(kShredder), + ENUM_VALUE_DEF(kToaster), + ENUM_VALUE_DEF(kMacPlus), + ENUM_VALUE_DEF(kGuitar), + ENUM_VALUE_DEF(kTV), + ENUM_VALUE_DEF(kCoffee), + ENUM_VALUE_DEF(kOutlet), + ENUM_VALUE_DEF(kVCR), + ENUM_VALUE_DEF(kStereo), + ENUM_VALUE_DEF(kMicrowave), + ENUM_VALUE_DEF(kCinderBlock), + ENUM_VALUE_DEF(kFlowerBox), + ENUM_VALUE_DEF(kCDs), + ENUM_VALUE_DEF(kCustomPict), + ENUM_VALUE_DEF(kBalloon), + ENUM_VALUE_DEF(kCopterLf), + ENUM_VALUE_DEF(kCopterRt), + ENUM_VALUE_DEF(kDartLf), + ENUM_VALUE_DEF(kDartRt), + ENUM_VALUE_DEF(kBall), + ENUM_VALUE_DEF(kDrip), + ENUM_VALUE_DEF(kFish), + ENUM_VALUE_DEF(kCobweb), + ENUM_VALUE_DEF(kOzma), + ENUM_VALUE_DEF(kMirror), + ENUM_VALUE_DEF(kMousehole), + ENUM_VALUE_DEF(kFireplace), + ENUM_VALUE_DEF(kFlower), + ENUM_VALUE_DEF(kWallWindow), + ENUM_VALUE_DEF(kBear), + ENUM_VALUE_DEF(kCalendar), + ENUM_VALUE_DEF(kVase1), + ENUM_VALUE_DEF(kVase2), + ENUM_VALUE_DEF(kBulletin), + ENUM_VALUE_DEF(kCloud), + ENUM_VALUE_DEF(kFaucet), + ENUM_VALUE_DEF(kRug), + ENUM_VALUE_DEF(kChimes), +}; + +const size_t g_objectTypeEnumSize = sizeof(g_objectTypeEnum) / sizeof(g_objectTypeEnum[0]); + + +struct IDataVisitor +{ + virtual IDataVisitor *EnterIndex(int index) = 0; + virtual IDataVisitor *EnterNamed(const char *name) = 0; + virtual void Exit() = 0; + + virtual void VisitLPStr(uint8_t &length, uint8_t *chars, int capacity) = 0; + virtual void VisitInt32(int32_t &v) = 0; + virtual void VisitUInt32(uint32_t &v) = 0; + virtual void VisitInt16(int16_t &v) = 0; + virtual void VisitBool8(uint8_t &v) = 0; + virtual void VisitByte(uint8_t &v) = 0; + virtual bool VisitEnum(const EnumDef *enumDefs, size_t numDefs, int &v) = 0; + + virtual bool VisitStaticCapacity(size_t size) = 0; + virtual void VisitDynamicCapacity(size_t &size) = 0; +}; + +bool VisitEnum(const EnumDef *enumDefs, size_t numDefs, IDataVisitor *visitor); + +void Visit(roomType &v, IDataVisitor *visitor); +void Visit(objectType &v, IDataVisitor *visitor); +void Visit(blowerType &v, IDataVisitor *visitor); +void Visit(furnitureType &v, IDataVisitor *visitor); +void Visit(bonusType &v, IDataVisitor *visitor); +void Visit(transportType &v, IDataVisitor *visitor); +void Visit(switchType &v, IDataVisitor *visitor); +void Visit(lightType &v, IDataVisitor *visitor); +void Visit(applianceType &v, IDataVisitor *visitor); +void Visit(enemyType &v, IDataVisitor *visitor); +void Visit(clutterType &v, IDataVisitor *visitor); +void Visit(scoresType &v, IDataVisitor *visitor); +void Visit(gameType &v, IDataVisitor *visitor); +void Visit(Bool8 &v, IDataVisitor *visitor); +void Visit(uint8_t &v, IDataVisitor *visitor); +void Visit(BEInt16_t &v, IDataVisitor *visitor); +void Visit(BEInt32_t &v, IDataVisitor *visitor); +void Visit(BEUInt32_t &v, IDataVisitor *visitor); +void Visit(BEPoint &v, IDataVisitor *visitor); +void Visit(BERect &v, IDataVisitor *visitor); + +template +void Visit(PascalStr &pstr, IDataVisitor *visitor) +{ + visitor->VisitLPStr(pstr.m_length, pstr.m_chars, TSize); +} + +template +void Visit(StaticArray &arr, IDataVisitor *visitor) +{ + if (!visitor->VisitStaticCapacity(TSize)) + return; + + for (int i = 0; i < TSize; i++) + { + IDataVisitor *subscriptVisitor = visitor->EnterIndex(i); + if (subscriptVisitor) + { + Visit(arr.m_data[i], visitor); + subscriptVisitor->Exit(); + } + } +} + +template +void VisitField(const char *subscriptName, T &subscript, IDataVisitor *visitor) +{ + IDataVisitor *subscriptVisitor = visitor->EnterNamed(subscriptName); + if (subscriptVisitor) + { + Visit(subscript, visitor); + subscriptVisitor->Exit(); + } +} + +template +void VisitArray(T *arr, int size, IDataVisitor *visitor) +{ + if (!visitor->VisitStaticCapacity(static_cast(size))) + return; + + for (int i = 0; i < size; i++) + { + IDataVisitor *subscriptVisitor = visitor->EnterIndex(i); + if (subscriptVisitor) + { + Visit(arr[i], visitor); + subscriptVisitor->Exit(); + } + } +} + + +bool VisitEnum(const EnumDef *enumDefs, size_t numDefs, int &v, IDataVisitor *visitor) +{ + return visitor->VisitEnum(enumDefs, numDefs, v); +} + +void Visit(houseType &house, std::vector &rooms, IDataVisitor *visitor) +{ + VisitField("version", house.version, visitor); + VisitField("unusedShort", house.unusedShort, visitor); + VisitField("timeStamp", house.timeStamp, visitor); + VisitField("flags", house.flags, visitor); + VisitField("initial", house.initial, visitor); + VisitField("banner", house.banner, visitor); + VisitField("trailer", house.trailer, visitor); + VisitField("highScores", house.highScores, visitor); + VisitField("savedGame", house.savedGame_Unused, visitor); + VisitField("hasGame", house.hasGame, visitor); + VisitField("unusedBoolean", house.unusedBoolean, visitor); + VisitField("firstRoom", house.firstRoom, visitor); + VisitField("nRooms", house.nRooms, visitor); + + IDataVisitor *roomsSubscript = visitor->EnterNamed("rooms"); + if (roomsSubscript) + { + size_t size = rooms.size(); + roomsSubscript->VisitDynamicCapacity(size); + + if (size > 0x7fff) + size = 0x7fff; + + if (size < rooms.size()) + rooms.resize(size); + else if (size > rooms.size()) + { + roomType emptyRoom; + memset(&emptyRoom, 0, sizeof(emptyRoom)); + + rooms.reserve(size); + while (size > rooms.size()) + rooms.push_back(emptyRoom); + } + + house.nRooms = static_cast(size); + + for (size_t i = 0; i < size; i++) + { + IDataVisitor *roomSubscript = roomsSubscript->EnterIndex(static_cast(i)); + if (roomSubscript) + { + Visit(rooms[i], roomSubscript); + roomSubscript->Exit(); + } + } + + roomsSubscript->Exit(); + } +} + +void Visit(blowerType &v, IDataVisitor *visitor) +{ + VisitField("topLeft", v.topLeft, visitor); + VisitField("distance", v.distance, visitor); + VisitField("initial", v.initial, visitor); + VisitField("state", v.state, visitor); + VisitField("vector", v.vector, visitor); + VisitField("tall", v.tall, visitor); +} + +void Visit(furnitureType &v, IDataVisitor *visitor) +{ + VisitField("bounds", v.bounds, visitor); + VisitField("pict", v.pict, visitor); +} + +void Visit(bonusType &v, IDataVisitor *visitor) +{ + VisitField("topLeft", v.topLeft, visitor); + VisitField("length", v.length, visitor); + VisitField("points", v.points, visitor); + VisitField("state", v.state, visitor); + VisitField("initial", v.initial, visitor); +} + +void Visit(transportType &v, IDataVisitor *visitor) +{ + VisitField("topLeft", v.topLeft, visitor); + VisitField("tall", v.tall, visitor); + VisitField("where", v.where, visitor); + VisitField("who", v.who, visitor); + VisitField("wide", v.wide, visitor); +} + +void Visit(switchType &v, IDataVisitor *visitor) +{ + VisitField("topLeft", v.topLeft, visitor); + VisitField("delay", v.delay, visitor); + VisitField("where", v.where, visitor); + VisitField("who", v.who, visitor); + VisitField("type", v.type, visitor); +} + +void Visit(lightType &v, IDataVisitor *visitor) +{ + VisitField("topLeft", v.topLeft, visitor); + VisitField("length", v.length, visitor); + VisitField("byte0", v.byte0, visitor); + VisitField("byte1", v.byte1, visitor); + VisitField("initial", v.initial, visitor); + VisitField("state", v.state, visitor); +} + +void Visit(applianceType &v, IDataVisitor *visitor) +{ + VisitField("topLeft", v.topLeft, visitor); + VisitField("height", v.height, visitor); + VisitField("byte0", v.byte0, visitor); + VisitField("delay", v.delay, visitor); + VisitField("initial", v.initial, visitor); + VisitField("state", v.state, visitor); +} + +void Visit(enemyType &v, IDataVisitor *visitor) +{ + VisitField("topLeft", v.topLeft, visitor); + VisitField("length", v.length, visitor); + VisitField("delay", v.delay, visitor); + VisitField("byte0", v.byte0, visitor); + VisitField("initial", v.initial, visitor); + VisitField("state", v.state, visitor); +} + +void Visit(clutterType &v, IDataVisitor *visitor) +{ + VisitField("bounds", v.bounds, visitor); + VisitField("pict", v.pict, visitor); +} + +void Visit(objectType &v, IDataVisitor *visitor) +{ + IDataVisitor *whatVisitor = visitor->EnterNamed("what"); + if (whatVisitor) + { + int ev = v.what; + if (!VisitEnum(g_objectTypeEnum, g_objectTypeEnumSize, ev, visitor)) + Visit(v.what, visitor); + whatVisitor->Exit(); + } + + switch (static_cast(v.what)) + { + default: + //VisitField("pad", v.data.pad, visitor); + break; + + case kFloorVent: + case kCeilingVent: + case kFloorBlower: + case kCeilingBlower: + case kSewerGrate: + case kLeftFan: + case kRightFan: + case kTaper: + case kCandle: + case kStubby: + case kTiki: + case kBBQ: + case kInvisBlower: + case kGrecoVent: + case kSewerBlower: + case kLiftArea: + Visit(v.data.a, visitor); + break; + + case kTable: + case kShelf: + case kCabinet: + case kFilingCabinet: + case kWasteBasket: + case kMilkCrate: + case kCounter: + case kDresser: + case kDeckTable: + case kStool: + case kTrunk: + case kInvisObstacle: + case kManhole: + case kBooks: + case kInvisBounce: + Visit(v.data.b, visitor); + break; + + case kRedClock: + case kBlueClock: + case kYellowClock: + case kCuckoo: + case kPaper: + case kBattery: + case kBands: + case kGreaseRt: + case kGreaseLf: + case kFoil: + case kInvisBonus: + case kStar: + case kSparkle: + case kHelium: + case kSlider: + Visit(v.data.c, visitor); + break; + + case kUpStairs: + case kDownStairs: + case kMailboxLf: + case kMailboxRt: + case kFloorTrans: + case kCeilingTrans: + case kDoorInLf: + case kDoorInRt: + case kDoorExRt: + case kDoorExLf: + case kWindowInLf: + case kWindowInRt: + case kWindowExRt: + case kWindowExLf: + case kInvisTrans: + case kDeluxeTrans: + Visit(v.data.d, visitor); + break; + + case kLightSwitch: + case kMachineSwitch: + case kThermostat: + case kPowerSwitch: + case kKnifeSwitch: + case kInvisSwitch: + case kTrigger: + case kLgTrigger: + case kSoundTrigger: + Visit(v.data.e, visitor); + break; + + case kCeilingLight: + case kLightBulb: + case kTableLamp: + case kHipLamp: + case kDecoLamp: + case kFlourescent: + case kTrackLight: + case kInvisLight: + Visit(v.data.f, visitor); + break; + + case kShredder: + case kToaster: + case kMacPlus: + case kGuitar: + case kTV: + case kCoffee: + case kOutlet: + case kVCR: + case kStereo: + case kMicrowave: + case kCinderBlock: + case kFlowerBox: + case kCDs: + case kCustomPict: + Visit(v.data.g, visitor); + break; + + case kBalloon: + case kCopterLf: + case kCopterRt: + case kDartLf: + case kDartRt: + case kBall: + case kDrip: + case kFish: + case kCobweb: + Visit(v.data.h, visitor); + break; + + case kOzma: + case kMirror: + case kMousehole: + case kFireplace: + case kFlower: + case kWallWindow: + case kBear: + case kCalendar: + case kVase1: + case kVase2: + case kBulletin: + case kCloud: + case kFaucet: + case kRug: + case kChimes: + Visit(v.data.i, visitor); + break; + } +} + +void Visit(roomType &v, IDataVisitor *visitor) +{ + VisitField("name", v.name, visitor); + VisitField("bounds", v.bounds, visitor); + VisitField("leftStart", v.leftStart, visitor); + VisitField("rightStart", v.rightStart, visitor); + VisitField("unusedByte", v.unusedByte, visitor); + VisitField("visited", v.visited, visitor); + VisitField("background", v.background, visitor); + VisitField("tiles", v.tiles, visitor); + VisitField("floor", v.floor, visitor); + VisitField("suite", v.suite, visitor); + VisitField("openings", v.openings, visitor); + VisitField("numObjects", v.numObjects, visitor); + VisitField("objects", v.objects, visitor); +} + +void Visit(scoresType &v, IDataVisitor *visitor) +{ + VisitField("banner", v.banner, visitor); + VisitField("names", v.names, visitor); + VisitField("scores", v.scores, visitor); + VisitField("timeStamps", v.timeStamps, visitor); + VisitField("levels", v.levels, visitor); +} + +void Visit(gameType &v, IDataVisitor *visitor) +{ + VisitField("version", v.version, visitor); + VisitField("starsLeft", v.wasStarsLeft, visitor); + VisitField("timeStamp", v.timeStamp, visitor); + VisitField("where", v.where, visitor); + VisitField("score", v.score, visitor); + VisitField("unusedLong", v.unusedLong, visitor); + VisitField("unusedLong2", v.unusedLong2, visitor); + VisitField("energy", v.energy, visitor); + VisitField("bands", v.bands, visitor); + VisitField("roomNumber", v.roomNumber, visitor); + VisitField("gliderState", v.gliderState, visitor); + VisitField("numGliders", v.numGliders, visitor); + VisitField("foil", v.foil, visitor); + VisitField("unusedShort", v.unusedShort, visitor); + VisitField("facing", v.facing, visitor); + VisitField("showFoil", v.showFoil, visitor); +} + +void Visit(Bool8 &v, IDataVisitor *visitor) +{ + visitor->VisitBool8(v.m_value); +} + +void Visit(uint8_t &v, IDataVisitor *visitor) +{ + visitor->VisitByte(v); +} + +void Visit(BEInt16_t &v, IDataVisitor *visitor) +{ + int16_t vi = v; + visitor->VisitInt16(vi); + v = vi; +} + +void Visit(BEInt32_t &v, IDataVisitor *visitor) +{ + int32_t vi = v; + visitor->VisitInt32(vi); + v = vi; +} + +void Visit(BEUInt32_t &v, IDataVisitor *visitor) +{ + uint32_t vi = v; + visitor->VisitUInt32(vi); + v = vi; +} + +void Visit(BEPoint &v, IDataVisitor *visitor) +{ + VisitField("h", v.h, visitor); + VisitField("v", v.v, visitor); +} + +void Visit(BERect &v, IDataVisitor *visitor) +{ + VisitField("top", v.top, visitor); + VisitField("left", v.left, visitor); + VisitField("bottom", v.bottom, visitor); + VisitField("right", v.right, visitor); +} + +int PrintUsage() +{ + fprintf(stderr, "Usage:\n"); + fprintf(stderr, "HouseTool decompile \n"); + fprintf(stderr, "HouseTool patch \n"); + return -1; +} + +bool ReadHouseFromPath(const char *path, houseType &house, std::vector &rooms) +{ + FILE *f = fopen_utf8(path, "rb"); + if (!f) + return false; + + if (fread(&house, 1, houseType::kBinaryDataSize, f) != houseType::kBinaryDataSize) + { + fclose(f); + return false; + } + + int16_t nRooms = house.nRooms; + if (nRooms < 0) + { + fclose(f); + return false; + } + + rooms.resize(nRooms); + + if (nRooms > 0) + { + if (fread(&rooms[0], 1, sizeof(roomType) * nRooms, f) != sizeof(roomType) * nRooms) + { + rooms.clear(); + fclose(f); + return false; + } + } + + fclose(f); + return true; +} + + +class PatchVisitor final : public IDataVisitor +{ +public: + PatchVisitor(const char *scope, const char *replacementValue); + + IDataVisitor *EnterIndex(int index) override; + IDataVisitor *EnterNamed(const char *name) override; + void Exit() override; + + void VisitLPStr(uint8_t &length, uint8_t *chars, int capacity) override; + void VisitInt32(int32_t &v) override; + void VisitUInt32(uint32_t &v) override; + void VisitInt16(int16_t &v) override; + void VisitBool8(uint8_t &v) override; + void VisitByte(uint8_t &v) override; + bool VisitEnum(const EnumDef *enumDefs, size_t numDefs, int &v) override; + + bool VisitStaticCapacity(size_t size) override; + void VisitDynamicCapacity(size_t &size) override; + + bool PatchedOK() const; + +private: + static bool DecodeInteger(const std::string &scopeStr, size_t startPos, int &outInteger, size_t &outEndPos); + static bool DecodeQuotedString(const std::string &scopeStr, size_t startPos, std::string &outStr, size_t &outEndPos); + + std::string m_scope; + std::string m_nextScope; + int m_scopeInteger; + bool m_nextScopeIsInteger; + const char *m_replacementValue; + + void EnterScope(); + bool TryEnterScope(); + + bool m_isDone; + bool m_haveScope; + bool m_patchedOK; +}; + +PatchVisitor::PatchVisitor(const char *scope, const char *replacementValue) + : m_scopeInteger(0) + , m_nextScopeIsInteger(false) + , m_replacementValue(replacementValue) + , m_nextScope(scope) + , m_isDone(false) + , m_haveScope(true) + , m_patchedOK(false) +{ + EnterScope(); +} + +IDataVisitor *PatchVisitor::EnterIndex(int index) +{ + if (m_isDone || !m_haveScope || !m_nextScopeIsInteger) + return nullptr; + + if (m_scopeInteger == index) + { + EnterScope(); + return this; + } + + return nullptr; +} + +IDataVisitor *PatchVisitor::EnterNamed(const char *name) +{ + if (m_isDone || !m_haveScope || m_nextScopeIsInteger) + return nullptr; + + if (m_scope == name) + { + EnterScope(); + return this; + } + + return nullptr; +} + +void PatchVisitor::Exit() +{ + m_isDone = true; +} + +void PatchVisitor::VisitLPStr(uint8_t &length, uint8_t *chars, int capacity) +{ + if (m_isDone || m_haveScope) + return; + + const uint8_t *replacementUTF8 = reinterpret_cast(m_replacementValue); + size_t rLen = strlen(m_replacementValue); + + length = 0; + while (rLen > 0) + { + uint32_t codePoint = 0; + size_t charsDigested = 0; + if (!GpUnicode::UTF8::Decode(replacementUTF8, rLen, charsDigested, codePoint)) + break; + + rLen -= charsDigested; + replacementUTF8 += charsDigested; + + uint8_t macRomanChar = 0; + if (codePoint > 0xffff) + macRomanChar = '?'; + else + { + if (!MacRoman::FromUnicode(macRomanChar, static_cast(codePoint))) + macRomanChar = '?'; + } + + chars[length++] = macRomanChar; + if (length == capacity) + break; + } + + for (int i = length; i < capacity; i++) + chars[i] = 0; + + m_patchedOK = true; + m_isDone = true; +} + +void PatchVisitor::VisitInt32(int32_t &v) +{ + if (m_isDone || m_haveScope) + return; + + int integer = 0; + if (sscanf(m_replacementValue, "%i", &integer) == 1) + { + m_patchedOK = true; + m_isDone = true; + v = integer; + } +} + +void PatchVisitor::VisitUInt32(uint32_t &v) +{ + if (m_isDone || m_haveScope) + return; + + unsigned int integer = 0; + if (sscanf(m_replacementValue, "%u", &integer) == 1) + { + m_patchedOK = true; + m_isDone = true; + v = integer; + } +} + +void PatchVisitor::VisitInt16(int16_t &v) +{ + if (m_isDone || m_haveScope) + return; + + int integer = 0; + if (sscanf(m_replacementValue, "%i", &integer) == 1) + { + m_patchedOK = true; + m_isDone = true; + v = integer; + } +} + +void PatchVisitor::VisitBool8(uint8_t &v) +{ + if (m_isDone || m_haveScope) + return; + + if (!strcmp(m_replacementValue, "true")) + { + m_patchedOK = true; + m_isDone = true; + v = 1; + } + else if (!strcmp(m_replacementValue, "false")) + { + m_patchedOK = true; + m_isDone = true; + v = 0; + } + else + { + int integer = 0; + if (sscanf(m_replacementValue, "%i", &integer) == 1) + { + m_patchedOK = true; + m_isDone = true; + v = integer; + } + } +} + +void PatchVisitor::VisitByte(uint8_t &v) +{ + if (m_isDone || m_haveScope) + return; + + int integer = 0; + if (sscanf(m_replacementValue, "%i", &integer) == 1) + { + m_patchedOK = true; + m_isDone = true; + v = integer; + } +} + +bool PatchVisitor::VisitEnum(const EnumDef *enumDefs, size_t numDefs, int &v) +{ + if (m_isDone || m_haveScope) + return false; + + for (size_t i = 0; i < numDefs; i++) + { + if (!strcmp(enumDefs[i].m_name, m_replacementValue)) + { + m_patchedOK = true; + m_isDone = true; + v = enumDefs[i].m_value; + return true; + } + } + + return false; +} + +bool PatchVisitor::VisitStaticCapacity(size_t size) +{ + return true; +} + +void PatchVisitor::VisitDynamicCapacity(size_t &size) +{ +} + +bool PatchVisitor::PatchedOK() const +{ + return m_patchedOK; +} + +bool PatchVisitor::DecodeInteger(const std::string &scopeStr, size_t startPos, int &outInteger, size_t &outEndPos) +{ + size_t len = scopeStr.length(); + + if (startPos >= len) + return false; + + bool isNegative = false; + char firstChar = scopeStr[startPos]; + if (firstChar == '-') + { + isNegative = true; + startPos++; + + if (startPos >= len) + return false; + } + + int resultInteger = 0; + + for (size_t i = startPos; i < len; i++) + { + char decChar = scopeStr[i]; + if (decChar >= '0' && decChar <= '9') + { + int digit = decChar - '0'; + if (isNegative) + resultInteger = resultInteger * 10 - digit; + else + resultInteger = resultInteger * 10 + digit; + } + else + { + if (i == startPos) + return false; + + outInteger = resultInteger; + outEndPos = i; + return true; + } + } + + outInteger = resultInteger; + outEndPos = len; + return true; +} + +bool PatchVisitor::DecodeQuotedString(const std::string &scopeStr, size_t startPos, std::string &outString, size_t &outEndPos) +{ + size_t len = scopeStr.length(); + + if (startPos >= len || scopeStr[startPos] != '\"') + return false; + + std::vector decoded; + for (size_t i = startPos + 1; i < len; i++) + { + char decChar = scopeStr[i]; + if (decChar == '\"') + { + if (decoded.size() == 0) + outString = std::string(); + else + outString = std::string(&decoded[0], decoded.size()); + + outEndPos = i + 1; + return true; + } + + if (decChar == '\\') + { + i++; + if (i == len) + return false; + + char escChar = scopeStr[i]; + if (escChar == '\"') + decoded.push_back('\"'); + else if (escChar == '\\') + decoded.push_back('\\'); + else if (escChar == '/') + decoded.push_back('/'); + else if (escChar == 'b') + decoded.push_back('\b'); + else if (escChar == 'f') + decoded.push_back('\f'); + else if (escChar == 'n') + decoded.push_back('\n'); + else if (escChar == 'r') + decoded.push_back('\r'); + else if (escChar == 't') + decoded.push_back('\t'); + else if (escChar == 'u') + { + int nibbles[4]; + for (int ni = 0; ni < 4; ni++) + { + i++; + if (i == len) + return false; + + char nibbleChar = scopeStr[i]; + if (nibbleChar >= '0' && nibbleChar <= '9') + nibbles[ni] = nibbleChar - '0'; + else if (nibbleChar >= 'A' && nibbleChar <= 'F') + nibbles[ni] = nibbleChar - 'A' + 0xa; + else if (nibbleChar >= 'a' && nibbleChar <= 'f') + nibbles[ni] = nibbleChar - 'a' + 0xa; + else + return false; + } + + const uint16_t unicodeCodePoint = (nibbles[0] << 12) + (nibbles[1] << 8) + (nibbles[2] << 4) + nibbles[3]; + uint8_t encoded[GpUnicode::UTF8::kMaxEncodedBytes]; + size_t emitted = 0; + GpUnicode::UTF8::Encode(encoded, emitted, unicodeCodePoint); + + for (size_t ei = 0; ei < emitted; ei++) + decoded.push_back(static_cast(encoded[ei])); + } + } + else + { + if (decChar < ' ' || decChar > '~') + return false; + + decoded.push_back(decChar); + } + } + + outEndPos = len; + return false; +} + +void PatchVisitor::EnterScope() +{ + if (!m_haveScope) + { + m_isDone = true; + return; + } + + bool shouldHaveScope = (m_nextScope.size() > 0); + if (!shouldHaveScope) + { + m_haveScope = false; + return; + } + + if (!TryEnterScope()) + { + m_haveScope = false; + m_isDone = true; + } +} + +bool PatchVisitor::TryEnterScope() +{ + if (m_nextScope.size() == 0) + return false; + + if (m_nextScope[0] == '.') + { + size_t lastFieldChar = 1; + while (lastFieldChar < m_nextScope.size()) + { + char c = m_nextScope[lastFieldChar]; + if ((c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || (c >= '0' && c <= '9') + || c == '_') + lastFieldChar++; + else + break; + } + + if (lastFieldChar == 1) + return false; + + m_nextScopeIsInteger = false; + m_scope = m_nextScope.substr(1, lastFieldChar - 1); + m_nextScope = m_nextScope.substr(lastFieldChar); + + return true; + } + + if (m_nextScope[0] == '[') + { + if (m_nextScope.size() == 1) + return false; + + if (m_nextScope[1] == '\"') + { + std::string quotedStr; + size_t endPos = 0; + if (!DecodeQuotedString(m_nextScope, 1, quotedStr, endPos)) + return false; + + if (endPos >= m_nextScope.size()) + return false; + + if (m_nextScope[endPos] != ']') + return false; + + m_nextScopeIsInteger = false; + m_scope = quotedStr; + m_nextScope = m_nextScope.substr(endPos + 1); + + return true; + } + else + { + int integer = 0; + size_t endPos = 0; + if (!DecodeInteger(m_nextScope, 1, integer, endPos)) + return false; + + if (endPos >= m_nextScope.size()) + return false; + + if (m_nextScope[endPos] != ']') + return false; + + m_nextScopeIsInteger = true; + m_scope = ""; + m_scopeInteger = integer; + m_nextScope = m_nextScope.substr(endPos + 1); + + return true; + } + } + + return false; +} + + +int PatchMain(int argc, const char **argv) +{ + if (argc != 5) + return PrintUsage(); + + houseType house; + std::vector rooms; + + if (!ReadHouseFromPath(argv[2], house, rooms)) + { + fprintf(stderr, "Failed to read house\n"); + return -1; + } + + PatchVisitor patcher(argv[3], argv[4]); + Visit(house, rooms, &patcher); + + if (!patcher.PatchedOK()) + fprintf(stderr, "Patch failed\n"); + else + { + FILE *houseOutF = fopen_utf8(argv[2], "wb"); + if (!houseOutF) + { + fprintf(stderr, "Failed to open output house\n"); + return -1; + } + + fwrite(&house, 1, houseType::kBinaryDataSize, houseOutF); + if (rooms.size() > 0) + fwrite(&rooms[0], 1, sizeof(roomType) * rooms.size(), houseOutF); + + fclose(houseOutF); + } + + return 0; +} + +class DecompileVisitor final : public IDataVisitor +{ +public: + explicit DecompileVisitor(FILE *f); + + IDataVisitor *EnterIndex(int index) override; + IDataVisitor *EnterNamed(const char *name) override; + void Exit() override; + + void VisitLPStr(uint8_t &length, uint8_t *chars, int capacity) override; + void VisitInt32(int32_t &v) override; + void VisitUInt32(uint32_t &v) override; + void VisitInt16(int16_t &v) override; + void VisitBool8(uint8_t &v) override; + void VisitByte(uint8_t &v) override; + bool VisitEnum(const EnumDef *enumDefs, size_t numDefs, int &v) override; + + bool VisitStaticCapacity(size_t size) override; + void VisitDynamicCapacity(size_t &size) override; + +private: + enum ScopeType + { + ScopeType_Array, + ScopeType_Map, + ScopeType_Unknown, + }; + + FILE *m_f; + int m_indentLevel; + + bool m_isInNamed; + bool m_isInArray; + + std::vector m_scopes; + + ScopeType GetTopScope(); + void SetTopScope(ScopeType scopeType); + void PopScope(); + void PushScope(); + + void WriteIndent(); +}; + +DecompileVisitor::DecompileVisitor(FILE *f) + : m_f(f) +{ + m_scopes.push_back(ScopeType_Unknown); +} + +IDataVisitor *DecompileVisitor::EnterIndex(int index) +{ + ScopeType topScope = GetTopScope(); + if (topScope == ScopeType_Array) + { + fprintf(m_f, ",\n"); + WriteIndent(); + } + else + { + fprintf(m_f, "[\n"); + WriteIndent(); + SetTopScope(ScopeType_Array); + } + + PushScope(); + + fprintf(m_f, "[%i] = ", index); + + return this; +} + +IDataVisitor *DecompileVisitor::EnterNamed(const char *name) +{ + ScopeType topScope = GetTopScope(); + if (topScope == ScopeType_Map) + { + fprintf(m_f, ",\n"); + WriteIndent(); + } + else + { + fprintf(m_f, "{\n"); + WriteIndent(); + SetTopScope(ScopeType_Map); + } + + PushScope(); + + fprintf(m_f, "%s = ", name); + + return this; +} + +void DecompileVisitor::Exit() +{ + ScopeType topScope = GetTopScope(); + if (topScope == ScopeType_Map) + { + fprintf(m_f, "\n"); + PopScope(); + WriteIndent(); + fprintf(m_f, "}"); + } + else if (topScope == ScopeType_Array) + { + fprintf(m_f, "\n"); + PopScope(); + WriteIndent(); + fprintf(m_f, "]"); + } + else + PopScope(); +} + + +void DecompileVisitor::VisitLPStr(uint8_t &length, uint8_t *chars, int capacity) +{ + fputc('\"', m_f); + for (size_t i = 0; i < length; i++) + { + uint16_t unicodeChar = MacRoman::ToUnicode(chars[i]); + if (unicodeChar == '\\') + fputs("\\\\", m_f); + else if (unicodeChar == '\"') + fputs("\\\"", m_f); + else if (unicodeChar == '\r') + fputs("\\r", m_f); + else if (unicodeChar == '\n') + fputs("\\n", m_f); + else if (unicodeChar < 32 || unicodeChar > 126) + fprintf(m_f, "\\u%04x", unicodeChar); + else + { + uint8_t ubyte = static_cast(unicodeChar); + fwrite(&ubyte, 1, 1, m_f); + } + } + fputc('\"', m_f); +} + +void DecompileVisitor::VisitInt32(int32_t &v) +{ + fprintf(m_f, "%i", static_cast(v)); +} + +void DecompileVisitor::VisitUInt32(uint32_t &v) +{ + fprintf(m_f, "%u", static_cast(v)); +} + + +void DecompileVisitor::VisitInt16(int16_t &v) +{ + fprintf(m_f, "%i", static_cast(v)); +} + +void DecompileVisitor::VisitBool8(uint8_t &v) +{ + if (v == 0) + fprintf(m_f, "false"); + else if (v == 1) + fprintf(m_f, "true"); + else + fprintf(m_f, "%i", static_cast(v)); +} + +void DecompileVisitor::VisitByte(uint8_t &v) +{ + fprintf(m_f, "%i", static_cast(v)); +} + +bool DecompileVisitor::VisitEnum(const EnumDef *enumDefs, size_t numDefs, int &v) +{ + for (size_t i = 0; i < numDefs; i++) + { + if (enumDefs[i].m_value == v) + { + fprintf(m_f, "\"%s\"", enumDefs[i].m_name); + return true; + } + } + + return false; +} + +bool DecompileVisitor::VisitStaticCapacity(size_t size) +{ + return true; +} + +void DecompileVisitor::VisitDynamicCapacity(size_t &size) +{ +} + +DecompileVisitor::ScopeType DecompileVisitor::GetTopScope() +{ + return m_scopes[m_scopes.size() - 1]; +} + +void DecompileVisitor::SetTopScope(ScopeType scopeType) +{ + m_scopes[m_scopes.size() - 1] = scopeType; +} + +void DecompileVisitor::PopScope() +{ + m_scopes.pop_back(); +} + +void DecompileVisitor::PushScope() +{ + m_scopes.push_back(ScopeType_Unknown); +} + +void DecompileVisitor::WriteIndent() +{ + for (size_t i = 0; i < m_scopes.size(); i++) + fputc('\t', m_f); +} + +int DecompileMain(int argc, const char **argv) +{ + if (argc != 4) + return PrintUsage(); + + houseType house; + std::vector rooms; + + if (!ReadHouseFromPath(argv[2], house, rooms)) + { + fprintf(stderr, "Failed to read house\n"); + return -1; + } + + FILE *outF = fopen_utf8(argv[3], "wb"); + if (!outF) + { + fprintf(stderr, "Failed to open output house\n"); + return -1; + } + + DecompileVisitor decompiler(outF); + Visit(house, rooms, &decompiler); + + fclose(outF); + + return 0; +} + +int toolMain(int argc, const char **argv) +{ + static const size_t houseSize = sizeof(houseType); + static_assert(sizeof(houseType) >= houseType::kBinaryDataSize, "House type is too small"); + + if (argc < 3) + return PrintUsage(); + + std::string operation = argv[1]; + + if (operation == "patch") + return PatchMain(argc, argv); + + if (operation == "decompile") + return DecompileMain(argc, argv); + + return 0; +} diff --git a/HouseTool/HouseTool.vcxproj b/HouseTool/HouseTool.vcxproj new file mode 100644 index 0000000..d480288 --- /dev/null +++ b/HouseTool/HouseTool.vcxproj @@ -0,0 +1,101 @@ + + + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {B31BFF9D-2D14-4B1A-A625-8348CC3D8D67} + HouseTool + 10.0.17763.0 + + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + MaxSpeed + true + true + true + true + + + Console + true + true + + + + + Level3 + Disabled + true + true + + + Console + + + + + + + + {6ec62b0f-9353-40a4-a510-3788f1368b33} + + + {15009625-1120-405e-8bba-69a16cd6713d} + + + + + + + + + \ No newline at end of file diff --git a/HouseTool/HouseTool.vcxproj.filters b/HouseTool/HouseTool.vcxproj.filters new file mode 100644 index 0000000..84f151a --- /dev/null +++ b/HouseTool/HouseTool.vcxproj.filters @@ -0,0 +1,25 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + + \ No newline at end of file diff --git a/MergeGPF/MergeGPF.cpp b/MergeGPF/MergeGPF.cpp index b1ea2fd..783f8e1 100644 --- a/MergeGPF/MergeGPF.cpp +++ b/MergeGPF/MergeGPF.cpp @@ -5,6 +5,8 @@ #include "DeflateCodec.h" #include "MacFileInfo.h" #include "ZipFile.h" +#include "GpAllocator_C.h" +#include "PLDrivers.h" #include #include @@ -12,6 +14,9 @@ int toolMain(int argc, const char **argv) { + GpDriverCollection *drivers = PLDrivers::GetDriverCollection(); + drivers->SetDriver(GpAllocator_C::GetInstance()); + if (argc != 2) { fprintf(stderr, "Usage: MergeGPF "); diff --git a/MergeGPF/MergeGPF.vcxproj b/MergeGPF/MergeGPF.vcxproj index 808798b..bc0571a 100644 --- a/MergeGPF/MergeGPF.vcxproj +++ b/MergeGPF/MergeGPF.vcxproj @@ -42,6 +42,7 @@ + @@ -50,6 +51,7 @@ + @@ -84,6 +86,7 @@ + diff --git a/MergeGPF/MergeGPF.vcxproj.filters b/MergeGPF/MergeGPF.vcxproj.filters index f3f177d..3c48d44 100644 --- a/MergeGPF/MergeGPF.vcxproj.filters +++ b/MergeGPF/MergeGPF.vcxproj.filters @@ -18,5 +18,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/PortabilityLayer/Android.mk b/PortabilityLayer/Android.mk index 18452c0..a01634f 100644 --- a/PortabilityLayer/Android.mk +++ b/PortabilityLayer/Android.mk @@ -17,92 +17,7 @@ LOCAL_EXPORT_LDLIBS := -lz # Add your application source files here... LOCAL_SRC_FILES := \ - AntiAliasTable.cpp \ - AppEventHandler.cpp \ - BinHex4.cpp \ - BitmapImage.cpp \ - ByteSwap.cpp \ - CFileStream.cpp \ - DeflateCodec.cpp \ - DialogManager.cpp \ - DisplayDeviceManager.cpp \ - EllipsePlotter.cpp \ - FileBrowserUI.cpp \ - FileManager.cpp \ - FileSectionStream.cpp \ - FontFamily.cpp \ - FontManager.cpp \ - FontRenderer.cpp \ - GPArchive.cpp \ - HostSuspendHook.cpp \ - IconLoader.cpp \ - InflateStream.cpp \ - InputManager.cpp \ - LinePlotter.cpp \ - MacBinary2.cpp \ - MacFileInfo.cpp \ - MacFileMem.cpp \ - MemoryManager.cpp \ - MemReaderStream.cpp \ - MenuManager.cpp \ - MMBlock.cpp \ - MMHandleBlock.cpp \ - PLApplication.cpp \ - PLButtonWidget.cpp \ - PLControlDefinitions.cpp \ - PLCore.cpp \ - PLCTabReducer.cpp \ - PLDialogs.cpp \ - PLDrivers.cpp \ - PLEditboxWidget.cpp \ - PLEventQueue.cpp \ - PLHacks.cpp \ - PLHandle.cpp \ - PLIconWidget.cpp \ - PLImageWidget.cpp \ - PLInvisibleWidget.cpp \ - PLKeyEncoding.cpp \ - PLLabelWidget.cpp \ - PLMenus.cpp \ - PLMovies.cpp \ - PLNumberFormatting.cpp \ - PLPopupMenuWidget.cpp \ - PLQDOffscreen.cpp \ - PLQDraw.cpp \ - PLResourceManager.cpp \ - PLResources.cpp \ - PLScrollBarWidget.cpp \ - PLSound.cpp \ - PLStandardColors.cpp \ - PLStringCompare.cpp \ - PLSysCalls.cpp \ - PLTimeTaggedVOSEvent.cpp \ - PLWidgets.cpp \ - QDGraf.cpp \ - QDManager.cpp \ - QDPictDecoder.cpp \ - QDPictEmitContext.cpp \ - QDPictHeader.cpp \ - QDPixMap.cpp \ - QDPort.cpp \ - QDStandardPalette.cpp \ - RandomNumberGenerator.cpp \ - ResolveCachingColor.cpp \ - ResourceCompiledRef.cpp \ - ResourceFile.cpp \ - ScanlineMask.cpp \ - ScanlineMaskBuilder.cpp \ - ScanlineMaskConverter.cpp \ - ScanlineMaskIterator.cpp \ - SimpleGraphic.cpp \ - TextPlacer.cpp \ - UTF8.cpp \ - UTF16.cpp \ - WindowDef.cpp \ - WindowManager.cpp \ - WorkerThread.cpp \ - XModemCRC.cpp \ - ZipFileProxy.cpp + PortabilityLayer_Combined.cpp LOCAL_STATIC_LIBRARIES := MacRomanConversion stb diff --git a/PortabilityLayer/AntiAliasTable.cpp b/PortabilityLayer/AntiAliasTable.cpp index c5e7e9a..e40cc01 100644 --- a/PortabilityLayer/AntiAliasTable.cpp +++ b/PortabilityLayer/AntiAliasTable.cpp @@ -35,40 +35,6 @@ namespace PortabilityLayer return minIndexInclusive; } - - bool AntiAliasTable::LoadFromCache(const char *cacheFileName) - { - GpIOStream *stream = PLDrivers::GetFileSystem()->OpenFile(PortabilityLayer::VirtualDirectories::kFontCache, cacheFileName, false, GpFileCreationDispositions::kOpenExisting); - if (!stream) - return false; - - BEUInt32_t cacheVersion; - if (stream->Read(&cacheVersion, sizeof(cacheVersion)) != sizeof(cacheVersion) || cacheVersion != kCacheVersion) - { - stream->Close(); - return false; - } - - const size_t readSize = sizeof(m_aaTranslate); - const bool readOK = (stream->Read(m_aaTranslate, readSize) == readSize); - stream->Close(); - - return readOK; - } - - void AntiAliasTable::SaveToCache(const char *cacheFileName) - { - GpIOStream *stream = PLDrivers::GetFileSystem()->OpenFile(PortabilityLayer::VirtualDirectories::kFontCache, cacheFileName, true, GpFileCreationDispositions::kCreateOrOverwrite); - if (!stream) - return; - - BEUInt32_t cacheVersion(static_cast(kCacheVersion)); - stream->Write(&cacheVersion, sizeof(cacheVersion)); - - stream->Write(m_aaTranslate, sizeof(m_aaTranslate)); - stream->Close(); - } - void AntiAliasTable::GenerateForPaletteFast(const RGBAColor &baseColorRef) { const RGBAColor baseColor = baseColorRef; @@ -191,16 +157,8 @@ namespace PortabilityLayer } } - void AntiAliasTable::GenerateForPalette(const RGBAColor &baseColorRef, const RGBAColor *colors, size_t numColors, bool cacheable) + void AntiAliasTable::GenerateForPalette(const RGBAColor &baseColorRef, const RGBAColor *colors, size_t numColors) { - char cacheFileName[256]; - if (cacheable) - { - sprintf(cacheFileName, "aa_p_%02x%02x%02x%02x.cache", static_cast(baseColorRef.r), static_cast(baseColorRef.g), static_cast(baseColorRef.b), static_cast(baseColorRef.a)); - if (LoadFromCache(cacheFileName)) - return; - } - const RGBAColor baseColor = baseColorRef; if (numColors > 256) @@ -259,21 +217,10 @@ namespace PortabilityLayer m_aaTranslate[i][b] = static_cast(bestColor); } } - - if (cacheable) - SaveToCache(cacheFileName); } - void AntiAliasTable::GenerateForSimpleScale(uint8_t colorChannel, bool cacheable) + void AntiAliasTable::GenerateForSimpleScale(uint8_t colorChannel) { - char cacheFileName[256]; - if (cacheable) - { - sprintf(cacheFileName, "aa_t_%02x.cache", static_cast(colorChannel)); - if (LoadFromCache(cacheFileName)) - return; - } - const double gamma = 1.8; const double rcpGamma = 1.0 / gamma; const double rcp255 = 1.0 / 255.0; @@ -294,8 +241,5 @@ namespace PortabilityLayer m_aaTranslate[baseColor][opacity] = static_cast(floor(blendedColorGammaSpace * 255.0 + 0.5)); } } - - if (cacheable) - SaveToCache(cacheFileName); } } diff --git a/PortabilityLayer/AntiAliasTable.h b/PortabilityLayer/AntiAliasTable.h index 7ee582e..dfc3dc3 100644 --- a/PortabilityLayer/AntiAliasTable.h +++ b/PortabilityLayer/AntiAliasTable.h @@ -12,14 +12,8 @@ namespace PortabilityLayer // Striped 256x16 because constant background color is more likely than constant sample uint8_t m_aaTranslate[256][16]; - void GenerateForPalette(const RGBAColor &baseColor, const RGBAColor *colors, size_t numColors, bool cacheable); + void GenerateForPalette(const RGBAColor &baseColor, const RGBAColor *colors, size_t numColors); void GenerateForPaletteFast(const RGBAColor &baseColor); - void GenerateForSimpleScale(uint8_t colorChannel, bool cacheable); - - private: - bool LoadFromCache(const char *path); - void SaveToCache(const char *path); - - static const unsigned int kCacheVersion = 1; + void GenerateForSimpleScale(uint8_t colorChannel); }; } diff --git a/PortabilityLayer/CFileStream.cpp b/PortabilityLayer/CFileStream.cpp index f013edc..da7ee46 100644 --- a/PortabilityLayer/CFileStream.cpp +++ b/PortabilityLayer/CFileStream.cpp @@ -81,7 +81,7 @@ namespace PortabilityLayer return static_cast(ftell(m_file)); } - void CFileStream::Close() + void CFileStream::GP_ASYNCIFY_PARANOID_NAMED(Close)() { if (m_file) { diff --git a/PortabilityLayer/CFileStream.h b/PortabilityLayer/CFileStream.h index 5bb0a6c..aefe406 100644 --- a/PortabilityLayer/CFileStream.h +++ b/PortabilityLayer/CFileStream.h @@ -23,7 +23,7 @@ namespace PortabilityLayer bool SeekEnd(GpUFilePos_t loc) override; GpUFilePos_t Size() const override; GpUFilePos_t Tell() const override; - void Close() override; + void GP_ASYNCIFY_PARANOID_NAMED(Close)() override; void Flush() override; private: diff --git a/PortabilityLayer/DeflateCodec.cpp b/PortabilityLayer/DeflateCodec.cpp index b87b64c..ff1caa0 100644 --- a/PortabilityLayer/DeflateCodec.cpp +++ b/PortabilityLayer/DeflateCodec.cpp @@ -371,6 +371,6 @@ uint32_t PortabilityLayer::DeflateContext::CRC32(uint32_t inputValue, const void PortabilityLayer::InflateContext *PortabilityLayer::InflateContext::Create() -{ +{ return InflateContextImpl::Create(); } diff --git a/PortabilityLayer/DialogManager.cpp b/PortabilityLayer/DialogManager.cpp index 2a01013..18f0803 100644 --- a/PortabilityLayer/DialogManager.cpp +++ b/PortabilityLayer/DialogManager.cpp @@ -3,6 +3,7 @@ #include "IGpDisplayDriver.h" #include "IGpLogDriver.h" #include "IGpSystemServices.h" +#include "MemoryManager.h" #include "ResourceManager.h" #include "QDPixMap.h" #include "Rect2i.h" @@ -361,7 +362,7 @@ namespace PortabilityLayer void DialogTemplate::Destroy() { this->~DialogTemplate(); - free(this); + DisposePtr(this); } ArrayView DialogTemplate::GetItems() const @@ -374,7 +375,7 @@ namespace PortabilityLayer PortabilityLayer::WindowManager::GetInstance()->DestroyWindow(m_window); this->~DialogImpl(); - free(this); + DisposePtr(this); } Window *DialogImpl::GetWindow() const @@ -646,7 +647,7 @@ namespace PortabilityLayer const size_t itemsSize = sizeof(DialogItem) * numItems; - void *storage = malloc(alignedSize + itemsSize); + void *storage = NewPtr(alignedSize + itemsSize); if (!storage) return nullptr; @@ -882,7 +883,7 @@ namespace PortabilityLayer const size_t dtlItemSize = sizeof(DialogTemplateItem) * numItems; - void *storage = malloc(dtlAlignedSize + dtlItemSize); + void *storage = NewPtr(dtlAlignedSize + dtlItemSize); if (!storage) { dtemplateH.Dispose(); diff --git a/PortabilityLayer/FileBrowserUI.cpp b/PortabilityLayer/FileBrowserUI.cpp index 24d9531..4735d03 100644 --- a/PortabilityLayer/FileBrowserUI.cpp +++ b/PortabilityLayer/FileBrowserUI.cpp @@ -459,7 +459,13 @@ namespace PortabilityLayer break; } - if (WaitForEvent(&evtHolder, 1)) + bool haveEvent = false; + { + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); + haveEvent = WaitForEvent(&evtHolder, 1); + } + + if (haveEvent) rcvEvt = &evtHolder; else rcvEvt = nullptr; diff --git a/PortabilityLayer/FileManager.cpp b/PortabilityLayer/FileManager.cpp index e1ccccd..0ffdf85 100644 --- a/PortabilityLayer/FileManager.cpp +++ b/PortabilityLayer/FileManager.cpp @@ -10,6 +10,7 @@ #include "ResTypeID.h" #include "ZipFileProxy.h" +#include "PLCore.h" #include "PLDrivers.h" #include "PLPasStr.h" #include "PLErrorCodes.h" @@ -39,17 +40,17 @@ namespace PortabilityLayer bool CompositeFileExists(VirtualDirectory_t dirID, const PLPasStr &filename) override; bool NonCompositeFileExists(VirtualDirectory_t dirID, const PLPasStr &filename, const char *extension) override; - bool DeleteNonCompositeFile(VirtualDirectory_t dirID, const PLPasStr &filename, const char *ext) override; - bool DeleteCompositeFile(VirtualDirectory_t dirID, const PLPasStr &filename) override; + bool DeleteNonCompositeFile(VirtualDirectory_t dirID, const PLPasStr &filename, const char *ext) GP_ASYNCIFY_PARANOID_OVERRIDE; + bool DeleteCompositeFile(VirtualDirectory_t dirID, const PLPasStr &filename) GP_ASYNCIFY_PARANOID_OVERRIDE; - PLError_t CreateFile(VirtualDirectory_t dirID, const PLPasStr &filename, const MacFileProperties &mfp) override; - PLError_t CreateFileAtCurrentTime(VirtualDirectory_t dirID, const PLPasStr &filename, const ResTypeID &fileCreator, const ResTypeID &fileType) override; + PLError_t CreateFile(VirtualDirectory_t dirID, const PLPasStr &filename, const MacFileProperties &mfp) GP_ASYNCIFY_PARANOID_OVERRIDE; + PLError_t CreateFileAtCurrentTime(VirtualDirectory_t dirID, const PLPasStr &filename, const ResTypeID &fileCreator, const ResTypeID &fileType) GP_ASYNCIFY_PARANOID_OVERRIDE; PLError_t RawOpenFileData(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, GpFileCreationDisposition_t creationDisposition, GpIOStream *&outStream) override; PLError_t RawOpenFileResources(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, GpFileCreationDisposition_t creationDisposition, GpIOStream *&outStream) override; - bool PromptSaveFile(VirtualDirectory_t dirID, const char *extension, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &initialFileName, const PLPasStr &promptText, bool composites, const FileBrowserUI_DetailsCallbackAPI &callbackAPI) override; - bool PromptOpenFile(VirtualDirectory_t dirID, const char *extension, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &promptText, bool composites, const FileBrowserUI_DetailsCallbackAPI &callbackAPI) override; + bool PromptSaveFile(VirtualDirectory_t dirID, const char *extension, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &initialFileName, const PLPasStr &promptText, bool composites, const FileBrowserUI_DetailsCallbackAPI &callbackAPI) GP_ASYNCIFY_PARANOID_OVERRIDE; + bool PromptOpenFile(VirtualDirectory_t dirID, const char *extension, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &promptText, bool composites, const FileBrowserUI_DetailsCallbackAPI &callbackAPI) GP_ASYNCIFY_PARANOID_OVERRIDE; static FileManagerImpl *GetInstance(); @@ -474,12 +475,12 @@ namespace PortabilityLayer void CompositeFileImpl::Close() { this->~CompositeFileImpl(); - free(this); + DisposePtr(this); } CompositeFileImpl *CompositeFileImpl::Create(VirtualDirectory_t dirID, const PLPasStr &filename, GpIOStream *stream, ZipFileProxy *zipFile, const MacFileProperties &mfp, bool resInline, bool dataInline, size_t inlineDataIndex) { - void *storage = malloc(sizeof(CompositeFileImpl)); + void *storage = NewPtr(sizeof(CompositeFileImpl)); if (!storage) return nullptr; @@ -506,4 +507,36 @@ namespace PortabilityLayer if (m_stream) m_stream->Close(); } + +#if GP_ASYNCIFY_PARANOID + bool FileManager::PromptSaveFile(VirtualDirectory_t dirID, const char *extension, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &initialFileName, const PLPasStr &promptText, bool composites, const FileBrowserUI_DetailsCallbackAPI &callbackAPI) + { + return static_cast(this)->PromptSaveFile(dirID, extension, path, outPathLength, pathCapacity, initialFileName, promptText, composites, callbackAPI); + } + + bool FileManager::PromptOpenFile(VirtualDirectory_t dirID, const char *extension, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &promptText, bool composites, const FileBrowserUI_DetailsCallbackAPI &callbackAPI) + { + return static_cast(this)->PromptOpenFile(dirID, extension, path, outPathLength, pathCapacity, promptText, composites, callbackAPI); + } + + PLError_t FileManager::CreateFile(VirtualDirectory_t dirID, const PLPasStr &filename, const MacFileProperties &mfp) + { + return static_cast(this)->CreateFile(dirID, filename, mfp); + } + + PLError_t FileManager::CreateFileAtCurrentTime(VirtualDirectory_t dirID, const PLPasStr &filename, const ResTypeID &fileCreator, const ResTypeID &fileType) + { + return static_cast(this)->CreateFileAtCurrentTime(dirID, filename, fileCreator, fileType); + } + + bool FileManager::DeleteNonCompositeFile(VirtualDirectory_t dirID, const PLPasStr &filename, const char *ext) + { + return static_cast(this)->DeleteNonCompositeFile(dirID, filename, ext); + } + + bool FileManager::DeleteCompositeFile(VirtualDirectory_t dirID, const PLPasStr &filename) + { + return static_cast(this)->DeleteCompositeFile(dirID, filename); + } +#endif } diff --git a/PortabilityLayer/FileManager.h b/PortabilityLayer/FileManager.h index 93f8045..a2f8482 100644 --- a/PortabilityLayer/FileManager.h +++ b/PortabilityLayer/FileManager.h @@ -46,17 +46,17 @@ namespace PortabilityLayer virtual bool CompositeFileExists(VirtualDirectory_t dirID, const PLPasStr &filename) = 0; virtual bool NonCompositeFileExists(VirtualDirectory_t dirID, const PLPasStr &filename, const char *extension) = 0; - virtual bool DeleteNonCompositeFile(VirtualDirectory_t dirID, const PLPasStr &filename, const char *ext) = 0; - virtual bool DeleteCompositeFile(VirtualDirectory_t dirID, const PLPasStr &filename) = 0; + GP_ASYNCIFY_PARANOID_VIRTUAL bool DeleteNonCompositeFile(VirtualDirectory_t dirID, const PLPasStr &filename, const char *ext) GP_ASYNCIFY_PARANOID_PURE; + GP_ASYNCIFY_PARANOID_VIRTUAL bool DeleteCompositeFile(VirtualDirectory_t dirID, const PLPasStr &filename) GP_ASYNCIFY_PARANOID_PURE; - virtual PLError_t CreateFile(VirtualDirectory_t dirID, const PLPasStr &filename, const MacFileProperties &mfp) = 0; - virtual PLError_t CreateFileAtCurrentTime(VirtualDirectory_t dirID, const PLPasStr &filename, const ResTypeID &fileCreator, const ResTypeID &fileType) = 0; + GP_ASYNCIFY_PARANOID_VIRTUAL PLError_t CreateFile(VirtualDirectory_t dirID, const PLPasStr &filename, const MacFileProperties &mfp) GP_ASYNCIFY_PARANOID_PURE; + GP_ASYNCIFY_PARANOID_VIRTUAL PLError_t CreateFileAtCurrentTime(VirtualDirectory_t dirID, const PLPasStr &filename, const ResTypeID &fileCreator, const ResTypeID &fileType) GP_ASYNCIFY_PARANOID_PURE; virtual PLError_t RawOpenFileData(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, GpFileCreationDisposition_t createDisposition, GpIOStream *&outStream) = 0; virtual PLError_t RawOpenFileResources(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, GpFileCreationDisposition_t createDisposition, GpIOStream *&outStream) = 0; - virtual bool PromptSaveFile(VirtualDirectory_t dirID, const char *extension, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &initialFileName, const PLPasStr &promptText, bool composites, const FileBrowserUI_DetailsCallbackAPI &callbackAPI) = 0; - virtual bool PromptOpenFile(VirtualDirectory_t dirID, const char *extension, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &promptText, bool composites, const FileBrowserUI_DetailsCallbackAPI &callbackAPI) = 0; + GP_ASYNCIFY_PARANOID_VIRTUAL bool PromptSaveFile(VirtualDirectory_t dirID, const char *extension, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &initialFileName, const PLPasStr &promptText, bool composites, const FileBrowserUI_DetailsCallbackAPI &callbackAPI) GP_ASYNCIFY_PARANOID_PURE; + GP_ASYNCIFY_PARANOID_VIRTUAL bool PromptOpenFile(VirtualDirectory_t dirID, const char *extension, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &promptText, bool composites, const FileBrowserUI_DetailsCallbackAPI &callbackAPI) GP_ASYNCIFY_PARANOID_PURE; static FileManager *GetInstance(); }; diff --git a/PortabilityLayer/FileSectionStream.cpp b/PortabilityLayer/FileSectionStream.cpp index cdc2c16..38fe5aa 100644 --- a/PortabilityLayer/FileSectionStream.cpp +++ b/PortabilityLayer/FileSectionStream.cpp @@ -1,4 +1,5 @@ #include "FileSectionStream.h" +#include "PLCore.h" #include #include @@ -21,7 +22,7 @@ namespace PortabilityLayer bool SeekEnd(GpUFilePos_t loc) override; GpUFilePos_t Size() const override; GpUFilePos_t Tell() const override; - void Close() override; + void GP_ASYNCIFY_PARANOID_NAMED(Close)() override; void Flush() override; private: @@ -148,10 +149,10 @@ namespace PortabilityLayer return m_expectedPosition - m_start; } - void FileSectionStreamImpl::Close() + void FileSectionStreamImpl::GP_ASYNCIFY_PARANOID_NAMED(Close)() { this->~FileSectionStreamImpl(); - free(this); + DisposePtr(this); } void FileSectionStreamImpl::Flush() @@ -161,7 +162,7 @@ namespace PortabilityLayer GpIOStream *FileSectionStream::Create(GpIOStream *stream, GpUFilePos_t start, GpUFilePos_t size) { - void *storage = malloc(sizeof(FileSectionStreamImpl)); + void *storage = NewPtr(sizeof(FileSectionStreamImpl)); if (!storage) return nullptr; diff --git a/PortabilityLayer/FontFamily.cpp b/PortabilityLayer/FontFamily.cpp index 39a5a7c..8e7c85e 100644 --- a/PortabilityLayer/FontFamily.cpp +++ b/PortabilityLayer/FontFamily.cpp @@ -7,6 +7,7 @@ #include "MemReaderStream.h" #include "MemoryManager.h" +#include "PLCore.h" #include "PLDrivers.h" #include @@ -15,16 +16,20 @@ namespace PortabilityLayer { FontFamily::FontSpec::FontSpec() - : m_fontPath(nullptr) + : m_fontVDir(VirtualDirectories::kUnspecified) + , m_fontPath(nullptr) , m_font(nullptr) , m_hacks(FontHacks_None) + , m_typeFaceIndex(0) , m_isRegistered(false) { } - void FontFamily::AddFont(int flags, const char *path, FontHacks fontHacks) + void FontFamily::AddFont(int flags, VirtualDirectory_t vDir, const char *path, int typeFaceIndex, FontHacks fontHacks) { + m_fontSpecs[flags].m_fontVDir = vDir; m_fontSpecs[flags].m_fontPath = path; + m_fontSpecs[flags].m_typeFaceIndex = typeFaceIndex; m_fontSpecs[flags].m_hacks = fontHacks; m_fontSpecs[flags].m_isRegistered = true; @@ -55,7 +60,7 @@ namespace PortabilityLayer if (spec.m_font) return spec.m_font; - GpIOStream *sysFontStream = PLDrivers::GetFileSystem()->OpenFile(PortabilityLayer::VirtualDirectories::kFonts, spec.m_fontPath, false, GpFileCreationDispositions::kOpenExisting); + GpIOStream *sysFontStream = PLDrivers::GetFileSystem()->OpenFile(spec.m_fontVDir, spec.m_fontPath, false, GpFileCreationDispositions::kOpenExisting); if (!sysFontStream) return nullptr; @@ -93,7 +98,7 @@ namespace PortabilityLayer IGpFontHandler *fontHandler = PLDrivers::GetFontHandler(); - IGpFont *font = fontHandler->LoadFont(sysFontStream); + IGpFont *font = fontHandler->LoadFont(sysFontStream, spec.m_typeFaceIndex); if (!fontHandler->KeepStreamOpen()) sysFontStream->Close(); @@ -106,18 +111,31 @@ namespace PortabilityLayer return font; } + void FontFamily::UnloadVariation(int variation) + { + FontSpec &spec = m_fontSpecs[variation]; + if (spec.m_font) + { + spec.m_font->Destroy(); + spec.m_font = nullptr; + } + } + PortabilityLayer::FontHacks FontFamily::GetHacksForVariation(int variation) const { return m_fontSpecs[variation].m_hacks; } - bool FontFamily::GetFontSpec(int variation, FontHacks &outHacks, const char *&outPath) + bool FontFamily::GetFontSpec(int variation, FontHacks &outHacks, VirtualDirectory_t &outVDir, const char *&outPath, int &outTypeFaceIndex) { - if (!m_fontSpecs[variation].m_isRegistered) + const FontSpec &spec = m_fontSpecs[variation]; + if (!spec.m_isRegistered) return false; - outHacks = m_fontSpecs[variation].m_hacks; - outPath = m_fontSpecs[variation].m_fontPath; + outHacks = spec.m_hacks; + outVDir = spec.m_fontVDir; + outPath = spec.m_fontPath; + outTypeFaceIndex = spec.m_typeFaceIndex; return true; } @@ -141,7 +159,7 @@ namespace PortabilityLayer FontFamily *FontFamily::Create(FontFamilyID_t familyID) { - void *storage = malloc(sizeof(FontFamily)); + void *storage = NewPtr(sizeof(FontFamily)); if (!storage) return nullptr; @@ -151,7 +169,7 @@ namespace PortabilityLayer void FontFamily::Destroy() { this->~FontFamily(); - free(this); + DisposePtr(this); } FontFamily::FontFamily(FontFamilyID_t familyID) diff --git a/PortabilityLayer/FontFamily.h b/PortabilityLayer/FontFamily.h index df1f1de..61fbbeb 100644 --- a/PortabilityLayer/FontFamily.h +++ b/PortabilityLayer/FontFamily.h @@ -2,6 +2,7 @@ #include "FontFamilyID.h" #include "FontHacks.h" +#include "VirtualDirectory.h" #include @@ -15,8 +16,9 @@ namespace PortabilityLayer FontFamilyFlag_None = 0, FontFamilyFlag_Bold = 1, + FontFamilyFlag_SyntheticBold = 2, - FontFamilyFlag_All = 1, + FontFamilyFlag_All = (FontFamilyFlag_Bold | FontFamilyFlag_SyntheticBold), }; class FontFamily final @@ -24,12 +26,13 @@ namespace PortabilityLayer public: static const unsigned int kNumVariations = FontFamilyFlag_All + 1; - void AddFont(int flags, const char *path, FontHacks fontHacks); + void AddFont(int flags, VirtualDirectory_t vDir, const char *path, int typeFaceIndex, FontHacks fontHacks); void SetDefaultVariation(int defaultVariation); - bool GetFontSpec(int variation, FontHacks &outHacks, const char *&outPath); + bool GetFontSpec(int variation, FontHacks &outHacks, VirtualDirectory_t &outVDir, const char *&outPath, int &outTypeFaceIndex); int GetVariationForFlags(int flags) const; IGpFont *GetFontForVariation(int variation); + void UnloadVariation(int variation); FontHacks GetHacksForVariation(int variation) const; FontFamilyID_t GetFamilyID() const; @@ -46,7 +49,9 @@ namespace PortabilityLayer IGpFont *m_font; FontHacks m_hacks; + VirtualDirectory_t m_fontVDir; const char *m_fontPath; + int m_typeFaceIndex; bool m_isRegistered; }; diff --git a/PortabilityLayer/FontHacks.h b/PortabilityLayer/FontHacks.h index 55a7444..c9a06b0 100644 --- a/PortabilityLayer/FontHacks.h +++ b/PortabilityLayer/FontHacks.h @@ -6,5 +6,6 @@ namespace PortabilityLayer { FontHacks_None, FontHacks_Roboto, + FontHacks_SyntheticBold_OpenSans, }; } diff --git a/PortabilityLayer/FontManager.cpp b/PortabilityLayer/FontManager.cpp index bf51a8d..0483878 100644 --- a/PortabilityLayer/FontManager.cpp +++ b/PortabilityLayer/FontManager.cpp @@ -6,6 +6,7 @@ #include "GpIOStream.h" #include "IGpFileSystem.h" #include "IGpFont.h" +#include "IGpSystemServices.h" #include "MemReaderStream.h" #include "PLBigEndian.h" @@ -32,8 +33,6 @@ namespace PortabilityLayer FontFamily *GetFont(FontFamilyID_t fontFamilyID) const override; void GetFontPreset(FontPreset_t fontPreset, FontFamilyID_t *outFamilyID, int *outSize, int *outVariationFlags, bool *outAA) const override; - RenderedFont *GetRenderedFontFromFamily(FontFamily *font, int size, bool aa, int flags) override; - RenderedFont *LoadCachedRenderedFont(FontFamilyID_t familyID, int size, bool aa, int flags) override; void PurgeCache() override; @@ -41,6 +40,9 @@ namespace PortabilityLayer static FontManagerImpl *GetInstance(); private: + RenderedFont *LoadAndRenderFontUsingFontHandler(FontFamily *font, int size, bool aa, int flags); + RenderedFont *LoadAndRenderFont(FontFamilyID_t familyID, int size, bool aa, int flags); + static const unsigned int kNumCachedRenderedFonts = 32; struct CachedRenderedFont @@ -48,8 +50,9 @@ namespace PortabilityLayer RenderedFont *m_rfont; int m_fontCacheID; int m_size; - uint32_t m_lastUsage; + int m_flags; bool m_aa; + uint32_t m_lastUsage; }; struct FontPreset @@ -62,7 +65,7 @@ namespace PortabilityLayer FontManagerImpl(); - bool FindOrReserveCacheSlot(int cacheID, int size, bool aa, CachedRenderedFont *&outCacheSlot, RenderedFont *&outRF); + bool FindOrReserveCacheSlot(int cacheID, int size, bool aa, int flags, CachedRenderedFont *&outCacheSlot, RenderedFont *&outRF); void ReplaceCachedRenderedFont(CachedRenderedFont &cacheSlot, RenderedFont *rfont, int cacheID, int size, bool aa, int flags); void ResetUsageCounter(); @@ -77,6 +80,8 @@ namespace PortabilityLayer PortabilityLayer::CompositeFile *m_fontArchiveFile; THandle m_fontArchiveCatalogData; + bool m_hasPreinstalledFonts; + static FontManagerImpl ms_instance; static FontPreset ms_fontPresets[FontPresets::kCount]; }; @@ -87,19 +92,20 @@ namespace PortabilityLayer m_fontFamilies[static_cast(i)] = FontFamily::Create(static_cast(i)); if (m_fontFamilies[FontFamilyIDs::kSystem]) - m_fontFamilies[FontFamilyIDs::kSystem]->AddFont(FontFamilyFlag_None, "Fonts/OpenSans/OpenSans-ExtraBold.ttf", FontHacks_None); + m_fontFamilies[FontFamilyIDs::kSystem]->AddFont(FontFamilyFlag_None, VirtualDirectories::kFonts, "Fonts/OpenSans/OpenSans-ExtraBold.ttf", 0, FontHacks_None); if (m_fontFamilies[FontFamilyIDs::kApplication]) { - m_fontFamilies[FontFamilyIDs::kApplication]->AddFont(FontFamilyFlag_None, "Fonts/OpenSans/OpenSans-SemiBold.ttf", FontHacks_None); - m_fontFamilies[FontFamilyIDs::kApplication]->AddFont(FontFamilyFlag_Bold, "Fonts/OpenSans/OpenSans-Bold.ttf", FontHacks_None); + m_fontFamilies[FontFamilyIDs::kApplication]->AddFont(FontFamilyFlag_None, VirtualDirectories::kFonts, "Fonts/OpenSans/OpenSans-SemiBold.ttf", 0, FontHacks_None); + m_fontFamilies[FontFamilyIDs::kApplication]->AddFont(FontFamilyFlag_Bold, VirtualDirectories::kFonts, "Fonts/OpenSans/OpenSans-Bold.ttf", 0, FontHacks_None); + m_fontFamilies[FontFamilyIDs::kApplication]->AddFont(FontFamilyFlag_SyntheticBold, VirtualDirectories::kFonts, "Fonts/OpenSans/OpenSans-Regular.ttf", 0, FontHacks_SyntheticBold_OpenSans); } if (m_fontFamilies[FontFamilyIDs::kHandwriting]) - m_fontFamilies[FontFamilyIDs::kHandwriting]->AddFont(FontFamilyFlag_None, "Fonts/GochiHand/GochiHand-Regular.ttf", FontHacks_None); + m_fontFamilies[FontFamilyIDs::kHandwriting]->AddFont(FontFamilyFlag_None, VirtualDirectories::kFonts, "Fonts/GochiHand/GochiHand-Regular.ttf", 0, FontHacks_None); if (m_fontFamilies[FontFamilyIDs::kMonospace]) - m_fontFamilies[FontFamilyIDs::kMonospace]->AddFont(FontFamilyFlag_None, "Fonts/Roboto/RobotoMono-Regular.ttf", FontHacks_None); + m_fontFamilies[FontFamilyIDs::kMonospace]->AddFont(FontFamilyFlag_None, VirtualDirectories::kFonts, "Fonts/Roboto/RobotoMono-Regular.ttf", 0, FontHacks_None); memset(m_cachedRenderedFonts, 0, sizeof(m_cachedRenderedFonts)); } @@ -139,23 +145,10 @@ namespace PortabilityLayer *outAA = ms_fontPresets[preset].m_aa; if (outFamilyID) - { - switch (ms_fontPresets[preset].m_familyID) - { - case FontFamilyIDs::kApplication: - if (ms_fontPresets[preset].m_textSize < 11 && (ms_fontPresets[preset].m_variationFlags & FontFamilyFlag_Bold) != 0) - *outFamilyID = FontFamilyIDs::kSystem; // Use heavier font below 11pt - else - *outFamilyID = FontFamilyIDs::kApplication; - break; - default: - *outFamilyID = ms_fontPresets[preset].m_familyID; - break; - } - } + *outFamilyID = ms_fontPresets[preset].m_familyID; } - bool FontManagerImpl::FindOrReserveCacheSlot(int cacheID, int size, bool aa, CachedRenderedFont *&outCacheSlot, RenderedFont *&outRF) + bool FontManagerImpl::FindOrReserveCacheSlot(int cacheID, int size, bool aa, int flags, CachedRenderedFont *&outCacheSlot, RenderedFont *&outRF) { CachedRenderedFont *newCacheSlot = &m_cachedRenderedFonts[0]; @@ -168,7 +161,7 @@ namespace PortabilityLayer break; } - if (crf.m_fontCacheID == cacheID && crf.m_size == size && crf.m_aa == aa) + if (crf.m_fontCacheID == cacheID && crf.m_size == size && crf.m_aa == aa && crf.m_flags == flags) { crf.m_lastUsage = m_usageCounter; RenderedFont *rf = crf.m_rfont; @@ -199,6 +192,7 @@ namespace PortabilityLayer cacheSlot.m_size = size; cacheSlot.m_rfont = rfont; cacheSlot.m_aa = aa; + cacheSlot.m_flags = flags; if (m_usageCounter == UINT32_MAX) ResetUsageCounter(); @@ -206,44 +200,49 @@ namespace PortabilityLayer m_usageCounter++; } - RenderedFont *FontManagerImpl::GetRenderedFontFromFamily(FontFamily *fontFamily, int size, bool aa, int flags) + RenderedFont *FontManagerImpl::LoadAndRenderFontUsingFontHandler(FontFamily *fontFamily, int size, bool aa, int flags) { PortabilityLayer::FontManager *fm = PortabilityLayer::FontManager::GetInstance(); - RenderedFont *rfont = nullptr; - CachedRenderedFont *cacheSlot = nullptr; - FontFamilyID_t familyID = fontFamily->GetFamilyID(); - - if (this->FindOrReserveCacheSlot(familyID, size, aa, cacheSlot, rfont)) - return rfont; - - rfont = fm->LoadCachedRenderedFont(familyID, size, aa, flags); - if (rfont) - { - ReplaceCachedRenderedFont(*cacheSlot, rfont, familyID, size, aa, flags); - return rfont; - } - const int variation = fontFamily->GetVariationForFlags(flags); IGpFont *hostFont = fontFamily->GetFontForVariation(variation); if (!hostFont) return nullptr; - - rfont = FontRenderer::GetInstance()->RenderFont(hostFont, size, aa, fontFamily->GetHacksForVariation(variation)); - if (rfont) - { - ReplaceCachedRenderedFont(*cacheSlot, rfont, familyID, size, aa, flags); - - return rfont; - } + RenderedFont *rfont = FontRenderer::GetInstance()->RenderFont(hostFont, size, aa, fontFamily->GetHacksForVariation(variation)); + fontFamily->UnloadVariation(variation); return rfont; } RenderedFont *FontManagerImpl::LoadCachedRenderedFont(FontFamilyID_t familyID, int size, bool aa, int flags) { + CachedRenderedFont *cacheSlot = nullptr; + RenderedFont *rfont = nullptr; + + if (this->FindOrReserveCacheSlot(familyID, size, aa, flags, cacheSlot, rfont)) + return rfont; + + rfont = LoadAndRenderFont(familyID, size, aa, flags); + if (rfont) + ReplaceCachedRenderedFont(*cacheSlot, rfont, familyID, size, aa, flags); + + return rfont; + } + + RenderedFont *FontManagerImpl::LoadAndRenderFont(FontFamilyID_t familyID, int size, bool aa, int flags) + { + FontFamily *fontFamily = this->GetFont(familyID); + + RenderedFont *rfont = nullptr; + if (PLDrivers::GetFontHandler() != nullptr) + { + rfont = LoadAndRenderFontUsingFontHandler(fontFamily, size, aa, flags); + if (rfont != nullptr) + return rfont; + } + if (!m_fontArchive) { m_fontArchiveFile = PortabilityLayer::FileManager::GetInstance()->OpenCompositeFile(VirtualDirectories::kApplicationData, PSTR("Fonts")); @@ -266,12 +265,17 @@ namespace PortabilityLayer } } - FontFamily *fontFamily = this->GetFont(familyID); int variation = fontFamily->GetVariationForFlags(flags); FontHacks hacks = FontHacks_None; + VirtualDirectory_t vDir = VirtualDirectories::kUnspecified; const char *path = nullptr; - if (!fontFamily->GetFontSpec(variation, hacks, path)) + int typeFaceIndex = 0; + if (!fontFamily->GetFontSpec(variation, hacks, vDir, path, typeFaceIndex)) + return nullptr; + + // Only single TTF fonts are supported by the prerendered font system currently + if (vDir != VirtualDirectories::kFonts || typeFaceIndex != 0) return nullptr; size_t pathLen = strlen(path); @@ -328,13 +332,13 @@ namespace PortabilityLayer return nullptr; THandle res = m_fontArchive->LoadResource('RFNT', 1000 + static_cast(fontIndex)); - if (!res) - return nullptr; + if (res) + { + PortabilityLayer::MemReaderStream stream(*res, res.MMBlock()->m_size); - PortabilityLayer::MemReaderStream stream(*res, res.MMBlock()->m_size); - - RenderedFont *rfont = PortabilityLayer::FontRenderer::GetInstance()->LoadCache(&stream); - res.Dispose(); + rfont = PortabilityLayer::FontRenderer::GetInstance()->LoadCache(&stream); + res.Dispose(); + } return rfont; } @@ -356,6 +360,7 @@ namespace PortabilityLayer FontManagerImpl::FontManagerImpl() : m_fontArchive(nullptr) , m_fontArchiveFile(nullptr) + , m_hasPreinstalledFonts(false) { for (int fid = 0; fid < FontFamilyIDs::kCount; fid++) m_fontFamilies[fid] = nullptr; @@ -409,11 +414,12 @@ namespace PortabilityLayer { FontFamilyIDs::kApplication, 8, FontFamilyFlag_None, true }, { FontFamilyIDs::kApplication, 9, FontFamilyFlag_None, true }, - { FontFamilyIDs::kApplication, 9, FontFamilyFlag_Bold, true }, - { FontFamilyIDs::kApplication, 10, FontFamilyFlag_Bold, true }, + { FontFamilyIDs::kApplication, 9, FontFamilyFlag_SyntheticBold, true }, + { FontFamilyIDs::kApplication, 10, FontFamilyFlag_SyntheticBold, true }, { FontFamilyIDs::kApplication, 12, FontFamilyFlag_Bold, true }, + { FontFamilyIDs::kApplication, 12, FontFamilyFlag_SyntheticBold, true }, { FontFamilyIDs::kApplication, 14, FontFamilyFlag_None, true }, - { FontFamilyIDs::kApplication, 14, FontFamilyFlag_Bold, true }, + { FontFamilyIDs::kApplication, 14, FontFamilyFlag_SyntheticBold, true }, { FontFamilyIDs::kApplication, 18, FontFamilyFlag_None, true }, { FontFamilyIDs::kApplication, 40, FontFamilyFlag_None, true }, diff --git a/PortabilityLayer/FontManager.h b/PortabilityLayer/FontManager.h index 8c281bd..9dacc93 100644 --- a/PortabilityLayer/FontManager.h +++ b/PortabilityLayer/FontManager.h @@ -2,6 +2,7 @@ #include "FontHacks.h" #include "FontFamilyID.h" +#include "FontPresets.h" struct IGpFont; @@ -10,34 +11,6 @@ namespace PortabilityLayer class FontFamily; class RenderedFont; - namespace FontPresets - { - enum FontPreset - { - kSystem12, - kSystem12Bold, - - kApplication8, - kApplication9, - kApplication9Bold, - kApplication10Bold, - kApplication12Bold, - kApplication14, - kApplication14Bold, - kApplication18, - kApplication40, - - kMono10, - - kHandwriting24, - kHandwriting48, - - kCount, - }; - } - - typedef FontPresets::FontPreset FontPreset_t; - class FontManager { public: @@ -47,8 +20,6 @@ namespace PortabilityLayer virtual FontFamily *GetFont(FontFamilyID_t fontFamilyID) const = 0; virtual void GetFontPreset(FontPreset_t fontPreset, FontFamilyID_t *outFamilyID, int *outSize, int *outVariationFlags, bool *outAA) const = 0; - virtual RenderedFont *GetRenderedFontFromFamily(FontFamily *fontFamily, int fontSize, bool aa, int flags) = 0; - virtual RenderedFont *LoadCachedRenderedFont(FontFamilyID_t familyID, int size, bool aa, int flags) = 0; virtual void PurgeCache() = 0; diff --git a/PortabilityLayer/FontPresets.h b/PortabilityLayer/FontPresets.h new file mode 100644 index 0000000..33257a0 --- /dev/null +++ b/PortabilityLayer/FontPresets.h @@ -0,0 +1,33 @@ +#pragma once + +namespace PortabilityLayer +{ + namespace FontPresets + { + enum FontPreset + { + kSystem12, + kSystem12Bold, + + kApplication8, + kApplication9, + kApplication9SyntheticBold, + kApplication10SyntheticBold, + kApplication12Bold, + kApplication12SyntheticBold, + kApplication14, + kApplication14SyntheticBold, + kApplication18, + kApplication40, + + kMono10, + + kHandwriting24, + kHandwriting48, + + kCount, + }; + } + + typedef FontPresets::FontPreset FontPreset_t; +} diff --git a/PortabilityLayer/FontRenderer.cpp b/PortabilityLayer/FontRenderer.cpp index 5cfef15..82c6c90 100644 --- a/PortabilityLayer/FontRenderer.cpp +++ b/PortabilityLayer/FontRenderer.cpp @@ -11,6 +11,7 @@ #include "GpRenderedGlyphMetrics.h" #include "PLBigEndian.h" +#include "PLCore.h" #include "PLDrivers.h" #include "PLPasStr.h" #include "DeflateCodec.h" @@ -59,6 +60,8 @@ namespace PortabilityLayer BEInt16_t m_bearingX; BEInt16_t m_bearingY; BEInt16_t m_advanceX; + BEInt16_t m_bitmapOffsetX; + BEInt16_t m_bitmapOffsetY; }; struct SerializedFontMetrics @@ -101,9 +104,31 @@ namespace PortabilityLayer static FontRendererImpl *GetInstance(); private: + static void SynthesizeBoldAA(IGpFontRenderedGlyph *&glyph, unsigned int xScale, unsigned int yScale, bool aa, uint8_t character, int size, FontHacks fontHacks); + static FontRendererImpl ms_instance; }; + class ReRenderedGlyph final : public IGpFontRenderedGlyph + { + public: + const GpRenderedGlyphMetrics &GetMetrics() const override; + const void *GetData() const override; + void Destroy() override; + + void *GetMutableData(); + GpRenderedGlyphMetrics &GetMutableMetrics(); + + static ReRenderedGlyph *Create(unsigned int width, unsigned int height, bool aa); + + private: + explicit ReRenderedGlyph(void *data, unsigned int width, unsigned int height, size_t pitch, size_t dataSize); + + GpRenderedGlyphMetrics m_metrics; + void *m_data; + size_t m_dataSize; + }; + bool RenderedFontImpl::GetGlyph(unsigned int character, const GpRenderedGlyphMetrics *&outMetricsPtr, const void *&outData) const { const size_t dataOffset = m_dataOffsets[character]; @@ -142,7 +167,7 @@ namespace PortabilityLayer void RenderedFontImpl::Destroy() { this->~RenderedFontImpl(); - free(this); + DisposePtr(this); } void RenderedFontImpl::SetCharData(unsigned int charID, const void *data, size_t dataOffset, const GpRenderedGlyphMetrics &metrics) @@ -227,7 +252,7 @@ namespace PortabilityLayer const size_t allocSize = alignedPrefixSize + glyphDataSize; - void *storage = malloc(allocSize); + void *storage = NewPtr(allocSize); if (!storage) return nullptr; @@ -293,6 +318,8 @@ namespace PortabilityLayer result.m_glyphDataPitch = static_cast(metrics.m_glyphDataPitch); result.m_glyphHeight = metrics.m_glyphHeight; result.m_glyphWidth = metrics.m_glyphWidth; + result.m_bitmapOffsetX = metrics.m_bitmapOffsetX; + result.m_bitmapOffsetY = metrics.m_bitmapOffsetY; return result; } @@ -306,6 +333,8 @@ namespace PortabilityLayer result.m_glyphDataPitch = static_cast(metrics.m_glyphDataPitch); result.m_glyphHeight = metrics.m_glyphHeight; result.m_glyphWidth = metrics.m_glyphWidth; + result.m_bitmapOffsetX = metrics.m_bitmapOffsetX; + result.m_bitmapOffsetY = metrics.m_bitmapOffsetY; return result; } @@ -347,13 +376,42 @@ namespace PortabilityLayer for (unsigned int i = 0; i < numCharacters; i++) glyphs[i] = nullptr; + bool isSyntheticBold = false; + if (fontHacks == FontHacks_SyntheticBold_OpenSans) + isSyntheticBold = true; + + unsigned int xScale = 1; + unsigned int yScale = 1; + bool syntheticBoldAA = false; + if (isSyntheticBold) + { + if (aa) + { + syntheticBoldAA = true; + xScale = 8; + yScale = 8; + } + } + for (unsigned int i = 0; i < numCharacters; i++) { uint16_t unicodeCodePoint = MacRoman::ToUnicode(i); if (unicodeCodePoint == 0xffff) continue; - glyphs[i] = font->Render(unicodeCodePoint, size, aa); + glyphs[i] = font->Render(unicodeCodePoint, size, xScale, yScale, aa); + } + + if (isSyntheticBold) + { + if (syntheticBoldAA) + { + for (unsigned int i = 0; i < numCharacters; i++) + { + if (glyphs[i]) + SynthesizeBoldAA(glyphs[i], xScale, yScale, syntheticBoldAA, i, size, fontHacks); + } + } } size_t glyphDataSize = GP_SYSTEM_MEMORY_ALIGNMENT; // So we can use 0 to mean no data @@ -401,6 +459,20 @@ namespace PortabilityLayer } } + /* + if (fontHacks == FontHacks_SyntheticBold_OpenSans && size == 12) + { + if (i == 'i') + metrics.m_bearingX++; + } + + if (fontHacks == FontHacks_SyntheticBold_OpenSans && size == 9) + { + if (i == 'V') + metrics.m_advanceX++; + } + */ + rfont->SetCharData(i, data, fillOffset, metrics); fillOffset += metrics.m_glyphDataPitch * metrics.m_glyphHeight; @@ -465,6 +537,137 @@ namespace PortabilityLayer return true; } + void FontRendererImpl::SynthesizeBoldAA(IGpFontRenderedGlyph *&glyph, unsigned int xScale, unsigned int yScale, bool aa, uint8_t character, int size, FontHacks fontHacks) + { + unsigned int extraWidth = 1; + + GpRenderedGlyphMetrics metrics = glyph->GetMetrics(); + const void *existingData = glyph->GetData(); + + uint32_t existingWidth = metrics.m_glyphWidth; + uint32_t existingHeight = metrics.m_glyphHeight; + + uint32_t leftPadding = 0; + uint32_t topPadding = 0; + + { + const int32_t leftCoord = metrics.m_bitmapOffsetX; + int32_t leftCoordRemainder = leftCoord % static_cast(xScale); + + if (leftCoordRemainder > 0) + leftPadding = leftCoordRemainder; + else if (leftCoordRemainder < 0) + leftPadding = leftCoordRemainder + static_cast(xScale); + + const int32_t topCoord = metrics.m_bitmapOffsetY; + int32_t topCoordRemainder = topCoord % static_cast(yScale); + + if (topCoordRemainder != 0) + { + if (topCoordRemainder < 0) + topCoordRemainder += static_cast(yScale); + + topPadding = static_cast(yScale) - topCoordRemainder; + } + } + + uint32_t paddedWidth = existingWidth + leftPadding; + uint32_t paddedHeight = existingHeight + topPadding; + + uint32_t newWidth = (paddedWidth + xScale - 1) / xScale + extraWidth; + uint32_t newHeight = (paddedHeight + yScale - 1) / yScale; + + ReRenderedGlyph *newGlyph = ReRenderedGlyph::Create(newWidth, newHeight, aa); + if (!newGlyph) + return; + + uint16_t *fattenAccumulateBuffer = static_cast(MemoryManager::GetInstance()->Alloc(newWidth * sizeof(uint16_t))); + if (!fattenAccumulateBuffer) + { + newGlyph->Destroy(); + return; + } + + GpRenderedGlyphMetrics &newMetrics = newGlyph->GetMutableMetrics(); + newMetrics.m_advanceX = metrics.m_advanceX + static_cast(extraWidth); + newMetrics.m_bearingX = (metrics.m_bitmapOffsetX - static_cast(leftPadding)) / static_cast(xScale); + newMetrics.m_bearingY = (metrics.m_bitmapOffsetY + static_cast(topPadding)) / static_cast(yScale); + newMetrics.m_bitmapOffsetX = newMetrics.m_bearingX; + newMetrics.m_bitmapOffsetY = newMetrics.m_bearingY; + + const size_t existingDataPitch = metrics.m_glyphDataPitch; + const size_t newPitch = newMetrics.m_glyphDataPitch; + uint8_t *newData = static_cast(newGlyph->GetMutableData()); + + for (unsigned int outY = 0; outY < newHeight; outY++) + { + memset(fattenAccumulateBuffer, 0, newWidth * sizeof(uint16_t)); + + for (unsigned int subY = 0; subY < yScale; subY++) + { + uint32_t originalY = subY + outY * yScale; + if (originalY < topPadding) + continue; + + originalY -= topPadding; + if (originalY >= existingHeight) + break; + + const uint8_t *existingRow = static_cast(existingData) + originalY * existingDataPitch; + + unsigned int streakCounter = 0; + unsigned int outX = 0; + unsigned int outSubX = 0; + for (unsigned int unpaddedOriginalX = 0; unpaddedOriginalX < newWidth * xScale; unpaddedOriginalX++) + { + if (unpaddedOriginalX > leftPadding) + { + uint32_t originalX = unpaddedOriginalX - leftPadding; + + if (originalX < existingWidth) + { + //if (existingRow[originalX / 8] & (1 << (originalX & 7))) + uint8_t v = ((existingRow[originalX / 2] >> ((originalX & 1) * 4)) & 0xf); + if (v >= 8) + streakCounter = xScale + 1; + } + } + + if (streakCounter > 0) + { + streakCounter--; + fattenAccumulateBuffer[outX]++; + } + + outSubX++; + if (outSubX == xScale) + { + outSubX = 0; + outX++; + } + } + } + + uint8_t *outRow = newData + outY * newPitch; + unsigned int divisor = xScale * yScale; + for (unsigned int x = 0; x < newWidth; x++) + { + uint32_t fraction = static_cast(fattenAccumulateBuffer[x]) * 15; + fraction = (fraction * 2 + divisor) / (divisor * 2); + + uint8_t *outByte = outRow + (x / 2); + (*outByte) |= fraction << ((x & 1) * 4); + + size_t outOffset = outByte - newData; + } + } + + MemoryManager::GetInstance()->Release(fattenAccumulateBuffer); + + glyph->Destroy(); + glyph = newGlyph; + } + FontRendererImpl *FontRendererImpl::GetInstance() { return &ms_instance; @@ -472,6 +675,67 @@ namespace PortabilityLayer FontRendererImpl FontRendererImpl::ms_instance; + const GpRenderedGlyphMetrics &ReRenderedGlyph::GetMetrics() const + { + return m_metrics; + } + + const void *ReRenderedGlyph::GetData() const + { + return m_data; + } + + void ReRenderedGlyph::Destroy() + { + this->~ReRenderedGlyph(); + PortabilityLayer::MemoryManager::GetInstance()->Release(this); + } + + void *ReRenderedGlyph::GetMutableData() + { + return m_data; + } + + GpRenderedGlyphMetrics &ReRenderedGlyph::GetMutableMetrics() + { + return m_metrics; + } + + ReRenderedGlyph *ReRenderedGlyph::Create(unsigned int width, unsigned int height, bool aa) + { + size_t pitchRequired = 0; + if (aa) + pitchRequired = (width + 1) / 2; + else + pitchRequired = (width + 7) / 8; + + pitchRequired = pitchRequired + (GP_SYSTEM_MEMORY_ALIGNMENT - 1); + pitchRequired -= pitchRequired % GP_SYSTEM_MEMORY_ALIGNMENT; + + size_t baseRequired = sizeof(ReRenderedGlyph); + baseRequired = baseRequired + (GP_SYSTEM_MEMORY_ALIGNMENT - 1); + baseRequired -= baseRequired % GP_SYSTEM_MEMORY_ALIGNMENT; + + size_t totalRequired = baseRequired + pitchRequired * height; + void *storage = MemoryManager::GetInstance()->Alloc(totalRequired); + if (!storage) + return nullptr; + + uint8_t *data = static_cast(storage) + baseRequired; + memset(data, 0, pitchRequired * height); + + return new (storage) ReRenderedGlyph(data, width, height, pitchRequired, totalRequired - baseRequired); + } + + ReRenderedGlyph::ReRenderedGlyph(void *data, unsigned int width, unsigned int height, size_t pitch, size_t dataSize) + : m_data(data) + , m_dataSize(dataSize) + { + m_metrics.m_glyphWidth = width; + m_metrics.m_glyphHeight = height; + m_metrics.m_glyphDataPitch = pitch; + } + FontRenderer *FontRenderer::GetInstance() { return FontRendererImpl::GetInstance(); diff --git a/PortabilityLayer/InflateStream.cpp b/PortabilityLayer/InflateStream.cpp index a05d653..619a65c 100644 --- a/PortabilityLayer/InflateStream.cpp +++ b/PortabilityLayer/InflateStream.cpp @@ -1,5 +1,6 @@ #include "InflateStream.h" #include "DeflateCodec.h" +#include "PLCore.h" #include #include @@ -22,7 +23,7 @@ namespace PortabilityLayer bool SeekEnd(GpUFilePos_t loc) override; GpUFilePos_t Size() const override; GpUFilePos_t Tell() const override; - void Close() override; + void GP_ASYNCIFY_PARANOID_NAMED(Close)() override; void Flush() override; private: @@ -222,10 +223,10 @@ namespace PortabilityLayer return m_decompressedPos; } - void InflateStreamImpl::Close() + void InflateStreamImpl::GP_ASYNCIFY_PARANOID_NAMED(Close)() { this->~InflateStreamImpl(); - free(this); + DisposePtr(this); } void InflateStreamImpl::Flush() @@ -238,7 +239,7 @@ namespace PortabilityLayer if (!inflateContext) return nullptr; - void *storage = malloc(sizeof(InflateStreamImpl)); + void *storage = NewPtr(sizeof(InflateStreamImpl)); if (!storage) { inflateContext->Destroy(); diff --git a/PortabilityLayer/MMBlock.cpp b/PortabilityLayer/MMBlock.cpp deleted file mode 100644 index 3902d6e..0000000 --- a/PortabilityLayer/MMBlock.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "MMBlock.h" - -namespace PortabilityLayer -{ - size_t MMBlock::AlignedSize() - { - const size_t paddedSize = sizeof(MMBlock) + GP_SYSTEM_MEMORY_ALIGNMENT - 1; - const size_t paddedSizeTruncated = paddedSize - (paddedSize % GP_SYSTEM_MEMORY_ALIGNMENT); - - return paddedSizeTruncated; - } -} diff --git a/PortabilityLayer/MMBlock.h b/PortabilityLayer/MMBlock.h deleted file mode 100644 index 7e9ef0c..0000000 --- a/PortabilityLayer/MMBlock.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#ifndef __PL_MM_BLOCK_H__ -#define __PL_MM_BLOCK_H__ - -#include - -#include "CoreDefs.h" -#include "SmallestInt.h" - -namespace PortabilityLayer -{ - struct MMBlock - { - SmallestUInt::ValueType_t m_offsetFromAllocLocation; - - static size_t AlignedSize(); - }; -} - -#endif diff --git a/PortabilityLayer/MemReaderStream.cpp b/PortabilityLayer/MemReaderStream.cpp index cf051b6..9d5aad8 100644 --- a/PortabilityLayer/MemReaderStream.cpp +++ b/PortabilityLayer/MemReaderStream.cpp @@ -104,7 +104,7 @@ namespace PortabilityLayer return static_cast(m_loc); } - void MemReaderStream::Close() + void MemReaderStream::GP_ASYNCIFY_PARANOID_NAMED(Close)() { } @@ -128,7 +128,7 @@ namespace PortabilityLayer return new (storage) MemBufferReaderStream(buffer, size); } - void MemBufferReaderStream::Close() + void MemBufferReaderStream::GP_ASYNCIFY_PARANOID_NAMED(Close)() { this->~MemBufferReaderStream(); MemoryManager::GetInstance()->Release(this); diff --git a/PortabilityLayer/MemReaderStream.h b/PortabilityLayer/MemReaderStream.h index b73dc9b..35f0dc7 100644 --- a/PortabilityLayer/MemReaderStream.h +++ b/PortabilityLayer/MemReaderStream.h @@ -23,7 +23,7 @@ namespace PortabilityLayer bool SeekEnd(GpUFilePos_t loc) override; GpUFilePos_t Size() const override; GpUFilePos_t Tell() const override; - void Close() override; + void GP_ASYNCIFY_PARANOID_NAMED(Close)() override; void Flush() override; private: @@ -41,7 +41,7 @@ namespace PortabilityLayer static MemBufferReaderStream *Create(void *buffer, size_t size); - void Close() override; + void GP_ASYNCIFY_PARANOID_NAMED(Close)() override; private: MemBufferReaderStream() GP_DELETED; diff --git a/PortabilityLayer/MemoryManager.cpp b/PortabilityLayer/MemoryManager.cpp index 5697df2..6fba318 100644 --- a/PortabilityLayer/MemoryManager.cpp +++ b/PortabilityLayer/MemoryManager.cpp @@ -1,8 +1,9 @@ #include "MemoryManager.h" -#include "MMBlock.h" #include "MMHandleBlock.h" #include "ResourceCompiledRef.h" #include "ResourceManager.h" +#include "IGpAllocator.h" +#include "PLDrivers.h" #include #include @@ -28,7 +29,6 @@ namespace PortabilityLayer static MemoryManagerImpl *GetInstance(); private: - static MemoryManagerImpl ms_instance; }; @@ -42,75 +42,17 @@ namespace PortabilityLayer void *MemoryManagerImpl::Realloc(void *buf, size_t newSize) { - assert(buf != nullptr); - - const size_t mmBlockSize = MMBlock::AlignedSize(); - uint8_t *oldBufBytes = static_cast(buf); - const MMBlock *oldBufMMBlock = reinterpret_cast(oldBufBytes - MMBlock::AlignedSize()); - - const size_t oldBufOffsetFromAlignLoc = oldBufMMBlock->m_offsetFromAllocLocation; - uint8_t *oldBufBase = oldBufBytes - MMBlock::AlignedSize() - oldBufOffsetFromAlignLoc; - - const size_t mmBlockSizeWithMaxPadding = MMBlock::AlignedSize() + GP_SYSTEM_MEMORY_ALIGNMENT - 1; - if (SIZE_MAX - newSize < mmBlockSizeWithMaxPadding) - return nullptr; - - const size_t newBufferSize = newSize + mmBlockSizeWithMaxPadding; - uint8_t *newBuffer = static_cast(realloc(oldBufBase, newSize + mmBlockSizeWithMaxPadding)); - if (!newBuffer) - return nullptr; - - const intptr_t offsetFromAlignPoint = reinterpret_cast(newBuffer) & static_cast(GP_SYSTEM_MEMORY_ALIGNMENT - 1); - intptr_t alignPadding = 0; - if (offsetFromAlignPoint != 0) - alignPadding = static_cast(GP_SYSTEM_MEMORY_ALIGNMENT) - offsetFromAlignPoint; - - // Check if the alignment changed, if so relocate - if (static_cast(alignPadding) != oldBufOffsetFromAlignLoc) - memmove(newBuffer + alignPadding, newBuffer + oldBufOffsetFromAlignLoc, MMBlock::AlignedSize() + newSize); - - MMBlock *newMMBlock = reinterpret_cast(newBuffer + alignPadding); - newMMBlock->m_offsetFromAllocLocation = static_cast::ValueType_t>(alignPadding); - - return newBuffer + alignPadding + MMBlock::AlignedSize(); + return PLDrivers::GetAlloc()->Realloc(buf, newSize); } void *MemoryManagerImpl::Alloc(size_t size) { - if (size == 0) - return nullptr; - - const size_t mmBlockSizeWithMaxPadding = MMBlock::AlignedSize() + GP_SYSTEM_MEMORY_ALIGNMENT - 1; - if (SIZE_MAX - size < mmBlockSizeWithMaxPadding) - return nullptr; - - uint8_t *buffer = static_cast(malloc(size + mmBlockSizeWithMaxPadding)); - if (!buffer) - return nullptr; - - const intptr_t offsetFromAlignPoint = reinterpret_cast(buffer) & static_cast(GP_SYSTEM_MEMORY_ALIGNMENT - 1); - intptr_t alignPadding = 0; - if (offsetFromAlignPoint != 0) - alignPadding = static_cast(GP_SYSTEM_MEMORY_ALIGNMENT) - offsetFromAlignPoint; - - MMBlock *mmBlock = reinterpret_cast(buffer + alignPadding); - mmBlock->m_offsetFromAllocLocation = static_cast::ValueType_t>(alignPadding); - - return buffer + alignPadding + MMBlock::AlignedSize(); + return PLDrivers::GetAlloc()->Realloc(nullptr, size); } void MemoryManagerImpl::Release(void *buf) { - if (!buf) - return; - - const size_t mmBlockSize = MMBlock::AlignedSize(); - - uint8_t *bytes = static_cast(buf); - const MMBlock *mmBlock = reinterpret_cast(bytes - MMBlock::AlignedSize()); - - void *freeLoc = bytes - MMBlock::AlignedSize() - mmBlock->m_offsetFromAllocLocation; - free(freeLoc); + PLDrivers::GetAlloc()->Realloc(buf, 0); } MMHandleBlock *MemoryManagerImpl::AllocHandle(size_t size) diff --git a/PortabilityLayer/MemoryManager.h b/PortabilityLayer/MemoryManager.h index 5d56fe4..0b0baf2 100644 --- a/PortabilityLayer/MemoryManager.h +++ b/PortabilityLayer/MemoryManager.h @@ -1,10 +1,10 @@ #pragma once -#ifndef __PL_MEMORY_MANAGER_H__ -#define __PL_MEMORY_MANAGER_H__ #include #include +struct IGpAllocator; + namespace PortabilityLayer { struct MMHandleBlock; @@ -50,5 +50,3 @@ namespace PortabilityLayer return objectHdl; } } - -#endif diff --git a/PortabilityLayer/MenuManager.cpp b/PortabilityLayer/MenuManager.cpp index a2b565e..7ba0c94 100644 --- a/PortabilityLayer/MenuManager.cpp +++ b/PortabilityLayer/MenuManager.cpp @@ -155,7 +155,7 @@ namespace PortabilityLayer bool FindMenuShortcut(uint16_t &menuID, uint16_t &itemID, uint8_t shortcutChar) override; void MenuSelect(const Vec2i &initialPoint, int16_t *outMenu, uint16_t *outItem) GP_ASYNCIFY_PARANOID_OVERRIDE; - void PopupMenuSelect(const THandle &menu, const Vec2i &popupMenuPos, const Vec2i &initialPoint, size_t initialItem, uint16_t *outItem) override; + void PopupMenuSelect(const THandle &menu, const Vec2i &popupMenuPos, const Vec2i &initialPoint, size_t initialItem, uint16_t *outItem) GP_ASYNCIFY_PARANOID_OVERRIDE; void DrawMenuBar() override; void SetMenuVisible(bool isVisible) override; @@ -288,7 +288,7 @@ namespace PortabilityLayer if (m_iconGraphic) { m_iconGraphic->~SimpleGraphic(); - free(m_iconGraphic); + DisposePtr(m_iconGraphic); } // GP TODO: Dispose of menus properly @@ -776,7 +776,14 @@ namespace PortabilityLayer bool canDismiss = false; while (!canDismiss) { - if (WaitForEvent(&evt, 1)) + bool haveEvent = false; + + { + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); + haveEvent = WaitForEvent(&evt, 1); + } + + if (haveEvent) { if (evt.m_vosEvent.m_eventType == GpVOSEventTypes::kMouseInput) { @@ -827,7 +834,7 @@ namespace PortabilityLayer { typedef SimpleGraphicInstanceStandardPalette<16, 16> GraphicType_t; - void *storage = static_cast(malloc(sizeof(GraphicType_t))); + void *storage = static_cast(NewPtr(sizeof(GraphicType_t))); if (storage) { memcpy(m_iconMask, static_cast(*icsHandle) + 32, 32); @@ -1589,5 +1596,10 @@ namespace PortabilityLayer { static_cast(this)->MenuSelect(initialPoint, outMenu, outItem); } + + void MenuManager::PopupMenuSelect(const THandle &menu, const Vec2i &popupMenuPos, const Vec2i &initialPoint, size_t initialItem, uint16_t *outItem) + { + static_cast(this)->PopupMenuSelect(menu, popupMenuPos, initialPoint, initialItem, outItem); + } #endif } diff --git a/PortabilityLayer/MenuManager.h b/PortabilityLayer/MenuManager.h index cf66c6d..638cc34 100644 --- a/PortabilityLayer/MenuManager.h +++ b/PortabilityLayer/MenuManager.h @@ -50,7 +50,7 @@ namespace PortabilityLayer virtual bool FindMenuShortcut(uint16_t &menuID, uint16_t &itemID, uint8_t shortcutChar) = 0; GP_ASYNCIFY_PARANOID_VIRTUAL void MenuSelect(const Vec2i &initialPoint, int16_t *outMenu, uint16_t *outItem) GP_ASYNCIFY_PARANOID_PURE; - virtual void PopupMenuSelect(const THandle &menu, const Vec2i &popupMenuPos, const Vec2i &initialPoint, size_t initialItem, uint16_t *outItem) = 0; + GP_ASYNCIFY_PARANOID_VIRTUAL void PopupMenuSelect(const THandle &menu, const Vec2i &popupMenuPos, const Vec2i &initialPoint, size_t initialItem, uint16_t *outItem) GP_ASYNCIFY_PARANOID_PURE; virtual void DrawMenuBar() = 0; virtual void SetMenuVisible(bool isVisible) = 0; diff --git a/PortabilityLayer/PLCore.cpp b/PortabilityLayer/PLCore.cpp index 29d203e..53a4e77 100644 --- a/PortabilityLayer/PLCore.cpp +++ b/PortabilityLayer/PLCore.cpp @@ -46,7 +46,7 @@ #include "PLTimeTaggedVOSEvent.h" #include "PLWidgets.h" -#include "UTF8.h" +#include "GpUnicode.h" #include #include @@ -515,6 +515,12 @@ Boolean WaitMouseUp() return isDown; } +Boolean WaitMouseUp_DisarmAsyncify() +{ + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); + return WaitMouseUp(); +} + short Random() { // Should return with range -32767..32767 @@ -685,12 +691,12 @@ PLClipboardContentsText *PLClipboardContentsText::CreateFromMacRomanStr(const ui for (size_t i = 0; i < length; i++) { - uint8_t utf8Bytes[PortabilityLayer::UTF8Processor::kMaxEncodedBytes]; + uint8_t utf8Bytes[GpUnicode::UTF8::kMaxEncodedBytes]; uint16_t codePoint = MacRoman::ToUnicode(chars[i]); size_t numBytesEmitted = 0; - PortabilityLayer::UTF8Processor::EncodeCodePoint(utf8Bytes, numBytesEmitted, codePoint); + GpUnicode::UTF8::Encode(utf8Bytes, numBytesEmitted, codePoint); numUTF8Bytes += numBytesEmitted; } @@ -709,7 +715,7 @@ PLClipboardContentsText *PLClipboardContentsText::CreateFromMacRomanStr(const ui uint16_t codePoint = MacRoman::ToUnicode(chars[i]); size_t numBytesEmitted = 0; - PortabilityLayer::UTF8Processor::EncodeCodePoint(utf8Bytes + numUTF8Bytes, numBytesEmitted, codePoint); + GpUnicode::UTF8::Encode(utf8Bytes + numUTF8Bytes, numBytesEmitted, codePoint); numUTF8Bytes += numBytesEmitted; } diff --git a/PortabilityLayer/PLCore.h b/PortabilityLayer/PLCore.h index 5d95872..50e2af2 100644 --- a/PortabilityLayer/PLCore.h +++ b/PortabilityLayer/PLCore.h @@ -249,6 +249,7 @@ void DisposeDirectoryFiles(DirectoryFileListEntry *firstDFL); void GetMouse(Window *window, Point *point); Boolean StillDown(); Boolean WaitMouseUp(); +Boolean WaitMouseUp_DisarmAsyncify(); short Random(); void GetTime(DateTimeRec *dateTime); diff --git a/PortabilityLayer/PLDrivers.cpp b/PortabilityLayer/PLDrivers.cpp index 57f5dd0..d3a36a6 100644 --- a/PortabilityLayer/PLDrivers.cpp +++ b/PortabilityLayer/PLDrivers.cpp @@ -50,4 +50,10 @@ IGpVOSEventQueue *PLDrivers::GetVOSEventQueue() return ms_drivers.GetDriver(); } +IGpAllocator *PLDrivers::GetAlloc() +{ + return ms_drivers.GetDriver(); +} + + GpDriverCollection PLDrivers::ms_drivers; diff --git a/PortabilityLayer/PLDrivers.h b/PortabilityLayer/PLDrivers.h index e5b9e13..5d410ae 100644 --- a/PortabilityLayer/PLDrivers.h +++ b/PortabilityLayer/PLDrivers.h @@ -1,9 +1,9 @@ -#pragma once +#pragma once #include "GpDriverIndex.h" class PLDrivers -{ +{ public: static GpDriverCollection *GetDriverCollection(); @@ -16,6 +16,7 @@ public: static IGpSystemServices *GetSystemServices(); static IGpFontHandler *GetFontHandler(); static IGpVOSEventQueue *GetVOSEventQueue(); + static IGpAllocator *GetAlloc(); private: static GpDriverCollection ms_drivers; diff --git a/PortabilityLayer/PLEditboxWidget.cpp b/PortabilityLayer/PLEditboxWidget.cpp index 59fc22f..180c35c 100644 --- a/PortabilityLayer/PLEditboxWidget.cpp +++ b/PortabilityLayer/PLEditboxWidget.cpp @@ -12,7 +12,7 @@ #include "ResolveCachingColor.h" #include "Rect2i.h" #include "TextPlacer.h" -#include "UTF8.h" +#include "GpUnicode.h" #include "PLDrivers.h" #include "PLKeyEncoding.h" @@ -721,7 +721,7 @@ namespace PortabilityLayer { uint32_t codePoint = 0; size_t numDigested = 0; - if (!UTF8Processor::DecodeCodePoint(utf8Bytes + i, utf8Size - i, numDigested, codePoint)) + if (!GpUnicode::UTF8::Decode(utf8Bytes + i, utf8Size - i, numDigested, codePoint)) { clipboardContents->Destroy(); return; @@ -745,7 +745,7 @@ namespace PortabilityLayer { uint32_t codePoint = 0; size_t numDigested = 0; - if (!UTF8Processor::DecodeCodePoint(utf8Bytes + i, utf8Size - i, numDigested, codePoint)) + if (!GpUnicode::UTF8::Decode(utf8Bytes + i, utf8Size - i, numDigested, codePoint)) { clipboardContents->Destroy(); return; @@ -1330,16 +1330,19 @@ namespace PortabilityLayer return ccs->m_category; } - FontFamily *EditboxWidget::GetFontFamily() const + FontPreset_t EditboxWidget::GetFontPreset() const { - FontFamilyID_t preset = FontFamilyIDs::kCount; - PortabilityLayer::FontManager::GetInstance()->GetFontPreset(FontPresets::kSystem12, &preset, nullptr, nullptr, nullptr); - return PortabilityLayer::FontManager::GetInstance()->GetFont(preset); + return FontPresets::kSystem12; } RenderedFont *EditboxWidget::GetRenderedFont() const { - return PortabilityLayer::FontManager::GetInstance()->GetRenderedFontFromFamily(GetFontFamily(), 12, true, FontFamilyFlag_None); + PortabilityLayer::FontFamilyID_t fontFamilyID = FontFamilyIDs::kCount; + int size = 0; + int varFlags = 0; + bool aa = false; + PortabilityLayer::FontManager::GetInstance()->GetFontPreset(GetFontPreset(), &fontFamilyID, &size, &varFlags, &aa); + return PortabilityLayer::FontManager::GetInstance()->LoadCachedRenderedFont(fontFamilyID, size, aa, varFlags); } void EditboxWidget::SetMultiLine(bool isMultiLine) diff --git a/PortabilityLayer/PLEditboxWidget.h b/PortabilityLayer/PLEditboxWidget.h index b45ad8f..e60f7fa 100644 --- a/PortabilityLayer/PLEditboxWidget.h +++ b/PortabilityLayer/PLEditboxWidget.h @@ -1,5 +1,6 @@ #pragma once +#include "FontPresets.h" #include "PascalStr.h" #include "PLWidgets.h" #include "Vec2i.h" @@ -111,7 +112,7 @@ namespace PortabilityLayer size_t IdentifySpanLength(size_t startChar, SpanScanDirection scanDirection) const; static CharacterCategory CategorizeCharacter(uint8_t character); - PortabilityLayer::FontFamily *GetFontFamily() const; + PortabilityLayer::FontPreset_t GetFontPreset() const; PortabilityLayer::RenderedFont *GetRenderedFont() const; uint8_t *m_chars; diff --git a/PortabilityLayer/PLQDraw.cpp b/PortabilityLayer/PLQDraw.cpp index 226a56c..0ca50f8 100644 --- a/PortabilityLayer/PLQDraw.cpp +++ b/PortabilityLayer/PLQDraw.cpp @@ -2016,7 +2016,7 @@ PortabilityLayer::RenderedFont *GetFont(PortabilityLayer::FontPreset_t fontPrese if (familyID == PortabilityLayer::FontFamilyIDs::kCount) return nullptr; - return fontManager->GetRenderedFontFromFamily(fontManager->GetFont(familyID), size, aa, variationFlags); + return fontManager->LoadCachedRenderedFont(familyID, size, aa, variationFlags); } #include "stb_image_write.h" diff --git a/PortabilityLayer/PLResourceManager.cpp b/PortabilityLayer/PLResourceManager.cpp index 5443f00..bd685dc 100644 --- a/PortabilityLayer/PLResourceManager.cpp +++ b/PortabilityLayer/PLResourceManager.cpp @@ -81,8 +81,7 @@ namespace if (infoHeader.m_thisStructureSize > sizeForInfoHeader) return false; - // Dimensions need to fit in 16-bit signed space - if (infoHeader.m_width >= 0x8000 || infoHeader.m_height >= 0x8000) + if (infoHeader.m_width >= 0x1000 || infoHeader.m_height >= 0x1000 || infoHeader.m_width < 1 || infoHeader.m_height < 1) return false; return true; @@ -116,7 +115,7 @@ namespace PortabilityLayer IResourceArchive *GetAppResourceArchive() const override; IResourceArchive *LoadResFile(CompositeFile *file) const override; - PLError_t CreateBlankResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) override; + PLError_t CreateBlankResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) GP_ASYNCIFY_PARANOID_OVERRIDE; void DissociateHandle(MMHandleBlock *hdl) const override; const ResourceArchiveRef *ResourceForHandle(MMHandleBlock *hdl) const override; @@ -524,4 +523,11 @@ namespace PortabilityLayer if (m_stream) m_stream->Close(); } + +#if GP_ASYNCIFY_PARANOID + PLError_t ResourceManager::CreateBlankResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) + { + return static_cast(this)->CreateBlankResFile(virtualDir, filename); + } +#endif } diff --git a/PortabilityLayer/PLSound.cpp b/PortabilityLayer/PLSound.cpp index ade717d..9b9b0fa 100644 --- a/PortabilityLayer/PLSound.cpp +++ b/PortabilityLayer/PLSound.cpp @@ -1,6 +1,7 @@ #include "PLSound.h" #include "MemoryManager.h" +#include "IGpAudioBuffer.h" #include "IGpMutex.h" #include "IGpThreadEvent.h" #include "IGpAudioChannel.h" @@ -30,7 +31,7 @@ namespace PortabilityLayer { union AudioCommandParam { - const void *m_ptr; + IGpAudioBuffer *m_buffer; AudioChannelCallback_t m_callback; }; @@ -45,7 +46,7 @@ namespace PortabilityLayer ~AudioChannelImpl(); void Destroy(bool wait) override; - bool AddBuffer(const void *lengthTaggedBuffer, bool blocking) override; + bool AddBuffer(IGpAudioBuffer *buffer, bool blocking) override; bool AddCallback(AudioChannelCallback_t callback, bool blocking) override; void ClearAllCommands() override; void Stop() override; @@ -70,7 +71,7 @@ namespace PortabilityLayer static const unsigned int kMaxQueuedCommands = 64; void DigestQueueItems(); - void DigestBufferCommand(const void *dataPointer); + void DigestBufferCommand(IGpAudioBuffer *buffer); IGpAudioChannel *m_audioChannel; @@ -103,6 +104,16 @@ namespace PortabilityLayer m_mutex->Destroy(); m_threadEvent->Destroy(); m_audioChannel->Destroy(); + + while (m_numQueuedCommands) + { + const AudioCommand &command = m_commandQueue[m_nextDequeueCommandPos]; + m_numQueuedCommands--; + m_nextDequeueCommandPos = (m_nextDequeueCommandPos + 1) % static_cast(kMaxQueuedCommands); + + if (command.m_commandType == AudioCommandTypes::kBuffer) + command.m_param.m_buffer->Release(); + } } void AudioChannelImpl::NotifyBufferFinished() @@ -167,20 +178,26 @@ namespace PortabilityLayer PortabilityLayer::MemoryManager::GetInstance()->Release(this); } - bool AudioChannelImpl::AddBuffer(const void *lengthTaggedBuffer, bool blocking) + bool AudioChannelImpl::AddBuffer(IGpAudioBuffer *buffer, bool blocking) { + buffer->AddRef(); + AudioCommand cmd; cmd.m_commandType = AudioCommandTypes::kBuffer; - cmd.m_param.m_ptr = lengthTaggedBuffer; + cmd.m_param.m_buffer = buffer; - return this->PushCommand(cmd, blocking); + bool pushedOK = this->PushCommand(cmd, blocking); + if (!pushedOK) + buffer->Release(); + + return pushedOK; } bool AudioChannelImpl::AddCallback(AudioChannelCallback_t callback, bool blocking) { AudioCommand cmd; cmd.m_commandType = AudioCommandTypes::kCallback; - cmd.m_param.m_ptr = reinterpret_cast(callback); + cmd.m_param.m_callback = callback; return this->PushCommand(cmd, blocking); } @@ -200,7 +217,7 @@ namespace PortabilityLayer switch (command.m_commandType) { case AudioCommandTypes::kBuffer: - DigestBufferCommand(command.m_param.m_ptr); + DigestBufferCommand(command.m_param.m_buffer); assert(m_state == State_PlayingAsync); m_mutex->Unlock(); return; @@ -222,16 +239,14 @@ namespace PortabilityLayer m_mutex->Unlock(); } - void AudioChannelImpl::DigestBufferCommand(const void *dataPointer) + void AudioChannelImpl::DigestBufferCommand(IGpAudioBuffer *buffer) { assert(m_state == State_Idle); - // At this point, the buffer should already be validated and converted, and the data pointer should point at the data tag - uint32_t length; - memcpy(&length, dataPointer, 4); + if (m_audioChannel->PostBuffer(buffer)) + m_state = State_PlayingAsync; - m_audioChannel->PostBuffer(static_cast(dataPointer) + 4, length); - m_state = State_PlayingAsync; + buffer->Release(); } bool AudioChannelImpl::PushCommand(const AudioCommand &command, bool blocking) diff --git a/PortabilityLayer/PLSound.h b/PortabilityLayer/PLSound.h index 4c2d528..bc94151 100644 --- a/PortabilityLayer/PLSound.h +++ b/PortabilityLayer/PLSound.h @@ -2,6 +2,8 @@ #include "PLCore.h" +struct IGpAudioBuffer; + namespace PortabilityLayer { struct AudioChannel; @@ -11,7 +13,7 @@ namespace PortabilityLayer struct AudioChannel { virtual void Destroy(bool wait) = 0; - virtual bool AddBuffer(const void *lengthTaggedBuffer, bool blocking) = 0; + virtual bool AddBuffer(IGpAudioBuffer *buffer, bool blocking) = 0; virtual bool AddCallback(AudioChannelCallback_t callback, bool blocking) = 0; virtual void ClearAllCommands() = 0; virtual void Stop() = 0; diff --git a/PortabilityLayer/PLSysCalls.cpp b/PortabilityLayer/PLSysCalls.cpp index b59a10d..54621ef 100644 --- a/PortabilityLayer/PLSysCalls.cpp +++ b/PortabilityLayer/PLSysCalls.cpp @@ -19,6 +19,7 @@ #include #include +#include static void TranslateMouseInputEvent(const GpVOSEvent &vosEventBase, uint32_t timestamp, PortabilityLayer::EventQueue *queue) { @@ -176,7 +177,7 @@ namespace PLSysCalls { // Asyncify disarm checks are for manually checking that a stack has no indirect calls. // They should not be nested! -#if GP_DEBUG_CONFIG && GP_ASYNCIFY_PARANOID +#if GP_DEBUG_CONFIG && GP_ASYNCIFY_PARANOID_VALIDATION static bool g_asyncifyParanoidDisarmed = false; void AsyncifyParanoidSetDisarmed(bool state) @@ -198,7 +199,7 @@ namespace PLSysCalls void Sleep(uint32_t ticks) { -#if GP_DEBUG_CONFIG && GP_ASYNCIFY_PARANOID +#if GP_DEBUG_CONFIG && GP_ASYNCIFY_PARANOID_VALIDATION assert(g_asyncifyParanoidDisarmed); #endif if (ticks > 0) diff --git a/PortabilityLayer/PLSysCalls.h b/PortabilityLayer/PLSysCalls.h index 0bd77a8..4d4f8ba 100644 --- a/PortabilityLayer/PLSysCalls.h +++ b/PortabilityLayer/PLSysCalls.h @@ -10,7 +10,7 @@ namespace PLSysCalls void Sleep(uint32_t ticks); void Exit(int exitCode); -#if GP_DEBUG_CONFIG && GP_ASYNCIFY_PARANOID +#if GP_DEBUG_CONFIG && GP_ASYNCIFY_PARANOID_VALIDATION class AsyncifyDisarmScope { public: diff --git a/PortabilityLayer/PortabilityLayer.vcxproj b/PortabilityLayer/PortabilityLayer.vcxproj index 705e4f9..6d4d862 100644 --- a/PortabilityLayer/PortabilityLayer.vcxproj +++ b/PortabilityLayer/PortabilityLayer.vcxproj @@ -105,6 +105,7 @@ + @@ -123,7 +124,6 @@ - @@ -156,7 +156,6 @@ - @@ -250,7 +249,6 @@ - @@ -301,7 +299,6 @@ - diff --git a/PortabilityLayer/PortabilityLayer.vcxproj.filters b/PortabilityLayer/PortabilityLayer.vcxproj.filters index 61c8d6d..73b1f28 100644 --- a/PortabilityLayer/PortabilityLayer.vcxproj.filters +++ b/PortabilityLayer/PortabilityLayer.vcxproj.filters @@ -132,9 +132,6 @@ Header Files - - Header Files - Header Files @@ -399,9 +396,6 @@ Header Files - - Header Files - Header Files @@ -432,6 +426,9 @@ Header Files + + Header Files + @@ -494,9 +491,6 @@ Source Files - - Source Files - Source Files @@ -668,9 +662,6 @@ Source Files - - Source Files - Source Files diff --git a/PortabilityLayer/PortabilityLayer_Combined.cpp b/PortabilityLayer/PortabilityLayer_Combined.cpp index 8f68695..ae49bf3 100644 --- a/PortabilityLayer/PortabilityLayer_Combined.cpp +++ b/PortabilityLayer/PortabilityLayer_Combined.cpp @@ -26,7 +26,6 @@ #include "MemoryManager.cpp" #include "MemReaderStream.cpp" #include "MenuManager.cpp" -#include "MMBlock.cpp" #include "MMHandleBlock.cpp" #include "PLApplication.cpp" #include "PLButtonWidget.cpp" @@ -78,7 +77,6 @@ #include "SimpleGraphic.cpp" #include "TextPlacer.cpp" #include "UTF8.cpp" -#include "UTF16.cpp" #include "WindowDef.cpp" #include "WindowManager.cpp" #include "WorkerThread.cpp" diff --git a/PortabilityLayer/QDStandardPalette.cpp b/PortabilityLayer/QDStandardPalette.cpp index 8d25e7a..c39098e 100644 --- a/PortabilityLayer/QDStandardPalette.cpp +++ b/PortabilityLayer/QDStandardPalette.cpp @@ -293,7 +293,7 @@ namespace PortabilityLayer if (mutex) mutex->Unlock(); - entry.m_aaTable.GenerateForSimpleScale(tone, false); + entry.m_aaTable.GenerateForSimpleScale(tone); return entry.m_aaTable; } diff --git a/PortabilityLayer/RGBAColor.h b/PortabilityLayer/RGBAColor.h index fa907f2..145dc5f 100644 --- a/PortabilityLayer/RGBAColor.h +++ b/PortabilityLayer/RGBAColor.h @@ -1,39 +1,39 @@ -#pragma once - -#include - -namespace PortabilityLayer -{ - struct RGBAColor - { +#pragma once + +#include + +namespace PortabilityLayer +{ + struct RGBAColor + { uint8_t r, g, b, a; bool operator==(const RGBAColor &other) const; bool operator!=(const RGBAColor &other) const; static RGBAColor Create(uint8_t r, uint8_t g, uint8_t b, uint8_t a); - uint32_t AsUInt32() const; + uint32_t AsUInt32() const; }; inline RGBAColor RGBAColor::Create(uint8_t r, uint8_t g, uint8_t b, uint8_t a) - { + { RGBAColor color; color.r = r; color.g = g; color.b = b; color.a = a; - return color; + return color; } inline bool RGBAColor::operator==(const RGBAColor &other) const - { - return this->r == other.r && this->g == other.g && this->b == other.b && this->a == other.a; - } + { + return this->r == other.r && this->g == other.g && this->b == other.b && this->a == other.a; + } inline bool RGBAColor::operator!=(const RGBAColor &other) const - { - return !((*this) == other); + { + return !((*this) == other); } inline uint32_t RGBAColor::AsUInt32() const @@ -46,4 +46,4 @@ namespace PortabilityLayer rgbaColorBytes[3] = a; return rgbaColor; } -} +} diff --git a/PortabilityLayer/ResourceManager.h b/PortabilityLayer/ResourceManager.h index ea49208..95f0546 100644 --- a/PortabilityLayer/ResourceManager.h +++ b/PortabilityLayer/ResourceManager.h @@ -78,7 +78,7 @@ namespace PortabilityLayer virtual IResourceArchive *GetAppResourceArchive() const = 0; virtual IResourceArchive *LoadResFile(CompositeFile *file) const = 0; - virtual PLError_t CreateBlankResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) = 0; + GP_ASYNCIFY_PARANOID_VIRTUAL PLError_t CreateBlankResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) GP_ASYNCIFY_PARANOID_PURE; virtual void DissociateHandle(MMHandleBlock *hdl) const = 0; virtual const ResourceArchiveRef *ResourceForHandle(MMHandleBlock *hdl) const = 0; diff --git a/PortabilityLayer/ScanlineMask.cpp b/PortabilityLayer/ScanlineMask.cpp index 6ff11a9..d239621 100644 --- a/PortabilityLayer/ScanlineMask.cpp +++ b/PortabilityLayer/ScanlineMask.cpp @@ -3,6 +3,8 @@ #include "ScanlineMaskBuilder.h" #include "ScanlineMaskIterator.h" +#include "PLCore.h" + #include #include @@ -11,7 +13,7 @@ namespace PortabilityLayer void ScanlineMask::Destroy() { this->~ScanlineMask(); - free(this); + DisposePtr(this); } const Rect &ScanlineMask::GetRect() const @@ -50,7 +52,7 @@ namespace PortabilityLayer else return nullptr; - void *storage = malloc(alignedPrefixSize + storageSize); + void *storage = NewPtr(alignedPrefixSize + storageSize); if (!storage) return nullptr; diff --git a/PortabilityLayer/ScanlineMaskConverter.cpp b/PortabilityLayer/ScanlineMaskConverter.cpp index 03bfdbe..6951cd2 100644 --- a/PortabilityLayer/ScanlineMaskConverter.cpp +++ b/PortabilityLayer/ScanlineMaskConverter.cpp @@ -7,6 +7,7 @@ #include "LinePlotter.h" #include "ScanlineMaskBuilder.h" #include "IPlotter.h" +#include "PLCore.h" #include #include @@ -135,7 +136,7 @@ namespace PortabilityLayer #else const size_t storageSize = (numElements * 2 + 7) / 8; #endif - void *storage = malloc(storageSize); + void *storage = NewPtr(storageSize); if (!storage) return nullptr; @@ -250,7 +251,7 @@ namespace PortabilityLayer stbi_write_png(path, width, height, 4, flagBits, width * 4); #endif - free(storage); + DisposePtr(storage); return ScanlineMask::Create(Rect::Create(minPoint.m_y, minPoint.m_x, minPoint.m_y + static_cast(height), minPoint.m_x + static_cast(width)), maskBuilder); } diff --git a/PortabilityLayer/UTF16.cpp b/PortabilityLayer/UTF16.cpp deleted file mode 100644 index 7757236..0000000 --- a/PortabilityLayer/UTF16.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "UTF16.h" - -namespace PortabilityLayer -{ - bool UTF16Processor::DecodeCodePoint(const uint16_t *characters, size_t availableCharacters, size_t &outCharactersDigested, uint32_t &outCodePoint) - { - if (availableCharacters <= 0) - return false; - - if ((characters[0] & 0xff80) == 0x00) - { - outCharactersDigested = 1; - outCodePoint = characters[0]; - return true; - } - - if (characters[0] <= 0xd7ff || characters[0] >= 0xe000) - { - outCharactersDigested = 1; - outCodePoint = characters[0]; - return true; - } - - // Surrogate pair - if (characters[0] >= 0xdc00 || availableCharacters < 2) - return false; - - if (characters[1] < 0xdc00 || characters[1] >= 0xe000) - return false; - - uint16_t highBits = (characters[0] & 0x3ff); - uint16_t lowBits = (characters[1] & 0x3ff); - - outCharactersDigested = 2; - outCodePoint = (highBits << 10) + lowBits + 0x10000; - - return true; - } - - void UTF16Processor::EncodeCodePoint(uint16_t *characters, size_t &outCharactersEmitted, uint32_t codePoint) - { - if (codePoint <= 0xd7ff || codePoint >= 0xe000) - { - outCharactersEmitted = 1; - characters[0] = static_cast(codePoint); - return; - } - - uint32_t codePointBits = (codePoint - 0x10000) & 0xfffff; - uint16_t lowBits = (codePointBits & 0x3ff); - uint16_t highBits = ((codePointBits >> 10) & 0x3ff); - - outCharactersEmitted = 2; - characters[0] = (0xd800 + highBits); - characters[1] = (0xdc00 + lowBits); - } -} diff --git a/PortabilityLayer/UTF16.h b/PortabilityLayer/UTF16.h deleted file mode 100644 index 4de6ab9..0000000 --- a/PortabilityLayer/UTF16.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include - -namespace PortabilityLayer -{ - class UTF16Processor - { - public: - static bool DecodeCodePoint(const uint16_t *characters, size_t availableCharacters, size_t &outCharactersDigested, uint32_t &outCodePoint); - static void EncodeCodePoint(uint16_t *characters, size_t &outCharactersEmitted, uint32_t codePoint); - }; -} diff --git a/PortabilityLayer/UTF8.cpp b/PortabilityLayer/UTF8.cpp index c6a267a..12775df 100644 --- a/PortabilityLayer/UTF8.cpp +++ b/PortabilityLayer/UTF8.cpp @@ -1,105 +1,9 @@ #include "UTF8.h" +#include "GpUnicode.h" #include "MacRomanConversion.h" namespace PortabilityLayer { - bool UTF8Processor::DecodeCodePoint(const uint8_t *characters, size_t availableCharacters, size_t &outCharactersDigested, uint32_t &outCodePoint) - { - if (availableCharacters <= 0) - return false; - - if ((characters[0] & 0x80) == 0x00) - { - outCharactersDigested = 1; - outCodePoint = characters[0]; - return true; - } - - size_t sz = 0; - uint32_t codePoint = 0; - uint32_t minCodePoint = 0; - if ((characters[0] & 0xe0) == 0xc0) - { - sz = 2; - minCodePoint = 0x80; - codePoint = (characters[0] & 0x1f); - } - else if ((characters[0] & 0xf0) == 0xe0) - { - sz = 3; - minCodePoint = 0x800; - codePoint = (characters[0] & 0x0f); - } - else if ((characters[0] & 0xf8) == 0xf0) - { - sz = 4; - minCodePoint = 0x10000; - codePoint = (characters[0] & 0x07); - } - else - return false; - - if (availableCharacters < sz) - return false; - - for (size_t auxByte = 1; auxByte < sz; auxByte++) - { - if ((characters[auxByte] & 0xc0) != 0x80) - return false; - - codePoint = (codePoint << 6) | (characters[auxByte] & 0x3f); - } - - if (codePoint < minCodePoint || codePoint > 0x10ffff) - return false; - - if (codePoint >= 0xd800 && codePoint <= 0xdfff) - return false; - - outCodePoint = codePoint; - outCharactersDigested = sz; - - return true; - } - - void UTF8Processor::EncodeCodePoint(uint8_t *characters, size_t &outCharactersEmitted, uint32_t codePoint) - { - codePoint &= 0x1fffff; - - uint8_t signalBits = 0; - size_t numBytes = 0; - if (codePoint < 0x0080) - { - numBytes = 1; - signalBits = 0; - } - else if (codePoint < 0x0800) - { - numBytes = 2; - signalBits = 0xc0; - } - else if (codePoint < 0x10000) - { - numBytes = 3; - signalBits = 0xe0; - } - else - { - numBytes = 4; - signalBits = 0xf0; - } - - characters[0] = static_cast((codePoint >> (6 * (numBytes - 1))) | signalBits); - - for (size_t i = 1; i < numBytes; i++) - { - const uint32_t isolate = ((codePoint >> (6 * (numBytes - 1 - i))) & 0x3f) | 0x80; - characters[i] = static_cast(isolate); - } - - outCharactersEmitted = numBytes; - } - bool UTF8Processor::DecodeToMacRomanPascalStr(const uint8_t *inChars, size_t inSize, uint8_t *outChars, size_t maxOutSize, size_t &outSizeRef) { size_t outSize = 0; @@ -107,7 +11,7 @@ namespace PortabilityLayer { size_t digestedChars = 0; uint32_t codePoint = 0; - if (!DecodeCodePoint(inChars, inSize, digestedChars, codePoint)) + if (!GpUnicode::UTF8::Decode(inChars, inSize, digestedChars, codePoint)) return false; inChars += digestedChars; @@ -122,10 +26,10 @@ namespace PortabilityLayer { for (uint16_t c = 0x80; c <= 0xff; c++) { - uint16_t decodedCP = MacRoman::ToUnicode(c); + uint16_t decodedCP = MacRoman::ToUnicode(static_cast(c)); if (decodedCP == codePoint) { - macRomanChar = c; + macRomanChar = static_cast(c); break; } } diff --git a/PortabilityLayer/UTF8.h b/PortabilityLayer/UTF8.h index 2c9412a..a668092 100644 --- a/PortabilityLayer/UTF8.h +++ b/PortabilityLayer/UTF8.h @@ -8,11 +8,6 @@ namespace PortabilityLayer class UTF8Processor { public: - static bool DecodeCodePoint(const uint8_t *characters, size_t availableCharacters, size_t &outCharactersDigested, uint32_t &outCodePoint); - static void EncodeCodePoint(uint8_t *characters, size_t &outCharactersEmitted, uint32_t codePoint); - static bool DecodeToMacRomanPascalStr(const uint8_t *inChars, size_t inSize, uint8_t *outChars, size_t maxOutSize, size_t &outSize); - - static const unsigned int kMaxEncodedBytes = 4; }; } diff --git a/PortabilityLayer/VirtualDirectory.h b/PortabilityLayer/VirtualDirectory.h index a8447b6..39a1867 100644 --- a/PortabilityLayer/VirtualDirectory.h +++ b/PortabilityLayer/VirtualDirectory.h @@ -13,11 +13,11 @@ namespace PortabilityLayer kUserData, kUserSaves, kPrefs, + kPreinstalledFonts, kFonts, kCursors, kHighScores, kLogs, - kFontCache, kSourceExport, }; diff --git a/PortabilityLayer/WindowManager.cpp b/PortabilityLayer/WindowManager.cpp index 9521c38..2b7f512 100644 --- a/PortabilityLayer/WindowManager.cpp +++ b/PortabilityLayer/WindowManager.cpp @@ -181,8 +181,8 @@ namespace PortabilityLayer void HideWindow(Window *window) override; void FindWindow(const Point &point, Window **outWindow, short *outRegion) const override; void DestroyWindow(Window *window) override; - void DragWindow(Window *window, const Point &startPoint, const Rect &constraintRect) override; - bool HandleCloseBoxClick(Window *window, const Point &startPoint) override; + void DragWindow(Window *window, const Point &startPoint, const Rect &constraintRect) GP_ASYNCIFY_PARANOID_OVERRIDE; + bool HandleCloseBoxClick(Window *window, const Point &startPoint) GP_ASYNCIFY_PARANOID_OVERRIDE; void SetWindowTitle(Window *window, const PLPasStr &title) override; Rect2i GetWindowFullRect(Window *window) const override; bool GetWindowChromeInteractionZone(Window *window, const Vec2i &point, RegionID_t &outRegion) const override; @@ -593,7 +593,7 @@ namespace PortabilityLayer if (window->GetStyleFlags() & WindowStyleFlags::kCloseBox) RenderChromeCloseBox(surface, rect, false); - PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication10Bold); + PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication10SyntheticBold); int32_t ascender = appFont->GetMetrics().m_ascent; const PLPasStr titlePStr = window->GetTitle().ToShortStr(); @@ -1198,7 +1198,14 @@ namespace PortabilityLayer for (;;) { TimeTaggedVOSEvent evt; - if (WaitForEvent(&evt, 1)) + bool haveEvent = false; + + { + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); + haveEvent = WaitForEvent(&evt, 1); + } + + if (haveEvent) { if (evt.m_vosEvent.m_eventType == GpVOSEventTypes::kMouseInput) { @@ -1253,7 +1260,14 @@ namespace PortabilityLayer for (;;) { TimeTaggedVOSEvent evt; - if (WaitForEvent(&evt, 1)) + + bool haveEvent = false; + { + PL_ASYNCIFY_PARANOID_DISARM_FOR_SCOPE(); + haveEvent = WaitForEvent(&evt, 1); + } + + if (haveEvent) { if (evt.m_vosEvent.m_eventType == GpVOSEventTypes::kMouseInput) { @@ -1693,6 +1707,16 @@ namespace PortabilityLayer } #if GP_ASYNCIFY_PARANOID + void WindowManager::DragWindow(Window *window, const Point &startPoint, const Rect &constraintRect) + { + static_cast(this)->DragWindow(window, startPoint, constraintRect); + } + + bool WindowManager::HandleCloseBoxClick(Window *window, const Point &startPoint) + { + return static_cast(this)->HandleCloseBoxClick(window, startPoint); + } + void WindowManager::FlickerWindowIn(Window *window, int32_t velocity) { static_cast(this)->FlickerWindowIn(window, velocity); diff --git a/PortabilityLayer/WindowManager.h b/PortabilityLayer/WindowManager.h index abfdfce..a17483e 100644 --- a/PortabilityLayer/WindowManager.h +++ b/PortabilityLayer/WindowManager.h @@ -33,8 +33,8 @@ namespace PortabilityLayer virtual void HideWindow(Window *window) = 0; virtual void FindWindow(const Point &point, Window **outWindow, short *outRegion) const = 0; virtual void DestroyWindow(Window *window) = 0; - virtual void DragWindow(Window *window, const Point &startPoint, const Rect &constraintRect) = 0; - virtual bool HandleCloseBoxClick(Window *window, const Point &startPoint) = 0; + GP_ASYNCIFY_PARANOID_VIRTUAL void DragWindow(Window *window, const Point &startPoint, const Rect &constraintRect) GP_ASYNCIFY_PARANOID_PURE; + GP_ASYNCIFY_PARANOID_VIRTUAL bool HandleCloseBoxClick(Window *window, const Point &startPoint) GP_ASYNCIFY_PARANOID_PURE; virtual void SetWindowTitle(Window *window, const PLPasStr &title) = 0; virtual Rect2i GetWindowFullRect(Window *window) const = 0; virtual bool GetWindowChromeInteractionZone(Window *window, const Vec2i &point, RegionID_t &outRegion) const = 0; diff --git a/PortabilityLayer/WorkerThread.cpp b/PortabilityLayer/WorkerThread.cpp index 5ba031c..85288b4 100644 --- a/PortabilityLayer/WorkerThread.cpp +++ b/PortabilityLayer/WorkerThread.cpp @@ -2,6 +2,7 @@ #include "IGpThreadEvent.h" #include "IGpSystemServices.h" +#include "PLCore.h" #include "PLDrivers.h" #include @@ -39,7 +40,7 @@ namespace PortabilityLayer void PortabilityLayer::WorkerThreadImpl::Destroy() { this->~WorkerThreadImpl(); - free(this); + DisposePtr(this); } void PortabilityLayer::WorkerThreadImpl::AsyncExecuteTask(PortabilityLayer::WorkerThread::Callback_t callback, void *context) @@ -139,7 +140,7 @@ PortabilityLayer::WorkerThread::~WorkerThread() PortabilityLayer::WorkerThread *PortabilityLayer::WorkerThread::Create() { - void *storage = malloc(sizeof(PortabilityLayer::WorkerThreadImpl)); + void *storage = NewPtr(sizeof(PortabilityLayer::WorkerThreadImpl)); if (!storage) return nullptr; diff --git a/ShaderSrc/DrawQuadPaletteP.hlsl b/ShaderSrc/DrawQuadPaletteP.hlsl index 7385aff..3fd8dbb 100644 --- a/ShaderSrc/DrawQuadPaletteP.hlsl +++ b/ShaderSrc/DrawQuadPaletteP.hlsl @@ -23,7 +23,7 @@ SDrawQuadPixelOutput PSMain(SDrawQuadPixelInput input) int2 pixelCoordinate = int2(floor(input.texCoord.xy)); result.color = float4(SamplePixel(int2(floor(input.texCoord.xy))), 1.0); result.color *= constants_Modulation; - result.color = ApplyFlicker(pixelCoordinate, constants_FlickerStartThreshold, constants_FlickerEndThreshold, result.color * constants_Modulation); + result.color = ApplyFlicker(pixelCoordinate, constants_FlickerStartThreshold, constants_FlickerEndThreshold, result.color); result.color = ApplyDesaturation(constants_Desaturation, result.color); if (result.color.a <= 0.0) diff --git a/ShaderSrc/DrawQuadRGBP.hlsl b/ShaderSrc/DrawQuadRGBP.hlsl index ca44ea1..255b0a9 100644 --- a/ShaderSrc/DrawQuadRGBP.hlsl +++ b/ShaderSrc/DrawQuadRGBP.hlsl @@ -21,7 +21,7 @@ SDrawQuadPixelOutput PSMain(SDrawQuadPixelInput input) int2 pixelCoordinate = int2(floor(input.texCoord.xy)); result.color = float4(SamplePixel(int2(floor(input.texCoord.xy))), 1.0); result.color *= constants_Modulation; - result.color = ApplyFlicker(pixelCoordinate, constants_FlickerStartThreshold, constants_FlickerEndThreshold, result.color * constants_Modulation); + result.color = ApplyFlicker(pixelCoordinate, constants_FlickerStartThreshold, constants_FlickerEndThreshold, result.color); result.color = ApplyDesaturation(constants_Desaturation, result.color); if (result.color.a <= 0.0) diff --git a/WindowsUnicodeToolShim/WindowsUnicodeToolShim.cpp b/WindowsUnicodeToolShim/WindowsUnicodeToolShim.cpp index ceed94a..a2c4bd7 100644 --- a/WindowsUnicodeToolShim/WindowsUnicodeToolShim.cpp +++ b/WindowsUnicodeToolShim/WindowsUnicodeToolShim.cpp @@ -1,7 +1,6 @@ #include -#include "UTF8.h" -#include "UTF16.h" +#include "GpUnicode.h" #include #include @@ -20,13 +19,13 @@ static std::string ConvertWStringToUTF8(const wchar_t *str) size_t charsDigested = 0; uint32_t codePoint = 0; uint8_t asUTF8[4]; - if (!PortabilityLayer::UTF16Processor::DecodeCodePoint(reinterpret_cast(str) + i, strLength - i, charsDigested, codePoint)) + if (!GpUnicode::UTF16::Decode(reinterpret_cast(str) + i, strLength - i, charsDigested, codePoint)) return ""; i += charsDigested; size_t bytesEmitted = 0; - PortabilityLayer::UTF8Processor::EncodeCodePoint(asUTF8, bytesEmitted, codePoint); + GpUnicode::UTF8::Encode(asUTF8, bytesEmitted, codePoint); result.append(reinterpret_cast(asUTF8), bytesEmitted); } @@ -45,13 +44,13 @@ static std::wstring ConvertUTF8ToWString(const char *str) size_t charsDigested = 0; uint32_t codePoint = 0; uint16_t asUTF16[4]; - if (!PortabilityLayer::UTF8Processor::DecodeCodePoint(reinterpret_cast(str) + i, strLength - i, charsDigested, codePoint)) + if (!GpUnicode::UTF8::Decode(reinterpret_cast(str) + i, strLength - i, charsDigested, codePoint)) return L""; i += charsDigested; size_t codePointsEmitted = 0; - PortabilityLayer::UTF16Processor::EncodeCodePoint(asUTF16, codePointsEmitted, codePoint); + GpUnicode::UTF16::Encode(asUTF16, codePointsEmitted, codePoint); result.append(reinterpret_cast(asUTF16), codePointsEmitted); } diff --git a/WindowsUnicodeToolShim/WindowsUnicodeToolShim.vcxproj b/WindowsUnicodeToolShim/WindowsUnicodeToolShim.vcxproj index 2267d6a..c4bd6b2 100644 --- a/WindowsUnicodeToolShim/WindowsUnicodeToolShim.vcxproj +++ b/WindowsUnicodeToolShim/WindowsUnicodeToolShim.vcxproj @@ -41,6 +41,7 @@ + @@ -48,6 +49,7 @@ + diff --git a/gpr2gpa/gpr2gpa.cpp b/gpr2gpa/gpr2gpa.cpp index 18a7680..366e936 100644 --- a/gpr2gpa/gpr2gpa.cpp +++ b/gpr2gpa/gpr2gpa.cpp @@ -2,6 +2,7 @@ #include "CFileStream.h" #include "CombinedTimestamp.h" #include "GPArchive.h" +#include "GpAllocator_C.h" #include "MacRomanConversion.h" #include "MemReaderStream.h" #include "QDPictDecoder.h" @@ -14,6 +15,8 @@ #include "UTF8.h" #include "ZipFile.h" #include "WaveFormat.h" +#include "GpUnicode.h" +#include "PLDrivers.h" #include "zlib.h" @@ -116,7 +119,7 @@ void AppendUTF8(std::vector &array, uint32_t codePoint) uint8_t bytes[5]; size_t sz; - PortabilityLayer::UTF8Processor::EncodeCodePoint(bytes, sz, codePoint); + GpUnicode::UTF8::Encode(bytes, sz, codePoint); for (size_t i = 0; i < sz; i++) array.push_back(bytes[i]); } @@ -1430,6 +1433,9 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes PortabilityLayer::CFileStream cfs(inF); + GpDriverCollection *drivers = PLDrivers::GetDriverCollection(); + drivers->SetDriver(GpAllocator_C::GetInstance()); + PortabilityLayer::ResourceFile *resFile = PortabilityLayer::ResourceFile::Create(); resFile->Load(&cfs); cfs.Close(); diff --git a/gpr2gpa/gpr2gpa.vcxproj b/gpr2gpa/gpr2gpa.vcxproj index 23bcd52..2b8f5c9 100644 --- a/gpr2gpa/gpr2gpa.vcxproj +++ b/gpr2gpa/gpr2gpa.vcxproj @@ -45,6 +45,7 @@ + @@ -56,6 +57,7 @@ + @@ -95,6 +97,7 @@ + diff --git a/gpr2gpa/gpr2gpa.vcxproj.filters b/gpr2gpa/gpr2gpa.vcxproj.filters index e68c12b..ae6bba6 100644 --- a/gpr2gpa/gpr2gpa.vcxproj.filters +++ b/gpr2gpa/gpr2gpa.vcxproj.filters @@ -21,6 +21,9 @@ Source Files + + Source Files + diff --git a/unpacktool/StringCommon.cpp b/unpacktool/StringCommon.cpp index c6b2b1e..36c3209 100644 --- a/unpacktool/StringCommon.cpp +++ b/unpacktool/StringCommon.cpp @@ -1,7 +1,7 @@ #include "StringCommon.h" #include "MacRomanConversion.h" -#include "UTF8.h" +#include "GpUnicode.h" void StringCommon::ConvertMacRomanFileName(std::vector &utf8FileName, const uint8_t *macRomanName, size_t macRomanLength) { @@ -9,7 +9,7 @@ void StringCommon::ConvertMacRomanFileName(std::vector &utf8FileName, c { uint8_t bytes[8]; size_t bytesEmitted; - PortabilityLayer::UTF8Processor::EncodeCodePoint(bytes, bytesEmitted, MacRoman::ToUnicode(macRomanName[i])); + GpUnicode::UTF8::Encode(bytes, bytesEmitted, MacRoman::ToUnicode(macRomanName[i])); for (size_t bi = 0; bi < bytesEmitted; bi++) utf8FileName.push_back(bytes[bi]); diff --git a/unpacktool/unpacktool.cpp b/unpacktool/unpacktool.cpp index e91b7fd..630b3cb 100644 --- a/unpacktool/unpacktool.cpp +++ b/unpacktool/unpacktool.cpp @@ -7,8 +7,7 @@ #include "CompactProParser.h" #include "CFileStream.h" -#include "UTF8.h" -#include "UTF16.h" +#include "GpUnicode.h" #include "ArchiveDescription.h" #include "IDecompressor.h" @@ -342,7 +341,7 @@ int ExtractFile(const ArchiveItem &item, const std::string &path, IFileReader &r PortabilityLayer::CFileStream metadataStream(metadataF); - if (mfps.WriteAsPackage(metadataStream, ts)) + if (!mfps.WriteAsPackage(metadataStream, ts)) { fprintf(stderr, "A problem occurred writing metadata"); metadataStream.Close();