diff --git a/Aerofoil/GpFiberStarter_Win32.cpp b/Aerofoil/GpFiberStarter_Win32.cpp index 37e9ce4..1c5a181 100644 --- a/Aerofoil/GpFiberStarter_Win32.cpp +++ b/Aerofoil/GpFiberStarter_Win32.cpp @@ -28,7 +28,7 @@ namespace GpFiberStarter_Win32 } } -IGpFiber *GpFiberStarter::StartFiber(ThreadFunc_t threadFunc, void *context, IGpFiber *creatingFiber) +IGpFiber *GpFiberStarter::StartFiber(PortabilityLayer::HostSystemServices *systemServices, ThreadFunc_t threadFunc, void *context, IGpFiber *creatingFiber) { ULONG_PTR lowLimit; ULONG_PTR highLimit; diff --git a/Aerofoil/GpThreadEvent_Win32.cpp b/Aerofoil/GpThreadEvent_Win32.cpp index 2e49ea7..1497d10 100644 --- a/Aerofoil/GpThreadEvent_Win32.cpp +++ b/Aerofoil/GpThreadEvent_Win32.cpp @@ -8,9 +8,9 @@ void GpThreadEvent_Win32::Wait() WaitForSingleObject(m_event, INFINITE); } -void GpThreadEvent_Win32::WaitTimed(uint32_t msec) +bool GpThreadEvent_Win32::WaitTimed(uint32_t msec) { - WaitForSingleObject(m_event, static_cast(msec)); + return WaitForSingleObject(m_event, static_cast(msec)) == WAIT_OBJECT_0; } void GpThreadEvent_Win32::Signal() diff --git a/Aerofoil/GpThreadEvent_Win32.h b/Aerofoil/GpThreadEvent_Win32.h index 8977a9a..4fc0ee3 100644 --- a/Aerofoil/GpThreadEvent_Win32.h +++ b/Aerofoil/GpThreadEvent_Win32.h @@ -8,7 +8,7 @@ class GpThreadEvent_Win32 final : public PortabilityLayer::HostThreadEvent { public: void Wait() override; - void WaitTimed(uint32_t msec) override; + bool WaitTimed(uint32_t msec) override; void Signal() override; void Destroy() override; diff --git a/AerofoilAndroid/app/jni/.gitignore b/AerofoilAndroid/app/jni/.gitignore index 9e706dd..ba04a04 100644 --- a/AerofoilAndroid/app/jni/.gitignore +++ b/AerofoilAndroid/app/jni/.gitignore @@ -1 +1,13 @@ +AerofoilSDL +Common +FreeType +GpApp +GpCommon +GpFontHandler_FreeType2 +GpShell +MacRomanConversion +PortabilityLayer +rapidjson SDL2 +stb +zlib diff --git a/AerofoilAndroid/app/jni/Application.mk b/AerofoilAndroid/app/jni/Application.mk index 023bc20..89f5556 100644 --- a/AerofoilAndroid/app/jni/Application.mk +++ b/AerofoilAndroid/app/jni/Application.mk @@ -2,7 +2,7 @@ # Uncomment this if you're using STL in your project # You can find more information here: # https://developer.android.com/ndk/guides/cpp-support -# APP_STL := c++_shared +APP_STL := c++_shared APP_ABI := armeabi-v7a arm64-v8a x86 x86_64 diff --git a/AerofoilAndroid/app/jni/main/Android.mk b/AerofoilAndroid/app/jni/main/Android.mk index 1adcb6e..9cd7b6c 100644 --- a/AerofoilAndroid/app/jni/main/Android.mk +++ b/AerofoilAndroid/app/jni/main/Android.mk @@ -6,13 +6,25 @@ LOCAL_MODULE := main SDL_PATH := ../SDL -LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include +LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include \ + $(LOCAL_PATH)/../GpShell \ + $(LOCAL_PATH)/../GpCommon \ + $(LOCAL_PATH)/../AerofoilSDL \ + $(LOCAL_PATH)/../Common \ + $(LOCAL_PATH)/../PortabilityLayer + +LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0 # Add your application source files here... -LOCAL_SRC_FILES := YourSourceHere.c +LOCAL_SRC_FILES := \ + GpMain_SDL_Android.cpp \ + GpSystemServices_Android.cpp \ + GpFileSystem_Android.cpp LOCAL_SHARED_LIBRARIES := SDL2 +LOCAL_STATIC_LIBRARIES := GpShell GpFontHandler_FreeType2 AerofoilSDL GpApp + LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -llog include $(BUILD_SHARED_LIBRARY) diff --git a/AerofoilAndroid/app/jni/main/GpAndroid.h b/AerofoilAndroid/app/jni/main/GpAndroid.h new file mode 100644 index 0000000..0ec050c --- /dev/null +++ b/AerofoilAndroid/app/jni/main/GpAndroid.h @@ -0,0 +1,5 @@ +#pragma once + +struct GpAndroidGlobals +{ +}; diff --git a/AerofoilAndroid/app/jni/main/GpFileSystem_Android.cpp b/AerofoilAndroid/app/jni/main/GpFileSystem_Android.cpp new file mode 100644 index 0000000..02c3008 --- /dev/null +++ b/AerofoilAndroid/app/jni/main/GpFileSystem_Android.cpp @@ -0,0 +1,84 @@ +#include "GpFileSystem_Android.h" + +GpFileSystem_Android::GpFileSystem_Android() +{ +} + +bool GpFileSystem_Android::FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) +{ + return false; +} + +bool GpFileSystem_Android::FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists) +{ + return false; +} + +GpIOStream *GpFileSystem_Android::OpenFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition) +{ + return nullptr; +} + +bool GpFileSystem_Android::DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) +{ + existed = false; + return false; +} + +PortabilityLayer::HostDirectoryCursor *GpFileSystem_Android::ScanDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory) +{ + return nullptr; +} + +bool GpFileSystem_Android::ValidateFilePath(const char *path, size_t length) const +{ + for (size_t i = 0; i < length; i++) + { + const char c = path[i]; + if (c >= '0' && c <= '9') + continue; + + if (c == '_' || c == '.' || c == '\'') + continue; + + if (c == ' ' && i != 0 && i != length - 1) + continue; + + if (c >= 'a' && c <= 'z') + continue; + + if (c >= 'A' && c <= 'Z') + continue; + + return false; + } + + return true; +} + +bool GpFileSystem_Android::ValidateFilePathUnicodeChar(uint32_t c) const +{ + if (c >= '0' && c <= '9') + return true; + + if (c == '_' || c == '\'') + return true; + + if (c == ' ') + return true; + + if (c >= 'a' && c <= 'z') + return true; + + if (c >= 'A' && c <= 'Z') + return true; + + return false; +} + +GpFileSystem_Android *GpFileSystem_Android::GetInstance() +{ + return &ms_instance; +} + +GpFileSystem_Android GpFileSystem_Android::ms_instance; diff --git a/AerofoilAndroid/app/jni/main/GpFileSystem_Android.h b/AerofoilAndroid/app/jni/main/GpFileSystem_Android.h new file mode 100644 index 0000000..fb34d69 --- /dev/null +++ b/AerofoilAndroid/app/jni/main/GpFileSystem_Android.h @@ -0,0 +1,27 @@ +#pragma once + +#include "HostFileSystem.h" + +#include "GpCoreDefs.h" + +class GpFileSystem_Android final : public PortabilityLayer::HostFileSystem +{ +public: + GpFileSystem_Android(); + + bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override; + bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists) override; + GpIOStream *OpenFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition) override; + bool DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) override; + PortabilityLayer::HostDirectoryCursor *ScanDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory) override; + + bool ValidateFilePath(const char *path, size_t sz) const override; + bool ValidateFilePathUnicodeChar(uint32_t ch) const override; + + static GpFileSystem_Android *GetInstance(); + +private: + bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, wchar_t *outPath); + + static GpFileSystem_Android ms_instance; +}; diff --git a/AerofoilAndroid/app/jni/main/GpMain_SDL_Android.cpp b/AerofoilAndroid/app/jni/main/GpMain_SDL_Android.cpp index 545fac4..6d545e2 100644 --- a/AerofoilAndroid/app/jni/main/GpMain_SDL_Android.cpp +++ b/AerofoilAndroid/app/jni/main/GpMain_SDL_Android.cpp @@ -4,7 +4,6 @@ #include "GpAudioDriverFactory.h" #include "GpDisplayDriverFactory.h" #include "GpGlobalConfig.h" -#include "GpFiber_Win32.h" #include "GpFiber_SDL.h" #include "GpFileSystem_Android.h" #include "GpFontHandlerFactory.h" @@ -19,8 +18,6 @@ #include "GpAndroid.h" -#include "resource.h" - GpAndroidGlobals g_gpAndroidGlobals; extern "C" IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties); @@ -29,17 +26,19 @@ IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProp IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties); -int main(int argc, const char **argv) +int main(int argc, char* argv[]) { if (SDL_Init(SDL_INIT_VIDEO) < 0) return -1; + SDL_GL_LoadLibrary("libGLESv2.so"); + GpAppInterface_Get()->PL_HostFileSystem_SetInstance(GpFileSystem_Android::GetInstance()); GpAppInterface_Get()->PL_HostSystemServices_SetInstance(GpSystemServices_Android::GetInstance()); g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_SDL_GL2; - g_gpGlobalConfig.m_audioDriverType = EGpAudioDriverType_SDL2; + g_gpGlobalConfig.m_audioDriverType = EGpAudioDriverType_None; g_gpGlobalConfig.m_fontHandlerType = EGpFontHandlerType_FreeType2; @@ -54,13 +53,7 @@ int main(int argc, const char **argv) GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_SDL2, GpDriver_CreateAudioDriver_SDL); GpFontHandlerFactory::RegisterFontHandlerFactory(EGpFontHandlerType_FreeType2, GpDriver_CreateFontHandler_FreeType2); - if (logger) - logger->Printf(IGpLogDriver::Category_Information, "SDL environment configured, starting up"); - int returnCode = GpMain::Run(); - if (logger) - logger->Printf(IGpLogDriver::Category_Information, "SDL environment exited with code %i, cleaning up", returnCode); - return returnCode; } diff --git a/AerofoilAndroid/app/jni/main/GpSystemServices_Android.cpp b/AerofoilAndroid/app/jni/main/GpSystemServices_Android.cpp new file mode 100644 index 0000000..823ed6a --- /dev/null +++ b/AerofoilAndroid/app/jni/main/GpSystemServices_Android.cpp @@ -0,0 +1,174 @@ +#include "GpSystemServices_Android.h" +#include "HostMutex.h" +#include "HostThreadEvent.h" + +#include +#include +#include + +template +class GpMutex_Cpp11 final : public PortabilityLayer::HostMutex +{ +public: + GpMutex_Cpp11(); + ~GpMutex_Cpp11(); + + void Destroy() override; + + void Lock() override; + void Unlock() override; + +private: + TMutex m_mutex; +}; + +template +GpMutex_Cpp11::GpMutex_Cpp11() +{ +} + +template +GpMutex_Cpp11::~GpMutex_Cpp11() +{ +} + +template +void GpMutex_Cpp11::Destroy() +{ + this->~GpMutex_Cpp11(); + free(this); +} + +template +void GpMutex_Cpp11::Lock() +{ + m_mutex.lock(); +} + +template +void GpMutex_Cpp11::Unlock() +{ + m_mutex.unlock(); +} + +typedef GpMutex_Cpp11 GpMutex_Cpp11_Vanilla; +typedef GpMutex_Cpp11 GpMutex_Cpp11_Recursive; + + +class GpThreadEvent_Cpp11 final : public PortabilityLayer::HostThreadEvent +{ +public: + GpThreadEvent_Cpp11(); + ~GpThreadEvent_Cpp11(); + + void Wait() override; + bool WaitTimed(uint32_t msec) override; + void Signal() override; + void Destroy() override; + +private: + std::mutex m_mutex; + std::condition_variable m_cvar; + bool m_flag; +}; + +GpThreadEvent_Cpp11::GpThreadEvent_Cpp11() + : m_flag(false) +{ +} + +GpThreadEvent_Cpp11::~GpThreadEvent_Cpp11() +{ +} + +void GpThreadEvent_Cpp11::Wait() +{ + std::unique_lock lock(m_mutex); + m_cvar.wait(lock,[&]()->bool{ return m_flag; }); +} + +bool GpThreadEvent_Cpp11::WaitTimed(uint32_t msec) +{ + std::unique_lock lock(m_mutex); + if (!m_cvar.wait_for(lock, std::chrono::milliseconds(msec), [&]()->bool{ return m_flag; })) + return false; + return true; +} + +void GpThreadEvent_Cpp11::Signal() +{ + m_mutex.lock(); + m_flag = true; + m_mutex.unlock(); + m_cvar.notify_all(); +} + +void GpThreadEvent_Cpp11::Destroy() +{ + this->~GpThreadEvent_Cpp11(); + free(this); +} + +GpSystemServices_Android::GpSystemServices_Android() +{ +} + +int64_t GpSystemServices_Android::GetTime() const +{ + time_t t = time(nullptr); + return static_cast(t) - 2082844800; +} + +void GpSystemServices_Android::GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const +{ + time_t t = time(nullptr); + tm *tmObject = localtime(&t); + year = static_cast(tmObject->tm_year); + month = static_cast(tmObject->tm_mon); + hour = static_cast(tmObject->tm_hour); + minute = static_cast(tmObject->tm_min); + second = static_cast(tmObject->tm_sec); +} + +PortabilityLayer::HostMutex *GpSystemServices_Android::CreateMutex() +{ + GpMutex_Cpp11_Vanilla *mutex = static_cast(malloc(sizeof(GpMutex_Cpp11_Vanilla))); + if (!mutex) + return nullptr; + + return new (mutex) GpMutex_Cpp11_Vanilla(); +} + +PortabilityLayer::HostMutex *GpSystemServices_Android::CreateRecursiveMutex() +{ + GpMutex_Cpp11_Recursive *mutex = static_cast(malloc(sizeof(GpMutex_Cpp11_Recursive))); + if (!mutex) + return nullptr; + + return new (mutex) GpMutex_Cpp11_Recursive(); +} + +PortabilityLayer::HostThreadEvent *GpSystemServices_Android::CreateThreadEvent(bool autoReset, bool startSignaled) +{ + GpThreadEvent_Cpp11 *evt = static_cast(malloc(sizeof(GpThreadEvent_Cpp11))); + if (!evt) + return nullptr; + + return new (evt) GpThreadEvent_Cpp11(); +} + +uint64_t GpSystemServices_Android::GetFreeMemoryCosmetic() const +{ + return 0; +} + +void GpSystemServices_Android::Beep() const +{ +} + +GpSystemServices_Android *GpSystemServices_Android::GetInstance() +{ + return &ms_instance; +} + +GpSystemServices_Android GpSystemServices_Android::ms_instance; diff --git a/AerofoilAndroid/app/jni/main/GpSystemServices_Android.h b/AerofoilAndroid/app/jni/main/GpSystemServices_Android.h new file mode 100644 index 0000000..893e67f --- /dev/null +++ b/AerofoilAndroid/app/jni/main/GpSystemServices_Android.h @@ -0,0 +1,23 @@ +#pragma once + +#include "HostSystemServices.h" +#include "GpCoreDefs.h" + +class GpSystemServices_Android final : public PortabilityLayer::HostSystemServices +{ +public: + GpSystemServices_Android(); + + int64_t GetTime() const override; + void GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const override; + PortabilityLayer::HostMutex *CreateMutex() override; + PortabilityLayer::HostMutex *CreateRecursiveMutex() override; + PortabilityLayer::HostThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) override; + uint64_t GetFreeMemoryCosmetic() const override; + void Beep() const override; + + static GpSystemServices_Android *GetInstance(); + +private: + static GpSystemServices_Android ms_instance; +}; diff --git a/AerofoilAndroid/app/src/main/.gitignore b/AerofoilAndroid/app/src/main/.gitignore new file mode 100644 index 0000000..c7ed3c8 --- /dev/null +++ b/AerofoilAndroid/app/src/main/.gitignore @@ -0,0 +1 @@ +assets diff --git a/AerofoilAndroid/make_symlinks.bat b/AerofoilAndroid/make_symlinks.bat index ca7f774..ac3508d 100644 --- a/AerofoilAndroid/make_symlinks.bat +++ b/AerofoilAndroid/make_symlinks.bat @@ -3,6 +3,20 @@ call remove_symlinks.bat + +mklink /D app\jni\AerofoilSDL ..\..\..\AerofoilSDL +mklink /D app\jni\Common ..\..\..\Common mklink /D app\jni\SDL2 ..\..\..\SDL2-2.0.12 +mklink /D app\jni\GpApp ..\..\..\GpApp +mklink /D app\jni\GpShell ..\..\..\GpShell +mklink /D app\jni\GpCommon ..\..\..\GpCommon +mklink /D app\jni\GpFontHandler_FreeType2 ..\..\..\GpFontHandler_FreeType2 +mklink /D app\jni\PortabilityLayer ..\..\..\PortabilityLayer +mklink /D app\jni\FreeType ..\..\..\FreeType +mklink /D app\jni\zlib ..\..\..\zlib +mklink /D app\jni\rapidjson ..\..\..\rapidjson +mklink /D app\jni\MacRomanConversion ..\..\..\MacRomanConversion +mklink /D app\jni\stb ..\..\..\stb +mklink /D app\src\main\assets ..\..\..\..\Packaged pause diff --git a/AerofoilAndroid/remove_symlinks.bat b/AerofoilAndroid/remove_symlinks.bat index 0fab45a..8d3e7ae 100644 --- a/AerofoilAndroid/remove_symlinks.bat +++ b/AerofoilAndroid/remove_symlinks.bat @@ -1,4 +1,17 @@ @setlocal enableextensions @cd /d "%~dp0" +rmdir app\jni\AerofoilSDL +rmdir app\jni\Common rmdir app\jni\SDL2 +rmdir app\jni\GpShell +rmdir app\jni\GpCommon +rmdir app\jni\GpApp +rmdir app\jni\GpFontHandler_FreeType2 +rmdir app\jni\PortabilityLayer +rmdir app\jni\FreeType +rmdir app\jni\zlib +rmdir app\jni\rapidjson +rmdir app\jni\MacRomanConversion +rmdir app\jni\stb +rmdir app\src\main\assets \ No newline at end of file diff --git a/AerofoilSDL/AerofoilSDL.vcxproj b/AerofoilSDL/AerofoilSDL.vcxproj index 9e82cc0..afee054 100644 --- a/AerofoilSDL/AerofoilSDL.vcxproj +++ b/AerofoilSDL/AerofoilSDL.vcxproj @@ -87,6 +87,7 @@ + diff --git a/AerofoilSDL/AerofoilSDL.vcxproj.filters b/AerofoilSDL/AerofoilSDL.vcxproj.filters index f9115f8..9947e3d 100644 --- a/AerofoilSDL/AerofoilSDL.vcxproj.filters +++ b/AerofoilSDL/AerofoilSDL.vcxproj.filters @@ -60,6 +60,9 @@ Source Files + + Source Files + diff --git a/AerofoilSDL/Android.mk b/AerofoilSDL/Android.mk new file mode 100644 index 0000000..e0e53d7 --- /dev/null +++ b/AerofoilSDL/Android.mk @@ -0,0 +1,28 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := AerofoilSDL + +SDL_PATH := ../SDL2 + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/../GpCommon \ + $(LOCAL_PATH)/../GpShell \ + $(LOCAL_PATH)/../Common \ + $(LOCAL_PATH)/../PortabilityLayer \ + $(LOCAL_PATH)/$(SDL_PATH)/include + +LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0 + +# Add your application source files here... +LOCAL_SRC_FILES := \ + GpAudioDriver_SDL2.cpp \ + GpDisplayDriver_SDL_GL2.cpp \ + GpFiber_SDL.cpp \ + GpFiberStarter_SDL.cpp \ + ShaderCode/DrawQuadPaletteP.cpp \ + ShaderCode/DrawQuadV.cpp \ + ShaderCode/ScaleQuadP.cpp + +include $(BUILD_STATIC_LIBRARY) diff --git a/AerofoilSDL/GpAudioDriver_SDL2.cpp b/AerofoilSDL/GpAudioDriver_SDL2.cpp index b0aca13..471062f 100644 --- a/AerofoilSDL/GpAudioDriver_SDL2.cpp +++ b/AerofoilSDL/GpAudioDriver_SDL2.cpp @@ -62,7 +62,7 @@ struct GpAudioChannelBufferChain_SDL2 final bool m_hasTrigger; }; -GP_ALIGNED(GP_SYSTEM_MEMORY_ALIGNMENT) class GpAudioChannel_SDL2 final : public IGpAudioChannel +class GP_ALIGNED(GP_SYSTEM_MEMORY_ALIGNMENT) GpAudioChannel_SDL2 final : public IGpAudioChannel { public: enum ChannelState @@ -104,7 +104,7 @@ private: ChannelState m_channelState; }; -GP_ALIGNED(GP_SYSTEM_MEMORY_ALIGNMENT) class GpAudioDriver_SDL2 final : public IGpAudioDriver, public IGpPrefsHandler +class GP_ALIGNED(GP_SYSTEM_MEMORY_ALIGNMENT) GpAudioDriver_SDL2 final : public IGpAudioDriver, public IGpPrefsHandler { public: friend class GpAudioChannel_SDL2; diff --git a/AerofoilSDL/GpDisplayDriver_SDL_GL2.cpp b/AerofoilSDL/GpDisplayDriver_SDL_GL2.cpp index 4cd1ede..07d36ce 100644 --- a/AerofoilSDL/GpDisplayDriver_SDL_GL2.cpp +++ b/AerofoilSDL/GpDisplayDriver_SDL_GL2.cpp @@ -4,10 +4,11 @@ #include "GpComPtr.h" #include "GpFiber_SDL.h" #include "GpDisplayDriverProperties.h" -#include "GpSystemServices_Win32.h" -#include "GpWindows.h" // TODO: Remove +//#include "GpSystemServices_Win32.h" +//#include "GpWindows.h" // TODO: Remove #include "GpVOSEvent.h" #include "GpRingBuffer.h" +#include "HostSystemServices.h" #include "IGpCursor.h" #include "IGpDisplayDriverSurface.h" #include "IGpLogDriver.h" @@ -152,7 +153,6 @@ struct GpGLFunctions PFNGLGENBUFFERSPROC GenBuffers; PFNGLBUFFERDATAPROC BufferData; - PFNGLMAPBUFFERPROC MapBuffer; PFNGLBINDBUFFERPROC BindBuffer; PFNGLDELETEBUFFERSPROC DeleteBuffers; @@ -823,8 +823,6 @@ private: SDL_Cursor *m_arrowCursor; bool m_cursorIsHidden; - - UINT m_expectedSyncDelta; bool m_isResettingSwapChain; bool m_isFullScreen; @@ -854,7 +852,6 @@ private: IGpFiber *m_vosFiber; PortabilityLayer::HostThreadEvent *m_vosEvent; - GpWindowsGlobals *m_osGlobals; float m_bgColor[4]; bool m_bgIsDark; @@ -896,6 +893,9 @@ GpDisplayDriverSurface_GL2::GpDisplayDriverSurface_GL2(GpDisplayDriver_SDL_GL2 * assert(pitch % 4 == 0); paddingPixels = pitch / 4 - width; break; + default: + assert(false); + paddingPixels = 0; } m_paddedTextureWidth = width + paddingPixels; @@ -1082,7 +1082,6 @@ GpDisplayDriver_SDL_GL2::GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties , m_lastFullScreenToggleTimeStamp(0) , m_bgIsDark(false) , m_useICCProfile(false) - , m_osGlobals(static_cast(properties.m_osGlobals)) , m_properties(properties) , m_syncTimeBase(std::chrono::time_point::duration::zero()) , m_waitCursor(nullptr) @@ -1112,7 +1111,7 @@ static bool LookupOpenGLFunction(T &target, const char *name) void *proc = SDL_GL_GetProcAddress(name); if (proc) { - target = static_cast(proc); + target = reinterpret_cast(proc); return true; } else @@ -1120,7 +1119,7 @@ static bool LookupOpenGLFunction(T &target, const char *name) } #define LOOKUP_FUNC(func) do { if (!LookupOpenGLFunction(this->func, "gl" #func)) return false; } while(false) - + bool GpGLFunctions::LookUpFunctions() { @@ -1139,12 +1138,6 @@ bool GpGLFunctions::LookUpFunctions() LOOKUP_FUNC(CheckFramebufferStatus); LOOKUP_FUNC(DeleteFramebuffers); - LOOKUP_FUNC(GenBuffers); - LOOKUP_FUNC(BufferData); - LOOKUP_FUNC(MapBuffer); - LOOKUP_FUNC(BindBuffer); - LOOKUP_FUNC(DeleteBuffers); - LOOKUP_FUNC(CreateProgram); LOOKUP_FUNC(DeleteProgram); LOOKUP_FUNC(LinkProgram); @@ -1152,6 +1145,11 @@ bool GpGLFunctions::LookUpFunctions() LOOKUP_FUNC(GetProgramiv); LOOKUP_FUNC(GetProgramInfoLog); + LOOKUP_FUNC(GenBuffers); + LOOKUP_FUNC(BufferData); + LOOKUP_FUNC(BindBuffer); + LOOKUP_FUNC(DeleteBuffers); + LOOKUP_FUNC(GetUniformLocation); LOOKUP_FUNC(GetAttribLocation); LOOKUP_FUNC(Uniform4fv); @@ -1671,7 +1669,7 @@ void GpDisplayDriver_SDL_GL2::Run() IGpLogDriver *logger = m_properties.m_logger; - m_vosEvent = GpSystemServices_Win32::GetInstance()->CreateThreadEvent(true, false); + m_vosEvent = m_properties.m_systemServices->CreateThreadEvent(true, false); m_vosFiber = new GpFiber_SDL(nullptr, m_vosEvent); m_window = SDL_CreateWindow(GP_APPLICATION_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, m_windowWidthPhysical, m_windowHeightPhysical, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); @@ -1685,10 +1683,6 @@ void GpDisplayDriver_SDL_GL2::Run() InitResources(m_windowWidthVirtual, m_windowHeightVirtual); - LARGE_INTEGER lastTimestamp; - memset(&lastTimestamp, 0, sizeof(lastTimestamp)); - - MSG msg; for (;;) { SDL_Event msg; @@ -2320,13 +2314,13 @@ bool GpDisplayDriver_SDL_GL2::ResizeOpenGLWindow(uint32_t &windowWidth, uint32_t if (desiredWidth < 640) desiredWidth = 640; - else if (desiredWidth > MAXDWORD) - desiredWidth = MAXDWORD; + else if (desiredWidth > 32768) + desiredWidth = 32768; if (desiredHeight < 480) desiredHeight = 480; - else if (desiredHeight > MAXDWORD) - desiredHeight = MAXDWORD; + else if (desiredHeight > 32768) + desiredHeight = 32768; if (logger) logger->Printf(IGpLogDriver::Category_Information, "ResizeOpenGLWindow: Adjusted dimensions: %i x %i", static_cast(desiredWidth), static_cast(desiredHeight)); @@ -2432,8 +2426,8 @@ void GpDisplayDriver_SDL_GL2::ScaleVirtualScreen() { static_cast(static_cast(m_windowWidthVirtual) / static_cast(m_windowWidthPhysical)), static_cast(static_cast(m_windowHeightVirtual) / static_cast(m_windowHeightPhysical)), - m_windowWidthVirtual, - m_windowHeightVirtual + static_cast(m_windowWidthVirtual), + static_cast(m_windowHeightVirtual) }; m_gl.Uniform4fv(m_scaleQuadProgram.m_pixelDXDYDimensionsLocation, 1, reinterpret_cast(dxdy_dimensions)); @@ -2526,7 +2520,7 @@ bool GpDisplayDriver_SDL_GL2::ScaleQuadProgram::Link(GpDisplayDriver_SDL_GL2 *dr std::vector errorMsgBuffer; errorMsgBuffer.resize(static_cast(logLength) + 1); errorMsgBuffer[logLength] = '\0'; - + gl->GetProgramInfoLog(m_program->GetID(), static_cast(logLength), nullptr, reinterpret_cast(&errorMsgBuffer[0])); const char *errorMsg = &errorMsgBuffer[0]; diff --git a/AerofoilSDL/GpFiberStarter_SDL.cpp b/AerofoilSDL/GpFiberStarter_SDL.cpp index 6b756ee..04d48d3 100644 --- a/AerofoilSDL/GpFiberStarter_SDL.cpp +++ b/AerofoilSDL/GpFiberStarter_SDL.cpp @@ -1,7 +1,7 @@ #include "GpFiberStarter.h" #include "GpFiber_SDL.h" -#include "GpSystemServices_Win32.h" +#include "HostSystemServices.h" #include "HostThreadEvent.h" #include "SDL_thread.h" @@ -14,6 +14,7 @@ namespace GpFiberStarter_SDL { GpFiberStarter::ThreadFunc_t m_threadFunc; PortabilityLayer::HostThreadEvent *m_creatingReturnEvent; + PortabilityLayer::HostThreadEvent *m_creatingWakeEvent; void *m_context; }; @@ -23,29 +24,47 @@ namespace GpFiberStarter_SDL GpFiberStarter::ThreadFunc_t threadFunc = tss->m_threadFunc; PortabilityLayer::HostThreadEvent *creatingReturnEvent = tss->m_creatingReturnEvent; + PortabilityLayer::HostThreadEvent *wakeEvent = tss->m_creatingWakeEvent; void *context = tss->m_context; creatingReturnEvent->Signal(); + wakeEvent->Wait(); + threadFunc(context); return 0; } } -IGpFiber *GpFiberStarter::StartFiber(ThreadFunc_t threadFunc, void *context, IGpFiber *creatingFiber) +IGpFiber *GpFiberStarter::StartFiber(PortabilityLayer::HostSystemServices *systemServices, ThreadFunc_t threadFunc, void *context, IGpFiber *creatingFiber) { - PortabilityLayer::HostThreadEvent *returnEvent = GpSystemServices_Win32::GetInstance()->CreateThreadEvent(true, false); + PortabilityLayer::HostThreadEvent *returnEvent = systemServices->CreateThreadEvent(true, false); + if (!returnEvent) + return nullptr; + + PortabilityLayer::HostThreadEvent *wakeEvent = systemServices->CreateThreadEvent(true, false); + if (!wakeEvent) + { + returnEvent->Destroy(); + return nullptr; + } GpFiberStarter_SDL::FiberStartState startState; startState.m_context = context; startState.m_creatingReturnEvent = returnEvent; + startState.m_creatingWakeEvent = wakeEvent; startState.m_threadFunc = threadFunc; SDL_Thread *thread = SDL_CreateThread(GpFiberStarter_SDL::FiberStartRoutine, "Fiber", &startState); if (!thread) + { + returnEvent->Destroy(); + wakeEvent->Destroy(); return nullptr; + } returnEvent->Wait(); + returnEvent->Destroy(); - return new GpFiber_SDL(thread, returnEvent); + return new GpFiber_SDL(thread, wakeEvent); } diff --git a/AerofoilSDL/GpFiber_SDL.cpp b/AerofoilSDL/GpFiber_SDL.cpp index 39f34f8..f4cfc78 100644 --- a/AerofoilSDL/GpFiber_SDL.cpp +++ b/AerofoilSDL/GpFiber_SDL.cpp @@ -2,8 +2,6 @@ #include "HostSystemServices.h" #include "HostThreadEvent.h" -#include "GpSystemServices_Win32.h" - GpFiber_SDL::GpFiber_SDL(SDL_Thread *thread, PortabilityLayer::HostThreadEvent *threadEvent) : m_event(threadEvent) , m_thread(thread) diff --git a/AerofoilSDL/ShaderCode/DrawQuadPaletteP.cpp b/AerofoilSDL/ShaderCode/DrawQuadPaletteP.cpp index cdf2f71..6150e1a 100644 --- a/AerofoilSDL/ShaderCode/DrawQuadPaletteP.cpp +++ b/AerofoilSDL/ShaderCode/DrawQuadPaletteP.cpp @@ -1,7 +1,9 @@ #include "Functions.h" #include "DrawQuadPixelConstants.h" -#define GP_GL_SHADER_CODE_DRAWQUADPALETTEP_GLSL "varying vec4 texCoord;\n"\ +#define GP_GL_SHADER_CODE_DRAWQUADPALETTEP_GLSL \ +"\n"\ +"varying vec4 texCoord;\n"\ "uniform sampler2D surfaceTexture;\n"\ "uniform sampler2D paletteTexture;\n"\ "\n"\ @@ -23,6 +25,6 @@ namespace GpBinarizedShaders { - const char *g_drawQuadPaletteP_GL2 = GP_GL_SHADER_CODE_DRAWQUADPIXELCONSTANTS_H GP_GL_SHADER_CODE_FUNCTIONS_H GP_GL_SHADER_CODE_DRAWQUADPALETTEP_GLSL; - const char *g_drawQuadPaletteICCP_GL2 = "#define USE_ICC_PROFILE\n" GP_GL_SHADER_CODE_DRAWQUADPIXELCONSTANTS_H GP_GL_SHADER_CODE_FUNCTIONS_H GP_GL_SHADER_CODE_DRAWQUADPALETTEP_GLSL; + const char *g_drawQuadPaletteP_GL2 = GP_GL_SHADER_CODE_PRECISION_PREFIX GP_GL_SHADER_CODE_DRAWQUADPIXELCONSTANTS_H GP_GL_SHADER_CODE_FUNCTIONS_H GP_GL_SHADER_CODE_DRAWQUADPALETTEP_GLSL; + const char *g_drawQuadPaletteICCP_GL2 = "#define USE_ICC_PROFILE\n" GP_GL_SHADER_CODE_PRECISION_PREFIX GP_GL_SHADER_CODE_DRAWQUADPIXELCONSTANTS_H GP_GL_SHADER_CODE_FUNCTIONS_H GP_GL_SHADER_CODE_DRAWQUADPALETTEP_GLSL; } diff --git a/AerofoilSDL/ShaderCode/Functions.h b/AerofoilSDL/ShaderCode/Functions.h index 24b1ff6..3900593 100644 --- a/AerofoilSDL/ShaderCode/Functions.h +++ b/AerofoilSDL/ShaderCode/Functions.h @@ -1,3 +1,5 @@ +#define GP_GL_SHADER_CODE_PRECISION_PREFIX "precision mediump float;\n"\ + #define GP_GL_SHADER_CODE_FUNCTIONS_H "vec3 pow3(vec3 v, float ex)\n"\ "{\n"\ " return vec3(pow(v.x, ex), pow(v.y, ex), pow(v.z, ex));\n"\ diff --git a/AerofoilSDL/ShaderCode/ScaleQuadP.cpp b/AerofoilSDL/ShaderCode/ScaleQuadP.cpp index 1cf3ffc..601f9ee 100644 --- a/AerofoilSDL/ShaderCode/ScaleQuadP.cpp +++ b/AerofoilSDL/ShaderCode/ScaleQuadP.cpp @@ -39,7 +39,7 @@ namespace GpBinarizedShaders { - const char *g_scaleQuadP_GL2 = GP_GL_SHADER_CODE_FUNCTIONS_H GP_GL_SHADER_CODE_SCALEQUADP_GLSL; + const char *g_scaleQuadP_GL2 = GP_GL_SHADER_CODE_PRECISION_PREFIX GP_GL_SHADER_CODE_FUNCTIONS_H GP_GL_SHADER_CODE_SCALEQUADP_GLSL; extern const char *g_drawQuadRGBP_GL2; extern const char *g_drawQuad15BitP_GL2; diff --git a/Common/CoreDefs.h b/Common/CoreDefs.h index 48031a6..5483174 100644 --- a/Common/CoreDefs.h +++ b/Common/CoreDefs.h @@ -1,5 +1,7 @@ #pragma once +#include + #if __cplusplus >= 199711L #define GP_IS_CPP11 1 #else diff --git a/FreeType/Android.mk b/FreeType/Android.mk new file mode 100644 index 0000000..17f10c0 --- /dev/null +++ b/FreeType/Android.mk @@ -0,0 +1,38 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := FreeType + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/freetype/include + +# Add your application source files here... +LOCAL_SRC_FILES := \ + $(LOCAL_PATH)/freetype/src/base/ftbase.c \ + $(LOCAL_PATH)/freetype/src/base/ftbitmap.c \ + $(LOCAL_PATH)/freetype/src/base/ftdebug.c \ + $(LOCAL_PATH)/freetype/src/base/ftinit.c \ + $(LOCAL_PATH)/freetype/src/base/ftsystem.c \ + $(LOCAL_PATH)/freetype/src/winfonts/winfnt.c \ + $(LOCAL_PATH)/freetype/src/autofit/autofit.c \ + $(LOCAL_PATH)/freetype/src/bdf/bdf.c \ + $(LOCAL_PATH)/freetype/src/cff/cff.c \ + $(LOCAL_PATH)/freetype/src/gzip/ftgzip.c \ + $(LOCAL_PATH)/freetype/src/lzw/ftlzw.c \ + $(LOCAL_PATH)/freetype/src/pcf/pcf.c \ + $(LOCAL_PATH)/freetype/src/pfr/pfr.c \ + $(LOCAL_PATH)/freetype/src/psaux/psaux.c \ + $(LOCAL_PATH)/freetype/src/pshinter/pshinter.c \ + $(LOCAL_PATH)/freetype/src/psnames/psnames.c \ + $(LOCAL_PATH)/freetype/src/raster/raster.c \ + $(LOCAL_PATH)/freetype/src/sfnt/sfnt.c \ + $(LOCAL_PATH)/freetype/src/smooth/smooth.c \ + $(LOCAL_PATH)/freetype/src/truetype/truetype.c \ + $(LOCAL_PATH)/freetype/src/type1/type1.c \ + $(LOCAL_PATH)/freetype/src/cid/type1cid.c \ + $(LOCAL_PATH)/freetype/src/type42/type42.c + +LOCAL_CFLAGS := -DFT2_BUILD_LIBRARY + +include $(BUILD_SHARED_LIBRARY) diff --git a/FreeType/FreeType.vcxproj.filters b/FreeType/FreeType.vcxproj.filters index 30621bc..c9d7aef 100644 --- a/FreeType/FreeType.vcxproj.filters +++ b/FreeType/FreeType.vcxproj.filters @@ -19,9 +19,6 @@ {3fb0e907-a078-4943-ab94-631783b69f75} - - {61b2d9d3-2578-438e-bbf2-52b3a0f60001} - diff --git a/GpApp/Android.mk b/GpApp/Android.mk new file mode 100644 index 0000000..e252fbb --- /dev/null +++ b/GpApp/Android.mk @@ -0,0 +1,88 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := GpApp + +SDL_PATH := ../SDL2 + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/../GpCommon \ + $(LOCAL_PATH)/../Common \ + $(LOCAL_PATH)/../PortabilityLayer + +LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0 + +# 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 \ + 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 \ + StringUtils.cpp \ + StructuresInit.cpp \ + StructuresInit2.cpp \ + Tools.cpp \ + Transit.cpp \ + Transitions.cpp \ + Triggers.cpp \ + Trip.cpp \ + Utilities.cpp \ + WindowUtils.cpp + +LOCAL_STATIC_LIBRARIES := PortabilityLayer + +include $(BUILD_SHARED_LIBRARY) diff --git a/GpApp/AnimCursor.cpp b/GpApp/AnimCursor.cpp index 8a785fa..dea8562 100644 --- a/GpApp/AnimCursor.cpp +++ b/GpApp/AnimCursor.cpp @@ -233,7 +233,7 @@ Boolean GetColorCursors (acurHandle ballCursH, compiledAcurHandle compiledBallCu short i, j; IGpCursor *hwCursor; Boolean result = true; - + if (ballCursH) { j = (*ballCursH)->n; // Get the number of cursors @@ -266,8 +266,8 @@ Boolean GetColorCursors (acurHandle ballCursH, compiledAcurHandle compiledBallCu void InitAnimatedCursor (acurHandle ballCursH) { compiledAcurHandle compiledBallCursorH; - - if (ballCursH == nil) + + if (ballCursH == nil) ballCursH = PortabilityLayer::ResourceManager::GetInstance()->GetAppResource('acur', 128).StaticCast(); if (ballCursH && ballCursH != animCursorH) { @@ -288,7 +288,7 @@ void InitAnimatedCursor (acurHandle ballCursH) //-------------------------------------------------------------- LoadCursors -// Just calls the above function. Other code could be added here thoughÉ +// Just calls the above function. Other code could be added here though? // to add additional cursors. void LoadCursors (void) @@ -302,8 +302,8 @@ void LoadCursors (void) void DisposCursors (void) { - register short i, j; - + short i, j; + if (compiledAnimCursorH != nil) { j = (*animCursorH)->n; @@ -372,7 +372,7 @@ void SpinCursor (short incrementIndex) { UInt32 dummyLong; short i; - + for (i = 0; i < incrementIndex; i++) { IncrementCursor(); @@ -388,7 +388,7 @@ void BackSpinCursor (short decrementIndex) { UInt32 dummyLong; short i; - + for (i = 0; i < decrementIndex; i++) { DecrementCursor(); diff --git a/GpApp/Environ.cpp b/GpApp/Environ.cpp index 60bcc90..5bc9abf 100644 --- a/GpApp/Environ.cpp +++ b/GpApp/Environ.cpp @@ -76,7 +76,7 @@ short GetThisVolumeRefNum (void) { PLError_t theErr; short vRef; - + theErr = GetVol(nil, &vRef); return (vRef); } @@ -87,7 +87,7 @@ short GetThisVolumeRefNum (void) long GetThisCurrentDirectoryID (void) { long dirID; - + dirID = LMGetCurDirStore(); return (dirID); } @@ -110,7 +110,7 @@ Boolean DoWeHaveGestalt (void) return (TrapExists(kGestaltTrap)); } */ -//-------------------------------------------------------------- DoWeHaveWNE +//-------------------------------------------------------------- DoWeHaveWNE // Specifically tests for the availablity of the WaitNextEvent() trap. /* @@ -119,25 +119,25 @@ Boolean DoWeHaveWNE (void) return (TrapExists(kWNETrap)); } */ -//-------------------------------------------------------------- DoWeHaveColor +//-------------------------------------------------------------- DoWeHaveColor // Determines if ROMs support Color QuickDraw (monitor not neccessarily color). /* Boolean DoWeHaveColor (void) { SysEnvRec thisWorld; - + SysEnvirons(2, &thisWorld); return (thisWorld.hasColorQD); } */ -//-------------------------------------------------------------- DoWeHaveSystem602 +//-------------------------------------------------------------- DoWeHaveSystem602 // Determines if the System version is at least 6.0.2 or more recent. /* Boolean DoWeHaveSystem602 (void) { SysEnvRec thisWorld; Boolean haveIt; - + SysEnvirons(2, &thisWorld); if (thisWorld.systemVersion >= 0x0602) haveIt = true; @@ -146,14 +146,14 @@ Boolean DoWeHaveSystem602 (void) return (haveIt); } */ -//-------------------------------------------------------------- DoWeHaveSystem605 +//-------------------------------------------------------------- DoWeHaveSystem605 // Determines if the System version is at least 6.0.5 or more recent. /* Boolean DoWeHaveSystem605 (void) { SysEnvRec thisWorld; Boolean haveIt; - + SysEnvirons(2, &thisWorld); if (thisWorld.systemVersion >= 0x0605) haveIt = true; @@ -161,16 +161,16 @@ Boolean DoWeHaveSystem605 (void) haveIt = false; return (haveIt); } -/ -//-------------------------------------------------------------- DoWeHaveSystem7 +*/ +//-------------------------------------------------------------- DoWeHaveSystem7 // Determines if the System version is at least 7.0.0 or more recent. - +/* Boolean DoWeHaveSystem7 (void) { SysEnvRec thisWorld; Boolean haveIt; - + SysEnvirons(2, &thisWorld); if (thisWorld.systemVersion >= 0x0700) haveIt = true; @@ -178,7 +178,7 @@ Boolean DoWeHaveSystem7 (void) haveIt = false; return (haveIt); } - +*/ //-------------------------------------------------------------- DoWeHaveSoundManager3 // Determines if the Sound Manager version is at least 3.0.0 or more recent. /* @@ -186,12 +186,12 @@ Boolean DoWeHaveSoundManager3 (void) { // NumVersion version; Boolean hasIt; - + hasIt = true; - + version = SndSoundManagerVersion(); hasIt = (version.majorRev >= 3); - + return hasIt; } */ @@ -213,35 +213,35 @@ void SwitchToDepth (short, Boolean) { } -//-------------------------------------------------------------- CanWeDisplay4Bit +//-------------------------------------------------------------- CanWeDisplay4Bit // Determines if device (monitor) capable of supporting 4 bit (16 colors/grays). /* Boolean CanWeDisplay4Bit (GDHandle theDevice) { short canDepth; Boolean canDo; - + canDo = false; canDepth = HasDepth(theDevice, 4, 1, 0); if (canDepth != 0) canDo = true; - + return (canDo); } */ -//-------------------------------------------------------------- CanWeDisplay1Bit +//-------------------------------------------------------------- CanWeDisplay1Bit // Determines if device (monitor) capable of supporting 1 bit (black & white). /* Boolean CanWeDisplay1Bit (GDHandle theDevice) { short canDepth; Boolean canDo; - + canDo = false; canDepth = HasDepth(theDevice, 1, 1, 0); if (canDepth != 0) canDo = true; - + return (canDo); } */ @@ -278,12 +278,12 @@ void FlushResolutionChange(void) } } -//-------------------------------------------------------------- CheckOurEnvirons -// Calls all the above functions in order to fill out a sort of "spec sheet"É +//-------------------------------------------------------------- CheckOurEnvirons +// Calls all the above functions in order to fill out a sort of "spec sheet"� // for the current Mac. void CheckOurEnvirons (void) -{ +{ thisMac.vRefNum = 0; // TEMP thisMac.dirID = 0; // TEMP thisMac.hasGestalt = true; // TEMP @@ -294,7 +294,7 @@ void CheckOurEnvirons (void) thisMac.hasSM3 = true; // TEMP thisMac.hasQT = DoWeHaveQuickTime(); thisMac.hasDrag = DoWeHaveDragManager(); - + thisMac.can1Bit = true; thisMac.can4Bit = true; thisMac.can8Bit = true; @@ -368,13 +368,13 @@ void InstallResolutionHandler(void) void ReflectSecondMonitorEnvirons (Boolean use1Bit, Boolean use4Bit, Boolean use8Bit) { GDHandle tempGDevice; - + tempGDevice = GetDeviceList(); while (tempGDevice != nil) { if (TestDeviceAttribute(tempGDevice, screenDevice)) - if ((use1Bit && CanWeDisplay1Bit(tempGDevice)) || - (use4Bit && CanWeDisplay4Bit(tempGDevice)) || + if ((use1Bit && CanWeDisplay1Bit(tempGDevice)) || + (use4Bit && CanWeDisplay4Bit(tempGDevice)) || (use8Bit && CanWeDisplay8Bit(tempGDevice))) if (!TestDeviceAttribute(tempGDevice, mainScreen)) { @@ -418,8 +418,8 @@ void HandleDepthSwitching (void) //-------------------------------------------------------------- CheckMemorySize -// Tests for a specific amount of memory available. If the required memoryÉ -// is not available, attempts to turn off various game features (music, etc.)É +// Tests for a specific amount of memory available. If the required memory� +// is not available, attempts to turn off various game features (music, etc.)� // in order to accomodate the constrained memory available. void CheckMemorySize (void) @@ -428,10 +428,10 @@ void CheckMemorySize (void) #define kPaddingBytes 204800L // 200K Padding long bytesNeeded; long soundBytes, musicBytes; - + dontLoadMusic = false; dontLoadSounds = false; - + bytesNeeded = kBaseBytesNeeded; // base memory soundBytes = SoundBytesNeeded(); // sound memory if (soundBytes <= 0L) @@ -444,15 +444,15 @@ void CheckMemorySize (void) else bytesNeeded += musicBytes; bytesNeeded += 4L * (long)thisMac.constrainedScreen.bottom; // main screen - bytesNeeded += (((long)houseRect.right - (long)houseRect.left) * - ((long)houseRect.bottom + 1 - (long)houseRect.top) * + bytesNeeded += (((long)houseRect.right - (long)houseRect.left) * + ((long)houseRect.bottom + 1 - (long)houseRect.top) * (long)thisMac.isDepth) / 8L; // work map bytesNeeded += 4L * (long)houseRect.bottom; - bytesNeeded += (((long)houseRect.right - (long)houseRect.left) * - ((long)houseRect.bottom + 1 - (long)houseRect.top) * + bytesNeeded += (((long)houseRect.right - (long)houseRect.left) * + ((long)houseRect.bottom + 1 - (long)houseRect.top) * (long)thisMac.isDepth) / 8L; // back map bytesNeeded += 4L * houseRect.bottom; - bytesNeeded += (((long)houseRect.right - (long)houseRect.left) * 21 * + bytesNeeded += (((long)houseRect.right - (long)houseRect.left) * 21 * (long)thisMac.isDepth) / 8L; // scoreboard map bytesNeeded += (6396L * (long)thisMac.isDepth) / 8L; // more scoreboard bytesNeeded += (32112L * (long)thisMac.isDepth) / 8L; // glider map @@ -516,7 +516,7 @@ void CheckMemorySize (void) bytesNeeded += sizeof(dynaType) * kMaxDynamicObs; bytesNeeded += sizeof(objDataType) * kMaxMasterObjects; bytesNeeded += kDemoLength; SpinCursor(1); - + SpinCursor(1); } diff --git a/GpApp/GliderStructs.h b/GpApp/GliderStructs.h index 3e92476..64d89e2 100644 --- a/GpApp/GliderStructs.h +++ b/GpApp/GliderStructs.h @@ -180,7 +180,7 @@ typedef struct objectType objects[kMaxRoomObs]; // 24 * 12 } roomType, *roomPtr; // total = 348 -typedef struct +struct houseType { int16_t version; // 2 int16_t unusedShort; // 2 @@ -198,9 +198,12 @@ typedef struct int16_t padding; roomType rooms[1]; // 348 * nRooms + // total = 866 + static const size_t kBinaryDataSize = 866; -} houseType, *housePtr; // total = 866 + +}; + +typedef houseType *housePtr; typedef THandle houseHand; diff --git a/GpApp/SoundSync_Cpp11.cpp b/GpApp/SoundSync_Cpp11.cpp new file mode 100644 index 0000000..12bda5e --- /dev/null +++ b/GpApp/SoundSync_Cpp11.cpp @@ -0,0 +1,30 @@ +#include "SoundSync.h" + +#include + +static std::atomic gs_prioritiesBlob(0); + +SoundSyncState SoundSync_ReadAll() +{ + const uint64_t priorities = gs_prioritiesBlob.load(std::memory_order_relaxed); + + SoundSyncState state; + state.priority0 = static_cast((priorities >> 0) & 0xffff); + state.priority1 = static_cast((priorities >> 16) & 0xffff); + state.priority2 = static_cast((priorities >> 32) & 0xffff); + state.priority3 = static_cast((priorities >> 48) & 0xffff); + + return state; +} + +void SoundSync_ClearPriority(int index) +{ + const uint64_t clearMask = ~(static_cast(0xffff) << (index * 16)); + gs_prioritiesBlob &= clearMask; +} + +void SoundSync_PutPriority(int index, int16_t priority) +{ + const uint64_t insertMask = static_cast(priority) << (index * 16); + gs_prioritiesBlob |= insertMask; +} diff --git a/GpCommon/EGpAudioDriverType.h b/GpCommon/EGpAudioDriverType.h index 7f589e3..a7199c7 100644 --- a/GpCommon/EGpAudioDriverType.h +++ b/GpCommon/EGpAudioDriverType.h @@ -1,7 +1,9 @@ #pragma once enum EGpAudioDriverType -{ +{ + EGpAudioDriverType_None, + EGpAudioDriverType_XAudio2, EGpAudioDriverType_SDL2, diff --git a/GpCommon/GpComPtr.h b/GpCommon/GpComPtr.h index eb4f317..6f42d3d 100644 --- a/GpCommon/GpComPtr.h +++ b/GpCommon/GpComPtr.h @@ -5,7 +5,7 @@ class GpComPtr final { public: GpComPtr(); - const GpComPtr(const GpComPtr &other); + GpComPtr(const GpComPtr &other); explicit GpComPtr(T *ptr); ~GpComPtr(); diff --git a/GpCommon/GpDisplayDriverProperties.h b/GpCommon/GpDisplayDriverProperties.h index 77c8f2d..a0eedef 100644 --- a/GpCommon/GpDisplayDriverProperties.h +++ b/GpCommon/GpDisplayDriverProperties.h @@ -10,6 +10,11 @@ struct IGpFiber; struct IGpVOSEventQueue; struct IGpLogDriver; +namespace PortabilityLayer +{ + class HostSystemServices; +} + struct GpDisplayDriverProperties { typedef GpDisplayDriverTickStatus_t (*TickFunc_t)(void *context, IGpFiber *vosFiber); @@ -41,4 +46,5 @@ struct GpDisplayDriverProperties IGpVOSEventQueue *m_eventQueue; IGpLogDriver *m_logger; + PortabilityLayer::HostSystemServices *m_systemServices; }; diff --git a/GpFontHandler_FreeType2/Android.mk b/GpFontHandler_FreeType2/Android.mk new file mode 100644 index 0000000..3efd541 --- /dev/null +++ b/GpFontHandler_FreeType2/Android.mk @@ -0,0 +1,20 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := GpFontHandler_FreeType2 + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/../Common \ + $(LOCAL_PATH)/../GpCommon \ + $(LOCAL_PATH)/../FreeType/freetype/include + +LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0 + +# Add your application source files here... +LOCAL_SRC_FILES := \ + GpFontHandler_FreeType2.cpp + +LOCAL_SHARED_LIBRARIES := FreeType + +include $(BUILD_STATIC_LIBRARY) diff --git a/GpFontHandler_FreeType2/GpFontHandler_FreeType2.cpp b/GpFontHandler_FreeType2/GpFontHandler_FreeType2.cpp index 73ab31e..1ee56aa 100644 --- a/GpFontHandler_FreeType2/GpFontHandler_FreeType2.cpp +++ b/GpFontHandler_FreeType2/GpFontHandler_FreeType2.cpp @@ -425,7 +425,11 @@ bool GpFontHandler_FreeType2::Init() return true; } -extern "C" __declspec(dllexport) IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties) +extern "C" +#ifdef _MSC_VER +__declspec(dllexport) +#endif +IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties) { return GpFontHandler_FreeType2::Create(); } diff --git a/GpShell/Android.mk b/GpShell/Android.mk new file mode 100644 index 0000000..aee8f56 --- /dev/null +++ b/GpShell/Android.mk @@ -0,0 +1,26 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := GpShell + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/../Common \ + $(LOCAL_PATH)/../GpCommon \ + $(LOCAL_PATH)/../PortabilityLayer + +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 \ + GpMemoryBuffer.cpp \ + GpVOSEventQueue.cpp + +include $(BUILD_STATIC_LIBRARY) diff --git a/GpShell/GpAppEnvironment.cpp b/GpShell/GpAppEnvironment.cpp index 4199eaf..a323e3f 100644 --- a/GpShell/GpAppEnvironment.cpp +++ b/GpShell/GpAppEnvironment.cpp @@ -18,6 +18,7 @@ GpAppEnvironment::GpAppEnvironment() , m_numInputDrivers(0) , m_fontHandler(nullptr) , m_vosEventQueue(nullptr) + , m_systemServices(nullptr) , m_applicationFiber(nullptr) , m_vosFiber(nullptr) , m_suspendCallID(PortabilityLayer::HostSuspendCallID_Unknown) @@ -50,7 +51,7 @@ GpDisplayDriverTickStatus_t GpAppEnvironment::Tick(IGpFiber *vosFiber) { case ApplicationState_NotStarted: InitializeApplicationState(); - m_applicationFiber = GpFiberStarter::StartFiber(GpAppEnvironment::StaticAppThreadFunc, this, vosFiber); + m_applicationFiber = GpFiberStarter::StartFiber(m_systemServices, GpAppEnvironment::StaticAppThreadFunc, this, vosFiber); m_applicationState = ApplicationState_Running; break; case ApplicationState_WaitingForEvents: @@ -125,6 +126,11 @@ void GpAppEnvironment::SetVOSEventQueue(GpVOSEventQueue *eventQueue) m_vosEventQueue = eventQueue; } +void GpAppEnvironment::SetSystemServices(PortabilityLayer::HostSystemServices *systemServices) +{ + m_systemServices = systemServices; +} + void GpAppEnvironment::StaticAppThreadFunc(void *context) { static_cast(context)->AppThreadFunc(); diff --git a/GpShell/GpAppEnvironment.h b/GpShell/GpAppEnvironment.h index 841cea3..30b58b2 100644 --- a/GpShell/GpAppEnvironment.h +++ b/GpShell/GpAppEnvironment.h @@ -10,6 +10,7 @@ namespace PortabilityLayer { union HostSuspendCallArgument; class HostVOSEventQueue; + class HostSystemServices; } struct IGpDisplayDriver; @@ -35,6 +36,7 @@ public: void SetInputDrivers(IGpInputDriver *const* inputDrivers, size_t numDrivers); void SetFontHandler(IGpFontHandler *fontHandler); void SetVOSEventQueue(GpVOSEventQueue *eventQueue); + void SetSystemServices(PortabilityLayer::HostSystemServices *systemServices); private: enum ApplicationState @@ -61,6 +63,7 @@ private: IGpInputDriver *const* m_inputDrivers; IGpFontHandler *m_fontHandler; GpVOSEventQueue *m_vosEventQueue; + PortabilityLayer::HostSystemServices *m_systemServices; IGpFiber *m_applicationFiber; IGpFiber *m_vosFiber; diff --git a/GpShell/GpFiberStarter.h b/GpShell/GpFiberStarter.h index 7c12c9b..a074401 100644 --- a/GpShell/GpFiberStarter.h +++ b/GpShell/GpFiberStarter.h @@ -1,11 +1,16 @@ #pragma once -struct IGpFiber; +struct IGpFiber; + +namespace PortabilityLayer +{ + class HostSystemServices; +} class GpFiberStarter { public: typedef void(*ThreadFunc_t)(void *context); - static IGpFiber *StartFiber(ThreadFunc_t threadFunc, void *context, IGpFiber *creatingFiber); + static IGpFiber *StartFiber(PortabilityLayer::HostSystemServices *systemServices, ThreadFunc_t threadFunc, void *context, IGpFiber *creatingFiber); }; diff --git a/GpShell/GpGlobalConfig.h b/GpShell/GpGlobalConfig.h index d1cf59e..8693c3b 100644 --- a/GpShell/GpGlobalConfig.h +++ b/GpShell/GpGlobalConfig.h @@ -1,19 +1,21 @@ -#pragma once - +#pragma once + #include "EGpDisplayDriverType.h" #include "EGpAudioDriverType.h" #include "EGpFontHandlerType.h" #include "EGpInputDriverType.h" +#include + struct IGpLogDriver; namespace PortabilityLayer -{ - class HostSystemServices; -} - -struct GpGlobalConfig -{ +{ + class HostSystemServices; +} + +struct GpGlobalConfig +{ EGpDisplayDriverType m_displayDriverType; EGpAudioDriverType m_audioDriverType; EGpFontHandlerType m_fontHandlerType; @@ -23,7 +25,7 @@ struct GpGlobalConfig IGpLogDriver *m_logger; PortabilityLayer::HostSystemServices *m_systemServices; - void *m_osGlobals; -}; - -extern GpGlobalConfig g_gpGlobalConfig; + void *m_osGlobals; +}; + +extern GpGlobalConfig g_gpGlobalConfig; diff --git a/GpShell/GpMain.cpp b/GpShell/GpMain.cpp index 0a35c6e..b75d539 100644 --- a/GpShell/GpMain.cpp +++ b/GpShell/GpMain.cpp @@ -66,6 +66,7 @@ int GpMain::Run() ddProps.m_osGlobals = g_gpGlobalConfig.m_osGlobals; ddProps.m_eventQueue = eventQueue; ddProps.m_logger = g_gpGlobalConfig.m_logger; + ddProps.m_systemServices = g_gpGlobalConfig.m_systemServices; GpAudioDriverProperties adProps; memset(&adProps, 0, sizeof(adProps)); @@ -116,6 +117,7 @@ int GpMain::Run() appEnvironment->SetInputDrivers(inputDrivers, numCreatedInputDrivers); appEnvironment->SetFontHandler(fontHandler); appEnvironment->SetVOSEventQueue(eventQueue); + appEnvironment->SetSystemServices(g_gpGlobalConfig.m_systemServices); // Start the display loop displayDriver->Run(); @@ -129,7 +131,5 @@ int GpMain::Run() free(inputDrivers); } - // GP TODO: Cleanup - return 0; } diff --git a/MacRomanConversion/Android.mk b/MacRomanConversion/Android.mk new file mode 100644 index 0000000..f56f92d --- /dev/null +++ b/MacRomanConversion/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := MacRomanConversion + +# Add your application source files here... +LOCAL_SRC_FILES := \ + MacRomanConversion.cpp + + +include $(BUILD_STATIC_LIBRARY) diff --git a/PortabilityLayer/Android.mk b/PortabilityLayer/Android.mk new file mode 100644 index 0000000..fab13a1 --- /dev/null +++ b/PortabilityLayer/Android.mk @@ -0,0 +1,112 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := PortabilityLayer + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/../GpCommon \ + $(LOCAL_PATH)/../Common \ + $(LOCAL_PATH)/../rapidjson/include \ + $(LOCAL_PATH)/../MacRomanConversion \ + $(LOCAL_PATH)/../stb + +LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0 + +# 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 \ + FontFamily.cpp \ + FontManager.cpp \ + FontRenderer.cpp \ + GPArchive.cpp \ + HostAudioDriver.cpp \ + HostDisplayDriver.cpp \ + HostFileSystem.cpp \ + HostFontHandler.cpp \ + HostInputDriver.cpp \ + HostLogDriver.cpp \ + HostSuspendHook.cpp \ + HostSystemServices.cpp \ + HostVOSEventQueue.cpp \ + IconLoader.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 \ + 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 \ + XModemCRC.cpp \ + ZipFileProxy.cpp + + +LOCAL_STATIC_LIBRARIES := zlib MacRomanConversion stb + +include $(BUILD_SHARED_LIBRARY) diff --git a/PortabilityLayer/BinHex4.cpp b/PortabilityLayer/BinHex4.cpp index bfe32c2..8e75437 100644 --- a/PortabilityLayer/BinHex4.cpp +++ b/PortabilityLayer/BinHex4.cpp @@ -1,302 +1,302 @@ -#include "BinHex4.h" -#include "GpIOStream.h" - -#include -#include -#include - -// See: https://files.stairways.com/other/binhex-40-specs-info.txt -// Unfortunately, while the spec specifies that decoding is to be done high-to-low, -// it doesn't specify how the encoded 6-bit value is split. - -#include "MacFileInfo.h" -#include "ByteUnpack.h" -#include "XModemCRC.h" -#include "MacFileMem.h" - -namespace -{ - static bool IsEOL(char c) - { - return c == '\r' || c == '\n'; - } - - static bool IsWhitespaceChar(char c) - { - return c == '\r' || c == '\n' || c == ' ' || c == '\t'; - } - - uint16_t BinHexCRCNoPadding(const uint8_t *bytes, size_t size, int initialValue) - { - uint16_t crc = initialValue; - for (size_t b = 0; b < size; b++) - { - uint8_t v = bytes[b]; - - for (int i = 0; i < 8; i++) - { - int temp = (crc & 0x8000); - crc = (crc << 1) | (v >> 7); - - if (temp) - crc = crc ^ 0x1021; - - v = (v << 1) & 0xff; - } - } - - return static_cast(crc); - } - - uint16_t BinHexCRC(const uint8_t *bytes, size_t size) - { - const uint8_t zeroBytes[] = { 0, 0 }; - - uint16_t crc = BinHexCRCNoPadding(bytes, size, 0); - return BinHexCRCNoPadding(zeroBytes, 2, crc); - } -} - -namespace PortabilityLayer -{ - MacFileMem *BinHex4::LoadHQX(GpIOStream *stream) - { - const uint8_t errCodeChar = 64; - - uint8_t charMap[128]; - for (int i = 0; i < 128; i++) - charMap[i] = errCodeChar; - - const char binHexCharacters[] = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr"; - - for (int i = 0; i < 64; i++) - charMap[binHexCharacters[i]] = static_cast(i); - - const char expectedPrefix[] = "(This file must be converted with BinHex"; - const size_t prefixSizeChars = sizeof(expectedPrefix) - 1; - char prefix[prefixSizeChars]; - - if (stream->Read(prefix, prefixSizeChars) != prefixSizeChars) - return nullptr; - - if (memcmp(prefix, expectedPrefix, prefixSizeChars)) - return nullptr; - - // Find end char - for (;;) - { - char nextChar; - if (!stream->Read(&nextChar, 1)) - return nullptr; - - if (IsEOL(nextChar)) - break; - } - - // Find start colon - for (;;) - { - char nextChar; - if (!stream->Read(&nextChar, 1)) - return nullptr; - - if (IsWhitespaceChar(nextChar)) - continue; - else if (nextChar == ':') - break; - else - return nullptr; - } - - std::vector bytesAfter6To8; - - if (stream->IsSeekable()) - { - GpUFilePos_t filePos = stream->Tell(); - if (stream->SeekEnd(0)) - { - GpUFilePos_t endPos = stream->Tell(); - if (!stream->SeekStart(filePos)) - return nullptr; - - if (endPos > filePos && (endPos - filePos) < SIZE_MAX / 6) - bytesAfter6To8.reserve(static_cast(endPos - filePos) * 6 / 8); - } - } - - // Undo 8-to-6 coding - const size_t bufferCapacity = 128; - size_t bufferReadPos = 0; - size_t bufferSize = 0; - char buffer[bufferCapacity]; - - bool isEOF = false; - - int decodedByte = 0; - int decodedByteBitPos = 8; - - for (;;) - { - if (bufferReadPos == bufferSize) - { - const size_t numRead = stream->Read(buffer, bufferCapacity); - if (numRead == 0) - return nullptr; // Missing terminator - - bufferSize = numRead; - bufferReadPos = 0; - } - - char nextChar = buffer[bufferReadPos++]; - - if (nextChar == ':') - break; - - if (IsWhitespaceChar(nextChar)) - continue; - - if (nextChar < 0 || nextChar > 127) - return nullptr; - - uint8_t value6Bit = charMap[nextChar]; - if (value6Bit == errCodeChar) - return nullptr; - - switch (decodedByteBitPos) - { - case 8: - decodedByte = value6Bit << 2; - decodedByteBitPos = 2; - break; - case 6: - decodedByte |= value6Bit; - bytesAfter6To8.push_back(decodedByte); - decodedByte = 0; - decodedByteBitPos = 8; - break; - case 4: - decodedByte |= (value6Bit >> 2); - bytesAfter6To8.push_back(decodedByte); - decodedByte = (value6Bit << 6) & 0xff; - decodedByteBitPos = 6; - break; - case 2: - decodedByte |= (value6Bit >> 4); - bytesAfter6To8.push_back(decodedByte); - decodedByte = (value6Bit << 4) & 0xff; - decodedByteBitPos = 4; - break; - default: - return nullptr; - } - } - - const size_t bytesBeforeRLEDec = bytesAfter6To8.size(); - size_t decodedDataSize = 0; - for (size_t i = 0; i < bytesBeforeRLEDec; i++) - { - const uint8_t b = bytesAfter6To8[i]; - if (b == 0x90) - { - if (i == bytesBeforeRLEDec - 1) - return nullptr; - - const uint8_t runLength = bytesAfter6To8[++i]; - - if (runLength == 0) - decodedDataSize++; // 0x90 literal - else - decodedDataSize += runLength - 1; // RLE, runs of length 1 are permitted - } - else - decodedDataSize++; - } - - std::vector decodedBytes; - decodedBytes.reserve(decodedDataSize); - - for (size_t i = 0; i < bytesBeforeRLEDec; i++) - { - const uint8_t b = bytesAfter6To8[i]; - - if (b == 0x90) - { - const uint8_t runLength = bytesAfter6To8[++i]; - - if (runLength == 0) - decodedBytes.push_back(0x90); - else - { - if (decodedBytes.size() == 0) - return nullptr; - - const uint8_t lastByte = *(decodedBytes.end() - 1); - for (size_t r = 1; r < runLength; r++) - decodedBytes.push_back(lastByte); - } - } - else - decodedBytes.push_back(b); - } - - assert(decodedBytes.size() == decodedDataSize); - - if (decodedBytes.size() == 0) - return nullptr; - - const uint8_t nameLength = decodedBytes[0]; - if (decodedBytes.size() < 22 + nameLength || nameLength > 63) - return nullptr; - - // Header format: - // uint8_t nameLength - // char name[nameLength] - // char - // char fileType[4] - // char fileCreator[4] - // word flags - // dword dataLength - // dword resourceLength - // word headerCRC - - const size_t headerStartLoc = 2 + nameLength; - - if (decodedBytes[nameLength + 1] != 0) - return nullptr; - - MacFileInfo mfi; - mfi.m_fileName.Set(nameLength, reinterpret_cast(&decodedBytes[1])); - memcpy(mfi.m_properties.m_fileType, &decodedBytes[headerStartLoc + 0], 4); - memcpy(mfi.m_properties.m_fileCreator, &decodedBytes[headerStartLoc + 4], 4); - mfi.m_properties.m_finderFlags = ByteUnpack::BigUInt16(&decodedBytes[headerStartLoc + 8]); - mfi.m_dataForkSize = ByteUnpack::BigUInt32(&decodedBytes[headerStartLoc + 10]); - mfi.m_resourceForkSize = ByteUnpack::BigUInt32(&decodedBytes[headerStartLoc + 14]); - - const size_t availableDataSize = decodedBytes.size() - 26 - nameLength; // +4 bytes for CRCs - - if (mfi.m_dataForkSize > availableDataSize || availableDataSize - mfi.m_dataForkSize < mfi.m_resourceForkSize) - return nullptr; - - const uint16_t expectedHeaderCRC = ByteUnpack::BigUInt16(&decodedBytes[headerStartLoc + 18]); - const uint16_t actualHeaderCRC = BinHexCRC(&decodedBytes[0], headerStartLoc + 18); - - if (expectedHeaderCRC != actualHeaderCRC) - return nullptr; - - const size_t dataForkStart = headerStartLoc + 20; - const size_t dataForkCRCLoc = dataForkStart + mfi.m_dataForkSize; - const size_t resourceForkStart = dataForkCRCLoc + 2; - const size_t resourceForkCRCLoc = resourceForkStart + mfi.m_resourceForkSize; - - const uint16_t expectedDataCRC = ByteUnpack::BigUInt16(&decodedBytes[dataForkCRCLoc]); - const uint16_t expectedResCRC = ByteUnpack::BigUInt16(&decodedBytes[resourceForkCRCLoc]); - - if (expectedDataCRC != BinHexCRC(&decodedBytes[dataForkStart], mfi.m_dataForkSize)) - return false; - - if (expectedResCRC != BinHexCRC(&decodedBytes[resourceForkStart], mfi.m_resourceForkSize)) - return false; - - return new MacFileMem(&decodedBytes[dataForkStart], &decodedBytes[resourceForkStart], nullptr, mfi); - } -} +#include "BinHex4.h" +#include "GpIOStream.h" + +#include +#include +#include + +// See: https://files.stairways.com/other/binhex-40-specs-info.txt +// Unfortunately, while the spec specifies that decoding is to be done high-to-low, +// it doesn't specify how the encoded 6-bit value is split. + +#include "MacFileInfo.h" +#include "ByteUnpack.h" +#include "XModemCRC.h" +#include "MacFileMem.h" + +namespace +{ + static bool IsEOL(char c) + { + return c == '\r' || c == '\n'; + } + + static bool IsWhitespaceChar(char c) + { + return c == '\r' || c == '\n' || c == ' ' || c == '\t'; + } + + uint16_t BinHexCRCNoPadding(const uint8_t *bytes, size_t size, int initialValue) + { + uint16_t crc = initialValue; + for (size_t b = 0; b < size; b++) + { + uint8_t v = bytes[b]; + + for (int i = 0; i < 8; i++) + { + int temp = (crc & 0x8000); + crc = (crc << 1) | (v >> 7); + + if (temp) + crc = crc ^ 0x1021; + + v = (v << 1) & 0xff; + } + } + + return static_cast(crc); + } + + uint16_t BinHexCRC(const uint8_t *bytes, size_t size) + { + const uint8_t zeroBytes[] = { 0, 0 }; + + uint16_t crc = BinHexCRCNoPadding(bytes, size, 0); + return BinHexCRCNoPadding(zeroBytes, 2, crc); + } +} + +namespace PortabilityLayer +{ + MacFileMem *BinHex4::LoadHQX(GpIOStream *stream) + { + const uint8_t errCodeChar = 64; + + uint8_t charMap[128]; + for (int i = 0; i < 128; i++) + charMap[i] = errCodeChar; + + const char binHexCharacters[] = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr"; + + for (int i = 0; i < 64; i++) + charMap[binHexCharacters[i]] = static_cast(i); + + const char expectedPrefix[] = "(This file must be converted with BinHex"; + const size_t prefixSizeChars = sizeof(expectedPrefix) - 1; + char prefix[prefixSizeChars]; + + if (stream->Read(prefix, prefixSizeChars) != prefixSizeChars) + return nullptr; + + if (memcmp(prefix, expectedPrefix, prefixSizeChars)) + return nullptr; + + // Find end char + for (;;) + { + char nextChar; + if (!stream->Read(&nextChar, 1)) + return nullptr; + + if (IsEOL(nextChar)) + break; + } + + // Find start colon + for (;;) + { + char nextChar; + if (!stream->Read(&nextChar, 1)) + return nullptr; + + if (IsWhitespaceChar(nextChar)) + continue; + else if (nextChar == ':') + break; + else + return nullptr; + } + + std::vector bytesAfter6To8; + + if (stream->IsSeekable()) + { + GpUFilePos_t filePos = stream->Tell(); + if (stream->SeekEnd(0)) + { + GpUFilePos_t endPos = stream->Tell(); + if (!stream->SeekStart(filePos)) + return nullptr; + + if (endPos > filePos && (endPos - filePos) < SIZE_MAX / 6) + bytesAfter6To8.reserve(static_cast(endPos - filePos) * 6 / 8); + } + } + + // Undo 8-to-6 coding + const size_t bufferCapacity = 128; + size_t bufferReadPos = 0; + size_t bufferSize = 0; + char buffer[bufferCapacity]; + + bool isEOF = false; + + int decodedByte = 0; + int decodedByteBitPos = 8; + + for (;;) + { + if (bufferReadPos == bufferSize) + { + const size_t numRead = stream->Read(buffer, bufferCapacity); + if (numRead == 0) + return nullptr; // Missing terminator + + bufferSize = numRead; + bufferReadPos = 0; + } + + char nextChar = buffer[bufferReadPos++]; + + if (nextChar == ':') + break; + + if (IsWhitespaceChar(nextChar)) + continue; + + if (nextChar < 0 || nextChar > 127) + return nullptr; + + uint8_t value6Bit = charMap[nextChar]; + if (value6Bit == errCodeChar) + return nullptr; + + switch (decodedByteBitPos) + { + case 8: + decodedByte = value6Bit << 2; + decodedByteBitPos = 2; + break; + case 6: + decodedByte |= value6Bit; + bytesAfter6To8.push_back(decodedByte); + decodedByte = 0; + decodedByteBitPos = 8; + break; + case 4: + decodedByte |= (value6Bit >> 2); + bytesAfter6To8.push_back(decodedByte); + decodedByte = (value6Bit << 6) & 0xff; + decodedByteBitPos = 6; + break; + case 2: + decodedByte |= (value6Bit >> 4); + bytesAfter6To8.push_back(decodedByte); + decodedByte = (value6Bit << 4) & 0xff; + decodedByteBitPos = 4; + break; + default: + return nullptr; + } + } + + const size_t bytesBeforeRLEDec = bytesAfter6To8.size(); + size_t decodedDataSize = 0; + for (size_t i = 0; i < bytesBeforeRLEDec; i++) + { + const uint8_t b = bytesAfter6To8[i]; + if (b == 0x90) + { + if (i == bytesBeforeRLEDec - 1) + return nullptr; + + const uint8_t runLength = bytesAfter6To8[++i]; + + if (runLength == 0) + decodedDataSize++; // 0x90 literal + else + decodedDataSize += runLength - 1; // RLE, runs of length 1 are permitted + } + else + decodedDataSize++; + } + + std::vector decodedBytes; + decodedBytes.reserve(decodedDataSize); + + for (size_t i = 0; i < bytesBeforeRLEDec; i++) + { + const uint8_t b = bytesAfter6To8[i]; + + if (b == 0x90) + { + const uint8_t runLength = bytesAfter6To8[++i]; + + if (runLength == 0) + decodedBytes.push_back(0x90); + else + { + if (decodedBytes.size() == 0) + return nullptr; + + const uint8_t lastByte = *(decodedBytes.end() - 1); + for (size_t r = 1; r < runLength; r++) + decodedBytes.push_back(lastByte); + } + } + else + decodedBytes.push_back(b); + } + + assert(decodedBytes.size() == decodedDataSize); + + if (decodedBytes.size() == 0) + return nullptr; + + const uint8_t nameLength = decodedBytes[0]; + if (decodedBytes.size() < 22 + nameLength || nameLength > 63) + return nullptr; + + // Header format: + // uint8_t nameLength + // char name[nameLength] + // char + // char fileType[4] + // char fileCreator[4] + // word flags + // dword dataLength + // dword resourceLength + // word headerCRC + + const size_t headerStartLoc = 2 + nameLength; + + if (decodedBytes[nameLength + 1] != 0) + return nullptr; + + MacFileInfo mfi; + mfi.m_fileName.Set(nameLength, reinterpret_cast(&decodedBytes[1])); + memcpy(mfi.m_properties.m_fileType, &decodedBytes[headerStartLoc + 0], 4); + memcpy(mfi.m_properties.m_fileCreator, &decodedBytes[headerStartLoc + 4], 4); + mfi.m_properties.m_finderFlags = ByteUnpack::BigUInt16(&decodedBytes[headerStartLoc + 8]); + mfi.m_dataForkSize = ByteUnpack::BigUInt32(&decodedBytes[headerStartLoc + 10]); + mfi.m_resourceForkSize = ByteUnpack::BigUInt32(&decodedBytes[headerStartLoc + 14]); + + const size_t availableDataSize = decodedBytes.size() - 26 - nameLength; // +4 bytes for CRCs + + if (mfi.m_dataForkSize > availableDataSize || availableDataSize - mfi.m_dataForkSize < mfi.m_resourceForkSize) + return nullptr; + + const uint16_t expectedHeaderCRC = ByteUnpack::BigUInt16(&decodedBytes[headerStartLoc + 18]); + const uint16_t actualHeaderCRC = BinHexCRC(&decodedBytes[0], headerStartLoc + 18); + + if (expectedHeaderCRC != actualHeaderCRC) + return nullptr; + + const size_t dataForkStart = headerStartLoc + 20; + const size_t dataForkCRCLoc = dataForkStart + mfi.m_dataForkSize; + const size_t resourceForkStart = dataForkCRCLoc + 2; + const size_t resourceForkCRCLoc = resourceForkStart + mfi.m_resourceForkSize; + + const uint16_t expectedDataCRC = ByteUnpack::BigUInt16(&decodedBytes[dataForkCRCLoc]); + const uint16_t expectedResCRC = ByteUnpack::BigUInt16(&decodedBytes[resourceForkCRCLoc]); + + if (expectedDataCRC != BinHexCRC(&decodedBytes[dataForkStart], mfi.m_dataForkSize)) + return nullptr; + + if (expectedResCRC != BinHexCRC(&decodedBytes[resourceForkStart], mfi.m_resourceForkSize)) + return nullptr; + + return new MacFileMem(&decodedBytes[dataForkStart], &decodedBytes[resourceForkStart], nullptr, mfi); + } +} diff --git a/PortabilityLayer/FileBrowserUI.h b/PortabilityLayer/FileBrowserUI.h index 407ea46..e92a63e 100644 --- a/PortabilityLayer/FileBrowserUI.h +++ b/PortabilityLayer/FileBrowserUI.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "VirtualDirectory.h" class PLPasStr; diff --git a/PortabilityLayer/HostInputDriver.h b/PortabilityLayer/HostInputDriver.h index 8593c1e..f078a84 100644 --- a/PortabilityLayer/HostInputDriver.h +++ b/PortabilityLayer/HostInputDriver.h @@ -1,5 +1,7 @@ #pragma once +#include + struct IGpInputDriver; namespace PortabilityLayer diff --git a/PortabilityLayer/HostSystemServices.h b/PortabilityLayer/HostSystemServices.h index a9b0503..29fe479 100644 --- a/PortabilityLayer/HostSystemServices.h +++ b/PortabilityLayer/HostSystemServices.h @@ -21,7 +21,7 @@ namespace PortabilityLayer virtual HostMutex *CreateMutex() = 0; virtual HostMutex *CreateRecursiveMutex() = 0; virtual HostThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) = 0; - virtual size_t GetFreeMemoryCosmetic() const = 0; // Returns free memory in bytes, does not have to be accurate + virtual uint64_t GetFreeMemoryCosmetic() const = 0; // Returns free memory in bytes, does not have to be accurate virtual void Beep() const = 0; static void SetInstance(HostSystemServices *instance); diff --git a/PortabilityLayer/HostThreadEvent.h b/PortabilityLayer/HostThreadEvent.h index 7f28481..1b277f8 100644 --- a/PortabilityLayer/HostThreadEvent.h +++ b/PortabilityLayer/HostThreadEvent.h @@ -8,7 +8,7 @@ namespace PortabilityLayer { public: virtual void Wait() = 0; - virtual void WaitTimed(uint32_t msec) = 0; + virtual bool WaitTimed(uint32_t msec) = 0; virtual void Signal() = 0; virtual void Destroy() = 0; }; diff --git a/PortabilityLayer/MacBinary2.cpp b/PortabilityLayer/MacBinary2.cpp index 105f0e2..225ecd2 100644 --- a/PortabilityLayer/MacBinary2.cpp +++ b/PortabilityLayer/MacBinary2.cpp @@ -1,185 +1,185 @@ -#include "MacBinary2.h" - -#include "BytePack.h" -#include "ByteUnpack.h" -#include "DataTypes.h" -#include "GpIOStream.h" -#include "MacFileMem.h" -#include "XModemCRC.h" - -// See: https://files.stairways.com/other/macbinaryii-standard-info.txt - -namespace -{ - namespace MB2FileOffsets - { - const unsigned int Version = 0; - const unsigned int FileNameLength = 1; - const unsigned int FileName = 2; - const unsigned int FileType = 65; - const unsigned int FileCreator = 69; - const unsigned int FinderFlagsHigh = 73; - const unsigned int YPos = 75; - const unsigned int XPos = 77; - const unsigned int Protected = 81; - const unsigned int DataForkSize = 83; - const unsigned int ResourceForkSize = 87; - const unsigned int CreationDate = 91; - const unsigned int ModifiedDate = 95; - const unsigned int CommentLength = 99; - const unsigned int FinderFlagsLow = 101; - const unsigned int DecompressedSize = 116; - const unsigned int SecondaryHeaderLength = 120; - - const unsigned int WriterVersion = 122; - const unsigned int MinVersion = 123; - const unsigned int Checksum = 124; - const unsigned int ContentStart = 128; - }; -} - -namespace PortabilityLayer -{ - void MacBinary2::WriteBin(const MacFileMem *file, GpIOStream *stream) - { - const MacFileInfo &fileInfo = file->FileInfo(); - - uint8_t mb2Header[128]; - - memset(mb2Header, 0, sizeof(mb2Header)); - - mb2Header[MB2FileOffsets::Version] = 0; - - size_t fileNameLength = fileInfo.m_fileName.Length(); - if (fileNameLength == 0) - { - mb2Header[MB2FileOffsets::FileNameLength] = 1; - mb2Header[MB2FileOffsets::FileName] = '?'; - } - else - { - if (fileNameLength > 63) - fileNameLength = 63; - - mb2Header[MB2FileOffsets::FileNameLength] = static_cast(fileNameLength); - memcpy(mb2Header + MB2FileOffsets::FileName, &fileInfo.m_fileName[0], fileNameLength); - } - - memcpy(mb2Header + MB2FileOffsets::FileType, fileInfo.m_properties.m_fileType, 4); - memcpy(mb2Header + MB2FileOffsets::FileCreator, fileInfo.m_properties.m_fileCreator, 4); - - mb2Header[MB2FileOffsets::FinderFlagsHigh] = static_cast((fileInfo.m_properties.m_finderFlags >> 8) & 0xff); - - BytePack::BigInt16(mb2Header + MB2FileOffsets::YPos, fileInfo.m_properties.m_yPos); - BytePack::BigInt16(mb2Header + MB2FileOffsets::XPos, fileInfo.m_properties.m_xPos); - mb2Header[MB2FileOffsets::Protected] = fileInfo.m_properties.m_protected; - BytePack::BigUInt32(mb2Header + MB2FileOffsets::DataForkSize, fileInfo.m_dataForkSize); - BytePack::BigUInt32(mb2Header + MB2FileOffsets::ResourceForkSize, fileInfo.m_resourceForkSize); - BytePack::BigUInt32(mb2Header + MB2FileOffsets::CreationDate, fileInfo.m_properties.m_creationDate); - BytePack::BigUInt32(mb2Header + MB2FileOffsets::ModifiedDate, fileInfo.m_properties.m_modifiedDate); - - BytePack::BigUInt16(mb2Header + MB2FileOffsets::CommentLength, fileInfo.m_commentSize); - mb2Header[MB2FileOffsets::FinderFlagsLow] = static_cast(fileInfo.m_properties.m_finderFlags & 0xff); - // DecompressedSize is unused - // SecondaryHeaderLength is zero - - mb2Header[MB2FileOffsets::WriterVersion] = 129; - mb2Header[MB2FileOffsets::MinVersion] = 129; - - BytePack::BigUInt16(mb2Header + MB2FileOffsets::Checksum, XModemCRC(mb2Header, 124, 0)); - - stream->Write(mb2Header, 128); - - uint8_t *padding = mb2Header; - memset(padding, 0, 128); - - const size_t dataForkPadding = 127 - ((fileInfo.m_dataForkSize + 127) % 128); - const size_t resourceForkPadding = 127 - ((fileInfo.m_resourceForkSize + 127) % 128); - - stream->Write(file->DataFork(), fileInfo.m_dataForkSize); - stream->Write(padding, dataForkPadding); - stream->Write(file->ResourceFork(), fileInfo.m_resourceForkSize); - stream->Write(padding, resourceForkPadding); - } - - MacFileMem *MacBinary2::ReadBin(GpIOStream *stream) - { - MacFileInfo fileInfo; - - uint8_t mb2Header[128]; - - if (stream->Read(mb2Header, 128) != 128) - return nullptr; - - if (mb2Header[MB2FileOffsets::Version] != 0) - return nullptr; - - const uint8_t fileNameLength = mb2Header[MB2FileOffsets::FileNameLength]; - if (fileNameLength < 1 || fileNameLength > 63) - return nullptr; - - fileInfo.m_fileName.Set(fileNameLength, reinterpret_cast(mb2Header + MB2FileOffsets::FileName)); - - memcpy(fileInfo.m_properties.m_fileType, mb2Header + MB2FileOffsets::FileType, 4); - memcpy(fileInfo.m_properties.m_fileCreator, mb2Header + MB2FileOffsets::FileCreator, 4); - - fileInfo.m_properties.m_finderFlags = mb2Header[MB2FileOffsets::FinderFlagsHigh] << 8; - - fileInfo.m_properties.m_yPos = ByteUnpack::BigInt16(mb2Header + MB2FileOffsets::YPos); - fileInfo.m_properties.m_xPos = ByteUnpack::BigInt16(mb2Header + MB2FileOffsets::XPos); - fileInfo.m_properties.m_protected = mb2Header[MB2FileOffsets::Protected]; - fileInfo.m_dataForkSize = ByteUnpack::BigUInt32(mb2Header + MB2FileOffsets::DataForkSize); - fileInfo.m_resourceForkSize = ByteUnpack::BigUInt32(mb2Header + MB2FileOffsets::ResourceForkSize); - fileInfo.m_properties.m_creationDate = ByteUnpack::BigUInt32(mb2Header + MB2FileOffsets::CreationDate); - fileInfo.m_properties.m_modifiedDate = ByteUnpack::BigUInt32(mb2Header + MB2FileOffsets::ModifiedDate); - - fileInfo.m_commentSize = ByteUnpack::BigUInt16(mb2Header + MB2FileOffsets::CommentLength); - fileInfo.m_properties.m_finderFlags |= mb2Header[MB2FileOffsets::FinderFlagsLow]; - - if (ByteUnpack::BigInt16(mb2Header + MB2FileOffsets::SecondaryHeaderLength) != 0) - return nullptr; - - uint16_t crc = ByteUnpack::BigUInt16(mb2Header + MB2FileOffsets::Checksum); - - uint16_t expectedCRC = XModemCRC(mb2Header, 124, 0); - - if (fileInfo.m_dataForkSize > SIZE_MAX) - return nullptr; - - if (fileInfo.m_resourceForkSize > SIZE_MAX) - return nullptr; - - uint8_t *dataBuffer = nullptr; - uint8_t *rsrcBuffer = nullptr; - - if (fileInfo.m_dataForkSize != 0) - dataBuffer = new uint8_t[fileInfo.m_dataForkSize]; - - if (fileInfo.m_resourceForkSize != 0) - rsrcBuffer = new uint8_t[fileInfo.m_resourceForkSize]; - - ScopedArray dataContents = dataBuffer; - ScopedArray rsrcContents = rsrcBuffer; - - uint8_t *padding = mb2Header; - - const size_t dataForkPadding = 127 - ((fileInfo.m_dataForkSize + 127) % 128); - const size_t resourceForkPadding = 127 - ((fileInfo.m_resourceForkSize + 127) % 128); - - if (stream->Read(dataBuffer, fileInfo.m_dataForkSize) != fileInfo.m_dataForkSize) - return nullptr; - - if (stream->Read(padding, dataForkPadding) != dataForkPadding) - return nullptr; - - if (stream->Read(rsrcBuffer, fileInfo.m_resourceForkSize) != fileInfo.m_resourceForkSize) - return nullptr; - - if (stream->Read(padding, resourceForkPadding) != resourceForkPadding) - return nullptr; - - // Ignore comment for now - return new MacFileMem(dataBuffer, rsrcBuffer, nullptr, fileInfo); - } -} - +#include "MacBinary2.h" + +#include "BytePack.h" +#include "ByteUnpack.h" +#include "DataTypes.h" +#include "GpIOStream.h" +#include "MacFileMem.h" +#include "XModemCRC.h" + +// See: https://files.stairways.com/other/macbinaryii-standard-info.txt + +namespace +{ + namespace MB2FileOffsets + { + const unsigned int Version = 0; + const unsigned int FileNameLength = 1; + const unsigned int FileName = 2; + const unsigned int FileType = 65; + const unsigned int FileCreator = 69; + const unsigned int FinderFlagsHigh = 73; + const unsigned int YPos = 75; + const unsigned int XPos = 77; + const unsigned int Protected = 81; + const unsigned int DataForkSize = 83; + const unsigned int ResourceForkSize = 87; + const unsigned int CreationDate = 91; + const unsigned int ModifiedDate = 95; + const unsigned int CommentLength = 99; + const unsigned int FinderFlagsLow = 101; + const unsigned int DecompressedSize = 116; + const unsigned int SecondaryHeaderLength = 120; + + const unsigned int WriterVersion = 122; + const unsigned int MinVersion = 123; + const unsigned int Checksum = 124; + const unsigned int ContentStart = 128; + }; +} + +namespace PortabilityLayer +{ + void MacBinary2::WriteBin(const MacFileMem *file, GpIOStream *stream) + { + const MacFileInfo &fileInfo = file->FileInfo(); + + uint8_t mb2Header[128]; + + memset(mb2Header, 0, sizeof(mb2Header)); + + mb2Header[MB2FileOffsets::Version] = 0; + + size_t fileNameLength = fileInfo.m_fileName.Length(); + if (fileNameLength == 0) + { + mb2Header[MB2FileOffsets::FileNameLength] = 1; + mb2Header[MB2FileOffsets::FileName] = '?'; + } + else + { + if (fileNameLength > 63) + fileNameLength = 63; + + mb2Header[MB2FileOffsets::FileNameLength] = static_cast(fileNameLength); + memcpy(mb2Header + MB2FileOffsets::FileName, &fileInfo.m_fileName[0], fileNameLength); + } + + memcpy(mb2Header + MB2FileOffsets::FileType, fileInfo.m_properties.m_fileType, 4); + memcpy(mb2Header + MB2FileOffsets::FileCreator, fileInfo.m_properties.m_fileCreator, 4); + + mb2Header[MB2FileOffsets::FinderFlagsHigh] = static_cast((fileInfo.m_properties.m_finderFlags >> 8) & 0xff); + + BytePack::BigInt16(mb2Header + MB2FileOffsets::YPos, fileInfo.m_properties.m_yPos); + BytePack::BigInt16(mb2Header + MB2FileOffsets::XPos, fileInfo.m_properties.m_xPos); + mb2Header[MB2FileOffsets::Protected] = fileInfo.m_properties.m_protected; + BytePack::BigUInt32(mb2Header + MB2FileOffsets::DataForkSize, fileInfo.m_dataForkSize); + BytePack::BigUInt32(mb2Header + MB2FileOffsets::ResourceForkSize, fileInfo.m_resourceForkSize); + BytePack::BigUInt32(mb2Header + MB2FileOffsets::CreationDate, fileInfo.m_properties.m_creationDate); + BytePack::BigUInt32(mb2Header + MB2FileOffsets::ModifiedDate, fileInfo.m_properties.m_modifiedDate); + + BytePack::BigUInt16(mb2Header + MB2FileOffsets::CommentLength, fileInfo.m_commentSize); + mb2Header[MB2FileOffsets::FinderFlagsLow] = static_cast(fileInfo.m_properties.m_finderFlags & 0xff); + // DecompressedSize is unused + // SecondaryHeaderLength is zero + + mb2Header[MB2FileOffsets::WriterVersion] = 129; + mb2Header[MB2FileOffsets::MinVersion] = 129; + + BytePack::BigUInt16(mb2Header + MB2FileOffsets::Checksum, XModemCRC(mb2Header, 124, 0)); + + stream->Write(mb2Header, 128); + + uint8_t *padding = mb2Header; + memset(padding, 0, 128); + + const size_t dataForkPadding = 127 - ((fileInfo.m_dataForkSize + 127) % 128); + const size_t resourceForkPadding = 127 - ((fileInfo.m_resourceForkSize + 127) % 128); + + stream->Write(file->DataFork(), fileInfo.m_dataForkSize); + stream->Write(padding, dataForkPadding); + stream->Write(file->ResourceFork(), fileInfo.m_resourceForkSize); + stream->Write(padding, resourceForkPadding); + } + + MacFileMem *MacBinary2::ReadBin(GpIOStream *stream) + { + MacFileInfo fileInfo; + + uint8_t mb2Header[128]; + + if (stream->Read(mb2Header, 128) != 128) + return nullptr; + + if (mb2Header[MB2FileOffsets::Version] != 0) + return nullptr; + + const uint8_t fileNameLength = mb2Header[MB2FileOffsets::FileNameLength]; + if (fileNameLength < 1 || fileNameLength > 63) + return nullptr; + + fileInfo.m_fileName.Set(fileNameLength, reinterpret_cast(mb2Header + MB2FileOffsets::FileName)); + + memcpy(fileInfo.m_properties.m_fileType, mb2Header + MB2FileOffsets::FileType, 4); + memcpy(fileInfo.m_properties.m_fileCreator, mb2Header + MB2FileOffsets::FileCreator, 4); + + fileInfo.m_properties.m_finderFlags = mb2Header[MB2FileOffsets::FinderFlagsHigh] << 8; + + fileInfo.m_properties.m_yPos = ByteUnpack::BigInt16(mb2Header + MB2FileOffsets::YPos); + fileInfo.m_properties.m_xPos = ByteUnpack::BigInt16(mb2Header + MB2FileOffsets::XPos); + fileInfo.m_properties.m_protected = mb2Header[MB2FileOffsets::Protected]; + fileInfo.m_dataForkSize = ByteUnpack::BigUInt32(mb2Header + MB2FileOffsets::DataForkSize); + fileInfo.m_resourceForkSize = ByteUnpack::BigUInt32(mb2Header + MB2FileOffsets::ResourceForkSize); + fileInfo.m_properties.m_creationDate = ByteUnpack::BigUInt32(mb2Header + MB2FileOffsets::CreationDate); + fileInfo.m_properties.m_modifiedDate = ByteUnpack::BigUInt32(mb2Header + MB2FileOffsets::ModifiedDate); + + fileInfo.m_commentSize = ByteUnpack::BigUInt16(mb2Header + MB2FileOffsets::CommentLength); + fileInfo.m_properties.m_finderFlags |= mb2Header[MB2FileOffsets::FinderFlagsLow]; + + if (ByteUnpack::BigInt16(mb2Header + MB2FileOffsets::SecondaryHeaderLength) != 0) + return nullptr; + + uint16_t crc = ByteUnpack::BigUInt16(mb2Header + MB2FileOffsets::Checksum); + + uint16_t expectedCRC = XModemCRC(mb2Header, 124, 0); + + if (fileInfo.m_dataForkSize > SIZE_MAX) + return nullptr; + + if (fileInfo.m_resourceForkSize > SIZE_MAX) + return nullptr; + + uint8_t *dataBuffer = nullptr; + uint8_t *rsrcBuffer = nullptr; + + if (fileInfo.m_dataForkSize != 0) + dataBuffer = new uint8_t[fileInfo.m_dataForkSize]; + + if (fileInfo.m_resourceForkSize != 0) + rsrcBuffer = new uint8_t[fileInfo.m_resourceForkSize]; + + ScopedArray dataContents(dataBuffer); + ScopedArray rsrcContents(rsrcBuffer); + + uint8_t *padding = mb2Header; + + const size_t dataForkPadding = 127 - ((fileInfo.m_dataForkSize + 127) % 128); + const size_t resourceForkPadding = 127 - ((fileInfo.m_resourceForkSize + 127) % 128); + + if (stream->Read(dataBuffer, fileInfo.m_dataForkSize) != fileInfo.m_dataForkSize) + return nullptr; + + if (stream->Read(padding, dataForkPadding) != dataForkPadding) + return nullptr; + + if (stream->Read(rsrcBuffer, fileInfo.m_resourceForkSize) != fileInfo.m_resourceForkSize) + return nullptr; + + if (stream->Read(padding, resourceForkPadding) != resourceForkPadding) + return nullptr; + + // Ignore comment for now + return new MacFileMem(dataBuffer, rsrcBuffer, nullptr, fileInfo); + } +} + diff --git a/PortabilityLayer/MenuManager.cpp b/PortabilityLayer/MenuManager.cpp index 8240f4b..53790e0 100644 --- a/PortabilityLayer/MenuManager.cpp +++ b/PortabilityLayer/MenuManager.cpp @@ -706,6 +706,8 @@ namespace PortabilityLayer if (evt.m_vosEvent.m_event.m_mouseInputEvent.m_button == GpMouseButtons::kLeft) canDismiss = true; break; + default: + break; } } } @@ -764,6 +766,8 @@ namespace PortabilityLayer if (evt.m_vosEvent.m_event.m_mouseInputEvent.m_button == GpMouseButtons::kLeft) canDismiss = true; break; + default: + break; } } } diff --git a/PortabilityLayer/PLCore.cpp b/PortabilityLayer/PLCore.cpp index c690e40..d5a3540 100644 --- a/PortabilityLayer/PLCore.cpp +++ b/PortabilityLayer/PLCore.cpp @@ -298,7 +298,7 @@ void NumToString(long number, unsigned char *str) number /= 10; *outChar = '0' + digit; - *outChar++; + outChar++; } const ptrdiff_t strLength = outChar - firstChar; @@ -753,7 +753,7 @@ bool Window::ReplaceWidget(PortabilityLayer::Widget *oldWidget, PortabilityLayer oldWidget->Destroy(); m_widgets[i] = newWidget; - newWidget->m_window = this; + newWidget->SetWindow(this); newWidget->DrawControl(&m_surface); m_surface.m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents); diff --git a/PortabilityLayer/PLEditboxWidget.h b/PortabilityLayer/PLEditboxWidget.h index e99852a..db6ebba 100644 --- a/PortabilityLayer/PLEditboxWidget.h +++ b/PortabilityLayer/PLEditboxWidget.h @@ -29,7 +29,7 @@ namespace PortabilityLayer Rect GetExpandedRect() const override; - bool HandlesTickEvents() const; + bool HandlesTickEvents() const override; void SetSelection(size_t startChar, size_t endChar); @@ -87,7 +87,7 @@ namespace PortabilityLayer CaratSelectionAnchor m_caratSelectionAnchor; // Where the carat is attached to the selection range Vec2i m_caratScrollPosition; // Ideal position of the carat in the editbox, but not necessarily its actual location (i.e. may be in the middle of a glyph) - bool m_caratScrollLocked; // If true, the vertical position + bool m_caratScrollLocked; // If true, the vertical position Vec2i m_scrollOffset; diff --git a/PortabilityLayer/PLPopupMenuWidget.h b/PortabilityLayer/PLPopupMenuWidget.h index a289ba0..7c9e7d3 100644 --- a/PortabilityLayer/PLPopupMenuWidget.h +++ b/PortabilityLayer/PLPopupMenuWidget.h @@ -14,8 +14,8 @@ namespace PortabilityLayer bool Init(const WidgetBasicState &state, const void *additionalData) override; - WidgetHandleState_t ProcessEvent(void *captureContext, const TimeTaggedVOSEvent &evt); - int16_t Capture(void *captureContext, const Point &pos, WidgetUpdateCallback_t callback); + WidgetHandleState_t ProcessEvent(void *captureContext, const TimeTaggedVOSEvent &evt) override; + int16_t Capture(void *captureContext, const Point &pos, WidgetUpdateCallback_t callback) override; void DrawControl(DrawSurface *surface) override; void OnStateChanged() override; diff --git a/PortabilityLayer/PLQDraw.cpp b/PortabilityLayer/PLQDraw.cpp index c726b9e..a52fbe4 100644 --- a/PortabilityLayer/PLQDraw.cpp +++ b/PortabilityLayer/PLQDraw.cpp @@ -1783,6 +1783,7 @@ static void CopyBitsComplete(const BitMap *srcBitmap, const BitMap *maskBitmap8, { case GpPixelFormats::k8BitCustom: case GpPixelFormats::k8BitStandard: + case GpPixelFormats::kBW1: pixelSizeBytes = 1; break; case GpPixelFormats::kRGB555: @@ -1794,6 +1795,8 @@ static void CopyBitsComplete(const BitMap *srcBitmap, const BitMap *maskBitmap8, case GpPixelFormats::kRGB32: pixelSizeBytes = 4; break; + default: + return; }; const uint8_t *srcBytes = static_cast(srcBitmap->m_data); @@ -2029,8 +2032,8 @@ void DebugPixMap(PixMap **pixMapH, const char *outName) { PixMap *pixMap = *pixMapH; char outPath[1024]; - strcpy_s(outPath, outName); - strcat_s(outPath, ".png"); + strcpy(outPath, outName); + strcat(outPath, ".png"); stbi_write_png(outPath, pixMap->m_rect.right - pixMap->m_rect.left, pixMap->m_rect.bottom - pixMap->m_rect.top, 1, pixMap->m_data, pixMap->m_pitch); } diff --git a/PortabilityLayer/PLSound.cpp b/PortabilityLayer/PLSound.cpp index 699a4af..0418bae 100644 --- a/PortabilityLayer/PLSound.cpp +++ b/PortabilityLayer/PLSound.cpp @@ -179,7 +179,7 @@ namespace PortabilityLayer { AudioCommand cmd; cmd.m_commandType = AudioCommandTypes::kCallback; - cmd.m_param.m_ptr = callback; + cmd.m_param.m_ptr = reinterpret_cast(callback); return this->PushCommand(cmd, blocking); } diff --git a/PortabilityLayer/PLSysCalls.cpp b/PortabilityLayer/PLSysCalls.cpp index b65660d..ca42bda 100644 --- a/PortabilityLayer/PLSysCalls.cpp +++ b/PortabilityLayer/PLSysCalls.cpp @@ -71,7 +71,7 @@ static void TranslateKeyboardInputEvent(const GpVOSEvent &vosEventBase, uint32_t inputManager->ApplyKeyboardEvent(vosEvent); // Special handling of alt-enter, redirect to display driver - if (vosEventBase.m_eventType == GpKeyboardInputEventTypes::kDown && + if (vosEventBase.m_event.m_keyboardInputEvent.m_eventType == GpKeyboardInputEventTypes::kDown && vosEventBase.m_event.m_keyboardInputEvent.m_keyIDSubset == GpKeyIDSubsets::kSpecial && vosEventBase.m_event.m_keyboardInputEvent.m_key.m_specialKey == GpKeySpecials::kEnter) { diff --git a/PortabilityLayer/PLWidgets.cpp b/PortabilityLayer/PLWidgets.cpp index d99a7df..507a286 100644 --- a/PortabilityLayer/PLWidgets.cpp +++ b/PortabilityLayer/PLWidgets.cpp @@ -139,6 +139,11 @@ namespace PortabilityLayer return m_rect; } + void Widget::SetWindow(Window *window) + { + m_window = window; + } + Window *Widget::GetWindow() const { return m_window; diff --git a/PortabilityLayer/PLWidgets.h b/PortabilityLayer/PLWidgets.h index 3f5f45e..b28f9fc 100644 --- a/PortabilityLayer/PLWidgets.h +++ b/PortabilityLayer/PLWidgets.h @@ -80,21 +80,23 @@ namespace PortabilityLayer virtual int ResolvePart(const Point &point) const; const Rect &GetRect() const; - Window *GetWindow() const; - protected: - friend struct Window; + void SetWindow(Window *window); + Window *GetWindow() const; virtual void GainFocus(); virtual void LoseFocus(); - explicit Widget(const WidgetBasicState &state); - virtual ~Widget(); - virtual void OnEnabledChanged(); virtual void OnStateChanged(); virtual void OnTick(); + protected: + friend struct Window; + + explicit Widget(const WidgetBasicState &state); + virtual ~Widget(); + static void BaseRelease(void *storage); static void *BaseAlloc(size_t sz); diff --git a/stb/Android.mk b/stb/Android.mk new file mode 100644 index 0000000..3ca5222 --- /dev/null +++ b/stb/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := stb + +# Add your application source files here... +LOCAL_SRC_FILES := \ + stb_image_write.c + + +include $(BUILD_STATIC_LIBRARY) diff --git a/zlib/Android.mk b/zlib/Android.mk new file mode 100644 index 0000000..7cf2dd7 --- /dev/null +++ b/zlib/Android.mk @@ -0,0 +1,19 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := zlib + +# Add your application source files here... +LOCAL_SRC_FILES := \ + adler32.c \ + crc32.c \ + deflate.c \ + inffast.c \ + inflate.c \ + inftrees.c \ + trees.c \ + zutil.c + + +include $(BUILD_STATIC_LIBRARY)