Skip to content

Commit

Permalink
wasm in pure C
Browse files Browse the repository at this point in the history
  • Loading branch information
toyobayashi committed Apr 21, 2022
1 parent c73102a commit 63b8871
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 162 deletions.
20 changes: 19 additions & 1 deletion .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
],
Expand Down Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion build.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')))
Expand Down
4 changes: 2 additions & 2 deletions src/properties/WzPngProperty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 7 additions & 4 deletions src/util/wz.d.ts
Original file line number Diff line number Diff line change
@@ -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
25 changes: 19 additions & 6 deletions test/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -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++
Expand All @@ -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();

Expand Down
9 changes: 5 additions & 4 deletions wasm/cgen.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
66 changes: 64 additions & 2 deletions wasm/export.js
Original file line number Diff line number Diff line change
@@ -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;
}
72 changes: 72 additions & 0 deletions wasm/src/main.c
Original file line number Diff line number Diff line change
@@ -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;
}
Loading

0 comments on commit 63b8871

Please sign in to comment.