aboutsummaryrefslogtreecommitdiff
path: root/libs/bsatk/src/filehash.cpp
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-02-11 02:37:39 -0600
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-02-11 02:37:39 -0600
commit7ee008e150bc5bcf76082d726f719ee0fdfda982 (patch)
tree27fb39be241fdb5ac2734c574de678977d1856d0 /libs/bsatk/src/filehash.cpp
Fluorine Manager: full Linux port of Mod Organizer 2
Complete native Linux port with FUSE-based virtual filesystem, Proton/umu-run integration, and Flatpak packaging. Key features: - FUSE VFS replacing Windows USVFS (in-process + standalone helper for Flatpak) - Proton/GE-Proton/umu-run launcher with env var forwarding - Flatpak support (sandbox-aware VFS, NXM handler, umu-run) - Wine prefix management UI - Case-insensitive path resolution for Linux filesystems - QSettings-safe INI handling (avoids Bethesda INI corruption) - Portable instance support with auto-generated launcher scripts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'libs/bsatk/src/filehash.cpp')
-rw-r--r--libs/bsatk/src/filehash.cpp100
1 files changed, 100 insertions, 0 deletions
diff --git a/libs/bsatk/src/filehash.cpp b/libs/bsatk/src/filehash.cpp
new file mode 100644
index 0000000..717a02c
--- /dev/null
+++ b/libs/bsatk/src/filehash.cpp
@@ -0,0 +1,100 @@
+/*
+Mod Organizer BSA handling
+
+Copyright (C) 2012 Sebastian Herbord. All rights reserved.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "filehash.h"
+
+#include <algorithm>
+#include <climits>
+#include <cstdlib>
+#include <cstring>
+
+#ifndef MAX_PATH
+#define MAX_PATH PATH_MAX
+#endif // MAX_PATH
+
+static unsigned long genHashInt(const unsigned char* pos, const unsigned char* end)
+{
+ unsigned long hash = 0;
+ for (; pos < end; ++pos) {
+ hash *= 0x1003f;
+ hash += *pos;
+ }
+ return hash;
+}
+
+/**
+ * @brief calculateBSAHash
+ * @param fileName
+ * @return
+ * @note the hash calculated for folders seem to be wrong
+ */
+BSAHash calculateBSAHash(const std::string& fileName)
+{
+ char fileNameLower[FILENAME_MAX + 1];
+ int i = 0;
+ for (; i < FILENAME_MAX && fileName[i] != '\0'; ++i) {
+ fileNameLower[i] = tolower(fileName[i]);
+ if (fileNameLower[i] == '/') {
+ fileNameLower[i] = '\\';
+ }
+ }
+ fileNameLower[i] = '\0';
+
+ unsigned char* fileNameLowerU = reinterpret_cast<unsigned char*>(fileNameLower);
+
+ size_t length = strlen(fileNameLower);
+
+ char* ext = strrchr(fileNameLower, '.');
+ if (ext == nullptr) {
+ ext = fileNameLower + length;
+ }
+
+ size_t extLen = strlen(ext);
+ length -= extLen;
+
+ unsigned char* extU = reinterpret_cast<unsigned char*>(ext);
+
+ BSAHash hash1 = 0ULL;
+
+ if (length > 0) {
+ hash1 = static_cast<BSAHash>(fileNameLowerU[length - 1] |
+ ((length > 2 ? fileNameLowerU[length - 2] : 0) << 8) |
+ (length << 16) | (fileNameLowerU[0] << 24));
+ }
+
+ if (extLen > 0) {
+ if (strcmp(ext + 1, "kf") == 0) {
+ hash1 |= 0x80;
+ } else if (strcmp(ext + 1, "nif") == 0) {
+ hash1 |= 0x8000;
+ } else if (strcmp(ext + 1, "dds") == 0) {
+ hash1 |= 0x8080;
+ } else if (strcmp(ext + 1, "wav") == 0) {
+ hash1 |= 0x80000000;
+ }
+
+ BSAHash hash2 = static_cast<BSAHash>(genHashInt(fileNameLowerU + 1, extU - 2)) +
+ static_cast<BSAHash>(genHashInt(extU, extU + strlen(ext)));
+
+ hash1 |= (hash2 & 0xFFFFFFFF) << 32;
+ }
+
+ return hash1;
+}