aboutsummaryrefslogtreecommitdiff
path: root/libs/esptk/include
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/esptk/include
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/esptk/include')
-rw-r--r--libs/esptk/include/esptk/espexceptions.h23
-rw-r--r--libs/esptk/include/esptk/espfile.h72
-rw-r--r--libs/esptk/include/esptk/esptypes.h20
-rw-r--r--libs/esptk/include/esptk/record.h60
-rw-r--r--libs/esptk/include/esptk/subrecord.h44
-rw-r--r--libs/esptk/include/esptk/tes3record.h32
-rw-r--r--libs/esptk/include/esptk/tes3subrecord.h42
7 files changed, 293 insertions, 0 deletions
diff --git a/libs/esptk/include/esptk/espexceptions.h b/libs/esptk/include/esptk/espexceptions.h
new file mode 100644
index 0000000..9830ed6
--- /dev/null
+++ b/libs/esptk/include/esptk/espexceptions.h
@@ -0,0 +1,23 @@
+#ifndef ESPEXCEPTIONS_H
+#define ESPEXCEPTIONS_H
+
+#include <stdexcept>
+
+namespace ESP
+{
+
+class InvalidRecordException : public std::runtime_error
+{
+public:
+ InvalidRecordException(const std::string& message) : std::runtime_error(message) {}
+};
+
+class InvalidFileException : public std::runtime_error
+{
+public:
+ InvalidFileException(const std::string& message) : std::runtime_error(message) {}
+};
+
+} // namespace ESP
+
+#endif // ESPEXCEPTIONS_H
diff --git a/libs/esptk/include/esptk/espfile.h b/libs/esptk/include/esptk/espfile.h
new file mode 100644
index 0000000..04be76e
--- /dev/null
+++ b/libs/esptk/include/esptk/espfile.h
@@ -0,0 +1,72 @@
+#ifndef ESPFILE_H
+#define ESPFILE_H
+
+#include "record.h"
+#include "tes3record.h"
+#include <fstream>
+#include <set>
+#include <string>
+
+namespace ESP
+{
+
+class SubRecord;
+
+class File
+{
+public:
+ File(const std::string& fileName);
+ File(const std::wstring& fileName);
+
+ Record readRecord();
+
+ bool isMaster() const;
+ bool isLight(bool overlaySupport = false) const;
+ bool isMedium() const;
+ bool isOverlay() const;
+ bool isBlueprint() const;
+ bool isDummy() const;
+ uint16_t formVersion() const { return m_MainRecord.formVersion(); };
+ float headerVersion() const { return m_Header.version; }
+ std::string author() const { return m_Author; }
+ std::string description() const { return m_Description; }
+ std::set<std::string> masters() const { return m_Masters; }
+
+private:
+ void init();
+
+ void onHEDR(const SubRecord& rec);
+ void onMAST(const SubRecord& rec);
+ void onCNAM(const SubRecord& rec);
+ void onSNAM(const SubRecord& rec);
+
+private:
+ std::ifstream m_File;
+
+ struct
+ {
+ float version;
+ int32_t numRecords;
+ uint32_t nextObjectId;
+ } m_Header;
+
+ struct
+ {
+ float version;
+ uint32_t unknown;
+ char author[32];
+ char description[256];
+ uint32_t numRecords;
+ } m_TES3Header;
+
+ Record m_MainRecord;
+
+ std::string m_Author;
+ std::string m_Description;
+
+ std::set<std::string> m_Masters;
+};
+
+} // namespace ESP
+
+#endif // ESPFILE_H
diff --git a/libs/esptk/include/esptk/esptypes.h b/libs/esptk/include/esptk/esptypes.h
new file mode 100644
index 0000000..135dde1
--- /dev/null
+++ b/libs/esptk/include/esptk/esptypes.h
@@ -0,0 +1,20 @@
+#ifndef ESPTYPES_H
+#define ESPTYPES_H
+
+#include <cstring>
+#include <istream>
+
+template <typename T>
+static T readType(std::istream& stream)
+{
+ union
+ {
+ char buffer[sizeof(T)];
+ T value;
+ };
+ memset(buffer, 0x42, sizeof(T));
+ stream.read(buffer, sizeof(T));
+ return value;
+}
+
+#endif // ESPTYPES_H
diff --git a/libs/esptk/include/esptk/record.h b/libs/esptk/include/esptk/record.h
new file mode 100644
index 0000000..3a2c996
--- /dev/null
+++ b/libs/esptk/include/esptk/record.h
@@ -0,0 +1,60 @@
+#ifndef RECORD_H
+#define RECORD_H
+
+#include <cstdint>
+#include <istream>
+#include <vector>
+
+namespace ESP
+{
+
+/**
+ * @brief record storage class without record-specific information
+ */
+class Record
+{
+public:
+ enum EFlag
+ {
+ FLAG_MASTER = 0x00000001,
+ FLAG_LIGHT_ALTERNATE = 0x00000100, // SF light flag (FE/FF memory space)
+ FLAG_LIGHT = 0x00000200, // SSE & FO4 light flag (FE/FF memory space)
+ FLAG_OVERLAY = 0x00000200, // SF overlay flag (does not claim new memory space,
+ // overrules light flag)
+ FLAG_MEDIUM = 0x00000400, // SF Creation update, indicates medium plugin type (FD
+ // memory space)
+ FLAG_BLUEPRINT =
+ 0x0000800, // SF blueprint flag (force loads after all other plugins)
+ FLAG_COMPRESSED = 0x00040000
+ };
+
+public:
+ Record();
+
+ bool readFrom(std::istream& stream);
+
+ bool flagSet(EFlag flag) const;
+
+ uint16_t formVersion() const { return m_FormVersion; }
+
+ const std::vector<uint8_t>& data() const { return m_Data; }
+
+private:
+ struct Header
+ {
+ char type[4];
+ uint32_t dataSize;
+ uint32_t flags;
+ uint32_t id;
+ uint32_t revision;
+ } m_Header;
+
+ uint16_t m_FormVersion;
+ std::vector<uint8_t> m_Data;
+
+ bool m_OblivionStyle;
+};
+
+} // namespace ESP
+
+#endif // RECORD_H
diff --git a/libs/esptk/include/esptk/subrecord.h b/libs/esptk/include/esptk/subrecord.h
new file mode 100644
index 0000000..f9eb36c
--- /dev/null
+++ b/libs/esptk/include/esptk/subrecord.h
@@ -0,0 +1,44 @@
+#ifndef SUBRECORD_H
+#define SUBRECORD_H
+
+#include <cstdint>
+#include <istream>
+#include <vector>
+
+namespace ESP
+{
+
+/**
+ * @brief sub-record storage class without record-specific information
+ */
+class SubRecord
+{
+public:
+ enum EType
+ {
+ TYPE_UNKNOWN,
+ TYPE_HEDR,
+ TYPE_CNAM,
+ TYPE_SNAM,
+ TYPE_MAST,
+ TYPE_ONAM
+ };
+
+ static const int NUM_TYPES = TYPE_ONAM;
+
+public:
+ SubRecord();
+
+ bool readFrom(std::istream& stream, uint32_t sizeOverride = 0UL);
+
+ EType type() const { return m_Type; }
+ const std::vector<uint8_t>& data() const { return m_Data; }
+
+private:
+ EType m_Type;
+ std::vector<uint8_t> m_Data;
+};
+
+} // namespace ESP
+
+#endif // SUBRECORD_H
diff --git a/libs/esptk/include/esptk/tes3record.h b/libs/esptk/include/esptk/tes3record.h
new file mode 100644
index 0000000..19fa040
--- /dev/null
+++ b/libs/esptk/include/esptk/tes3record.h
@@ -0,0 +1,32 @@
+#ifndef TES3_RECORD_H
+#define TES3_RECORD_H
+
+#include <cstdint>
+#include <istream>
+#include <vector>
+
+namespace ESP
+{
+
+/**
+ * @brief record storage class without record-specific information
+ */
+class TES3Record
+{
+public:
+ TES3Record();
+
+ bool readFrom(std::istream& stream);
+
+private:
+ struct Header
+ {
+ char type[4];
+ float version;
+ long unknown;
+ } m_Header;
+};
+
+} // namespace ESP
+
+#endif // TES3_RECORD_H
diff --git a/libs/esptk/include/esptk/tes3subrecord.h b/libs/esptk/include/esptk/tes3subrecord.h
new file mode 100644
index 0000000..966afcb
--- /dev/null
+++ b/libs/esptk/include/esptk/tes3subrecord.h
@@ -0,0 +1,42 @@
+#ifndef TES3_SUBRECORD_H
+#define TES3_SUBRECORD_H
+
+#include <cstdint>
+#include <istream>
+#include <vector>
+
+namespace ESP
+{
+
+/**
+ * @brief sub-record storage class without record-specific information
+ */
+class TES3SubRecord
+{
+public:
+ enum EType
+ {
+ TYPE_UNKNOWN,
+ TYPE_HEDR,
+ TYPE_MAST,
+ TYPE_DATA
+ };
+
+ static const int NUM_TYPES = TYPE_DATA;
+
+public:
+ TES3SubRecord();
+
+ bool readFrom(std::istream& stream, uint32_t sizeOverride = 0UL);
+
+ EType type() const { return m_Type; }
+ const std::vector<uint8_t>& data() const { return m_Data; }
+
+private:
+ EType m_Type;
+ std::vector<uint8_t> m_Data;
+};
+
+} // namespace ESP
+
+#endif // TES3_SUBRECORD_H