Browse Source

Remove MAX_PATH restriction (#898)

Do not limit filesystem paths to 259 chars for MPQs, save files, and diablo.ini.

The MAX_PATH constant remains but now only limits path lengths within the MPQs.
pull/902/head
Gleb Mazovetskiy 6 years ago committed by GitHub
parent
commit
a091a56e8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      3rdParty/Storm/Source/storm.h
  2. 12
      3rdParty/StormLib/src/SFileOpenArchive.cpp
  3. 1
      3rdParty/StormLib/src/StormPort.h
  4. 12
      CMakeLists.txt
  5. 29
      Source/capture.cpp
  6. 19
      Source/diablo.cpp
  7. 104
      Source/init.cpp
  8. 16
      Source/init.h
  9. 110
      Source/pfile.cpp
  10. 2
      Source/pfile.h
  11. 14
      Source/restrict.cpp
  12. 2
      SourceS/file_util.h
  13. 65
      SourceS/paths.cpp
  14. 13
      SourceS/paths.h
  15. 1
      SourceS/storm_full.h
  16. 89
      SourceX/storm/storm.cpp
  17. 8
      structs.h

7
3rdParty/Storm/Source/storm.h vendored

@ -4,9 +4,6 @@
#include <string>
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);

12
3rdParty/StormLib/src/SFileOpenArchive.cpp vendored

@ -13,6 +13,11 @@
/* 19.11.03 1.01 Dan Big endian handling */
/*****************************************************************************/
#ifndef FULL
#include <algorithm>
#include <string>
#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;

1
3rdParty/StormLib/src/StormPort.h vendored

@ -386,6 +386,5 @@
//
#define bool int
extern "C" void TranslateFileName(char* dst, int dstLen, const char* src);
#endif // __STORMPORT_H__

12
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>)

29
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++) {

19
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 <config.h>
@ -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) {

104
Source/init.cpp

@ -3,8 +3,10 @@
*
* Implementation of routines for initializing the environment, disable screen saver, load MPQ.
*/
#include "all.h"
#include <string>
#include "all.h"
#include "paths.h"
#include "../3rdParty/Storm/Source/storm.h"
#include "../DiabloUI/diabloui.h"
#include <SDL.h>
@ -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)

16
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
}

110
Source/pfile.cpp

@ -3,7 +3,10 @@
*
* Implementation of the save game encoding functionality.
*/
#include <string>
#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);

2
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);

14
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

2
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(), '\\', '/');

65
SourceS/paths.cpp

@ -0,0 +1,65 @@
#include "paths.h"
#include <SDL.h>
#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

13
SourceS/paths.h

@ -0,0 +1,13 @@
#pragma once
#include <string>
namespace dvl {
const std::string &GetBasePath();
const std::string &GetPrefPath();
void SetBasePath(const char *path);
void SetPrefPath(const char *path);
} // namespace dvl

1
SourceS/storm_full.h

@ -5,6 +5,5 @@ extern "C" {
extern DWORD nLastError;
void TranslateFileName(char *dst, int dstLen, const char *src);
}
} // namespace dvl

89
SourceX/storm/storm.cpp

@ -1,4 +1,8 @@
#include <cstddef>
#include <string>
#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<unsigned char>(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<unsigned char>(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;
}

8
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 {

Loading…
Cancel
Save