mirror of
https://github.com/kichikuou/xsystem35-sdl2.git
synced 2026-10-02 11:48:04 +03:00
Do not use FileReaderSync
This commit is contained in:
+66
-36
@@ -1,10 +1,12 @@
|
||||
importScripts('text-decoder.js');
|
||||
|
||||
class ISO9660FileSystem {
|
||||
private pvd: PVD;
|
||||
static async create(sectorReader: CDImageReader): Promise<ISO9660FileSystem> {
|
||||
let pvd = new PVD(await sectorReader.readSector(0x10));
|
||||
return new ISO9660FileSystem(sectorReader, pvd);
|
||||
}
|
||||
|
||||
constructor(private sectorReader: CDImageReader) {
|
||||
this.pvd = new PVD(sectorReader.readSector(0x10));
|
||||
private constructor(private sectorReader: CDImageReader, private pvd: PVD) {
|
||||
if (this.pvd.type !== 1)
|
||||
throw('PVD not found');
|
||||
}
|
||||
@@ -17,16 +19,16 @@ class ISO9660FileSystem {
|
||||
return this.pvd.rootDirEnt();
|
||||
}
|
||||
|
||||
getDirEnt(name: string, parent: DirEnt): DirEnt {
|
||||
async getDirEnt(name: string, parent: DirEnt): Promise<DirEnt> {
|
||||
name = name.toLowerCase();
|
||||
for (let e of this.readDir(parent)) {
|
||||
for (let e of await this.readDir(parent)) {
|
||||
if (e.name.toLowerCase() === name)
|
||||
return e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
readDir(dirent: DirEnt): DirEnt[] {
|
||||
async readDir(dirent: DirEnt): Promise<DirEnt[]> {
|
||||
let sector = dirent.sector;
|
||||
let position = 0;
|
||||
let length = dirent.size;
|
||||
@@ -34,7 +36,7 @@ class ISO9660FileSystem {
|
||||
let buf: ArrayBuffer;
|
||||
while (position < length) {
|
||||
if (position === 0)
|
||||
buf = this.sectorReader.readSector(sector);
|
||||
buf = await this.sectorReader.readSector(sector);
|
||||
let child = new DirEnt(buf, position);
|
||||
if (child.length === 0) {
|
||||
// Padded end of sector
|
||||
@@ -54,7 +56,7 @@ class ISO9660FileSystem {
|
||||
return entries;
|
||||
}
|
||||
|
||||
readFile(dirent: DirEnt): Uint8Array[] {
|
||||
readFile(dirent: DirEnt): Promise<Uint8Array[]> {
|
||||
return this.sectorReader.readSequentialSectors(dirent.sector, dirent.size);
|
||||
}
|
||||
}
|
||||
@@ -101,23 +103,41 @@ class DirEnt {
|
||||
}
|
||||
|
||||
interface CDImageReader {
|
||||
readSector(sector: number): ArrayBuffer;
|
||||
readSequentialSectors(startSector: number, length: number): Uint8Array[];
|
||||
readSector(sector: number): Promise<ArrayBuffer>;
|
||||
readSequentialSectors(startSector: number, length: number): Promise<Uint8Array[]>;
|
||||
maxTrack(): number;
|
||||
extractTrack(track: number): Blob;
|
||||
extractTrack(track: number): Promise<Blob>;
|
||||
}
|
||||
|
||||
function readAsArrayBuffer(blob: Blob): Promise<ArrayBuffer> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let reader = new FileReader();
|
||||
reader.onload = () => { resolve(reader.result); };
|
||||
reader.onerror = () => { reject(reader.error); };
|
||||
reader.readAsArrayBuffer(blob);
|
||||
});
|
||||
}
|
||||
|
||||
function readAsText(blob: Blob): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let reader = new FileReader();
|
||||
reader.onload = () => { resolve(reader.result); };
|
||||
reader.onerror = () => { reject(reader.error); };
|
||||
reader.readAsText(blob);
|
||||
});
|
||||
}
|
||||
|
||||
class ImageReaderBase {
|
||||
constructor(public image: File) {}
|
||||
|
||||
readSequential(startOffset: number,
|
||||
bytesToRead: number,
|
||||
blockSize: number,
|
||||
sectorSize: number,
|
||||
sectorOffset: number): Uint8Array[] {
|
||||
async readSequential(startOffset: number,
|
||||
bytesToRead: number,
|
||||
blockSize: number,
|
||||
sectorSize: number,
|
||||
sectorOffset: number): Promise<Uint8Array[]> {
|
||||
let sectors = Math.ceil(bytesToRead / sectorSize);
|
||||
let blob = this.image.slice(startOffset, startOffset + sectors * blockSize);
|
||||
let buf = new FileReaderSync().readAsArrayBuffer(blob);
|
||||
let buf = await readAsArrayBuffer(blob);
|
||||
let bufs: Uint8Array[] = [];
|
||||
for (let i = 0; i < sectors; i++) {
|
||||
bufs.push(new Uint8Array(buf, i * blockSize + sectorOffset, Math.min(bytesToRead, sectorSize)));
|
||||
@@ -130,23 +150,28 @@ class ImageReaderBase {
|
||||
class ImgCueReader extends ImageReaderBase implements CDImageReader {
|
||||
private tracks: Array<{ type: string; index: string[]; }>;
|
||||
|
||||
constructor(img: File, cue: File) {
|
||||
super(img);
|
||||
this.parseCue(cue);
|
||||
static async create(img: File, cue: File): Promise<ImgCueReader> {
|
||||
let reader = new ImgCueReader(img);
|
||||
await reader.parseCue(cue);
|
||||
return reader;
|
||||
}
|
||||
|
||||
readSector(sector: number): ArrayBuffer {
|
||||
private constructor(img: File) {
|
||||
super(img);
|
||||
}
|
||||
|
||||
readSector(sector: number): Promise<ArrayBuffer> {
|
||||
let start = sector * 2352 + 16;
|
||||
let end = start + 2048;
|
||||
return new FileReaderSync().readAsArrayBuffer(this.image.slice(start, end));
|
||||
return readAsArrayBuffer(this.image.slice(start, end));
|
||||
}
|
||||
|
||||
readSequentialSectors(startSector: number, length: number): Uint8Array[] {
|
||||
readSequentialSectors(startSector: number, length: number): Promise<Uint8Array[]> {
|
||||
return this.readSequential(startSector * 2352, length, 2352, 2048, 16);
|
||||
}
|
||||
|
||||
private parseCue(cueFile: File) {
|
||||
let lines = new FileReaderSync().readAsText(cueFile).split('\n');
|
||||
private async parseCue(cueFile: File) {
|
||||
let lines = (await readAsText(cueFile)).split('\n');
|
||||
this.tracks = [];
|
||||
let currentTrack: number = null;
|
||||
for (let line of lines) {
|
||||
@@ -170,7 +195,7 @@ class ImgCueReader extends ImageReaderBase implements CDImageReader {
|
||||
return this.tracks.length - 1;
|
||||
}
|
||||
|
||||
extractTrack(track: number): Blob {
|
||||
async extractTrack(track: number): Promise<Blob> {
|
||||
if (!this.tracks[track] || this.tracks[track].type !== 'AUDIO')
|
||||
return;
|
||||
|
||||
@@ -197,13 +222,18 @@ enum MdsTrackMode { Audio = 0xa9, Mode1 = 0xaa };
|
||||
class MdfMdsReader extends ImageReaderBase implements CDImageReader {
|
||||
private tracks: Array<{ mode: number; sectorSize: number; offset: number; sectors: number; }>;
|
||||
|
||||
constructor(mdf: File, mds: File) {
|
||||
super(mdf);
|
||||
this.parseMds(mds);
|
||||
static async create(mdf: File, mds: File): Promise<MdfMdsReader> {
|
||||
let reader = new MdfMdsReader(mdf);
|
||||
await reader.parseMds(mds);
|
||||
return reader;
|
||||
}
|
||||
|
||||
private parseMds(mdsFile: File) {
|
||||
let buf = new FileReaderSync().readAsArrayBuffer(mdsFile);
|
||||
private constructor(mdf: File) {
|
||||
super(mdf);
|
||||
}
|
||||
|
||||
private async parseMds(mdsFile: File) {
|
||||
let buf = await readAsArrayBuffer(mdsFile);
|
||||
|
||||
let signature = new TextDecoder().decode(new DataView(buf, 0, 16));
|
||||
if (signature !== 'MEDIA DESCRIPTOR')
|
||||
@@ -228,13 +258,13 @@ class MdfMdsReader extends ImageReaderBase implements CDImageReader {
|
||||
throw 'track 1 is not mode1';
|
||||
}
|
||||
|
||||
readSector(sector: number): ArrayBuffer {
|
||||
readSector(sector: number): Promise<ArrayBuffer> {
|
||||
let start = sector * this.tracks[1].sectorSize + 16;
|
||||
let end = start + 2048;
|
||||
return new FileReaderSync().readAsArrayBuffer(this.image.slice(start, end));
|
||||
return readAsArrayBuffer(this.image.slice(start, end));
|
||||
}
|
||||
|
||||
readSequentialSectors(startSector: number, length: number): Uint8Array[] {
|
||||
readSequentialSectors(startSector: number, length: number): Promise<Uint8Array[]> {
|
||||
let track = this.tracks[1];
|
||||
return this.readSequential(track.offset + startSector * track.sectorSize, length, track.sectorSize, 2048, 16);
|
||||
}
|
||||
@@ -243,12 +273,12 @@ class MdfMdsReader extends ImageReaderBase implements CDImageReader {
|
||||
return this.tracks.length - 1;
|
||||
}
|
||||
|
||||
extractTrack(track: number): Blob {
|
||||
async extractTrack(track: number): Promise<Blob> {
|
||||
if (!this.tracks[track] || this.tracks[track].mode !== MdsTrackMode.Audio)
|
||||
return;
|
||||
|
||||
let size = this.tracks[track].sectors * 2352;
|
||||
let chunks = this.readSequential(this.tracks[track].offset, size, this.tracks[track].sectorSize, 2352, 0);
|
||||
let chunks = await this.readSequential(this.tracks[track].offset, size, this.tracks[track].sectorSize, 2352, 0);
|
||||
return new Blob([<any>createWaveHeader(size)].concat(chunks), {type : 'audio/wav'});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,10 +11,10 @@ class Installer {
|
||||
addEventListener('message', this.onMessage.bind(this));
|
||||
}
|
||||
|
||||
private onMessage(evt: MessageEvent) {
|
||||
private async onMessage(evt: MessageEvent) {
|
||||
switch (evt.data.command) {
|
||||
case 'setFile':
|
||||
this.setFile(evt.data.file);
|
||||
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});
|
||||
@@ -32,7 +32,7 @@ class Installer {
|
||||
}
|
||||
}
|
||||
|
||||
private setFile(file: File) {
|
||||
private async setFile(file: File) {
|
||||
let name = file.name.toLowerCase();
|
||||
if (name.endsWith('.img') || name.endsWith('.mdf'))
|
||||
this.imgFile = file;
|
||||
@@ -40,9 +40,9 @@ class Installer {
|
||||
this.cueFile = file;
|
||||
if (this.imgFile && this.cueFile) {
|
||||
if (this.cueFile.name.endsWith('.cue'))
|
||||
this.imageReader = new ImgCueReader(this.imgFile, this.cueFile);
|
||||
this.imageReader = await ImgCueReader.create(this.imgFile, this.cueFile);
|
||||
else
|
||||
this.imageReader = new MdfMdsReader(this.imgFile, this.cueFile);
|
||||
this.imageReader = await MdfMdsReader.create(this.imgFile, this.cueFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,22 +50,22 @@ class Installer {
|
||||
return !!this.imageReader;
|
||||
}
|
||||
|
||||
private extractFiles() {
|
||||
let isofs = new ISO9660FileSystem(this.imageReader);
|
||||
private async extractFiles() {
|
||||
let isofs = await ISO9660FileSystem.create(this.imageReader);
|
||||
// this.walk(isofs, isofs.rootDir(), '/');
|
||||
let gamedata = isofs.getDirEnt('gamedata', 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 isofs.readDir(gamedata)) {
|
||||
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 isofs.readFile(e)) {
|
||||
for (let buf of await isofs.readFile(e)) {
|
||||
uint8.set(buf, ptr);
|
||||
ptr += buf.byteLength;
|
||||
}
|
||||
@@ -80,8 +80,8 @@ class Installer {
|
||||
files}, transfers);
|
||||
}
|
||||
|
||||
private walk(isofs: ISO9660FileSystem, dir: DirEnt, dirname: string) {
|
||||
for (let e of isofs.readDir(dir)) {
|
||||
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)
|
||||
@@ -90,8 +90,8 @@ class Installer {
|
||||
}
|
||||
}
|
||||
|
||||
private getTrack(track: number) {
|
||||
let blob = this.imageReader.extractTrack(track);
|
||||
private async getTrack(track: number) {
|
||||
let blob = await this.imageReader.extractTrack(track);
|
||||
postMessage({command: 'complete', track, wav: blob});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user