mirror of
https://github.com/whscullin/apple2js.git
synced 2024-01-12 14:14:38 +00:00
Lazy load ROMs (#81)
* Switch modules to `esnext` to allow `webpack` to see import statements * Pass rom names into Apple2 class * Move ROMs into `system` and `character` directories to allow webpack bundle appropriate ROMs. * Wait for ROMs to load before completing initialization.
This commit is contained in:
parent
af57378852
commit
8087294456
@ -25,6 +25,7 @@
|
||||
"always"
|
||||
],
|
||||
"no-use-before-define": "off",
|
||||
"@typescript-eslint/no-floating-promises": "error",
|
||||
"@typescript-eslint/no-use-before-define": [
|
||||
"error",
|
||||
{
|
||||
@ -59,7 +60,8 @@
|
||||
"es6": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "module"
|
||||
"sourceType": "module",
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"overrides": [
|
||||
@ -109,5 +111,6 @@
|
||||
"commonjs": true
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"ignorePatterns": ["coverage/**/*"]
|
||||
}
|
||||
|
@ -309,6 +309,6 @@
|
||||
</filter>
|
||||
</svg>
|
||||
|
||||
<script src="dist/main2.js"></script>
|
||||
<script src="dist/main2.bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -29,10 +29,6 @@
|
||||
<link rel="stylesheet" type="text/css" href="css/apple2.css" />
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.2/css/all.css" />
|
||||
|
||||
<script>
|
||||
window.e = true
|
||||
</script>
|
||||
|
||||
<!-- Disk Index -->
|
||||
<script type="text/javascript" src="json/disks/index.js"></script>
|
||||
|
||||
@ -318,6 +314,6 @@
|
||||
</filter>
|
||||
</svg>
|
||||
|
||||
<script src="dist/main2e.js"></script>
|
||||
<script src="dist/main2e.bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
36
js/apple2.ts
36
js/apple2.ts
@ -28,11 +28,11 @@ import { Restorable, rom } from './types';
|
||||
import { processGamepad } from './ui/gamepad';
|
||||
|
||||
export interface Apple2Options {
|
||||
characterRom: rom,
|
||||
characterRom: string;
|
||||
enhanced: boolean,
|
||||
e: boolean,
|
||||
gl: boolean,
|
||||
rom: ROM,
|
||||
rom: string,
|
||||
canvas: HTMLCanvasElement,
|
||||
tick: () => void,
|
||||
}
|
||||
@ -68,6 +68,8 @@ export class Apple2 implements Restorable<State>, DebuggerContainer {
|
||||
private io: Apple2IO;
|
||||
private mmu: MMU | undefined;
|
||||
private ram: [RAM, RAM, RAM] | undefined;
|
||||
private characterRom: rom;
|
||||
private rom: ROM;
|
||||
|
||||
private tick: () => void;
|
||||
|
||||
@ -76,22 +78,41 @@ export class Apple2 implements Restorable<State>, DebuggerContainer {
|
||||
renderedFrames: 0
|
||||
};
|
||||
|
||||
public ready: Promise<void>
|
||||
|
||||
constructor(options: Apple2Options) {
|
||||
this.ready = this.init(options);
|
||||
}
|
||||
|
||||
async init(options: Apple2Options) {
|
||||
const romImportPromise = import(`./roms/system/${options.rom}`);
|
||||
const characterRomImportPromise = import(`./roms/character/${options.characterRom}`);
|
||||
|
||||
const LoresPage = options.gl ? LoresPageGL : LoresPage2D;
|
||||
const HiresPage = options.gl ? HiresPageGL : HiresPage2D;
|
||||
const VideoModes = options.gl ? VideoModesGL : VideoModes2D;
|
||||
|
||||
this.cpu = new CPU6502({ '65C02': options.enhanced });
|
||||
this.vm = new VideoModes(options.canvas, options.e);
|
||||
this.gr = new LoresPage(this.vm, 1, options.characterRom, options.e);
|
||||
this.gr2 = new LoresPage(this.vm, 2, options.characterRom, options.e);
|
||||
|
||||
const [{ default: Apple2ROM }, { default: characterRom }] = await Promise.all([
|
||||
romImportPromise,
|
||||
characterRomImportPromise,
|
||||
this.vm.ready,
|
||||
]);
|
||||
|
||||
this.rom = new Apple2ROM();
|
||||
this.characterRom = characterRom;
|
||||
|
||||
this.gr = new LoresPage(this.vm, 1, this.characterRom, options.e);
|
||||
this.gr2 = new LoresPage(this.vm, 2, this.characterRom, options.e);
|
||||
this.hgr = new HiresPage(this.vm, 1);
|
||||
this.hgr2 = new HiresPage(this.vm, 2);
|
||||
this.io = new Apple2IO(this.cpu, this.vm);
|
||||
this.tick = options.tick;
|
||||
|
||||
if (options.e) {
|
||||
this.mmu = new MMU(this.cpu, this.vm, this.gr, this.gr2, this.hgr, this.hgr2, this.io, options.rom);
|
||||
this.mmu = new MMU(this.cpu, this.vm, this.gr, this.gr2, this.hgr, this.hgr2, this.io, this.rom);
|
||||
this.cpu.addPageHandler(this.mmu);
|
||||
} else {
|
||||
this.ram = [
|
||||
@ -108,7 +129,7 @@ export class Apple2 implements Restorable<State>, DebuggerContainer {
|
||||
this.cpu.addPageHandler(this.hgr2);
|
||||
this.cpu.addPageHandler(this.ram[2]);
|
||||
this.cpu.addPageHandler(this.io);
|
||||
this.cpu.addPageHandler(options.rom);
|
||||
this.cpu.addPageHandler(this.rom);
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,6 +256,9 @@ export class Apple2 implements Restorable<State>, DebuggerContainer {
|
||||
return this.mmu;
|
||||
}
|
||||
|
||||
getROM() {
|
||||
return this.rom;
|
||||
}
|
||||
|
||||
getVideoModes() {
|
||||
return this.vm;
|
||||
|
78
js/main2.ts
78
js/main2.ts
@ -11,49 +11,43 @@ import SmartPort from './cards/smartport';
|
||||
import Thunderclock from './cards/thunderclock';
|
||||
import VideoTerm from './cards/videoterm';
|
||||
|
||||
import apple2_charset from './roms/apple2_char';
|
||||
import apple2j_charset from './roms/apple2j_char';
|
||||
import apple2lc_charset from './roms/apple2lc_char';
|
||||
import pigfont_charset from './roms/pigfont_char';
|
||||
|
||||
import Apple2ROM from './roms/fpbasic';
|
||||
import Apple2jROM from './roms/apple2j';
|
||||
import IntBASIC from './roms/intbasic';
|
||||
import OriginalROM from './roms/original';
|
||||
|
||||
import { Apple2 } from './apple2';
|
||||
|
||||
const prefs = new Prefs();
|
||||
const romVersion = prefs.readPref('computer_type2');
|
||||
let rom;
|
||||
let characterRom = apple2_charset;
|
||||
let rom: string;
|
||||
let characterRom: string;
|
||||
let sectors = 16;
|
||||
|
||||
switch (romVersion) {
|
||||
case 'apple2':
|
||||
rom = new IntBASIC();
|
||||
rom = 'intbasic';
|
||||
characterRom = 'apple2_char';
|
||||
break;
|
||||
case 'apple213':
|
||||
rom = new IntBASIC();
|
||||
rom = 'intbasic';
|
||||
characterRom = 'apple2_char';
|
||||
sectors = 13;
|
||||
break;
|
||||
case 'original':
|
||||
rom = new OriginalROM();
|
||||
rom = 'original';
|
||||
characterRom = 'apple2_char';
|
||||
break;
|
||||
case 'apple2jplus':
|
||||
rom = new Apple2jROM();
|
||||
characterRom = apple2j_charset;
|
||||
rom = 'apple2j';
|
||||
characterRom = 'apple2j_char';
|
||||
break;
|
||||
case 'apple2pig':
|
||||
rom = new Apple2ROM();
|
||||
characterRom = pigfont_charset;
|
||||
rom = 'fpbasic';
|
||||
characterRom = 'pigfont_char';
|
||||
break;
|
||||
case 'apple2lc':
|
||||
rom = new Apple2ROM();
|
||||
characterRom = apple2lc_charset;
|
||||
rom = 'fpbasic';
|
||||
characterRom = 'apple2lc_char';
|
||||
break;
|
||||
default:
|
||||
rom = new Apple2ROM();
|
||||
rom = 'fpbasic';
|
||||
characterRom = 'apple2_char';
|
||||
}
|
||||
|
||||
const options = {
|
||||
@ -67,27 +61,29 @@ const options = {
|
||||
};
|
||||
|
||||
export const apple2 = new Apple2(options);
|
||||
const cpu = apple2.getCPU();
|
||||
const io = apple2.getIO();
|
||||
apple2.ready.then(() => {
|
||||
const cpu = apple2.getCPU();
|
||||
const io = apple2.getIO();
|
||||
|
||||
const printer = new Printer('#printer-modal .paper');
|
||||
const printer = new Printer('#printer-modal .paper');
|
||||
|
||||
const lc = new LanguageCard(rom);
|
||||
const parallel = new Parallel(printer);
|
||||
const videoTerm = new VideoTerm();
|
||||
const slinky = new RAMFactor(1024 * 1024);
|
||||
const disk2 = new DiskII(io, driveLights, sectors);
|
||||
const clock = new Thunderclock();
|
||||
const smartport = new SmartPort(cpu, { block: true });
|
||||
const lc = new LanguageCard(apple2.getROM());
|
||||
const parallel = new Parallel(printer);
|
||||
const videoTerm = new VideoTerm();
|
||||
const slinky = new RAMFactor(1024 * 1024);
|
||||
const disk2 = new DiskII(io, driveLights, sectors);
|
||||
const clock = new Thunderclock();
|
||||
const smartport = new SmartPort(cpu, { block: true });
|
||||
|
||||
io.setSlot(0, lc);
|
||||
io.setSlot(1, parallel);
|
||||
io.setSlot(2, slinky);
|
||||
io.setSlot(4, clock);
|
||||
io.setSlot(3, videoTerm);
|
||||
io.setSlot(6, disk2);
|
||||
io.setSlot(7, smartport);
|
||||
io.setSlot(0, lc);
|
||||
io.setSlot(1, parallel);
|
||||
io.setSlot(2, slinky);
|
||||
io.setSlot(4, clock);
|
||||
io.setSlot(3, videoTerm);
|
||||
io.setSlot(6, disk2);
|
||||
io.setSlot(7, smartport);
|
||||
|
||||
cpu.addPageHandler(lc);
|
||||
cpu.addPageHandler(lc);
|
||||
|
||||
initUI(apple2, disk2, smartport, printer, false);
|
||||
initUI(apple2, disk2, smartport, printer, false);
|
||||
}).catch(console.error);
|
||||
|
52
js/main2e.ts
52
js/main2e.ts
@ -9,33 +9,27 @@ import RAMFactor from './cards/ramfactor';
|
||||
import SmartPort from './cards/smartport';
|
||||
import Thunderclock from './cards/thunderclock';
|
||||
|
||||
import apple2e_charset from './roms/apple2e_char';
|
||||
import apple2enh_charset from './roms/apple2enh_char';
|
||||
import rmfont_charset from './roms/rmfont_char';
|
||||
|
||||
import Apple2eROM from './roms/apple2e';
|
||||
import Apple2eEnhancedROM from './roms/apple2enh';
|
||||
|
||||
import { Apple2 } from './apple2';
|
||||
|
||||
const prefs = new Prefs();
|
||||
const romVersion = prefs.readPref('computer_type2e');
|
||||
let enhanced = false;
|
||||
let rom;
|
||||
let characterRom = apple2e_charset;
|
||||
let rom: string;
|
||||
let characterRom: string;
|
||||
|
||||
switch (romVersion) {
|
||||
case 'apple2e':
|
||||
rom = new Apple2eROM();
|
||||
rom = 'apple2e';
|
||||
characterRom = 'apple2e_char';
|
||||
break;
|
||||
case 'apple2rm':
|
||||
rom = new Apple2eEnhancedROM();
|
||||
characterRom = rmfont_charset;
|
||||
rom = 'apple2e';
|
||||
characterRom = 'rmfont_char';
|
||||
enhanced = true;
|
||||
break;
|
||||
default:
|
||||
rom = new Apple2eEnhancedROM();
|
||||
characterRom = apple2enh_charset;
|
||||
rom = 'apple2enh';
|
||||
characterRom = 'apple2enh_char';
|
||||
enhanced = true;
|
||||
}
|
||||
|
||||
@ -50,21 +44,23 @@ const options = {
|
||||
};
|
||||
|
||||
export const apple2 = new Apple2(options);
|
||||
const io = apple2.getIO();
|
||||
const cpu = apple2.getCPU();
|
||||
apple2.ready.then(() => {
|
||||
const io = apple2.getIO();
|
||||
const cpu = apple2.getCPU();
|
||||
|
||||
const printer = new Printer('#printer-modal .paper');
|
||||
const printer = new Printer('#printer-modal .paper');
|
||||
|
||||
const parallel = new Parallel(printer);
|
||||
const slinky = new RAMFactor(1024 * 1024);
|
||||
const disk2 = new DiskII(io, driveLights);
|
||||
const clock = new Thunderclock();
|
||||
const smartport = new SmartPort(cpu, { block: !enhanced });
|
||||
const parallel = new Parallel(printer);
|
||||
const slinky = new RAMFactor(1024 * 1024);
|
||||
const disk2 = new DiskII(io, driveLights);
|
||||
const clock = new Thunderclock();
|
||||
const smartport = new SmartPort(cpu, { block: !enhanced });
|
||||
|
||||
io.setSlot(1, parallel);
|
||||
io.setSlot(2, slinky);
|
||||
io.setSlot(5, clock);
|
||||
io.setSlot(6, disk2);
|
||||
io.setSlot(7, smartport);
|
||||
io.setSlot(1, parallel);
|
||||
io.setSlot(2, slinky);
|
||||
io.setSlot(5, clock);
|
||||
io.setSlot(6, disk2);
|
||||
io.setSlot(7, smartport);
|
||||
|
||||
initUI(apple2, disk2, smartport, printer, options.e);
|
||||
initUI(apple2, disk2, smartport, printer, options.e);
|
||||
}).catch(console.error);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ReadonlyUint8Array } from '../types';
|
||||
import { ReadonlyUint8Array } from '../../types';
|
||||
|
||||
const apple2_charset = new Uint8Array([
|
||||
0x00,0x1c,0x22,0x2a,0x2e,0x2c,0x20,0x1e,
|
@ -1,4 +1,4 @@
|
||||
import { ReadonlyUint8Array } from '../types';
|
||||
import { ReadonlyUint8Array } from '../../types';
|
||||
|
||||
/* exported apple2e_charset */
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ReadonlyUint8Array } from '../types';
|
||||
import { ReadonlyUint8Array } from '../../types';
|
||||
|
||||
const apple2enh_charset = new Uint8Array([
|
||||
0x1c,0x22,0x2a,0x3a,0x1a,0x02,0x3c,0x00,
|
@ -1,4 +1,4 @@
|
||||
import { ReadonlyUint8Array } from '../types';
|
||||
import { ReadonlyUint8Array } from '../../types';
|
||||
|
||||
const apple2j_charset = new Uint8Array([
|
||||
0xff,0xef,0xe1,0xed,0xd5,0xfb,0xf7,0xef,
|
@ -1,4 +1,4 @@
|
||||
import { ReadonlyUint8Array } from '../types';
|
||||
import { ReadonlyUint8Array } from '../../types';
|
||||
|
||||
const apple2lc_charset = new Uint8Array([
|
||||
0x1c,0x22,0x2a,0x2a,0x2c,0x20,0x1e,0x00,
|
@ -1,4 +1,4 @@
|
||||
import { ReadonlyUint8Array } from '../types';
|
||||
import { ReadonlyUint8Array } from '../../types';
|
||||
|
||||
const pigfont_charset = new Uint8Array([
|
||||
0x00,0x1c,0x22,0x2a,0x2e,0x20,0x1e,0x00,
|
@ -1,4 +1,4 @@
|
||||
import { ReadonlyUint8Array } from '../types';
|
||||
import { ReadonlyUint8Array } from '../../types';
|
||||
|
||||
const rmfont_charset = new Uint8Array([
|
||||
0x3c,0x42,0x59,0x55,0x55,0x39,0x02,0x3c,
|
@ -1,5 +1,5 @@
|
||||
import { ReadonlyUint8Array } from '../types';
|
||||
import ROM from './rom';
|
||||
import { ReadonlyUint8Array } from '../../types';
|
||||
import ROM from '../rom';
|
||||
|
||||
const rom = new Uint8Array([
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
@ -1,5 +1,5 @@
|
||||
import { ReadonlyUint8Array } from '../types';
|
||||
import ROM from './rom';
|
||||
import { ReadonlyUint8Array } from '../../types';
|
||||
import ROM from '../rom';
|
||||
|
||||
const rom = new Uint8Array([
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
@ -1,5 +1,5 @@
|
||||
import { ReadonlyUint8Array } from '../types';
|
||||
import ROM from './rom';
|
||||
import { ReadonlyUint8Array } from '../../types';
|
||||
import ROM from '../rom';
|
||||
|
||||
const rom = new Uint8Array([
|
||||
0x6f,0xd8,0x65,0xd7,0xf8,0xdc,0x94,0xd9,
|
@ -1,5 +1,5 @@
|
||||
import { ReadonlyUint8Array } from '../types';
|
||||
import ROM from './rom';
|
||||
import { ReadonlyUint8Array } from '../../types';
|
||||
import ROM from '../rom';
|
||||
|
||||
const rom = new Uint8Array([
|
||||
0x6f, 0xd8, 0x65, 0xd7, 0xf8, 0xdc, 0x94, 0xd9,
|
@ -1,5 +1,5 @@
|
||||
import { ReadonlyUint8Array } from '../types';
|
||||
import ROM from './rom';
|
||||
import { ReadonlyUint8Array } from '../../types';
|
||||
import ROM from '../rom';
|
||||
|
||||
const rom = new Uint8Array([
|
||||
0xa9, 0x20, 0x8d, 0x26, 0x03, 0xad, 0x57, 0xc0,
|
@ -1,5 +1,5 @@
|
||||
import { ReadonlyUint8Array } from '../types';
|
||||
import ROM from './rom';
|
||||
import { ReadonlyUint8Array } from '../../types';
|
||||
import ROM from '../rom';
|
||||
|
||||
const rom = new Uint8Array([
|
||||
0xa9, 0x20, 0x8d, 0x26, 0x03, 0xad, 0x57, 0xc0,
|
106
js/ui/apple2.ts
106
js/ui/apple2.ts
@ -49,7 +49,14 @@ type DiskCollection = {
|
||||
[name: string]: DiskDescriptor[]
|
||||
};
|
||||
|
||||
const KNOWN_FILE_TYPES = [...DISK_FORMATS, ...TAPE_TYPES] as readonly string[];
|
||||
const CIDERPRESS_EXTENSION = /#([0-9a-f]{2})([0-9a-f]{4})$/i;
|
||||
const BIN_TYPES = ['bin'];
|
||||
|
||||
const KNOWN_FILE_TYPES = [
|
||||
...DISK_FORMATS,
|
||||
...TAPE_TYPES,
|
||||
...BIN_TYPES,
|
||||
] as readonly string[];
|
||||
|
||||
const disk_categories: DiskCollection = { 'Local Saves': [] };
|
||||
const disk_sets: DiskCollection = {};
|
||||
@ -73,6 +80,7 @@ let system: System;
|
||||
let keyboard: KeyBoard;
|
||||
let io: Apple2IO;
|
||||
let _currentDrive: DriveNumber = 1;
|
||||
let _e: boolean;
|
||||
|
||||
export const driveLights = new DriveLights();
|
||||
|
||||
@ -84,6 +92,7 @@ export function dumpAppleSoftProgram() {
|
||||
export function compileAppleSoftProgram(program: string) {
|
||||
const compiler = new ApplesoftCompiler(cpu);
|
||||
compiler.compile(program);
|
||||
dumpAppleSoftProgram();
|
||||
}
|
||||
|
||||
export function openLoad(driveString: string, event: MouseEvent) {
|
||||
@ -204,9 +213,9 @@ function loadingStop() {
|
||||
MicroModal.close('loading-modal');
|
||||
|
||||
if (!paused) {
|
||||
vm.ready.then(() => {
|
||||
_apple2.ready.then(() => {
|
||||
_apple2.run();
|
||||
});
|
||||
}).catch(console.error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -297,11 +306,8 @@ export function doDelete(name: string) {
|
||||
}
|
||||
}
|
||||
|
||||
const CIDERPRESS_EXTENSION = /#([0-9a-f]{2})([0-9a-f]{4})$/i;
|
||||
const BIN_TYPES = ['bin'];
|
||||
|
||||
interface LoadOptions {
|
||||
address: word,
|
||||
address?: word,
|
||||
runOnLoad?: boolean,
|
||||
}
|
||||
|
||||
@ -318,7 +324,8 @@ function doLoadLocal(drive: DriveNumber, file: File, options: Partial<LoadOption
|
||||
} else if (includes(TAPE_TYPES, ext)) {
|
||||
tape.doLoadLocalTape(file);
|
||||
} else if (BIN_TYPES.includes(ext) || type === '06' || options.address) {
|
||||
doLoadBinary(file, { address: parseInt(aux || '2000', 16), ...options });
|
||||
const address = aux !== undefined ? parseInt(aux, 16) : undefined;
|
||||
doLoadBinary(file, { address, ...options });
|
||||
} else {
|
||||
const addressInput = document.querySelector<HTMLInputElement>('#local_file_address');
|
||||
const addressStr = addressInput?.value;
|
||||
@ -342,6 +349,7 @@ function doLoadBinary(file: File, options: LoadOptions) {
|
||||
fileReader.onload = function () {
|
||||
const result = this.result as ArrayBuffer;
|
||||
let { address } = options;
|
||||
address = address ?? 0x2000;
|
||||
const bytes = new Uint8Array(result);
|
||||
for (let idx = 0; idx < result.byteLength; idx++) {
|
||||
cpu.write(address >> 8, address & 0xff, bytes[idx]);
|
||||
@ -349,7 +357,7 @@ function doLoadBinary(file: File, options: LoadOptions) {
|
||||
}
|
||||
if (options.runOnLoad) {
|
||||
cpu.reset();
|
||||
cpu.setPC(options.address);
|
||||
cpu.setPC(address);
|
||||
}
|
||||
loadingStop();
|
||||
};
|
||||
@ -437,9 +445,10 @@ export function doLoadHTTP(drive: DriveNumber, url?: string) {
|
||||
initGamepad();
|
||||
}
|
||||
} else {
|
||||
if (includes(DISK_FORMATS, ext)
|
||||
&& _disk2.setBinary(drive, name, ext, data)) {
|
||||
initGamepad();
|
||||
if (includes(DISK_FORMATS, ext)) {
|
||||
if (_disk2.setBinary(drive, name, ext, data)) {
|
||||
initGamepad();
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Extension ${ext} not recognized.`);
|
||||
}
|
||||
@ -678,38 +687,40 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
let oldCat = '';
|
||||
let option;
|
||||
for (let idx = 0; idx < window.disk_index.length; idx++) {
|
||||
const file = window.disk_index[idx];
|
||||
const cat = file.category;
|
||||
const name = file.name;
|
||||
const disk = file.disk;
|
||||
if (file.e && !window.e) {
|
||||
continue;
|
||||
}
|
||||
if (cat != oldCat) {
|
||||
option = document.createElement('option');
|
||||
option.value = cat;
|
||||
option.innerText = cat;
|
||||
categorySelect.append(option);
|
||||
|
||||
disk_categories[cat] = [];
|
||||
oldCat = cat;
|
||||
}
|
||||
disk_categories[cat].push(file);
|
||||
if (disk) {
|
||||
if (!disk_sets[name]) {
|
||||
disk_sets[name] = [];
|
||||
function buildDiskIndex() {
|
||||
let oldCat = '';
|
||||
let option;
|
||||
for (let idx = 0; idx < window.disk_index.length; idx++) {
|
||||
const file = window.disk_index[idx];
|
||||
const cat = file.category;
|
||||
const name = file.name;
|
||||
const disk = file.disk;
|
||||
if (file.e && !_e) {
|
||||
continue;
|
||||
}
|
||||
disk_sets[name].push(file);
|
||||
}
|
||||
}
|
||||
option = document.createElement('option');
|
||||
option.innerText = 'Local Saves';
|
||||
categorySelect.append(option);
|
||||
if (cat != oldCat) {
|
||||
option = document.createElement('option');
|
||||
option.value = cat;
|
||||
option.innerText = cat;
|
||||
categorySelect.append(option);
|
||||
|
||||
updateLocalStorage();
|
||||
disk_categories[cat] = [];
|
||||
oldCat = cat;
|
||||
}
|
||||
disk_categories[cat].push(file);
|
||||
if (disk) {
|
||||
if (!disk_sets[name]) {
|
||||
disk_sets[name] = [];
|
||||
}
|
||||
disk_sets[name].push(file);
|
||||
}
|
||||
}
|
||||
option = document.createElement('option');
|
||||
option.innerText = 'Local Saves';
|
||||
categorySelect.append(option);
|
||||
|
||||
updateLocalStorage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the URL fragment. It is expected to be of the form:
|
||||
@ -751,9 +762,9 @@ export function updateUI() {
|
||||
export function pauseRun() {
|
||||
const label = document.querySelector<HTMLElement>('#pause-run i')!;
|
||||
if (paused) {
|
||||
vm.ready.then(() => {
|
||||
_apple2.ready.then(() => {
|
||||
_apple2.run();
|
||||
});
|
||||
}).catch(console.error);
|
||||
label.classList.remove('fa-play');
|
||||
label.classList.add('fa-pause');
|
||||
} else {
|
||||
@ -805,6 +816,7 @@ function onLoaded(apple2: Apple2, disk2: DiskII, smartPort: SmartPort, printer:
|
||||
_disk2 = disk2;
|
||||
_smartPort = smartPort;
|
||||
_printer = printer;
|
||||
_e = e;
|
||||
|
||||
system = new System(io, e);
|
||||
optionsModal.addOptions(system);
|
||||
@ -835,6 +847,8 @@ function onLoaded(apple2: Apple2, disk2: DiskII, smartPort: SmartPort, printer:
|
||||
}
|
||||
});
|
||||
|
||||
buildDiskIndex();
|
||||
|
||||
/*
|
||||
* Input Handling
|
||||
*/
|
||||
@ -865,9 +879,9 @@ function onLoaded(apple2: Apple2, disk2: DiskII, smartPort: SmartPort, printer:
|
||||
_apple2.stop();
|
||||
processHash(hash);
|
||||
} else {
|
||||
vm.ready.then(() => {
|
||||
_apple2.ready.then(() => {
|
||||
_apple2.run();
|
||||
});
|
||||
}).catch(console.error);
|
||||
}
|
||||
|
||||
document.querySelector<HTMLInputElement>('#local_file')?.addEventListener(
|
||||
|
@ -89,15 +89,20 @@ export class Audio implements OptionHandler {
|
||||
autoStart = () => {
|
||||
if (this.audioContext && !this.started) {
|
||||
this.samples = [];
|
||||
this.audioContext.resume();
|
||||
this.started = true;
|
||||
this.audioContext.resume().then(() => {
|
||||
this.started = true;
|
||||
}).catch((error) => {
|
||||
console.warn('audio not started', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
start = () => {
|
||||
if (this.audioContext) {
|
||||
this.samples = [];
|
||||
this.audioContext.resume();
|
||||
this.audioContext.resume().catch((error) => {
|
||||
console.warn('audio not resumed', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ export default class Tape {
|
||||
fileReader.onload = (ev: ProgressEvent) => {
|
||||
const target: FileReader = ev.target as FileReader;
|
||||
const result: ArrayBuffer = target.result as ArrayBuffer;
|
||||
context.decodeAudioData(result, (buffer) => {
|
||||
context.decodeAudioData(result).then((buffer) => {
|
||||
const buf: TapeData = [];
|
||||
const data = buffer.getChannelData(0);
|
||||
let datum = data[0];
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
import { VideoPage } from 'js/videomodes';
|
||||
import { LoresPage2D, HiresPage2D, VideoModes2D } from 'js/canvas';
|
||||
import apple2enh_char from 'js/roms/apple2enh_char';
|
||||
import apple2enh_char from 'js/roms/character/apple2enh_char';
|
||||
import { createImageFromImageData } from 'test/util/image';
|
||||
|
||||
function checkImageData(page: VideoPage) {
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
import { VideoPage } from 'js/videomodes';
|
||||
import { LoresPageGL, HiresPageGL, VideoModesGL } from 'js/gl';
|
||||
import apple2enh_char from 'js/roms/apple2enh_char';
|
||||
import apple2enh_char from 'js/roms/character/apple2enh_char';
|
||||
import { createImageFromImageData } from 'test/util/image';
|
||||
|
||||
function checkImageData(page: VideoPage) {
|
||||
|
@ -1,10 +1,10 @@
|
||||
import type ROM from '../../js/roms/rom';
|
||||
import OriginalROM from '../../js/roms/original';
|
||||
import IntegerROM from '../../js/roms/intbasic';
|
||||
import FPBasicROM from '../../js/roms/fpbasic';
|
||||
import Apple2eROM from '../../js/roms/apple2e';
|
||||
import Apple2enhROM from '../../js/roms/apple2enh';
|
||||
import Apple2jROM from '../../js/roms/apple2j';
|
||||
import OriginalROM from '../../js/roms/system/original';
|
||||
import IntegerROM from '../../js/roms/system/intbasic';
|
||||
import FPBasicROM from '../../js/roms/system/fpbasic';
|
||||
import Apple2eROM from '../../js/roms/system/apple2e';
|
||||
import Apple2enhROM from '../../js/roms/system/apple2enh';
|
||||
import Apple2jROM from '../../js/roms/system/apple2j';
|
||||
|
||||
const roms: { [name: string]: { new(): ROM } } = {
|
||||
'original': OriginalROM,
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"module": "esnext",
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"target": "es6",
|
||||
@ -30,5 +30,6 @@
|
||||
"include": [
|
||||
"js/**/*",
|
||||
"test/**/*",
|
||||
"*.config.js"
|
||||
]
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ module.exports =
|
||||
},
|
||||
output: {
|
||||
path: path.resolve('dist/'),
|
||||
filename: '[name].bundle.js',
|
||||
chunkFilename: '[name].bundle.js',
|
||||
library: {
|
||||
name: 'Apple2',
|
||||
type: 'umd',
|
||||
@ -54,7 +56,7 @@ module.exports =
|
||||
},
|
||||
],
|
||||
exclude: /node_modules/,
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
|
Loading…
Reference in New Issue
Block a user