diff --git a/CMakeLists.txt b/CMakeLists.txt index 80a51768..fc495a52 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,9 @@ cmake_minimum_required(VERSION 3.15 FATAL_ERROR) # MSVC runtime library flags are selected by an abstraction cmake_policy(SET CMP0091 NEW) +# To set BUILD_* variables for iniparser below. Is there another way? +set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) + project(isle CXX C) # By configuring CMake with -DDOWNLOAD_DEPENDENCIES=ON/OFF, @@ -19,11 +22,23 @@ if(DOWNLOAD_DEPENDENCIES) EXCLUDE_FROM_ALL ) FetchContent_MakeAvailable(SDL3) + + FetchContent_Declare( + iniparser + GIT_REPOSITORY "https://github.com/ndevilla/iniparser.git" + GIT_TAG "main" + EXCLUDE_FROM_ALL + ) + set(BUILD_DOCS off) + set(BUILD_SHARED_LIBS off) + FetchContent_MakeAvailable(iniparser) else() # find_package looks for already-installed system packages. # Configure with `-DCMAKE_PREFIX_PATH="/path/to/package1;/path/to/package2"` # to add search paths. find_package(SDL3 CONFIG REQUIRED) + + # TODO add iniparser? endif() include(CheckCXXSourceCompiles) @@ -479,7 +494,10 @@ if (ISLE_BUILD_APP) target_compile_definitions(isle PRIVATE ISLE_APP) # Use internal DirectX 5 if required - target_link_libraries(isle PRIVATE $<$:DirectX5::DirectX5> SDL3::SDL3) + target_link_libraries(isle PRIVATE $<$:DirectX5::DirectX5>) + + # Link SDL and iniparser + target_link_libraries(isle PRIVATE SDL3::SDL3 iniparser-static) # Link DSOUND, WINMM, and LEGO1 target_link_libraries(isle PRIVATE dsound winmm lego1) diff --git a/ISLE/isleapp.cpp b/ISLE/isleapp.cpp index c0b23b38..6d442923 100644 --- a/ISLE/isleapp.cpp +++ b/ISLE/isleapp.cpp @@ -28,8 +28,11 @@ #include "viewmanager/viewmanager.h" #define SDL_MAIN_USE_CALLBACKS +#include +#include #include #include +#include DECOMP_SIZE_ASSERT(IsleApp, 0x8c) @@ -240,6 +243,9 @@ void IsleApp::SetupVideoFlags( int SDL_AppInit(void** appstate, int argc, char** argv) { + // Add subsystems as necessary later + SDL_Init(SDL_INIT_TIMER); + // Look for another instance, if we find one, bring it to the foreground instead if (!FindExistingInstance()) { return 1; @@ -348,6 +354,7 @@ int SDL_AppEvent(void* appstate, const SDL_Event* event) void SDL_AppQuit(void* appstate) { DestroyWindow((HWND) appstate); + SDL_Quit(); } // FUNCTION: ISLE 0x401ca0 @@ -694,97 +701,42 @@ MxResult IsleApp::SetupWindow(HINSTANCE hInstance, LPSTR lpCmdLine) return SUCCESS; } -// FUNCTION: ISLE 0x402740 -BOOL IsleApp::ReadReg(LPCSTR name, LPSTR outValue, DWORD outSize) -{ - HKEY hKey; - DWORD valueType; - - BOOL out = FALSE; - DWORD size = outSize; - if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Mindscape\\LEGO Island", 0, KEY_READ, &hKey) == ERROR_SUCCESS) { - if (RegQueryValueExA(hKey, name, NULL, &valueType, (LPBYTE) outValue, &size) == ERROR_SUCCESS) { - if (RegCloseKey(hKey) == ERROR_SUCCESS) { - out = TRUE; - } - } - } - - return out; -} - -// FUNCTION: ISLE 0x4027b0 -BOOL IsleApp::ReadRegBool(LPCSTR name, BOOL* out) -{ - char buffer[256]; - - BOOL read = ReadReg(name, buffer, sizeof(buffer)); - if (read) { - if (strcmp("YES", buffer) == 0) { - *out = TRUE; - return read; - } - - if (strcmp("NO", buffer) == 0) { - *out = FALSE; - return read; - } - - read = FALSE; - } - return read; -} - -// FUNCTION: ISLE 0x402880 -BOOL IsleApp::ReadRegInt(LPCSTR name, int* out) -{ - char buffer[256]; - - BOOL read = ReadReg(name, buffer, sizeof(buffer)); - if (read) { - *out = atoi(buffer); - } - - return read; -} - // FUNCTION: ISLE 0x4028d0 void IsleApp::LoadConfig() { - char buffer[1024]; - - if (!ReadReg("diskpath", buffer, sizeof(buffer))) { - strcpy(buffer, MxOmni::GetHD()); - } - - m_hdPath = new char[strlen(buffer) + 1]; - strcpy(m_hdPath, buffer); + char* basePath = SDL_GetBasePath(); + char* prefPath = SDL_GetPrefPath("isledecomp", "isle"); + char* iniConfig = new char[strlen(prefPath) + strlen("isle.ini") + 1](); + strcat(iniConfig, prefPath); + strcat(iniConfig, "isle.ini"); + dictionary* dict = iniparser_load(iniConfig); + + const char* hdPath = iniparser_getstring(dict, "isle:diskpath", basePath); + m_hdPath = new char[strlen(hdPath) + 1]; + strcpy(m_hdPath, hdPath); MxOmni::SetHD(m_hdPath); - if (!ReadReg("cdpath", buffer, sizeof(buffer))) { - strcpy(buffer, MxOmni::GetCD()); - } - - m_cdPath = new char[strlen(buffer) + 1]; - strcpy(m_cdPath, buffer); + const char* cdPath = iniparser_getstring(dict, "isle:cdpath", MxOmni::GetCD()); + m_cdPath = new char[strlen(cdPath) + 1]; + strcpy(m_cdPath, cdPath); MxOmni::SetCD(m_cdPath); - ReadRegBool("Flip Surfaces", &m_flipSurfaces); - ReadRegBool("Full Screen", &m_fullScreen); - ReadRegBool("Wide View Angle", &m_wideViewAngle); - ReadRegBool("3DSound", &m_use3dSound); - ReadRegBool("Music", &m_useMusic); - ReadRegBool("UseJoystick", &m_useJoystick); - ReadRegInt("JoystickIndex", &m_joystickIndex); - ReadRegBool("Draw Cursor", &m_drawCursor); - - int backBuffersInVRAM; - if (ReadRegBool("Back Buffers in Video RAM", &backBuffersInVRAM)) { + m_flipSurfaces = iniparser_getboolean(dict, "isle:Flip Surfaces", m_flipSurfaces); + m_fullScreen = iniparser_getboolean(dict, "isle:Full Screen", m_fullScreen); + m_wideViewAngle = iniparser_getboolean(dict, "isle:Wide View Angle", m_wideViewAngle); + m_use3dSound = iniparser_getboolean(dict, "isle:3DSound", m_use3dSound); + m_useMusic = iniparser_getboolean(dict, "isle:Music", m_useMusic); + m_useJoystick = iniparser_getboolean(dict, "isle:UseJoystick", m_useJoystick); + m_joystickIndex = iniparser_getint(dict, "isle:JoystickIndex", m_joystickIndex); + m_drawCursor = iniparser_getboolean(dict, "isle:Draw Cursor", m_drawCursor); + + int backBuffersInVRAM = iniparser_getboolean(dict, "isle:Back Buffers in Video RAM", -1); + if (backBuffersInVRAM != -1) { m_backBuffersInVram = !backBuffersInVRAM; } - int bitDepth; - if (ReadRegInt("Display Bit Depth", &bitDepth)) { + int bitDepth = iniparser_getint(dict, "isle:Display Bit Depth", -1); + if (bitDepth != -1) { if (bitDepth == 8) { m_using8bit = TRUE; } @@ -793,25 +745,25 @@ void IsleApp::LoadConfig() } } - if (!ReadReg("Island Quality", buffer, sizeof(buffer))) { - strcpy(buffer, "1"); - } - m_islandQuality = atoi(buffer); + m_islandQuality = iniparser_getint(dict, "isle:Island Quality", 1); + m_islandTexture = iniparser_getint(dict, "isle:Island Texture", 1); - if (!ReadReg("Island Texture", buffer, sizeof(buffer))) { - strcpy(buffer, "1"); + const char* deviceId = iniparser_getstring(dict, "isle:3D Device ID", NULL); + if (deviceId != NULL) { + m_deviceId = new char[strlen(deviceId) + 1]; + strcpy(m_deviceId, deviceId); } - m_islandTexture = atoi(buffer); - if (ReadReg("3D Device ID", buffer, sizeof(buffer))) { - m_deviceId = new char[strlen(buffer) + 1]; - strcpy(m_deviceId, buffer); - } + // [library:config] The original game does not save any data if no savepath is given. + // Instead, we use SDLs prefPath as a default fallback and always save data. + const char* savePath = iniparser_getstring(dict, "isle:savepath", prefPath); + m_savePath = new char[strlen(savePath) + 1]; + strcpy(m_savePath, savePath); - if (ReadReg("savepath", buffer, sizeof(buffer))) { - m_savePath = new char[strlen(buffer) + 1]; - strcpy(m_savePath, buffer); - } + iniparser_freedict(dict); + delete[] iniConfig; + SDL_free(prefPath); + SDL_free(basePath); } // FUNCTION: ISLE 0x402c20 diff --git a/ISLE/isleapp.h b/ISLE/isleapp.h index 9fcd5df6..966fcb5c 100644 --- a/ISLE/isleapp.h +++ b/ISLE/isleapp.h @@ -28,10 +28,6 @@ class IsleApp { ); MxResult SetupWindow(HINSTANCE hInstance, LPSTR lpCmdLine); - BOOL ReadReg(LPCSTR name, LPSTR outValue, DWORD outSize); - BOOL ReadRegBool(LPCSTR name, BOOL* out); - BOOL ReadRegInt(LPCSTR name, int* out); - void LoadConfig(); void Tick(BOOL sleepIfNotNextFrame); void SetupCursor(WPARAM wParam); @@ -47,10 +43,10 @@ class IsleApp { inline void SetWindowActive(BOOL p_windowActive) { m_windowActive = p_windowActive; } private: - LPSTR m_hdPath; // 0x00 - LPSTR m_cdPath; // 0x04 - LPSTR m_deviceId; // 0x08 - LPSTR m_savePath; // 0x0c + char* m_hdPath; // 0x00 + char* m_cdPath; // 0x04 + char* m_deviceId; // 0x08 + char* m_savePath; // 0x0c BOOL m_fullScreen; // 0x10 BOOL m_flipSurfaces; // 0x14 BOOL m_backBuffersInVram; // 0x18 diff --git a/LEGO1/omni/src/main/mxomni.cpp b/LEGO1/omni/src/main/mxomni.cpp index 29196431..e2ee9c10 100644 --- a/LEGO1/omni/src/main/mxomni.cpp +++ b/LEGO1/omni/src/main/mxomni.cpp @@ -19,10 +19,10 @@ #include "mxvideomanager.h" // GLOBAL: LEGO1 0x101015b8 -char g_hdPath[1024] = ""; +MxString g_hdPath = ""; // GLOBAL: LEGO1 0x101019b8 -char g_cdPath[1024] = "E:"; +MxString g_cdPath = "E:"; // GLOBAL: LEGO1 0x10101db8 MxBool g_use3dSound = FALSE; @@ -362,25 +362,25 @@ MxLong MxOmni::HandleEndAction(MxParam& p_param) // FUNCTION: LEGO1 0x100b0900 const char* MxOmni::GetHD() { - return g_hdPath; + return g_hdPath.GetData(); } // FUNCTION: LEGO1 0x100b0910 void MxOmni::SetHD(const char* p_hd) { - strcpy(g_hdPath, p_hd); + g_hdPath = p_hd; } // FUNCTION: LEGO1 0x100b0940 const char* MxOmni::GetCD() { - return g_cdPath; + return g_cdPath.GetData(); } // FUNCTION: LEGO1 0x100b0950 void MxOmni::SetCD(const char* p_cd) { - strcpy(g_cdPath, p_cd); + g_cdPath = p_cd; } // FUNCTION: LEGO1 0x100b0980 diff --git a/README.md b/README.md index 16d69fb6..2d686f0c 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ To achieve our goal of platform independence, we need to replace any Windows-onl | Library/subsystem | Substitution | Status | | | - | - | - | - | | Window, Events | [SDL3](https://www.libsdl.org/) | WIP | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3Awindow%5D%22&type=code) | -| Windows Registry (Configuration) | [libiniparser](https://github.com/ndevilla/iniparser) | ❌ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3Aconfig%5D%22&type=code) | +| Windows Registry (Configuration) | [libiniparser](https://github.com/ndevilla/iniparser) | ✅ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3Aconfig%5D%22&type=code) | | Filesystem | [SDL3](https://www.libsdl.org/) | ❌ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3Afilesystem%5D%22&type=code) | | Threads, Mutexes (Synchronization) | [SDL3](https://www.libsdl.org/) | ✅ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3Asynchronization%5D%22&type=code) | | Keyboard/Mouse, Joystick, DirectInput (Input) | [SDL3](https://www.libsdl.org/) | ❌ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3Ainput%5D%22&type=code) |