diff --git a/package-lock.json b/package-lock.json
index a6e0c24..3f7e9f0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "diabloweb",
- "version": "1.0.36",
+ "version": "1.0.37",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index 48310c1..e9ae3f8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "diabloweb",
- "version": "1.0.36",
+ "version": "1.0.37",
"private": true,
"dependencies": {
"@babel/core": "7.4.3",
diff --git a/src/App.js b/src/App.js
index f01e1eb..7b8b728 100644
--- a/src/App.js
+++ b/src/App.js
@@ -11,6 +11,7 @@ import { mapStackTrace } from 'sourcemapped-stacktrace';
import create_fs from './fs';
import load_game from './api/loader';
import { SpawnSizes } from './api/load_spawn';
+import CompressMpq from './mpqcmp';
import Peer from 'peerjs';
@@ -130,7 +131,9 @@ class App extends React.Component {
if (spawn && SpawnSizes.includes(spawn.byteLength)) {
this.setState({has_spawn: true});
}
- this.updateSaves();
+ if ([...fs.files.keys()].filter(name => name.match(/\.sv$/i)).length) {
+ this.setState({save_names: true});
+ }
});
}
@@ -138,7 +141,11 @@ class App extends React.Component {
const file = getDropFile(e);
if (file) {
e.preventDefault();
- this.start(file);
+ if (this.compressMpq) {
+ this.compressMpq.start(file);
+ } else {
+ this.start(file);
+ }
}
this.setState({dropping: 0});
}
@@ -223,12 +230,18 @@ class App extends React.Component {
this.saveName = name;
}
+ showSaves = () => {
+ if (this.state.save_names === true) {
+ this.updateSaves().then(() => this.setState({show_saves: !this.state.show_saves}));
+ } else {
+ this.setState({show_saves: !this.state.show_saves});
+ }
+ }
updateSaves() {
- this.fs.then(fs => {
- const saves = [];
+ return this.fs.then(fs => {
+ const saves = {};
[...fs.files.keys()].filter(name => name.match(/\.sv$/i)).forEach(name => {
- saves.push(name);
- console.log(name, getPlayerName(fs.files.get(name).buffer));
+ saves[name] = getPlayerName(fs.files.get(name).buffer, name);
});
this.setState({save_names: saves});
});
@@ -302,7 +315,7 @@ class App extends React.Component {
document.removeEventListener("dragleave", this.onDragLeave, true);
this.setState({dropping: 0});
- const retail = !!(file && file.name.match(/^diabdat\.mpq$/i));
+ const retail = !!(file && !file.name.match(/^spawn\.mpq$/i));
if (process.env.NODE_ENV === 'production') {
ReactGA.event({
category: 'Game',
@@ -656,30 +669,78 @@ class App extends React.Component {
}
}
- render() {
- const {started, loading, error, progress, dropping, has_spawn, save_names, show_saves} = this.state;
- if (show_saves && save_names) {
+ renderUi() {
+ const {started, loading, error, progress, has_spawn, save_names, show_saves, compress} = this.state;
+ if (show_saves && typeof save_names === "object") {
+ const plrClass = ["Warrior", "Rogue", "Sorcerer"];
return (
-
-
-
-
- {save_names.map(name =>
- {name}
- this.downloadSave(name)}/>
- this.removeSave(name)}/>
- )}
-
-
-
this.setState({show_saves: false})}>Back
-
-
+
+
+ {Object.entries(save_names).map(([name, info]) =>
+ {name}{info ? {info.name} (lv. {info.level} {plrClass[info.cls]}) : ""}
+ this.downloadSave(name)}/>
+ this.removeSave(name)}/>
+ )}
+
+
+
this.setState({show_saves: false})}>Back
+
+ );
+ } else if (compress) {
+ return (
+
this.compressMpq = e}/>
+ );
+ } else if (error) {
+ return (
+
+ The following error has occurred:
+ {error.message}
+ Click to create an issue on GitHub
+ {error.save != null && Download save file }
+
+ );
+ } else if (loading && !started) {
+ return (
+
+ {(progress && progress.text) || 'Loading...'}
+ {progress != null && !!progress.total && (
+
+ )}
+
+ );
+ } else if (!started) {
+ return (
+
+
+ This is a web port of the original Diablo game, based on source code reconstructed by
+ GalaXyHaXz and devilution team. The project page with information and links can be found over here https://github.com/d07RiV/diabloweb
+
+
+ If you own the original game, you can drop the original DIABDAT.MPQ onto this page or click the button below to start playing.
+ The game can be purchased from GoG.
+ {" "} this.setState({compress: true})}>Click here to compress the MPQ, greatly reducing its size.
+
+ {!has_spawn && (
+
+ Or you can play the shareware version for free (50MB download).
+
+ )}
+
+
this.start()}>Play Shareware
+ {!!save_names &&
Manage Saves
}
);
}
+ }
+
+ render() {
+ const {started, error, dropping} = this.state;
return (
@@ -699,45 +760,7 @@ class App extends React.Component {
- {!!error && (
-
-
The following error has occurred:
-
{error.message}
-
Click to create an issue on GitHub
- {error.save != null &&
Download save file }
-
- )}
- {!!loading && !started && !error && (
-
- {(progress && progress.text) || 'Loading...'}
- {progress != null && !!progress.total && (
-
- )}
-
- )}
- {!started && !loading && !error && (
-
-
- This is a web port of the original Diablo game, based on source code reconstructed by
- GalaXyHaXz and devilution team. The project page with information and links can be found over here https://github.com/d07RiV/diabloweb
-
-
- If you own the original game, you can drop the original DIABDAT.MPQ onto this page or click the button below to start playing.
- The game can be purchased from GoG.
-
- {!has_spawn && (
-
- Or you can play the shareware version for free (50MB download).
-
- )}
-
-
this.start()}>Play Shareware
- {!!(save_names && save_names.length) &&
this.setState({show_saves: true})}>Manage Saves }
-
- )}
+ {this.renderUi()}
);
diff --git a/src/App.scss b/src/App.scss
index af3e5ff..08ff118 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -110,7 +110,9 @@ body, #root, .App {
margin: 10px 0;
}
.startButton {
- display: inline-block;
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
border: 1px solid #fff;
background: #000;
font-size: 2em;
@@ -127,14 +129,24 @@ body, #root, .App {
text-align: left;
li {
padding: 0 6px;
+ .info {
+ color: #888;
+ margin-left: 6px;
+ }
.btnRemove {
- color: #f88;
+ color: #800;
+ &:hover {
+ color: #f00;
+ }
float: right;
cursor: pointer;
margin: 0 4px;
}
.btnDownload {
- color: #fff;
+ color: #888;
+ &:hover {
+ color: #fff;
+ }
float: right;
cursor: pointer;
margin: 0 4px;
diff --git a/src/api/codec.js b/src/api/codec.js
index 2bf2aa6..9736192 100644
--- a/src/api/codec.js
+++ b/src/api/codec.js
@@ -1,25 +1,28 @@
const W = new Uint32Array(80);
-const SHA1CircularShift = (shift, value) => ((value << shift) | (value >>> (32 - shift)));
+const SHA1CircularShift = (shift, value) => ((value << shift) | (value >> (32 - shift)));
class SHA1 {
- state = new Uint32Array(5);
+ digest = new Uint32Array(5);
count = 0;
- input(u8) {
+ input8(u8) {
const u32 = new Uint32Array(u8.buffer, u8.byteOffset, 16);
- context.count += data.length * 32;
+ this.input(u32);
+ }
+ input(u32) {
+ this.count += u32.length * 32;
for (let i = 0; i < 16; ++i) {
W[i] = u32[i];
}
for (let i = 16; i < 80; ++i) {
W[i] = W[i - 16] ^ W[i - 14] ^ W[i - 8] ^ W[i - 3];
}
- let A = this.state[0];
- let B = this.state[1];
- let C = this.state[2];
- let D = this.state[3];
- let E = this.state[4];
+ let A = this.digest[0];
+ let B = this.digest[1];
+ let C = this.digest[2];
+ let D = this.digest[3];
+ let E = this.digest[4];
for (let i = 0; i < 20; i++) {
const temp = SHA1CircularShift(5, A) + ((B & C) | ((~B) & D)) + E + W[i] + 0x5A827999;
@@ -57,21 +60,21 @@ class SHA1 {
A = temp | 0;
}
- this.state[0] += A;
- this.state[1] += B;
- this.state[2] += C;
- this.state[3] += D;
- this.state[4] += E;
+ this.digest[0] += A;
+ this.digest[1] += B;
+ this.digest[2] += C;
+ this.digest[3] += D;
+ this.digest[4] += E;
}
constructor() {
- this.state[0] = 0x67452301;
- this.state[1] = 0xEFCDAB89;
- this.state[2] = 0x98BADCFE;
- this.state[3] = 0x10325476;
- this.state[4] = 0xC3D2E1F0;
+ this.digest[0] = 0x67452301;
+ this.digest[1] = 0xEFCDAB89;
+ this.digest[2] = 0x98BADCFE;
+ this.digest[3] = 0x10325476;
+ this.digest[4] = 0xC3D2E1F0;
- this.result = new Uint8Array(this.state.buffer);
+ this.digest8 = new Uint8Array(this.digest.buffer);
}
}
@@ -85,16 +88,10 @@ class Random {
}
}
-struct CodecSignature {
- DWORD checksum;
- BYTE error;
- BYTE last_chunk_size;
- WORD unused;
-};
-
function codec_init_key(password) {
const rand = new Random(0x7058);
const key = new Uint8Array(136);
+ const k32 = new Uint32Array(key.buffer);
for (let i = 0; i < 136; ++i) {
key[i] = rand.next();
}
@@ -103,62 +100,50 @@ function codec_init_key(password) {
pw[i] = password.charCodeAt(i % password.length);
}
- const sha = new SHA1();
- sha.input(pw);
+ let sha = new SHA1();
+ sha.input8(pw);
- for (let i = 0; i < 136; ++i) {
- key[i] ^= sha.result[i % sha.result.length];
+ for (let i = 0; i < 34; ++i) {
+ k32[i] ^= sha.digest[i % sha.digest.length];
}
sha = new SHA1();
- sha.input(key.subarray(72));
+ sha.input(k32.subarray(18));
return sha;
}
-function codec_decode(data, password) {
- const sha = codec_init_key(password);
+export default function codec_decode(data, password) {
if (data.length <= 8) {
return;
}
const size = data.length - 8;
- if ()
- char buf[128];
- char dst[SHA1HashSize];
- int i;
- CodecSignature *sig;
+ if (size % 64) {
+ return;
+ }
- codec_init_key(0, pszPassword);
- if (size <= 8)
- return 0;
- size = size - 8;
- if (size % 64 != 0)
- return 0;
- for (i = size; i != 0; pbSrcDst += 64, i -= 64) {
- memcpy(buf, pbSrcDst, 64);
- SHA1Result(0, dst);
- for (int j = 0; j < 64; j++) {
- buf[j] ^= dst[j % SHA1HashSize];
- }
- SHA1Calculate(0, buf, NULL);
- memset(dst, 0, sizeof(dst));
- memcpy(pbSrcDst, buf, 64);
- }
+ if (data[size + 4]) {
+ return;
+ }
- memset(buf, 0, sizeof(buf));
- sig = (CodecSignature *)pbSrcDst;
- if (sig->error > 0) {
- size = 0;
- SHA1Clear();
- } else {
- SHA1Result(0, dst);
- if (sig->checksum != *(DWORD *)dst) {
- memset(dst, 0, sizeof(dst));
- size = 0;
- SHA1Clear();
- } else {
- size += sig->last_chunk_size - 64;
- SHA1Clear();
- }
- }
- return size;
+ const last_size = data[size + 5];
+ const result_size = size + last_size - 64;
+ const result = new Uint8Array(result_size);
+
+ const sha = codec_init_key(password);
+ const size32 = size >> 2;
+ const data32 = new Uint32Array(data.buffer, data.byteOffset, size32 + 1);
+ const buf32 = new Uint32Array(16);
+ const buf = new Uint8Array(buf32.buffer);
+
+ for (let i = 0; i < size32; i += 16) {
+ for (let j = 0; j < 16; ++j) {
+ buf32[j] = data32[i + j] ^ sha.digest[j % sha.digest.length];
+ }
+ sha.input(buf32);
+ result.set(i === size32 - 16 ? buf.subarray(0, last_size) : buf, i * 4);
+ }
+ if (data32[size32] !== sha.digest[0]) {
+ return;
+ }
+ return result;
}
diff --git a/src/api/savefile.js b/src/api/savefile.js
index 728b966..508d528 100644
--- a/src/api/savefile.js
+++ b/src/api/savefile.js
@@ -1,4 +1,5 @@
import { explode } from './explode';
+import codec_decode from './codec';
function pkzip_decompress(data, out_size) {
if (data.length === out_size) {
@@ -43,7 +44,7 @@ const hashtable = (function() {
}
return hashtable;
})();
-function decrypt(u32, key) {
+export function decrypt(u32, key) {
let seed = 0xEEEEEEEE;
for (let i = 0; i < u32.length; ++i) {
seed += hashtable[0x400 + (key & 0xFF)];
@@ -52,10 +53,23 @@ function decrypt(u32, key) {
key = ((~key << 0x15) + 0x11111111) | (key >>> 0x0B);
}
}
-function decrypt8(u8, key) {
+export function decrypt8(u8, key) {
decrypt(new Uint32Array(u8.buffer, u8.byteOffset, u8.length >> 2), key);
}
-function hash(name, type) {
+export function encrypt(u32, key) {
+ let seed = 0xEEEEEEEE;
+ for (let i = 0; i < u32.length; ++i) {
+ seed += hashtable[0x400 + (key & 0xFF)];
+ const orig = u32[i];
+ u32[i] ^= seed + key;
+ seed = (orig + seed * 33 + 3) | 0;
+ key = ((~key << 0x15) + 0x11111111) | (key >>> 0x0B);
+ }
+}
+export function encrypt8(u8, key) {
+ encrypt(new Uint32Array(u8.buffer, u8.byteOffset, u8.length >> 2), key);
+}
+export function hash(name, type) {
let seed1 = 0x7FED7FED;
let seed2 = 0xEEEEEEEE;
for (let i = 0; i < name.length; ++i) {
@@ -72,7 +86,7 @@ function hash(name, type) {
return seed1 >>> 0;
}
-function path_name(name) {
+export function path_name(name) {
const pos = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\'));
return name.substring(pos + 1);
}
@@ -90,11 +104,11 @@ const Flags = {
Exists: 0x80000000,
};
-class MpqReader {
+export class MpqReader {
constructor(buffer) {
this.buffer = buffer;
this.u8 = new Uint8Array(buffer);
- this.u32 = new Uint32Array(buffer);
+ this.u32 = new Uint32Array(buffer, 0, buffer.byteLength >> 2);
this.readHeader();
}
@@ -132,79 +146,81 @@ class MpqReader {
}
}
- read(name) {
+ readRaw(name) {
const index = this.fileIndex(name);
if (index == null) {
return;
}
const block = this.hashTable[index * 4 + 3];
- const filePos = this.blockTable[block * 4];
- let cmpSize = this.blockTable[block * 4 + 1];
- const fileSize = this.blockTable[block * 4 + 2];
- const flags = this.blockTable[block * 4 + 3];
-
- if (flags & Flags.PatchFile) {
+ const info = {
+ filePos: this.blockTable[block * 4],
+ cmpSize: this.blockTable[block * 4 + 1],
+ fileSize: this.blockTable[block * 4 + 2],
+ flags: this.blockTable[block * 4 + 3],
+ key: hash(path_name(name), 3),
+ };
+ if ((info.flags & Flags.PatchFile) || info.filePos + info.cmpSize > this.buffer.byteLength) {
return;
}
- if (!(flags & Flags.Compressed)) {
- cmpSize = fileSize;
+ if (!(info.flags & Flags.Compressed)) {
+ info.cmpSize = info.fileSize;
}
-
- let key = hash(path_name(name), 3);
- if (flags & Flags.FixSeed) {
- key = (key + filePos) ^ fileSize;
+ if (info.flags & Flags.FixSeed) {
+ info.key = (info.key + info.filePos) ^ info.fileSize;
}
+ return {info, data: new Uint8Array(this.buffer, info.filePos, info.cmpSize)};
+ }
- if (flags & Flags.SingleUnit) {
- const raw = new Uint8Array(this.buffer, filePos, cmpSize);
- if (raw.length !== cmpSize) {
+ read(name) {
+ const raw = this.readRaw(name);
+ if (!raw) {
+ return;
+ }
+ let {info, data} = raw;
+ data = data.slice();
+
+ if (info.flags & Flags.SingleUnit) {
+ if (info.flags & Flags.Encrypted) {
+ decrypt8(data, info.key);
+ }
+ if (info.flags & Flags.CompressMulti) {
return;
+ } else if (info.flags & Flags.CompressPkWare) {
+ return pkzip_decompress(data, info.fileSize);
}
- if (flags & Flags.Encrypted) {
- decrypt8(raw, key);
- }
- if (flags & Flags.CompressMulti) {
- return;
- } else if (flags & Flags.CompressPkWare) {
- return pkzip_decompress(raw, fileSize);
- }
- return raw;
- } else if (!(flags & Flags.Compressed)) {
- const raw = Uint8Array(this.buffer, filePos, fileSize);
- if (raw.length !== fileSize) {
- return;
- }
- if (flags & Flags.Encrypted) {
- for (let i = 0; i < fileSize; i += this.blockSize) {
- decrypt8(raw.subarray(i, Math.min(fileSize, i + this.blockSize)), key + i / this.blockSize);
+ return data;
+ } else if (!(info.flags & Flags.Compressed)) {
+ if (info.flags & Flags.Encrypted) {
+ for (let i = 0; i < info.fileSize; i += this.blockSize) {
+ decrypt8(data.subarray(i, Math.min(info.fileSize, i + this.blockSize)), info.key + i / this.blockSize);
}
}
- return raw;
+ return data;
} else {
- const numBlocks = Math.floor((fileSize + this.blockSize - 1) / this.blockSize);
- const tableSize = numBlocks + 1 + ((flags & Flags.SectorCrc) ? 1 : 0);
- const blocks = new Uint32Array(this.buffer, filePos, tableSize);
- if (blocks.length !== tableSize) {
+ const numBlocks = Math.floor((info.fileSize + this.blockSize - 1) / this.blockSize);
+ const tableSize = numBlocks + 1;
+ if (data.length < tableSize * 4) {
return;
}
- if (flags & Flags.Encrypted) {
- decrypt(blocks, key - 1);
+ const blocks = new Uint32Array(data.buffer, 0, tableSize);
+ if (info.flags & Flags.Encrypted) {
+ decrypt(blocks, info.key - 1);
}
- const output = new Uint8Array(fileSize);
+ const output = new Uint8Array(info.fileSize);
for (let i = 0; i < numBlocks; ++i) {
const oPos = i * this.blockSize;
- const cSize = blocks[i + 1] - blocks[i];
- const uSize = Math.min(this.blockSize, fileSize - oPos);
- let tmp = new Uint8Array(this.buffer, filePos + blocks[i], cSize);
- if (tmp.length !== cSize) {
+ const uSize = Math.min(this.blockSize, info.fileSize - oPos);
+ if (blocks[i + 1] > data.length) {
return;
}
- if (flags & Flags.Encrypted) {
- decrypt8(tmp, key + i);
+ let tmp = data.subarray(blocks[i], blocks[i + 1]);
+ if (info.flags & Flags.Encrypted) {
+ // this is not safe, but our files are small enough
+ decrypt8(tmp, info.key + i);
}
- if (flags & Flags.CompressMulti) {
+ if (info.flags & Flags.CompressMulti) {
return;
- } else if (flags & Flags.CompressPkWare) {
+ } else if (info.flags & Flags.CompressPkWare) {
tmp = pkzip_decompress(tmp, uSize);
}
if (!tmp || tmp.length !== uSize) {
@@ -217,12 +233,28 @@ class MpqReader {
}
}
-export default function getPlayerName(data) {
- debugger;
+function getPassword(name) {
+ if (name.match(/spawn\d+\.sv/i)) {
+ return 'lshbkfg1'; // single, spawn
+ } else if (name.match(/share_\d+\.sv/i)) {
+ return 'lshbkfg1'; // multi, spawn
+ } else if (name.match(/multi_\d+\.sv/i)) {
+ return 'szqnlsk1'; // multi, retail
+ } else {
+ return 'xrgyrkj1'; // single, retail
+ }
+}
+
+export default function getPlayerName(data, name) {
try {
const reader = new MpqReader(data);
- const hero = reader.read("hero");
- return '';
+ const hero = codec_decode(reader.read("hero"), getPassword(name));
+ const nameEnd = hero.indexOf(0, 16);
+ const result = {};
+ result.name = String.fromCharCode(...hero.subarray(16, nameEnd));
+ result.cls = hero[48];
+ result.level = hero[53];
+ return result;
} catch (e) {
return null;
}
diff --git a/src/mpqcmp/MpqCmp.jscc b/src/mpqcmp/MpqCmp.jscc
index cc1906b..b48a5e7 100644
--- a/src/mpqcmp/MpqCmp.jscc
+++ b/src/mpqcmp/MpqCmp.jscc
@@ -5,11 +5,6 @@ var MpqCmp = (function() {
function(MpqCmp) {
MpqCmp = MpqCmp || {};
-// Copyright 2010 The Emscripten Authors. All rights reserved.
-// Emscripten is available under two separate licenses, the MIT license and the
-// University of Illinois/NCSA Open Source License. Both these licenses can be
-// found in the LICENSE file.
-
// The Module object: Our interface to the outside world. We import
// and export values on it. There are various ways Module can be used:
// 1. Not defined. We create it here
@@ -50,35 +45,25 @@ Module['quit'] = function(status, toThrow) {
Module['preRun'] = [];
Module['postRun'] = [];
-// Determine the runtime environment we are in. You can customize this by
-// setting the ENVIRONMENT setting at compile time (see settings.js).
+// The environment setup code below is customized to use Module.
+// *** Environment setup code ***
var ENVIRONMENT_IS_WEB = false;
var ENVIRONMENT_IS_WORKER = false;
var ENVIRONMENT_IS_NODE = false;
-var ENVIRONMENT_HAS_NODE = false;
var ENVIRONMENT_IS_SHELL = false;
ENVIRONMENT_IS_WEB = typeof window === 'object';
ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
-// A web environment like Electron.js can have Node enabled, so we must
-// distinguish between Node-enabled environments and Node environments per se.
-// This will allow the former to do things like mount NODEFS.
-// Extended check using process.versions fixes issue #8816.
-// (Also makes redundant the original check that 'require' is a function.)
-ENVIRONMENT_HAS_NODE = typeof process === 'object' && typeof process.versions === 'object' && typeof process.versions.node === 'string';
-ENVIRONMENT_IS_NODE = ENVIRONMENT_HAS_NODE && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER;
+ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function' && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER;
ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
-
// Three configurations we can be running in:
// 1) We could be the application main() thread running in the main JS UI thread. (ENVIRONMENT_IS_WORKER == false and ENVIRONMENT_IS_PTHREAD == false)
// 2) We could be the application main() thread proxied to worker. (with Emscripten -s PROXY_TO_WORKER=1) (ENVIRONMENT_IS_WORKER == true, ENVIRONMENT_IS_PTHREAD == false)
// 3) We could be an application pthread running in a worker. (ENVIRONMENT_IS_WORKER == true and ENVIRONMENT_IS_PTHREAD == true)
-
-
// `/` should be present at the end if `scriptDirectory` is not empty
var scriptDirectory = '';
function locateFile(path) {
@@ -89,12 +74,6 @@ function locateFile(path) {
}
}
-// Hooks that are implemented differently in different runtime environments.
-var read_,
- readAsync,
- readBinary,
- setWindowTitle;
-
if (ENVIRONMENT_IS_NODE) {
scriptDirectory = __dirname + '/';
@@ -103,7 +82,7 @@ if (ENVIRONMENT_IS_NODE) {
var nodeFS;
var nodePath;
- read_ = function shell_read(filename, binary) {
+ Module['read'] = function shell_read(filename, binary) {
var ret;
if (!nodeFS) nodeFS = require('fs');
if (!nodePath) nodePath = require('path');
@@ -112,8 +91,8 @@ if (ENVIRONMENT_IS_NODE) {
return binary ? ret : ret.toString();
};
- readBinary = function readBinary(filename) {
- var ret = read_(filename, true);
+ Module['readBinary'] = function readBinary(filename) {
+ var ret = Module['read'](filename, true);
if (!ret.buffer) {
ret = new Uint8Array(ret);
}
@@ -137,7 +116,9 @@ if (ENVIRONMENT_IS_NODE) {
});
// Currently node will swallow unhandled rejections, but this behavior is
// deprecated, and in the future it will exit with error status.
- process['on']('unhandledRejection', abort);
+ process['on']('unhandledRejection', function(reason, p) {
+ process['exit'](1);
+ });
Module['quit'] = function(status) {
process['exit'](status);
@@ -149,12 +130,12 @@ if (ENVIRONMENT_IS_SHELL) {
if (typeof read != 'undefined') {
- read_ = function shell_read(f) {
+ Module['read'] = function shell_read(f) {
return read(f);
};
}
- readBinary = function readBinary(f) {
+ Module['readBinary'] = function readBinary(f) {
var data;
if (typeof readbuffer === 'function') {
return new Uint8Array(readbuffer(f));
@@ -177,10 +158,12 @@ if (ENVIRONMENT_IS_SHELL) {
}
} else
if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
- if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled
+ if (ENVIRONMENT_IS_WEB) {
+ if (document.currentScript) {
+ scriptDirectory = document.currentScript.src;
+ }
+ } else { // worker
scriptDirectory = self.location.href;
- } else if (document.currentScript) { // web
- scriptDirectory = document.currentScript.src;
}
// When MODULARIZE (and not _INSTANCE), this JS may be executed later, after document.currentScript
// is gone, so we saved it, and we use it here instead of any other info.
@@ -189,16 +172,14 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
}
// blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them.
// otherwise, slice off the final part of the url to find the script directory.
- // if scriptDirectory does not contain a slash, lastIndexOf will return -1,
- // and scriptDirectory will correctly be replaced with an empty string.
if (scriptDirectory.indexOf('blob:') !== 0) {
- scriptDirectory = scriptDirectory.substr(0, scriptDirectory.lastIndexOf('/')+1);
+ scriptDirectory = scriptDirectory.split('/').slice(0, -1).join('/') + '/';
} else {
scriptDirectory = '';
}
- read_ = function shell_read(url) {
+ Module['read'] = function shell_read(url) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, false);
xhr.send(null);
@@ -206,7 +187,7 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
};
if (ENVIRONMENT_IS_WORKER) {
- readBinary = function readBinary(url) {
+ Module['readBinary'] = function readBinary(url) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, false);
xhr.responseType = 'arraybuffer';
@@ -215,7 +196,7 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
};
}
- readAsync = function readAsync(url, onload, onerror) {
+ Module['readAsync'] = function readAsync(url, onload, onerror) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
@@ -230,7 +211,7 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
xhr.send(null);
};
- setWindowTitle = function(title) { document.title = title };
+ Module['setWindowTitle'] = function(title) { document.title = title };
} else
{
}
@@ -244,6 +225,8 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
var out = Module['print'] || (typeof console !== 'undefined' ? console.log.bind(console) : (typeof print !== 'undefined' ? print : null));
var err = Module['printErr'] || (typeof printErr !== 'undefined' ? printErr : ((typeof console !== 'undefined' && console.warn.bind(console)) || out));
+// *** Environment setup code ***
+
// Merge back in the overrides
for (key in moduleOverrides) {
if (moduleOverrides.hasOwnProperty(key)) {
@@ -254,35 +237,37 @@ for (key in moduleOverrides) {
// reclaim data used e.g. in memoryInitializerRequest, which is a large typed array.
moduleOverrides = undefined;
-// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message
-// TODO remove when SDL2 is fixed; also add the above assertion
-
-
-
-// Copyright 2017 The Emscripten Authors. All rights reserved.
-// Emscripten is available under two separate licenses, the MIT license and the
-// University of Illinois/NCSA Open Source License. Both these licenses can be
-// found in the LICENSE file.
// {{PREAMBLE_ADDITIONS}}
var STACK_ALIGN = 16;
+function staticAlloc(size) {
+ var ret = STATICTOP;
+ STATICTOP = (STATICTOP + size + 15) & -16;
+ return ret;
+}
+
function dynamicAlloc(size) {
var ret = HEAP32[DYNAMICTOP_PTR>>2];
var end = (ret + size + 15) & -16;
- if (end > _emscripten_get_heap_size()) {
- abort();
- }
HEAP32[DYNAMICTOP_PTR>>2] = end;
+ if (end >= TOTAL_MEMORY) {
+ var success = enlargeMemory();
+ if (!success) {
+ HEAP32[DYNAMICTOP_PTR>>2] = ret;
+ return 0;
+ }
+ }
return ret;
}
function alignMemory(size, factor) {
if (!factor) factor = STACK_ALIGN; // stack alignment (16-byte) by default
- return Math.ceil(size / factor) * factor;
+ var ret = size = Math.ceil(size / factor) * factor;
+ return ret;
}
function getNativeTypeSize(type) {
@@ -298,7 +283,7 @@ function getNativeTypeSize(type) {
return 4; // A pointer
} else if (type[0] === 'i') {
var bits = parseInt(type.substr(1));
- assert(bits % 8 === 0, 'getNativeTypeSize invalid bits ' + bits + ', type ' + type);
+ assert(bits % 8 === 0);
return bits / 8;
} else {
return 0;
@@ -329,112 +314,8 @@ var asm2wasmImports = { // special asm2wasm imports
var jsCallStartIndex = 1;
var functionPointers = new Array(0);
-// Wraps a JS function as a wasm function with a given signature.
-// In the future, we may get a WebAssembly.Function constructor. Until then,
-// we create a wasm module that takes the JS function as an import with a given
-// signature, and re-exports that as a wasm function.
-function convertJsFunctionToWasm(func, sig) {
-
- // The module is static, with the exception of the type section, which is
- // generated based on the signature passed in.
- var typeSection = [
- 0x01, // id: section,
- 0x00, // length: 0 (placeholder)
- 0x01, // count: 1
- 0x60, // form: func
- ];
- var sigRet = sig.slice(0, 1);
- var sigParam = sig.slice(1);
- var typeCodes = {
- 'i': 0x7f, // i32
- 'j': 0x7e, // i64
- 'f': 0x7d, // f32
- 'd': 0x7c, // f64
- };
-
- // Parameters, length + signatures
- typeSection.push(sigParam.length);
- for (var i = 0; i < sigParam.length; ++i) {
- typeSection.push(typeCodes[sigParam[i]]);
- }
-
- // Return values, length + signatures
- // With no multi-return in MVP, either 0 (void) or 1 (anything else)
- if (sigRet == 'v') {
- typeSection.push(0x00);
- } else {
- typeSection = typeSection.concat([0x01, typeCodes[sigRet]]);
- }
-
- // Write the overall length of the type section back into the section header
- // (excepting the 2 bytes for the section id and length)
- typeSection[1] = typeSection.length - 2;
-
- // Rest of the module is static
- var bytes = new Uint8Array([
- 0x00, 0x61, 0x73, 0x6d, // magic ("\0asm")
- 0x01, 0x00, 0x00, 0x00, // version: 1
- ].concat(typeSection, [
- 0x02, 0x07, // import section
- // (import "e" "f" (func 0 (type 0)))
- 0x01, 0x01, 0x65, 0x01, 0x66, 0x00, 0x00,
- 0x07, 0x05, // export section
- // (export "f" (func 0 (type 0)))
- 0x01, 0x01, 0x66, 0x00, 0x00,
- ]));
-
- // We can compile this wasm module synchronously because it is very small.
- // This accepts an import (at "e.f"), that it reroutes to an export (at "f")
- var module = new WebAssembly.Module(bytes);
- var instance = new WebAssembly.Instance(module, {
- e: {
- f: func
- }
- });
- var wrappedFunc = instance.exports.f;
- return wrappedFunc;
-}
-
-// Add a wasm function to the table.
-function addFunctionWasm(func, sig) {
- var table = wasmTable;
- var ret = table.length;
-
- // Grow the table
- try {
- table.grow(1);
- } catch (err) {
- if (!err instanceof RangeError) {
- throw err;
- }
- throw 'Unable to grow wasm table. Use a higher value for RESERVED_FUNCTION_POINTERS or set ALLOW_TABLE_GROWTH.';
- }
-
- // Insert new element
- try {
- // Attempting to call this with JS function will cause of table.set() to fail
- table.set(ret, func);
- } catch (err) {
- if (!err instanceof TypeError) {
- throw err;
- }
- assert(typeof sig !== 'undefined', 'Missing signature argument to addFunction');
- var wrapped = convertJsFunctionToWasm(func, sig);
- table.set(ret, wrapped);
- }
-
- return ret;
-}
-
-function removeFunctionWasm(index) {
- // TODO(sbc): Look into implementing this to allow re-using of table slots
-}
-
-// 'sig' parameter is required for the llvm backend but only when func is not
-// already a WebAssembly function.
+// 'sig' parameter is only used on LLVM wasm backend
function addFunction(func, sig) {
-
-
var base = 0;
for (var i = base; i < base + 0; i++) {
if (!functionPointers[i]) {
@@ -443,11 +324,9 @@ function addFunction(func, sig) {
}
}
throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.';
-
}
function removeFunction(index) {
-
functionPointers[index-jsCallStartIndex] = null;
}
@@ -493,18 +372,13 @@ function dynCall(sig, ptr, args) {
}
}
-var tempRet0 = 0;
-
-var setTempRet0 = function(value) {
- tempRet0 = value;
-};
-
-var getTempRet0 = function() {
- return tempRet0;
-};
var Runtime = {
+ // FIXME backwards compatibility layer for ports. Support some Runtime.*
+ // for now, fix it there, then remove it from here. That way we
+ // can minimize any period of breakage.
+ dynCall: dynCall, // for SDL2 port
};
// The address globals begin at. Very low in memory, for code size and optimization opportunities.
@@ -514,8 +388,6 @@ var Runtime = {
var GLOBAL_BASE = 1024;
-
-
// === Preamble library stuff ===
// Documentation for the public APIs defined in this file must be updated in:
@@ -528,70 +400,11 @@ var GLOBAL_BASE = 1024;
-if (typeof WebAssembly !== 'object') {
- err('no native wasm support detected');
-}
-
-
-// In MINIMAL_RUNTIME, setValue() and getValue() are only available when building with safe heap enabled, for heap safety checking.
-// In traditional runtime, setValue() and getValue() are always available (although their use is highly discouraged due to perf penalties)
-
-/** @type {function(number, number, string, boolean=)} */
-function setValue(ptr, value, type, noSafe) {
- type = type || 'i8';
- if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
- switch(type) {
- case 'i1': HEAP8[((ptr)>>0)]=value; break;
- case 'i8': HEAP8[((ptr)>>0)]=value; break;
- case 'i16': HEAP16[((ptr)>>1)]=value; break;
- case 'i32': HEAP32[((ptr)>>2)]=value; break;
- case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math_abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? ((Math_min((+(Math_floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break;
- case 'float': HEAPF32[((ptr)>>2)]=value; break;
- case 'double': HEAPF64[((ptr)>>3)]=value; break;
- default: abort('invalid type for setValue: ' + type);
- }
-}
-
-/** @type {function(number, string, boolean=)} */
-function getValue(ptr, type, noSafe) {
- type = type || 'i8';
- if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
- switch(type) {
- case 'i1': return HEAP8[((ptr)>>0)];
- case 'i8': return HEAP8[((ptr)>>0)];
- case 'i16': return HEAP16[((ptr)>>1)];
- case 'i32': return HEAP32[((ptr)>>2)];
- case 'i64': return HEAP32[((ptr)>>2)];
- case 'float': return HEAPF32[((ptr)>>2)];
- case 'double': return HEAPF64[((ptr)>>3)];
- default: abort('invalid type for getValue: ' + type);
- }
- return null;
-}
-
-
-
-
-
-// Wasm globals
-
-var wasmMemory;
-
-// Potentially used for direct table calls.
-var wasmTable;
-
-
//========================================
// Runtime essentials
//========================================
-// whether we are quitting the application. no code should run after this.
-// set in exit() and abort()
-var ABORT = false;
-
-// set by exit() and abort(). Passed to 'onExit' handler.
-// NOTE: This is also used as the process return code code in shell environments
-// but only when noExitRuntime is false.
+var ABORT = 0; // whether we are quitting the application. no code should run after this. set in exit() and abort()
var EXITSTATUS = 0;
/** @type {function(*, string=)} */
@@ -601,6 +414,8 @@ function assert(condition, text) {
}
}
+var globalScope = this;
+
// Returns the C function with a specified identifier (for C++, you need to do manual name mangling)
function getCFunc(ident) {
var func = Module['_' + ident]; // closure exported function
@@ -608,29 +423,44 @@ function getCFunc(ident) {
return func;
}
+var JSfuncs = {
+ // Helpers for cwrap -- it can't refer to Runtime directly because it might
+ // be renamed by closure, instead it calls JSfuncs['stackSave'].body to find
+ // out what the minified function name is.
+ 'stackSave': function() {
+ stackSave()
+ },
+ 'stackRestore': function() {
+ stackRestore()
+ },
+ // type conversion from js to c
+ 'arrayToC' : function(arr) {
+ var ret = stackAlloc(arr.length);
+ writeArrayToMemory(arr, ret);
+ return ret;
+ },
+ 'stringToC' : function(str) {
+ var ret = 0;
+ if (str !== null && str !== undefined && str !== 0) { // null string
+ // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0'
+ var len = (str.length << 2) + 1;
+ ret = stackAlloc(len);
+ stringToUTF8(str, ret, len);
+ }
+ return ret;
+ }
+};
+
+// For fast lookup of conversion functions
+var toC = {
+ 'string': JSfuncs['stringToC'], 'array': JSfuncs['arrayToC']
+};
+
+
// C calling interface.
function ccall(ident, returnType, argTypes, args, opts) {
- // For fast lookup of conversion functions
- var toC = {
- 'string': function(str) {
- var ret = 0;
- if (str !== null && str !== undefined && str !== 0) { // null string
- // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0'
- var len = (str.length << 2) + 1;
- ret = stackAlloc(len);
- stringToUTF8(str, ret, len);
- }
- return ret;
- },
- 'array': function(arr) {
- var ret = stackAlloc(arr.length);
- writeArrayToMemory(arr, ret);
- return ret;
- }
- };
-
function convertReturnValue(ret) {
- if (returnType === 'string') return UTF8ToString(ret);
+ if (returnType === 'string') return Pointer_stringify(ret);
if (returnType === 'boolean') return Boolean(ret);
return ret;
}
@@ -669,10 +499,44 @@ function cwrap(ident, returnType, argTypes, opts) {
}
}
+/** @type {function(number, number, string, boolean=)} */
+function setValue(ptr, value, type, noSafe) {
+ type = type || 'i8';
+ if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
+ switch(type) {
+ case 'i1': HEAP8[((ptr)>>0)]=value; break;
+ case 'i8': HEAP8[((ptr)>>0)]=value; break;
+ case 'i16': HEAP16[((ptr)>>1)]=value; break;
+ case 'i32': HEAP32[((ptr)>>2)]=value; break;
+ case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math_abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? ((Math_min((+(Math_floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break;
+ case 'float': HEAPF32[((ptr)>>2)]=value; break;
+ case 'double': HEAPF64[((ptr)>>3)]=value; break;
+ default: abort('invalid type for setValue: ' + type);
+ }
+}
+
+/** @type {function(number, string, boolean=)} */
+function getValue(ptr, type, noSafe) {
+ type = type || 'i8';
+ if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
+ switch(type) {
+ case 'i1': return HEAP8[((ptr)>>0)];
+ case 'i8': return HEAP8[((ptr)>>0)];
+ case 'i16': return HEAP16[((ptr)>>1)];
+ case 'i32': return HEAP32[((ptr)>>2)];
+ case 'i64': return HEAP32[((ptr)>>2)];
+ case 'float': return HEAPF32[((ptr)>>2)];
+ case 'double': return HEAPF64[((ptr)>>3)];
+ default: abort('invalid type for getValue: ' + type);
+ }
+ return null;
+}
+
var ALLOC_NORMAL = 0; // Tries to use _malloc()
var ALLOC_STACK = 1; // Lives for the duration of the current function call
-var ALLOC_DYNAMIC = 2; // Cannot be freed except through sbrk
-var ALLOC_NONE = 3; // Do not allocate
+var ALLOC_STATIC = 2; // Cannot be freed
+var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk
+var ALLOC_NONE = 4; // Do not allocate
// allocate(): This is for internal use. You can use it yourself as well, but the interface
// is a little tricky (see docs right below). The reason is that it is optimized
@@ -704,9 +568,7 @@ function allocate(slab, types, allocator, ptr) {
if (allocator == ALLOC_NONE) {
ret = ptr;
} else {
- ret = [_malloc,
- stackAlloc,
- dynamicAlloc][allocator](Math.max(size, singleType ? 1 : types.length));
+ ret = [typeof _malloc === 'function' ? _malloc : staticAlloc, stackAlloc, staticAlloc, dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length));
}
if (zeroinit) {
@@ -760,16 +622,41 @@ function allocate(slab, types, allocator, ptr) {
// Allocate memory during any stage of startup - static memory early on, dynamic memory later, malloc when ready
function getMemory(size) {
+ if (!staticSealed) return staticAlloc(size);
if (!runtimeInitialized) return dynamicAlloc(size);
return _malloc(size);
}
-
-
-
/** @type {function(number, number=)} */
function Pointer_stringify(ptr, length) {
- abort("this function has been removed - you should use UTF8ToString(ptr, maxBytesToRead) instead!");
+ if (length === 0 || !ptr) return '';
+ // Find the length, and check for UTF while doing so
+ var hasUtf = 0;
+ var t;
+ var i = 0;
+ while (1) {
+ t = HEAPU8[(((ptr)+(i))>>0)];
+ hasUtf |= t;
+ if (t == 0 && !length) break;
+ i++;
+ if (length && i == length) break;
+ }
+ if (!length) length = i;
+
+ var ret = '';
+
+ if (hasUtf < 128) {
+ var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack
+ var curr;
+ while (length > 0) {
+ curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK)));
+ ret = ret ? ret + curr : curr;
+ ptr += MAX_CHUNK;
+ length -= MAX_CHUNK;
+ }
+ return ret;
+ }
+ return UTF8ToString(ptr);
}
// Given a pointer 'ptr' to a null-terminated ASCII-encoded string in the emscripten HEAP, returns
@@ -778,7 +665,7 @@ function Pointer_stringify(ptr, length) {
function AsciiToString(ptr) {
var str = '';
while (1) {
- var ch = HEAPU8[((ptr++)>>0)];
+ var ch = HEAP8[((ptr++)>>0)];
if (!ch) return str;
str += String.fromCharCode(ch);
}
@@ -791,46 +678,46 @@ function stringToAscii(str, outPtr) {
return writeAsciiToMemory(str, outPtr, false);
}
-
// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the given array that contains uint8 values, returns
// a copy of that string as a Javascript String object.
var UTF8Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf8') : undefined;
-
-/**
- * @param {number} idx
- * @param {number=} maxBytesToRead
- * @return {string}
- */
-function UTF8ArrayToString(u8Array, idx, maxBytesToRead) {
- var endIdx = idx + maxBytesToRead;
+function UTF8ArrayToString(u8Array, idx) {
var endPtr = idx;
// TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself.
// Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage.
- // (As a tiny code save trick, compare endPtr against endIdx using a negation, so that undefined means Infinity)
- while (u8Array[endPtr] && !(endPtr >= endIdx)) ++endPtr;
+ while (u8Array[endPtr]) ++endPtr;
if (endPtr - idx > 16 && u8Array.subarray && UTF8Decoder) {
return UTF8Decoder.decode(u8Array.subarray(idx, endPtr));
} else {
+ var u0, u1, u2, u3, u4, u5;
+
var str = '';
- // If building with TextDecoder, we have already computed the string length above, so test loop end condition against that
- while (idx < endPtr) {
- // For UTF8 byte structure, see:
- // http://en.wikipedia.org/wiki/UTF-8#Description
- // https://www.ietf.org/rfc/rfc2279.txt
- // https://tools.ietf.org/html/rfc3629
- var u0 = u8Array[idx++];
+ while (1) {
+ // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629
+ u0 = u8Array[idx++];
+ if (!u0) return str;
if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }
- var u1 = u8Array[idx++] & 63;
+ u1 = u8Array[idx++] & 63;
if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }
- var u2 = u8Array[idx++] & 63;
+ u2 = u8Array[idx++] & 63;
if ((u0 & 0xF0) == 0xE0) {
u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
} else {
- u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (u8Array[idx++] & 63);
+ u3 = u8Array[idx++] & 63;
+ if ((u0 & 0xF8) == 0xF0) {
+ u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | u3;
+ } else {
+ u4 = u8Array[idx++] & 63;
+ if ((u0 & 0xFC) == 0xF8) {
+ u0 = ((u0 & 3) << 24) | (u1 << 18) | (u2 << 12) | (u3 << 6) | u4;
+ } else {
+ u5 = u8Array[idx++] & 63;
+ u0 = ((u0 & 1) << 30) | (u1 << 24) | (u2 << 18) | (u3 << 12) | (u4 << 6) | u5;
+ }
+ }
}
-
if (u0 < 0x10000) {
str += String.fromCharCode(u0);
} else {
@@ -839,26 +726,13 @@ function UTF8ArrayToString(u8Array, idx, maxBytesToRead) {
}
}
}
- return str;
}
-// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns a
-// copy of that string as a Javascript String object.
-// maxBytesToRead: an optional length that specifies the maximum number of bytes to read. You can omit
-// this parameter to scan the string until the first \0 byte. If maxBytesToRead is
-// passed, and the string at [ptr, ptr+maxBytesToReadr[ contains a null byte in the
-// middle, then the string will cut short at that byte index (i.e. maxBytesToRead will
-// not produce a string of exact length [ptr, ptr+maxBytesToRead[)
-// N.B. mixing frequent uses of UTF8ToString() with and without maxBytesToRead may
-// throw JS JIT optimizations off, so it is worth to consider consistently using one
-// style or the other.
-/**
- * @param {number} ptr
- * @param {number=} maxBytesToRead
- * @return {string}
- */
-function UTF8ToString(ptr, maxBytesToRead) {
- return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : '';
+// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns
+// a copy of that string as a Javascript String object.
+
+function UTF8ToString(ptr) {
+ return UTF8ArrayToString(HEAPU8,ptr);
}
// Copies the given Javascript String object 'str' to the given byte array at address 'outIdx',
@@ -901,12 +775,27 @@ function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) {
outU8Array[outIdx++] = 0xE0 | (u >> 12);
outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
outU8Array[outIdx++] = 0x80 | (u & 63);
- } else {
+ } else if (u <= 0x1FFFFF) {
if (outIdx + 3 >= endIdx) break;
outU8Array[outIdx++] = 0xF0 | (u >> 18);
outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63);
outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
outU8Array[outIdx++] = 0x80 | (u & 63);
+ } else if (u <= 0x3FFFFFF) {
+ if (outIdx + 4 >= endIdx) break;
+ outU8Array[outIdx++] = 0xF8 | (u >> 24);
+ outU8Array[outIdx++] = 0x80 | ((u >> 18) & 63);
+ outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63);
+ outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
+ outU8Array[outIdx++] = 0x80 | (u & 63);
+ } else {
+ if (outIdx + 5 >= endIdx) break;
+ outU8Array[outIdx++] = 0xFC | (u >> 30);
+ outU8Array[outIdx++] = 0x80 | ((u >> 24) & 63);
+ outU8Array[outIdx++] = 0x80 | ((u >> 18) & 63);
+ outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63);
+ outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
+ outU8Array[outIdx++] = 0x80 | (u & 63);
}
}
// Null-terminate the pointer to the buffer.
@@ -924,6 +813,7 @@ function stringToUTF8(str, outPtr, maxBytesToWrite) {
}
// Returns the number of bytes the given Javascript string takes if encoded as a UTF8 byte array, EXCLUDING the null terminator byte.
+
function lengthBytesUTF8(str) {
var len = 0;
for (var i = 0; i < str.length; ++i) {
@@ -931,15 +821,23 @@ function lengthBytesUTF8(str) {
// See http://unicode.org/faq/utf_bom.html#utf16-3
var u = str.charCodeAt(i); // possibly a lead surrogate
if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF);
- if (u <= 0x7F) ++len;
- else if (u <= 0x7FF) len += 2;
- else if (u <= 0xFFFF) len += 3;
- else len += 4;
+ if (u <= 0x7F) {
+ ++len;
+ } else if (u <= 0x7FF) {
+ len += 2;
+ } else if (u <= 0xFFFF) {
+ len += 3;
+ } else if (u <= 0x1FFFFF) {
+ len += 4;
+ } else if (u <= 0x3FFFFFF) {
+ len += 5;
+ } else {
+ len += 6;
+ }
}
return len;
}
-
// Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns
// a copy of that string as a Javascript String object.
@@ -1093,42 +991,6 @@ function allocateUTF8OnStack(str) {
return ret;
}
-// Deprecated: This function should not be called because it is unsafe and does not provide
-// a maximum length limit of how many bytes it is allowed to write. Prefer calling the
-// function stringToUTF8Array() instead, which takes in a maximum length that can be used
-// to be secure from out of bounds writes.
-/** @deprecated */
-function writeStringToMemory(string, buffer, dontAddNull) {
- warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!');
-
- var /** @type {number} */ lastChar, /** @type {number} */ end;
- if (dontAddNull) {
- // stringToUTF8Array always appends null. If we don't want to do that, remember the
- // character that existed at the location where the null will be placed, and restore
- // that after the write (below).
- end = buffer + lengthBytesUTF8(string);
- lastChar = HEAP8[end];
- }
- stringToUTF8(string, buffer, Infinity);
- if (dontAddNull) HEAP8[end] = lastChar; // Restore the value under the null character.
-}
-
-function writeArrayToMemory(array, buffer) {
- HEAP8.set(array, buffer);
-}
-
-function writeAsciiToMemory(str, buffer, dontAddNull) {
- for (var i = 0; i < str.length; ++i) {
- HEAP8[((buffer++)>>0)]=str.charCodeAt(i);
- }
- // Null-terminate the pointer to the HEAP.
- if (!dontAddNull) HEAP8[((buffer)>>0)]=0;
-}
-
-
-
-
-
function demangle(func) {
return func;
}
@@ -1139,7 +1001,7 @@ function demangleAll(text) {
return text.replace(regex,
function(x) {
var y = demangle(x);
- return x === y ? x : (y + ' [' + x + ']');
+ return x === y ? x : (x + ' [' + y + ']');
});
}
@@ -1166,13 +1028,12 @@ function stackTrace() {
return demangleAll(js);
}
-
-
// Memory management
var PAGE_SIZE = 16384;
var WASM_PAGE_SIZE = 65536;
var ASMJS_PAGE_SIZE = 16777216;
+var MIN_TOTAL_MEMORY = 16777216;
function alignUp(x, multiple) {
if (x % multiple > 0) {
@@ -1201,6 +1062,10 @@ var HEAP,
/** @type {Float64Array} */
HEAPF64;
+function updateGlobalBuffer(buf) {
+ Module['buffer'] = buffer = buf;
+}
+
function updateGlobalBufferViews() {
Module['HEAP8'] = HEAP8 = new Int8Array(buffer);
Module['HEAP16'] = HEAP16 = new Int16Array(buffer);
@@ -1212,53 +1077,116 @@ function updateGlobalBufferViews() {
Module['HEAPF64'] = HEAPF64 = new Float64Array(buffer);
}
+var STATIC_BASE, STATICTOP, staticSealed; // static area
+var STACK_BASE, STACKTOP, STACK_MAX; // stack area
+var DYNAMIC_BASE, DYNAMICTOP_PTR; // dynamic area handled by sbrk
-var STATIC_BASE = 1024,
- STACK_BASE = 127296,
- STACKTOP = STACK_BASE,
- STACK_MAX = 5370176,
- DYNAMIC_BASE = 5370176,
- DYNAMICTOP_PTR = 127264;
+ STATIC_BASE = STATICTOP = STACK_BASE = STACKTOP = STACK_MAX = DYNAMIC_BASE = DYNAMICTOP_PTR = 0;
+ staticSealed = false;
-var TOTAL_STACK = 5242880;
+function abortOnCannotGrowMemory() {
+ abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ');
+}
-var INITIAL_TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 134217728;
-if (INITIAL_TOTAL_MEMORY < TOTAL_STACK) err('TOTAL_MEMORY should be larger than TOTAL_STACK, was ' + INITIAL_TOTAL_MEMORY + '! (TOTAL_STACK=' + TOTAL_STACK + ')');
+if (!Module['reallocBuffer']) Module['reallocBuffer'] = function(size) {
+ var ret;
+ try {
+ if (ArrayBuffer.transfer) {
+ ret = ArrayBuffer.transfer(buffer, size);
+ } else {
+ var oldHEAP8 = HEAP8;
+ ret = new ArrayBuffer(size);
+ var temp = new Int8Array(ret);
+ temp.set(oldHEAP8);
+ }
+ } catch(e) {
+ return false;
+ }
+ var success = _emscripten_replace_memory(ret);
+ if (!success) return false;
+ return ret;
+};
+
+function enlargeMemory() {
+ // TOTAL_MEMORY is the current size of the actual array, and DYNAMICTOP is the new top.
+
+
+ var PAGE_MULTIPLE = Module["usingWasm"] ? WASM_PAGE_SIZE : ASMJS_PAGE_SIZE; // In wasm, heap size must be a multiple of 64KB. In asm.js, they need to be multiples of 16MB.
+ var LIMIT = 2147483648 - PAGE_MULTIPLE; // We can do one page short of 2GB as theoretical maximum.
+
+ if (HEAP32[DYNAMICTOP_PTR>>2] > LIMIT) {
+ return false;
+ }
+
+ var OLD_TOTAL_MEMORY = TOTAL_MEMORY;
+ TOTAL_MEMORY = Math.max(TOTAL_MEMORY, MIN_TOTAL_MEMORY); // So the loop below will not be infinite, and minimum asm.js memory size is 16MB.
+
+ while (TOTAL_MEMORY < HEAP32[DYNAMICTOP_PTR>>2]) { // Keep incrementing the heap size as long as it's less than what is requested.
+ if (TOTAL_MEMORY <= 536870912) {
+ TOTAL_MEMORY = alignUp(2 * TOTAL_MEMORY, PAGE_MULTIPLE); // Simple heuristic: double until 1GB...
+ } else {
+ // ..., but after that, add smaller increments towards 2GB, which we cannot reach
+ TOTAL_MEMORY = Math.min(alignUp((3 * TOTAL_MEMORY + 2147483648) / 4, PAGE_MULTIPLE), LIMIT);
+ }
+ }
+
+
+ var replacement = Module['reallocBuffer'](TOTAL_MEMORY);
+ if (!replacement || replacement.byteLength != TOTAL_MEMORY) {
+ // restore the state to before this call, we failed
+ TOTAL_MEMORY = OLD_TOTAL_MEMORY;
+ return false;
+ }
+
+ // everything worked
+
+ updateGlobalBuffer(replacement);
+ updateGlobalBufferViews();
+
+
+
+ return true;
+}
+
+var byteLength;
+try {
+ byteLength = Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, 'byteLength').get);
+ byteLength(new ArrayBuffer(4)); // can fail on older ie
+} catch(e) { // can fail on older node/v8
+ byteLength = function(buffer) { return buffer.byteLength; };
+}
+
+var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880;
+var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 536870912;
+if (TOTAL_MEMORY < TOTAL_STACK) err('TOTAL_MEMORY should be larger than TOTAL_STACK, was ' + TOTAL_MEMORY + '! (TOTAL_STACK=' + TOTAL_STACK + ')');
// Initialize the runtime's memory
-
-
-
- if (Module['wasmMemory']) {
- wasmMemory = Module['wasmMemory'];
- } else {
- wasmMemory = new WebAssembly.Memory({
- 'initial': INITIAL_TOTAL_MEMORY / WASM_PAGE_SIZE
- });
+// Use a provided buffer, if there is one, or else allocate a new one
+if (Module['buffer']) {
+ buffer = Module['buffer'];
+} else {
+ // Use a WebAssembly memory where available
+ if (typeof WebAssembly === 'object' && typeof WebAssembly.Memory === 'function') {
+ Module['wasmMemory'] = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE });
+ buffer = Module['wasmMemory'].buffer;
+ } else
+ {
+ buffer = new ArrayBuffer(TOTAL_MEMORY);
}
-
-
-if (wasmMemory) {
- buffer = wasmMemory.buffer;
+ Module['buffer'] = buffer;
}
-
-// If the user provides an incorrect length, just use that length instead rather than providing the user to
-// specifically provide the memory length with Module['TOTAL_MEMORY'].
-INITIAL_TOTAL_MEMORY = buffer.byteLength;
updateGlobalBufferViews();
-HEAP32[DYNAMICTOP_PTR>>2] = DYNAMIC_BASE;
-
-
-
-
+function getTotalMemory() {
+ return TOTAL_MEMORY;
+}
// Endianness check (note: assumes compiler arch was little-endian)
@@ -1303,18 +1231,18 @@ function preRun() {
callRuntimeCallbacks(__ATPRERUN__);
}
-function initRuntime() {
+function ensureInitRuntime() {
+ if (runtimeInitialized) return;
runtimeInitialized = true;
-
callRuntimeCallbacks(__ATINIT__);
}
function preMain() {
-
callRuntimeCallbacks(__ATMAIN__);
}
function exitRuntime() {
+ callRuntimeCallbacks(__ATEXIT__);
runtimeExited = true;
}
@@ -1342,12 +1270,45 @@ function addOnPreMain(cb) {
}
function addOnExit(cb) {
+ __ATEXIT__.unshift(cb);
}
function addOnPostRun(cb) {
__ATPOSTRUN__.unshift(cb);
}
+// Deprecated: This function should not be called because it is unsafe and does not provide
+// a maximum length limit of how many bytes it is allowed to write. Prefer calling the
+// function stringToUTF8Array() instead, which takes in a maximum length that can be used
+// to be secure from out of bounds writes.
+/** @deprecated */
+function writeStringToMemory(string, buffer, dontAddNull) {
+ warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!');
+
+ var /** @type {number} */ lastChar, /** @type {number} */ end;
+ if (dontAddNull) {
+ // stringToUTF8Array always appends null. If we don't want to do that, remember the
+ // character that existed at the location where the null will be placed, and restore
+ // that after the write (below).
+ end = buffer + lengthBytesUTF8(string);
+ lastChar = HEAP8[end];
+ }
+ stringToUTF8(string, buffer, Infinity);
+ if (dontAddNull) HEAP8[end] = lastChar; // Restore the value under the null character.
+}
+
+function writeArrayToMemory(array, buffer) {
+ HEAP8.set(array, buffer);
+}
+
+function writeAsciiToMemory(str, buffer, dontAddNull) {
+ for (var i = 0; i < str.length; ++i) {
+ HEAP8[((buffer++)>>0)]=str.charCodeAt(i);
+ }
+ // Null-terminate the pointer to the HEAP.
+ if (!dontAddNull) HEAP8[((buffer)>>0)]=0;
+}
+
function unSign(value, bits, ignore) {
if (value >= 0) {
return value;
@@ -1370,7 +1331,6 @@ function reSign(value, bits, ignore) {
}
-
var Math_abs = Math.abs;
var Math_cos = Math.cos;
var Math_sin = Math.sin;
@@ -1393,12 +1353,10 @@ var Math_max = Math.max;
var Math_clz32 = Math.clz32;
var Math_trunc = Math.trunc;
-
-
// A counter of dependencies for calling run(). If we need to
// do asynchronous work before running, increment this and
// decrement it. Incrementing must happen in a place like
-// Module.preRun (used by emcc to add file preloading).
+// PRE_RUN_ADDITIONS (used by emcc to add file preloading).
// Note that you can add dependencies in preRun, even though
// it happens right before run - run will be postponed until
// the dependencies are met.
@@ -1439,6 +1397,7 @@ Module["preloadedImages"] = {}; // maps url to image data
Module["preloadedAudios"] = {}; // maps url to audio data
+
var memoryInitializer = null;
@@ -1446,11 +1405,6 @@ var memoryInitializer = null;
-// Copyright 2017 The Emscripten Authors. All rights reserved.
-// Emscripten is available under two separate licenses, the MIT license and the
-// University of Illinois/NCSA Open Source License. Both these licenses can be
-// found in the LICENSE file.
-
// Prefix of data URIs emitted by SINGLE_FILE and related options.
var dataURIPrefix = 'data:application/octet-stream;base64,';
@@ -1464,162 +1418,276 @@ function isDataURI(filename) {
-var wasmBinaryFile = 'MpqCmp.wasm';
-if (!isDataURI(wasmBinaryFile)) {
- wasmBinaryFile = locateFile(wasmBinaryFile);
-}
+function integrateWasmJS() {
+ // wasm.js has several methods for creating the compiled code module here:
+ // * 'native-wasm' : use native WebAssembly support in the browser
+ // * 'interpret-s-expr': load s-expression code from a .wast and interpret
+ // * 'interpret-binary': load binary wasm and interpret
+ // * 'interpret-asm2wasm': load asm.js code, translate to wasm, and interpret
+ // * 'asmjs': no wasm, just load the asm.js code and use that (good for testing)
+ // The method is set at compile time (BINARYEN_METHOD)
+ // The method can be a comma-separated list, in which case, we will try the
+ // options one by one. Some of them can fail gracefully, and then we can try
+ // the next.
-function getBinary() {
- try {
- if (Module['wasmBinary']) {
- return new Uint8Array(Module['wasmBinary']);
- }
- if (readBinary) {
- return readBinary(wasmBinaryFile);
- } else {
- throw "both async and sync fetching of the wasm failed";
- }
- }
- catch (err) {
- abort(err);
- }
-}
+ // inputs
-function getBinaryPromise() {
- // if we don't have the binary yet, and have the Fetch api, use that
- // in some environments, like Electron's render process, Fetch api may be present, but have a different context than expected, let's only use it on the Web
- if (!Module['wasmBinary'] && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && typeof fetch === 'function') {
- return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) {
- if (!response['ok']) {
- throw "failed to load wasm binary file at '" + wasmBinaryFile + "'";
+ var method = 'native-wasm';
+
+ var wasmTextFile = 'MpqCmp.wast';
+ var wasmBinaryFile = 'MpqCmp.wasm';
+ var asmjsCodeFile = 'MpqCmp.temp.asm.js';
+
+ if (!isDataURI(wasmTextFile)) {
+ wasmTextFile = locateFile(wasmTextFile);
+ }
+ if (!isDataURI(wasmBinaryFile)) {
+ wasmBinaryFile = locateFile(wasmBinaryFile);
+ }
+ if (!isDataURI(asmjsCodeFile)) {
+ asmjsCodeFile = locateFile(asmjsCodeFile);
+ }
+
+ // utilities
+
+ var wasmPageSize = 64*1024;
+
+ var info = {
+ 'global': null,
+ 'env': null,
+ 'asm2wasm': asm2wasmImports,
+ 'parent': Module // Module inside wasm-js.cpp refers to wasm-js.cpp; this allows access to the outside program.
+ };
+
+ var exports = null;
+
+
+ function mergeMemory(newBuffer) {
+ // The wasm instance creates its memory. But static init code might have written to
+ // buffer already, including the mem init file, and we must copy it over in a proper merge.
+ // TODO: avoid this copy, by avoiding such static init writes
+ // TODO: in shorter term, just copy up to the last static init write
+ var oldBuffer = Module['buffer'];
+ if (newBuffer.byteLength < oldBuffer.byteLength) {
+ err('the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here');
+ }
+ var oldView = new Int8Array(oldBuffer);
+ var newView = new Int8Array(newBuffer);
+
+
+ newView.set(oldView);
+ updateGlobalBuffer(newBuffer);
+ updateGlobalBufferViews();
+ }
+
+ function fixImports(imports) {
+ return imports;
+ }
+
+ function getBinary() {
+ try {
+ if (Module['wasmBinary']) {
+ return new Uint8Array(Module['wasmBinary']);
}
- return response['arrayBuffer']();
- }).catch(function () {
- return getBinary();
+ if (Module['readBinary']) {
+ return Module['readBinary'](wasmBinaryFile);
+ } else {
+ throw "both async and sync fetching of the wasm failed";
+ }
+ }
+ catch (err) {
+ abort(err);
+ }
+ }
+
+ function getBinaryPromise() {
+ // if we don't have the binary yet, and have the Fetch api, use that
+ // in some environments, like Electron's render process, Fetch api may be present, but have a different context than expected, let's only use it on the Web
+ if (!Module['wasmBinary'] && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && typeof fetch === 'function') {
+ return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) {
+ if (!response['ok']) {
+ throw "failed to load wasm binary file at '" + wasmBinaryFile + "'";
+ }
+ return response['arrayBuffer']();
+ }).catch(function () {
+ return getBinary();
+ });
+ }
+ // Otherwise, getBinary should be able to get it synchronously
+ return new Promise(function(resolve, reject) {
+ resolve(getBinary());
});
}
- // Otherwise, getBinary should be able to get it synchronously
- return new Promise(function(resolve, reject) {
- resolve(getBinary());
- });
-}
+
+ // do-method functions
-
-// Create the wasm instance.
-// Receives the wasm imports, returns the exports.
-function createWasm(env) {
-
- // prepare imports
- var info = {
- 'env': env
- ,
- 'global': {
+ function doNativeWasm(global, env, providedBuffer) {
+ if (typeof WebAssembly !== 'object') {
+ err('no native wasm support detected');
+ return false;
+ }
+ // prepare memory import
+ if (!(Module['wasmMemory'] instanceof WebAssembly.Memory)) {
+ err('no native wasm Memory in use');
+ return false;
+ }
+ env['memory'] = Module['wasmMemory'];
+ // Load the wasm module and create an instance of using native support in the JS engine.
+ info['global'] = {
'NaN': NaN,
'Infinity': Infinity
- },
- 'global.Math': Math,
- 'asm2wasm': asm2wasmImports
- };
- // Load the wasm module and create an instance of using native support in the JS engine.
- // handle a generated wasm instance, receiving its exports and
- // performing other necessary setup
- function receiveInstance(instance, module) {
- var exports = instance.exports;
- Module['asm'] = exports;
- removeRunDependency('wasm-instantiate');
- }
- addRunDependency('wasm-instantiate');
+ };
+ info['global.Math'] = Math;
+ info['env'] = env;
+ // handle a generated wasm instance, receiving its exports and
+ // performing other necessary setup
+ function receiveInstance(instance, module) {
+ exports = instance.exports;
+ if (exports.memory) mergeMemory(exports.memory);
+ Module['asm'] = exports;
+ Module["usingWasm"] = true;
+ removeRunDependency('wasm-instantiate');
+ }
+ addRunDependency('wasm-instantiate');
+ // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
+ // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel
+ // to any other async startup actions they are performing.
+ if (Module['instantiateWasm']) {
+ try {
+ return Module['instantiateWasm'](info, receiveInstance);
+ } catch(e) {
+ err('Module.instantiateWasm callback failed with error: ' + e);
+ return false;
+ }
+ }
- function receiveInstantiatedSource(output) {
- // 'output' is a WebAssemblyInstantiatedSource object which has both the module and instance.
- // receiveInstance() will swap in the exports (to Module.asm) so they can be called
- // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line.
- // When the regression is fixed, can restore the above USE_PTHREADS-enabled path.
- receiveInstance(output['instance']);
- }
-
-
- function instantiateArrayBuffer(receiver) {
- return getBinaryPromise().then(function(binary) {
- return WebAssembly.instantiate(binary, info);
- }).then(receiver, function(reason) {
- err('failed to asynchronously prepare wasm: ' + reason);
- abort(reason);
- });
- }
-
- // Prefer streaming instantiation if available.
- function instantiateAsync() {
+ function receiveInstantiatedSource(output) {
+ // 'output' is a WebAssemblyInstantiatedSource object which has both the module and instance.
+ // receiveInstance() will swap in the exports (to Module.asm) so they can be called
+ receiveInstance(output['instance'], output['module']);
+ }
+ function instantiateArrayBuffer(receiver) {
+ getBinaryPromise().then(function(binary) {
+ return WebAssembly.instantiate(binary, info);
+ }).then(receiver).catch(function(reason) {
+ err('failed to asynchronously prepare wasm: ' + reason);
+ abort(reason);
+ });
+ }
+ // Prefer streaming instantiation if available.
if (!Module['wasmBinary'] &&
typeof WebAssembly.instantiateStreaming === 'function' &&
!isDataURI(wasmBinaryFile) &&
typeof fetch === 'function') {
- fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function (response) {
- return WebAssembly.instantiateStreaming(response, info)
- .then(receiveInstantiatedSource, function(reason) {
- // We expect the most common failure cause to be a bad MIME type for the binary,
- // in which case falling back to ArrayBuffer instantiation should work.
- err('wasm streaming compile failed: ' + reason);
- err('falling back to ArrayBuffer instantiation');
- instantiateArrayBuffer(receiveInstantiatedSource);
- });
- });
+ WebAssembly.instantiateStreaming(fetch(wasmBinaryFile, { credentials: 'same-origin' }), info)
+ .then(receiveInstantiatedSource)
+ .catch(function(reason) {
+ // We expect the most common failure cause to be a bad MIME type for the binary,
+ // in which case falling back to ArrayBuffer instantiation should work.
+ err('wasm streaming compile failed: ' + reason);
+ err('falling back to ArrayBuffer instantiation');
+ instantiateArrayBuffer(receiveInstantiatedSource);
+ });
} else {
- return instantiateArrayBuffer(receiveInstantiatedSource);
- }
- }
- // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
- // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel
- // to any other async startup actions they are performing.
- if (Module['instantiateWasm']) {
- try {
- var exports = Module['instantiateWasm'](info, receiveInstance);
- return exports;
- } catch(e) {
- err('Module.instantiateWasm callback failed with error: ' + e);
- return false;
+ instantiateArrayBuffer(receiveInstantiatedSource);
}
+ return {}; // no exports yet; we'll fill them in later
}
- instantiateAsync();
- return {}; // no exports yet; we'll fill them in later
+
+ // We may have a preloaded value in Module.asm, save it
+ Module['asmPreload'] = Module['asm'];
+
+ // Memory growth integration code
+
+ var asmjsReallocBuffer = Module['reallocBuffer'];
+
+ var wasmReallocBuffer = function(size) {
+ var PAGE_MULTIPLE = Module["usingWasm"] ? WASM_PAGE_SIZE : ASMJS_PAGE_SIZE; // In wasm, heap size must be a multiple of 64KB. In asm.js, they need to be multiples of 16MB.
+ size = alignUp(size, PAGE_MULTIPLE); // round up to wasm page size
+ var old = Module['buffer'];
+ var oldSize = old.byteLength;
+ if (Module["usingWasm"]) {
+ // native wasm support
+ try {
+ var result = Module['wasmMemory'].grow((size - oldSize) / wasmPageSize); // .grow() takes a delta compared to the previous size
+ if (result !== (-1 | 0)) {
+ // success in native wasm memory growth, get the buffer from the memory
+ return Module['buffer'] = Module['wasmMemory'].buffer;
+ } else {
+ return null;
+ }
+ } catch(e) {
+ return null;
+ }
+ }
+ };
+
+ Module['reallocBuffer'] = function(size) {
+ if (finalMethod === 'asmjs') {
+ return asmjsReallocBuffer(size);
+ } else {
+ return wasmReallocBuffer(size);
+ }
+ };
+
+ // we may try more than one; this is the final one, that worked and we are using
+ var finalMethod = '';
+
+ // Provide an "asm.js function" for the application, called to "link" the asm.js module. We instantiate
+ // the wasm module at that time, and it receives imports and provides exports and so forth, the app
+ // doesn't need to care that it is wasm or olyfilled wasm or asm.js.
+
+ Module['asm'] = function(global, env, providedBuffer) {
+ env = fixImports(env);
+
+ // import table
+ if (!env['table']) {
+ var TABLE_SIZE = Module['wasmTableSize'];
+ if (TABLE_SIZE === undefined) TABLE_SIZE = 1024; // works in binaryen interpreter at least
+ var MAX_TABLE_SIZE = Module['wasmMaxTableSize'];
+ if (typeof WebAssembly === 'object' && typeof WebAssembly.Table === 'function') {
+ if (MAX_TABLE_SIZE !== undefined) {
+ env['table'] = new WebAssembly.Table({ 'initial': TABLE_SIZE, 'maximum': MAX_TABLE_SIZE, 'element': 'anyfunc' });
+ } else {
+ env['table'] = new WebAssembly.Table({ 'initial': TABLE_SIZE, element: 'anyfunc' });
+ }
+ } else {
+ env['table'] = new Array(TABLE_SIZE); // works in binaryen interpreter at least
+ }
+ Module['wasmTable'] = env['table'];
+ }
+
+ if (!env['memoryBase']) {
+ env['memoryBase'] = Module['STATIC_BASE']; // tell the memory segments where to place themselves
+ }
+ if (!env['tableBase']) {
+ env['tableBase'] = 0; // table starts at 0 by default, in dynamic linking this will change
+ }
+
+ // try the methods. each should return the exports if it succeeded
+
+ var exports;
+ exports = doNativeWasm(global, env, providedBuffer);
+
+ assert(exports, 'no binaryen method succeeded.');
+
+
+ return exports;
+ };
+
+ var methodHandler = Module['asm']; // note our method handler, as we may modify Module['asm'] later
}
-// Provide an "asm.js function" for the application, called to "link" the asm.js module. We instantiate
-// the wasm module at that time, and it receives imports and provides exports and so forth, the app
-// doesn't need to care that it is wasm or asm.js.
-
-Module['asm'] = function(global, env, providedBuffer) {
- // memory was already allocated (so js could use the buffer)
- env['memory'] = wasmMemory
- ;
- // import table
- env['table'] = wasmTable = new WebAssembly.Table({
- 'initial': 402,
- 'maximum': 402,
- 'element': 'anyfunc'
- });
- // With the wasm backend __memory_base and __table_base and only needed for
- // relocatable output.
- env['__memory_base'] = 1024; // tell the memory segments where to place themselves
- // table starts at 0 by default (even in dynamic linking, for the main module)
- env['__table_base'] = 0;
-
- var exports = createWasm(env);
- return exports;
-};
-
-// Globals used by JS i64 conversions
-var tempDouble;
-var tempI64;
+integrateWasmJS();
// === Body ===
var ASM_CONSTS = [];
-function _do_error(err){ var end = HEAPU8.indexOf( 0, err ); var text = String.fromCharCode.apply(null, HEAPU8.subarray( err, end )); self.DApi.exit_error( text ); }
+function _do_error(err){ var end = HEAPU8.indexOf(0, err); var text = String.fromCharCode.apply(null, HEAPU8.subarray(err, end)); self.DApi.exit_error(text); }
function _do_progress(done,total){ self.DApi.progress(done, total); }
function _get_file_contents(ptr,offset,size){ self.DApi.get_file_contents(HEAPU8.subarray(ptr, ptr + size), offset); }
function _put_file_contents(ptr,offset,size){ self.DApi.put_file_contents(HEAPU8.subarray(ptr, ptr + size), offset); }
@@ -1627,8 +1695,10 @@ function _put_file_size(size){ self.DApi.put_file_size(size); }
-// STATICTOP = STATIC_BASE + 126272;
-/* global initializers */ /*__ATINIT__.push();*/
+STATIC_BASE = GLOBAL_BASE;
+
+STATICTOP = STATIC_BASE + 113200;
+/* global initializers */ __ATINIT__.push();
@@ -1636,123 +1706,118 @@ function _put_file_size(size){ self.DApi.put_file_size(size); }
+var STATIC_BUMP = 113200;
+Module["STATIC_BASE"] = STATIC_BASE;
+Module["STATIC_BUMP"] = STATIC_BUMP;
/* no memory initializer */
-var tempDoublePtr = 127280
+var tempDoublePtr = STATICTOP; STATICTOP += 16;
function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much
+
HEAP8[tempDoublePtr] = HEAP8[ptr];
+
HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];
+
HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];
+
HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];
+
}
function copyTempDouble(ptr) {
+
HEAP8[tempDoublePtr] = HEAP8[ptr];
+
HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];
+
HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];
+
HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];
+
HEAP8[tempDoublePtr+4] = HEAP8[ptr+4];
+
HEAP8[tempDoublePtr+5] = HEAP8[ptr+5];
+
HEAP8[tempDoublePtr+6] = HEAP8[ptr+6];
+
HEAP8[tempDoublePtr+7] = HEAP8[ptr+7];
+
}
// {{PRE_LIBRARY}}
function ___assert_fail(condition, filename, line, func) {
- abort('Assertion failed: ' + UTF8ToString(condition) + ', at: ' + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']);
+ abort('Assertion failed: ' + Pointer_stringify(condition) + ', at: ' + [filename ? Pointer_stringify(filename) : 'unknown filename', line, func ? Pointer_stringify(func) : 'unknown function']);
}
function ___cxa_allocate_exception(size) {
return _malloc(size);
}
-
- var ___exception_infos={};
-
- var ___exception_caught= [];
-
- function ___exception_addRef(ptr) {
- if (!ptr) return;
- var info = ___exception_infos[ptr];
- info.refcount++;
- }
-
- function ___exception_deAdjust(adjusted) {
- if (!adjusted || ___exception_infos[adjusted]) return adjusted;
- for (var key in ___exception_infos) {
- var ptr = +key; // the iteration key is a string, and if we throw this, it must be an integer as that is what we look for
- var adj = ___exception_infos[ptr].adjusted;
- var len = adj.length;
- for (var i = 0; i < len; i++) {
- if (adj[i] === adjusted) {
- return ptr;
- }
+ function ___cxa_find_matching_catch_2() {
+ return ___cxa_find_matching_catch.apply(null, arguments);
}
- }
- return adjusted;
- }function ___cxa_begin_catch(ptr) {
- var info = ___exception_infos[ptr];
- if (info && !info.caught) {
- info.caught = true;
- __ZSt18uncaught_exceptionv.uncaught_exceptions--;
- }
- if (info) info.rethrown = false;
- ___exception_caught.push(ptr);
- ___exception_addRef(___exception_deAdjust(ptr));
- return ptr;
- }
-
- var ___exception_last=0;
-
-
function ___cxa_free_exception(ptr) {
try {
return _free(ptr);
- } catch(e) {
- }
- }function ___exception_decRef(ptr) {
- if (!ptr) return;
- var info = ___exception_infos[ptr];
- info.refcount--;
- // A rethrown exception can reach refcount 0; it must not be discarded
- // Its next handler will clear the rethrown flag and addRef it, prior to
- // final decRef and destruction here
- if (info.refcount === 0 && !info.rethrown) {
- if (info.destructor) {
- Module['dynCall_vi'](info.destructor, ptr);
- }
- delete ___exception_infos[ptr];
- ___cxa_free_exception(ptr);
- }
- }
-
- function ___cxa_end_catch() {
- // Clear state flag.
- _setThrew(0);
- // Call destructor if one is registered then clear it.
- var ptr = ___exception_caught.pop();
- if (ptr) {
- ___exception_decRef(___exception_deAdjust(ptr));
- ___exception_last = 0; // XXX in decRef?
+ } catch(e) { // XXX FIXME
}
}
+ function __ZSt18uncaught_exceptionv() { // std::uncaught_exception()
+ return !!__ZSt18uncaught_exceptionv.uncaught_exception;
+ }
+
+
+ var EXCEPTIONS={last:0,caught:[],infos:{},deAdjust:function (adjusted) {
+ if (!adjusted || EXCEPTIONS.infos[adjusted]) return adjusted;
+ for (var key in EXCEPTIONS.infos) {
+ var ptr = +key; // the iteration key is a string, and if we throw this, it must be an integer as that is what we look for
+ var info = EXCEPTIONS.infos[ptr];
+ if (info.adjusted === adjusted) {
+ return ptr;
+ }
+ }
+ return adjusted;
+ },addRef:function (ptr) {
+ if (!ptr) return;
+ var info = EXCEPTIONS.infos[ptr];
+ info.refcount++;
+ },decRef:function (ptr) {
+ if (!ptr) return;
+ var info = EXCEPTIONS.infos[ptr];
+ assert(info.refcount > 0);
+ info.refcount--;
+ // A rethrown exception can reach refcount 0; it must not be discarded
+ // Its next handler will clear the rethrown flag and addRef it, prior to
+ // final decRef and destruction here
+ if (info.refcount === 0 && !info.rethrown) {
+ if (info.destructor) {
+ Module['dynCall_vi'](info.destructor, ptr);
+ }
+ delete EXCEPTIONS.infos[ptr];
+ ___cxa_free_exception(ptr);
+ }
+ },clearRef:function (ptr) {
+ if (!ptr) return;
+ var info = EXCEPTIONS.infos[ptr];
+ info.refcount = 0;
+ }};
function ___resumeException(ptr) {
- if (!___exception_last) { ___exception_last = ptr; }
+ if (!EXCEPTIONS.last) { EXCEPTIONS.last = ptr; }
throw ptr;
}function ___cxa_find_matching_catch() {
- var thrown = ___exception_last;
+ var thrown = EXCEPTIONS.last;
if (!thrown) {
// just pass through the null ptr
return ((setTempRet0(0),0)|0);
}
- var info = ___exception_infos[thrown];
+ var info = EXCEPTIONS.infos[thrown];
var throwntype = info.type;
if (!throwntype) {
// just pass through the thrown ptr
@@ -1760,19 +1825,19 @@ function copyTempDouble(ptr) {
}
var typeArray = Array.prototype.slice.call(arguments);
- var pointer = ___cxa_is_pointer_type(throwntype);
+ var pointer = Module['___cxa_is_pointer_type'](throwntype);
// can_catch receives a **, add indirection
- var buffer = 127248;
- HEAP32[((buffer)>>2)]=thrown;
- thrown = buffer;
+ if (!___cxa_find_matching_catch.buffer) ___cxa_find_matching_catch.buffer = _malloc(4);
+ HEAP32[((___cxa_find_matching_catch.buffer)>>2)]=thrown;
+ thrown = ___cxa_find_matching_catch.buffer;
// The different catch blocks are denoted by different types.
// Due to inheritance, those types may not precisely match the
// type of the thrown object. Find one which matches, and
// return the type of the catch block which should be called.
for (var i = 0; i < typeArray.length; i++) {
- if (typeArray[i] && ___cxa_can_catch(typeArray[i], throwntype, thrown)) {
+ if (typeArray[i] && Module['___cxa_can_catch'](typeArray[i], throwntype, thrown)) {
thrown = HEAP32[((thrown)>>2)]; // undo indirection
- info.adjusted.push(thrown);
+ info.adjusted = thrown;
return ((setTempRet0(typeArray[i]),thrown)|0);
}
}
@@ -1781,228 +1846,47 @@ function copyTempDouble(ptr) {
// typeinfo defined. Best-efforts match just in case.
thrown = HEAP32[((thrown)>>2)]; // undo indirection
return ((setTempRet0(throwntype),thrown)|0);
- }
- Module["___cxa_find_matching_catch"] = ___cxa_find_matching_catch;function ___cxa_find_matching_catch_2(a0,a1
- /*``*/) {
- return ___cxa_find_matching_catch(a0,a1);
- }
-
- function ___cxa_find_matching_catch_3(a0,a1,a2
- /*``*/) {
- return ___cxa_find_matching_catch(a0,a1,a2);
- }
-
-
- function ___cxa_pure_virtual() {
- ABORT = true;
- throw 'Pure virtual function called!';
- }
-
- function ___cxa_throw(ptr, type, destructor) {
- ___exception_infos[ptr] = {
+ }function ___cxa_throw(ptr, type, destructor) {
+ EXCEPTIONS.infos[ptr] = {
ptr: ptr,
- adjusted: [ptr],
+ adjusted: ptr,
type: type,
destructor: destructor,
refcount: 0,
caught: false,
rethrown: false
};
- ___exception_last = ptr;
+ EXCEPTIONS.last = ptr;
if (!("uncaught_exception" in __ZSt18uncaught_exceptionv)) {
- __ZSt18uncaught_exceptionv.uncaught_exceptions = 1;
+ __ZSt18uncaught_exceptionv.uncaught_exception = 1;
} else {
- __ZSt18uncaught_exceptionv.uncaught_exceptions++;
+ __ZSt18uncaught_exceptionv.uncaught_exception++;
}
throw ptr;
}
- function ___cxa_uncaught_exceptions() {
- return __ZSt18uncaught_exceptionv.uncaught_exceptions;
- }
-
function ___gxx_personality_v0() {
}
-
-
- var PATH={splitPath:function (filename) {
- var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
- return splitPathRe.exec(filename).slice(1);
- },normalizeArray:function (parts, allowAboveRoot) {
- // if the path tries to go above the root, `up` ends up > 0
- var up = 0;
- for (var i = parts.length - 1; i >= 0; i--) {
- var last = parts[i];
- if (last === '.') {
- parts.splice(i, 1);
- } else if (last === '..') {
- parts.splice(i, 1);
- up++;
- } else if (up) {
- parts.splice(i, 1);
- up--;
- }
- }
- // if the path is allowed to go above the root, restore leading ..s
- if (allowAboveRoot) {
- for (; up; up--) {
- parts.unshift('..');
- }
- }
- return parts;
- },normalize:function (path) {
- var isAbsolute = path.charAt(0) === '/',
- trailingSlash = path.substr(-1) === '/';
- // Normalize the path
- path = PATH.normalizeArray(path.split('/').filter(function(p) {
- return !!p;
- }), !isAbsolute).join('/');
- if (!path && !isAbsolute) {
- path = '.';
- }
- if (path && trailingSlash) {
- path += '/';
- }
- return (isAbsolute ? '/' : '') + path;
- },dirname:function (path) {
- var result = PATH.splitPath(path),
- root = result[0],
- dir = result[1];
- if (!root && !dir) {
- // No dirname whatsoever
- return '.';
- }
- if (dir) {
- // It has a dirname, strip trailing slash
- dir = dir.substr(0, dir.length - 1);
- }
- return root + dir;
- },basename:function (path) {
- // EMSCRIPTEN return '/'' for '/', not an empty string
- if (path === '/') return '/';
- var lastSlash = path.lastIndexOf('/');
- if (lastSlash === -1) return path;
- return path.substr(lastSlash+1);
- },extname:function (path) {
- return PATH.splitPath(path)[3];
- },join:function () {
- var paths = Array.prototype.slice.call(arguments, 0);
- return PATH.normalize(paths.join('/'));
- },join2:function (l, r) {
- return PATH.normalize(l + '/' + r);
- }};var SYSCALLS={buffers:[null,[],[]],printChar:function (stream, curr) {
- var buffer = SYSCALLS.buffers[stream];
- if (curr === 0 || curr === 10) {
- (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0));
- buffer.length = 0;
- } else {
- buffer.push(curr);
- }
- },varargs:0,get:function (varargs) {
- SYSCALLS.varargs += 4;
- var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)];
- return ret;
- },getStr:function () {
- var ret = UTF8ToString(SYSCALLS.get());
- return ret;
- },get64:function () {
- var low = SYSCALLS.get(), high = SYSCALLS.get();
- return low;
- },getZero:function () {
- SYSCALLS.get();
- }};function ___syscall140(which, varargs) {SYSCALLS.varargs = varargs;
- try {
- // llseek
- var stream = SYSCALLS.getStreamFromFD(), offset_high = SYSCALLS.get(), offset_low = SYSCALLS.get(), result = SYSCALLS.get(), whence = SYSCALLS.get();
- return 0;
- } catch (e) {
- if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
- return -e.errno;
- }
- }
-
-
- function flush_NO_FILESYSTEM() {
- // flush anything remaining in the buffers during shutdown
- var fflush = Module["_fflush"];
- if (fflush) fflush(0);
- var buffers = SYSCALLS.buffers;
- if (buffers[1].length) SYSCALLS.printChar(1, 10);
- if (buffers[2].length) SYSCALLS.printChar(2, 10);
- }function ___syscall146(which, varargs) {SYSCALLS.varargs = varargs;
- try {
- // writev
- // hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0
- var stream = SYSCALLS.get(), iov = SYSCALLS.get(), iovcnt = SYSCALLS.get();
- var ret = 0;
- for (var i = 0; i < iovcnt; i++) {
- var ptr = HEAP32[(((iov)+(i*8))>>2)];
- var len = HEAP32[(((iov)+(i*8 + 4))>>2)];
- for (var j = 0; j < len; j++) {
- SYSCALLS.printChar(stream, HEAPU8[ptr+j]);
- }
- ret += len;
- }
- return ret;
- } catch (e) {
- if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
- return -e.errno;
- }
- }
-
- function ___syscall54(which, varargs) {SYSCALLS.varargs = varargs;
- try {
- // ioctl
- return 0;
- } catch (e) {
- if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
- return -e.errno;
- }
- }
-
- function ___syscall6(which, varargs) {SYSCALLS.varargs = varargs;
- try {
- // close
- var stream = SYSCALLS.getStreamFromFD();
- return 0;
- } catch (e) {
- if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
- return -e.errno;
- }
- }
-
function _abort() {
Module['abort']();
}
- function _emscripten_get_heap_size() {
- return HEAP8.length;
- }
-
function _llvm_exp2_f32(x) {
return Math.pow(2, x);
- }function _llvm_exp2_f64(a0
- /*``*/) {
- return _llvm_exp2_f32(a0);
+ }function _llvm_exp2_f64() {
+ return _llvm_exp2_f32.apply(null, arguments)
}
- function _llvm_trap() {
- abort('trap!');
- }
-
function _emscripten_memcpy_big(dest, src, num) {
HEAPU8.set(HEAPU8.subarray(src, src+num), dest);
- }
-
-
-
-
+ return dest;
+ }
@@ -2010,80 +1894,20 @@ function copyTempDouble(ptr) {
function ___setErrNo(value) {
if (Module['___errno_location']) HEAP32[((Module['___errno_location']())>>2)]=value;
return value;
- }
-
-
- function abortOnCannotGrowMemory(requestedSize) {
- abort('OOM');
- }
-
- function emscripten_realloc_buffer(size) {
- var PAGE_MULTIPLE = 65536;
- size = alignUp(size, PAGE_MULTIPLE); // round up to wasm page size
- var oldSize = buffer.byteLength;
- // native wasm support
- // note that this is *not* threadsafe. multiple threads can call .grow(), and each
- // presents a delta, so in theory we may over-allocate here (e.g. if two threads
- // ask to grow from 256MB to 512MB, we get 2 requests to add +256MB, and may end
- // up growing to 768MB (even though we may have been able to make do with 512MB).
- // TODO: consider decreasing the step sizes in emscripten_resize_heap
- try {
- var result = wasmMemory.grow((size - oldSize) / 65536); // .grow() takes a delta compared to the previous size
- if (result !== (-1 | 0)) {
- // success in native wasm memory growth, get the buffer from the memory
- buffer = wasmMemory.buffer;
- return true;
- } else {
- return false;
- }
- } catch(e) {
- return false;
- }
- }function _emscripten_resize_heap(requestedSize) {
- var oldSize = _emscripten_get_heap_size();
- // With pthreads, races can happen (another thread might increase the size in between), so return a failure, and let the caller retry.
-
-
- var PAGE_MULTIPLE = 65536;
- var LIMIT = 2147483648 - PAGE_MULTIPLE; // We can do one page short of 2GB as theoretical maximum.
-
- if (requestedSize > LIMIT) {
- return false;
- }
-
- var MIN_TOTAL_MEMORY = 16777216;
- var newSize = Math.max(oldSize, MIN_TOTAL_MEMORY); // So the loop below will not be infinite, and minimum asm.js memory size is 16MB.
-
- // TODO: see realloc_buffer - for PTHREADS we may want to decrease these jumps
- while (newSize < requestedSize) { // Keep incrementing the heap size as long as it's less than what is requested.
- if (newSize <= 536870912) {
- newSize = alignUp(2 * newSize, PAGE_MULTIPLE); // Simple heuristic: double until 1GB...
- } else {
- // ..., but after that, add smaller increments towards 2GB, which we cannot reach
- newSize = Math.min(alignUp((3 * newSize + 2147483648) / 4, PAGE_MULTIPLE), LIMIT);
- }
-
- }
-
-
-
-
- if (!emscripten_realloc_buffer(newSize)) {
- return false;
- }
-
- updateGlobalBufferViews();
-
-
-
- return true;
}
-var ASSERTIONS = false;
+DYNAMICTOP_PTR = staticAlloc(4);
-// Copyright 2017 The Emscripten Authors. All rights reserved.
-// Emscripten is available under two separate licenses, the MIT license and the
-// University of Illinois/NCSA Open Source License. Both these licenses can be
-// found in the LICENSE file.
+STACK_BASE = STACKTOP = alignMemory(STATICTOP);
+
+STACK_MAX = STACK_BASE + TOTAL_STACK;
+
+DYNAMIC_BASE = alignMemory(STACK_MAX);
+
+HEAP32[DYNAMICTOP_PTR>>2] = DYNAMIC_BASE;
+
+staticSealed = true; // seal the static portion of memory
+
+var ASSERTIONS = false;
/** @type {function(string, boolean=, number=)} */
function intArrayFromString(stringy, dontAddNull, length) {
@@ -2110,358 +1934,222 @@ function intArrayToString(array) {
}
-// ASM_LIBRARY EXTERN PRIMITIVES: Int8Array,Int32Array
+Module['wasmTableSize'] = 163;
+
+Module['wasmMaxTableSize'] = 163;
function invoke_ii(index,a1) {
var sp = stackSave();
try {
- return dynCall_ii(index,a1);
+ return Module["dynCall_ii"](index,a1);
} catch(e) {
stackRestore(sp);
- if (e !== e+0 && e !== 'longjmp') throw e;
- _setThrew(1, 0);
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
}
}
function invoke_iii(index,a1,a2) {
var sp = stackSave();
try {
- return dynCall_iii(index,a1,a2);
+ return Module["dynCall_iii"](index,a1,a2);
} catch(e) {
stackRestore(sp);
- if (e !== e+0 && e !== 'longjmp') throw e;
- _setThrew(1, 0);
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
}
}
function invoke_iiii(index,a1,a2,a3) {
var sp = stackSave();
try {
- return dynCall_iiii(index,a1,a2,a3);
+ return Module["dynCall_iiii"](index,a1,a2,a3);
} catch(e) {
stackRestore(sp);
- if (e !== e+0 && e !== 'longjmp') throw e;
- _setThrew(1, 0);
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
}
}
function invoke_iiiii(index,a1,a2,a3,a4) {
var sp = stackSave();
try {
- return dynCall_iiiii(index,a1,a2,a3,a4);
+ return Module["dynCall_iiiii"](index,a1,a2,a3,a4);
} catch(e) {
stackRestore(sp);
- if (e !== e+0 && e !== 'longjmp') throw e;
- _setThrew(1, 0);
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
}
}
function invoke_iiiiii(index,a1,a2,a3,a4,a5) {
var sp = stackSave();
try {
- return dynCall_iiiiii(index,a1,a2,a3,a4,a5);
+ return Module["dynCall_iiiiii"](index,a1,a2,a3,a4,a5);
} catch(e) {
stackRestore(sp);
- if (e !== e+0 && e !== 'longjmp') throw e;
- _setThrew(1, 0);
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
}
}
function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6) {
var sp = stackSave();
try {
- return dynCall_iiiiiii(index,a1,a2,a3,a4,a5,a6);
+ return Module["dynCall_iiiiiii"](index,a1,a2,a3,a4,a5,a6);
} catch(e) {
stackRestore(sp);
- if (e !== e+0 && e !== 'longjmp') throw e;
- _setThrew(1, 0);
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
}
}
function invoke_ji(index,a1) {
var sp = stackSave();
try {
- return dynCall_ji(index,a1);
+ return Module["dynCall_ji"](index,a1);
} catch(e) {
stackRestore(sp);
- if (e !== e+0 && e !== 'longjmp') throw e;
- _setThrew(1, 0);
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
}
}
function invoke_v(index) {
var sp = stackSave();
try {
- dynCall_v(index);
+ Module["dynCall_v"](index);
} catch(e) {
stackRestore(sp);
- if (e !== e+0 && e !== 'longjmp') throw e;
- _setThrew(1, 0);
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
}
}
function invoke_vi(index,a1) {
var sp = stackSave();
try {
- dynCall_vi(index,a1);
+ Module["dynCall_vi"](index,a1);
} catch(e) {
stackRestore(sp);
- if (e !== e+0 && e !== 'longjmp') throw e;
- _setThrew(1, 0);
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
}
}
function invoke_vii(index,a1,a2) {
var sp = stackSave();
try {
- dynCall_vii(index,a1,a2);
+ Module["dynCall_vii"](index,a1,a2);
} catch(e) {
stackRestore(sp);
- if (e !== e+0 && e !== 'longjmp') throw e;
- _setThrew(1, 0);
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
}
}
function invoke_viii(index,a1,a2,a3) {
var sp = stackSave();
try {
- dynCall_viii(index,a1,a2,a3);
+ Module["dynCall_viii"](index,a1,a2,a3);
} catch(e) {
stackRestore(sp);
- if (e !== e+0 && e !== 'longjmp') throw e;
- _setThrew(1, 0);
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
+ }
+}
+
+function invoke_viiii(index,a1,a2,a3,a4) {
+ var sp = stackSave();
+ try {
+ Module["dynCall_viiii"](index,a1,a2,a3,a4);
+ } catch(e) {
+ stackRestore(sp);
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
+ }
+}
+
+function invoke_viiiii(index,a1,a2,a3,a4,a5) {
+ var sp = stackSave();
+ try {
+ Module["dynCall_viiiii"](index,a1,a2,a3,a4,a5);
+ } catch(e) {
+ stackRestore(sp);
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
+ }
+}
+
+function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6) {
+ var sp = stackSave();
+ try {
+ Module["dynCall_viiiiii"](index,a1,a2,a3,a4,a5,a6);
+ } catch(e) {
+ stackRestore(sp);
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
}
}
function invoke_viji(index,a1,a2,a3,a4) {
var sp = stackSave();
try {
- dynCall_viji(index,a1,a2,a3,a4);
+ Module["dynCall_viji"](index,a1,a2,a3,a4);
} catch(e) {
stackRestore(sp);
- if (e !== e+0 && e !== 'longjmp') throw e;
- _setThrew(1, 0);
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
}
}
-var asmGlobalArg = {};
+Module.asmGlobalArg = {};
-var asmLibraryArg = {
- "abort": abort,
- "setTempRet0": setTempRet0,
- "getTempRet0": getTempRet0,
- "invoke_ii": invoke_ii,
- "invoke_iii": invoke_iii,
- "invoke_iiii": invoke_iiii,
- "invoke_iiiii": invoke_iiiii,
- "invoke_iiiiii": invoke_iiiiii,
- "invoke_iiiiiii": invoke_iiiiiii,
- "invoke_ji": invoke_ji,
- "invoke_v": invoke_v,
- "invoke_vi": invoke_vi,
- "invoke_vii": invoke_vii,
- "invoke_viii": invoke_viii,
- "invoke_viji": invoke_viji,
- "___assert_fail": ___assert_fail,
- "___cxa_allocate_exception": ___cxa_allocate_exception,
- "___cxa_begin_catch": ___cxa_begin_catch,
- "___cxa_end_catch": ___cxa_end_catch,
- "___cxa_find_matching_catch": ___cxa_find_matching_catch,
- "___cxa_find_matching_catch_2": ___cxa_find_matching_catch_2,
- "___cxa_find_matching_catch_3": ___cxa_find_matching_catch_3,
- "___cxa_free_exception": ___cxa_free_exception,
- "___cxa_pure_virtual": ___cxa_pure_virtual,
- "___cxa_throw": ___cxa_throw,
- "___cxa_uncaught_exceptions": ___cxa_uncaught_exceptions,
- "___exception_addRef": ___exception_addRef,
- "___exception_deAdjust": ___exception_deAdjust,
- "___exception_decRef": ___exception_decRef,
- "___gxx_personality_v0": ___gxx_personality_v0,
- "___resumeException": ___resumeException,
- "___setErrNo": ___setErrNo,
- "___syscall140": ___syscall140,
- "___syscall146": ___syscall146,
- "___syscall54": ___syscall54,
- "___syscall6": ___syscall6,
- "_abort": _abort,
- "_do_error": _do_error,
- "_do_progress": _do_progress,
- "_emscripten_get_heap_size": _emscripten_get_heap_size,
- "_emscripten_memcpy_big": _emscripten_memcpy_big,
- "_emscripten_resize_heap": _emscripten_resize_heap,
- "_get_file_contents": _get_file_contents,
- "_llvm_exp2_f32": _llvm_exp2_f32,
- "_llvm_exp2_f64": _llvm_exp2_f64,
- "_llvm_trap": _llvm_trap,
- "_put_file_contents": _put_file_contents,
- "_put_file_size": _put_file_size,
- "abortOnCannotGrowMemory": abortOnCannotGrowMemory,
- "emscripten_realloc_buffer": emscripten_realloc_buffer,
- "flush_NO_FILESYSTEM": flush_NO_FILESYSTEM,
- "tempDoublePtr": tempDoublePtr,
- "DYNAMICTOP_PTR": DYNAMICTOP_PTR
-};
+Module.asmLibraryArg = { "abort": abort, "assert": assert, "enlargeMemory": enlargeMemory, "getTotalMemory": getTotalMemory, "abortOnCannotGrowMemory": abortOnCannotGrowMemory, "invoke_ii": invoke_ii, "invoke_iii": invoke_iii, "invoke_iiii": invoke_iiii, "invoke_iiiii": invoke_iiiii, "invoke_iiiiii": invoke_iiiiii, "invoke_iiiiiii": invoke_iiiiiii, "invoke_ji": invoke_ji, "invoke_v": invoke_v, "invoke_vi": invoke_vi, "invoke_vii": invoke_vii, "invoke_viii": invoke_viii, "invoke_viiii": invoke_viiii, "invoke_viiiii": invoke_viiiii, "invoke_viiiiii": invoke_viiiiii, "invoke_viji": invoke_viji, "__ZSt18uncaught_exceptionv": __ZSt18uncaught_exceptionv, "___assert_fail": ___assert_fail, "___cxa_allocate_exception": ___cxa_allocate_exception, "___cxa_find_matching_catch": ___cxa_find_matching_catch, "___cxa_find_matching_catch_2": ___cxa_find_matching_catch_2, "___cxa_free_exception": ___cxa_free_exception, "___cxa_throw": ___cxa_throw, "___gxx_personality_v0": ___gxx_personality_v0, "___resumeException": ___resumeException, "___setErrNo": ___setErrNo, "_abort": _abort, "_do_error": _do_error, "_do_progress": _do_progress, "_emscripten_memcpy_big": _emscripten_memcpy_big, "_get_file_contents": _get_file_contents, "_llvm_exp2_f32": _llvm_exp2_f32, "_llvm_exp2_f64": _llvm_exp2_f64, "_put_file_contents": _put_file_contents, "_put_file_size": _put_file_size, "DYNAMICTOP_PTR": DYNAMICTOP_PTR, "tempDoublePtr": tempDoublePtr, "ABORT": ABORT, "STACKTOP": STACKTOP, "STACK_MAX": STACK_MAX };
// EMSCRIPTEN_START_ASM
var asm =Module["asm"]// EMSCRIPTEN_END_ASM
-(asmGlobalArg, asmLibraryArg, buffer);
+(Module.asmGlobalArg, Module.asmLibraryArg, buffer);
Module["asm"] = asm;
-var _DApi_MpqCmp = Module["_DApi_MpqCmp"] = function() {
- return Module["asm"]["_DApi_MpqCmp"].apply(null, arguments)
-};
-
-var __ZSt18uncaught_exceptionv = Module["__ZSt18uncaught_exceptionv"] = function() {
- return Module["asm"]["__ZSt18uncaught_exceptionv"].apply(null, arguments)
-};
-
-var ___cxa_can_catch = Module["___cxa_can_catch"] = function() {
- return Module["asm"]["___cxa_can_catch"].apply(null, arguments)
-};
-
-var ___cxa_is_pointer_type = Module["___cxa_is_pointer_type"] = function() {
- return Module["asm"]["___cxa_is_pointer_type"].apply(null, arguments)
-};
-
-var ___em_js__do_error = Module["___em_js__do_error"] = function() {
- return Module["asm"]["___em_js__do_error"].apply(null, arguments)
-};
-
-var ___em_js__do_progress = Module["___em_js__do_progress"] = function() {
- return Module["asm"]["___em_js__do_progress"].apply(null, arguments)
-};
-
-var ___em_js__get_file_contents = Module["___em_js__get_file_contents"] = function() {
- return Module["asm"]["___em_js__get_file_contents"].apply(null, arguments)
-};
-
-var ___em_js__put_file_contents = Module["___em_js__put_file_contents"] = function() {
- return Module["asm"]["___em_js__put_file_contents"].apply(null, arguments)
-};
-
-var ___em_js__put_file_size = Module["___em_js__put_file_size"] = function() {
- return Module["asm"]["___em_js__put_file_size"].apply(null, arguments)
-};
-
-var _emscripten_replace_memory = Module["_emscripten_replace_memory"] = function() {
- return Module["asm"]["_emscripten_replace_memory"].apply(null, arguments)
-};
-
-var _free = Module["_free"] = function() {
- return Module["asm"]["_free"].apply(null, arguments)
-};
-
-var _llvm_bswap_i32 = Module["_llvm_bswap_i32"] = function() {
- return Module["asm"]["_llvm_bswap_i32"].apply(null, arguments)
-};
-
-var _malloc = Module["_malloc"] = function() {
- return Module["asm"]["_malloc"].apply(null, arguments)
-};
-
-var _memcpy = Module["_memcpy"] = function() {
- return Module["asm"]["_memcpy"].apply(null, arguments)
-};
-
-var _memmove = Module["_memmove"] = function() {
- return Module["asm"]["_memmove"].apply(null, arguments)
-};
-
-var _memset = Module["_memset"] = function() {
- return Module["asm"]["_memset"].apply(null, arguments)
-};
-
-var _sbrk = Module["_sbrk"] = function() {
- return Module["asm"]["_sbrk"].apply(null, arguments)
-};
-
-var _setThrew = Module["_setThrew"] = function() {
- return Module["asm"]["_setThrew"].apply(null, arguments)
-};
-
-var establishStackSpace = Module["establishStackSpace"] = function() {
- return Module["asm"]["establishStackSpace"].apply(null, arguments)
-};
-
-var stackAlloc = Module["stackAlloc"] = function() {
- return Module["asm"]["stackAlloc"].apply(null, arguments)
-};
-
-var stackRestore = Module["stackRestore"] = function() {
- return Module["asm"]["stackRestore"].apply(null, arguments)
-};
-
-var stackSave = Module["stackSave"] = function() {
- return Module["asm"]["stackSave"].apply(null, arguments)
-};
-
-var dynCall_ii = Module["dynCall_ii"] = function() {
- return Module["asm"]["dynCall_ii"].apply(null, arguments)
-};
-
-var dynCall_iidiiii = Module["dynCall_iidiiii"] = function() {
- return Module["asm"]["dynCall_iidiiii"].apply(null, arguments)
-};
-
-var dynCall_iii = Module["dynCall_iii"] = function() {
- return Module["asm"]["dynCall_iii"].apply(null, arguments)
-};
-
-var dynCall_iiii = Module["dynCall_iiii"] = function() {
- return Module["asm"]["dynCall_iiii"].apply(null, arguments)
-};
-
-var dynCall_iiiii = Module["dynCall_iiiii"] = function() {
- return Module["asm"]["dynCall_iiiii"].apply(null, arguments)
-};
-
-var dynCall_iiiiii = Module["dynCall_iiiiii"] = function() {
- return Module["asm"]["dynCall_iiiiii"].apply(null, arguments)
-};
-
-var dynCall_iiiiiii = Module["dynCall_iiiiiii"] = function() {
- return Module["asm"]["dynCall_iiiiiii"].apply(null, arguments)
-};
-
-var dynCall_ji = Module["dynCall_ji"] = function() {
- return Module["asm"]["dynCall_ji"].apply(null, arguments)
-};
-
-var dynCall_jiji = Module["dynCall_jiji"] = function() {
- return Module["asm"]["dynCall_jiji"].apply(null, arguments)
-};
-
-var dynCall_v = Module["dynCall_v"] = function() {
- return Module["asm"]["dynCall_v"].apply(null, arguments)
-};
-
-var dynCall_vi = Module["dynCall_vi"] = function() {
- return Module["asm"]["dynCall_vi"].apply(null, arguments)
-};
-
-var dynCall_vii = Module["dynCall_vii"] = function() {
- return Module["asm"]["dynCall_vii"].apply(null, arguments)
-};
-
-var dynCall_viii = Module["dynCall_viii"] = function() {
- return Module["asm"]["dynCall_viii"].apply(null, arguments)
-};
-
-var dynCall_viiii = Module["dynCall_viiii"] = function() {
- return Module["asm"]["dynCall_viiii"].apply(null, arguments)
-};
-
-var dynCall_viiiii = Module["dynCall_viiiii"] = function() {
- return Module["asm"]["dynCall_viiiii"].apply(null, arguments)
-};
-
-var dynCall_viiiiii = Module["dynCall_viiiiii"] = function() {
- return Module["asm"]["dynCall_viiiiii"].apply(null, arguments)
-};
-
-var dynCall_viji = Module["dynCall_viji"] = function() {
- return Module["asm"]["dynCall_viji"].apply(null, arguments)
-};
+var _DApi_MpqCmp = Module["_DApi_MpqCmp"] = function() { return Module["asm"]["_DApi_MpqCmp"].apply(null, arguments) };
+var ___cxa_can_catch = Module["___cxa_can_catch"] = function() { return Module["asm"]["___cxa_can_catch"].apply(null, arguments) };
+var ___cxa_is_pointer_type = Module["___cxa_is_pointer_type"] = function() { return Module["asm"]["___cxa_is_pointer_type"].apply(null, arguments) };
+var ___em_js__do_error = Module["___em_js__do_error"] = function() { return Module["asm"]["___em_js__do_error"].apply(null, arguments) };
+var ___em_js__do_progress = Module["___em_js__do_progress"] = function() { return Module["asm"]["___em_js__do_progress"].apply(null, arguments) };
+var ___em_js__get_file_contents = Module["___em_js__get_file_contents"] = function() { return Module["asm"]["___em_js__get_file_contents"].apply(null, arguments) };
+var ___em_js__put_file_contents = Module["___em_js__put_file_contents"] = function() { return Module["asm"]["___em_js__put_file_contents"].apply(null, arguments) };
+var ___em_js__put_file_size = Module["___em_js__put_file_size"] = function() { return Module["asm"]["___em_js__put_file_size"].apply(null, arguments) };
+var _emscripten_replace_memory = Module["_emscripten_replace_memory"] = function() { return Module["asm"]["_emscripten_replace_memory"].apply(null, arguments) };
+var _free = Module["_free"] = function() { return Module["asm"]["_free"].apply(null, arguments) };
+var _llvm_bswap_i32 = Module["_llvm_bswap_i32"] = function() { return Module["asm"]["_llvm_bswap_i32"].apply(null, arguments) };
+var _malloc = Module["_malloc"] = function() { return Module["asm"]["_malloc"].apply(null, arguments) };
+var _memcpy = Module["_memcpy"] = function() { return Module["asm"]["_memcpy"].apply(null, arguments) };
+var _memset = Module["_memset"] = function() { return Module["asm"]["_memset"].apply(null, arguments) };
+var _sbrk = Module["_sbrk"] = function() { return Module["asm"]["_sbrk"].apply(null, arguments) };
+var establishStackSpace = Module["establishStackSpace"] = function() { return Module["asm"]["establishStackSpace"].apply(null, arguments) };
+var getTempRet0 = Module["getTempRet0"] = function() { return Module["asm"]["getTempRet0"].apply(null, arguments) };
+var runPostSets = Module["runPostSets"] = function() { return Module["asm"]["runPostSets"].apply(null, arguments) };
+var setTempRet0 = Module["setTempRet0"] = function() { return Module["asm"]["setTempRet0"].apply(null, arguments) };
+var setThrew = Module["setThrew"] = function() { return Module["asm"]["setThrew"].apply(null, arguments) };
+var stackAlloc = Module["stackAlloc"] = function() { return Module["asm"]["stackAlloc"].apply(null, arguments) };
+var stackRestore = Module["stackRestore"] = function() { return Module["asm"]["stackRestore"].apply(null, arguments) };
+var stackSave = Module["stackSave"] = function() { return Module["asm"]["stackSave"].apply(null, arguments) };
+var dynCall_ii = Module["dynCall_ii"] = function() { return Module["asm"]["dynCall_ii"].apply(null, arguments) };
+var dynCall_iii = Module["dynCall_iii"] = function() { return Module["asm"]["dynCall_iii"].apply(null, arguments) };
+var dynCall_iiii = Module["dynCall_iiii"] = function() { return Module["asm"]["dynCall_iiii"].apply(null, arguments) };
+var dynCall_iiiii = Module["dynCall_iiiii"] = function() { return Module["asm"]["dynCall_iiiii"].apply(null, arguments) };
+var dynCall_iiiiii = Module["dynCall_iiiiii"] = function() { return Module["asm"]["dynCall_iiiiii"].apply(null, arguments) };
+var dynCall_iiiiiii = Module["dynCall_iiiiiii"] = function() { return Module["asm"]["dynCall_iiiiiii"].apply(null, arguments) };
+var dynCall_ji = Module["dynCall_ji"] = function() { return Module["asm"]["dynCall_ji"].apply(null, arguments) };
+var dynCall_v = Module["dynCall_v"] = function() { return Module["asm"]["dynCall_v"].apply(null, arguments) };
+var dynCall_vi = Module["dynCall_vi"] = function() { return Module["asm"]["dynCall_vi"].apply(null, arguments) };
+var dynCall_vii = Module["dynCall_vii"] = function() { return Module["asm"]["dynCall_vii"].apply(null, arguments) };
+var dynCall_viii = Module["dynCall_viii"] = function() { return Module["asm"]["dynCall_viii"].apply(null, arguments) };
+var dynCall_viiii = Module["dynCall_viiii"] = function() { return Module["asm"]["dynCall_viiii"].apply(null, arguments) };
+var dynCall_viiiii = Module["dynCall_viiiii"] = function() { return Module["asm"]["dynCall_viiiii"].apply(null, arguments) };
+var dynCall_viiiiii = Module["dynCall_viiiiii"] = function() { return Module["asm"]["dynCall_viiiiii"].apply(null, arguments) };
+var dynCall_viji = Module["dynCall_viji"] = function() { return Module["asm"]["dynCall_viji"].apply(null, arguments) };
;
@@ -2576,17 +2264,18 @@ function ExitStatus(status) {
this.name = "ExitStatus";
this.message = "Program terminated with exit(" + status + ")";
this.status = status;
-}
+};
ExitStatus.prototype = new Error();
ExitStatus.prototype.constructor = ExitStatus;
+var initialStackTop;
var calledMain = false;
dependenciesFulfilled = function runCaller() {
// If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false)
if (!Module['calledRun']) run();
if (!Module['calledRun']) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled
-};
+}
@@ -2612,7 +2301,7 @@ function run(args) {
if (ABORT) return;
- initRuntime();
+ ensureInitRuntime();
preMain();
@@ -2652,6 +2341,7 @@ function exit(status, implicit) {
ABORT = true;
EXITSTATUS = status;
+ STACKTOP = initialStackTop;
exitRuntime();
@@ -2668,9 +2358,13 @@ function abort(what) {
Module['onAbort'](what);
}
- what += '';
- out(what);
- err(what);
+ if (what !== undefined) {
+ out(what);
+ err(what);
+ what = JSON.stringify(what)
+ } else {
+ what = '';
+ }
ABORT = true;
EXITSTATUS = 1;
@@ -2679,6 +2373,8 @@ function abort(what) {
}
Module['abort'] = abort;
+// {{PRE_RUN_ADDITIONS}}
+
if (Module['preInit']) {
if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];
while (Module['preInit'].length > 0) {
@@ -2687,10 +2383,12 @@ if (Module['preInit']) {
}
- Module["noExitRuntime"] = true;
+Module["noExitRuntime"] = true;
run();
+// {{POST_RUN_ADDITIONS}}
+
@@ -2711,14 +2409,14 @@ Module['ready'] = new Promise(function (resolve, reject) {
- return MpqCmp
+ return MpqCmp;
}
);
})();
if (typeof exports === 'object' && typeof module === 'object')
- module.exports = MpqCmp;
- else if (typeof define === 'function' && define['amd'])
- define([], function() { return MpqCmp; });
- else if (typeof exports === 'object')
- exports["MpqCmp"] = MpqCmp;
-
\ No newline at end of file
+ module.exports = MpqCmp;
+ else if (typeof define === 'function' && define['amd'])
+ define([], function() { return MpqCmp; });
+ else if (typeof exports === 'object')
+ exports["MpqCmp"] = MpqCmp;
+
\ No newline at end of file
diff --git a/src/mpqcmp/MpqCmp.wasm b/src/mpqcmp/MpqCmp.wasm
index 2e07d00..a1b8386 100644
Binary files a/src/mpqcmp/MpqCmp.wasm and b/src/mpqcmp/MpqCmp.wasm differ
diff --git a/src/mpqcmp/compress.js b/src/mpqcmp/compress.js
new file mode 100644
index 0000000..9f602a6
--- /dev/null
+++ b/src/mpqcmp/compress.js
@@ -0,0 +1,27 @@
+import Worker from './mpqcmp.worker.js';
+
+export default function compress(mpq, progress) {
+ progress("Loading...");
+ return new Promise((resolve, reject) => {
+ try {
+ const worker = new Worker();
+ worker.addEventListener("message", ({data}) => {
+ switch (data.action) {
+ case "result":
+ resolve(data.result);
+ break;
+ case "error":
+ reject({message: data.error, stack: data.stack});
+ break;
+ case "progress":
+ progress(data.text, data.loaded, data.total);
+ break;
+ default:
+ }
+ });
+ worker.postMessage({action: "run", mpq});
+ } catch (e) {
+ reject(e);
+ }
+ });
+}
diff --git a/src/mpqcmp/index.js b/src/mpqcmp/index.js
new file mode 100644
index 0000000..bce78d8
--- /dev/null
+++ b/src/mpqcmp/index.js
@@ -0,0 +1,84 @@
+import React from 'react';
+import compress from './compress';
+
+export default class CompressMpq extends React.Component {
+ state = {};
+
+ parseFile = e => {
+ const files = e.target.files;
+ if (files.length > 0) {
+ this.start(files[0]);
+ }
+ }
+
+ onProgress(progress) {
+ this.setState({progress});
+ }
+ onDone = result => {
+ const blob = new Blob([result], {type: 'binary/octet-stream'});
+ const url = URL.createObjectURL(blob);
+ this.setState({url});
+
+ const lnk = document.createElement('a');
+ lnk.setAttribute('href', url);
+ lnk.setAttribute('download', 'DIABDAT.MPQ');
+ document.body.appendChild(lnk);
+ lnk.click();
+ document.body.removeChild(lnk);
+ }
+ onError(message, stack) {
+ const { api } = this.props;
+ api.setState({compress: false});
+ api.onError(message, stack);
+ }
+
+ onClose = () => {
+ if (this.state.url) {
+ URL.revokeObjectURL(this.state.url);
+ }
+ this.props.api.setState({compress: false});
+ }
+
+ start(file) {
+ this.setState({started: true});
+ compress(file, (text, loaded, total) => this.onProgress({text, loaded, total}))
+ .then(this.onDone, e => this.onError(e.message, e.stack));
+ }
+
+ render() {
+ const { url, started, progress } = this.state;
+ if (url) {
+ return (
+
+ );
+ }
+ if (started) {
+ return (
+
+ {(progress && progress.text) || 'Processing...'}
+ {progress != null && !!progress.total && (
+
+ )}
+
+ );
+ }
+ return (
+
+
+ You can use this tool to reduce the original MPQ to about half its size. It encodes sounds in MP3 format and uses better compression for regular files.
+ To begin, click the button below or drop the MPQ onto the page.
+
+
+
Back
+
+ );
+ }
+}
diff --git a/src/mpqcmp/mpqcmp.worker.js b/src/mpqcmp/mpqcmp.worker.js
index 2ffdbb9..6852f74 100644
--- a/src/mpqcmp/mpqcmp.worker.js
+++ b/src/mpqcmp/mpqcmp.worker.js
@@ -7,14 +7,6 @@ const MpqSize = 356747;
/* eslint-disable-next-line no-restricted-globals */
const worker = self;
-function onError(err, action="error") {
- if (err instanceof Error) {
- worker.postMessage({action, error: err.toString(), stack: err.stack});
- } else {
- worker.postMessage({action, error: err.toString()});
- }
-}
-
let input_file = null;
let output_file = null;
let last_progress = 0;
@@ -31,6 +23,7 @@ const DApi = {
array.set(input_file.subarray(offset, offset + array.byteLength));
},
put_file_size(size) {
+ debugger;
output_file = new Uint8Array(size);
},
put_file_contents(array, offset) {
@@ -65,25 +58,27 @@ const readFile = (file, progress) => new Promise((resolve, reject) => {
reader.readAsArrayBuffer(file);
});
-async function initWasm(spawn, progress) {
+async function initWasm(progress) {
const binary = await axios.request({
- url: spawn ? SpawnBinary : DiabloBinary,
+ url: MpqBinary,
responseType: 'arraybuffer',
onDownloadProgress: progress,
});
- const result = await (spawn ? SpawnModule : DiabloModule)({wasmBinary: binary.data}).ready;
- progress({loaded: 2000000});
+ const result = await MpqModule({
+ wasmBinary: binary.data,
+ }).ready;
+ progress({loaded: MpqSize});
return result;
}
async function run(mpq) {
progress("Loading...");
- let mpqLoaded = 0, mpqTotal = (mpq ? mpq.size : 0), wasmLoaded = 0, wasmTotal = (spawn ? SpawnSize : DiabloSize);
+ let mpqLoaded = 0, mpqTotal = (mpq ? mpq.size : 0), wasmLoaded = 0, wasmTotal = MpqSize;
const wasmWeight = 5;
function updateProgress() {
progress("Loading...", mpqLoaded + wasmLoaded * wasmWeight, mpqTotal + wasmTotal * wasmWeight);
}
- const loadWasm = initWasm(spawn, e => {
+ const loadWasm = initWasm(e => {
wasmLoaded = Math.min(e.loaded, wasmTotal);
updateProgress();
});
@@ -95,7 +90,7 @@ async function run(mpq) {
input_file = new Uint8Array(mpq);
- progress("Initializing...");
+ progress("Processing...");
wasm._DApi_MpqCmp(input_file.length);
@@ -105,10 +100,10 @@ async function run(mpq) {
worker.addEventListener("message", ({data}) => {
switch (data.action) {
case "run":
- init_game(data.mpq).then(
- res => worker.postMessage({action: "result", data: res}, [res]),
- e => onError(e, "failed"));
+ run(data.mpq).then(
+ result => worker.postMessage({action: "result", result}, [result]),
+ err => worker.postMessage({action: "error", error: err.toString(), stack: err.stack}));
break;
default:
}
-});
+});
\ No newline at end of file