Map internal paths to filesystem paths (#100)

* Map internal paths to actual filesystem paths

* Only do this on non-Windows

* Update LEGO1/omni/src/common/mxstring.cpp

Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>

* add priority

* Revert for now

---------

Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>
This commit is contained in:
Christian Semmler 2025-05-16 18:46:50 -07:00 committed by GitHub
parent 543edf292a
commit 5ae47c2b56
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 74 additions and 12 deletions

View File

@ -172,7 +172,7 @@ MxResult LegoWorldPresenter::LoadWorld(char* p_worldName, LegoWorld* p_world)
}
strcat(wdbPath, "lego\\data\\world.wdb");
MxString::NormalizePath(wdbPath);
MxString::MapPathToFilesystem(wdbPath);
SDL_IOStream* wdbFile;
@ -184,7 +184,7 @@ MxResult LegoWorldPresenter::LoadWorld(char* p_worldName, LegoWorld* p_world)
}
strcat(wdbPath, "lego\\data\\world.wdb");
MxString::NormalizePath(wdbPath);
MxString::MapPathToFilesystem(wdbPath);
if ((wdbFile = SDL_IOFromFile(wdbPath, "rb")) == NULL) {
return FAILURE;

View File

@ -121,7 +121,7 @@ LegoResult LegoFile::Open(const char* p_name, LegoU32 p_mode)
}
MxString path(p_name);
path.NormalizePath();
path.MapPathToFilesystem();
if (!(m_file = SDL_IOFromFile(path.GetData(), mode))) {
return FAILURE;

View File

@ -4,6 +4,7 @@
#include "lego1_export.h"
#include "mxcore.h"
#include "mxcriticalsection.h"
#include "mxstl/stlcompat.h"
#include "mxstring.h"
#include <SDL3/SDL_video.h>
@ -42,7 +43,8 @@ class MxOmni : public MxCore {
LEGO1_EXPORT static void SetCD(const char* p_cd);
LEGO1_EXPORT static void SetHD(const char* p_hd);
LEGO1_EXPORT static void SetSound3D(MxBool p_use3dSound);
static void NormalizePath(char* p_path);
static const vector<MxString>& GetHDFiles() { return g_hdFiles; }
static const vector<MxString>& GetCDFiles() { return g_cdFiles; }
MxOmni();
~MxOmni() override;
@ -105,6 +107,10 @@ class MxOmni : public MxCore {
protected:
static MxOmni* g_instance;
static vector<MxString> g_hdFiles;
static vector<MxString> g_cdFiles;
static vector<MxString> GlobIsleFiles(const MxString& p_path);
MxString m_mediaPath; // 0x08
HWND m_windowHandle; // 0x18

View File

@ -18,7 +18,7 @@ class MxString : public MxCore {
void Reverse();
void ToUpperCase();
void ToLowerCase();
void NormalizePath() { NormalizePath(m_data); }
void MapPathToFilesystem() { MapPathToFilesystem(m_data); }
MxString& operator=(const MxString& p_str);
const MxString& operator=(const char* p_str);
@ -27,7 +27,7 @@ class MxString : public MxCore {
MxString& operator+=(const char* p_str);
static void CharSwap(char* p_a, char* p_b);
static void NormalizePath(char* p_path);
static void MapPathToFilesystem(char* p_path);
// FUNCTION: BETA10 0x10017c50
char* GetData() const { return m_data; }

View File

@ -1,7 +1,9 @@
#include "mxstring.h"
#include "decomp.h"
#include "mxomni.h"
#include <SDL3/SDL_log.h>
#include <SDL3/SDL_platform_defines.h>
#include <SDL3/SDL_stdinc.h>
#include <stdlib.h>
@ -188,13 +190,11 @@ void MxString::CharSwap(char* p_a, char* p_b)
*p_b = t;
}
void MxString::NormalizePath(char* p_path)
void MxString::MapPathToFilesystem(char* p_path)
{
// [library:filesystem]
// This function is used to build a consistent path that will eventually be used to read a file.
// The input may come with Windows path separators, i.e. \lego\scripts\infocntr\infomain
// We have to replace the backslashes with forward slashes to be able to access the files
// on non-Windows systems
// This function is used to map an internal Windows-style path (found in SI files or in the code)
// to an actual file on disk or CD. We have to account for both Windows path separators and case.
#if !defined(SDL_PLATFORM_WINDOWS)
char* path = p_path;
while (*path) {
@ -204,5 +204,30 @@ void MxString::NormalizePath(char* p_path)
path++;
}
size_t pathLen = SDL_strlen(p_path);
auto mapPath = [p_path, pathLen](const vector<MxString>& p_files) -> bool {
for (const MxString& file : p_files) {
// Test whether file is a suffix of the provided path (case insensitive)
// If yes, copy the original file system path into p_path.
for (size_t i = pathLen, j = file.GetLength(); i != 0 && j != 0; i--, j--) {
if (SDL_tolower(p_path[i - 1]) != SDL_tolower(file.GetData()[j - 1])) {
break;
}
else if (j == 1) {
SDL_strlcpy(&p_path[i - 1], file.GetData(), file.GetLength() + 1);
SDL_Log("Resolved file path to %s", p_path);
return true;
}
}
}
return false;
};
if (!mapPath(MxOmni::GetHDFiles())) {
mapPath(MxOmni::GetCDFiles());
}
#endif
}

View File

@ -17,6 +17,9 @@
#include "mxvariabletable.h"
#include "mxvideomanager.h"
#include <SDL3/SDL_filesystem.h>
#include <SDL3/SDL_log.h>
// GLOBAL: LEGO1 0x101015b8
MxString g_hdPath = "";
@ -29,6 +32,9 @@ MxBool g_use3dSound = FALSE;
// GLOBAL: LEGO1 0x101015b0
MxOmni* MxOmni::g_instance = NULL;
vector<MxString> MxOmni::g_hdFiles;
vector<MxString> MxOmni::g_cdFiles;
// FUNCTION: LEGO1 0x100aef10
MxOmni::MxOmni()
{
@ -357,6 +363,7 @@ const char* MxOmni::GetHD()
void MxOmni::SetHD(const char* p_hd)
{
g_hdPath = p_hd;
g_hdFiles = GlobIsleFiles(g_hdPath);
}
// FUNCTION: LEGO1 0x100b0940
@ -369,6 +376,7 @@ const char* MxOmni::GetCD()
void MxOmni::SetCD(const char* p_cd)
{
g_cdPath = p_cd;
g_cdFiles = GlobIsleFiles(g_cdPath);
}
// FUNCTION: LEGO1 0x100b0980
@ -415,3 +423,26 @@ void MxOmni::Resume()
m_paused = FALSE;
}
}
vector<MxString> MxOmni::GlobIsleFiles(const MxString& p_path)
{
int count;
char** files = SDL_GlobDirectory(p_path.GetData(), NULL, 0, &count);
vector<MxString> result;
if (files == NULL) {
SDL_Log("Error enumerating files for path %s (%s)", p_path.GetData(), SDL_GetError());
return result;
}
for (int i = 0; i < count; i++) {
if (!SDL_strncasecmp(files[i], "lego", 4)) {
result.emplace_back(files[i]);
}
}
SDL_Log("Found %d game files in %s", count, p_path.GetData());
SDL_free(files);
return result;
}

View File

@ -41,7 +41,7 @@ MxU16 MXIOINFO::Open(const char* p_filename, MxULong p_flags)
m_info.lDiskOffset = m_info.lBufOffset = 0;
MxString path(p_filename);
path.NormalizePath();
path.MapPathToFilesystem();
ASSIGN_M_FILE(SDL_IOFromFile(path.GetData(), "rb"));
if (M_FILE != NULL) {