Provide compatibility layer for paths on Linux/Mac (#50)

See #17
See #49
This commit is contained in:
Alexander Batalov 2022-06-18 10:58:15 +03:00 committed by GitHub
parent 9098ad6486
commit 8b37a22dd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 200 additions and 66 deletions

View File

@ -69,7 +69,7 @@ int audioFileOpen(const char* fname, int flags, ...)
*pm++ = 'b'; *pm++ = 'b';
} }
FILE* stream = fopen(path, mode); FILE* stream = compat_fopen(path, mode);
if (stream == NULL) { if (stream == NULL) {
return -1; return -1;
} }

View File

@ -237,7 +237,7 @@ void automapExit()
if (configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_MASTER_PATCHES_KEY, &masterPatchesPath)) { if (configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_MASTER_PATCHES_KEY, &masterPatchesPath)) {
char path[COMPAT_MAX_PATH]; char path[COMPAT_MAX_PATH];
sprintf(path, "%s\\%s\\%s", masterPatchesPath, "MAPS", AUTOMAP_DB); sprintf(path, "%s\\%s\\%s", masterPatchesPath, "MAPS", AUTOMAP_DB);
remove(path); compat_remove(path);
} }
} }
@ -774,7 +774,7 @@ int automapSaveCurrent()
// NOTE: Not sure about the size. // NOTE: Not sure about the size.
char automapDbPath[512]; char automapDbPath[512];
sprintf(automapDbPath, "%s\\%s\\%s", masterPatchesPath, "MAPS", AUTOMAP_DB); sprintf(automapDbPath, "%s\\%s\\%s", masterPatchesPath, "MAPS", AUTOMAP_DB);
if (remove(automapDbPath) != 0) { if (compat_remove(automapDbPath) != 0) {
debugPrint("\nAUTOMAP: Error removing database!\n"); debugPrint("\nAUTOMAP: Error removing database!\n");
return -1; return -1;
} }
@ -782,7 +782,7 @@ int automapSaveCurrent()
// NOTE: Not sure about the size. // NOTE: Not sure about the size.
char automapTmpPath[512]; char automapTmpPath[512];
sprintf(automapTmpPath, "%s\\%s\\%s", masterPatchesPath, "MAPS", AUTOMAP_TMP); sprintf(automapTmpPath, "%s\\%s\\%s", masterPatchesPath, "MAPS", AUTOMAP_TMP);
if (rename(automapTmpPath, automapDbPath) != 0) { if (compat_rename(automapTmpPath, automapDbPath) != 0) {
debugPrint("\nAUTOMAP: Error renaming database!\n"); debugPrint("\nAUTOMAP: Error renaming database!\n");
return -1; return -1;
} }

View File

