mirror of
https://github.com/EmulatorJS/EmulatorJS.git
synced 2026-02-06 11:17:36 +00:00
Add utility functions for hashing and integrate into cache management
This commit is contained in:
parent
2a6d65f8a5
commit
77a3ff935d
@ -4,6 +4,7 @@
|
||||
"nipplejs.js",
|
||||
"shaders.js",
|
||||
"storage.js",
|
||||
"utils.js",
|
||||
"cache.js",
|
||||
"gamepad.js",
|
||||
"GameManager.js",
|
||||
|
||||
@ -20,6 +20,8 @@ class EJS_Cache {
|
||||
this.minAgeMins = Math.max(60, maxAgeMins * 0.1); // Minimum 1 hour, or 10% of max age
|
||||
this.debug = debug;
|
||||
|
||||
this.utils = new EJS_UTILS();
|
||||
|
||||
if (this.debug) {
|
||||
console.log("Initialized EJS_Cache with settings:", {
|
||||
enabled: this.enabled,
|
||||
@ -33,6 +35,17 @@ class EJS_Cache {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a cache key for the given data array.
|
||||
* @param {Uint8Array} dataArray
|
||||
* @returns {string} The generated cache key.
|
||||
*/
|
||||
generateCacheKey(dataArray) {
|
||||
let hash = this.utils.simpleHash(dataArray);
|
||||
const compressionCacheKey = "Obj-" + hash + "-" + dataArray.length;
|
||||
return compressionCacheKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an item from the cache.
|
||||
* @param {*} key - The unique key identifying the cached item.
|
||||
|
||||
@ -209,6 +209,7 @@ class EmulatorJS {
|
||||
this.checkForUpdates();
|
||||
}
|
||||
this.netplayEnabled = true;
|
||||
this.utils = new EJS_UTILS();
|
||||
this.config = config;
|
||||
this.config.buttonOpts = this.buildButtonOptions(this.config.buttonOpts);
|
||||
this.config.settingsLanguage = window.EJS_settingsLanguage || false;
|
||||
@ -579,11 +580,7 @@ class EmulatorJS {
|
||||
// Generate cache key based on data hash
|
||||
const hashStartTime = performance.now();
|
||||
const dataArray = new Uint8Array(data);
|
||||
let hash = 0;
|
||||
for (let i = 0; i < dataArray.length; i++) {
|
||||
hash = ((hash << 5) - hash + dataArray[i]) & 0xffffffff;
|
||||
}
|
||||
const cacheKey = `compression_${hash}_${dataArray.length}`;
|
||||
const cacheKey = this.storageCache.generateCacheKey(dataArray);
|
||||
const hashTime = performance.now() - hashStartTime;
|
||||
|
||||
// Check if decompressed content is in cache
|
||||
@ -763,16 +760,6 @@ class EmulatorJS {
|
||||
});
|
||||
}
|
||||
|
||||
// Helper function to generate cache key for core data
|
||||
const generateCoreDataCacheKey = (data) => {
|
||||
const dataArray = new Uint8Array(data);
|
||||
let hash = 0;
|
||||
for (let i = 0; i < dataArray.length; i++) {
|
||||
hash = ((hash << 5) - hash + dataArray[i]) & 0xffffffff;
|
||||
}
|
||||
return "compression_" + hash + "_" + dataArray.length;
|
||||
};
|
||||
|
||||
// Helper function to check if cached core is expired
|
||||
const isCoreExpired = (cachedItem) => {
|
||||
if (!cachedItem) return true;
|
||||
@ -842,11 +829,7 @@ class EmulatorJS {
|
||||
if (quickDownload && quickDownload.data) {
|
||||
// Generate cache key the same way checkCompression does
|
||||
const dataArray = new Uint8Array(quickDownload.data);
|
||||
let hash = 0;
|
||||
for (let i = 0; i < dataArray.length; i++) {
|
||||
hash = ((hash << 5) - hash + dataArray[i]) & 0xffffffff;
|
||||
}
|
||||
const compressionCacheKey = `compression_${hash}_${dataArray.length}`;
|
||||
const compressionCacheKey = this.storageCache.generateCacheKey(dataArray);
|
||||
const cachedDecompression = await this.storageCache.get(compressionCacheKey);
|
||||
|
||||
if (cachedDecompression && cachedDecompression.files && cachedDecompression.files.length > 0) {
|
||||
@ -7452,28 +7435,9 @@ class EmulatorJS {
|
||||
}
|
||||
|
||||
enableSaveUpdateEvent() {
|
||||
// https://stackoverflow.com/questions/7616461
|
||||
// Modified to accept a buffer instead of a string and return hex instead of an int
|
||||
async function cyrb53(charBuffer, seed = 0) {
|
||||
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
|
||||
for(let i = 0, ch; i < charBuffer.length; i++) {
|
||||
ch = charBuffer[i];
|
||||
h1 = Math.imul(h1 ^ ch, 2654435761);
|
||||
h2 = Math.imul(h2 ^ ch, 1597334677);
|
||||
}
|
||||
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507);
|
||||
h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909);
|
||||
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507);
|
||||
h2 ^= Math.imul(h1 ^ (h1 >>> 13), 3266489909);
|
||||
|
||||
// Cyrb53 is a 53-bit hash; we need 14 hex characters to represent it, and the first char will
|
||||
// always be 0 or 1 (since it is only 1 bit)
|
||||
return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16).padStart(14, "0");
|
||||
};
|
||||
|
||||
function withGameSaveHash(saveFile, callback) {
|
||||
if (saveFile) {
|
||||
cyrb53(saveFile).then(digest => callback(digest, saveFile));
|
||||
this.utils.cyrb53(saveFile).then(digest => callback(digest, saveFile));
|
||||
} else {
|
||||
console.warn("Save file not found when attempting to hash");
|
||||
callback(null, null);
|
||||
|
||||
42
data/src/utils.js
Normal file
42
data/src/utils.js
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* EJS Utility Functions
|
||||
*/
|
||||
class EJS_UTILS {
|
||||
/**
|
||||
* Computes a simple hash of the given data array.
|
||||
* @param {Uint8Array} dataArray
|
||||
* @returns {number} The computed hash.
|
||||
*/
|
||||
simpleHash(dataArray) {
|
||||
let hash = 0;
|
||||
for (let i = 0; i < dataArray.length; i++) {
|
||||
hash = ((hash << 5) - hash + dataArray[i]) & 0xffffffff;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cyrb53 hash function adapted for buffers.
|
||||
* @param {*} charBuffer
|
||||
* @param {*} seed
|
||||
* @returns {string} Hexadecimal representation of the hash.
|
||||
*/
|
||||
async cyrb53(charBuffer, seed = 0) {
|
||||
// https://stackoverflow.com/questions/7616461
|
||||
// Modified to accept a buffer instead of a string and return hex instead of an int
|
||||
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
|
||||
for(let i = 0, ch; i < charBuffer.length; i++) {
|
||||
ch = charBuffer[i];
|
||||
h1 = Math.imul(h1 ^ ch, 2654435761);
|
||||
h2 = Math.imul(h2 ^ ch, 1597334677);
|
||||
}
|
||||
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507);
|
||||
h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909);
|
||||
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507);
|
||||
h2 ^= Math.imul(h1 ^ (h1 >>> 13), 3266489909);
|
||||
|
||||
// Cyrb53 is a 53-bit hash; we need 14 hex characters to represent it, and the first char will
|
||||
// always be 0 or 1 (since it is only 1 bit)
|
||||
return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16).padStart(14, "0");
|
||||
};
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user