mirror of
https://anongit.gentoo.org/git/repo/gentoo.git
synced 2025-12-21 02:42:18 +00:00
226 lines
7.8 KiB
Diff
226 lines
7.8 KiB
Diff
diff --git a/README.md b/README.md
|
||
index fe466e50..e91dd4ed 100644
|
||
--- a/README.md
|
||
+++ b/README.md
|
||
@@ -46,7 +46,7 @@ Jazz² Resurrection is reimplementation of the game **Jazz Jackrabbit 2** releas
|
||
* Install dependencies: `sudo apt install libglew2.2 libglfw3 libsdl2-2.0-0 libopenal1 libvorbisfile3 libopenmpt0`
|
||
* Alternatively, install provided `.deb` or `.rpm` package and dependencies should be installed automatically
|
||
* Copy contents of original *Jazz Jackrabbit 2* directory to `‹Game›/Source/`
|
||
- * If packages are used, the files must be copied to `~/.local/share/Jazz² Resurrection/Source/` instead
|
||
+ * If packages are used, the files must be copied to `~/.local/share/Jazz² Resurrection/Source/` or `/usr/local/share/Jazz² Resurrection/Source/` instead, please follow instructions of specific package
|
||
* Run `‹Game›/jazz2` or `‹Game›/jazz2_sdl2` application
|
||
* If packages are used, the game should be visible in application list
|
||
|
||
diff --git a/Sources/Common.h b/Sources/Common.h
|
||
index 865d42bb..cf6f112c 100644
|
||
--- a/Sources/Common.h
|
||
+++ b/Sources/Common.h
|
||
@@ -33,6 +33,10 @@
|
||
|
||
#include <stdlib.h>
|
||
|
||
+#if !defined(NCINE_INSTALL_PREFIX) && defined(DEATH_TARGET_UNIX)
|
||
+# define NCINE_INSTALL_PREFIX "/usr/local"
|
||
+#endif
|
||
+
|
||
// Check platform-specific capabilities
|
||
#if defined(WITH_SDL) || defined(DEATH_TARGET_WINDOWS_RT)
|
||
# define NCINE_HAS_GAMEPAD_RUMBLE
|
||
diff --git a/Sources/Jazz2/ContentResolver.cpp b/Sources/Jazz2/ContentResolver.cpp
|
||
index 737582db..a7c5d460 100644
|
||
--- a/Sources/Jazz2/ContentResolver.cpp
|
||
+++ b/Sources/Jazz2/ContentResolver.cpp
|
||
@@ -207,7 +207,7 @@ namespace Jazz2
|
||
# elif defined(NCINE_OVERRIDE_CONTENT_PATH)
|
||
_contentPath = NCINE_OVERRIDE_CONTENT_PATH;
|
||
# else
|
||
- _contentPath = "/usr/share/" NCINE_LINUX_PACKAGE "/Content/";
|
||
+ _contentPath = NCINE_INSTALL_PREFIX "/share/" NCINE_LINUX_PACKAGE "/Content/";
|
||
# endif
|
||
# if defined(NCINE_PACKAGED_CONTENT_PATH)
|
||
// If Content is packaged with binaries, always use standard XDG paths for everything else
|
||
@@ -226,18 +226,25 @@ namespace Jazz2
|
||
auto localStorage = fs::GetLocalStorage();
|
||
if (!localStorage.empty()) {
|
||
// Use "$XDG_DATA_HOME/Jazz² Resurrection/" if exists (for backward compatibility), otherwise "$XDG_DATA_HOME/{NCINE_LINUX_PACKAGE}/"
|
||
- _sourcePath = fs::CombinePath(localStorage, "Jazz² Resurrection/Source/"_s);
|
||
- if (fs::DirectoryExists(_sourcePath)) {
|
||
- _cachePath = fs::CombinePath(localStorage, "Jazz² Resurrection/Cache/"_s);
|
||
- } else {
|
||
+ _cachePath = fs::CombinePath(localStorage, "Jazz² Resurrection/Cache/"_s);
|
||
+ if (!fs::DirectoryExists(_cachePath)) {
|
||
auto appData = fs::CombinePath(localStorage, NCINE_LINUX_PACKAGE);
|
||
- _sourcePath = fs::CombinePath(appData, "Source/"_s);
|
||
_cachePath = fs::CombinePath(appData, "Cache/"_s);
|
||
}
|
||
} else {
|
||
- _sourcePath = "Source/"_s;
|
||
_cachePath = "Cache/"_s;
|
||
}
|
||
+
|
||
+ // Prefer system-wide Source only if it exists and local one doesn't exist
|
||
+ _sourcePath = fs::CombinePath(fs::GetDirectoryName(_cachePath), "Source/"_s);
|
||
+ if (!fs::FindPathCaseInsensitive(fs::CombinePath(_sourcePath, "Anims.j2a"_s)) &&
|
||
+ !fs::FindPathCaseInsensitive(fs::CombinePath(_sourcePath, "AnimsSw.j2a"_s))) {
|
||
+ auto systemWideSource = NCINE_INSTALL_PREFIX "/share/" NCINE_LINUX_PACKAGE "/Source/";
|
||
+ if (fs::FindPathCaseInsensitive(fs::CombinePath(systemWideSource, "Anims.j2a"_s)) ||
|
||
+ fs::FindPathCaseInsensitive(fs::CombinePath(systemWideSource, "AnimsSw.j2a"_s))) {
|
||
+ _sourcePath = systemWideSource;
|
||
+ }
|
||
+ }
|
||
} else {
|
||
// Fallback to relative paths
|
||
_contentPath = "Content/"_s;
|
||
diff --git a/Sources/Shared/IO/FileSystem.cpp b/Sources/Shared/IO/FileSystem.cpp
|
||
index 5b5199b0..0d4850bd 100644
|
||
--- a/Sources/Shared/IO/FileSystem.cpp
|
||
+++ b/Sources/Shared/IO/FileSystem.cpp
|
||
@@ -701,73 +701,91 @@ namespace Death { namespace IO {
|
||
#if !defined(DEATH_TARGET_WINDOWS) && !defined(DEATH_TARGET_SWITCH)
|
||
String FileSystem::FindPathCaseInsensitive(const StringView path)
|
||
{
|
||
- if (Exists(path)) {
|
||
+ if (path.empty() || Exists(path)) {
|
||
return path;
|
||
}
|
||
|
||
- std::size_t l = path.size();
|
||
- char* p = (char*)alloca(l + 1);
|
||
- strncpy(p, path.data(), l);
|
||
- p[l] = '\0';
|
||
- std::size_t rl = 0;
|
||
- bool isAbsolute = (p[0] == '/' || p[0] == '\\');
|
||
+ DIR* d = nullptr;
|
||
+ String result = path;
|
||
+ MutableStringView partialResult = result;
|
||
+ char* nextPartBegin;
|
||
|
||
- String result(NoInit, path.size() + (isAbsolute ? 0 : 2));
|
||
+ while (MutableStringView separator = partialResult.findLast('/')) {
|
||
+ if DEATH_UNLIKELY(separator.begin() == result.begin()) {
|
||
+ // Nothing left, only first slash of absolute path
|
||
+ break;
|
||
+ }
|
||
|
||
- DIR* d;
|
||
- if (isAbsolute) {
|
||
- d = ::opendir("/");
|
||
- p = p + 1;
|
||
- } else {
|
||
- d = ::opendir(".");
|
||
- result[0] = '.';
|
||
- result[1] = '\0';
|
||
- rl = 1;
|
||
+ partialResult = partialResult.prefix(separator.begin());
|
||
+ separator[0] = '\0';
|
||
+ d = ::opendir(result.data());
|
||
+ separator[0] = '/';
|
||
+ if (d != nullptr) {
|
||
+ nextPartBegin = separator.end();
|
||
+ break;
|
||
+ }
|
||
}
|
||
|
||
- bool last = false;
|
||
- char* c = strsep(&p, "/");
|
||
- while (c) {
|
||
- if (d == nullptr) {
|
||
- return {};
|
||
+ if (d == nullptr) {
|
||
+ if (result[0] == '/' || result[0] == '\\') {
|
||
+ d = ::opendir("/");
|
||
+ nextPartBegin = result.begin() + 1;
|
||
+ } else {
|
||
+ d = ::opendir(".");
|
||
+ nextPartBegin = result.begin();
|
||
}
|
||
|
||
- if (last) {
|
||
- ::closedir(d);
|
||
+ if DEATH_UNLIKELY(d == nullptr) {
|
||
return {};
|
||
}
|
||
+ }
|
||
+
|
||
+ while (true) {
|
||
+ partialResult = result.suffix(nextPartBegin);
|
||
+ MutableStringView nextSeparator = partialResult.findOr('/', result.end());
|
||
+ if DEATH_UNLIKELY(nextSeparator.begin() == nextPartBegin) {
|
||
+ // Skip empty parts
|
||
+ nextPartBegin = nextSeparator.end();
|
||
+ continue;
|
||
+ }
|
||
|
||
- result[rl] = '/';
|
||
- rl += 1;
|
||
- result[rl] = '\0';
|
||
+ bool hasNextSeparator = (nextSeparator.begin() != result.end());
|
||
+ if DEATH_LIKELY(hasNextSeparator) {
|
||
+ nextSeparator[0] = '\0';
|
||
+ }
|
||
|
||
struct dirent* entry = ::readdir(d);
|
||
while (entry != nullptr) {
|
||
- if (::strcasecmp(c, entry->d_name) == 0) {
|
||
- strcpy(&result[rl], entry->d_name);
|
||
- rl += strlen(entry->d_name);
|
||
-
|
||
+ if (::strcasecmp(partialResult.begin(), entry->d_name) == 0) {
|
||
+ std::size_t fileNameLength = std::strlen(entry->d_name);
|
||
+ DEATH_DEBUG_ASSERT(partialResult.begin() + fileNameLength == nextSeparator.begin());
|
||
+ std::memcpy(partialResult.begin(), entry->d_name, fileNameLength);
|
||
::closedir(d);
|
||
+
|
||
+ nextPartBegin = nextSeparator.end();
|
||
+ if (!hasNextSeparator || nextPartBegin == result.end()) {
|
||
+ if (hasNextSeparator) {
|
||
+ nextSeparator[0] = '/';
|
||
+ }
|
||
+ return result;
|
||
+ }
|
||
+
|
||
d = ::opendir(result.data());
|
||
+ if DEATH_UNLIKELY(d == nullptr) {
|
||
+ return {};
|
||
+ }
|
||
+ nextSeparator[0] = '/';
|
||
break;
|
||
}
|
||
|
||
entry = ::readdir(d);
|
||
}
|
||
|
||
- if (entry == nullptr) {
|
||
- strcpy(&result[rl], c);
|
||
- rl += strlen(c);
|
||
- last = true;
|
||
+ if DEATH_UNLIKELY(entry == nullptr) {
|
||
+ ::closedir(d);
|
||
+ return {};
|
||
}
|
||
-
|
||
- c = strsep(&p, "/");
|
||
}
|
||
-
|
||
- if (d != nullptr) {
|
||
- ::closedir(d);
|
||
- }
|
||
- return result;
|
||
}
|
||
#endif
|
||
|
||
diff --git a/cmake/ncine_compiler_options.cmake b/cmake/ncine_compiler_options.cmake
|
||
index 9ca461ad..6d981fdc 100644
|
||
--- a/cmake/ncine_compiler_options.cmake
|
||
+++ b/cmake/ncine_compiler_options.cmake
|
||
@@ -10,6 +10,10 @@ target_compile_definitions(${NCINE_APP} PUBLIC "NCINE_VERSION=\"${NCINE_VERSION}
|
||
string(TIMESTAMP NCINE_BUILD_YEAR "%Y")
|
||
target_compile_definitions(${NCINE_APP} PUBLIC "NCINE_BUILD_YEAR=\"${NCINE_BUILD_YEAR}\"")
|
||
|
||
+if(UNIX)
|
||
+ target_compile_definitions(${NCINE_APP} PUBLIC "NCINE_INSTALL_PREFIX=\"${CMAKE_INSTALL_PREFIX}\"")
|
||
+endif()
|
||
+
|
||
if(NCINE_OVERRIDE_CONTENT_PATH)
|
||
message(STATUS "Using overriden `Content` path: ${NCINE_OVERRIDE_CONTENT_PATH}")
|
||
target_compile_definitions(${NCINE_APP} PUBLIC "NCINE_OVERRIDE_CONTENT_PATH=\"${NCINE_OVERRIDE_CONTENT_PATH}\"")
|