diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index 7843a0a..de88e1b 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -2,7 +2,7 @@
   "env": {
     "includePath": [
       "${default}",
-      "${env:EMSDK}/upstream/emscripten/system/include",
+      "${env:EMSDK}/upstream/emscripten/cache/sysroot/include",
       "${workspaceFolder}/wasm/deps/zlib",
       "${workspaceFolder}/wasm/deps/openssl/include"
     ],
@@ -58,6 +58,24 @@
       "cStandard": "c11",
       "cppStandard": "c++11",
       "intelliSenseMode": "${default}"
+    },
+    {
+      "name": "Emscripten",
+      "defines": ["${defines}"],
+      "compilerPath": "${env:EMSDK}/upstream/emscripten/emcc",
+      "intelliSenseMode": "clang-x86",
+      "cStandard": "c99",
+      "cppStandard": "c++11",
+      "includePath": ["${includePath}"]
+    },
+    {
+      "name": "Emscripten (Win32)",
+      "defines": ["${defines}"],
+      "compilerPath": "${env:EMSDK}/upstream/emscripten/emcc.bat",
+      "intelliSenseMode": "clang-x86",
+      "cStandard": "c99",
+      "cppStandard": "c++11",
+      "includePath": ["${includePath}"]
     }
   ],
   "version": 4
