diff --git a/web/shell/audio.ts b/web/shell/audio.ts
index 11f5bad..043e1bb 100644
--- a/web/shell/audio.ts
+++ b/web/shell/audio.ts
@@ -2,113 +2,6 @@
///
namespace xsystem35 {
- abstract class PCMSound {
- protected context: AudioContext;
- protected gain: GainNode;
- protected duration_: number;
- protected startTime: number;
-
- constructor(protected dst: AudioNode) {
- this.context = dst.context;
- this.gain = this.context.createGain();
- this.gain.connect(dst);
- }
- abstract start(loop: number): void;
- abstract stop(): void;
- setGain(gain: number) {
- this.gain.gain.value = gain;
- }
- fadeout(msec: number) {
- this.gain.gain.linearRampToValueAtTime(0, this.context.currentTime + msec / 1000);
- }
- getPosition(): number {
- if (!this.startTime)
- return 0;
- return this.context.currentTime - this.startTime;
- }
- isPlaying(): boolean {
- return !!this.startTime;
- }
- get duration(): number {
- return this.duration_;
- }
- }
-
- class PCMSoundSimple extends PCMSound {
- private node: AudioBufferSourceNode;
-
- constructor(dst: AudioNode, buf: AudioBuffer) {
- super(dst);
- this.node = this.context.createBufferSource();
- this.node.buffer = buf;
- this.node.connect(this.gain);
- this.node.onended = this.onended.bind(this);
- this.duration_ = buf.duration;
- }
-
- start(loop: number) {
- if (loop == 0)
- this.node.loop = true;
- else if (loop != 1)
- console.warn('Unsupported PCM loop count ' + loop);
- this.node.start();
- this.startTime = this.context.currentTime;
- }
-
- stop() {
- if (this.startTime) {
- this.node.stop();
- this.startTime = null;
- }
- }
-
- private onended() {
- this.startTime = null;
- }
- }
-
- class PCMSoundMixLR extends PCMSound {
- private lsrc: AudioBufferSourceNode;
- private rsrc: AudioBufferSourceNode;
- private endCount = 0;
-
- constructor(dst: AudioNode, lbuf: AudioBuffer, rbuf: AudioBuffer) {
- super(dst);
- this.lsrc = this.context.createBufferSource();
- this.rsrc = this.context.createBufferSource();
- this.lsrc.buffer = lbuf;
- this.rsrc.buffer = rbuf;
- var merger = this.context.createChannelMerger(2);
- merger.connect(this.gain);
- this.lsrc.connect(merger, 0, 0);
- this.rsrc.connect(merger, 0, 1);
- this.lsrc.onended = this.rsrc.onended = this.onended.bind(this);
- this.duration_ = Math.max(lbuf.duration, rbuf.duration);
- }
-
- start(loop: number) {
- if (loop != 1)
- console.warn('PCMSoundMixLR: loop is not supported ' + loop);
- this.lsrc.start();
- this.rsrc.start();
- this.startTime = this.context.currentTime;
- }
-
- stop() {
- if (this.startTime) {
- this.lsrc.stop();
- this.rsrc.stop();
- this.startTime = null;
- }
- }
-
- private onended() {
- this.endCount++;
- if (this.endCount == 2)
- this.startTime = null;
- }
- }
-
declare var webkitAudioContext: any;
export class AudioManager {
private context: AudioContext;
@@ -134,8 +27,8 @@ namespace xsystem35 {
}
private removeUserGestureRestriction() {
- var hanlder = () => {
- var src = this.context.createBufferSource();
+ let hanlder = () => {
+ let src = this.context.createBufferSource();
src.buffer = this.context.createBuffer(1, 1, 22050);
src.connect(this.context.destination);
src.start();
@@ -146,11 +39,11 @@ namespace xsystem35 {
}
private load(no: number): Promise {
- var buf = this.getWave(no);
+ let buf = this.getWave(no);
if (!buf)
return Promise.reject('Failed to open wave ' + no);
- var decoded: Promise;
+ let decoded: Promise;
if (this.isSafari) {
decoded = new Promise((resolve, reject) => {
this.context.decodeAudioData(buf, resolve, reject);
@@ -165,12 +58,12 @@ namespace xsystem35 {
}
private getWave(no: number): ArrayBuffer {
- var dfile = _ald_getdata(2 /* DRIFILE_WAVE */, no - 1);
+ let dfile = _ald_getdata(2 /* DRIFILE_WAVE */, no - 1);
if (!dfile)
return null;
- var ptr = Module.getValue(dfile + 8, '*');
- var size = Module.getValue(dfile, 'i32');
- var buf = Module.HEAPU8.buffer.slice(ptr, ptr + size);
+ let ptr = Module.getValue(dfile + 8, '*');
+ let size = Module.getValue(dfile, 'i32');
+ let buf = Module.HEAPU8.buffer.slice(ptr, ptr + size);
_ald_freedata(dfile);
return buf;
}
@@ -196,7 +89,7 @@ namespace xsystem35 {
this.slots[slot] = new PCMSoundMixLR(this.masterGain, this.buffers[noL], this.buffers[noR]);
return resume();
}
- var ps = [];
+ let ps = [];
if (!this.buffers[noL]) ps.push(this.load(noL));
if (!this.buffers[noR]) ps.push(this.load(noR));
Promise.all(ps).then(() => {
@@ -258,4 +151,114 @@ namespace xsystem35 {
this.masterGain.gain.value = evt.detail;
}
}
-}
\ No newline at end of file
+
+ abstract class PCMSound {
+ protected context: AudioContext;
+ protected gain: GainNode;
+ protected startTime: number;
+
+ constructor(protected dst: AudioNode) {
+ this.context = dst.context;
+ this.gain = this.context.createGain();
+ this.gain.connect(dst);
+ }
+ abstract start(loop: number): void;
+ abstract stop(): void;
+ setGain(gain: number) {
+ this.gain.gain.value = gain;
+ }
+ fadeout(msec: number) {
+ this.gain.gain.linearRampToValueAtTime(0, this.context.currentTime + msec / 1000);
+ }
+ getPosition(): number {
+ if (!this.startTime)
+ return 0;
+ return this.context.currentTime - this.startTime;
+ }
+ isPlaying(): boolean {
+ return !!this.startTime;
+ }
+ abstract get duration(): number;
+ }
+
+ class PCMSoundSimple extends PCMSound {
+ private node: AudioBufferSourceNode;
+
+ constructor(dst: AudioNode, buf: AudioBuffer) {
+ super(dst);
+ this.node = this.context.createBufferSource();
+ this.node.buffer = buf;
+ this.node.connect(this.gain);
+ this.node.onended = this.onended.bind(this);
+ }
+
+ start(loop: number) {
+ if (loop === 0)
+ this.node.loop = true;
+ else if (loop !== 1)
+ console.warn('Unsupported PCM loop count ' + loop);
+ this.node.start();
+ this.startTime = this.context.currentTime;
+ }
+
+ stop() {
+ if (this.startTime) {
+ this.node.stop();
+ this.startTime = null;
+ }
+ }
+
+ get duration() {
+ return this.node.buffer.duration;
+ }
+
+ private onended() {
+ this.startTime = null;
+ }
+ }
+
+ class PCMSoundMixLR extends PCMSound {
+ private lsrc: AudioBufferSourceNode;
+ private rsrc: AudioBufferSourceNode;
+ private endCount = 0;
+
+ constructor(dst: AudioNode, lbuf: AudioBuffer, rbuf: AudioBuffer) {
+ super(dst);
+ this.lsrc = this.context.createBufferSource();
+ this.rsrc = this.context.createBufferSource();
+ this.lsrc.buffer = lbuf;
+ this.rsrc.buffer = rbuf;
+ let merger = this.context.createChannelMerger(2);
+ merger.connect(this.gain);
+ this.lsrc.connect(merger, 0, 0);
+ this.rsrc.connect(merger, 0, 1);
+ this.lsrc.onended = this.rsrc.onended = this.onended.bind(this);
+ }
+
+ start(loop: number) {
+ if (loop !== 1)
+ console.warn('PCMSoundMixLR: loop is not supported ' + loop);
+ this.lsrc.start();
+ this.rsrc.start();
+ this.startTime = this.context.currentTime;
+ }
+
+ stop() {
+ if (this.startTime) {
+ this.lsrc.stop();
+ this.rsrc.stop();
+ this.startTime = null;
+ }
+ }
+
+ get duration() {
+ return Math.max(this.lsrc.buffer.duration, this.rsrc.buffer.duration);
+ }
+
+ private onended() {
+ this.endCount++;
+ if (this.endCount === 2)
+ this.startTime = null;
+ }
+ }
+}
diff --git a/web/shell/cdda.ts b/web/shell/cdda.ts
index 14fefef..009bb96 100644
--- a/web/shell/cdda.ts
+++ b/web/shell/cdda.ts
@@ -13,7 +13,7 @@ namespace xsystem35 {
volumeControl.addEventListener(this.onVolumeChanged.bind(this));
this.audio.volume = volumeControl.volume();
this.waiting = false;
- this.removeUserGestureRestriction()
+ this.removeUserGestureRestriction();
}
play(track: number, loop: number) {
@@ -37,13 +37,13 @@ namespace xsystem35 {
getPosition(): number {
if (!this.currentTrack)
return 0;
- var time = Math.round(this.audio.currentTime * 75);
+ let time = Math.round(this.audio.currentTime * 75);
return this.currentTrack | time << 8;
}
private startPlayback(blob: Blob, loop: number) {
this.audio.setAttribute('src', URL.createObjectURL(blob));
- this.audio.loop = (loop != 0);
+ this.audio.loop = (loop !== 0);
this.audio.load();
this.audio.play();
this.waiting = false;
@@ -54,7 +54,7 @@ namespace xsystem35 {
}
private removeUserGestureRestriction() {
- var hanlder = () => {
+ let hanlder = () => {
this.audio.load();
console.log('CDDA unlocked');
window.removeEventListener('touchend', hanlder);
diff --git a/web/shell/loader.ts b/web/shell/loader.ts
index ee9f4ec..28a94d4 100644
--- a/web/shell/loader.ts
+++ b/web/shell/loader.ts
@@ -5,7 +5,7 @@ namespace xsystem35 {
private worker: Worker;
private cddaCallback: (wab: Blob) => void;
- constructor(private runMain: ()=>void) {
+ constructor(private runMain: () => void) {
this.initWorker();
$('#fileselect').addEventListener('change', this.handleFileSelect.bind(this), false);
document.body.ondragover = this.handleDragOver.bind(this);
@@ -13,7 +13,7 @@ namespace xsystem35 {
}
getCDDA(track: number, callback: (wav: Blob) => void) {
- this.send({ command: 'getTrack', track: track });
+ this.send({ command: 'getTrack', track });
this.cddaCallback = callback;
}
@@ -35,13 +35,14 @@ namespace xsystem35 {
}
private populateFiles(files: any, volumeLabel: string) {
- var grGenerator = new GameResourceGenerator();
- for (var name in files) {
- var data: ArrayBuffer = files[name];
+ 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
- var ptr = Module.getMemory(data.byteLength);
+ 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 });
+ FS.writeFile(name, Module.HEAPU8.subarray(ptr, ptr + data.byteLength),
+ { encoding: 'binary', canOwn: true });
grGenerator.addFile(name);
}
FS.writeFile('xsystem35.gr', grGenerator.generate());
@@ -51,9 +52,9 @@ namespace xsystem35 {
}
private handleFileSelect(evt: Event) {
- var input = evt.target;
- var files = input.files;
- for (var i = 0; i < files.length; i++)
+ let input = evt.target;
+ let files = input.files;
+ for (let i = 0; i < files.length; i++)
this.setFile(files[i]);
input.value = '';
}
@@ -67,13 +68,13 @@ namespace xsystem35 {
private handleDrop(evt: DragEvent) {
evt.stopPropagation();
evt.preventDefault();
- var files = evt.dataTransfer.files;
- for (var i = 0; i < files.length; i++)
+ let files = evt.dataTransfer.files;
+ for (let i = 0; i < files.length; i++)
this.setFile(files[i]);
}
private setFile(file: File) {
- this.send({ command: 'setFile', file: file });
+ this.send({ command: 'setFile', file });
}
private startInstall() {
@@ -101,6 +102,8 @@ namespace xsystem35 {
case 'error':
console.log(evt.data.message);
break;
+ default:
+ throw('unknown command: ' + evt.data.command);
}
}
@@ -110,27 +113,28 @@ namespace xsystem35 {
}
class GameResourceGenerator {
- static resourceType: { [ch: string]: string } = { s: 'Scenario', g: 'Graphics', w: 'Wave', d: 'Data', r: 'Resource', m: 'Midi' };
+ static resourceType: { [ch: string]: string } =
+ { s: 'Scenario', g: 'Graphics', w: 'Wave', d: 'Data', r: 'Resource', m: 'Midi' };
private basename: string;
private lines: string[] = [];
addFile(name: string) {
- var type = name.charAt(name.length - 6).toLowerCase();
- var id = name.charAt(name.length - 5);
+ let type = name.charAt(name.length - 6).toLowerCase();
+ let id = name.charAt(name.length - 5);
this.basename = name.slice(0, -6);
this.lines.push(GameResourceGenerator.resourceType[type] + id.toUpperCase() + ' ' + name);
}
generate(): string {
- for (var i = 0; i < 26; i++) {
- var id = String.fromCharCode(65 + i);
+ for (let i = 0; i < 26; i++) {
+ let id = String.fromCharCode(65 + i);
this.lines.push('Save' + id + ' save/' + this.basename + 's' + id.toLowerCase() + '.asd');
}
return this.lines.join('\n') + '\n';
}
isEmpty(): boolean {
- return this.lines.length == 0;
+ return this.lines.length === 0;
}
}
}
diff --git a/web/shell/shell.ts b/web/shell/shell.ts
index 494d073..e4f9b30 100644
--- a/web/shell/shell.ts
+++ b/web/shell/shell.ts
@@ -10,10 +10,10 @@ namespace xsystem35 {
export const xsys35rc = [
'font_device: ttf',
'ttfont_mincho: ' + Font.fname,
- 'ttfont_gothic: ' + Font.fname, ''
+ 'ttfont_gothic: ' + Font.fname, '',
].join('\n');
- export var cdPlayer: CDPlayer;
- export var audio: AudioManager;
+ export let cdPlayer: CDPlayer;
+ export let audio: AudioManager;
class System35Shell {
private imageLoader: ImageLoader;
@@ -46,15 +46,15 @@ namespace xsystem35 {
FS.mkdir('/save');
FS.mount(IDBFS, {}, '/save');
Module.addRunDependency('syncfs');
- FS.syncfs(true, (err) => { Module.removeRunDependency('syncfs') });
- }
+ FS.syncfs(true, (err) => { Module.removeRunDependency('syncfs'); });
+ },
];
this.volumeControl = new VolumeControl();
xsystem35.cdPlayer = new CDPlayer(this.imageLoader, this.volumeControl);
this.zoom = new ZoomManager();
this.antialiasCheckbox = $('#antialias');
this.antialiasCheckbox.addEventListener('change', this.antialiasChanged.bind(this));
- this.antialiasCheckbox.checked = localStorage.getItem('antialias') != 'false';
+ this.antialiasCheckbox.checked = localStorage.getItem('antialias') !== 'false';
xsystem35.audio = new AudioManager(this.volumeControl);
}
@@ -83,7 +83,7 @@ namespace xsystem35 {
this.fsyncTimer = window.setTimeout(() => {
FS.syncfs(false, (err) => {
if (err)
- console.log("FS.syncfs error: ", err);
+ console.log('FS.syncfs error: ', err);
});
}, 100);
}
@@ -94,7 +94,7 @@ namespace xsystem35 {
}
private addRightClickEmulation() {
- var emulatingRightClick = false;
+ let emulatingRightClick = false;
document.body.addEventListener('touchstart', (e) => {
if (e.target !== document.body)
return;
@@ -110,5 +110,5 @@ namespace xsystem35 {
}
}
- export var shell = new System35Shell();
+ export let shell = new System35Shell();
}
diff --git a/web/shell/tslint.json b/web/shell/tslint.json
new file mode 100644
index 0000000..5d99943
--- /dev/null
+++ b/web/shell/tslint.json
@@ -0,0 +1,27 @@
+{
+ "extends": "tslint:recommended",
+ "rules": {
+ "curly": false,
+ "interface-name": false,
+ "max-classes-per-file": false,
+ "member-access": false,
+ "member-ordering": false,
+ "no-bitwise": false,
+ "no-empty": false,
+ "no-namespace": false,
+ "no-reference": false,
+ "only-arrow-functions": ["allow-declarations", "allow-named-functions"],
+ "prefer-for-of": false,
+ "quotemark": [true, "single", "avoid-escape"],
+ "whitespace": [
+ true,
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-separator",
+ "check-type"
+ ],
+
+ "no-console": false
+ }
+}
\ No newline at end of file
diff --git a/web/shell/util.ts b/web/shell/util.ts
index 537ab37..bcd938d 100644
--- a/web/shell/util.ts
+++ b/web/shell/util.ts
@@ -1,4 +1,4 @@
-var $: (selector:string)=>HTMLElement = document.querySelector.bind(document);
+let $: (selector: string) => HTMLElement = document.querySelector.bind(document);
// xsystem35 exported functions
declare function _musfade_setvolval_all(vol: number): void;
@@ -8,10 +8,10 @@ declare function _ald_getdata(type: number, no: number): number;
declare function _ald_freedata(data: number): void;
declare namespace Module {
- var noInitialRun: boolean;
+ let noInitialRun: boolean;
// Undocumented methods / attributes
- var canvas: HTMLElement;
+ let canvas: HTMLElement;
function setStatus(status: string): void;
function monitorRunDependencies(left: number): void;
function callMain(): void;
@@ -19,9 +19,10 @@ declare namespace Module {
}
declare namespace FS {
- function writeFile(path: string, data: ArrayBufferView | string, opts?: {encoding?: string; flags?: string; canOwn?: boolean}): void;
+ function writeFile(path: string, data: ArrayBufferView | string,
+ opts?: {encoding?: string; flags?: string; canOwn?: boolean}): void;
}
declare namespace EmterpreterAsync {
- function handle(asyncOp: (resume:()=>void) => void): void;
+ function handle(asyncOp: (resume: () => void) => void): void;
}
diff --git a/web/shell/volume.ts b/web/shell/volume.ts
index a3d12c8..afe97e7 100644
--- a/web/shell/volume.ts
+++ b/web/shell/volume.ts
@@ -23,7 +23,7 @@ namespace xsystem35 {
}
volume(): number {
- return this.muted ? 0 : parseInt(this.slider.value) / 100;
+ return this.muted ? 0 : parseInt(this.slider.value, 10) / 100;
}
addEventListener(handler: (evt: CustomEvent) => any) {
@@ -45,7 +45,7 @@ namespace xsystem35 {
}
private onSliderValueChanged(e: Event) {
- this.vol = parseInt(this.slider.value) / 100;
+ this.vol = parseInt(this.slider.value, 10) / 100;
if (this.vol > 0 && this.muted) {
this.muted = false;
this.icon.classList.remove('fa-volume-off');
@@ -59,7 +59,7 @@ namespace xsystem35 {
}
private dispatchEvent() {
- var event = new CustomEvent('volumechange', { detail: this.volume() });
+ let event = new CustomEvent('volumechange', { detail: this.volume() });
this.elem.dispatchEvent(event);
}
}
diff --git a/web/shell/zoom.ts b/web/shell/zoom.ts
index ef633fe..542e36b 100644
--- a/web/shell/zoom.ts
+++ b/web/shell/zoom.ts
@@ -13,21 +13,21 @@ namespace xsystem35 {
this.zoomSelect.value = localStorage.getItem('zoom') || '1';
this.smoothingCheckbox = $('#smoothing');
this.smoothingCheckbox.addEventListener('change', this.handleSmoothing.bind(this));
- if (localStorage.getItem('smoothing') == 'false') {
+ if (localStorage.getItem('smoothing') === 'false') {
this.smoothingCheckbox.checked = false;
this.handleSmoothing();
}
}
handleZoom() {
- var value = this.zoomSelect.value;
+ let value = this.zoomSelect.value;
localStorage.setItem('zoom', value);
- var contentsStyle = $('.contents').style;
- if (value == 'fit') {
+ let contentsStyle = $('.contents').style;
+ if (value === 'fit') {
contentsStyle.maxWidth = 'none';
contentsStyle.width = this.canvas.style.width = '100%';
} else {
- var ratio = Number(value);
+ let ratio = Number(value);
contentsStyle.maxWidth = 'none';
contentsStyle.width = this.canvas.style.width = this.canvas.width * ratio + 'px';
}
diff --git a/web/worker/cdimage.ts b/web/worker/cdimage.ts
index 6dc2ba0..ccde71a 100644
--- a/web/worker/cdimage.ts
+++ b/web/worker/cdimage.ts
@@ -5,7 +5,7 @@ class ISO9660FileSystem {
constructor(private sectorReader: CDImageReader) {
this.pvd = new PVD(sectorReader.readSector(0x10));
- if (this.pvd.type != 1)
+ if (this.pvd.type !== 1)
throw('PVD not found');
}
@@ -17,25 +17,26 @@ class ISO9660FileSystem {
return this.pvd.rootDirEnt();
}
- getDirEnt(name:string, parent:DirEnt): DirEnt {
+ getDirEnt(name: string, parent: DirEnt): DirEnt {
name = name.toLowerCase();
- for (var e of this.readDir(parent)) {
- if (e.name.toLowerCase() == name)
+ for (let e of this.readDir(parent)) {
+ if (e.name.toLowerCase() === name)
return e;
}
return null;
}
- readDir(dirent:DirEnt): DirEnt[] {
- var sector = dirent.sector;
- var position = 0;
- var length = dirent.size;
- var entries:DirEnt[] = [];
+ readDir(dirent: DirEnt): DirEnt[] {
+ let sector = dirent.sector;
+ let position = 0;
+ let length = dirent.size;
+ let entries: DirEnt[] = [];
+ let buf: ArrayBuffer;
while (position < length) {
- if (position == 0)
- var buf = this.sectorReader.readSector(sector);
- var child = new DirEnt(buf, position);
- if (child.length == 0) {
+ if (position === 0)
+ buf = this.sectorReader.readSector(sector);
+ let child = new DirEnt(buf, position);
+ if (child.length === 0) {
// Padded end of sector
position = 2048;
} else {
@@ -44,7 +45,7 @@ class ISO9660FileSystem {
}
if (position > 2048)
throw('dirent across sector boundary');
- if (position == 2048) {
+ if (position === 2048) {
sector++;
position = 0;
length -= 2048;
@@ -53,21 +54,21 @@ class ISO9660FileSystem {
return entries;
}
- readFile(dirent:DirEnt): Uint8Array[] {
+ readFile(dirent: DirEnt): Uint8Array[] {
return this.sectorReader.readSequentialSectors(dirent.sector, dirent.size);
}
}
class PVD {
- private view:DataView;
- constructor(private buf:ArrayBuffer) {
+ private view: DataView;
+ constructor(private buf: ArrayBuffer) {
this.view = new DataView(buf);
}
get type(): number {
return this.view.getUint8(0);
}
volumeLabel(): string {
- var decoder = new TextDecoder('shift_jis');
+ let decoder = new TextDecoder('shift_jis');
return decoder.decode(new DataView(this.buf, 40, 32)).trim();
}
rootDirEnt(): DirEnt {
@@ -76,8 +77,8 @@ class PVD {
}
class DirEnt {
- private view:DataView;
- constructor(private buf:ArrayBuffer, private offset:number) {
+ private view: DataView;
+ constructor(private buf: ArrayBuffer, private offset: number) {
this.view = new DataView(buf, offset);
}
get length(): number {
@@ -90,35 +91,35 @@ class DirEnt {
return this.view.getUint32(10, true);
}
get isDirectory(): boolean {
- return (this.view.getUint8(25) & 2) != 0;
+ return (this.view.getUint8(25) & 2) !== 0;
}
get name(): string {
- var len = this.view.getUint8(32);
- var decoder = new TextDecoder('shift_jis');
- return decoder.decode(new DataView(this.buf, this.offset+33, len)).split(';')[0];
+ let len = this.view.getUint8(32);
+ let decoder = new TextDecoder('shift_jis');
+ return decoder.decode(new DataView(this.buf, this.offset + 33, len)).split(';')[0];
}
}
interface CDImageReader {
- readSector(sector:number): ArrayBuffer;
+ readSector(sector: number): ArrayBuffer;
readSequentialSectors(startSector: number, length: number): Uint8Array[];
maxTrack(): number;
- extractTrack(track:number): Blob;
+ extractTrack(track: number): Blob;
}
class ImageReaderBase {
- constructor(public image:File) {}
+ constructor(public image: File) {}
- readSequential(startOffset:number,
- bytesToRead:number,
- blockSize:number,
- sectorSize:number,
- sectorOffset:number): Uint8Array[] {
- var sectors = Math.ceil(bytesToRead / sectorSize);
- var blob = this.image.slice(startOffset, startOffset + sectors * blockSize);
- var buf = new FileReaderSync().readAsArrayBuffer(blob);
- var bufs:Uint8Array[] = [];
- for (var i = 0; i < sectors; i++) {
+ readSequential(startOffset: number,
+ bytesToRead: number,
+ blockSize: number,
+ sectorSize: number,
+ sectorOffset: number): Uint8Array[] {
+ let sectors = Math.ceil(bytesToRead / sectorSize);
+ let blob = this.image.slice(startOffset, startOffset + sectors * blockSize);
+ let buf = new FileReaderSync().readAsArrayBuffer(blob);
+ let bufs: Uint8Array[] = [];
+ for (let i = 0; i < sectors; i++) {
bufs.push(new Uint8Array(buf, i * blockSize + sectorOffset, Math.min(bytesToRead, sectorSize)));
bytesToRead -= sectorSize;
}
@@ -127,16 +128,16 @@ class ImageReaderBase {
}
class ImgCueReader extends ImageReaderBase implements CDImageReader {
- private tracks:{ type:string; index:string[]; }[];
+ private tracks: Array<{ type: string; index: string[]; }>;
- constructor(img:File, cue:File) {
+ constructor(img: File, cue: File) {
super(img);
this.parseCue(cue);
}
- readSector(sector:number): ArrayBuffer {
- var start = sector * 2352 + 16;
- var end = start + 2048;
+ readSector(sector: number): ArrayBuffer {
+ let start = sector * 2352 + 16;
+ let end = start + 2048;
return new FileReaderSync().readAsArrayBuffer(this.image.slice(start, end));
}
@@ -144,115 +145,117 @@ class ImgCueReader extends ImageReaderBase implements CDImageReader {
return this.readSequential(startSector * 2352, length, 2352, 2048, 16);
}
- private parseCue(cueFile:File) {
- var lines = new FileReaderSync().readAsText(cueFile).split('\n');
+ private parseCue(cueFile: File) {
+ let lines = new FileReaderSync().readAsText(cueFile).split('\n');
this.tracks = [];
- var currentTrack:number = null;
- for (var line of lines) {
- var fields = line.trim().split(/\s+/);
+ let currentTrack: number = null;
+ for (let line of lines) {
+ let fields = line.trim().split(/\s+/);
switch (fields[0]) {
case 'TRACK':
currentTrack = Number(fields[1]);
- this.tracks[currentTrack] = {type:fields[2], index:[]};
+ this.tracks[currentTrack] = {type: fields[2], index: []};
break;
case 'INDEX':
if (currentTrack)
this.tracks[currentTrack].index[Number(fields[1])] = fields[2];
break;
+ default:
+ ; // Do nothing
}
}
}
- maxTrack():number {
+ maxTrack(): number {
return this.tracks.length - 1;
}
- extractTrack(track:number): Blob {
- if (!this.tracks[track] || this.tracks[track].type != 'AUDIO')
+ extractTrack(track: number): Blob {
+ if (!this.tracks[track] || this.tracks[track].type !== 'AUDIO')
return;
- var start = this.indexToSector(this.tracks[track].index[1]) * 2352;
- var end:number;
- if (this.tracks[track+1]) {
- var index = this.tracks[track+1].index[0] || this.tracks[track+1].index[1];
+ let start = this.indexToSector(this.tracks[track].index[1]) * 2352;
+ let end: number;
+ if (this.tracks[track + 1]) {
+ let index = this.tracks[track + 1].index[0] || this.tracks[track + 1].index[1];
end = this.indexToSector(index) * 2352;
} else {
end = this.image.size;
}
- var size = end - start;
+ let size = end - start;
return new Blob([createWaveHeader(size), this.image.slice(start, start + size)], {type : 'audio/wav'});
}
- private indexToSector(index:string):number {
- var msf = index.split(':').map(Number);
- return msf[0]*60*75 + msf[1]*75 + msf[2];
+ private indexToSector(index: string): number {
+ let msf = index.split(':').map(Number);
+ return msf[0] * 60 * 75 + msf[1] * 75 + msf[2];
}
}
enum MdsTrackMode { Audio = 0xa9, Mode1 = 0xaa };
class MdfMdsReader extends ImageReaderBase implements CDImageReader {
- private tracks:{ mode:number; sectorSize:number; offset:number; sectors:number; }[];
+ private tracks: Array<{ mode: number; sectorSize: number; offset: number; sectors: number; }>;
- constructor(mdf:File, mds:File) {
+ constructor(mdf: File, mds: File) {
super(mdf);
this.parseMds(mds);
}
- private parseMds(mdsFile:File) {
- var buf = new FileReaderSync().readAsArrayBuffer(mdsFile);
+ private parseMds(mdsFile: File) {
+ let buf = new FileReaderSync().readAsArrayBuffer(mdsFile);
- var signature = new TextDecoder().decode(new DataView(buf, 0, 16));
- if (signature != 'MEDIA DESCRIPTOR')
+ let signature = new TextDecoder().decode(new DataView(buf, 0, 16));
+ if (signature !== 'MEDIA DESCRIPTOR')
throw mdsFile.name + ': not a mds file';
- var header = new DataView(buf, 0, 0x70);
- var entries = header.getUint8(0x62);
+ let header = new DataView(buf, 0, 0x70);
+ let entries = header.getUint8(0x62);
this.tracks = [];
- for (var i = 0; i < entries; i++) {
- var trackData = new DataView(buf, 0x70 + i * 0x50, 0x50);
- var extraData = new DataView(buf, 0x70 + entries * 0x50 + i * 8, 8);
- var mode = trackData.getUint8(0x00);
- var track = trackData.getUint8(0x04);
- var sectorSize = trackData.getUint16(0x10, true);
- var offset = trackData.getUint32(0x28, true); // >4GB offset is not supported.
- var sectors = extraData.getUint32(0x4, true);
+ for (let i = 0; i < entries; i++) {
+ let trackData = new DataView(buf, 0x70 + i * 0x50, 0x50);
+ let extraData = new DataView(buf, 0x70 + entries * 0x50 + i * 8, 8);
+ let mode = trackData.getUint8(0x00);
+ let track = trackData.getUint8(0x04);
+ let sectorSize = trackData.getUint16(0x10, true);
+ let offset = trackData.getUint32(0x28, true); // >4GB offset is not supported.
+ let sectors = extraData.getUint32(0x4, true);
if (track < 100)
- this.tracks[track] = {mode:mode, sectorSize:sectorSize, offset:offset, sectors:sectors};
+ this.tracks[track] = {mode, sectorSize, offset, sectors};
}
- if (this.tracks[1].mode != MdsTrackMode.Mode1)
+ if (this.tracks[1].mode !== MdsTrackMode.Mode1)
throw 'track 1 is not mode1';
}
- readSector(sector:number): ArrayBuffer {
- var start = sector * this.tracks[1].sectorSize + 16;
- var end = start + 2048;
+ readSector(sector: number): ArrayBuffer {
+ let start = sector * this.tracks[1].sectorSize + 16;
+ let end = start + 2048;
return new FileReaderSync().readAsArrayBuffer(this.image.slice(start, end));
}
readSequentialSectors(startSector: number, length: number): Uint8Array[] {
- var track = this.tracks[1];
+ let track = this.tracks[1];
return this.readSequential(track.offset + startSector * track.sectorSize, length, track.sectorSize, 2048, 16);
}
- maxTrack():number {
+ maxTrack(): number {
return this.tracks.length - 1;
}
- extractTrack(track:number): Blob {
- if (!this.tracks[track] || this.tracks[track].mode != MdsTrackMode.Audio)
+ extractTrack(track: number): Blob {
+ if (!this.tracks[track] || this.tracks[track].mode !== MdsTrackMode.Audio)
return;
- var size = this.tracks[track].sectors * 2352;
- var chunks = this.readSequential(this.tracks[track].offset, size, this.tracks[track].sectorSize, 2352, 0);
+ let size = this.tracks[track].sectors * 2352;
+ let chunks = this.readSequential(this.tracks[track].offset, size, this.tracks[track].sectorSize, 2352, 0);
return new Blob([createWaveHeader(size)].concat(chunks), {type : 'audio/wav'});
}
}
-function createWaveHeader(size:number):ArrayBuffer {
- var buf = new ArrayBuffer(44);
- var view = new DataView(buf);
+function createWaveHeader(size: number): ArrayBuffer {
+ let buf = new ArrayBuffer(44);
+ let view = new DataView(buf);
view.setUint32(0, 0x52494646, false); // 'RIFF'
view.setUint32(4, size + 36, true); // filesize - 8
view.setUint32(8, 0x57415645, false); // 'WAVE'
diff --git a/web/worker/imagereader-worker.ts b/web/worker/imagereader-worker.ts
index 0d3be0a..c27fcc6 100644
--- a/web/worker/imagereader-worker.ts
+++ b/web/worker/imagereader-worker.ts
@@ -1,11 +1,11 @@
importScripts('cdimage.js');
-declare function postMessage(data: any, transfers:any): void;
+declare function postMessage(data: any, transfers: any): void;
class Installer {
- private imgFile:File;
- private cueFile:File;
- private imageReader:CDImageReader;
+ private imgFile: File;
+ private cueFile: File;
+ private imageReader: CDImageReader;
constructor() {
addEventListener('message', this.onMessage.bind(this));
@@ -15,9 +15,9 @@ class Installer {
switch (evt.data.command) {
case 'setFile':
this.setFile(evt.data.file);
- var imgName = this.imgFile && this.imgFile.name;
- var cueName = this.cueFile && this.cueFile.name;
- postMessage({command:'readyState', img:imgName, cue:cueName});
+ 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())
@@ -27,11 +27,13 @@ class Installer {
if (this.ready())
this.getTrack(evt.data.track);
break;
+ default:
+ throw('unknown command: ' + evt.data.command);
}
}
- private setFile(file:File) {
- var name = file.name.toLowerCase();
+ private 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'))
@@ -49,25 +51,25 @@ class Installer {
}
private extractFiles() {
- var isofs = new ISO9660FileSystem(this.imageReader);
- //this.walk(isofs, isofs.rootDir(), '/');
- var gamedata = isofs.getDirEnt('gamedata', isofs.rootDir());
+ let isofs = new ISO9660FileSystem(this.imageReader);
+ // this.walk(isofs, isofs.rootDir(), '/');
+ let gamedata = isofs.getDirEnt('gamedata', isofs.rootDir());
if (!gamedata) {
- postMessage({command:'error', message:'インストールできません。GAMEDATAフォルダが見つかりません。'});
+ postMessage({command: 'error', message: 'インストールできません。GAMEDATAフォルダが見つかりません。'});
return;
}
- var files: any = {};
- var transfers = [];
- for (var e of isofs.readDir(gamedata)) {
+ let files: any = {};
+ let transfers = [];
+ for (let e of isofs.readDir(gamedata)) {
if (e.name.toLowerCase().endsWith('.ald')) {
- var buffer = new ArrayBuffer(e.size);
- var uint8 = new Uint8Array(buffer);
- var ptr = 0;
- for (var buf of isofs.readFile(e)) {
+ let buffer = new ArrayBuffer(e.size);
+ let uint8 = new Uint8Array(buffer);
+ let ptr = 0;
+ for (let buf of isofs.readFile(e)) {
uint8.set(buf, ptr);
ptr += buf.byteLength;
}
- if (ptr != e.size)
+ if (ptr !== e.size)
throw('expected ' + e.size + ' bytes, but read ' + ptr + 'bytes');
files[e.name] = buffer;
transfers.push(buffer);
@@ -75,12 +77,12 @@ class Installer {
}
postMessage({command: 'extractFiles',
volumeLabel: isofs.volumeLabel(),
- files: files}, transfers);
+ files}, transfers);
}
- private walk(isofs:ISO9660FileSystem, dir:DirEnt, dirname:string) {
- for (var e of isofs.readDir(dir)) {
- if (e.name != '\0' && e.name != '\x01') {
+ private walk(isofs: ISO9660FileSystem, dir: DirEnt, dirname: string) {
+ for (let e of 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 + '/');
@@ -88,10 +90,10 @@ class Installer {
}
}
- private getTrack(track:number) {
- var blob = this.imageReader.extractTrack(track);
- postMessage({command:'complete', track:track, wav:blob});
+ private getTrack(track: number) {
+ let blob = this.imageReader.extractTrack(track);
+ postMessage({command: 'complete', track, wav: blob});
}
}
-var installer = new Installer();
+let installer = new Installer();
diff --git a/web/worker/text-decoder.ts b/web/worker/text-decoder.ts
index c39a0a0..3d22b65 100644
--- a/web/worker/text-decoder.ts
+++ b/web/worker/text-decoder.ts
@@ -2,8 +2,8 @@ class FallbackTextDecoder {
constructor(utfLabel?: string) {}
decode(buffer: DataView): string {
- var out = '';
- for (var i = 0; i < buffer.byteLength; i++) {
+ let out = '';
+ for (let i = 0; i < buffer.byteLength; i++) {
let c = buffer.getUint8(i);
if (c < 128)
out += String.fromCharCode(c);
diff --git a/web/worker/tslint.json b/web/worker/tslint.json
new file mode 120000
index 0000000..b9c0b95
--- /dev/null
+++ b/web/worker/tslint.json
@@ -0,0 +1 @@
+../shell/tslint.json
\ No newline at end of file