From fd6375e17d7ffcf0a5eae71fe6a150b1f6061c8f Mon Sep 17 00:00:00 2001
From: Varun Patil <radialapps@gmail.com>
Date: Thu, 7 May 2020 12:27:51 +0530
Subject: [PATCH] Use file mapping

---
 CMakeLists.txt        |  2 +-
 extra/make_mapping.sh | 17 +++++++++++++++++
 shell.html            | 22 +++++++++++++++++++++-
 src/alstream.cpp      |  2 +-
 src/bitmap.cpp        |  5 ++++-
 src/emscripten.cpp    | 38 +++++++++++++-------------------------
 src/emscripten.hpp    |  2 --
 src/soundemitter.cpp  |  2 +-
 8 files changed, 58 insertions(+), 32 deletions(-)
 create mode 100755 extra/make_mapping.sh

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 852f2de..1a4a821 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -455,7 +455,7 @@ SET(ASYNCIFY "-s ASYNCIFY=1 -s 'ASYNCIFY_IMPORTS=[\"load_file_async_js\"]'")
 
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EMS_FLAGS} ${ERR_FLAGS} ${ASYNCIFY}")
 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EMS_FLAGS} ${ERR_FLAGS} ${ASYNCIFY}")
-SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${EMS_FLAGS} ${ASYNCIFY} -s INITIAL_MEMORY=536870912 -lopenal --preload-file game -s DISABLE_EXCEPTION_CATCHING=1 -s ASSERTIONS=0 -s SAFE_HEAP=0 -s MINIFY_HTML=0  --shell-file shell.html -s EMULATE_FUNCTION_POINTER_CASTS=0 -s ALLOW_MEMORY_GROWTH=1 -s MAX_WEBGL_VERSION=2")
+SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${EMS_FLAGS} ${ASYNCIFY} -s INITIAL_MEMORY=536870912 -lopenal -s DISABLE_EXCEPTION_CATCHING=1 -s ASSERTIONS=0 -s SAFE_HEAP=0 -s MINIFY_HTML=0  --shell-file shell.html -s EMULATE_FUNCTION_POINTER_CASTS=0 -s ALLOW_MEMORY_GROWTH=1 -s MAX_WEBGL_VERSION=2")
 
 set_target_properties(
     ${PROJECT_NAME}
diff --git a/extra/make_mapping.sh b/extra/make_mapping.sh
new file mode 100755
index 0000000..089d4a9
--- /dev/null
+++ b/extra/make_mapping.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+echo "var mapping = {" > mapping.js
+
+for file in {*,*/*,*/**/*}
+do
+
+filename="${file%.*}"
+fl="$(echo "$filename" | tr '[:upper:]' '[:lower:]')"
+md5=`md5sum ${file} | awk '{ print $1 }'`
+
+echo "\"$fl\": \"${file}?h=${md5}\"," >> mapping.js
+
+done
+
+echo "};" >> mapping.js
+
diff --git a/shell.html b/shell.html
index e32ed46..7b4c94c 100644
--- a/shell.html
+++ b/shell.html
@@ -4,6 +4,7 @@
     <meta charset="utf-8">
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     <script src="js/localforage.min.js"></script>
+    <script src="gameasync/mapping.js"></script>
 
     <title>MKXP</title>
     <style>
@@ -134,8 +135,27 @@
           });
       }
 
+      var createDummies = function() {
+          // Base directory
+          FS.mkdir('/game');
+
+          // Create dummy objects
+          Object.values(mapping).forEach((file) => {
+              // Get filename
+              const filename = '/game/' + file.split("?")[0];
+
+              // Check if folder
+              if (file.endsWith('h=')) {
+                  return FS.mkdir(filename);
+              }
+
+              // Create dummy file
+              FS.writeFile(filename, '1');
+          });
+      };
+
       var Module = {
-        preRun: [],
+        preRun: [createDummies],
         postRun: [loadFiles],
         noAudioDecoding: true,
         print: (function() {
diff --git a/src/alstream.cpp b/src/alstream.cpp
index 7722c5f..73feb24 100644
--- a/src/alstream.cpp
+++ b/src/alstream.cpp
@@ -263,7 +263,7 @@ struct ALStreamOpenHandler : FileSystem::OpenHandler
 void ALStream::openSource(const std::string &filename)
 {
 #ifdef __EMSCRIPTEN__
-	load_file_async(filename.c_str());
+	load_file_async_js(filename.c_str());
 #endif
 
 	ALStreamOpenHandler handler(srcOps, looped);
diff --git a/src/bitmap.cpp b/src/bitmap.cpp
index efd6025..4ecbc0b 100644
--- a/src/bitmap.cpp
+++ b/src/bitmap.cpp
@@ -248,7 +248,6 @@ struct BitmapOpenHandler : FileSystem::OpenHandler
 	bool tryRead(SDL_RWops &ops, const char *ext, const char * fullPath)
 	{
 #ifdef __EMSCRIPTEN__
-		load_file_async_js(fullPath);
 		surf = IMG_Load(fullPath);
 #else
 		surf = IMG_LoadTyped_RW(&ops, 1, ext);
@@ -259,6 +258,10 @@ struct BitmapOpenHandler : FileSystem::OpenHandler
 
 Bitmap::Bitmap(const char *filename)
 {
+#ifdef __EMSCRIPTEN__
+	load_file_async_js(filename);
+#endif
+
 	BitmapOpenHandler handler;
 	shState->fileSystem().openRead(handler, filename);
 	SDL_Surface *imgSurf = handler.surf;
diff --git a/src/emscripten.cpp b/src/emscripten.cpp
index b52236f..588db8e 100644
--- a/src/emscripten.cpp
+++ b/src/emscripten.cpp
@@ -1,6 +1,4 @@
 #include "emscripten.hpp"
-#include "filesystem.h"
-#include "sharedstate.h"
 
 #ifdef __EMSCRIPTEN__
 
@@ -18,15 +16,22 @@ EM_JS(void, load_file_async_js, (const char* fullPathC), {
 		// Show spinner
 		if (window.setBusy) window.setBusy();
 
-		// Get full destination
-		const file = "game/" + fullPath;
+		// Get mapping key
+		const mappingKey = fullPath.toLowerCase().replace(new RegExp("\\\\.[^/.]+$"), "");
+		const mappingValue = mapping[mappingKey];
 
-		// Get path and filename
-		const path = "/" + file.substring(0, file.lastIndexOf("/"));
-		const filename = file.substring(file.lastIndexOf("/") + 1);
+		// Check if this is a folder
+		if (!mappingValue || mappingValue.endsWith("h=")) {
+			console.error("Skipping loading", fullPath, mappingValue);
+			return wakeUp();
+		}
 
 		// Get target URL
-		const iurl = "gameasync/" + fullPath;
+		const iurl = "gameasync/" + mappingValue;
+
+		// Get path and filename
+		const path = "/game/" + mappingValue.substring(0, mappingValue.lastIndexOf("/"));
+		const filename = mappingValue.substring(mappingValue.lastIndexOf("/") + 1).split("?")[0];
 
 		// Delete original file if existent
 		try {
@@ -43,23 +48,6 @@ EM_JS(void, load_file_async_js, (const char* fullPathC), {
 	});
 });
 
-struct LoadOpenHandler : FileSystem::OpenHandler
-{
-	LoadOpenHandler()
-	{}
-
-	bool tryRead(SDL_RWops &ops, const char *ext, const char *fullPath)
-	{
-		load_file_async_js(fullPath);
-		return true;
-	}
-};
-
-void load_file_async(const char * filename) {
-	LoadOpenHandler handler;
-	shState->fileSystem().openRead(handler, filename);
-}
-
 EM_JS(void, save_file_async_js, (const char* fullPathC), {
 	if (window.saveFile) window.saveFile(UTF8ToString(fullPathC));
 });
diff --git a/src/emscripten.hpp b/src/emscripten.hpp
index bf49ac7..3ba6dda 100644
--- a/src/emscripten.hpp
+++ b/src/emscripten.hpp
@@ -7,8 +7,6 @@
 extern "C" {
 	void load_file_async_js(const char* fullPathC);
 
-	void load_file_async(const char* filename);
-
 	void save_file_async_js(const char* fullPathC);
 }
 
diff --git a/src/soundemitter.cpp b/src/soundemitter.cpp
index 406d90e..02caa5f 100644
--- a/src/soundemitter.cpp
+++ b/src/soundemitter.cpp
@@ -250,7 +250,7 @@ SoundBuffer *SoundEmitter::allocateBuffer(const std::string &filename)
 	{
 		/* Buffer not in cache, needs to be loaded */
 #ifdef __EMSCRIPTEN__
-		load_file_async(filename.c_str());
+		load_file_async_js(filename.c_str());
 #endif
 
 		SoundOpenHandler handler;