From b4eb336f76f6fe12395e2b67e52108a35f06b573 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sun, 21 Jun 2026 09:26:29 +0200 Subject: [PATCH 1/8] PORTABLE_BUILD option: keep game and user data in the directory IVAN is launched from --- CMakeLists.txt | 7 +++++++ FeLib/Source/save.cpp | 4 ++++ Main/Source/game.cpp | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 95db47bc7..a75528373 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,9 +15,11 @@ add_definitions(-DIVAN_VERSION="${PROJECT_VERSION}" -DUSE_SDL) option(BUILD_MAC_APP "Build standalone application for MacOS" OFF) option(USE_HOME_FOR_STATE_DIR "Statedir will be /.ivan/ in current user's homedir" OFF) option(WIZARD "Enable Wizard Mode" OFF) +option(PORTABLE_BUILD "Keep game and user data in the directory IVAN is launched from" OFF) if(UNIX) add_definitions(-DUNIX) + if(NOT PORTABLE_BUILD) include(GNUInstallDirs) if(BUILD_MAC_APP) @@ -37,6 +39,7 @@ if(UNIX) " please move them to \"$ENV{HOME}/.ivan\".") endif() endif() + endif() elseif(WIN32) install(DIRECTORY Graphics Script Music Sound DESTINATION "ivan") @@ -63,6 +66,10 @@ if(WIZARD) add_definitions(-DWIZARD) endif() +if(PORTABLE_BUILD) + add_definitions(-DPORTABLE_BUILD) +endif() + find_path(EXECINFO_INCLUDE_DIR NAMES execinfo.h) if(NOT EXECINFO_INCLUDE_DIR MATCHES "-NOTFOUND$") add_definitions(-DBACKTRACE) diff --git a/FeLib/Source/save.cpp b/FeLib/Source/save.cpp index 507c636b7..bde90def6 100644 --- a/FeLib/Source/save.cpp +++ b/FeLib/Source/save.cpp @@ -811,6 +811,9 @@ void MakePath(cfestring& Path) festring GetUserDataDir() { +#ifdef PORTABLE_BUILD + return "./"; +#else #ifdef UNIX festring Dir; #ifdef MAC_APP @@ -834,4 +837,5 @@ festring GetUserDataDir() #if defined(WIN32) || defined(__DJGPP__) return "./"; #endif +#endif } diff --git a/Main/Source/game.cpp b/Main/Source/game.cpp index 2b37ec797..79e4db8a5 100644 --- a/Main/Source/game.cpp +++ b/Main/Source/game.cpp @@ -5304,6 +5304,9 @@ inputfile& operator>>(inputfile& SaveFile, dangerid& Value) festring game::GetDataDir() { +#ifdef PORTABLE_BUILD + return "./"; +#else #ifdef UNIX #ifdef MAC_APP return "../Resources/data/"; @@ -5315,6 +5318,7 @@ festring game::GetDataDir() #if defined(WIN32) || defined(__DJGPP__) return GetUserDataDir(); #endif +#endif } festring game::GetSaveDir() From b0ce2d46c40a6c8ea008115bd7999e0be3610162 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sun, 21 Jun 2026 19:15:18 +0200 Subject: [PATCH 2/8] minor fixes unrelated to IVAN3D --- Main/Include/square.h | 2 +- Main/Include/trap.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Main/Include/square.h b/Main/Include/square.h index 3ad331e4d..38365b258 100644 --- a/Main/Include/square.h +++ b/Main/Include/square.h @@ -39,7 +39,7 @@ class square area* GetArea() const { return AreaUnder; } virtual gterrain* GetGTerrain() const = 0; virtual oterrain* GetOTerrain() const = 0; - festring GetMemorizedDescription() { return MemorizedDescription; } + festring GetMemorizedDescription() const { return MemorizedDescription; } void SetMemorizedDescription(cfestring& What) { MemorizedDescription = What; } virtual truth CanBeSeenByPlayer(truth = false) const = 0; virtual truth CanBeSeenFrom(v2, long, truth = false) const = 0; diff --git a/Main/Include/trap.h b/Main/Include/trap.h index 082f3fa50..711b66045 100644 --- a/Main/Include/trap.h +++ b/Main/Include/trap.h @@ -47,6 +47,7 @@ class itemtrapbase { public: itemtrapbase() : Active(false) { } + virtual ~itemtrapbase() { } void Save(outputfile&) const; void Load(inputfile&); void SetIsActive(truth); From be196376c18fcb0ed8d35fc2fba646ae653e70cc Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Tue, 23 Jun 2026 02:10:01 +0200 Subject: [PATCH 3/8] save compatibility between Windows x86_64-w64-mingw32 and Linux --- FeLib/Include/save.h | 33 +++++++++++++++++++++++++++++++++ FeLib/Source/femath.cpp | 12 ++++-------- Main/Source/bugworkaround.cpp | 2 +- Main/Source/cmdcraft.cpp | 2 +- Main/Source/lsquare.cpp | 6 ++---- 5 files changed, 41 insertions(+), 14 deletions(-) diff --git a/FeLib/Include/save.h b/FeLib/Include/save.h index f92fad191..de2cff4cc 100644 --- a/FeLib/Include/save.h +++ b/FeLib/Include/save.h @@ -229,8 +229,41 @@ inline inputfile& operator>>(inputfile& SaveFile, ushort& Value) return SaveFile; } +/* SAVE_COMPATIBILITY: + * make x86_64-w64-mingw32 saves compatible with Linux, + * by forcing the correct sizes. + * Note: This also lets us save 64-bit time_t values. + **/ + +#if SAVE_COMPATIBILITY +#include +RAW_SAVE_LOAD(int64_t) +RAW_SAVE_LOAD(uint64_t) + +inline outputfile& operator<<(outputfile& SaveFile, long Value) +{ + int64_t Value2 = Value; return SaveFile << Value2; +} + +inline inputfile& operator>>(inputfile& SaveFile, long& Value) +{ + int64_t Value2; SaveFile >> Value2; Value = Value2; return SaveFile; +} + +inline outputfile& operator<<(outputfile& SaveFile, ulong Value) +{ + uint64_t Value2 = Value; return SaveFile << Value2; +} + +inline inputfile& operator>>(inputfile& SaveFile, ulong& Value) +{ + uint64_t Value2; SaveFile >> Value2; Value = Value2; return SaveFile; +} + +#else RAW_SAVE_LOAD(long) RAW_SAVE_LOAD(ulong) +#endif RAW_SAVE_LOAD(int) RAW_SAVE_LOAD(uint) RAW_SAVE_LOAD(double) diff --git a/FeLib/Source/femath.cpp b/FeLib/Source/femath.cpp index 6a8310450..4c03355fb 100644 --- a/FeLib/Source/femath.cpp +++ b/FeLib/Source/femath.cpp @@ -315,26 +315,22 @@ void ReadData(region& R, inputfile& SaveFile) outputfile& operator<<(outputfile& SaveFile, const interval& I) { - SaveFile.Write(reinterpret_cast(&I), sizeof(I)); - return SaveFile; + return SaveFile << I.Min << I.Max; } inputfile& operator>>(inputfile& SaveFile, interval& I) { - SaveFile.Read(reinterpret_cast(&I), sizeof(I)); - return SaveFile; + return SaveFile >> I.Min >> I.Max; } outputfile& operator<<(outputfile& SaveFile, const region& R) { - SaveFile.Write(reinterpret_cast(&R), sizeof(R)); - return SaveFile; + return SaveFile << R.X << R.Y; } inputfile& operator>>(inputfile& SaveFile, region& R) { - SaveFile.Read(reinterpret_cast(&R), sizeof(R)); - return SaveFile; + return SaveFile >> R.X >> R.Y; } long femath::SumArray(const fearray& Vector) diff --git a/Main/Source/bugworkaround.cpp b/Main/Source/bugworkaround.cpp index 9dcf562f2..7dcf99751 100644 --- a/Main/Source/bugworkaround.cpp +++ b/Main/Source/bugworkaround.cpp @@ -428,7 +428,7 @@ character* bugfixdp::ValidatePlayerAt(square* sqr) if(vPF.size()>1){ // FIRST CHECK/FIX! festring fsMsg; - fsMsg << "Multiple player instances found (x" << vPF.size() << "), try to fix this?"; + fsMsg << "Multiple player instances found (x" << int(vPF.size()) << "), try to fix this?"; if(AlertConfirmFixMsg(fsMsg.CStr())) return BugWorkaroundDupPlayer(); /** diff --git a/Main/Source/cmdcraft.cpp b/Main/Source/cmdcraft.cpp index 7b2a5d040..9ca3ccac1 100644 --- a/Main/Source/cmdcraft.cpp +++ b/Main/Source/cmdcraft.cpp @@ -3062,7 +3062,7 @@ void updateCraftDesc(){ festring fsDesc=fsSkill; if(vSuspended.size()>0) - fsDesc<<" (Suspended Actions: "<(&Emitter), sizeof(Emitter)); - return SaveFile; + return SaveFile << Emitter.ID << Emitter.Emitation; } inputfile& operator>>(inputfile& SaveFile, emitter& Emitter) { - SaveFile.Read(reinterpret_cast(&Emitter), sizeof(Emitter)); - return SaveFile; + return SaveFile >> Emitter.ID >> Emitter.Emitation; } void lsquare::AddItem(item* Item) From d8ec3fef2862c474010cfb55b220d0891c3847ed Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Tue, 23 Jun 2026 02:10:11 +0200 Subject: [PATCH 4/8] guards added to libxbrzscale.h --- xbrzscale/libxbrzscale.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xbrzscale/libxbrzscale.h b/xbrzscale/libxbrzscale.h index 64aeb4179..e2442f819 100644 --- a/xbrzscale/libxbrzscale.h +++ b/xbrzscale/libxbrzscale.h @@ -16,6 +16,9 @@ * along with this program. If not, see . */ +#ifndef _XRBZSCALE_ +#define _XRBZSCALE_ + #ifndef XBRZLIB_RELATIVEPATHSDL #include #else @@ -49,3 +52,4 @@ class libxbrzscale static bool bFreeInputSurfaceAfterScale; static bool bFreeOutputSurfaceAfterScale; }; +#endif \ No newline at end of file From 608bdd46950581679ca147318efa220af6c55de5 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Mon, 29 Jun 2026 03:44:15 +0200 Subject: [PATCH 5/8] PORTABLE_BUILD now also uniformizes the highscore filename --- FeLib/Include/hscore.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/FeLib/Include/hscore.h b/FeLib/Include/hscore.h index dc2e3072f..586bfb976 100644 --- a/FeLib/Include/hscore.h +++ b/FeLib/Include/hscore.h @@ -18,6 +18,10 @@ #include "festring.h" +#ifdef PORTABLE_BUILD +#define HIGH_SCORE_FILENAME "ivan-highscore.scores" +#else + #ifdef UNIX #define HIGH_SCORE_FILENAME "ivan-highscore.scores" #endif @@ -25,6 +29,7 @@ #if defined(WIN32) || defined(__DJGPP__) #define HIGH_SCORE_FILENAME "HScore.dat" #endif +#endif class festring; From cdd99c67e408c8c6a6d50a509c28eeed4bfa8ecf Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Mon, 6 Jul 2026 13:56:27 +0200 Subject: [PATCH 6/8] fix the bug with REFS being used as ulong while being allocated as int* --- FeLib/Include/fearray.h | 4 ++-- FeLib/Source/festring.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/FeLib/Include/fearray.h b/FeLib/Include/fearray.h index a68072efd..c01862176 100644 --- a/FeLib/Include/fearray.h +++ b/FeLib/Include/fearray.h @@ -45,9 +45,9 @@ template inline fearray::fearray(const type* Array, sizetype Size) : Size(Size) { - char* Ptr = new char[Size * sizeof(type) + sizeof(int*)]; + char* Ptr = new char[Size * sizeof(type) + sizeof(ulong)]; *reinterpret_cast(Ptr) = 0; - Data = reinterpret_cast(Ptr + sizeof(int*)); + Data = reinterpret_cast(Ptr + sizeof(ulong)); for(sizetype c = 0; c < Size; ++c) new(&Data[c]) type(Array[c]); diff --git a/FeLib/Source/festring.cpp b/FeLib/Source/festring.cpp index 6d26138ce..9c7df0bc4 100644 --- a/FeLib/Source/festring.cpp +++ b/FeLib/Source/festring.cpp @@ -884,7 +884,7 @@ long festring::GetCheckSum() const void festring::CreateNewData(sizetype N) { Reserved = N|FESTRING_PAGE; - Data = sizeof(int*) + new char[Reserved + sizeof(int*) + 1]; + Data = sizeof(ulong) + new char[Reserved + sizeof(ulong) + 1]; OwnsData = true; REFS(Data) = 0; Size = 0; From 02d7a1a1e2688db503ed200ba245ea28d7708367 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Mon, 6 Jul 2026 15:59:18 +0200 Subject: [PATCH 7/8] compilation option USE_OPENDIR to force using Unix standard opendir/readdir/closedir instead of their Windows native equivalents --- FeLib/Source/feio.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/FeLib/Source/feio.cpp b/FeLib/Source/feio.cpp index be34ae64e..2f5cec7f8 100644 --- a/FeLib/Source/feio.cpp +++ b/FeLib/Source/feio.cpp @@ -22,13 +22,22 @@ #include #include +#if defined(UNIX) || defined(USE_OPENDIR) +#include +#else + #ifdef WIN32 #define stat _stat #include #endif +#ifdef __DJGPP__ +#include +#endif + +#endif + #ifdef UNIX -#include #include #include #include @@ -37,9 +46,6 @@ #include #endif -#ifdef __DJGPP__ -#include -#endif #include "bitmap.h" #include "error.h" @@ -1044,7 +1050,7 @@ festring iosystem::ContinueMenu(col16 TopicColor, col16 ListColor, felist List(CONST_S("Choose a file and be sorry:"), TopicColor); ////////////////////////// OS SPECIFIC!!! collect all files at save folder. ////////////////////////// -#ifdef UNIX +#if defined(UNIX) || defined(USE_OPENDIR) { DIR* dp; struct dirent* ep; @@ -1091,6 +1097,7 @@ festring iosystem::ContinueMenu(col16 TopicColor, col16 ListColor, Check = findnext(&Found); } } +#endif #endif if(vFiles.size()==0){ From 1fd1c072b182e2b612f980955278f891db3058d8 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sat, 11 Jul 2026 00:45:30 +0200 Subject: [PATCH 8/8] fixup to opendir --- FeLib/Source/feio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FeLib/Source/feio.cpp b/FeLib/Source/feio.cpp index 2f5cec7f8..070cca9d9 100644 --- a/FeLib/Source/feio.cpp +++ b/FeLib/Source/feio.cpp @@ -1061,7 +1061,7 @@ festring iosystem::ContinueMenu(col16 TopicColor, col16 ListColor, closedir(dp); } } -#endif +#else #ifdef WIN32 struct _finddata_t Found;