diff --git a/3rdParty/Storm/Source/storm.h b/3rdParty/Storm/Source/storm.h index 1ac5d7de8..a2b922770 100644 --- a/3rdParty/Storm/Source/storm.h +++ b/3rdParty/Storm/Source/storm.h @@ -4,9 +4,6 @@ #include namespace dvl { -extern std::string basePath; -extern std::string prefPath; - // Note to self: Linker error => forgot a return value in cpp // Storm API definition @@ -297,8 +294,6 @@ SMemFree( int logline, char defaultValue); -void GetBasePath(char *buffer, size_t size); -void GetPrefPath(char *buffer, size_t size); bool getIniBool(const char *sectionName, const char *keyName, bool defaultValue = false); bool getIniValue(const char *sectionName, const char *keyName, char *string, int stringSize, int *dataSize = NULL); void setIniValue(const char *sectionName, const char *keyName, char *value, int len = 0); @@ -355,7 +350,7 @@ SStrCopy( const char *src, int max_length); -BOOL SFileSetBasePath(char *); +BOOL SFileSetBasePath(const char *); BOOL SVidPlayContinue(void); BOOL SNetGetOwnerTurnsWaiting(DWORD *); BOOL SNetUnregisterEventHandler(int, SEVTHANDLER); diff --git a/3rdParty/StormLib/src/SFileOpenArchive.cpp b/3rdParty/StormLib/src/SFileOpenArchive.cpp index 7dd2ce63e..493f5532e 100644 --- a/3rdParty/StormLib/src/SFileOpenArchive.cpp +++ b/3rdParty/StormLib/src/SFileOpenArchive.cpp @@ -13,6 +13,11 @@ /* 19.11.03 1.01 Dan Big endian handling */ /*****************************************************************************/ +#ifndef FULL +#include +#include +#endif + #define __STORMLIB_SELF__ #include "StormLib.h" #include "StormCommon.h" @@ -177,12 +182,13 @@ bool STORMAPI SFileOpenArchive( dwStreamFlags |= (dwFlags & MPQ_OPEN_FORCE_MPQ_V1) ? 0 : STREAM_FLAG_USE_BITMAP; #ifndef FULL - char translatedName[260]; - TranslateFileName(translatedName, sizeof(translatedName), szMpqName); + std::string name = szMpqName; + std::replace(name.begin(), name.end(), '\\', '/'); + szMpqName = name.c_str(); #endif // Open the MPQ archive file - pStream = FileStream_OpenFile(translatedName, dwStreamFlags); + pStream = FileStream_OpenFile(szMpqName, dwStreamFlags); if(pStream == NULL) return false; diff --git a/3rdParty/StormLib/src/StormPort.h b/3rdParty/StormLib/src/StormPort.h index eecb42d92..681ba7584 100644 --- a/3rdParty/StormLib/src/StormPort.h +++ b/3rdParty/StormLib/src/StormPort.h @@ -386,6 +386,5 @@ // #define bool int -extern "C" void TranslateFileName(char* dst, int dstLen, const char* src); #endif // __STORMPORT_H__ diff --git a/CMakeLists.txt b/CMakeLists.txt index 723e226f3..a1e45b22b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -183,6 +183,9 @@ add_library(PKWare STATIC 3rdParty/PKWare/explode.cpp 3rdParty/PKWare/implode.cpp) +add_library(SourceS STATIC + SourceS/paths.cpp) + add_library(devilution STATIC Source/appfat.cpp Source/automap.cpp @@ -378,14 +381,19 @@ endif() target_include_directories(devilution PUBLIC Source SourceS ${CMAKE_CURRENT_BINARY_DIR}) target_include_directories(${BIN_TARGET} PRIVATE + SourceS SourceX 3rdParty/asio/include 3rdParty/Radon/Radon/include 3rdParty/libsmacker) -target_link_libraries(devilution PUBLIC Threads::Threads) +target_link_libraries(devilution PUBLIC + Threads::Threads + SourceS +) target_link_libraries(${BIN_TARGET} PRIVATE devilution + SourceS PKWare StormLib smacker @@ -472,7 +480,7 @@ endforeach(def_name) genex_for_option(ASAN) genex_for_option(UBSAN) -foreach(target devilution ${BIN_TARGET}) +foreach(target devilution ${BIN_TARGET} SourceS) target_compile_options(${target} PUBLIC "$<${ASAN_GENEX}:-fsanitize=address;-fsanitize-recover=address>") target_link_libraries(${target} PUBLIC "$<${ASAN_GENEX}:-fsanitize=address;-fsanitize-recover=address>") target_compile_options(${target} PUBLIC $<${UBSAN_GENEX}:-fsanitize=undefined>) diff --git a/Source/capture.cpp b/Source/capture.cpp index fd0d2884b..296cf3dba 100644 --- a/Source/capture.cpp +++ b/Source/capture.cpp @@ -7,6 +7,7 @@ #include "all.h" #include "../3rdParty/Storm/Source/storm.h" +#include "paths.h" #include "file_util.h" DEVILUTION_BEGIN_NAMESPACE @@ -130,18 +131,16 @@ static bool CapturePix(WORD width, WORD height, WORD stride, BYTE *pixels, std:: /** * Returns a pointer because in GCC < 5 ofstream itself is not moveable due to a bug. */ -static std::ofstream *CaptureFile(char *dst_path) +static std::ofstream *CaptureFile(std::string *dst_path) { - char path[MAX_PATH]; - - GetPrefPath(path, MAX_PATH); - - for (int i = 0; i <= 99; i++) { - snprintf(dst_path, MAX_PATH, "%sscreen%02d.PCX", path, i); - if (!FileExists(dst_path)) - return new std::ofstream(dst_path, std::ios::binary | std::ios::trunc); + char filename[sizeof("screen00.PCX") / sizeof(char)]; + for (int i = 0; i <= 99; ++i) { + snprintf(filename, sizeof(filename) / sizeof(char), "screen%02d.PCX", i); + *dst_path = GetPrefPath() + filename; + if (!FileExists(dst_path->c_str())) { + return new std::ofstream(*dst_path, std::ios::binary | std::ios::trunc); + } } - return NULL; } @@ -172,10 +171,10 @@ static void RedPalette() void CaptureScreen() { SDL_Color palette[256]; - char FileName[MAX_PATH]; + std::string FileName; BOOL success; - std::ofstream *out = CaptureFile(FileName); + std::ofstream *out = CaptureFile(&FileName); if (out == NULL) return; DrawAndBlit(); PaletteGetEntries(256, palette); @@ -193,10 +192,10 @@ void CaptureScreen() out->close(); if (!success) { - SDL_Log("Failed to save screenshot at %s", FileName); - RemoveFile(FileName); + SDL_Log("Failed to save screenshot at %s", FileName.c_str()); + RemoveFile(FileName.c_str()); } else { - SDL_Log("Screenshot saved at %s", FileName); + SDL_Log("Screenshot saved at %s", FileName.c_str()); } SDL_Delay(300); for (int i = 0; i < 256; i++) { diff --git a/Source/diablo.cpp b/Source/diablo.cpp index c76c2a721..ccdc90a0f 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -4,6 +4,7 @@ * Implementation of the main game initialization functions. */ #include "all.h" +#include "paths.h" #include "../3rdParty/Storm/Source/storm.h" #include "../DiabloUI/diabloui.h" #include @@ -429,23 +430,9 @@ void diablo_parse_flags(int argc, char **argv) printf("%s v%s\n", PROJECT_NAME, PROJECT_VERSION); diablo_quit(0); } else if (strcasecmp("--data-dir", argv[i]) == 0) { - basePath = argv[++i]; -#ifdef _WIN32 - if (basePath.back() != '\\') - basePath += '\\'; -#else - if (basePath.back() != '/') - basePath += '/'; -#endif + SetBasePath(argv[++i]); } else if (strcasecmp("--save-dir", argv[i]) == 0) { - prefPath = argv[++i]; -#ifdef _WIN32 - if (prefPath.back() != '\\') - prefPath += '\\'; -#else - if (prefPath.back() != '/') - prefPath += '/'; -#endif + SetPrefPath(argv[++i]); } else if (strcasecmp("-n", argv[i]) == 0) { showintrodebug = FALSE; } else if (strcasecmp("-f", argv[i]) == 0) { diff --git a/Source/init.cpp b/Source/init.cpp index 4fbc69b8b..520ad23e7 100644 --- a/Source/init.cpp +++ b/Source/init.cpp @@ -3,8 +3,10 @@ * * Implementation of routines for initializing the environment, disable screen saver, load MPQ. */ -#include "all.h" +#include +#include "all.h" +#include "paths.h" #include "../3rdParty/Storm/Source/storm.h" #include "../DiabloUI/diabloui.h" #include @@ -15,31 +17,17 @@ DEVILUTION_BEGIN_NAMESPACE _SNETVERSIONDATA fileinfo; /** True if the game is the current active window */ int gbActive; -/** Specifies the path to diablo.exe. */ -char diablo_exe_path[MAX_PATH]; /** A handle to an unused MPQ archive. */ HANDLE hellfire_mpq; -/** Specifies the path to patch_rt.mpq. */ -char patch_rt_mpq_path[MAX_PATH]; /** The current input handler function */ WNDPROC CurrentProc; /** A handle to the diabdat.mpq archive. */ HANDLE diabdat_mpq; -/** Specifies the path to diabdat.mpq. */ -char diabdat_mpq_path[MAX_PATH]; /** A handle to the patch_rt.mpq archive. */ HANDLE patch_rt_mpq; /** Indicate if we only have access to demo data */ bool gbIsSpawn; #ifdef HELLFIRE -char hellfire_mpq_path[MAX_PATH]; -char hfmonk_mpq_path[MAX_PATH]; -char hfbard_mpq_path[MAX_PATH]; -char hfbarb_mpq_path[MAX_PATH]; -char hfmusic_mpq_path[MAX_PATH]; -char hfvoice_mpq_path[MAX_PATH]; -char hfopt1_mpq_path[MAX_PATH]; -char hfopt2_mpq_path[MAX_PATH]; HANDLE hfmonk_mpq; HANDLE hfbard_mpq; HANDLE hfbarb_mpq; @@ -49,10 +37,34 @@ HANDLE hfopt1_mpq; HANDLE hfopt2_mpq; #endif +namespace { + +HANDLE init_test_access(const char *mpq_name, const char *reg_loc, int dwPriority, int fs) +{ + HANDLE archive; + const std::string *paths[2] = {&GetBasePath(), &GetPrefPath()}; + std::string mpq_abspath; + DWORD mpq_flags = 0; +#if !defined(__SWITCH__) && !defined(__AMIGA__) + mpq_flags |= MPQ_FLAG_READ_ONLY; +#endif + for (int i = 0; i < 2; i++) { + mpq_abspath = *paths[i] + mpq_name; + if (SFileOpenArchive(mpq_abspath.c_str(), dwPriority, mpq_flags, &archive)) { + SFileSetBasePath(paths[i]->c_str()); + return archive; + } + } + + return NULL; +} + +} // namespace + /* data */ -char gszVersionNumber[MAX_PATH] = "internal version unknown"; -char gszProductName[MAX_PATH] = "Diablo v1.09"; +char gszVersionNumber[260] = "internal version unknown"; +char gszProductName[260] = "Diablo v1.09"; void init_cleanup() { @@ -122,14 +134,14 @@ void init_archives() memset(&fileinfo, 0, sizeof(fileinfo)); fileinfo.size = sizeof(fileinfo); fileinfo.versionstring = gszVersionNumber; - fileinfo.executablefile = diablo_exe_path; - fileinfo.originalarchivefile = diabdat_mpq_path; - fileinfo.patcharchivefile = patch_rt_mpq_path; + fileinfo.executablefile = ""; + fileinfo.originalarchivefile = ""; + fileinfo.patcharchivefile = ""; init_get_file_info(); - diabdat_mpq = init_test_access(diabdat_mpq_path, "diabdat.mpq", "DiabloCD", 1000, FS_CD); + diabdat_mpq = init_test_access("diabdat.mpq", "DiabloCD", 1000, FS_CD); if (diabdat_mpq == NULL) { - diabdat_mpq = init_test_access(diabdat_mpq_path, "spawn.mpq", "DiabloSpawn", 1000, FS_PC); + diabdat_mpq = init_test_access("spawn.mpq", "DiabloSpawn", 1000, FS_PC); if (diabdat_mpq != NULL) gbIsSpawn = true; } @@ -137,50 +149,26 @@ void init_archives() InsertCDDlg(); SFileCloseFile(fh); - patch_rt_mpq = init_test_access(patch_rt_mpq_path, "patch_rt.mpq", "DiabloInstall", 2000, FS_PC); + patch_rt_mpq = init_test_access("patch_rt.mpq", "DiabloInstall", 2000, FS_PC); if (patch_rt_mpq == NULL) - patch_rt_mpq = init_test_access(patch_rt_mpq_path, "patch_sh.mpq", "DiabloSpawn", 2000, FS_PC); + patch_rt_mpq = init_test_access("patch_sh.mpq", "DiabloSpawn", 2000, FS_PC); #ifdef HELLFIRE - hellfire_mpq = init_test_access(hellfire_mpq_path, "hellfire.mpq", "DiabloInstall", 8000, FS_PC); - hfmonk_mpq = init_test_access(hfmonk_mpq_path, "hfmonk.mpq", "DiabloInstall", 8100, FS_PC); - hfbard_mpq = init_test_access(hfbard_mpq_path, "hfbard.mpq", "DiabloInstall", 8110, FS_PC); - hfbarb_mpq = init_test_access(hfbarb_mpq_path, "hfbarb.mpq", "DiabloInstall", 8120, FS_PC); - hfmusic_mpq = init_test_access(hfmusic_mpq_path, "hfmusic.mpq", "DiabloInstall", 8200, FS_PC); - hfvoice_mpq = init_test_access(hfvoice_mpq_path, "hfvoice.mpq", "DiabloInstall", 8500, FS_PC); - hfopt1_mpq = init_test_access(hfopt1_mpq_path, "hfopt1.mpq", "DiabloInstall", 8600, FS_PC); - hfopt2_mpq = init_test_access(hfopt2_mpq_path, "hfopt2.mpq", "DiabloInstall", 8610, FS_PC); + hellfire_mpq = init_test_access("hellfire.mpq", "DiabloInstall", 8000, FS_PC); + hfmonk_mpq = init_test_access("hfmonk.mpq", "DiabloInstall", 8100, FS_PC); + hfbard_mpq = init_test_access("hfbard.mpq", "DiabloInstall", 8110, FS_PC); + hfbarb_mpq = init_test_access("hfbarb.mpq", "DiabloInstall", 8120, FS_PC); + hfmusic_mpq = init_test_access("hfmusic.mpq", "DiabloInstall", 8200, FS_PC); + hfvoice_mpq = init_test_access("hfvoice.mpq", "DiabloInstall", 8500, FS_PC); + hfopt1_mpq = init_test_access("hfopt1.mpq", "DiabloInstall", 8600, FS_PC); + hfopt2_mpq = init_test_access("hfopt2.mpq", "DiabloInstall", 8610, FS_PC); #endif } -HANDLE init_test_access(char *mpq_path, const char *mpq_name, const char *reg_loc, int dwPriority, int fs) -{ - char Buffer[2][MAX_PATH]; - HANDLE archive; - - GetBasePath(Buffer[0], MAX_PATH); - GetPrefPath(Buffer[1], MAX_PATH); - - for (int i = 0; i < 2; i++) { - snprintf(mpq_path, MAX_PATH, "%s%s", Buffer[i], mpq_name); -#if !defined(__SWITCH__) && !defined(__AMIGA__) - if (SFileOpenArchive(mpq_path, dwPriority, MPQ_FLAG_READ_ONLY, &archive)) { -#else - if (SFileOpenArchive(mpq_path, dwPriority, 0, &archive)) { -#endif - SFileSetBasePath(Buffer[i]); - return archive; - - } - } - - return NULL; -} - void init_get_file_info() { - snprintf(gszProductName, MAX_PATH, "%s v%s", PROJECT_NAME, PROJECT_VERSION); - snprintf(gszVersionNumber, MAX_PATH, "version %s", PROJECT_VERSION); + snprintf(gszProductName, sizeof(gszProductName) / sizeof(char), "%s v%s", PROJECT_NAME, PROJECT_VERSION); + snprintf(gszVersionNumber, sizeof(gszVersionNumber) / sizeof(char), "version %s", PROJECT_VERSION); } LRESULT MainWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) diff --git a/Source/init.h b/Source/init.h index f0c7dda79..1790f7dbf 100644 --- a/Source/init.h +++ b/Source/init.h @@ -14,24 +14,13 @@ extern "C" { extern _SNETVERSIONDATA fileinfo; extern int gbActive; -extern char diablo_exe_path[MAX_PATH]; extern HANDLE hellfire_mpq; -extern char patch_rt_mpq_path[MAX_PATH]; extern WNDPROC CurrentProc; extern HANDLE diabdat_mpq; -extern char diabdat_mpq_path[MAX_PATH]; extern HANDLE patch_rt_mpq; extern bool gbIsSpawn; extern BOOLEAN screensaver_enabled_prev; #ifdef HELLFIRE -extern char hellfire_mpq_path[MAX_PATH]; -extern char hfmonk_mpq_path[MAX_PATH]; -extern char hfbard_mpq_path[MAX_PATH]; -extern char hfbarb_mpq_path[MAX_PATH]; -extern char hfmusic_mpq_path[MAX_PATH]; -extern char hfvoice_mpq_path[MAX_PATH]; -extern char hfopt1_mpq_path[MAX_PATH]; -extern char hfopt2_mpq_path[MAX_PATH]; extern HANDLE hfmonk_mpq; extern HANDLE hfbard_mpq; extern HANDLE hfbarb_mpq; @@ -45,7 +34,6 @@ void init_cleanup(); void init_disable_screensaver(BOOLEAN disable); void init_create_window(); void init_archives(); -HANDLE init_test_access(char *mpq_path, const char *mpq_name, const char *reg_loc, int flags, int fs); void init_get_file_info(); LRESULT MainWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); void init_activate_window(HWND hWnd, BOOL bActive); @@ -57,8 +45,8 @@ extern BOOL was_window_init; /** defined in dx.cpp */ /* data */ -extern char gszVersionNumber[MAX_PATH]; -extern char gszProductName[MAX_PATH]; +extern char gszVersionNumber[260]; +extern char gszProductName[260]; #ifdef __cplusplus } diff --git a/Source/pfile.cpp b/Source/pfile.cpp index b7b89f412..8336c01fb 100644 --- a/Source/pfile.cpp +++ b/Source/pfile.cpp @@ -3,7 +3,10 @@ * * Implementation of the save game encoding functionality. */ +#include + #include "all.h" +#include "paths.h" #include "../3rdParty/Storm/Source/storm.h" #include "../DiabloUI/diabloui.h" #include "file_util.h" @@ -15,6 +18,45 @@ DEVILUTION_BEGIN_NAMESPACE #define PASSWORD_SINGLE "xrgyrkj1" #define PASSWORD_MULTI "szqnlsk1" +namespace { + +std::string GetSavePath(DWORD save_num) +{ + std::string path = GetPrefPath(); +#ifdef HELLFIRE + const char *ext = ".hsv"; +#else + const char *ext = ".sv"; +#endif + + if (gbIsSpawn) { + if (gbMaxPlayers <= 1) { + path.append("spawn"); + } else { + path.append("share_"); + } + } else { + if (gbMaxPlayers <= 1) { + path.append("single_"); + } else { +#ifdef HELLFIRE + path.append("hrinfo_"); + ext = ".drv"; +#else + path.append("multi_"); +#endif + } + } + + char save_num_str[21]; + snprintf(save_num_str, sizeof(save_num_str) / sizeof(char), "%d", save_num); + path.append(save_num_str); + path.append(ext); + return path; +} + +} // namespace + /** List of character names for the character selection screen. */ static char hero_names[MAX_CHARACTERS][PLR_NAME_LEN]; BOOL gbValidSaveFile; @@ -70,58 +112,15 @@ void pfile_encode_hero(const PkPlayerStruct *pPack) BOOL pfile_open_archive(BOOL update, DWORD save_num) { - char FileName[MAX_PATH]; - - pfile_get_save_path(FileName, sizeof(FileName), save_num); - if (OpenMPQ(FileName, save_num)) + if (OpenMPQ(GetSavePath(save_num).c_str(), save_num)) return TRUE; return FALSE; } -void pfile_get_save_path(char *pszBuf, DWORD dwBufSize, DWORD save_num) -{ - char path[MAX_PATH]; - const char *fmt; - - if (gbIsSpawn) { -#ifdef HELLFIRE - fmt = "%sshare_%d.hsv"; -#else - fmt = "%sshare_%d.sv"; -#endif - - if (gbMaxPlayers <= 1) -#ifdef HELLFIRE - fmt = "%sspawn%d.hsv"; -#else - fmt = "%sspawn%d.sv"; -#endif - } else { -#ifdef HELLFIRE - fmt = "%shrinfo_%d.drv"; -#else - fmt = "%smulti_%d.sv"; -#endif - - if (gbMaxPlayers <= 1) -#ifdef HELLFIRE - fmt = "%ssingle_%d.hsv"; -#else - fmt = "%ssingle_%d.sv"; -#endif - } - - GetPrefPath(path, MAX_PATH); - snprintf(pszBuf, MAX_PATH, fmt, path, save_num); -} - void pfile_flush(BOOL is_single_player, DWORD save_num) { - char FileName[MAX_PATH]; - - pfile_get_save_path(FileName, sizeof(FileName), save_num); - mpqapi_flush_and_close(FileName, is_single_player, save_num); + mpqapi_flush_and_close(GetSavePath(save_num).c_str(), is_single_player, save_num); } BOOL pfile_create_player_description(char *dst, DWORD len) @@ -289,11 +288,9 @@ BOOL pfile_read_hero(HANDLE archive, PkPlayerStruct *pPack) */ HANDLE pfile_open_save_archive(BOOL *showFixedMsg, DWORD save_num) { - char SrcStr[MAX_PATH]; HANDLE archive; - pfile_get_save_path(SrcStr, sizeof(SrcStr), save_num); - if (SFileOpenArchive(SrcStr, 0x7000, FS_PC, &archive)) + if (SFileOpenArchive(GetSavePath(save_num).c_str(), 0x7000, FS_PC, &archive)) return archive; return NULL; } @@ -409,13 +406,11 @@ BOOL pfile_get_file_name(DWORD lvl, char *dst) BOOL pfile_delete_save(_uiheroinfo *hero_info) { DWORD save_num; - char FileName[MAX_PATH]; save_num = pfile_get_save_num_from_name(hero_info->name); if (save_num < MAX_CHARACTERS) { hero_names[save_num][0] = '\0'; - pfile_get_save_path(FileName, sizeof(FileName), save_num); - RemoveFile(FileName); + RemoveFile(GetSavePath(save_num).c_str()); } return TRUE; } @@ -549,9 +544,7 @@ BOOL GetPermSaveNames(DWORD dwIndex, char *szPerm) void pfile_write_save_file(const char *pszName, BYTE *pbData, DWORD dwLen, DWORD qwLen) { DWORD save_num; - char FileName[MAX_PATH]; - pfile_strcpy(FileName, pszName); save_num = pfile_get_save_num_from_name(plr[myplr]._pName); { const char *password; @@ -569,29 +562,22 @@ void pfile_write_save_file(const char *pszName, BYTE *pbData, DWORD dwLen, DWORD } if (!pfile_open_archive(FALSE, save_num)) app_fatal("Unable to write so save file archive"); - mpqapi_write_file(FileName, pbData, qwLen); + mpqapi_write_file(pszName, pbData, qwLen); pfile_flush(TRUE, save_num); } -void pfile_strcpy(char *dst, const char *src) -{ - strcpy(dst, src); -} - BYTE *pfile_read(const char *pszName, DWORD *pdwLen) { DWORD save_num, nread; - char FileName[MAX_PATH]; HANDLE archive, save; BYTE *buf; - pfile_strcpy(FileName, pszName); save_num = pfile_get_save_num_from_name(plr[myplr]._pName); archive = pfile_open_save_archive(NULL, save_num); if (archive == NULL) app_fatal("Unable to open save file archive"); - if (!SFileOpenFileEx(archive, FileName, 0, &save)) + if (!SFileOpenFileEx(archive, pszName, 0, &save)) app_fatal("Unable to open save file"); *pdwLen = SFileGetFileSize(save, NULL); diff --git a/Source/pfile.h b/Source/pfile.h index c7e29497e..6ba8ee6b5 100644 --- a/Source/pfile.h +++ b/Source/pfile.h @@ -20,7 +20,6 @@ void pfile_write_hero(); DWORD pfile_get_save_num_from_name(const char *name); void pfile_encode_hero(const PkPlayerStruct *pPack); BOOL pfile_open_archive(BOOL update, DWORD save_num); -void pfile_get_save_path(char *pszBuf, DWORD dwBufSize, DWORD save_num); void pfile_flush(BOOL is_single_player, DWORD save_num); BOOL pfile_create_player_description(char *dst, DWORD len); BOOL pfile_rename_hero(const char *name_1, const char *name_2); @@ -47,7 +46,6 @@ BOOL GetTempSaveNames(DWORD dwIndex, char *szTemp); void pfile_rename_temp_to_perm(); BOOL GetPermSaveNames(DWORD dwIndex, char *szPerm); void pfile_write_save_file(const char *pszName, BYTE *pbData, DWORD dwLen, DWORD qwLen); -void pfile_strcpy(char *dst, const char *src); BYTE *pfile_read(const char *pszName, DWORD *pdwLen); void pfile_update(BOOL force_save); diff --git a/Source/restrict.cpp b/Source/restrict.cpp index 1bce371f7..d98bea442 100644 --- a/Source/restrict.cpp +++ b/Source/restrict.cpp @@ -4,6 +4,7 @@ * Implementation of functionality for checking if the game will be able run on the system. */ #include "all.h" +#include "paths.h" #include "../3rdParty/Storm/Source/storm.h" DEVILUTION_BEGIN_NAMESPACE @@ -14,19 +15,14 @@ DEVILUTION_BEGIN_NAMESPACE */ void ReadOnlyTest() { - FILE *f; - char path[MAX_PATH], Filename[MAX_PATH]; - - GetPrefPath(path, MAX_PATH); - snprintf(Filename, MAX_PATH, "%sDiablo1ReadOnlyTest.foo", path); - - f = fopen(Filename, "wt"); + const std::string path = GetPrefPath() + "Diablo1ReadOnlyTest.foo"; + FILE *f = fopen(path.c_str(), "wt"); if (!f) { - DirErrorDlg(path); + DirErrorDlg(GetPrefPath().c_str()); } fclose(f); - remove(Filename);; + remove(path.c_str()); } DEVILUTION_END_NAMESPACE diff --git a/SourceS/file_util.h b/SourceS/file_util.h index 927a435f9..f2a24a01f 100644 --- a/SourceS/file_util.h +++ b/SourceS/file_util.h @@ -94,7 +94,7 @@ inline bool ResizeFile(const char *path, std::uintmax_t size) #endif } -inline void RemoveFile(char *lpFileName) +inline void RemoveFile(const char *lpFileName) { std::string name = lpFileName; std::replace(name.begin(), name.end(), '\\', '/'); diff --git a/SourceS/paths.cpp b/SourceS/paths.cpp new file mode 100644 index 000000000..4eb15b07b --- /dev/null +++ b/SourceS/paths.cpp @@ -0,0 +1,65 @@ +#include "paths.h" + +#include + +#ifdef USE_SDL1 +#include "sdl2_to_1_2_backports.h" +#endif + +namespace dvl { + +namespace { + +std::string *basePath = NULL; +std::string *prefPath = NULL; + +void AddTrailingSlash(std::string *path) { +#ifdef _WIN32 + if (!path->empty() && path->back() != '\\') + *path += '\\'; +#else + if (!path->empty() && path->back() != '/') + *path += '/'; +#endif +} + +std::string *FromSDL(char *s) { + std::string *result = new std::string(s != NULL ? s : ""); + if (s != NULL) { + SDL_free(s); + } else { + SDL_Log("%s", SDL_GetError()); + SDL_ClearError(); + } + return result; +} + +} // namespace + +const std::string &GetBasePath() +{ + if (basePath == NULL) basePath = FromSDL(SDL_GetBasePath()); + return *basePath; +} + +const std::string &GetPrefPath() +{ + if (prefPath == NULL) prefPath = FromSDL(SDL_GetPrefPath("diasurgical", "devilution")); + return *prefPath; +} + +void SetBasePath(const char *path) +{ + if (basePath == NULL) basePath = new std::string; + *basePath = path; + AddTrailingSlash(basePath); +} + +void SetPrefPath(const char *path) +{ + if (prefPath == NULL) prefPath = new std::string; + *prefPath = path; + AddTrailingSlash(prefPath); +} + +} // namespace dvl diff --git a/SourceS/paths.h b/SourceS/paths.h new file mode 100644 index 000000000..e0aa50f79 --- /dev/null +++ b/SourceS/paths.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +namespace dvl { + +const std::string &GetBasePath(); +const std::string &GetPrefPath(); + +void SetBasePath(const char *path); +void SetPrefPath(const char *path); + +} // namespace dvl diff --git a/SourceS/storm_full.h b/SourceS/storm_full.h index 10292dc0a..cc9db16cd 100644 --- a/SourceS/storm_full.h +++ b/SourceS/storm_full.h @@ -5,6 +5,5 @@ extern "C" { extern DWORD nLastError; -void TranslateFileName(char *dst, int dstLen, const char *src); } } // namespace dvl diff --git a/SourceX/storm/storm.cpp b/SourceX/storm/storm.cpp index f9fad5dde..2e2d93bff 100644 --- a/SourceX/storm/storm.cpp +++ b/SourceX/storm/storm.cpp @@ -1,4 +1,8 @@ +#include +#include + #include "all.h" +#include "paths.h" #include "../3rdParty/Storm/Source/storm.h" #if !SDL_VERSION_ATLEAST(2, 0, 4) @@ -17,79 +21,26 @@ namespace dvl { -std::string basePath; -std::string prefPath; - DWORD nLastError = 0; + +namespace { + bool directFileAccess = false; -char SBasePath[MAX_PATH]; +std::string *SBasePath = NULL; + +} // namespace #ifdef USE_SDL1 static bool IsSVidVideoMode = false; #endif -static std::string getIniPath() -{ - char path[MAX_PATH]; - GetPrefPath(path, MAX_PATH); - std::string result = path; - result.append("diablo.ini"); - return result; -} - radon::File& getIni() { - static radon::File ini(getIniPath()); + static radon::File ini(GetPrefPath() + "diablo.ini"); return ini; } static Mix_Chunk *SFileChunk = NULL; -void GetBasePath(char *buffer, size_t size) -{ - if (basePath.length()) { - snprintf(buffer, size, "%s", basePath.c_str()); - return; - } - - char *path = SDL_GetBasePath(); - if (path == NULL) { - SDL_Log(SDL_GetError()); - buffer[0] = '\0'; - return; - } - - snprintf(buffer, size, "%s", path); - SDL_free(path); -} - -void GetPrefPath(char *buffer, size_t size) -{ - if (prefPath.length()) { - snprintf(buffer, size, "%s", prefPath.c_str()); - return; - } - - char *path = SDL_GetPrefPath("diasurgical", "devilution"); - if (path == NULL) { - buffer[0] = '\0'; - return; - } - - snprintf(buffer, size, "%s", path); - SDL_free(path); -} - -void TranslateFileName(char *dst, int dstLen, const char *src) -{ - for (int i = 0; i < dstLen; i++) { - char c = *src++; - dst[i] = c == '\\' ? '/' : c; - if (!c) { - break; - } - } -} - BOOL SFileDdaBeginEx(HANDLE hFile, DWORD flags, DWORD mask, unsigned __int32 lDistanceToMove, signed __int32 volume, signed int pan, int a7) { @@ -194,14 +145,11 @@ BOOL SFileOpenFile(const char *filename, HANDLE *phFile) { bool result = false; - if (directFileAccess) { - char directPath[MAX_PATH] = "\0"; - char tmpPath[MAX_PATH] = "\0"; - for (size_t i = 0; i < strlen(filename); i++) { - tmpPath[i] = AsciiToLowerTable_Path[static_cast(filename[i])]; - } - snprintf(directPath, MAX_PATH, "%s%s", SBasePath, tmpPath); - result = SFileOpenFileEx((HANDLE)0, directPath, 0xFFFFFFFF, phFile); + if (directFileAccess && SBasePath != NULL) { + std::string path = *SBasePath + filename; + for (std::size_t i = SBasePath->size(); i < path.size(); ++i) + path[i] = AsciiToLowerTable_Path[static_cast(path[i])]; + result = SFileOpenFileEx((HANDLE)0, path.c_str(), 0xFFFFFFFF, phFile); } #ifdef HELLFIRE @@ -893,9 +841,10 @@ int SStrCopy(char *dest, const char *src, int max_length) return strlen(dest); } -BOOL SFileSetBasePath(char *path) +BOOL SFileSetBasePath(const char *path) { - strncpy(SBasePath, path, MAX_PATH); + if (SBasePath == NULL) SBasePath = new std::string; + *SBasePath = path; return true; } diff --git a/structs.h b/structs.h index fb7bca35a..684a6a7cb 100644 --- a/structs.h +++ b/structs.h @@ -1389,10 +1389,10 @@ typedef struct _SNETPROGRAMDATA { typedef struct _SNETVERSIONDATA { int size; - char *versionstring; - char *executablefile; - char *originalarchivefile; - char *patcharchivefile; + const char *versionstring; + const char *executablefile; + const char *originalarchivefile; + const char *patcharchivefile; } _SNETVERSIONDATA; typedef struct _SNETUIDATA {