apple2js/js/cards/disk2.ts

853 lines
29 KiB
TypeScript
Raw Normal View History

import { base64_encode } from '../base64';
import type { byte, Card, ReadonlyUint8Array } from '../types';
import {
DISK_PROCESSED,
DriveNumber,
DRIVE_NUMBERS,
FloppyDisk,
FloppyFormat,
FormatWorkerMessage,
FormatWorkerResponse,
isNibbleDisk,
isNoFloppyDisk,
isWozDisk,
JSONDisk,
MassStorage,
MassStorageData,
NibbleDisk,
NibbleFormat,
NO_DISK,
PROCESS_BINARY,
PROCESS_JSON,
PROCESS_JSON_DISK,
SupportedSectors,
WozDisk,
} from '../formats/types';
import { createDisk, createDiskFromJsonDisk } from '../formats/create_disk';
import {
jsonDecode,
jsonEncode,
readSector,
_D13O,
_DO,
_PO,
} from '../formats/format_utils';
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
import Apple2IO from '../apple2io';
import { BOOTSTRAP_ROM_13, BOOTSTRAP_ROM_16 } from '../roms/cards/disk2';
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
import { EmptyDriver } from './drivers/EmptyDriver';
import { NibbleDiskDriver } from './drivers/NibbleDiskDriver';
import {
ControllerState,
DiskDriver,
Drive,
DriverState,
Phase,
} from './drivers/types';
import { WozDiskDriver } from './drivers/WozDiskDriver';
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
/** Softswitch locations */
const LOC = {
// Disk II Controller Commands
// See Understanding the Apple IIe, Table 9.1
PHASE0OFF: 0x80, // Q0L: Phase 0 OFF
PHASE0ON: 0x81, // Q0H: Phase 0 ON
PHASE1OFF: 0x82, // Q1L: Phase 1 OFF
PHASE1ON: 0x83, // Q1H: Phase 1 ON
PHASE2OFF: 0x84, // Q2L: Phase 2 OFF
PHASE2ON: 0x85, // Q2H: Phase 2 ON
PHASE3OFF: 0x86, // Q3L: Phase 3 OFF
PHASE3ON: 0x87, // Q3H: Phase 3 ON
DRIVEOFF: 0x88, // Q4L: Drives OFF
DRIVEON: 0x89, // Q4H: Selected drive ON
DRIVE1: 0x8a, // Q5L: Select drive 1
DRIVE2: 0x8b, // Q5H: Select drive 2
DRIVEREAD: 0x8c, // Q6L: Shift while writing; read data
DRIVEWRITE: 0x8d, // Q6H: Load while writing; read write protect
DRIVEREADMODE: 0x8e, // Q7L: Read
DRIVEWRITEMODE: 0x8f, // Q7H: Write
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
} as const;
/** Logic state sequencer ROM */
// See Understanding the Apple IIe, Table 9.3 Logic State Sequencer Commands
// CODE OPERATION BEFORE AFTER
// 0 CLR XXXXXXXX 00000000
// 8 NOP ABCDEFGH ABCDEFGH
// 9 SL0 ABCDEFGH BCDEFGH0
// A SR (write protected) ABCDEFGH 11111111
// (not write protected) ABCDEFGH 0ABCDEFG
// B LOAD XXXXXXXX YYYYYYYY
// D SL1 ABCDEFGH BCDEFGH1
// prettier-ignore
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
const SEQUENCER_ROM_13 = [
// See Understanding the Apple IIe, Figure 9.10 The DOS 3.2 Logic State Sequencer
// Note that the column order here is NOT the same as in Figure 9.10 for Q7 H (Write).
//
// Q7 L (Read) Q7 H (Write)
// Q6 L (Shift) Q6 H (Load) Q6 L (Shift) Q6 H (Load)
// QA L QA H QA L QA H QA L QA H QA L QA H
// 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
0xD8, 0x18, 0x18, 0x08, 0x0A, 0x0A, 0x0A, 0x0A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 0
0xD8, 0x2D, 0x28, 0x28, 0x0A, 0x0A, 0x0A, 0x0A, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, // 1
0xD8, 0x38, 0x38, 0x38, 0x0A, 0x0A, 0x0A, 0x0A, 0x39, 0x39, 0x39, 0x39, 0x3B, 0x3B, 0x3B, 0x3B, // 2
0xD8, 0x48, 0xD8, 0x48, 0x0A, 0x0A, 0x0A, 0x0A, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, // 3
0xD8, 0x58, 0xD8, 0x58, 0x0A, 0x0A, 0x0A, 0x0A, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, // 4
0xD8, 0x68, 0xD8, 0x68, 0x0A, 0x0A, 0x0A, 0x0A, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, // 5
0xD8, 0x78, 0xD8, 0x78, 0x0A, 0x0A, 0x0A, 0x0A, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, // 6
0xD8, 0x88, 0xD8, 0x88, 0x0A, 0x0A, 0x0A, 0x0A, 0x08, 0x08, 0x88, 0x88, 0x08, 0x08, 0x88, 0x88, // 7
0xD8, 0x98, 0xD8, 0x98, 0x0A, 0x0A, 0x0A, 0x0A, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, // 8
0xD8, 0x09, 0xD8, 0xA8, 0x0A, 0x0A, 0x0A, 0x0A, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, // 9
0xCD, 0xBD, 0xD8, 0xB8, 0x0A, 0x0A, 0x0A, 0x0A, 0xB9, 0xB9, 0xB9, 0xB9, 0xBB, 0xBB, 0xBB, 0xBB, // A
0xD9, 0x39, 0xD8, 0xC8, 0x0A, 0x0A, 0x0A, 0x0A, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, // B
0xD9, 0xD9, 0xD8, 0xA0, 0x0A, 0x0A, 0x0A, 0x0A, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, // C
0x1D, 0x0D, 0xE8, 0xE8, 0x0A, 0x0A, 0x0A, 0x0A, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, // D
0xFD, 0xFD, 0xF8, 0xF8, 0x0A, 0x0A, 0x0A, 0x0A, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, // E
0xDD, 0x4D, 0xE0, 0xE0, 0x0A, 0x0A, 0x0A, 0x0A, 0x88, 0x88, 0x08, 0x08, 0x88, 0x88, 0x08, 0x08 // F
] as const;
// prettier-ignore
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
const SEQUENCER_ROM_16 = [
// See Understanding the Apple IIe, Figure 9.11 The DOS 3.3 Logic State Sequencer
// Note that the column order here is NOT the same as in Figure 9.11 for Q7 H (Write).
//
// Q7 L (Read) Q7 H (Write)
// Q6 L (Shift) Q6 H (Load) Q6 L (Shift) Q6 H (Load)
// QA L QA H QA L QA H QA L QA H QA L QA H
// 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
0x18, 0x18, 0x18, 0x18, 0x0A, 0x0A, 0x0A, 0x0A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // 0
0x2D, 0x2D, 0x38, 0x38, 0x0A, 0x0A, 0x0A, 0x0A, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, // 1
0xD8, 0x38, 0x08, 0x28, 0x0A, 0x0A, 0x0A, 0x0A, 0x39, 0x39, 0x39, 0x39, 0x3B, 0x3B, 0x3B, 0x3B, // 2
0xD8, 0x48, 0x48, 0x48, 0x0A, 0x0A, 0x0A, 0x0A, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, // 3
0xD8, 0x58, 0xD8, 0x58, 0x0A, 0x0A, 0x0A, 0x0A, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, // 4
0xD8, 0x68, 0xD8, 0x68, 0x0A, 0x0A, 0x0A, 0x0A, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, // 5
0xD8, 0x78, 0xD8, 0x78, 0x0A, 0x0A, 0x0A, 0x0A, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, // 6
0xD8, 0x88, 0xD8, 0x88, 0x0A, 0x0A, 0x0A, 0x0A, 0x08, 0x08, 0x88, 0x88, 0x08, 0x08, 0x88, 0x88, // 7
0xD8, 0x98, 0xD8, 0x98, 0x0A, 0x0A, 0x0A, 0x0A, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, // 8
0xD8, 0x29, 0xD8, 0xA8, 0x0A, 0x0A, 0x0A, 0x0A, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, // 9
0xCD, 0xBD, 0xD8, 0xB8, 0x0A, 0x0A, 0x0A, 0x0A, 0xB9, 0xB9, 0xB9, 0xB9, 0xBB, 0xBB, 0xBB, 0xBB, // A
0xD9, 0x59, 0xD8, 0xC8, 0x0A, 0x0A, 0x0A, 0x0A, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, // B
0xD9, 0xD9, 0xD8, 0xA0, 0x0A, 0x0A, 0x0A, 0x0A, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, // C
0xD8, 0x08, 0xE8, 0xE8, 0x0A, 0x0A, 0x0A, 0x0A, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, // D
0xFD, 0xFD, 0xF8, 0xF8, 0x0A, 0x0A, 0x0A, 0x0A, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, // E
0xDD, 0x4D, 0xE0, 0xE0, 0x0A, 0x0A, 0x0A, 0x0A, 0x88, 0x88, 0x08, 0x08, 0x88, 0x88, 0x08, 0x08 // F
] as const;
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
/** Contents of the P6 sequencer ROM. */
export const SEQUENCER_ROM: Record<SupportedSectors, ReadonlyArray<byte>> = {
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
13: SEQUENCER_ROM_13,
16: SEQUENCER_ROM_16,
} as const;
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
/** Contents of the P5 ROM at 0xCnXX. */
const BOOTSTRAP_ROM: Record<SupportedSectors, ReadonlyUint8Array> = {
13: BOOTSTRAP_ROM_13,
16: BOOTSTRAP_ROM_16,
} as const;
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
/**
* How far the head moves, in quarter tracks, when in phase X and phase Y is
* activated. For example, if in phase 0 (top row), turning on phase 3 would
* step backwards a quarter track while turning on phase 2 would step forwards
* a half track.
*
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
* Note that this emulation is highly simplified as it only takes into account
* the order that coils are powered on and ignores when they are powered off.
* The actual hardware allows for multiple coils to be powered at the same time
* providing different levels of torque on the head arm. Along with that, the
* RWTS uses a complex delay system to drive the coils faster based on expected
* head momentum.
*
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
* Examining the https://computerhistory.org/blog/apple-ii-dos-source-code/,
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
* one finds the SEEK routine on line 4831 of `appdos31.lst`. It uses `ONTABLE`
* and `OFFTABLE` (each 12 bytes) to know exactly how many microseconds to
* power on/off each coil as the head accelerates. At the end, the final coil
* is left powered on 9.5 milliseconds to ensure the head has settled.
*
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
* https://embeddedmicro.weebly.com/apple-2iie.html shows traces of the boot
* seek (which is slightly different) and a regular seek.
*/
const PHASE_DELTA = [
[0, 1, 2, -1],
[-1, 0, 1, 2],
[-2, -1, 0, 1],
[1, -2, -1, 0],
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
] as const;
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
/** Callbacks triggered by events of the drive or controller. */
export interface Callbacks {
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
/** Called when a drive turns on or off. */
driveLight: (driveNo: DriveNumber, on: boolean) => void;
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
/**
* Called when a disk has been written to. For performance and integrity,
* this is only called when the drive stops spinning or is removed from
* the drive.
*/
dirty: (driveNo: DriveNumber, dirty: boolean) => void;
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
/** Called when a disk is inserted or removed from the drive. */
label: (driveNo: DriveNumber, name?: string, side?: string) => void;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
interface DriveState {
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
disk: FloppyDisk;
driver: DriverState;
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
readOnly: boolean;
2022-05-10 15:04:20 +00:00
track: byte;
head: byte;
phase: Phase;
dirty: boolean;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
/** State of the controller for saving/restoring. */
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
interface State {
drives: DriveState[];
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
controllerState: ControllerState;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
function getDiskState(disk: FloppyDisk): FloppyDisk {
if (isNoFloppyDisk(disk)) {
const { encoding, metadata, readOnly } = disk;
return {
encoding,
metadata: { ...metadata },
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
readOnly,
};
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
if (isNibbleDisk(disk)) {
const { format, encoding, metadata, readOnly, volume, tracks } = disk;
const result: NibbleDisk = {
format,
encoding,
volume,
tracks: [],
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
readOnly,
metadata: { ...metadata },
};
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
for (let idx = 0; idx < tracks.length; idx++) {
result.tracks.push(new Uint8Array(tracks[idx]));
}
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
return result;
}
if (isWozDisk(disk)) {
const { format, encoding, metadata, readOnly, trackMap, rawTracks } =
disk;
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
const result: WozDisk = {
format,
encoding,
readOnly,
trackMap: [],
rawTracks: [],
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
metadata: { ...metadata },
info: disk.info,
};
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
result.trackMap = [...trackMap];
for (let idx = 0; idx < rawTracks.length; idx++) {
result.rawTracks.push(new Uint8Array(rawTracks[idx]));
}
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
return result;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
throw new Error('Unknown drive state');
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
/**
* Emulates the 16-sector and 13-sector versions of the Disk ][ drive and controller.
*/
export default class DiskII implements Card<State>, MassStorage<NibbleFormat> {
private drives: Record<DriveNumber, Drive> = {
1: {
// Drive 1
track: 0,
head: 0,
phase: 0,
readOnly: false,
dirty: false,
},
2: {
// Drive 2
track: 0,
head: 0,
phase: 0,
readOnly: false,
dirty: false,
},
};
private disks: Record<DriveNumber, FloppyDisk> = {
1: {
encoding: NO_DISK,
readOnly: false,
metadata: { name: 'Disk 1' },
},
2: {
encoding: NO_DISK,
readOnly: false,
metadata: { name: 'Disk 2' },
},
};
private driver: Record<DriveNumber, DiskDriver> = {
1: new EmptyDriver(this.drives[1]),
2: new EmptyDriver(this.drives[2]),
};
private state: ControllerState;
/** Drive off timeout id or null. */
private offTimeout: number | null = null;
/** Current drive object. Must only be set by `updateActiveDrive()`. */
private curDrive: Drive;
/** Current driver object. Must only be set by `updateAcivetDrive()`. */
private curDriver: DiskDriver;
private worker: Worker;
/** Builds a new Disk ][ card. */
constructor(
private io: Apple2IO,
private callbacks: Callbacks,
private sectors: SupportedSectors = 16
) {
this.debug('Disk ][');
this.state = {
sectors,
bus: 0,
latch: 0,
driveNo: 1,
on: false,
q6: false,
q7: false,
clock: 0,
// From the example in UtA2e, p. 9-29, col. 1, para. 1., this is
// essentially the start of the sequencer loop and produces
// correctly synced nibbles immediately. Starting at state 0
// would introduce a spurrious 1 in the latch at the beginning,
// which requires reading several more sync bytes to sync up.
state: 2,
};
this.updateActiveDrive();
this.initWorker();
}
/** Updates the active drive based on the controller state. */
private updateActiveDrive() {
this.curDrive = this.drives[this.state.driveNo];
this.curDriver = this.driver[this.state.driveNo];
}
private debug(..._args: unknown[]) {
// debug(..._args);
}
public head(): number {
return this.curDrive.head;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
/**
* Sets whether the head positioning stepper motor coil for the given
* phase is on or off. Normally, the motor must be stepped two phases
* per track. Half tracks can be written by stepping only once; quarter
* tracks by activating two neighboring coils at once.
*/
private setPhase(phase: Phase, on: boolean) {
// According to Sather, UtA2e, p. 9-12, Drive On/Off and Drive
// Select:
// Turning a drive on ($C089,X) [...]:
// 1. [...]
// 5. [...] enables head positioning [...]
//
// Therefore do nothing if no drive is on.
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
if (!this.state.on) {
this.debug(`ignoring phase ${phase}${on ? ' on' : ' off'}`);
return;
}
this.debug(`phase ${phase}${on ? ' on' : ' off'}`);
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
if (on) {
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
this.curDrive.track += PHASE_DELTA[this.curDrive.phase][phase] * 2;
this.curDrive.phase = phase;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
this.curDriver.clampTrack();
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
// debug(
// 'Drive', _drive, 'track', toHex(_cur.track >> 2) + '.' + (_cur.track & 0x3),
// '(' + toHex(_cur.track) + ')',
// '[' + phase + ':' + (on ? 'on' : 'off') + ']');
}
private access(off: byte, val?: byte) {
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
const state = this.state;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
let result = 0;
const readMode = val === undefined;
switch (off & 0x8f) {
case LOC.PHASE0OFF: // 0x00
this.setPhase(0, false);
break;
case LOC.PHASE0ON: // 0x01
this.setPhase(0, true);
break;
case LOC.PHASE1OFF: // 0x02
this.setPhase(1, false);
break;
case LOC.PHASE1ON: // 0x03
this.setPhase(1, true);
break;
case LOC.PHASE2OFF: // 0x04
this.setPhase(2, false);
break;
case LOC.PHASE2ON: // 0x05
this.setPhase(2, true);
break;
case LOC.PHASE3OFF: // 0x06
this.setPhase(3, false);
break;
case LOC.PHASE3ON: // 0x07
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
this.setPhase(3, true);
break;
case LOC.DRIVEOFF: // 0x08
if (!this.offTimeout) {
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
if (state.on) {
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
// TODO(flan): This is fragile because it relies on
// wall-clock time instead of emulator time.
this.offTimeout = window.setTimeout(() => {
this.debug('Drive Off');
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
state.on = false;
this.callbacks.driveLight(state.driveNo, false);
this.curDriver.onDriveOff();
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}, 1000);
}
}
break;
case LOC.DRIVEON: // 0x09
if (this.offTimeout) {
// TODO(flan): Fragile—see above
window.clearTimeout(this.offTimeout);
this.offTimeout = null;
}
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
if (!state.on) {
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
this.debug('Drive On');
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
state.on = true;
this.callbacks.driveLight(state.driveNo, true);
this.curDriver.onDriveOn();
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
break;
case LOC.DRIVE1: // 0x0a
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
this.debug('Disk 1');
state.driveNo = 1;
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
this.updateActiveDrive();
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
if (state.on) {
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
this.callbacks.driveLight(2, false);
this.callbacks.driveLight(1, true);
}
break;
case LOC.DRIVE2: // 0x0b
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
this.debug('Disk 2');
state.driveNo = 2;
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
this.updateActiveDrive();
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
if (state.on) {
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
this.callbacks.driveLight(1, false);
this.callbacks.driveLight(2, true);
}
break;
case LOC.DRIVEREAD: // 0x0c (Q6L) Shift
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
state.q6 = false;
this.curDriver.onQ6Low();
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
break;
case LOC.DRIVEWRITE: // 0x0d (Q6H) LOAD
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
state.q6 = true;
this.curDriver.onQ6High(readMode);
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
break;
case LOC.DRIVEREADMODE: // 0x0e (Q7L)
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
this.debug('Read Mode');
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
state.q7 = false;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
break;
case LOC.DRIVEWRITEMODE: // 0x0f (Q7H)
this.debug('Write Mode');
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
state.q7 = true;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
break;
default:
break;
}
this.tick();
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
if (readMode) {
// According to UtAIIe, p. 9-13 to 9-14, any even address can be
// used to read the data register onto the CPU bus, although some
// also cause conflicts with the disk controller commands.
if ((off & 0x01) === 0) {
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
result = state.latch;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
} else {
result = 0;
}
} else {
// It's not explicitly stated, but writes to any address set the
// data register.
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
state.bus = val;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
return result;
}
private updateDirty(driveNo: DriveNumber, dirty: boolean) {
this.drives[driveNo].dirty = dirty;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
if (this.callbacks.dirty) {
this.callbacks.dirty(driveNo, dirty);
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
}
ioSwitch(off: byte, val?: byte) {
return this.access(off, val);
}
read(_page: byte, off: byte) {
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
return BOOTSTRAP_ROM[this.sectors][off];
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
write() {
// not writable
}
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
reset() {
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
const state = this.state;
if (state.on) {
this.callbacks.driveLight(state.driveNo, false);
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
state.q7 = false;
state.on = false;
state.driveNo = 1;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
this.updateActiveDrive();
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
tick() {
this.curDriver.tick();
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
private getDriveState(driveNo: DriveNumber): DriveState {
const curDrive = this.drives[driveNo];
const curDisk = this.disks[driveNo];
const curDriver = this.driver[driveNo];
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
const { readOnly, track, head, phase, dirty } = curDrive;
return {
disk: getDiskState(curDisk),
driver: curDriver.getState(),
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
readOnly,
track,
head,
phase,
dirty,
};
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
}
getState(): State {
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
const result = {
drives: [] as DriveState[],
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
controllerState: { ...this.state },
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
};
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
result.drives[1] = this.getDriveState(1);
result.drives[2] = this.getDriveState(2);
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
return result;
}
private setDriveState(driveNo: DriveNumber, state: DriveState) {
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
const { track, head, phase, readOnly, dirty } = state;
this.drives[driveNo] = {
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
track,
head,
phase,
readOnly,
dirty,
};
const disk = getDiskState(state.disk);
this.setDiskInternal(driveNo, disk);
this.driver[driveNo].setState(state.driver);
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
}
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
setState(state: State) {
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
this.state = { ...state.controllerState };
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
for (const d of DRIVE_NUMBERS) {
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
this.setDriveState(d, state.drives[d]);
const { name, side } = state.drives[d].disk.metadata;
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
const { dirty } = state.drives[d];
this.callbacks.label(d, name, side);
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
this.callbacks.driveLight(d, this.state.on);
this.callbacks.dirty(d, dirty);
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
this.updateActiveDrive();
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
getMetadata(driveNo: DriveNumber) {
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
const { track, head, phase, readOnly, dirty } = this.drives[driveNo];
return {
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
track,
head,
phase,
readOnly,
dirty,
};
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
/** Reads the given track and physical sector. */
rwts(driveNo: DriveNumber, track: byte, sector: byte) {
const curDisk = this.disks[driveNo];
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
if (!isNibbleDisk(curDisk)) {
throw new Error("Can't read WOZ disks");
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
return readSector(curDisk, track, sector);
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
/** Sets the data for `drive` from `disk`, which is expected to be JSON. */
// TODO(flan): This implementation is not very safe.
setDisk(driveNo: DriveNumber, jsonDisk: JSONDisk) {
if (this.worker) {
const message: FormatWorkerMessage = {
type: PROCESS_JSON_DISK,
payload: {
driveNo: driveNo,
jsonDisk,
},
};
this.worker.postMessage(message);
return true;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
} else {
const disk = createDiskFromJsonDisk(jsonDisk);
if (disk) {
this.insertDisk(driveNo, disk);
return true;
}
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
return false;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
getJSON(driveNo: DriveNumber, pretty: boolean = false) {
const curDisk = this.disks[driveNo];
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
if (!isNibbleDisk(curDisk)) {
throw new Error("Can't save WOZ disks to JSON");
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
return jsonEncode(curDisk, pretty);
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
setJSON(driveNo: DriveNumber, json: string) {
if (this.worker) {
const message: FormatWorkerMessage = {
type: PROCESS_JSON,
payload: {
driveNo: driveNo,
json,
},
};
this.worker.postMessage(message);
} else {
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
const disk = jsonDecode(json);
this.insertDisk(driveNo, disk);
}
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
return true;
}
setBinary(
driveNo: DriveNumber,
name: string,
fmt: FloppyFormat,
rawData: ArrayBuffer
) {
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
const readOnly = false;
const volume = 254;
const options = {
name,
rawData,
readOnly,
volume,
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
};
if (this.worker) {
const message: FormatWorkerMessage = {
type: PROCESS_BINARY,
payload: {
driveNo: driveNo,
fmt,
options,
},
};
this.worker.postMessage(message);
return true;
} else {
const disk = createDisk(fmt, options);
if (disk) {
this.insertDisk(driveNo, disk);
return true;
}
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
return false;
}
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
initWorker() {
if (!window.Worker) {
return;
}
try {
this.worker = new Worker('dist/format_worker.bundle.js');
this.worker.addEventListener(
'message',
(message: MessageEvent<FormatWorkerResponse>) => {
const { data } = message;
switch (data.type) {
case DISK_PROCESSED:
{
const { driveNo: drive, disk } = data.payload;
if (disk) {
this.insertDisk(drive, disk);
}
}
break;
}
}
);
} catch (e: unknown) {
console.error(e);
}
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
private setDiskInternal(driveNo: DriveNumber, disk: FloppyDisk) {
this.disks[driveNo] = disk;
if (isNoFloppyDisk(disk)) {
this.driver[driveNo] = new EmptyDriver(this.drives[driveNo]);
} else if (isNibbleDisk(disk)) {
this.driver[driveNo] = new NibbleDiskDriver(
driveNo,
this.drives[driveNo],
disk,
this.state,
() => this.updateDirty(driveNo, true)
);
} else if (isWozDisk(disk)) {
this.driver[driveNo] = new WozDiskDriver(
driveNo,
this.drives[driveNo],
disk,
this.state,
() => this.updateDirty(driveNo, true),
this.io
);
} else {
throw new Error(`Unknown disk format ${disk.encoding}`);
}
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
this.updateActiveDrive();
}
private insertDisk(driveNo: DriveNumber, disk: FloppyDisk) {
this.setDiskInternal(driveNo, disk);
this.drives[driveNo].head = 0;
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
const { name, side } = disk.metadata;
this.updateDirty(driveNo, this.drives[driveNo].dirty);
this.callbacks.label(driveNo, name, side);
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
}
/**
* Returns the binary image of the non-WOZ disk in the given drive.
* For WOZ disks, this method returns `null`. If the `ext` parameter
* is supplied, the returned data will match that format or an error
* will be thrown. If the `ext` parameter is not supplied, the
* original image format for the disk in the drive will be used. If
* the current data on the disk is no longer readable in that format,
* an error will be thrown. Using `ext == 'nib'` will always return
* an image.
*/
getBinary(
driveNo: DriveNumber,
ext?: Exclude<NibbleFormat, 'woz'>
): MassStorageData | null {
const curDisk = this.disks[driveNo];
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
if (!isNibbleDisk(curDisk)) {
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
return null;
}
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
const { format, readOnly, tracks, volume } = curDisk;
const { name } = curDisk.metadata;
const len =
format === 'nib'
? tracks.reduce((acc, track) => acc + track.length, 0)
: this.sectors * tracks.length * 256;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
const data = new Uint8Array(len);
ext = ext ?? format;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
let idx = 0;
2022-07-23 19:00:38 +00:00
for (let t = 0; t < tracks.length; t++) {
if (ext === 'nib') {
data.set(tracks[t], idx);
idx += tracks[t].length;
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
} else {
let maxSector: SupportedSectors;
let sectorMap: typeof _PO | typeof _DO | typeof _D13O;
if (ext === 'd13') {
maxSector = 13;
sectorMap = _D13O;
} else {
maxSector = 16;
sectorMap = format === 'po' ? _PO : _DO;
}
for (let s = 0; s < maxSector; s++) {
const _s = sectorMap[s];
const sector = readSector(
{ ...curDisk, format: ext },
t,
_s
);
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
data.set(sector, idx);
idx += sector.length;
}
}
}
return {
ext,
Floppy controller refactorings 1 (#155) * Add `DiskMetada` to the `Disk` interface Before, metadata about the image, such as name, side, etc. was mixed in with actual disk image information. This change breaks that information into a separate structure called `DiskMetadata`. Currently, the only two fields are `name` and `side`, but the idea is that more fields could be added as necessary, like a description, a scan of the disk or label, etc. In a follow-on change, the default write-protection status will come from the metadata as well. The current implementation copies the metadata when saving/restoring state, loading disk images, etc. In the future, the metadata should passed around until the format is required to change (like saving one disk image format as another). Likewise, in the future, in may be desirable to be able to override the disk image metadata with user-supplied metadata. This could be use, for example, to temporarily add or remove write-protection from a disk image. All existing tests pass and the emulator builds with no errors. * Rename `writeMode` to `q7` Before, nibble disk emulation used the `writeMode` field to keep track of whether the drive should be read from or written to, but the WOZ emulation used `q7` to keep track of the same state. This change renames `writeMode` to `q7` because it more accurately reflects the state of the Disk II controller as specified in the manuals, DOS source, and, especially, _Understanding the Apple //e_ by Jim Sather. * Remove the coil state Before, `q` captured the state of the coils. But it was never read. This change just deletes it. * Use the bootstrap and sequencer ROMs with indirection Before, the contents of the bootstrap ROM and sequencer ROM were set directly on fields of the controller. These were not saved or restored with the state in `getState` and `setState`. (It would have been very space inefficient if they had). Now, these ROMs are used from constants indexed by the number of sectors the card supports. This, in turn, means that if the number of sectors is saved with the state, it can be easily restored. * Split out the Disk II controller state This change factors the emulated hardware state into a separate structure in the Disk II controller. The idea is that this hardware state will be able to be shared with the WOZ and nibble disk code instead of sharing _all_ of the controller state (like callbacks and so forth). * Factor out disk insertion Before, several places in the code essentially inserted a new disk image into the drive, which similar—but not always exactly the same—code. Now there is an `insertDisk` method that is responsible for inserting a new `FloppyDisk`. All tests pass, everything compiles, manually tested nibble disks and WOZ disks.
2022-09-01 01:55:01 +00:00
metadata: { name },
2022-07-23 19:00:38 +00:00
data: data.buffer,
readOnly,
volume,
};
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
2022-07-23 19:00:38 +00:00
// TODO(flan): Does not work with WOZ or D13 disks
getBase64(driveNo: DriveNumber) {
const curDisk = this.disks[driveNo];
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
if (!isNibbleDisk(curDisk)) {
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
return null;
}
const data: string[][] | string[] = [];
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
for (let t = 0; t < curDisk.tracks.length; t++) {
if (isNibbleDisk(curDisk)) {
data[t] = base64_encode(curDisk.tracks[t]);
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
} else {
const track: string[] = [];
for (let s = 0; s < 0x10; s++) {
Split disk data out into its own record (#158) * Harmonize drive and disk type hierarchies Before, the `XXXDrive` and `XXXDisk` type hierarchies were similar, but not exactly the same. For example, `encoding` and `format` were missing on some `XXXDisk` types where they existed on the `XXXDrive` type. This change attempts to bring the hierarchies closer together. However, the biggest visible consequence is the introduction of the `FLOPPY_FORMATS` array and its associated `FloppyFormat` type. This replaces `NIBBLE_FORMATS` in most places. A couple of new type guards for disk formats and disks have been added as well. All tests pass, everything compiles with no errors, and both WOZ and nibble format disks load in the emulator. * Move disk data to a `disk` field in the drive Before, disk data was mixed in with state about the drive itself (like track, motor phase, etc.). This made it hard to know exactly what data was necessary for different image formats. Now, the disk data is in a `disk` field whose type depends on the drive type. This makes responisbility a bit easier. One oddity, though, is that the `Drive` has metadata _and_ the `Disk` has metadata. When a disk is in the drive, these should be `===`, but when there is no disk in the drive, obviously only the drive metadata is set. All tests pass, everything compiles, and both WOZ and nibble disks work in the emulator (both preact and classic). * Squash the `Drive` type hierarchy Before, the type of the drive depended on the type of the disk in the drive. Thus, `NibbleDrive` contained a `NibbleDisk` and a `WozDrive` contained a `WozDisk`. With the extraction of the disk data to a single field, this type hierarchy makes no sense. Instead, it suffices to check the type of the disk. This change removes the `NibbleDrive` and `WozDrive` types and type guards, checking the disk type where necessary. This change also introduces the `NoFloppyDisk` type to represent the lack of a disk. This allows the drive to have metadata, for one. All tests pass, everything compiles, and both WOZ and nibble disks work locally. * Use more destructuring assignment Now, more places use constructs like: ```TypeScript const { metadata, readOnly, track, head, phase, dirty } = drive; return { disk: getDiskState(drive.disk), metadata: {...metadata}, readOnly, track, head, phase, dirty, }; ``` * Remove the `Disk` object from the `Drive` object This change splits out the disk objects into a record parallel to the drive objects. The idea is that the `Drive` structure becomes a representation of the state of the drive that is separate from the disk image actually in the drive. This helps in an upcoming refactoring. This also changes the default empty disks to be writable. While odd, the write protect switch should be in the "off" position since there is no disk pressing on it. Finally, `insertDisk` now resets the head position to 0 since there is no way of preserving the head position across disks. (Even in the real world, the motor-off delay plus spindle spin-down would make it impossible to know the disk head position with any accuracy.)
2022-09-17 13:41:35 +00:00
track[s] = base64_encode(readSector(curDisk, t, s));
Convert `cards/disk2.js` to Typescript (#54) * Convert `cards/disk2.js` to Typescript This is mostly a straightforward conversion of `cards/disk2.js` to Typescript, with the following exceptions: * `setState()` did not restore the drive light state correctly because the callback was called with the old `on` value. * `setPhase()` did not work for WOZ images. * `getBinary()` did not work for `nib` files. * `getBase64()` did not work for `nib` files and maybe didn't work right at all. Even with these fixes, local storage still doesn't work correctly. I have also added several TODOs where methods don't support WOZ disks. * Convert most uses of `memory` to `Uint8Array` There are many places in the existing code where we use `Uint8Array` directly. This change merely makes the `memory` type equivalent to `Uint8Array`. This change also changes most ROM data to be read-only in Typescript to ensure that it is not modified by mistake. This can't be done just by applying `as const` to the declaration because `Uint8Array`s are can not be expressed as literals. Instead, we create a new type, `ReadonlyUint8Array` that drops the mutation methods and makes indexed access read-only. See https://www.growingwiththeweb.com/2020/10/typescript-readonly-typed-arrays.html for details. * Tighten types and document `disk2.ts` While trying to understand the Disk ][ emulation, I tighted the types and documented the parts that I could, including references to other sources, like _Understanding the Apple //e_ by Jim Sather. The one functional change is the addition of the P6 ROM of DOS 3.2 and earlier. This is automatically selected if the card is initialized for 13 sector disks.
2021-02-08 04:50:50 +00:00
}
data[t] = track;
}
}
return data;
}
}