diff --git a/web/worker/cdimage.ts b/web/shell/cdimage.ts
similarity index 99%
rename from web/worker/cdimage.ts
rename to web/shell/cdimage.ts
index 1a502a3..0f65e59 100644
--- a/web/worker/cdimage.ts
+++ b/web/shell/cdimage.ts
@@ -1,4 +1,4 @@
-importScripts('text-decoder.js');
+///
class ISO9660FileSystem {
static async create(sectorReader: CDImageReader): Promise {
diff --git a/web/shell/loader.ts b/web/shell/loader.ts
index 28a94d4..cfe8620 100644
--- a/web/shell/loader.ts
+++ b/web/shell/loader.ts
@@ -1,54 +1,21 @@
///
+///
namespace xsystem35 {
export class ImageLoader {
- private worker: Worker;
- private cddaCallback: (wab: Blob) => void;
+ private imgFile: File;
+ private cueFile: File;
+ private imageReader: CDImageReader;
constructor(private runMain: () => void) {
- this.initWorker();
$('#fileselect').addEventListener('change', this.handleFileSelect.bind(this), false);
document.body.ondragover = this.handleDragOver.bind(this);
document.body.ondrop = this.handleDrop.bind(this);
}
- getCDDA(track: number, callback: (wav: Blob) => void) {
- this.send({ command: 'getTrack', track });
- this.cddaCallback = callback;
- }
-
- private initWorker() {
- this.worker = new Worker('imagereader-worker.js');
- this.worker.addEventListener('message', this.onMessage.bind(this));
- this.worker.addEventListener('error', this.onWorkerError.bind(this));
- }
-
- private setReadyState(imgName: string, cueName: string) {
- if (imgName) {
- $('#imgReady').classList.remove('notready');
- $('#imgReady').textContent = imgName;
- }
- if (cueName) {
- $('#cueReady').classList.remove('notready');
- $('#cueReady').textContent = cueName;
- }
- }
-
- private populateFiles(files: any, volumeLabel: string) {
- let grGenerator = new GameResourceGenerator();
- for (let name in files) {
- let data: ArrayBuffer = files[name];
- // Store contents in the emscripten heap, so that it can be mmap-ed without copying
- let ptr = Module.getMemory(data.byteLength);
- Module.HEAPU8.set(new Uint8Array(data), ptr);
- FS.writeFile(name, Module.HEAPU8.subarray(ptr, ptr + data.byteLength),
- { encoding: 'binary', canOwn: true });
- grGenerator.addFile(name);
- }
- FS.writeFile('xsystem35.gr', grGenerator.generate());
- FS.writeFile('.xsys35rc', xsystem35.xsys35rc);
-
- this.runMain();
+ async getCDDA(track: number, callback: (wav: Blob) => void) {
+ let blob = await this.imageReader.extractTrack(track);
+ callback(blob);
}
private handleFileSelect(evt: Event) {
@@ -73,42 +40,77 @@ namespace xsystem35 {
this.setFile(files[i]);
}
- private setFile(file: File) {
- this.send({ command: 'setFile', file });
- }
-
- private startInstall() {
- this.send({ command: 'extractFiles' });
- }
-
- private send(msg: any) {
- this.worker.postMessage(msg);
- }
-
- private onMessage(evt: MessageEvent) {
- switch (evt.data.command) {
- case 'readyState':
- this.setReadyState(evt.data.img, evt.data.cue);
- if (evt.data.img && evt.data.cue)
- this.startInstall();
- break;
- case 'extractFiles':
- this.populateFiles(evt.data.files, evt.data.volumeLabel);
- break;
- case 'complete':
- this.cddaCallback(evt.data.wav);
- this.cddaCallback = null;
- break;
- case 'error':
- console.log(evt.data.message);
- break;
- default:
- throw('unknown command: ' + evt.data.command);
+ private async setFile(file: File) {
+ let name = file.name.toLowerCase();
+ if (name.endsWith('.img') || name.endsWith('.mdf')) {
+ this.imgFile = file;
+ $('#imgReady').classList.remove('notready');
+ $('#imgReady').textContent = file.name;
+ } else if (name.endsWith('.cue') || name.endsWith('.mds')) {
+ this.cueFile = file;
+ $('#cueReady').classList.remove('notready');
+ $('#cueReady').textContent = file.name;
+ }
+ if (this.imgFile && this.cueFile) {
+ if (this.cueFile.name.endsWith('.cue'))
+ this.imageReader = await ImgCueReader.create(this.imgFile, this.cueFile);
+ else
+ this.imageReader = await MdfMdsReader.create(this.imgFile, this.cueFile);
+ await this.installAndRun();
}
}
- private onWorkerError(evt: Event) {
- console.log('worker error', evt);
+ private async extractFile(isofs: ISO9660FileSystem, entry: DirEnt): Promise {
+ let buffer = new ArrayBuffer(entry.size);
+ let uint8 = new Uint8Array(buffer);
+ let ptr = 0;
+ for (let buf of await isofs.readFile(entry)) {
+ uint8.set(buf, ptr);
+ ptr += buf.byteLength;
+ }
+ if (ptr !== entry.size)
+ throw ('expected ' + entry.size + ' bytes, but read ' + ptr + 'bytes');
+ return buffer;
+ }
+
+ private async installAndRun() {
+ let isofs = await ISO9660FileSystem.create(this.imageReader);
+ // this.walk(isofs, isofs.rootDir(), '/');
+ let gamedata = await isofs.getDirEnt('gamedata', isofs.rootDir());
+ if (!gamedata) {
+ this.setError('インストールできません。GAMEDATAフォルダが見つかりません。');
+ return;
+ }
+ let grGenerator = new GameResourceGenerator();
+ for (let e of await isofs.readDir(gamedata)) {
+ if (e.name.toLowerCase().endsWith('.ald')) {
+ let data = await this.extractFile(isofs, e);
+ // Store contents in the emscripten heap, so that it can be mmap-ed without copying
+ let ptr = Module.getMemory(data.byteLength);
+ Module.HEAPU8.set(new Uint8Array(data), ptr);
+ FS.writeFile(e.name, Module.HEAPU8.subarray(ptr, ptr + data.byteLength),
+ { encoding: 'binary', canOwn: true });
+ grGenerator.addFile(e.name);
+ }
+ }
+ FS.writeFile('xsystem35.gr', grGenerator.generate());
+ FS.writeFile('.xsys35rc', xsystem35.xsys35rc);
+ this.runMain();
+ }
+
+ private setError(msg: string) {
+ console.log(msg);
+ }
+
+ // For debug
+ private async walk(isofs: ISO9660FileSystem, dir: DirEnt, dirname: string) {
+ for (let e of await isofs.readDir(dir)) {
+ if (e.name !== '\0' && e.name !== '\x01') {
+ console.log(dirname + e.name);
+ if (e.isDirectory)
+ this.walk(isofs, e, dirname + e.name + '/');
+ }
+ }
}
}
diff --git a/web/shell/package.json b/web/shell/package.json
index 81dcf6d..024e867 100644
--- a/web/shell/package.json
+++ b/web/shell/package.json
@@ -3,6 +3,7 @@
"version": "1.0.0",
"description": "",
"dependencies": {
- "@types/emscripten": "0.0.29"
+ "@types/emscripten": "0.0.29",
+ "@types/text-encoding": "0.0.30"
}
}
diff --git a/web/worker/text-decoder.ts b/web/shell/text-decoder.ts
similarity index 77%
rename from web/worker/text-decoder.ts
rename to web/shell/text-decoder.ts
index 3d22b65..7178d9d 100644
--- a/web/worker/text-decoder.ts
+++ b/web/shell/text-decoder.ts
@@ -14,5 +14,5 @@ class FallbackTextDecoder {
}
}
-if (!(self).TextDecoder)
- (self).TextDecoder = FallbackTextDecoder;
+if (!(window).TextDecoder)
+ (window).TextDecoder = FallbackTextDecoder;
diff --git a/web/worker/imagereader-worker.ts b/web/worker/imagereader-worker.ts
deleted file mode 100644
index c7481da..0000000
--- a/web/worker/imagereader-worker.ts
+++ /dev/null
@@ -1,99 +0,0 @@
-importScripts('cdimage.js');
-
-declare function postMessage(data: any, transfers: any): void;
-
-class Installer {
- private imgFile: File;
- private cueFile: File;
- private imageReader: CDImageReader;
-
- constructor() {
- addEventListener('message', this.onMessage.bind(this));
- }
-
- private async onMessage(evt: MessageEvent) {
- switch (evt.data.command) {
- case 'setFile':
- await this.setFile(evt.data.file);
- let imgName = this.imgFile && this.imgFile.name;
- let cueName = this.cueFile && this.cueFile.name;
- postMessage({command: 'readyState', img: imgName, cue: cueName});
- break;
- case 'extractFiles':
- if (this.ready())
- this.extractFiles();
- break;
- case 'getTrack':
- if (this.ready())
- this.getTrack(evt.data.track);
- break;
- default:
- throw('unknown command: ' + evt.data.command);
- }
- }
-
- private async setFile(file: File) {
- let name = file.name.toLowerCase();
- if (name.endsWith('.img') || name.endsWith('.mdf'))
- this.imgFile = file;
- else if (name.endsWith('.cue') || name.endsWith('.mds'))
- this.cueFile = file;
- if (this.imgFile && this.cueFile) {
- if (this.cueFile.name.endsWith('.cue'))
- this.imageReader = await ImgCueReader.create(this.imgFile, this.cueFile);
- else
- this.imageReader = await MdfMdsReader.create(this.imgFile, this.cueFile);
- }
- }
-
- private ready(): boolean {
- return !!this.imageReader;
- }
-
- private async extractFiles() {
- let isofs = await ISO9660FileSystem.create(this.imageReader);
- // this.walk(isofs, isofs.rootDir(), '/');
- let gamedata = await isofs.getDirEnt('gamedata', isofs.rootDir());
- if (!gamedata) {
- postMessage({command: 'error', message: 'インストールできません。GAMEDATAフォルダが見つかりません。'});
- return;
- }
- let files: any = {};
- let transfers = [];
- for (let e of await isofs.readDir(gamedata)) {
- if (e.name.toLowerCase().endsWith('.ald')) {
- let buffer = new ArrayBuffer(e.size);
- let uint8 = new Uint8Array(buffer);
- let ptr = 0;
- for (let buf of await isofs.readFile(e)) {
- uint8.set(buf, ptr);
- ptr += buf.byteLength;
- }
- if (ptr !== e.size)
- throw('expected ' + e.size + ' bytes, but read ' + ptr + 'bytes');
- files[e.name] = buffer;
- transfers.push(buffer);
- }
- }
- postMessage({command: 'extractFiles',
- volumeLabel: isofs.volumeLabel(),
- files}, transfers);
- }
-
- private async walk(isofs: ISO9660FileSystem, dir: DirEnt, dirname: string) {
- for (let e of await isofs.readDir(dir)) {
- if (e.name !== '\0' && e.name !== '\x01') {
- console.log(dirname + e.name);
- if (e.isDirectory)
- this.walk(isofs, e, dirname + e.name + '/');
- }
- }
- }
-
- private async getTrack(track: number) {
- let blob = await this.imageReader.extractTrack(track);
- postMessage({command: 'complete', track, wav: blob});
- }
-}
-
-let installer = new Installer();
diff --git a/web/worker/package.json b/web/worker/package.json
deleted file mode 100644
index 4ee2ce7..0000000
--- a/web/worker/package.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "name": "xsystem35-worker",
- "version": "1.0.0",
- "description": "",
- "dependencies": {
- "@types/text-encoding": "0.0.30"
- }
-}
diff --git a/web/worker/tsconfig.json b/web/worker/tsconfig.json
deleted file mode 100644
index ec80b37..0000000
--- a/web/worker/tsconfig.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "compilerOptions": {
- "module": "commonjs",
- "target": "es6",
- "outDir": "../../docs",
- "lib": ["es6", "webworker"],
- "noImplicitAny": true,
- "sourceMap": false
- }
-}
\ No newline at end of file
diff --git a/web/worker/tslint.json b/web/worker/tslint.json
deleted file mode 120000
index b9c0b95..0000000
--- a/web/worker/tslint.json
+++ /dev/null
@@ -1 +0,0 @@
-../shell/tslint.json
\ No newline at end of file