@ -277,7 +277,7 @@ bool configRead(Config* config, const char* filePath, bool isDb)
fileClose(stream); fileClose(stream);
} }
} else { } else {
FILE* stream = fopen(filePath, "rt"); FILE* stream = compat_fopen(filePath, "rt");
if (stream != NULL) { if (stream != NULL) {
while (fgets(string, sizeof(string), stream) != NULL) { while (fgets(string, sizeof(string), stream) != NULL) {
configParseLine(config, string); configParseLine(config, string);
@ -323,7 +323,7 @@ bool configWrite(Config* config, const char* filePath, bool isDb)
fileClose(stream); fileClose(stream);
} else { } else {
FILE* stream = fopen(filePath, "wt"); FILE* stream = compat_fopen(filePath, "wt");
if (stream == NULL) { if (stream == NULL) {
return false; return false;
} }

View File

@ -721,7 +721,7 @@ int screenshotHandlerDefaultImpl(int width, int height, unsigned char* data, uns
for (index = 0; index < 100000; index++) { for (index = 0; index < 100000; index++) {
sprintf(fileName, "scr%.5d.bmp", index); sprintf(fileName, "scr%.5d.bmp", index);
stream = fopen(fileName, "rb"); stream = compat_fopen(fileName, "rb");
if (stream == NULL) { if (stream == NULL) {
break; break;
} }
@ -733,7 +733,7 @@ int screenshotHandlerDefaultImpl(int width, int height, unsigned char* data, uns
return -1; return -1;
} }
stream = fopen(fileName, "wb"); stream = compat_fopen(fileName, "wb");
if (stream == NULL) { if (stream == NULL) {
return -1; return -1;
} }

View File

@ -53,7 +53,7 @@ void _debug_register_log(const char* fileName, const char* mode)
fclose(_fd); fclose(_fd);
} }
_fd = fopen(fileName, mode); _fd = compat_fopen(fileName, mode);
gDebugPrintProc = _debug_log; gDebugPrintProc = _debug_log;
} }
} }

View File

@ -16,7 +16,7 @@ DBase* dbaseOpen(const char* filePath)
{ {
assert(filePath); // "filename", "dfile.c", 74 assert(filePath); // "filename", "dfile.c", 74
FILE* stream = fopen(filePath, "rb"); FILE* stream = compat_fopen(filePath, "rb");
if (stream == NULL) { if (stream == NULL) {
return NULL; return NULL;
} }
@ -635,7 +635,7 @@ DFile* dfileOpenInternal(DBase* dbase, const char* filePath, const char* mode, D
dfile->entry = entry; dfile->entry = entry;
// Open stream to .DAT file. // Open stream to .DAT file.
dfile->stream = fopen(dbase->path, "rb"); dfile->stream = compat_fopen(dbase->path, "rb");
if (dfile->stream == NULL) { if (dfile->stream == NULL) {
goto err; goto err;
} }

View File

@ -1,6 +1,9 @@
#include "file_find.h" #include "file_find.h"
#include <fpattern.h>
#include <stddef.h> #include <stddef.h>
#include <string.h>
// 0x4E6380 // 0x4E6380
bool fileFindFirst(const char* path, DirectoryFileFindData* findData) bool fileFindFirst(const char* path, DirectoryFileFindData* findData)
@ -11,14 +14,33 @@ bool fileFindFirst(const char* path, DirectoryFileFindData* findData)
return false; return false;
} }
#else #else
findData->dir = opendir(path); strcpy(findData->path, path);
char drive[COMPAT_MAX_DRIVE];
char dir[COMPAT_MAX_DIR];
compat_splitpath(path, drive, dir, NULL, NULL);
char basePath[COMPAT_MAX_PATH];
compat_makepath(basePath, drive, dir, NULL, NULL);
findData->dir = opendir(basePath);
if (findData->dir == NULL) { if (findData->dir == NULL) {
return false; return false;
} }
findData->entry = readdir(findData->dir); findData->entry = readdir(findData->dir);
while (findData->entry != NULL) {
char entryPath[COMPAT_MAX_PATH];
compat_makepath(entryPath, drive, dir, fileFindGetName(findData), NULL);
if (fpattern_match(findData->path, entryPath)) {
break;
}
findData->entry = readdir(findData->dir);
}
if (findData->entry == NULL) { if (findData->entry == NULL) {
closedir(findData->dir); closedir(findData->dir);
findData->dir = NULL;
return false; return false;
} }
#endif #endif
@ -34,9 +56,23 @@ bool fileFindNext(DirectoryFileFindData* findData)
return false; return false;
} }
#else #else
char drive[COMPAT_MAX_DRIVE];
char dir[COMPAT_MAX_DIR];
compat_splitpath(findData->path, drive, dir, NULL, NULL);
findData->entry = readdir(findData->dir); findData->entry = readdir(findData->dir);
while (findData->entry != NULL) {
char entryPath[COMPAT_MAX_PATH];
compat_makepath(entryPath, drive, dir, fileFindGetName(findData), NULL);
if (fpattern_match(findData->path, entryPath)) {
break;
}
findData->entry = readdir(findData->dir);
}
if (findData->entry == NULL) { if (findData->entry == NULL) {
closedir(findData->dir); closedir(findData->dir);
findData->dir = NULL;
return false; return false;
} }
#endif #endif
@ -50,9 +86,11 @@ bool findFindClose(DirectoryFileFindData* findData)
#if defined(_MSC_VER) #if defined(_MSC_VER)
FindClose(findData->hFind); FindClose(findData->hFind);
#else #else
if (findData->dir != NULL) {
if (closedir(findData->dir) != 0) { if (closedir(findData->dir) != 0) {
return false; return false;
} }
}
#endif #endif
return true; return true;

View File

@ -1,6 +1,8 @@
#ifndef FILE_FIND_H #ifndef FILE_FIND_H
#define FILE_FIND_H #define FILE_FIND_H
#include "platform_compat.h"
#if defined(_WIN32) #if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#define NOMINMAX #define NOMINMAX
@ -35,6 +37,7 @@ typedef struct DirectoryFileFindData {
#else #else
DIR* dir; DIR* dir;
struct dirent* entry; struct dirent* entry;
char path[COMPAT_MAX_PATH];
#endif #endif
} DirectoryFileFindData; } DirectoryFileFindData;

View File

