Created
February 17, 2024 20:23
-
-
Save JohnnyonFlame/525468ffd197a67d068fa18f165c35d9 to your computer and use it in GitHub Desktop.
VVVVVV mmaped music.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/desktop_version/CMakeLists.txt b/desktop_version/CMakeLists.txt | |
index 9e60db8b..4d522961 100644 | |
--- a/desktop_version/CMakeLists.txt | |
+++ b/desktop_version/CMakeLists.txt | |
@@ -22,7 +22,7 @@ if(OFFICIAL_BUILD AND NOT MAKEANDPLAY) | |
endif() | |
option(REMOVE_ABSOLUTE_PATHS "If supported by the compiler, replace all absolute paths to source directories compiled into the binary (if any) with relative paths" ON) | |
- | |
+option(USE_MMAP "Use memory mapped blobs where possible, lowering physical memory requirements." OFF) | |
# Architecture Flags | |
if(APPLE) | |
@@ -396,6 +396,10 @@ if(REMOVE_ABSOLUTE_PATHS) | |
endif() | |
endif() | |
+if(USE_MMAP) | |
+ message(STATUS "Using memory mapped blobs") | |
+ target_compile_definitions(VVVVVV PRIVATE -DUSE_MMAP=1) | |
+endif() | |
target_compile_options(VVVVVV PRIVATE ${GLOBAL_COMPILE_FLAGS}) | |
diff --git a/desktop_version/src/BinaryBlob.cpp b/desktop_version/src/BinaryBlob.cpp | |
index 62d99f19..996328a3 100644 | |
--- a/desktop_version/src/BinaryBlob.cpp | |
+++ b/desktop_version/src/BinaryBlob.cpp | |
@@ -18,6 +18,10 @@ binaryBlob::binaryBlob(void) | |
#endif | |
SDL_zeroa(m_headers); | |
SDL_zeroa(m_memblocks); | |
+#ifdef USE_MMAP | |
+ m_mmap = MAP_FAILED; | |
+ m_fd = -1; | |
+#endif | |
} | |
#ifdef VVV_COMPILEMUSIC | |
@@ -83,20 +87,41 @@ void binaryBlob::writeBinaryBlob(const char* _name) | |
bool binaryBlob::unPackBinary(const char* name) | |
{ | |
- return FILESYSTEM_loadBinaryBlob(this, name); | |
+ if (FILESYSTEM_mapBinaryBlob(this, name)) | |
+ return true; | |
+ if (FILESYSTEM_loadBinaryBlob(this, name)) | |
+ return true; | |
+ | |
+ vlog_error("%s: Failed to read blob", name); | |
+ return false; | |
} | |
void binaryBlob::clear(void) | |
{ | |
- for (size_t i = 0; i < SDL_arraysize(m_headers); i += 1) | |
+#ifdef USE_MMAP | |
+ if (m_fd >= 0) | |
{ | |
- if (m_memblocks[i] != NULL) | |
+ munmap(m_mmap, m_mapsz); | |
+ close(m_fd); | |
+ m_mmap = MAP_FAILED; | |
+ m_mapsz = 0; | |
+ m_fd = -1; | |
+ SDL_zeroa(m_memblocks); | |
+ SDL_zeroa(m_headers); | |
+ } | |
+ else | |
+#endif //USE_MMAP | |
+ { | |
+ for (size_t i = 0; i < SDL_arraysize(m_headers); i += 1) | |
{ | |
- VVV_free(m_memblocks[i]); | |
+ if (m_memblocks[i] != NULL) | |
+ { | |
+ VVV_free(m_memblocks[i]); | |
+ } | |
} | |
+ SDL_zeroa(m_memblocks); | |
+ SDL_zeroa(m_headers); | |
} | |
- SDL_zeroa(m_memblocks); | |
- SDL_zeroa(m_headers); | |
} | |
int binaryBlob::getIndex(const char* _name) | |
diff --git a/desktop_version/src/BinaryBlob.h b/desktop_version/src/BinaryBlob.h | |
index f8089930..ea4c95d2 100644 | |
--- a/desktop_version/src/BinaryBlob.h | |
+++ b/desktop_version/src/BinaryBlob.h | |
@@ -1,6 +1,13 @@ | |
#ifndef BINARYBLOB_H | |
#define BINARYBLOB_H | |
+#ifdef USE_MMAP | |
+#include <sys/types.h> | |
+#include <sys/stat.h> | |
+#include <sys/mman.h> | |
+#include <fcntl.h> | |
+#include <unistd.h> | |
+#endif //USE_MMAP | |
#include <stddef.h> | |
#include <stdint.h> | |
@@ -63,6 +70,11 @@ public: | |
#endif | |
resourceheader m_headers[max_headers]; | |
char* m_memblocks[max_headers]; | |
+#ifdef USE_MMAP | |
+ void *m_mmap; | |
+ long long unsigned m_mapsz; | |
+ int m_fd; | |
+#endif //USE_MMAP | |
}; | |
diff --git a/desktop_version/src/FileSystemUtils.cpp b/desktop_version/src/FileSystemUtils.cpp | |
index 5643182d..83fe6047 100644 | |
--- a/desktop_version/src/FileSystemUtils.cpp | |
+++ b/desktop_version/src/FileSystemUtils.cpp | |
@@ -1071,6 +1071,88 @@ fail: | |
return true; | |
} | |
+#ifdef USE_MMAP | |
+bool FILESYSTEM_mapBinaryBlob(binaryBlob *blob, const char *filename) | |
+{ | |
+ int valid = 0; | |
+ uintptr_t offset = 0; | |
+ const char *fs_realdir; | |
+ char fs_path[MAX_PATH]; | |
+ struct stat s_stat; | |
+ | |
+ fs_realdir = PHYSFS_getRealDir(filename); | |
+ if (fs_realdir == NULL) | |
+ { | |
+ vlog_warn("%s: Unable to find file", filename); | |
+ return false; | |
+ } | |
+ snprintf(fs_path, sizeof(fs_path)-1, "%s%s%s", fs_realdir, pathSep, filename); | |
+ | |
+ blob->m_fd = open(fs_path, O_RDONLY); | |
+ if (blob->m_fd < 0) | |
+ { | |
+ vlog_warn("%s: Unable to open file", fs_path); | |
+ return false; | |
+ } | |
+ | |
+ fstat(blob->m_fd, &s_stat); | |
+ blob->m_mapsz = s_stat.st_size; | |
+ | |
+ blob->m_mmap = mmap(NULL, blob->m_mapsz, PROT_READ, MAP_PRIVATE, blob->m_fd, 0); | |
+ if (blob->m_mmap == MAP_FAILED) | |
+ { | |
+ vlog_error("%s: Unable to mmap file", fs_path); | |
+ goto clean_mmap; | |
+ } | |
+ | |
+ offset = sizeof(blob->m_headers); | |
+ | |
+ SDL_memcpy(&blob->m_headers, blob->m_mmap, sizeof(blob->m_headers)); | |
+ for (size_t i = 0; i < SDL_arraysize(blob->m_headers); i++) | |
+ { | |
+ resourceheader *header = &blob->m_headers[i]; | |
+ char **memblock = &blob->m_memblocks[i]; | |
+ | |
+ header->name[sizeof(header->name) - 1] = '\0'; | |
+ if (header->size < 1) { | |
+ vlog_error("%s: Header %li's size value is zero or negative", fs_path, i); | |
+ goto fail_mmaped_header; | |
+ } | |
+ | |
+ *memblock = (char*)((uintptr_t)blob->m_mmap + offset); | |
+ offset += header->size; | |
+ valid += 1; | |
+ continue; | |
+fail_mmaped_header: | |
+ header->valid = false; | |
+ } | |
+ | |
+ if (valid == 0) | |
+ { | |
+ goto clean_mmap; | |
+ } | |
+ | |
+ return true; | |
+clean_mmap: | |
+ if (blob->m_fd > 0) { | |
+ close(blob->m_fd); | |
+ blob->m_fd = -1; | |
+ } | |
+ if (blob->m_mmap != MAP_FAILED) { | |
+ munmap(blob->m_mmap, blob->m_mapsz); | |
+ blob->m_mmap = MAP_FAILED; | |
+ } | |
+ | |
+ return false; | |
+} | |
+#else //USE_MMAP | |
+bool FILESYSTEM_mapBinaryBlob(binaryBlob *blob, const char *filename) | |
+{ | |
+ /* Implementation only available on POSIX. */ | |
+ return false; | |
+} | |
+#endif | |
+ | |
bool FILESYSTEM_saveTiXml2Document(const char *name, tinyxml2::XMLDocument& doc, bool sync /*= true*/) | |
{ | |
if (!isInit) | |
diff --git a/desktop_version/src/FileSystemUtils.h b/desktop_version/src/FileSystemUtils.h | |
index e5c65031..4281fd64 100644 | |
--- a/desktop_version/src/FileSystemUtils.h | |
+++ b/desktop_version/src/FileSystemUtils.h | |
@@ -42,7 +42,7 @@ void FILESYSTEM_loadAssetToMemory( | |
); | |
bool FILESYSTEM_loadBinaryBlob(binaryBlob* blob, const char* filename); | |
- | |
+bool FILESYSTEM_mapBinaryBlob(binaryBlob *blob, const char *filename); | |
bool FILESYSTEM_saveTiXml2Document(const char *name, tinyxml2::XMLDocument& doc, bool sync = true); | |
bool FILESYSTEM_loadTiXml2Document(const char *name, tinyxml2::XMLDocument& doc); | |
bool FILESYSTEM_loadAssetTiXml2Document(const char *name, tinyxml2::XMLDocument& doc); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment