From ee42da90c9dc400831c84b9cb496b09a52378efe Mon Sep 17 00:00:00 2001 From: "Eevee (Alex Munroe)" Date: Thu, 28 May 2015 16:03:10 -0700 Subject: [PATCH 1/2] Fix RangeError when loading large games. There's a limit to how many arguments a JavaScript VM will accept for a single function call, and piping large blocks of the game image through String.fromCharCode.apply appears to violate that limit. --- src/quixe/gi_load.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/quixe/gi_load.js b/src/quixe/gi_load.js index 536b694..29d4761 100644 --- a/src/quixe/gi_load.js +++ b/src/quixe/gi_load.js @@ -742,9 +742,16 @@ var decode_base64; of the above.) */ if (window.btoa) { - encode_base64 = function(arr) { - return window.btoa(String.fromCharCode.apply(this, arr)); - } + encode_base64 = function(image) { + // There's a limit on how much can be piped into .apply() at a time, so + // do this in chunks + var blocks = []; + for (var i = 0, l = image.length; i < l; i += 16384) { + blocks.push(String.fromCharCode.apply(String, image.slice(i, i + 16384))); + } + + return btoa(blocks.join('')); + }; } else { encode_base64 = function(arr) { From b0f3c814ae797b4a2aea001b6f036a24638defbe Mon Sep 17 00:00:00 2001 From: "Eevee (Alex Munroe)" Date: Thu, 28 May 2015 16:19:01 -0700 Subject: [PATCH 2/2] Speed up fetch_search_key. Setting the length of an array is surprisingly expensive -- instead, just return a new literal array. Also use native array slicing when possible. --- src/quixe/quixe.js | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/quixe/quixe.js b/src/quixe/quixe.js index 2cb1f0c..43150e4 100644 --- a/src/quixe/quixe.js +++ b/src/quixe/quixe.js @@ -283,6 +283,9 @@ function Mem4(addr) { return (memmap[addr] * 0x1000000) + (memmap[addr+1] * 0x10000) + (memmap[addr+2] * 0x100) + (memmap[addr+3]); } +function MemSlice(addr, length) { + return memmap.slice(addr, addr + length); +} function MemW1(addr, val) { // ignore high bytes if necessary memmap[addr] = val & 0xFF; @@ -302,6 +305,7 @@ function MemW4(addr, val) { self.Mem1 = Mem1; self.Mem2 = Mem2; self.Mem4 = Mem4; +self.MemSlice = MemSlice; self.MemW1 = MemW1; self.MemW2 = MemW2; self.MemW4 = MemW4; @@ -5077,52 +5081,48 @@ self.do_gestalt = do_gestalt; /* This fetches a search key, and returns an array containing the key (bytewise). Actually it always returns the same array. */ -var tempsearchkey = []; function fetch_search_key(addr, len, options) { var ix; - tempsearchkey.length = len; if (options & 1) { /* indirect key */ - for (ix=0; ix> 24) & 0xFF; - tempsearchkey[1] = (addr >> 16) & 0xFF; - tempsearchkey[2] = (addr >> 8) & 0xFF; - tempsearchkey[3] = addr & 0xFF; - break; + return [ + (addr >> 24) & 0xFF, + (addr >> 16) & 0xFF, + (addr >> 8) & 0xFF, + addr & 0xFF + ]; case 2: - tempsearchkey[0] = (addr >> 8) & 0xFF; - tempsearchkey[1] = addr & 0xFF; - break; + return [ + (addr >> 8) & 0xFF, + addr & 0xFF + ]; case 1: - tempsearchkey[0] = addr & 0xFF; - break; + return [addr & 0xFF]; default: throw('Direct search key must hold one, two, or four bytes.'); } } - - return tempsearchkey; } function linear_search(key, keysize, start, structsize, numstructs, keyoffset, options) { - var ix, count, match, byt; + var ix, count, match, bytes; var retindex = ((options & 4) != 0); var zeroterm = ((options & 2) != 0); var keybuf = fetch_search_key(key, keysize, options); for (count=0; count