@ -2,8 +2,10 @@
// of regular __usercall. // of regular __usercall.
#include "file_utils.h" #include "file_utils.h"
#include "platform_compat.h"
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <zlib.h> #include <zlib.h>
#include <filesystem> #include <filesystem>
@ -11,7 +13,7 @@
// 0x452740 // 0x452740
int fileCopyDecompressed(const char* existingFilePath, const char* newFilePath) int fileCopyDecompressed(const char* existingFilePath, const char* newFilePath)
{ {
FILE* stream = fopen(existingFilePath, "rb"); FILE* stream = compat_fopen(existingFilePath, "rb");
if (stream == NULL) { if (stream == NULL) {
return -1; return -1;
} }
@ -22,8 +24,8 @@ int fileCopyDecompressed(const char* existingFilePath, const char* newFilePath)
fclose(stream); fclose(stream);
if (magic[0] == 0x1F && magic[1] == 0x8B) { if (magic[0] == 0x1F && magic[1] == 0x8B) {
gzFile inStream = gzopen(existingFilePath, "rb"); gzFile inStream = compat_gzopen(existingFilePath, "rb");
FILE* outStream = fopen(newFilePath, "wb"); FILE* outStream = compat_fopen(newFilePath, "wb");
if (inStream != NULL && outStream != NULL) { if (inStream != NULL && outStream != NULL) {
for (;;) { for (;;) {
@ -58,7 +60,7 @@ int fileCopyDecompressed(const char* existingFilePath, const char* newFilePath)
// 0x452804 // 0x452804
int fileCopyCompressed(const char* existingFilePath, const char* newFilePath) int fileCopyCompressed(const char* existingFilePath, const char* newFilePath)
{ {
FILE* inStream = fopen(existingFilePath, "rb"); FILE* inStream = compat_fopen(existingFilePath, "rb");
if (inStream == NULL) { if (inStream == NULL) {
return -1; return -1;
} }
@ -74,7 +76,7 @@ int fileCopyCompressed(const char* existingFilePath, const char* newFilePath)
fclose(inStream); fclose(inStream);
fileCopy(existingFilePath, newFilePath, true); fileCopy(existingFilePath, newFilePath, true);
} else { } else {
gzFile outStream = gzopen(newFilePath, "wb"); gzFile outStream = compat_gzopen(newFilePath, "wb");
if (outStream == NULL) { if (outStream == NULL) {
fclose(inStream); fclose(inStream);
return -1; return -1;
@ -100,7 +102,7 @@ int fileCopyCompressed(const char* existingFilePath, const char* newFilePath)
// TODO: Check, implementation looks odd. // TODO: Check, implementation looks odd.
int _gzdecompress_file(const char* existingFilePath, const char* newFilePath) int _gzdecompress_file(const char* existingFilePath, const char* newFilePath)
{ {
FILE* stream = fopen(existingFilePath, "rb"); FILE* stream = compat_fopen(existingFilePath, "rb");
if (stream == NULL) { if (stream == NULL) {
return -1; return -1;
} }
@ -112,12 +114,12 @@ int _gzdecompress_file(const char* existingFilePath, const char* newFilePath)
// TODO: Is it broken? // TODO: Is it broken?
if (magic[0] != 0x1F || magic[1] != 0x8B) { if (magic[0] != 0x1F || magic[1] != 0x8B) {
gzFile gzstream = gzopen(existingFilePath, "rb"); gzFile gzstream = compat_gzopen(existingFilePath, "rb");
if (gzstream == NULL) { if (gzstream == NULL) {
return -1; return -1;
} }
stream = fopen(newFilePath, "wb"); stream = compat_fopen(newFilePath, "wb");
if (stream == NULL) { if (stream == NULL) {
gzclose(gzstream); gzclose(gzstream);
return -1; return -1;
@ -145,9 +147,17 @@ int _gzdecompress_file(const char* existingFilePath, const char* newFilePath)
// `bFailIfExists` param. Update callers accordingly. // `bFailIfExists` param. Update callers accordingly.
void fileCopy(const char* existingFilePath, const char* newFilePath, bool overwrite) void fileCopy(const char* existingFilePath, const char* newFilePath, bool overwrite)
{ {
char nativeExistingFilePath[COMPAT_MAX_PATH];
strcpy(nativeExistingFilePath, existingFilePath);
compat_windows_path_to_native(nativeExistingFilePath);
char nativeNewFilePath[COMPAT_MAX_PATH];
strcpy(nativeNewFilePath, newFilePath);
compat_windows_path_to_native(nativeNewFilePath);
std::error_code ec; std::error_code ec;
std::filesystem::copy_options options = overwrite std::filesystem::copy_options options = overwrite
? std::filesystem::copy_options::overwrite_existing ? std::filesystem::copy_options::overwrite_existing
: std::filesystem::copy_options::none; : std::filesystem::copy_options::none;
std::filesystem::copy_file(std::filesystem::path(existingFilePath), std::filesystem::path(newFilePath), options, ec); std::filesystem::copy_file(std::filesystem::path(nativeExistingFilePath), std::filesystem::path(nativeNewFilePath), options, ec);
} }

View File

@ -1703,7 +1703,7 @@ int gameSoundFindBackgroundSoundPathWithCopy(char* dest, const char* src)
char inPath[COMPAT_MAX_PATH]; char inPath[COMPAT_MAX_PATH];
sprintf(inPath, "%s%s%s", _sound_music_path2, src, ".ACM"); sprintf(inPath, "%s%s%s", _sound_music_path2, src, ".ACM");
FILE* inStream = fopen(inPath, "rb"); FILE* inStream = compat_fopen(inPath, "rb");
if (inStream == NULL) { if (inStream == NULL) {
if (gGameSoundDebugEnabled) { if (gGameSoundDebugEnabled) {
debugPrint("Unable to find music file %s to copy down.\n", src); debugPrint("Unable to find music file %s to copy down.\n", src);
@ -1712,7 +1712,7 @@ int gameSoundFindBackgroundSoundPathWithCopy(char* dest, const char* src)
return -1; return -1;
} }
FILE* outStream = fopen(outPath, "wb"); FILE* outStream = compat_fopen(outPath, "wb");
if (outStream == NULL) { if (outStream == NULL) {
if (gGameSoundDebugEnabled) { if (gGameSoundDebugEnabled) {
debugPrint("Unable to open music file %s for copying to.", src); debugPrint("Unable to open music file %s for copying to.", src);
@ -1857,7 +1857,7 @@ void gameSoundDeleteOldMusicFile()
if (_background_fname_copied[0] != '\0') { if (_background_fname_copied[0] != '\0') {
char path[COMPAT_MAX_PATH]; char path[COMPAT_MAX_PATH];
sprintf(path, "%s%s%s", "sound\\music\\", _background_fname_copied, ".ACM"); sprintf(path, "%s%s%s", "sound\\music\\", _background_fname_copied, ".ACM");
if (remove(path)) { if (compat_remove(path)) {
if (gGameSoundDebugEnabled) { if (gGameSoundDebugEnabled) {
debugPrint("Deleting old music file failed.\n"); debugPrint("Deleting old music file failed.\n");
} }
@ -2026,7 +2026,7 @@ Sound* _gsound_get_sound_ready_for_effect()
// 0x4524E0 // 0x4524E0
bool _gsound_file_exists_f(const char* fname) bool _gsound_file_exists_f(const char* fname)
{ {
FILE* f = fopen(fname, "rb"); FILE* f = compat_fopen(fname, "rb");
if (f == NULL) { if (f == NULL) {
return false; return false;
} }

View File

@ -57,6 +57,18 @@
#define LS_COMMENT_WINDOW_X 169 #define LS_COMMENT_WINDOW_X 169
#define LS_COMMENT_WINDOW_Y 116 #define LS_COMMENT_WINDOW_Y 116
// NOTE: The following are "normalized" path components for "proto/critters" and
// "proto/items". The original code does not use uniform case for them (as
// opposed to other path components like MAPS, SAVE.DAT, etc). It does not have
// effect on Windows, but it's important on Linux and Mac, where filesystem is
// case-sensitive. Lowercase is preferred as it is used in other parts of the
// codebase (see `protoInit`, `gArtListDescriptions`).
#define PROTO_DIR_NAME "proto"
#define CRITTERS_DIR_NAME "critters"
#define ITEMS_DIR_NAME "items"
#define PROTO_FILE_EXT "pro"
// 0x47B7C0 // 0x47B7C0
const int gLoadSaveFrmIds[LOAD_SAVE_FRM_COUNT] = { const int gLoadSaveFrmIds[LOAD_SAVE_FRM_COUNT] = {
237, // lsgame.frm - load/save game 237, // lsgame.frm - load/save game
@ -233,16 +245,16 @@ void _InitLoadSave()
} }
_MapDirErase("MAPS\\", "SAV"); _MapDirErase("MAPS\\", "SAV");
_MapDirErase("PROTO\\CRITTERS\\", "PRO"); _MapDirErase(PROTO_DIR_NAME "\\" CRITTERS_DIR_NAME "\\", PROTO_FILE_EXT);
_MapDirErase("PROTO\\ITEMS\\", "PRO"); _MapDirErase(PROTO_DIR_NAME "\\" ITEMS_DIR_NAME "\\", PROTO_FILE_EXT);
} }
// 0x47B85C // 0x47B85C
void _ResetLoadSave() void _ResetLoadSave()
{ {
_MapDirErase("MAPS\\", "SAV"); _MapDirErase("MAPS\\", "SAV");
_MapDirErase("PROTO\\CRITTERS\\", "PRO"); _MapDirErase(PROTO_DIR_NAME "\\" CRITTERS_DIR_NAME "\\", PROTO_FILE_EXT);
_MapDirErase("PROTO\\ITEMS\\", "PRO"); _MapDirErase(PROTO_DIR_NAME "\\" ITEMS_DIR_NAME "\\", PROTO_FILE_EXT);
} }
// SaveGame // SaveGame
@ -1329,15 +1341,15 @@ int lsgPerformSaveGame()
sprintf(_gmpath, "%s\\%s\\%s%.2d", _patches, "SAVEGAME", "SLOT", _slot_cursor + 1); sprintf(_gmpath, "%s\\%s\\%s%.2d", _patches, "SAVEGAME", "SLOT", _slot_cursor + 1);
compat_mkdir(_gmpath); compat_mkdir(_gmpath);
strcat(_gmpath, "\\proto"); strcat(_gmpath, "\\" PROTO_DIR_NAME);
compat_mkdir(_gmpath); compat_mkdir(_gmpath);
char* protoBasePath = _gmpath + strlen(_gmpath); char* protoBasePath = _gmpath + strlen(_gmpath);
strcpy(protoBasePath, "\\critters"); strcpy(protoBasePath, "\\" CRITTERS_DIR_NAME);
compat_mkdir(_gmpath); compat_mkdir(_gmpath);
strcpy(protoBasePath, "\\items"); strcpy(protoBasePath, "\\" ITEMS_DIR_NAME);
compat_mkdir(_gmpath); compat_mkdir(_gmpath);
if (_SaveBackup() == -1) { if (_SaveBackup() == -1) {
@ -1576,7 +1588,8 @@ int lsgSaveHeaderInSlot(int slot)
char mapName[128]; char mapName[128];
strcpy(mapName, gMapHeader.name); strcpy(mapName, gMapHeader.name);
char* v1 = _strmfe(_str, mapName, "sav"); // NOTE: Uppercased from "sav".
char* v1 = _strmfe(_str, mapName, "SAV");
strncpy(ptr->file_name, v1, 16); strncpy(ptr->file_name, v1, 16);
if (fileWrite(ptr->file_name, 16, 1, _flptr) != 1) { if (fileWrite(ptr->file_name, 16, 1, _flptr) != 1) {
return -1; return -1;
@ -2141,7 +2154,9 @@ int _GameMap2Slot(File* stream)
continue; continue;
} }
const char* critterItemPath = (pid >> 24) == OBJ_TYPE_CRITTER ? "PROTO\\CRITTERS" : "PROTO\\ITEMS"; const char* critterItemPath = (pid >> 24) == OBJ_TYPE_CRITTER
? PROTO_DIR_NAME "\\" CRITTERS_DIR_NAME
: PROTO_DIR_NAME "\\" ITEMS_DIR_NAME;
sprintf(_str0, "%s\\%s\\%s", _patches, critterItemPath, path); sprintf(_str0, "%s\\%s\\%s", _patches, critterItemPath, path);
sprintf(_str1, "%s\\%s\\%s%.2d\\%s\\%s", _patches, "SAVEGAME", "SLOT", _slot_cursor + 1, critterItemPath, path); sprintf(_str1, "%s\\%s\\%s%.2d\\%s\\%s", _patches, "SAVEGAME", "SLOT", _slot_cursor + 1, critterItemPath, path);
if (fileCopyCompressed(_str0, _str1) == -1) { if (fileCopyCompressed(_str0, _str1) == -1) {
@ -2177,7 +2192,7 @@ int _GameMap2Slot(File* stream)
sprintf(_gmpath, "%s\\%s\\%s%.2d\\", _patches, "SAVEGAME", "SLOT", _slot_cursor + 1); sprintf(_gmpath, "%s\\%s\\%s%.2d\\", _patches, "SAVEGAME", "SLOT", _slot_cursor + 1);
_strmfe(_str0, "AUTOMAP.DB", "SAV"); _strmfe(_str0, "AUTOMAP.DB", "SAV");
strcat(_gmpath, _str0); strcat(_gmpath, _str0);
remove(_gmpath); compat_remove(_gmpath);
for (int index = 0; index < fileNameListLength; index += 1) { for (int index = 0; index < fileNameListLength; index += 1) {
char* string = fileNameList[index]; char* string = fileNameList[index];
@ -2246,15 +2261,15 @@ int _SlotMap2Game(File* stream)
return -1; return -1;
} }
sprintf(_str0, "%s\\", "PROTO\\CRITTERS"); sprintf(_str0, "%s\\", PROTO_DIR_NAME "\\" CRITTERS_DIR_NAME);
if (_MapDirErase(_str0, "PRO") == -1) { if (_MapDirErase(_str0, PROTO_FILE_EXT) == -1) {
debugPrint("LOADSAVE: returning 3\n"); debugPrint("LOADSAVE: returning 3\n");
return -1; return -1;
} }
sprintf(_str0, "%s\\", "PROTO\\ITEMS"); sprintf(_str0, "%s\\", PROTO_DIR_NAME "\\" ITEMS_DIR_NAME);
if (_MapDirErase(_str0, "PRO") == -1) { if (_MapDirErase(_str0, PROTO_FILE_EXT) == -1) {
debugPrint("LOADSAVE: returning 4\n"); debugPrint("LOADSAVE: returning 4\n");
return -1; return -1;
} }
@ -2266,7 +2281,7 @@ int _SlotMap2Game(File* stream)
} }
sprintf(_str0, "%s\\%s\\%s", _patches, "MAPS", "AUTOMAP.DB"); sprintf(_str0, "%s\\%s\\%s", _patches, "MAPS", "AUTOMAP.DB");
remove(_str0); compat_remove(_str0);
if (gPartyMemberDescriptionsLength > 1) { if (gPartyMemberDescriptionsLength > 1) {
for (int index = 1; index < gPartyMemberDescriptionsLength; index += 1) { for (int index = 1; index < gPartyMemberDescriptionsLength; index += 1) {
@ -2275,8 +2290,8 @@ int _SlotMap2Game(File* stream)
char protoPath[COMPAT_MAX_PATH]; char protoPath[COMPAT_MAX_PATH];
if (_proto_list_str(pid, protoPath) == 0) { if (_proto_list_str(pid, protoPath) == 0) {
const char* basePath = pid >> 24 == OBJ_TYPE_CRITTER const char* basePath = pid >> 24 == OBJ_TYPE_CRITTER
? "PROTO\\CRITTERS" ? PROTO_DIR_NAME "\\" CRITTERS_DIR_NAME
: "PROTO\\ITEMS"; : PROTO_DIR_NAME "\\" ITEMS_DIR_NAME;
sprintf(_str0, "%s\\%s\\%s", _patches, basePath, protoPath); sprintf(_str0, "%s\\%s\\%s", _patches, basePath, protoPath);
sprintf(_str1, "%s\\%s\\%s%.2d\\%s\\%s", _patches, "SAVEGAME", "SLOT", _slot_cursor + 1, basePath, protoPath); sprintf(_str1, "%s\\%s\\%s%.2d\\%s\\%s", _patches, "SAVEGAME", "SLOT", _slot_cursor + 1, basePath, protoPath);
@ -2448,7 +2463,7 @@ int _MapDirErase(const char* relativePath, const char* extension)
int fileListLength = fileNameListInit(path, &fileList, 0, 0); int fileListLength = fileNameListInit(path, &fileList, 0, 0);
while (--fileListLength >= 0) { while (--fileListLength >= 0) {
sprintf(path, "%s\\%s%s", _patches, relativePath, fileList[fileListLength]); sprintf(path, "%s\\%s%s", _patches, relativePath, fileList[fileListLength]);
remove(path); compat_remove(path);
} }
fileNameListFree(&fileList, 0); fileNameListFree(&fileList, 0);
@ -2461,7 +2476,7 @@ int _MapDirEraseFile_(const char* a1, const char* a2)
char path[COMPAT_MAX_PATH]; char path[COMPAT_MAX_PATH];
sprintf(path, "%s\\%s%s", _patches, a1, a2); sprintf(path, "%s\\%s%s", _patches, a1, a2);
if (remove(path) != 0) { if (compat_remove(path) != 0) {
return -1; return -1;
} }
@ -2483,7 +2498,7 @@ int _SaveBackup()
File* stream1 = fileOpen(_str0, "rb"); File* stream1 = fileOpen(_str0, "rb");
if (stream1 != NULL) { if (stream1 != NULL) {
fileClose(stream1); fileClose(stream1);
if (rename(_str0, _str1) != 0) { if (compat_rename(_str0, _str1) != 0) {
return -1; return -1;
} }
} }
@ -2505,7 +2520,7 @@ int _SaveBackup()
strcat(_str0, fileList[index]); strcat(_str0, fileList[index]);
_strmfe(_str1, _str0, "BAK"); _strmfe(_str1, _str0, "BAK");
if (rename(_str0, _str1) != 0) { if (compat_rename(_str0, _str1) != 0) {
fileNameListFree(&fileList, 0); fileNameListFree(&fileList, 0);
return -1; return -1;
} }
@ -2550,9 +2565,9 @@ int _RestoreSave()
strcpy(_str0, _gmpath); strcpy(_str0, _gmpath);
strcat(_str0, "SAVE.DAT"); strcat(_str0, "SAVE.DAT");
_strmfe(_str1, _str0, "BAK"); _strmfe(_str1, _str0, "BAK");
remove(_str0); compat_remove(_str0);
if (rename(_str1, _str0) != 0) { if (compat_rename(_str1, _str0) != 0) {
_EraseSave(); _EraseSave();
return -1; return -1;
} }
@ -2578,8 +2593,8 @@ int _RestoreSave()
strcpy(_str0, _gmpath); strcpy(_str0, _gmpath);
strcat(_str0, fileList[index]); strcat(_str0, fileList[index]);
_strmfe(_str1, _str0, "SAV"); _strmfe(_str1, _str0, "SAV");
remove(_str1); compat_remove(_str1);
if (rename(_str0, _str1) != 0) { if (compat_rename(_str0, _str1) != 0) {
// FIXME: Probably leaks fileList. // FIXME: Probably leaks fileList.
_EraseSave(); _EraseSave();
return -1; return -1;
@ -2601,7 +2616,7 @@ int _RestoreSave()
strcpy(_str1, _gmpath); strcpy(_str1, _gmpath);
strcat(_str1, v2); strcat(_str1, v2);
if (rename(_str0, _str1) != 0) { if (compat_rename(_str0, _str1) != 0) {
_EraseSave(); _EraseSave();
return -1; return -1;
} }
@ -2637,7 +2652,7 @@ int _EraseSave()
sprintf(_gmpath, "%s\\%s\\%s%.2d\\", _patches, "SAVEGAME", "SLOT", _slot_cursor + 1); sprintf(_gmpath, "%s\\%s\\%s%.2d\\", _patches, "SAVEGAME", "SLOT", _slot_cursor + 1);
strcpy(_str0, _gmpath); strcpy(_str0, _gmpath);
strcat(_str0, "SAVE.DAT"); strcat(_str0, "SAVE.DAT");
remove(_str0); compat_remove(_str0);
sprintf(_gmpath, "%s\\%s%.2d\\", "SAVEGAME", "SLOT", _slot_cursor + 1); sprintf(_gmpath, "%s\\%s%.2d\\", "SAVEGAME", "SLOT", _slot_cursor + 1);
sprintf(_str0, "%s*.%s", _gmpath, "SAV"); sprintf(_str0, "%s*.%s", _gmpath, "SAV");
@ -2652,7 +2667,7 @@ int _EraseSave()
for (int index = fileListLength - 1; index >= 0; index--) { for (int index = fileListLength - 1; index >= 0; index--) {
strcpy(_str0, _gmpath); strcpy(_str0, _gmpath);
strcat(_str0, fileList[index]); strcat(_str0, fileList[index]);
remove(_str0); compat_remove(_str0);
} }
fileNameListFree(&fileList, 0); fileNameListFree(&fileList, 0);
@ -2663,7 +2678,7 @@ int _EraseSave()
strcpy(_str0, _gmpath); strcpy(_str0, _gmpath);
strcat(_str0, v1); strcat(_str0, v1);
remove(_str0); compat_remove(_str0);
return 0; return 0;
} }

View File

@ -644,7 +644,8 @@ int mapScroll(int dx, int dy)
char* mapBuildPath(char* name) char* mapBuildPath(char* name)
{ {
if (*name != '\\') { if (*name != '\\') {
sprintf(_map_path, "maps\\%s", name); // NOTE: Uppercased from "maps".
sprintf(_map_path, "MAPS\\%s", name);
return _map_path; return _map_path;
} }
return name; return name;

View File

@ -132,8 +132,12 @@ long compat_filelength(int fd)
int compat_mkdir(const char* path) int compat_mkdir(const char* path)
{ {
char nativePath[COMPAT_MAX_PATH];
strcpy(nativePath, path);
compat_windows_path_to_native(nativePath);
std::error_code ec; std::error_code ec;
if (std::filesystem::create_directory(std::filesystem::path(path), ec)) { if (std::filesystem::create_directory(std::filesystem::path(nativePath), ec)) {
return 0; return 0;
} }
@ -150,3 +154,53 @@ unsigned int compat_timeGetTime()
return static_cast<unsigned int>(std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count()); return static_cast<unsigned int>(std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count());
#endif #endif
} }
FILE* compat_fopen(const char* path, const char* mode)
{
char nativePath[COMPAT_MAX_PATH];
strcpy(nativePath, path);
compat_windows_path_to_native(nativePath);
return fopen(nativePath, mode);
}
gzFile compat_gzopen(const char* path, const char* mode)
{
char nativePath[COMPAT_MAX_PATH];
strcpy(nativePath, path);
compat_windows_path_to_native(nativePath);
return gzopen(nativePath, mode);
}
int compat_remove(const char* path)
{
char nativePath[COMPAT_MAX_PATH];
strcpy(nativePath, path);
compat_windows_path_to_native(nativePath);
return remove(nativePath);
}
int compat_rename(const char* oldFileName, const char* newFileName)
{
char nativeOldFileName[COMPAT_MAX_PATH];
strcpy(nativeOldFileName, oldFileName);
compat_windows_path_to_native(nativeOldFileName);
char nativeNewFileName[COMPAT_MAX_PATH];
strcpy(nativeNewFileName, newFileName);
compat_windows_path_to_native(nativeNewFileName);
return rename(nativeOldFileName, nativeNewFileName);
}
void compat_windows_path_to_native(char* path)
{
#ifndef _WIN32
char* pch = path;
while (*pch != '\0') {
if (*pch == '\\') {
*pch = '/';
}
pch++;
}
#endif
}

View File

@ -2,6 +2,9 @@
#define PLATFORM_COMPAT_H #define PLATFORM_COMPAT_H
#include <stddef.h> #include <stddef.h>
#include <stdio.h>
#include <zlib.h>
// TODO: This is compatibility cross-platform layer. Designed to have minimal // TODO: This is compatibility cross-platform layer. Designed to have minimal
// impact on the codebase. Remove once it's no longer needed. // impact on the codebase. Remove once it's no longer needed.
@ -31,5 +34,10 @@ long compat_tell(int fileHandle);
long compat_filelength(int fd); long compat_filelength(int fd);
int compat_mkdir(const char* path); int compat_mkdir(const char* path);
unsigned int compat_timeGetTime(); unsigned int compat_timeGetTime();
FILE* compat_fopen(const char* path, const char* mode);
gzFile compat_gzopen(const char* path, const char* mode);
int compat_remove(const char* path);
int compat_rename(const char* oldFileName, const char* newFileName);
void compat_windows_path_to_native(char* path);
#endif /* PLATFORM_COMPAT_H */ #endif /* PLATFORM_COMPAT_H */

View File

@ -65,7 +65,7 @@ XFile* xfileOpen(const char* filePath, const char* mode)
char path[COMPAT_MAX_PATH]; char path[COMPAT_MAX_PATH];
if (drive[0] != '\0' || dir[0] == '\\' || dir[0] == '/' || dir[0] == '.') { if (drive[0] != '\0' || dir[0] == '\\' || dir[0] == '/' || dir[0] == '.') {
// [filePath] is an absolute path. Attempt to open as plain stream. // [filePath] is an absolute path. Attempt to open as plain stream.
stream->file = fopen(filePath, mode); stream->file = compat_fopen(filePath, mode);
if (stream->file == NULL) { if (stream->file == NULL) {
free(stream); free(stream);
return NULL; return NULL;
@ -91,7 +91,7 @@ XFile* xfileOpen(const char* filePath, const char* mode)
sprintf(path, "%s\\%s", curr->path, filePath); sprintf(path, "%s\\%s", curr->path, filePath);
// Attempt to open plain stream. // Attempt to open plain stream.
stream->file = fopen(path, mode); stream->file = compat_fopen(path, mode);
if (stream->file != NULL) { if (stream->file != NULL) {
stream->type = XFILE_TYPE_FILE; stream->type = XFILE_TYPE_FILE;
break; break;
@ -103,7 +103,7 @@ XFile* xfileOpen(const char* filePath, const char* mode)
if (stream->file == NULL) { if (stream->file == NULL) {
// File was not opened during the loop above. Attempt to open file // File was not opened during the loop above. Attempt to open file
// relative to the current working directory. // relative to the current working directory.
stream->file = fopen(filePath, mode); stream->file = compat_fopen(filePath, mode);
if (stream->file == NULL) { if (stream->file == NULL) {
free(stream); free(stream);
return NULL; return NULL;
@ -125,7 +125,7 @@ XFile* xfileOpen(const char* filePath, const char* mode)
fclose(stream->file); fclose(stream->file);
stream->type = XFILE_TYPE_GZFILE; stream->type = XFILE_TYPE_GZFILE;
stream->gzfile = gzopen(path, mode); stream->gzfile = compat_gzopen(path, mode);
} else { } else {
// File is not gzipped. // File is not gzipped.
rewind(stream->file); rewind(stream->file);
@ -544,13 +544,17 @@ bool xlistEnumerate(const char* pattern, XListEnumerationHandler* handler, XList
context.xlist = xlist; context.xlist = xlist;
char nativePattern[COMPAT_MAX_PATH];
strcpy(nativePattern, pattern);
compat_windows_path_to_native(nativePattern);
char drive[COMPAT_MAX_DRIVE]; char drive[COMPAT_MAX_DRIVE];
char dir[COMPAT_MAX_DIR]; char dir[COMPAT_MAX_DIR];
char fileName[COMPAT_MAX_FNAME]; char fileName[COMPAT_MAX_FNAME];
char extension[COMPAT_MAX_EXT]; char extension[COMPAT_MAX_EXT];
compat_splitpath(pattern, drive, dir, fileName, extension); compat_splitpath(nativePattern, drive, dir, fileName, extension);
if (drive[0] != '\0' || dir[0] == '\\' || dir[0] == '/' || dir[0] == '.') { if (drive[0] != '\0' || dir[0] == '\\' || dir[0] == '/' || dir[0] == '.') {
if (fileFindFirst(pattern, &directoryFileFindData)) { if (fileFindFirst(nativePattern, &directoryFileFindData)) {
do { do {
bool isDirectory = fileFindIsDirectory(&directoryFileFindData); bool isDirectory = fileFindIsDirectory(&directoryFileFindData);
char* entryName = fileFindGetName(&directoryFileFindData); char* entryName = fileFindGetName(&directoryFileFindData);
@ -594,6 +598,7 @@ bool xlistEnumerate(const char* pattern, XListEnumerationHandler* handler, XList
} else { } else {
char path[COMPAT_MAX_PATH]; char path[COMPAT_MAX_PATH];
sprintf(path, "%s\\%s", xbase->path, pattern); sprintf(path, "%s\\%s", xbase->path, pattern);
compat_windows_path_to_native(path);
if (fileFindFirst(path, &directoryFileFindData)) { if (fileFindFirst(path, &directoryFileFindData)) {
do { do {
@ -622,8 +627,8 @@ bool xlistEnumerate(const char* pattern, XListEnumerationHandler* handler, XList
xbase = xbase->next; xbase = xbase->next;
} }
compat_splitpath(pattern, drive, dir, fileName, extension); compat_splitpath(nativePattern, drive, dir, fileName, extension);
if (fileFindFirst(pattern, &directoryFileFindData)) { if (fileFindFirst(nativePattern, &directoryFileFindData)) {
do { do {
bool isDirectory = fileFindIsDirectory(&directoryFileFindData); bool isDirectory = fileFindIsDirectory(&directoryFileFindData);
char* entryName = fileFindGetName(&directoryFileFindData); char* entryName = fileFindGetName(&directoryFileFindData);