diff --git a/build.js b/build.js
index c4b0467..718e5eb 100644
--- a/build.js
+++ b/build.js
@@ -55,7 +55,9 @@ async function main () {
   cp(p(wasmoutdir, 'wzasm.js'), asm)
   fs.writeFileSync(asm, fs.readFileSync(asm, 'utf8').replace('wzasm.js.mem', 'wz.js.mem').replace('wzasm.wasm', 'wz.wasm'), 'utf8')
   ts.compile(p('tsconfig.esm.json'))
-  cp(p(wasmoutdir, 'wzasm.js.mem'), p('./lib/esm/util/wz.js.mem'))
+  if (fs.existsSync(p(wasmoutdir, 'wzasm.js.mem'))) {
+    cp(p(wasmoutdir, 'wzasm.js.mem'), p('./lib/esm/util/wz.js.mem'))
+  }
 
   await bundler.webpack(tsgoConfig)
   await bundler.webpack(readConfigNoCache(p('./tsgo.es5.config.js')))
diff --git a/src/properties/WzPngProperty.ts b/src/properties/WzPngProperty.ts
index da37a1f..7d6c1c9 100644
--- a/src/properties/WzPngProperty.ts
+++ b/src/properties/WzPngProperty.ts
@@ -534,8 +534,8 @@ function inflate (data: Uint8Array, len: number): Promise<Uint8Array> {
 async function inflateWasm (data: Uint8Array, len: number): Promise<Uint8Array> {
   if (wasmInflate === null) {
     const wzWasm = await import('../util/wz')
-    const { Module } = await wzWasm.default()
-    wasmInflate = Module.inflate
+    /* const { Module } =  */await wzWasm.default()
+    wasmInflate = wzWasm.inflate
   }
   const buf = wasmInflate(data, len)
   return buf
diff --git a/src/util/wz.d.ts b/src/util/wz.d.ts
index 85825a5..2f1db9b 100644
--- a/src/util/wz.d.ts
+++ b/src/util/wz.d.ts
@@ -1,14 +1,17 @@
+/* eslint-disable @typescript-eslint/naming-convention */
 // eslint-disable-next-line @typescript-eslint/triple-slash-reference
 /// <reference types="emscripten" />
 
 declare namespace mod {
-  export function inflate (data: Uint8Array, len: number): Uint8Array
-  export function aesEnc (data: Uint8Array, key: Uint8Array): Uint8Array
+  export function _wz_zlib_inflate (source: number, srclen: number, dest: number, destlen: number): number
+  export function _wz_aes_ecb_encrypt (data: number, dataLen: number, key: number, out: number, outLen: number): number
+  export function _malloc (size: number): number
+  export function _free (ptr: number): void
 }
 
 declare function init (moduleOverrides?: Partial<EmscriptenModule>): Promise<{ Module: typeof mod }>
 
-export declare const inflate: typeof mod.inflate
-export declare const aesEnc: typeof mod.aesEnc
+export declare function inflate (data: Uint8Array, len: number): Uint8Array
+export declare function aesEnc (data: Uint8Array, key: Uint8Array): Uint8Array
 
 export default init
diff --git a/test/browser.js b/test/browser.js
index 52e8529..859cdff 100644
--- a/test/browser.js
+++ b/test/browser.js
@@ -32,14 +32,27 @@ if (!HTMLCanvasElement.prototype.toBlob) {
   ];
 
   var input = document.getElementById('file');
+  var mapleVersion = wz.WzMapleVersion.GMS;
 
   input.addEventListener('change', function (e) {
     console.log(e.target.files[0]);
     if (!e.target.files[0]) return;
-    const f = e.target.files[0];
+    var f = e.target.files[0];
 
-    let n = 0;
-    wz.walkWzFileAsync(f, wz.WzMapleVersion.GMS, function (obj) {
+    if (f.name.indexOf('.img') !== -1) {
+      wz.init().then(function () {
+        var image = wz.WzImage.createFromFile(f, mapleVersion);
+        image.parseImage().then(function (parsed) {
+          if (parsed) {
+            console.log('parsed');
+          }
+        });
+      });
+      return;
+    }
+
+    var n = 0;
+    wz.walkWzFileAsync(f, mapleVersion, function (obj) {
       return new Promise(function (resolve, reject) {
         // if (n >= 10) return true
         // n++
@@ -50,9 +63,9 @@ if (!HTMLCanvasElement.prototype.toBlob) {
           console.log(n, wz.WzPropertyType[obj.propertyType], obj.fullPath);
 
           return resolve(obj.getBytes(false).then(function (buf) {
-            const blob = new Blob([buf.buffer], { type: 'audio/mp3' });
-            const src = URL.createObjectURL(blob);
-            const audio = new Audio();
+            var blob = new Blob([buf.buffer], { type: 'audio/mp3' });
+            var src = URL.createObjectURL(blob);
+            var audio = new Audio();
             audio.src = src;
             audio.play();
 
diff --git a/wasm/cgen.config.js b/wasm/cgen.config.js
index 7603af1..f74c6d2 100644
--- a/wasm/cgen.config.js
+++ b/wasm/cgen.config.js
@@ -2,20 +2,21 @@ const { defineFunctionConfig } = require('@tybys/cgen')
 
 function createTarget (name, asm, isDebug) {
   const compilerFlags = [
-    ...(isDebug ? ['-sDISABLE_EXCEPTION_CATCHING=0'] : [])
+    // ...(isDebug ? ['-sDISABLE_EXCEPTION_CATCHING=0'] : [])
   ]
   const linkerFlags = [
-    '--bind',
+    // '--bind',
     '-sALLOW_MEMORY_GROWTH=1',
+    "-sEXPORTED_FUNCTIONS=['_malloc','_free']",
     ...(asm ? ['-sWASM=0'] : []),
-    ...(isDebug ? ['-sDISABLE_EXCEPTION_CATCHING=0', '-sSAFE_HEAP=1'] : [])
+    ...(isDebug ? [/* '-sDISABLE_EXCEPTION_CATCHING=0',  */'-sSAFE_HEAP=1'] : [])
   ]
 
   return {
     name: name,
     type: 'exe',
     sources: [
-      './src/main.cpp'
+      './src/main.c'
     ],
     defines: [
       'AES256=1',
diff --git a/wasm/export.js b/wasm/export.js
index 903d248..7e73c5d 100644
--- a/wasm/export.js
+++ b/wasm/export.js
@@ -1,7 +1,69 @@
 exports.inflate = function (data, len) {
-  return Module.inflate(data, len)
+  var srclen = data.length >>> 0;
+  var source = Module._malloc(srclen);
+  if (!source) throw new Error('malloc failed');
+  var memory = new Uint8Array(Module.HEAPU8.buffer, source, srclen);
+  memory.set(data);
+
+  var destlen = len >>> 0;
+  var dest = Module._malloc(destlen);
+  if (!dest) {
+    Module._free(source);
+    throw new Error('malloc failed');
+  }
+  var r = Module._wz_zlib_inflate(source, srclen, dest, destlen);
+  Module._free(source);
+  if (r === 0) {
+    var ret = new Uint8Array(Module.HEAPU8.buffer, dest, destlen).slice();
+    Module._free(dest);
+    return ret;
+  }
+  Module._free(dest);
+  throw new Error('Inflate failed');
 }
 
 exports.aesEnc = function (data, key) {
-  return Module.aesEnc(data, key)
+  if (key.length !== 32) {
+    throw new Error('Invalid key');
+  }
+
+  var srclen = data.length >>> 0;
+  var source = Module._malloc(srclen);
+  if (!source) throw new Error('malloc failed');
+  var srcMemory = new Uint8Array(Module.HEAPU8.buffer, source, srclen);
+  srcMemory.set(data);
+
+  var outLenPointer = Module._malloc(4);
+  if (!source) {
+    Module._free(source);
+    throw new Error('malloc failed');
+  }
+  Module._wz_aes_ecb_encrypt(source, srclen, 0, 0, outLenPointer);
+  
+  var outLen = Module.HEAPU32[outLenPointer >> 2]
+  var out = Module._malloc(outLen);
+  if (!out) {
+    Module._free(source);
+    Module._free(outLenPointer);
+    throw new Error('malloc failed');
+  }
+  var keyLen = key.length >>> 0;
+  var keyPointer = Module._malloc(keyLen);
+  if (!keyPointer) {
+    Module._free(source);
+    Module._free(outLenPointer);
+    Module._free(out);
+    throw new Error('malloc failed');
+  }
+  var keyMemory = new Uint8Array(Module.HEAPU8.buffer, keyPointer, keyLen);
+  keyMemory.set(key);
+
+  Module._wz_aes_ecb_encrypt(source, srclen, keyPointer, out, outLenPointer);
+
+  var ret = new Uint8Array(Module.HEAPU8.buffer, out, outLen).slice();
+  Module._free(source);
+  Module._free(outLenPointer);
+  Module._free(out);
+  Module._free(keyPointer);
+  return ret;
 }
diff --git a/wasm/src/main.c b/wasm/src/main.c
new file mode 100644
index 0000000..ab97519
--- /dev/null
+++ b/wasm/src/main.c
@@ -0,0 +1,72 @@
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <emscripten.h>
+#include "zlib.h"
+#include "openssl/aes.h"
+
+EMSCRIPTEN_KEEPALIVE
+int wz_zlib_inflate(uint8_t *source,
+                    size_t srclen,
+                    uint8_t *dest,
+                    size_t destlen) {
+  z_stream infstream;
+  infstream.zalloc = Z_NULL;
+  infstream.zfree = Z_NULL;
+  infstream.opaque = Z_NULL;
+  infstream.avail_in = (uInt) srclen;  // size of input
+  infstream.next_in = (Bytef*) source;  // input char array NOLINT
+  infstream.avail_out = (uInt) destlen;  // size of output
+  infstream.next_out = (Bytef*) dest;  // output char array NOLINT
+
+  inflateInit(&infstream);
+  int r = inflate(&infstream, Z_NO_FLUSH);
+  inflateEnd(&infstream);
+  return r;
+}
+
+EMSCRIPTEN_KEEPALIVE
+int wz_aes_ecb_encrypt(const uint8_t* data,
+                       size_t data_len,
+                       const uint8_t* key,
+                       uint8_t* out,
+                       size_t* out_len) {
+  if (data == NULL || out_len == NULL) {
+    return 1;
+  }
+
+  uint8_t* data_buf = NULL;
+
+  size_t padding = data_len % 16;
+  size_t encrypt_len = 0;
+  if (padding != 0) {
+    padding = 16 - padding;
+    encrypt_len = data_len + padding;
+    if (out == NULL) {
+      *out_len = encrypt_len;
+      return 0;
+    }
+    if (key == NULL) return 2;
+    data_buf = (uint8_t*) malloc(encrypt_len);  // NOLINT
+    memcpy(data_buf, data, data_len);
+    memset(data_buf + data_len, padding, padding);
+  } else {
+    encrypt_len = data_len;
+    if (out == NULL) {
+      *out_len = encrypt_len;
+      return 0;
+    }
+    if (key == NULL) return 2;
+    data_buf = (uint8_t*) malloc(encrypt_len);  // NOLINT=
+    memcpy(data_buf, data, data_len);
+  }
+
+  AES_KEY k;
+  AES_set_encrypt_key(key, 256, &k);
+  AES_ecb_encrypt(data_buf, out, &k, AES_ENCRYPT);
+
+  free(data_buf);
+
+  return 0;
+}
diff --git a/wasm/src/main.cpp b/wasm/src/main.cpp
deleted file mode 100644
index 1b0d3ff..0000000
--- a/wasm/src/main.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-#include <cstring>
-#include <cstddef>
-#include <cstdint>
-#include <stdexcept>
-#include <vector>
-#include "zlib.h"
-#include "openssl/aes.h"
-
-#include <emscripten/bind.h>
-#include <emscripten/val.h>
-
-int inf(unsigned char *source, size_t srclen, unsigned char *dest, size_t destlen) {
-  z_stream infstream;
-  infstream.zalloc = Z_NULL;
-  infstream.zfree = Z_NULL;
-  infstream.opaque = Z_NULL;
-  infstream.avail_in = (uInt)(srclen); // size of input
-  infstream.next_in = (Bytef *)source; // input char array
-  infstream.avail_out = (uInt)(destlen); // size of output
-  infstream.next_out = (Bytef *)dest; // output char array
-
-  inflateInit(&infstream);
-  int r = inflate(&infstream, Z_NO_FLUSH);
-  inflateEnd(&infstream);
-  return r;
-}
-
-emscripten::val js_inflate(emscripten::val u8arr, emscripten::val len) {
-  int srclen = u8arr["length"].as<int>();
-  unsigned char* src = new unsigned char[srclen];
-  memset(src, 0, srclen);
-  for (int i = 0; i < srclen; i++) {
-    *(src + i) = u8arr[i].as<unsigned char>();
-  }
-  
-  int dstlen = len.as<int>();
-  unsigned char* dst = new unsigned char[dstlen];
-  memset(dst, 0, dstlen);
-
-  int r = inf(src, srclen, dst, dstlen);
-  if (r == 0) {
-    emscripten::val dstu8arr = emscripten::val::global("Uint8Array").new_(len);
-    for (int i = 0; i < dstlen; i++) {
-      dstu8arr.set(emscripten::val(i), emscripten::val(dst[i]));
-    }
-
-    delete[] src;
-    delete[] dst;
-
-    return dstu8arr;
-  } else {
-    delete[] src;
-    delete[] dst;
-    emscripten::val::global("Error").new_(emscripten::val("Inflate failed")).throw_();
-    return emscripten::val::undefined();
-  }
-}
-
-static size_t pkcs7cut(uint8_t *p, size_t plen) {
-  uint8_t last = p[plen - 1];
-  if (last > 0 && last <= 16) {
-    for (size_t x = 2; x <= last; x++) {
-      if (p[plen - x] != last) {
-        return plen;
-      }
-    }
-    return plen - last;
-  }
-
-  return plen;
-}
-
-std::vector<uint8_t> enc(const std::vector<uint8_t>& data,
-                         const std::vector<uint8_t>& key) {
-  if (key.size() != 32) {
-    throw std::runtime_error("Invalid key");
-  }
-
-  size_t dataLength = data.size();
-  const uint8_t* strBuf = (const uint8_t*) data.data();
-
-  uint8_t* dataBuf = nullptr;
-
-  size_t padding = dataLength % 16;
-  size_t encryptLength = 0;
-  if (padding != 0) {
-      padding = 16 - padding;
-      encryptLength = dataLength + padding;
-      dataBuf = new uint8_t[encryptLength];
-      memcpy(dataBuf, strBuf, dataLength);
-      memset(dataBuf + dataLength, padding, padding);
-  } else {
-      encryptLength = dataLength;
-      dataBuf = new uint8_t[dataLength];
-      memcpy(dataBuf, strBuf, dataLength);
-  }
-
-  AES_KEY k;
-  AES_set_encrypt_key(key.data(), 256, &k);
-
-  std::vector<uint8_t> out(encryptLength);
-
-  AES_ecb_encrypt(dataBuf, out.data(), &k, AES_ENCRYPT);
-
-  delete[] dataBuf;
-  dataBuf = nullptr;
-
-  return out;
-}
-
-emscripten::val js_aes_256_ecb(emscripten::val u8arr, emscripten::val key) {
-  int srclen = u8arr["length"].as<int>();
-  unsigned char* src = new unsigned char[srclen];
-  memset(src, 0, srclen);
-  for (int i = 0; i < srclen; i++) {
-    *(src + i) = u8arr[i].as<unsigned char>();
-  }
-
-  int keylen = key["length"].as<int>();
-  unsigned char* k = new unsigned char[keylen];
-  memset(k, 0, keylen);
-  for (int i = 0; i < keylen; i++) {
-    *(k + i) = key[i].as<unsigned char>();
-  }
-
-  std::vector<uint8_t> result = enc(std::vector<uint8_t>(src, src + srclen), std::vector<uint8_t>(k, k + keylen));
-  delete[] src;
-  delete[] k;
-
-  auto l = result.size();
-  emscripten::val ret = emscripten::val::global("Uint8Array").new_(l);
-  for (int i = 0; i < l; i++) {
-    ret.set(emscripten::val(i), emscripten::val(result[i]));
-  }
-
-  return ret;
-}
-
-EMSCRIPTEN_BINDINGS(wz) {
-  emscripten::function("inflate", js_inflate);
-  emscripten::function("aesEnc", js_aes_256_ecb);
-}