mirror of
https://github.com/whscullin/apple2js.git
synced 2024-01-12 14:14:38 +00:00
This reverts commit 8c2299e43e1af4ea8120aecc7fdb645e2700e4d4.
This commit is contained in:
parent
8c2299e43e
commit
2fcd6a377c
File diff suppressed because it is too large
Load Diff
@ -18,9 +18,9 @@ export interface SmartPortOptions {
|
||||
}
|
||||
|
||||
export interface Callbacks {
|
||||
driveLight: (driveNo: DriveNumber, on: boolean) => void;
|
||||
dirty: (driveNo: DriveNumber, dirty: boolean) => void;
|
||||
label: (driveNo: DriveNumber, name?: string, side?: string) => void;
|
||||
driveLight: (drive: DriveNumber, on: boolean) => void;
|
||||
dirty: (drive: DriveNumber, dirty: boolean) => void;
|
||||
label: (drive: DriveNumber, name?: string, side?: string) => void;
|
||||
}
|
||||
|
||||
class Address {
|
||||
@ -152,15 +152,15 @@ export default class SmartPort implements Card, MassStorage<BlockFormat>, Restor
|
||||
// debug.apply(this, arguments);
|
||||
}
|
||||
|
||||
private driveLight(driveNo: DriveNumber) {
|
||||
if (!this.busy[driveNo]) {
|
||||
this.busy[driveNo] = true;
|
||||
this.callbacks?.driveLight(driveNo, true);
|
||||
private driveLight(drive: DriveNumber) {
|
||||
if (!this.busy[drive]) {
|
||||
this.busy[drive] = true;
|
||||
this.callbacks?.driveLight(drive, true);
|
||||
}
|
||||
clearTimeout(this.busyTimeout[driveNo]);
|
||||
this.busyTimeout[driveNo] = setTimeout(() => {
|
||||
this.busy[driveNo] = false;
|
||||
this.callbacks?.driveLight(driveNo, false);
|
||||
clearTimeout(this.busyTimeout[drive]);
|
||||
this.busyTimeout[drive] = setTimeout(() => {
|
||||
this.busy[drive] = false;
|
||||
this.callbacks?.driveLight(drive, false);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
@ -168,7 +168,7 @@ export default class SmartPort implements Card, MassStorage<BlockFormat>, Restor
|
||||
* dumpBlock
|
||||
*/
|
||||
|
||||
dumpBlock(driveNo: DriveNumber, block: number) {
|
||||
dumpBlock(drive: DriveNumber, block: number) {
|
||||
let result = '';
|
||||
let b;
|
||||
let jdx;
|
||||
@ -176,7 +176,7 @@ export default class SmartPort implements Card, MassStorage<BlockFormat>, Restor
|
||||
for (let idx = 0; idx < 32; idx++) {
|
||||
result += toHex(idx << 4, 4) + ': ';
|
||||
for (jdx = 0; jdx < 16; jdx++) {
|
||||
b = this.disks[driveNo].blocks[block][idx * 16 + jdx];
|
||||
b = this.disks[drive].blocks[block][idx * 16 + jdx];
|
||||
if (jdx === 8) {
|
||||
result += ' ';
|
||||
}
|
||||
@ -184,7 +184,7 @@ export default class SmartPort implements Card, MassStorage<BlockFormat>, Restor
|
||||
}
|
||||
result += ' ';
|
||||
for (jdx = 0; jdx < 16; jdx++) {
|
||||
b = this.disks[driveNo].blocks[block][idx * 16 + jdx] & 0x7f;
|
||||
b = this.disks[drive].blocks[block][idx * 16 + jdx] & 0x7f;
|
||||
if (jdx === 8) {
|
||||
result += ' ';
|
||||
}
|
||||
@ -203,9 +203,9 @@ export default class SmartPort implements Card, MassStorage<BlockFormat>, Restor
|
||||
* getDeviceInfo
|
||||
*/
|
||||
|
||||
getDeviceInfo(state: CpuState, driveNo: DriveNumber) {
|
||||
if (this.disks[driveNo]) {
|
||||
const blocks = this.disks[driveNo].blocks.length;
|
||||
getDeviceInfo(state: CpuState, drive: DriveNumber) {
|
||||
if (this.disks[drive]) {
|
||||
const blocks = this.disks[drive].blocks.length;
|
||||
state.x = blocks & 0xff;
|
||||
state.y = blocks >> 8;
|
||||
|
||||
@ -221,23 +221,23 @@ export default class SmartPort implements Card, MassStorage<BlockFormat>, Restor
|
||||
* readBlock
|
||||
*/
|
||||
|
||||
readBlock(state: CpuState, driveNo: DriveNumber, block: number, buffer: Address) {
|
||||
this.debug(`read drive=${driveNo}`);
|
||||
readBlock(state: CpuState, drive: DriveNumber, block: number, buffer: Address) {
|
||||
this.debug(`read drive=${drive}`);
|
||||
this.debug(`read buffer=${buffer.toString()}`);
|
||||
this.debug(`read block=$${toHex(block)}`);
|
||||
|
||||
if (!this.disks[driveNo]?.blocks.length) {
|
||||
debug('Drive', driveNo, 'is empty');
|
||||
if (!this.disks[drive]?.blocks.length) {
|
||||
debug('Drive', drive, 'is empty');
|
||||
state.a = DEVICE_OFFLINE;
|
||||
state.s |= flags.C;
|
||||
return;
|
||||
}
|
||||
|
||||
// debug('read', '\n' + dumpBlock(drive, block));
|
||||
this.driveLight(driveNo);
|
||||
this.driveLight(drive);
|
||||
|
||||
for (let idx = 0; idx < 512; idx++) {
|
||||
buffer.writeByte(this.disks[driveNo].blocks[block][idx]);
|
||||
buffer.writeByte(this.disks[drive].blocks[block][idx]);
|
||||
buffer = buffer.inc(1);
|
||||
}
|
||||
|
||||
@ -249,30 +249,30 @@ export default class SmartPort implements Card, MassStorage<BlockFormat>, Restor
|
||||
* writeBlock
|
||||
*/
|
||||
|
||||
writeBlock(state: CpuState, driveNo: DriveNumber, block: number, buffer: Address) {
|
||||
this.debug(`write drive=${driveNo}`);
|
||||
writeBlock(state: CpuState, drive: DriveNumber, block: number, buffer: Address) {
|
||||
this.debug(`write drive=${drive}`);
|
||||
this.debug(`write buffer=${buffer.toString()}`);
|
||||
this.debug(`write block=$${toHex(block)}`);
|
||||
|
||||
if (!this.disks[driveNo]?.blocks.length) {
|
||||
debug('Drive', driveNo, 'is empty');
|
||||
if (!this.disks[drive]?.blocks.length) {
|
||||
debug('Drive', drive, 'is empty');
|
||||
state.a = DEVICE_OFFLINE;
|
||||
state.s |= flags.C;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.disks[driveNo].readOnly) {
|
||||
debug('Drive', driveNo, 'is write protected');
|
||||
if (this.disks[drive].readOnly) {
|
||||
debug('Drive', drive, 'is write protected');
|
||||
state.a = WRITE_PROTECTED;
|
||||
state.s |= flags.C;
|
||||
return;
|
||||
}
|
||||
|
||||
// debug('write', '\n' + dumpBlock(drive, block));
|
||||
this.driveLight(driveNo);
|
||||
this.driveLight(drive);
|
||||
|
||||
for (let idx = 0; idx < 512; idx++) {
|
||||
this.disks[driveNo].blocks[block][idx] = buffer.readByte();
|
||||
this.disks[drive].blocks[block][idx] = buffer.readByte();
|
||||
buffer = buffer.inc(1);
|
||||
}
|
||||
state.a = 0;
|
||||
@ -283,25 +283,25 @@ export default class SmartPort implements Card, MassStorage<BlockFormat>, Restor
|
||||
* formatDevice
|
||||
*/
|
||||
|
||||
formatDevice(state: CpuState, driveNo: DriveNumber) {
|
||||
if (!this.disks[driveNo]?.blocks.length) {
|
||||
debug('Drive', driveNo, 'is empty');
|
||||
formatDevice(state: CpuState, drive: DriveNumber) {
|
||||
if (!this.disks[drive]?.blocks.length) {
|
||||
debug('Drive', drive, 'is empty');
|
||||
state.a = DEVICE_OFFLINE;
|
||||
state.s |= flags.C;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.disks[driveNo].readOnly) {
|
||||
debug('Drive', driveNo, 'is write protected');
|
||||
if (this.disks[drive].readOnly) {
|
||||
debug('Drive', drive, 'is write protected');
|
||||
state.a = WRITE_PROTECTED;
|
||||
state.s |= flags.C;
|
||||
return;
|
||||
}
|
||||
|
||||
for (let idx = 0; idx < this.disks[driveNo].blocks.length; idx++) {
|
||||
this.disks[driveNo].blocks[idx] = new Uint8Array();
|
||||
for (let idx = 0; idx < this.disks[drive].blocks.length; idx++) {
|
||||
this.disks[drive].blocks[idx] = new Uint8Array();
|
||||
for (let jdx = 0; jdx < 512; jdx++) {
|
||||
this.disks[driveNo].blocks[idx][jdx] = 0;
|
||||
this.disks[drive].blocks[idx][jdx] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -549,18 +549,18 @@ export default class SmartPort implements Card, MassStorage<BlockFormat>, Restor
|
||||
);
|
||||
}
|
||||
|
||||
setBinary(driveNo: DriveNumber, name: string, fmt: BlockFormat, rawData: ArrayBuffer) {
|
||||
setBinary(drive: DriveNumber, name: string, fmt: BlockFormat, rawData: ArrayBuffer) {
|
||||
let volume = 254;
|
||||
let readOnly = false;
|
||||
if (fmt === '2mg') {
|
||||
const header = read2MGHeader(rawData);
|
||||
this.metadata[driveNo] = header;
|
||||
this.metadata[drive] = header;
|
||||
const { bytes, offset } = header;
|
||||
volume = header.volume;
|
||||
readOnly = header.readOnly;
|
||||
rawData = rawData.slice(offset, offset + bytes);
|
||||
} else {
|
||||
this.metadata[driveNo] = null;
|
||||
this.metadata[drive] = null;
|
||||
}
|
||||
const options = {
|
||||
rawData,
|
||||
@ -569,9 +569,9 @@ export default class SmartPort implements Card, MassStorage<BlockFormat>, Restor
|
||||
volume,
|
||||
};
|
||||
|
||||
this.ext[driveNo] = fmt;
|
||||
this.disks[driveNo] = createBlockDisk(fmt, options);
|
||||
this.callbacks?.label(driveNo, name);
|
||||
this.ext[drive] = fmt;
|
||||
this.disks[drive] = createBlockDisk(fmt, options);
|
||||
this.callbacks?.label(drive, name);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -63,19 +63,19 @@ export const BlockDisk = ({ smartPort, number, on, name }: BlockDiskProps) => {
|
||||
<DiskDragTarget
|
||||
className={styles.disk}
|
||||
storage={smartPort}
|
||||
driveNo={number}
|
||||
drive={number}
|
||||
formats={BLOCK_FORMATS}
|
||||
onError={setError}
|
||||
>
|
||||
<ErrorModal error={error} setError={setError} />
|
||||
<BlockFileModal
|
||||
smartPort={smartPort}
|
||||
driveNo={number}
|
||||
number={number}
|
||||
onClose={doClose}
|
||||
isOpen={modalOpen}
|
||||
/>
|
||||
<DownloadModal
|
||||
driveNo={number}
|
||||
number={number}
|
||||
massStorage={smartPort}
|
||||
isOpen={downloadModalOpen}
|
||||
onClose={doCloseDownload}
|
||||
|
@ -21,11 +21,11 @@ const DISK_TYPES: FilePickerAcceptType[] = [
|
||||
interface BlockFileModalProps {
|
||||
isOpen: boolean;
|
||||
smartPort: SmartPort;
|
||||
driveNo: DriveNumber;
|
||||
number: DriveNumber;
|
||||
onClose: (closeBox?: boolean) => void;
|
||||
}
|
||||
|
||||
export const BlockFileModal = ({ smartPort, driveNo: number, onClose, isOpen } : BlockFileModalProps) => {
|
||||
export const BlockFileModal = ({ smartPort, number, onClose, isOpen } : BlockFileModalProps) => {
|
||||
const [handles, setHandles] = useState<FileSystemFileHandle[]>();
|
||||
const [busy, setBusy] = useState<boolean>(false);
|
||||
const [empty, setEmpty] = useState<boolean>(true);
|
||||
|
@ -6,7 +6,7 @@ import { spawn } from './util/promises';
|
||||
|
||||
export interface DiskDragTargetProps<T> extends JSX.HTMLAttributes<HTMLDivElement> {
|
||||
storage: MassStorage<T> | undefined;
|
||||
driveNo?: DriveNumber;
|
||||
drive?: DriveNumber;
|
||||
formats: typeof FLOPPY_FORMATS
|
||||
| typeof BLOCK_FORMATS
|
||||
| typeof DISK_FORMATS;
|
||||
@ -16,7 +16,7 @@ export interface DiskDragTargetProps<T> extends JSX.HTMLAttributes<HTMLDivElemen
|
||||
|
||||
export const DiskDragTarget = ({
|
||||
storage,
|
||||
driveNo,
|
||||
drive,
|
||||
dropRef,
|
||||
formats,
|
||||
onError,
|
||||
@ -54,7 +54,7 @@ export const DiskDragTarget = ({
|
||||
const onDrop = (event: DragEvent) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const targetDrive = driveNo ?? 1; //TODO(whscullin) Maybe pick available drive
|
||||
const targetDrive = drive ?? 1; //TODO(whscullin) Maybe pick available drive
|
||||
|
||||
const dt = event.dataTransfer;
|
||||
if (dt?.files.length === 1 && storage) {
|
||||
@ -87,7 +87,7 @@ export const DiskDragTarget = ({
|
||||
div.removeEventListener('drop', onDrop);
|
||||
};
|
||||
}
|
||||
}, [driveNo, dropRef, formats, onError, storage]);
|
||||
}, [drive, dropRef, formats, onError, storage]);
|
||||
|
||||
return (
|
||||
<div ref={ref} {...props}>
|
||||
|
@ -65,13 +65,13 @@ export const DiskII = ({ disk2, number, on, name, side }: DiskIIProps) => {
|
||||
<DiskDragTarget
|
||||
className={styles.disk}
|
||||
storage={disk2}
|
||||
driveNo={number}
|
||||
drive={number}
|
||||
formats={FLOPPY_FORMATS}
|
||||
onError={setError}
|
||||
>
|
||||
<FileModal disk2={disk2} driveNo={number} onClose={doClose} isOpen={modalOpen} />
|
||||
<FileModal disk2={disk2} number={number} onClose={doClose} isOpen={modalOpen} />
|
||||
<DownloadModal
|
||||
driveNo={number}
|
||||
number={number}
|
||||
massStorage={disk2}
|
||||
isOpen={downloadModalOpen}
|
||||
onClose={doCloseDownload}
|
||||
|
@ -8,18 +8,18 @@ import styles from './css/DownloadModal.module.css';
|
||||
interface DownloadModalProps {
|
||||
isOpen: boolean;
|
||||
massStorage: MassStorage<unknown>;
|
||||
driveNo: DriveNumber;
|
||||
number: DriveNumber;
|
||||
onClose: (closeBox?: boolean) => void;
|
||||
}
|
||||
|
||||
export const DownloadModal = ({ massStorage, driveNo, onClose, isOpen } : DownloadModalProps) => {
|
||||
export const DownloadModal = ({ massStorage, number, onClose, isOpen } : DownloadModalProps) => {
|
||||
const [href, setHref] = useState('');
|
||||
const [downloadName, setDownloadName] = useState('');
|
||||
const doCancel = useCallback(() => onClose(true), [onClose]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
const storageData = massStorage.getBinary(driveNo);
|
||||
const storageData = massStorage.getBinary(number);
|
||||
if (storageData) {
|
||||
const { ext, data } = storageData;
|
||||
const { name } = storageData.metadata;
|
||||
@ -37,7 +37,7 @@ export const DownloadModal = ({ massStorage, driveNo, onClose, isOpen } : Downlo
|
||||
setHref('');
|
||||
setDownloadName('');
|
||||
}
|
||||
}, [isOpen, driveNo, massStorage]);
|
||||
}, [isOpen, number, massStorage]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -10,7 +10,7 @@ import { ErrorModal } from './ErrorModal';
|
||||
import { ProgressModal } from './ProgressModal';
|
||||
import { loadHttpUnknownFile, getHashParts, loadJSON, SmartStorageBroker } from './util/files';
|
||||
import { useHash } from './hooks/useHash';
|
||||
import { DISK_FORMATS, DRIVE_NUMBERS, SupportedSectors } from 'js/formats/types';
|
||||
import { DISK_FORMATS, DriveNumber, SupportedSectors } from 'js/formats/types';
|
||||
import { spawn, Ready } from './util/promises';
|
||||
|
||||
import styles from './css/Drives.module.css';
|
||||
@ -90,9 +90,9 @@ export const Drives = ({ cpu, io, sectors, enhanced, ready }: DrivesProps) => {
|
||||
const hashParts = getHashParts(hash);
|
||||
const controllers: AbortController[] = [];
|
||||
let loading = 0;
|
||||
for (const driveNo of DRIVE_NUMBERS) {
|
||||
if (hashParts && hashParts[driveNo]) {
|
||||
const hashPart = decodeURIComponent(hashParts[driveNo]);
|
||||
for (const drive of [1, 2] as DriveNumber[]) {
|
||||
if (hashParts && hashParts[drive]) {
|
||||
const hashPart = decodeURIComponent(hashParts[drive]);
|
||||
const isHttp = hashPart.match(/^https?:/i);
|
||||
const isJson = hashPart.match(/\.json$/i);
|
||||
if (isHttp && !isJson) {
|
||||
@ -101,7 +101,7 @@ export const Drives = ({ cpu, io, sectors, enhanced, ready }: DrivesProps) => {
|
||||
try {
|
||||
await loadHttpUnknownFile(
|
||||
smartStorageBroker,
|
||||
driveNo,
|
||||
drive,
|
||||
hashPart,
|
||||
signal,
|
||||
onProgress);
|
||||
@ -116,7 +116,7 @@ export const Drives = ({ cpu, io, sectors, enhanced, ready }: DrivesProps) => {
|
||||
}));
|
||||
} else {
|
||||
const url = isHttp ? hashPart : `json/disks/${hashPart}.json`;
|
||||
loadJSON(disk2, driveNo, url).catch((e) => setError(e));
|
||||
loadJSON(disk2, drive, url).catch((e) => setError(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ export type NibbleFileCallback = (
|
||||
interface FileModalProps {
|
||||
isOpen: boolean;
|
||||
disk2: DiskII;
|
||||
driveNo: DriveNumber;
|
||||
number: DriveNumber;
|
||||
onClose: (closeBox?: boolean) => void;
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ interface IndexEntry {
|
||||
category: string;
|
||||
}
|
||||
|
||||
export const FileModal = ({ disk2, driveNo, onClose, isOpen }: FileModalProps) => {
|
||||
export const FileModal = ({ disk2, number, onClose, isOpen }: FileModalProps) => {
|
||||
const [busy, setBusy] = useState<boolean>(false);
|
||||
const [empty, setEmpty] = useState<boolean>(true);
|
||||
const [category, setCategory] = useState<string>();
|
||||
@ -69,13 +69,13 @@ export const FileModal = ({ disk2, driveNo, onClose, isOpen }: FileModalProps) =
|
||||
|
||||
try {
|
||||
if (handles?.length === 1) {
|
||||
hashParts[driveNo] = '';
|
||||
await loadLocalNibbleFile(disk2, driveNo, await handles[0].getFile());
|
||||
hashParts[number] = '';
|
||||
await loadLocalNibbleFile(disk2, number, await handles[0].getFile());
|
||||
}
|
||||
if (filename) {
|
||||
const name = filename.match(/\/([^/]+).json$/) || ['', ''];
|
||||
hashParts[driveNo] = name[1];
|
||||
await loadJSON(disk2, driveNo, filename);
|
||||
hashParts[number] = name[1];
|
||||
await loadJSON(disk2, number, filename);
|
||||
}
|
||||
} catch (e) {
|
||||
setError(e);
|
||||
@ -86,7 +86,7 @@ export const FileModal = ({ disk2, driveNo, onClose, isOpen }: FileModalProps) =
|
||||
}
|
||||
|
||||
setHashParts(hashParts);
|
||||
}, [disk2, filename, driveNo, onClose, handles, hash]);
|
||||
}, [disk2, filename, number, onClose, handles, hash]);
|
||||
|
||||
const onChange = useCallback((handles: FileSystemFileHandle[]) => {
|
||||
setEmpty(handles.length === 0);
|
||||
|
@ -235,7 +235,7 @@ const Catalog = ({ dos, setFileData }: CatalogProps) => {
|
||||
*/
|
||||
interface DiskInfoProps {
|
||||
massStorage: MassStorage<DiskFormat>;
|
||||
driveNo: DriveNumber;
|
||||
drive: DriveNumber;
|
||||
setFileData: (fileData: FileData) => void;
|
||||
}
|
||||
|
||||
@ -250,9 +250,9 @@ interface DiskInfoProps {
|
||||
* @param drive The drive number
|
||||
* @returns DiskInfo component
|
||||
*/
|
||||
const DiskInfo = ({ massStorage, driveNo, setFileData }: DiskInfoProps) => {
|
||||
const DiskInfo = ({ massStorage, drive, setFileData }: DiskInfoProps) => {
|
||||
const disk = useMemo(() => {
|
||||
const massStorageData = massStorage.getBinary(driveNo, 'po');
|
||||
const massStorageData = massStorage.getBinary(drive, 'po');
|
||||
if (massStorageData) {
|
||||
const { data, readOnly, ext } = massStorageData;
|
||||
const { name } = massStorageData.metadata;
|
||||
@ -265,7 +265,7 @@ const DiskInfo = ({ massStorage, driveNo, setFileData }: DiskInfoProps) => {
|
||||
volume: 254,
|
||||
});
|
||||
} else if (data.byteLength < 800 * 1024) {
|
||||
const doData = massStorage.getBinary(driveNo, 'do');
|
||||
const doData = massStorage.getBinary(drive, 'do');
|
||||
if (doData) {
|
||||
if (isMaybeDOS33(doData)) {
|
||||
disk = createDiskFromDOS({
|
||||
@ -288,7 +288,7 @@ const DiskInfo = ({ massStorage, driveNo, setFileData }: DiskInfoProps) => {
|
||||
return disk;
|
||||
}
|
||||
return null;
|
||||
}, [massStorage, driveNo]);
|
||||
}, [massStorage, drive]);
|
||||
|
||||
if (disk) {
|
||||
try {
|
||||
@ -409,11 +409,11 @@ export const Disks = ({ apple2 }: DisksProps) => {
|
||||
<div className={debuggerStyles.subHeading}>
|
||||
{card.constructor.name} - 1
|
||||
</div>
|
||||
<DiskInfo massStorage={card} driveNo={1} setFileData={setFileData} />
|
||||
<DiskInfo massStorage={card} drive={1} setFileData={setFileData} />
|
||||
<div className={debuggerStyles.subHeading}>
|
||||
{card.constructor.name} - 2
|
||||
</div>
|
||||
<DiskInfo massStorage={card} driveNo={2} setFileData={setFileData} />
|
||||
<DiskInfo massStorage={card} drive={2} setFileData={setFileData} />
|
||||
</div>
|
||||
))}
|
||||
<FileViewer fileData={fileData} onClose={onClose} />
|
||||
|
@ -48,7 +48,7 @@ export const getNameAndExtension = (url: string) => {
|
||||
export const loadLocalFile = (
|
||||
storage: MassStorage<FloppyFormat|BlockFormat>,
|
||||
formats: typeof FLOPPY_FORMATS | typeof BLOCK_FORMATS | typeof DISK_FORMATS,
|
||||
driveNo: DriveNumber,
|
||||
number: DriveNumber,
|
||||
file: File,
|
||||
) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -58,7 +58,7 @@ export const loadLocalFile = (
|
||||
const { name, ext } = getNameAndExtension(file.name);
|
||||
if (includes(formats, ext)) {
|
||||
initGamepad();
|
||||
if (storage.setBinary(driveNo, name, ext, result)) {
|
||||
if (storage.setBinary(number, name, ext, result)) {
|
||||
resolve(true);
|
||||
} else {
|
||||
reject(`Unable to load ${name}`);
|
||||
@ -76,12 +76,12 @@ export const loadLocalFile = (
|
||||
* selection form element to be loaded.
|
||||
*
|
||||
* @param smartPort SmartPort object
|
||||
* @param driveNo Drive number
|
||||
* @param number Drive number
|
||||
* @param file Browser File object to load
|
||||
* @returns true if successful
|
||||
*/
|
||||
export const loadLocalBlockFile = (smartPort: SmartPort, driveNo: DriveNumber, file: File) => {
|
||||
return loadLocalFile(smartPort, BLOCK_FORMATS, driveNo, file);
|
||||
export const loadLocalBlockFile = (smartPort: SmartPort, number: DriveNumber, file: File) => {
|
||||
return loadLocalFile(smartPort, BLOCK_FORMATS, number, file);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -89,12 +89,12 @@ export const loadLocalBlockFile = (smartPort: SmartPort, driveNo: DriveNumber, f
|
||||
* selection form element to be loaded.
|
||||
*
|
||||
* @param disk2 Disk2 object
|
||||
* @param driveNo Drive number
|
||||
* @param number Drive number
|
||||
* @param file Browser File object to load
|
||||
* @returns true if successful
|
||||
*/
|
||||
export const loadLocalNibbleFile = (disk2: Disk2, driveNo: DriveNumber, file: File) => {
|
||||
return loadLocalFile(disk2, FLOPPY_FORMATS, driveNo, file);
|
||||
export const loadLocalNibbleFile = (disk2: Disk2, number: DriveNumber, file: File) => {
|
||||
return loadLocalFile(disk2, FLOPPY_FORMATS, number, file);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -103,13 +103,13 @@ export const loadLocalNibbleFile = (disk2: Disk2, driveNo: DriveNumber, file: Fi
|
||||
* as the emulator.
|
||||
*
|
||||
* @param disk2 Disk2 object
|
||||
* @param driveNo Drive number
|
||||
* @param number Drive number
|
||||
* @param url URL, relative or absolute to JSON file
|
||||
* @returns true if successful
|
||||
*/
|
||||
export const loadJSON = async (
|
||||
disk2: Disk2,
|
||||
driveNo: DriveNumber,
|
||||
number: DriveNumber,
|
||||
url: string,
|
||||
) => {
|
||||
const response = await fetch(url);
|
||||
@ -120,7 +120,7 @@ export const loadJSON = async (
|
||||
if (!includes(FLOPPY_FORMATS, data.type)) {
|
||||
throw new Error(`Type "${data.type}" not recognized.`);
|
||||
}
|
||||
disk2.setDisk(driveNo, data);
|
||||
disk2.setDisk(number, data);
|
||||
initGamepad(data.gamepad);
|
||||
};
|
||||
|
||||
@ -166,13 +166,13 @@ export const loadHttpFile = async (
|
||||
* as the emulator.
|
||||
*
|
||||
* @param smartPort SmartPort object
|
||||
* @param driveNo Drive number
|
||||
* @param number Drive number
|
||||
* @param url URL, relative or absolute to JSON file
|
||||
* @returns true if successful
|
||||
*/
|
||||
export const loadHttpBlockFile = async (
|
||||
smartPort: SmartPort,
|
||||
driveNo: DriveNumber,
|
||||
number: DriveNumber,
|
||||
url: string,
|
||||
signal?: AbortSignal,
|
||||
onProgress?: ProgressCallback
|
||||
@ -182,7 +182,7 @@ export const loadHttpBlockFile = async (
|
||||
throw new Error(`Extension "${ext}" not recognized.`);
|
||||
}
|
||||
const data = await loadHttpFile(url, signal, onProgress);
|
||||
smartPort.setBinary(driveNo, name, ext, data);
|
||||
smartPort.setBinary(number, name, ext, data);
|
||||
initGamepad();
|
||||
|
||||
return true;
|
||||
@ -194,55 +194,55 @@ export const loadHttpBlockFile = async (
|
||||
* as the emulator.
|
||||
*
|
||||
* @param disk2 Disk2 object
|
||||
* @param driveNo Drive number
|
||||
* @param number Drive number
|
||||
* @param url URL, relative or absolute to JSON file
|
||||
* @returns true if successful
|
||||
*/
|
||||
export const loadHttpNibbleFile = async (
|
||||
disk2: Disk2,
|
||||
driveNo: DriveNumber,
|
||||
number: DriveNumber,
|
||||
url: string,
|
||||
signal?: AbortSignal,
|
||||
onProgress?: ProgressCallback
|
||||
) => {
|
||||
if (url.endsWith('.json')) {
|
||||
return loadJSON(disk2, driveNo, url);
|
||||
return loadJSON(disk2, number, url);
|
||||
}
|
||||
const { name, ext } = getNameAndExtension(url);
|
||||
if (!includes(FLOPPY_FORMATS, ext)) {
|
||||
throw new Error(`Extension "${ext}" not recognized.`);
|
||||
}
|
||||
const data = await loadHttpFile(url, signal, onProgress);
|
||||
disk2.setBinary(driveNo, name, ext, data);
|
||||
disk2.setBinary(number, name, ext, data);
|
||||
initGamepad();
|
||||
return loadHttpFile(url, signal, onProgress);
|
||||
};
|
||||
|
||||
export const loadHttpUnknownFile = async (
|
||||
smartStorageBroker: SmartStorageBroker,
|
||||
driveNo: DriveNumber,
|
||||
number: DriveNumber,
|
||||
url: string,
|
||||
signal?: AbortSignal,
|
||||
onProgress?: ProgressCallback,
|
||||
) => {
|
||||
const data = await loadHttpFile(url, signal, onProgress);
|
||||
const { name, ext } = getNameAndExtension(url);
|
||||
smartStorageBroker.setBinary(driveNo, name, ext, data);
|
||||
smartStorageBroker.setBinary(number, name, ext, data);
|
||||
};
|
||||
|
||||
export class SmartStorageBroker implements MassStorage<unknown> {
|
||||
constructor(private disk2: Disk2, private smartPort: SmartPort) {}
|
||||
|
||||
setBinary(driveNo: DriveNumber, name: string, ext: string, data: ArrayBuffer): boolean {
|
||||
setBinary(drive: DriveNumber, name: string, ext: string, data: ArrayBuffer): boolean {
|
||||
if (includes(DISK_FORMATS, ext)) {
|
||||
if (data.byteLength >= 800 * 1024) {
|
||||
if (includes(BLOCK_FORMATS, ext)) {
|
||||
this.smartPort.setBinary(driveNo, name, ext, data);
|
||||
this.smartPort.setBinary(drive, name, ext, data);
|
||||
} else {
|
||||
throw new Error(`Unable to load "${name}"`);
|
||||
}
|
||||
} else if (includes(FLOPPY_FORMATS, ext)) {
|
||||
this.disk2.setBinary(driveNo, name, ext, data);
|
||||
this.disk2.setBinary(drive, name, ext, data);
|
||||
} else {
|
||||
throw new Error(`Unable to load "${name}"`);
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ export const PROCESS_JSON = 'PROCESS_JSON';
|
||||
export interface ProcessBinaryMessage {
|
||||
type: typeof PROCESS_BINARY;
|
||||
payload: {
|
||||
driveNo: DriveNumber;
|
||||
drive: DriveNumber;
|
||||
fmt: FloppyFormat;
|
||||
options: DiskOptions;
|
||||
};
|
||||
@ -244,7 +244,7 @@ export interface ProcessBinaryMessage {
|
||||
export interface ProcessJsonDiskMessage {
|
||||
type: typeof PROCESS_JSON_DISK;
|
||||
payload: {
|
||||
driveNo: DriveNumber;
|
||||
drive: DriveNumber;
|
||||
jsonDisk: JSONDisk;
|
||||
};
|
||||
}
|
||||
@ -253,7 +253,7 @@ export interface ProcessJsonDiskMessage {
|
||||
export interface ProcessJsonMessage {
|
||||
type: typeof PROCESS_JSON;
|
||||
payload: {
|
||||
driveNo: DriveNumber;
|
||||
drive: DriveNumber;
|
||||
json: string;
|
||||
};
|
||||
}
|
||||
@ -272,7 +272,7 @@ export const DISK_PROCESSED = 'DISK_PROCESSED';
|
||||
export interface DiskProcessedResponse {
|
||||
type: typeof DISK_PROCESSED;
|
||||
payload: {
|
||||
driveNo: DriveNumber;
|
||||
drive: DriveNumber;
|
||||
disk: FloppyDisk | null;
|
||||
};
|
||||
}
|
||||
|
103
js/ui/apple2.ts
103
js/ui/apple2.ts
@ -84,7 +84,7 @@ let joystick: JoyStick;
|
||||
let system: System;
|
||||
let keyboard: KeyBoard;
|
||||
let io: Apple2IO;
|
||||
let driveNo: DriveNumber = 1;
|
||||
let _currentDrive: DriveNumber = 1;
|
||||
let _e: boolean;
|
||||
|
||||
let ready: Promise<[void, void]>;
|
||||
@ -103,13 +103,14 @@ export function compileApplesoftProgram(program: string) {
|
||||
}
|
||||
|
||||
export function openLoad(driveString: string, event: MouseEvent) {
|
||||
driveNo = parseInt(driveString, 10) as DriveNumber;
|
||||
if (event.metaKey && includes(DRIVE_NUMBERS, driveNo)) {
|
||||
const drive = parseInt(driveString, 10) as DriveNumber;
|
||||
_currentDrive = drive;
|
||||
if (event.metaKey && includes(DRIVE_NUMBERS, drive)) {
|
||||
openLoadHTTP();
|
||||
} else {
|
||||
if (disk_cur_cat[driveNo]) {
|
||||
if (disk_cur_cat[drive]) {
|
||||
const element = document.querySelector<HTMLSelectElement>('#category_select')!;
|
||||
element.value = disk_cur_cat[driveNo];
|
||||
element.value = disk_cur_cat[drive];
|
||||
selectCategory();
|
||||
}
|
||||
MicroModal.show('load-modal');
|
||||
@ -117,27 +118,27 @@ export function openLoad(driveString: string, event: MouseEvent) {
|
||||
}
|
||||
|
||||
export function openSave(driveString: string, event: MouseEvent) {
|
||||
const driveNo = parseInt(driveString, 10) as DriveNumber;
|
||||
const drive = parseInt(driveString, 10) as DriveNumber;
|
||||
|
||||
const mimeType = 'application/octet-stream';
|
||||
const storageData = _disk2.getBinary(driveNo);
|
||||
const storageData = _disk2.getBinary(drive);
|
||||
const a = document.querySelector<HTMLAnchorElement>('#local_save_link')!;
|
||||
|
||||
if (!storageData) {
|
||||
alert(`No data from drive ${driveNo}`);
|
||||
alert(`No data from drive ${drive}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const { data } = storageData;
|
||||
const blob = new Blob([data], { 'type': mimeType });
|
||||
a.href = window.URL.createObjectURL(blob);
|
||||
a.download = driveLights.label(driveNo) + '.dsk';
|
||||
a.download = driveLights.label(drive) + '.dsk';
|
||||
|
||||
if (event.metaKey) {
|
||||
dumpDisk(driveNo);
|
||||
dumpDisk(drive);
|
||||
} else {
|
||||
const saveName = document.querySelector<HTMLInputElement>('#save_name')!;
|
||||
saveName.value = driveLights.label(driveNo);
|
||||
saveName.value = driveLights.label(drive);
|
||||
MicroModal.show('save-modal');
|
||||
}
|
||||
}
|
||||
@ -153,12 +154,12 @@ export function openAlert(msg: string) {
|
||||
* Drag and Drop
|
||||
*/
|
||||
|
||||
export function handleDragOver(_driveNo: number, event: DragEvent) {
|
||||
export function handleDragOver(_drive: number, event: DragEvent) {
|
||||
event.preventDefault();
|
||||
event.dataTransfer!.dropEffect = 'copy';
|
||||
}
|
||||
|
||||
export function handleDragEnd(_driveNo: number, event: DragEvent) {
|
||||
export function handleDragEnd(_drive: number, event: DragEvent) {
|
||||
const dt = event.dataTransfer!;
|
||||
if (dt.items) {
|
||||
for (let i = 0; i < dt.items.length; i++) {
|
||||
@ -169,23 +170,23 @@ export function handleDragEnd(_driveNo: number, event: DragEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
export function handleDrop(driveNo: number, event: DragEvent) {
|
||||
export function handleDrop(drive: number, event: DragEvent) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
if (driveNo < 1) {
|
||||
if (drive < 1) {
|
||||
if (!_disk2.getMetadata(1)) {
|
||||
driveNo = 1;
|
||||
drive = 1;
|
||||
} else if (!_disk2.getMetadata(2)) {
|
||||
driveNo = 2;
|
||||
drive = 2;
|
||||
} else {
|
||||
driveNo = 1;
|
||||
drive = 1;
|
||||
}
|
||||
}
|
||||
const dt = event.dataTransfer!;
|
||||
if (dt.files.length === 1) {
|
||||
const runOnLoad = event.shiftKey;
|
||||
doLoadLocal(driveNo as DriveNumber, dt.files[0], { runOnLoad });
|
||||
doLoadLocal(drive as DriveNumber, dt.files[0], { runOnLoad });
|
||||
} else if (dt.files.length === 2) {
|
||||
doLoadLocal(1, dt.files[0]);
|
||||
doLoadLocal(2, dt.files[1]);
|
||||
@ -194,7 +195,7 @@ export function handleDrop(driveNo: number, event: DragEvent) {
|
||||
if (dt.items[idx].type === 'text/uri-list') {
|
||||
dt.items[idx].getAsString(function (url) {
|
||||
const parts = hup().split('|');
|
||||
parts[driveNo - 1] = url;
|
||||
parts[drive - 1] = url;
|
||||
document.location.hash = parts.join('|');
|
||||
});
|
||||
}
|
||||
@ -227,7 +228,7 @@ function loadingStop() {
|
||||
}
|
||||
}
|
||||
|
||||
export function loadAjax(driveNo: DriveNumber, url: string) {
|
||||
export function loadAjax(drive: DriveNumber, url: string) {
|
||||
loadingStart();
|
||||
|
||||
fetch(url).then(function (response: Response) {
|
||||
@ -240,7 +241,7 @@ export function loadAjax(driveNo: DriveNumber, url: string) {
|
||||
if (data.type === 'binary') {
|
||||
loadBinary(data );
|
||||
} else if (includes(DISK_FORMATS, data.type)) {
|
||||
loadDisk(driveNo, data);
|
||||
loadDisk(drive, data);
|
||||
}
|
||||
initGamepad(data.gamepad);
|
||||
loadingStop();
|
||||
@ -268,7 +269,7 @@ export function doLoad(event: MouseEvent|KeyboardEvent) {
|
||||
const files = localFile.files;
|
||||
if (files && files.length === 1) {
|
||||
const runOnLoad = event.shiftKey;
|
||||
doLoadLocal(driveNo, files[0], { runOnLoad });
|
||||
doLoadLocal(_currentDrive, files[0], { runOnLoad });
|
||||
} else if (url) {
|
||||
let filename;
|
||||
MicroModal.close('load-modal');
|
||||
@ -277,7 +278,7 @@ export function doLoad(event: MouseEvent|KeyboardEvent) {
|
||||
if (filename === '__manage') {
|
||||
openManage();
|
||||
} else {
|
||||
loadLocalStorage(driveNo, filename);
|
||||
loadLocalStorage(_currentDrive, filename);
|
||||
}
|
||||
} else {
|
||||
const r1 = /json\/disks\/(.*).json$/.exec(url);
|
||||
@ -287,7 +288,7 @@ export function doLoad(event: MouseEvent|KeyboardEvent) {
|
||||
filename = url;
|
||||
}
|
||||
const parts = hup().split('|');
|
||||
parts[driveNo - 1] = filename;
|
||||
parts[_currentDrive - 1] = filename;
|
||||
document.location.hash = parts.join('|');
|
||||
}
|
||||
}
|
||||
@ -296,7 +297,7 @@ export function doLoad(event: MouseEvent|KeyboardEvent) {
|
||||
export function doSave() {
|
||||
const saveName = document.querySelector<HTMLInputElement>('#save_name')!;
|
||||
const name = saveName.value;
|
||||
saveLocalStorage(driveNo, name);
|
||||
saveLocalStorage(_currentDrive, name);
|
||||
MicroModal.close('save-modal');
|
||||
window.setTimeout(() => openAlert('Saved'), 0);
|
||||
}
|
||||
@ -312,7 +313,7 @@ interface LoadOptions {
|
||||
runOnLoad?: boolean;
|
||||
}
|
||||
|
||||
function doLoadLocal(driveNo: DriveNumber, file: File, options: Partial<LoadOptions> = {}) {
|
||||
function doLoadLocal(drive: DriveNumber, file: File, options: Partial<LoadOptions> = {}) {
|
||||
const parts = file.name.split('.');
|
||||
const ext = parts[parts.length - 1].toLowerCase();
|
||||
const matches = file.name.match(CIDERPRESS_EXTENSION);
|
||||
@ -321,7 +322,7 @@ function doLoadLocal(driveNo: DriveNumber, file: File, options: Partial<LoadOpti
|
||||
[, type, aux] = matches;
|
||||
}
|
||||
if (includes(DISK_FORMATS, ext)) {
|
||||
doLoadLocalDisk(driveNo, file);
|
||||
doLoadLocalDisk(drive, file);
|
||||
} else if (includes(TAPE_TYPES, ext)) {
|
||||
tape.doLoadLocalTape(file);
|
||||
} else if (BIN_TYPES.includes(ext) || type === '06' || options.address) {
|
||||
@ -365,7 +366,7 @@ function doLoadBinary(file: File, options: LoadOptions) {
|
||||
fileReader.readAsArrayBuffer(file);
|
||||
}
|
||||
|
||||
function doLoadLocalDisk(driveNo: DriveNumber, file: File) {
|
||||
function doLoadLocalDisk(drive: DriveNumber, file: File) {
|
||||
loadingStart();
|
||||
const fileReader = new FileReader();
|
||||
fileReader.onload = function () {
|
||||
@ -376,14 +377,14 @@ function doLoadLocalDisk(driveNo: DriveNumber, file: File) {
|
||||
|
||||
// Remove any json file reference
|
||||
const files = hup().split('|');
|
||||
files[driveNo - 1] = '';
|
||||
files[drive - 1] = '';
|
||||
document.location.hash = files.join('|');
|
||||
|
||||
if (includes(DISK_FORMATS, ext)) {
|
||||
if (result.byteLength >= 800 * 1024) {
|
||||
if (
|
||||
includes(BLOCK_FORMATS, ext) &&
|
||||
_massStorage.setBinary(driveNo, name, ext, result)
|
||||
_massStorage.setBinary(drive, name, ext, result)
|
||||
) {
|
||||
initGamepad();
|
||||
} else {
|
||||
@ -392,7 +393,7 @@ function doLoadLocalDisk(driveNo: DriveNumber, file: File) {
|
||||
} else {
|
||||
if (
|
||||
includes(FLOPPY_FORMATS, ext) &&
|
||||
_disk2.setBinary(driveNo, name, ext, result)
|
||||
_disk2.setBinary(drive, name, ext, result)
|
||||
) {
|
||||
initGamepad();
|
||||
} else {
|
||||
@ -405,7 +406,7 @@ function doLoadLocalDisk(driveNo: DriveNumber, file: File) {
|
||||
fileReader.readAsArrayBuffer(file);
|
||||
}
|
||||
|
||||
export function doLoadHTTP(driveNo: DriveNumber, url?: string) {
|
||||
export function doLoadHTTP(drive: DriveNumber, url?: string) {
|
||||
if (!url) {
|
||||
MicroModal.close('http-modal');
|
||||
}
|
||||
@ -453,13 +454,13 @@ export function doLoadHTTP(driveNo: DriveNumber, url?: string) {
|
||||
if (includes(DISK_FORMATS, ext)) {
|
||||
if (data.byteLength >= 800 * 1024) {
|
||||
if (includes(BLOCK_FORMATS, ext)) {
|
||||
_massStorage.setBinary(driveNo, name, ext, data);
|
||||
_massStorage.setBinary(drive, name, ext, data);
|
||||
initGamepad();
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
includes(FLOPPY_FORMATS, ext) &&
|
||||
_disk2.setBinary(driveNo, name, ext, data)
|
||||
_disk2.setBinary(drive, name, ext, data)
|
||||
) {
|
||||
initGamepad();
|
||||
}
|
||||
@ -546,11 +547,11 @@ function updateSoundButton(on: boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
function dumpDisk(driveNo: DriveNumber) {
|
||||
function dumpDisk(drive: DriveNumber) {
|
||||
const wind = window.open('', '_blank')!;
|
||||
wind.document.title = driveLights.label(driveNo);
|
||||
wind.document.title = driveLights.label(drive);
|
||||
wind.document.write('<pre>');
|
||||
wind.document.write(_disk2.getJSON(driveNo, true));
|
||||
wind.document.write(_disk2.getJSON(drive, true));
|
||||
wind.document.write('</pre>');
|
||||
wind.document.close();
|
||||
}
|
||||
@ -585,7 +586,7 @@ export function selectCategory() {
|
||||
option.value = file.filename;
|
||||
option.innerText = name;
|
||||
diskSelect.append(option);
|
||||
if (disk_cur_name[driveNo] === name) {
|
||||
if (disk_cur_name[_currentDrive] === name) {
|
||||
option.selected = true;
|
||||
}
|
||||
}
|
||||
@ -602,7 +603,7 @@ export function clickDisk(event: MouseEvent|KeyboardEvent) {
|
||||
}
|
||||
|
||||
/** Called to load disks from the local catalog. */
|
||||
function loadDisk(driveNo: DriveNumber, disk: JSONDisk) {
|
||||
function loadDisk(drive: DriveNumber, disk: JSONDisk) {
|
||||
let name = disk.name;
|
||||
const category = disk.category!; // all disks in the local catalog have a category
|
||||
|
||||
@ -610,10 +611,10 @@ function loadDisk(driveNo: DriveNumber, disk: JSONDisk) {
|
||||
name += ' - ' + disk.disk;
|
||||
}
|
||||
|
||||
disk_cur_cat[driveNo] = category;
|
||||
disk_cur_name[driveNo] = name;
|
||||
disk_cur_cat[drive] = category;
|
||||
disk_cur_name[drive] = name;
|
||||
|
||||
_disk2.setDisk(driveNo, disk);
|
||||
_disk2.setDisk(drive, disk);
|
||||
initGamepad(disk.gamepad);
|
||||
}
|
||||
|
||||
@ -653,16 +654,16 @@ type LocalDiskIndex = {
|
||||
[name: string]: string;
|
||||
};
|
||||
|
||||
function saveLocalStorage(driveNo: DriveNumber, name: string) {
|
||||
function saveLocalStorage(drive: DriveNumber, name: string) {
|
||||
const diskIndex = JSON.parse(window.localStorage.getItem('diskIndex') || '{}') as LocalDiskIndex;
|
||||
|
||||
const json = _disk2.getJSON(driveNo);
|
||||
const json = _disk2.getJSON(drive);
|
||||
diskIndex[name] = json;
|
||||
|
||||
window.localStorage.setItem('diskIndex', JSON.stringify(diskIndex));
|
||||
|
||||
driveLights.label(driveNo, name);
|
||||
driveLights.dirty(driveNo, false);
|
||||
driveLights.label(drive, name);
|
||||
driveLights.dirty(drive, false);
|
||||
updateLocalStorage();
|
||||
}
|
||||
|
||||
@ -676,12 +677,12 @@ function deleteLocalStorage(name: string) {
|
||||
updateLocalStorage();
|
||||
}
|
||||
|
||||
function loadLocalStorage(driveNo: DriveNumber, name: string) {
|
||||
function loadLocalStorage(drive: DriveNumber, name: string) {
|
||||
const diskIndex = JSON.parse(window.localStorage.getItem('diskIndex') || '{}') as LocalDiskIndex;
|
||||
if (diskIndex[name]) {
|
||||
_disk2.setJSON(driveNo, diskIndex[name]);
|
||||
driveLights.label(driveNo, name);
|
||||
driveLights.dirty(driveNo, false);
|
||||
_disk2.setJSON(drive, diskIndex[name]);
|
||||
driveLights.label(drive, name);
|
||||
driveLights.dirty(drive, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,8 @@ import { Callbacks } from '../cards/disk2';
|
||||
import type { DriveNumber } from '../formats/types';
|
||||
|
||||
export default class DriveLights implements Callbacks {
|
||||
public driveLight(driveNo: DriveNumber, on: boolean) {
|
||||
const disk = document.querySelector<HTMLElement>(`#disk${driveNo}`);
|
||||
public driveLight(drive: DriveNumber, on: boolean) {
|
||||
const disk = document.querySelector<HTMLElement>(`#disk${drive}`);
|
||||
if (disk) {
|
||||
disk.style.backgroundImage =
|
||||
on ? 'url(css/red-on-16.png)' :
|
||||
@ -11,12 +11,12 @@ export default class DriveLights implements Callbacks {
|
||||
}
|
||||
}
|
||||
|
||||
public dirty(_driveNo: DriveNumber, _dirty: boolean) {
|
||||
public dirty(_drive: DriveNumber, _dirty: boolean) {
|
||||
// document.querySelector('#disksave' + drive).disabled = !dirty;
|
||||
}
|
||||
|
||||
public label(driveNo: DriveNumber, label?: string, side?: string) {
|
||||
const labelElement = document.querySelector<HTMLElement>(`#disk-label${driveNo}`);
|
||||
public label(drive: DriveNumber, label?: string, side?: string) {
|
||||
const labelElement = document.querySelector<HTMLElement>(`#disk-label${drive}`);
|
||||
let labelText = '';
|
||||
if (labelElement) {
|
||||
labelText = labelElement.innerText;
|
||||
|
@ -66,8 +66,8 @@ describe('DiskII', () => {
|
||||
|
||||
const state = diskII.getState();
|
||||
// These are just arbitrary changes, not an exhaustive list of fields.
|
||||
(state.drives[1].driver as {skip:number}).skip = 1;
|
||||
state.controllerState.driveNo = 2;
|
||||
state.skip = 1;
|
||||
state.controllerState.drive = 2;
|
||||
state.controllerState.latch = 0x42;
|
||||
state.controllerState.on = true;
|
||||
state.controllerState.q7 = true;
|
||||
@ -97,7 +97,7 @@ describe('DiskII', () => {
|
||||
expect(callbacks.label).toHaveBeenCalledWith(2, 'Disk 2', undefined);
|
||||
|
||||
expect(callbacks.dirty).toHaveBeenCalledTimes(2);
|
||||
expect(callbacks.dirty).toHaveBeenCalledWith(1, false);
|
||||
expect(callbacks.dirty).toHaveBeenCalledWith(1, true);
|
||||
expect(callbacks.dirty).toHaveBeenCalledWith(2, false);
|
||||
});
|
||||
|
||||
@ -760,11 +760,11 @@ class TestDiskReader {
|
||||
nibbles = 0;
|
||||
diskII: DiskII;
|
||||
|
||||
constructor(driveNo: DriveNumber, label: string, image: ArrayBufferLike, apple2IO: Apple2IO, callbacks: Callbacks) {
|
||||
constructor(drive: DriveNumber, label: string, image: ArrayBufferLike, apple2IO: Apple2IO, callbacks: Callbacks) {
|
||||
mocked(apple2IO).cycles.mockImplementation(() => this.cycles);
|
||||
|
||||
this.diskII = new DiskII(apple2IO, callbacks);
|
||||
this.diskII.setBinary(driveNo, label, 'woz', image);
|
||||
this.diskII.setBinary(drive, label, 'woz', image);
|
||||
}
|
||||
|
||||
readNibble(): byte {
|
||||
@ -824,7 +824,7 @@ class TestDiskReader {
|
||||
|
||||
rawTracks() {
|
||||
// NOTE(flan): Hack to access private properties.
|
||||
const disk = (this.diskII as unknown as { disks: WozDisk[] }).disks[1];
|
||||
const disk = (this.diskII as unknown as { curDisk: WozDisk }).curDisk;
|
||||
const result: Uint8Array[] = [];
|
||||
for (let i = 0; i < disk.rawTracks.length; i++) {
|
||||
result[i] = disk.rawTracks[i].slice(0);
|
||||
|
@ -19,7 +19,7 @@ debug('Worker loaded');
|
||||
addEventListener('message', (message: MessageEvent<FormatWorkerMessage>) => {
|
||||
debug('Worker started', message.type);
|
||||
const data = message.data;
|
||||
const { driveNo } = data.payload;
|
||||
const { drive } = data.payload;
|
||||
let disk: FloppyDisk | null = null;
|
||||
|
||||
switch (data.type) {
|
||||
@ -45,7 +45,7 @@ addEventListener('message', (message: MessageEvent<FormatWorkerMessage>) => {
|
||||
const response: DiskProcessedResponse = {
|
||||
type: DISK_PROCESSED,
|
||||
payload: {
|
||||
driveNo,
|
||||
drive,
|
||||
disk
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user