mirror of
https://github.com/whscullin/apple2js.git
synced 2024-01-12 14:14:38 +00:00
a7bf5d025d
Before, all of the disk drivers were in the `disk2.ts` file. With this change, they are now in separate files with a common `types.ts` file for shared types. Now, none of the drives depend on the `disk2.ts` except the WOZ driver that needs access to the sequencer rom. (This may be moved in a future refactoring.)
107 lines
3.0 KiB
TypeScript
107 lines
3.0 KiB
TypeScript
import { DriveNumber, NibbleDisk } from '../../formats/types';
|
|
import { BaseDiskDriver } from './BaseDiskDriver';
|
|
import { ControllerState, Drive, DriverState } from './types';
|
|
|
|
interface NibbleDiskDriverState extends DriverState {
|
|
skip: number;
|
|
nibbleCount: number;
|
|
}
|
|
|
|
export class NibbleDiskDriver extends BaseDiskDriver {
|
|
/**
|
|
* When `1`, the next nibble will be available for read; when `0`,
|
|
* the card is pretending to wait for data to be shifted in by the
|
|
* sequencer.
|
|
*/
|
|
private skip: number = 0;
|
|
/** Number of nibbles reads since the drive was turned on. */
|
|
private nibbleCount: number = 0;
|
|
|
|
constructor(
|
|
driveNo: DriveNumber,
|
|
drive: Drive,
|
|
readonly disk: NibbleDisk,
|
|
controller: ControllerState,
|
|
private readonly onDirty: () => void) {
|
|
super(driveNo, drive, disk, controller);
|
|
}
|
|
|
|
tick(): void {
|
|
// do nothing
|
|
}
|
|
|
|
onQ6Low(): void {
|
|
const drive = this.drive;
|
|
const disk = this.disk;
|
|
if (this.isOn() && (this.skip || this.controller.q7)) {
|
|
const track = disk.tracks[drive.track >> 2];
|
|
if (track && track.length) {
|
|
if (drive.head >= track.length) {
|
|
drive.head = 0;
|
|
}
|
|
|
|
if (this.controller.q7) {
|
|
const writeProtected = disk.readOnly;
|
|
if (!writeProtected) {
|
|
track[drive.head] = this.controller.bus;
|
|
drive.dirty = true;
|
|
this.onDirty();
|
|
}
|
|
} else {
|
|
this.controller.latch = track[drive.head];
|
|
this.nibbleCount++;
|
|
}
|
|
|
|
++drive.head;
|
|
}
|
|
} else {
|
|
this.controller.latch = 0;
|
|
}
|
|
this.skip = (++this.skip % 2);
|
|
}
|
|
|
|
onQ6High(readMode: boolean): void {
|
|
const drive = this.drive;
|
|
if (readMode && !this.controller.q7) {
|
|
const writeProtected = drive.readOnly;
|
|
if (writeProtected) {
|
|
this.controller.latch = 0xff;
|
|
this.debug('Setting readOnly');
|
|
} else {
|
|
this.controller.latch >>= 1;
|
|
this.debug('Clearing readOnly');
|
|
}
|
|
}
|
|
}
|
|
|
|
onDriveOn(): void {
|
|
this.nibbleCount = 0;
|
|
}
|
|
|
|
onDriveOff(): void {
|
|
this.debug('nibbles read', this.nibbleCount);
|
|
}
|
|
|
|
clampTrack(): void {
|
|
// For NibbleDisks, the emulator clamps the track to the available
|
|
// range.
|
|
if (this.drive.track < 0) {
|
|
this.drive.track = 0;
|
|
}
|
|
const lastTrack = 35 * 4 - 1;
|
|
if (this.drive.track > lastTrack) {
|
|
this.drive.track = lastTrack;
|
|
}
|
|
}
|
|
|
|
getState(): NibbleDiskDriverState {
|
|
const { skip, nibbleCount } = this;
|
|
return { skip, nibbleCount };
|
|
}
|
|
|
|
setState(state: NibbleDiskDriverState) {
|
|
this.skip = state.skip;
|
|
this.nibbleCount = state.nibbleCount;
|
|
}
|
|
}
|