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).
This commit is contained in:
parent
3a28fcb9fb
commit
62b48d3893
|
@ -2,7 +2,6 @@ import { base64_encode } from '../base64';
|
|||
import type {
|
||||
byte,
|
||||
Card,
|
||||
memory,
|
||||
nibble,
|
||||
ReadonlyUint8Array,
|
||||
} from '../types';
|
||||
|
@ -26,6 +25,10 @@ import {
|
|||
SupportedSectors,
|
||||
FloppyDisk,
|
||||
FloppyFormat,
|
||||
WozDisk,
|
||||
NibbleDisk,
|
||||
isNibbleDisk,
|
||||
isWozDisk,
|
||||
} from '../formats/types';
|
||||
|
||||
import {
|
||||
|
@ -38,7 +41,6 @@ import { jsonDecode, jsonEncode, readSector } from '../formats/format_utils';
|
|||
|
||||
import { BOOTSTRAP_ROM_16, BOOTSTRAP_ROM_13 } from '../roms/cards/disk2';
|
||||
import Apple2IO from '../apple2io';
|
||||
import { InfoChunk } from 'js/formats/woz';
|
||||
|
||||
/** Softswitch locations */
|
||||
const LOC = {
|
||||
|
@ -215,8 +217,8 @@ export interface Callbacks {
|
|||
|
||||
/** Common information for Nibble and WOZ disks. */
|
||||
interface BaseDrive {
|
||||
/** Current disk format. */
|
||||
format: FloppyFormat;
|
||||
/** The disk in the drive. */
|
||||
disk: FloppyDisk;
|
||||
/** Metadata about the disk image */
|
||||
metadata: DiskMetadata;
|
||||
/** Whether the drive write protect is on. */
|
||||
|
@ -233,71 +235,34 @@ interface BaseDrive {
|
|||
|
||||
/** WOZ format track data from https://applesaucefdc.com/woz/reference2/. */
|
||||
interface WozDrive extends BaseDrive {
|
||||
/** Woz encoding */
|
||||
encoding: typeof ENCODING_BITSTREAM;
|
||||
format: 'woz';
|
||||
/** Maps quarter tracks to data in rawTracks; `0xFF` = random garbage. */
|
||||
trackMap: byte[];
|
||||
/** Unique track bitstreams. The index is arbitrary; it is NOT the track number. */
|
||||
rawTracks: Uint8Array[];
|
||||
/** Optional `INFO` chunk from WOZ image. */
|
||||
info?: InfoChunk;
|
||||
disk: WozDisk;
|
||||
}
|
||||
|
||||
/** Nibble format track data. */
|
||||
interface NibbleDrive extends BaseDrive {
|
||||
/** Nibble encoding */
|
||||
encoding: typeof ENCODING_NIBBLE;
|
||||
/** Format */
|
||||
format: Exclude<NibbleFormat, 'woz'>;
|
||||
/** Current disk volume number. */
|
||||
volume: byte;
|
||||
/** Nibble data. The index is the track number. */
|
||||
tracks: memory[];
|
||||
disk: NibbleDisk;
|
||||
}
|
||||
|
||||
type Drive = WozDrive | NibbleDrive;
|
||||
|
||||
function isNibbleDrive(drive: Drive): drive is NibbleDrive {
|
||||
return drive.encoding === ENCODING_NIBBLE;
|
||||
return drive.disk.encoding === ENCODING_NIBBLE;
|
||||
}
|
||||
|
||||
function isWozDrive(drive: Drive): drive is WozDrive {
|
||||
return drive.encoding === ENCODING_BITSTREAM;
|
||||
return drive.disk.encoding === ENCODING_BITSTREAM;
|
||||
}
|
||||
|
||||
interface NibbleDriveState {
|
||||
format: Exclude<NibbleFormat, 'woz'>;
|
||||
encoding: typeof ENCODING_NIBBLE;
|
||||
volume: byte;
|
||||
tracks: memory[];
|
||||
interface DriveState {
|
||||
disk: FloppyDisk;
|
||||
metadata: DiskMetadata;
|
||||
readOnly: boolean;
|
||||
track: byte;
|
||||
head: byte;
|
||||
phase: Phase;
|
||||
readOnly: boolean;
|
||||
dirty: boolean;
|
||||
trackMap: number[];
|
||||
rawTracks: Uint8Array[];
|
||||
metadata: DiskMetadata;
|
||||
}
|
||||
|
||||
interface WozDriveState {
|
||||
format: 'woz';
|
||||
encoding: typeof ENCODING_BITSTREAM;
|
||||
tracks: memory[];
|
||||
track: byte;
|
||||
head: byte;
|
||||
phase: Phase;
|
||||
readOnly: boolean;
|
||||
dirty: boolean;
|
||||
trackMap: number[];
|
||||
rawTracks: Uint8Array[];
|
||||
metadata: DiskMetadata;
|
||||
info?: InfoChunk;
|
||||
}
|
||||
|
||||
type DriveState = NibbleDriveState | WozDriveState;
|
||||
|
||||
/** State of the controller for saving/restoring. */
|
||||
// TODO(flan): It's unclear whether reusing ControllerState here is a good idea.
|
||||
interface State {
|
||||
|
@ -307,47 +272,49 @@ interface State {
|
|||
}
|
||||
|
||||
function getDriveState(drive: Drive): DriveState {
|
||||
if (isNibbleDrive(drive)) {
|
||||
const result: NibbleDriveState = {
|
||||
format: drive.format,
|
||||
encoding: drive.encoding,
|
||||
volume: drive.volume,
|
||||
return {
|
||||
disk: getDiskState(drive.disk),
|
||||
metadata: {...drive.metadata},
|
||||
readOnly: drive.readOnly,
|
||||
track: drive.track,
|
||||
head: drive.head,
|
||||
phase: drive.phase,
|
||||
dirty: drive.dirty,
|
||||
};
|
||||
}
|
||||
|
||||
function getDiskState(disk: NibbleDisk): NibbleDisk;
|
||||
function getDiskState(disk: WozDisk): WozDisk;
|
||||
function getDiskState(disk: FloppyDisk): FloppyDisk;
|
||||
function getDiskState(disk: FloppyDisk): FloppyDisk {
|
||||
if (isNibbleDisk(disk)) {
|
||||
const result: NibbleDisk = {
|
||||
format: disk.format,
|
||||
encoding: disk.encoding,
|
||||
volume: disk.volume,
|
||||
tracks: [],
|
||||
track: drive.track,
|
||||
head: drive.head,
|
||||
phase: drive.phase,
|
||||
readOnly: drive.readOnly,
|
||||
dirty: drive.dirty,
|
||||
trackMap: [],
|
||||
rawTracks: [],
|
||||
metadata: { ...drive.metadata },
|
||||
readOnly: disk.readOnly,
|
||||
metadata: { ...disk.metadata },
|
||||
};
|
||||
for (let idx = 0; idx < drive.tracks.length; idx++) {
|
||||
result.tracks.push(new Uint8Array(drive.tracks[idx]));
|
||||
for (let idx = 0; idx < disk.tracks.length; idx++) {
|
||||
result.tracks.push(new Uint8Array(disk.tracks[idx]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (isWozDrive(drive)) {
|
||||
const result: WozDriveState = {
|
||||
format: drive.format,
|
||||
encoding: drive.encoding,
|
||||
tracks: [],
|
||||
track: drive.track,
|
||||
head: drive.head,
|
||||
phase: drive.phase,
|
||||
readOnly: drive.readOnly,
|
||||
dirty: drive.dirty,
|
||||
if (isWozDisk(disk)) {
|
||||
const result: WozDisk = {
|
||||
format: disk.format,
|
||||
encoding: disk.encoding,
|
||||
readOnly: disk.readOnly,
|
||||
trackMap: [],
|
||||
rawTracks: [],
|
||||
metadata: { ...drive.metadata },
|
||||
metadata: { ...disk.metadata },
|
||||
info: disk.info,
|
||||
};
|
||||
result.trackMap = [...drive.trackMap];
|
||||
for (let idx = 0; idx < drive.rawTracks.length; idx++) {
|
||||
result.rawTracks.push(new Uint8Array(drive.rawTracks[idx]));
|
||||
}
|
||||
if (drive.info) {
|
||||
result.info = drive.info;
|
||||
result.trackMap = [...disk.trackMap];
|
||||
for (let idx = 0; idx < disk.rawTracks.length; idx++) {
|
||||
result.rawTracks.push(new Uint8Array(disk.rawTracks[idx]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -356,13 +323,9 @@ function getDriveState(drive: Drive): DriveState {
|
|||
}
|
||||
|
||||
function setDriveState(state: DriveState) {
|
||||
let result: Drive;
|
||||
if (state.encoding === ENCODING_NIBBLE) {
|
||||
result = {
|
||||
format: state.format,
|
||||
encoding: ENCODING_NIBBLE,
|
||||
volume: state.volume || 254,
|
||||
tracks: [],
|
||||
if (isNibbleDisk(state.disk)) {
|
||||
const result: NibbleDrive = {
|
||||
disk: getDiskState(state.disk),
|
||||
track: state.track,
|
||||
head: state.head,
|
||||
phase: state.phase,
|
||||
|
@ -370,27 +333,20 @@ function setDriveState(state: DriveState) {
|
|||
dirty: state.dirty,
|
||||
metadata: { ...state.metadata },
|
||||
};
|
||||
for (let idx = 0; idx < state.tracks.length; idx++) {
|
||||
result.tracks.push(new Uint8Array(state.tracks[idx]));
|
||||
}
|
||||
} else {
|
||||
result = {
|
||||
format: state.format,
|
||||
encoding: ENCODING_BITSTREAM,
|
||||
return result;
|
||||
} else if (isWozDisk(state.disk)) {
|
||||
const result: WozDrive = {
|
||||
disk: getDiskState(state.disk),
|
||||
track: state.track,
|
||||
head: state.head,
|
||||
phase: state.phase,
|
||||
readOnly: state.readOnly,
|
||||
dirty: state.dirty,
|
||||
trackMap: [...state.trackMap],
|
||||
rawTracks: [],
|
||||
metadata: { ...state.metadata },
|
||||
};
|
||||
for (let idx = 0; idx < state.rawTracks.length; idx++) {
|
||||
result.rawTracks.push(new Uint8Array(state.rawTracks[idx]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
throw new Error('Unable to restore drive state');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -400,10 +356,14 @@ export default class DiskII implements Card<State>, MassStorage<NibbleFormat> {
|
|||
|
||||
private drives: Record<DriveNumber, Drive> = {
|
||||
1: { // Drive 1
|
||||
format: 'dsk',
|
||||
encoding: ENCODING_NIBBLE,
|
||||
volume: 254,
|
||||
tracks: [],
|
||||
disk: {
|
||||
format: 'dsk',
|
||||
encoding: ENCODING_NIBBLE,
|
||||
volume: 254,
|
||||
tracks: [],
|
||||
readOnly: true,
|
||||
metadata: { name: 'Disk 1' },
|
||||
},
|
||||
track: 0,
|
||||
head: 0,
|
||||
phase: 0,
|
||||
|
@ -412,10 +372,14 @@ export default class DiskII implements Card<State>, MassStorage<NibbleFormat> {
|
|||
metadata: { name: 'Disk 1' },
|
||||
},
|
||||
2: { // Drive 2
|
||||
format: 'dsk',
|
||||
encoding: ENCODING_NIBBLE,
|
||||
volume: 254,
|
||||
tracks: [],
|
||||
disk: {
|
||||
format: 'dsk',
|
||||
encoding: ENCODING_NIBBLE,
|
||||
volume: 254,
|
||||
tracks: [],
|
||||
readOnly: true,
|
||||
metadata: { name: 'Disk 2' },
|
||||
},
|
||||
track: 0,
|
||||
head: 0,
|
||||
phase: 0,
|
||||
|
@ -533,7 +497,7 @@ export default class DiskII implements Card<State>, MassStorage<NibbleFormat> {
|
|||
return;
|
||||
}
|
||||
const track =
|
||||
this.cur.rawTracks[this.cur.trackMap[this.cur.track]] || [0];
|
||||
this.cur.disk.rawTracks[this.cur.disk.trackMap[this.cur.track]] || [0];
|
||||
|
||||
const state = this.state;
|
||||
|
||||
|
@ -615,7 +579,7 @@ export default class DiskII implements Card<State>, MassStorage<NibbleFormat> {
|
|||
}
|
||||
const state = this.state;
|
||||
if (state.on && (this.skip || state.q7)) {
|
||||
const track = this.cur.tracks[this.cur.track >> 2];
|
||||
const track = this.cur.disk.tracks[this.cur.track >> 2];
|
||||
if (track && track.length) {
|
||||
if (this.cur.head >= track.length) {
|
||||
this.cur.head = 0;
|
||||
|
@ -670,8 +634,8 @@ export default class DiskII implements Card<State>, MassStorage<NibbleFormat> {
|
|||
// at least a half track, usually a full track. Some 3rd party
|
||||
// drives can seek to track 39.
|
||||
const maxTrack = isNibbleDrive(this.cur)
|
||||
? this.cur.tracks.length * 4 - 1
|
||||
: this.cur.trackMap.length - 1;
|
||||
? this.cur.disk.tracks.length * 4 - 1
|
||||
: this.cur.disk.trackMap.length - 1;
|
||||
if (this.cur.track > maxTrack) {
|
||||
this.cur.track = maxTrack;
|
||||
}
|
||||
|
@ -891,7 +855,7 @@ export default class DiskII implements Card<State>, MassStorage<NibbleFormat> {
|
|||
getMetadata(driveNo: DriveNumber) {
|
||||
const drive = this.drives[driveNo];
|
||||
return {
|
||||
format: drive.format,
|
||||
format: drive.disk.format,
|
||||
track: drive.track,
|
||||
head: drive.head,
|
||||
phase: drive.phase,
|
||||
|
@ -906,7 +870,7 @@ export default class DiskII implements Card<State>, MassStorage<NibbleFormat> {
|
|||
if (!isNibbleDrive(cur)) {
|
||||
throw new Error('Can\'t read WOZ disks');
|
||||
}
|
||||
return readSector(cur, track, sector);
|
||||
return readSector(cur.disk, track, sector);
|
||||
}
|
||||
|
||||
/** Sets the data for `drive` from `disk`, which is expected to be JSON. */
|
||||
|
@ -937,7 +901,7 @@ export default class DiskII implements Card<State>, MassStorage<NibbleFormat> {
|
|||
if (!isNibbleDrive(cur)) {
|
||||
throw new Error('Can\'t save WOZ disks to JSON');
|
||||
}
|
||||
return jsonEncode(cur, pretty);
|
||||
return jsonEncode(cur.disk, pretty);
|
||||
}
|
||||
|
||||
setJSON(drive: DriveNumber, json: string) {
|
||||
|
@ -1017,7 +981,8 @@ export default class DiskII implements Card<State>, MassStorage<NibbleFormat> {
|
|||
|
||||
private insertDisk(drive: DriveNumber, disk: FloppyDisk) {
|
||||
const cur = this.drives[drive];
|
||||
Object.assign(cur, disk);
|
||||
cur.disk = disk as WozDisk | NibbleDisk;
|
||||
cur.metadata = disk.metadata;
|
||||
const { name, side } = cur.metadata;
|
||||
this.updateDirty(drive, true);
|
||||
this.callbacks.label(drive, name, side);
|
||||
|
@ -1029,7 +994,7 @@ export default class DiskII implements Card<State>, MassStorage<NibbleFormat> {
|
|||
if (!isNibbleDrive(cur)) {
|
||||
return null;
|
||||
}
|
||||
const { format, readOnly, tracks, volume } = cur;
|
||||
const { format, readOnly, tracks, volume } = cur.disk;
|
||||
const { name } = cur.metadata;
|
||||
const len = format === 'nib' ?
|
||||
tracks.reduce((acc, track) => acc + track.length, 0) :
|
||||
|
@ -1044,7 +1009,7 @@ export default class DiskII implements Card<State>, MassStorage<NibbleFormat> {
|
|||
idx += tracks[t].length;
|
||||
} else {
|
||||
for (let s = 0; s < 0x10; s++) {
|
||||
const sector = readSector({ ...cur, format: extension }, t, s);
|
||||
const sector = readSector({ ...cur.disk, format: extension }, t, s);
|
||||
data.set(sector, idx);
|
||||
idx += sector.length;
|
||||
}
|
||||
|
@ -1067,13 +1032,13 @@ export default class DiskII implements Card<State>, MassStorage<NibbleFormat> {
|
|||
return null;
|
||||
}
|
||||
const data: string[][] | string[] = [];
|
||||
for (let t = 0; t < cur.tracks.length; t++) {
|
||||
if (cur.format === 'nib') {
|
||||
data[t] = base64_encode(cur.tracks[t]);
|
||||
for (let t = 0; t < cur.disk.tracks.length; t++) {
|
||||
if (isNibbleDisk(cur.disk)) {
|
||||
data[t] = base64_encode(cur.disk.tracks[t]);
|
||||
} else {
|
||||
const track: string[] = [];
|
||||
for (let s = 0; s < 0x10; s++) {
|
||||
track[s] = base64_encode(readSector(cur, t, s));
|
||||
track[s] = base64_encode(readSector(cur.disk, t, s));
|
||||
}
|
||||
data[t] = track;
|
||||
}
|
||||
|
|
|
@ -70,13 +70,13 @@ export const ENCODING_BLOCK = 'block';
|
|||
|
||||
export interface FloppyDisk extends Disk {
|
||||
encoding: typeof ENCODING_NIBBLE | typeof ENCODING_BITSTREAM;
|
||||
tracks: memory[];
|
||||
}
|
||||
|
||||
export interface NibbleDisk extends FloppyDisk {
|
||||
encoding: typeof ENCODING_NIBBLE;
|
||||
format: Exclude<NibbleFormat, 'woz'>;
|
||||
volume: byte;
|
||||
tracks: memory[];
|
||||
}
|
||||
|
||||
export interface WozDisk extends FloppyDisk {
|
||||
|
@ -158,6 +158,11 @@ export function isNibbleDisk(disk: Disk): disk is NibbleDisk {
|
|||
return (disk as NibbleDisk)?.encoding === ENCODING_NIBBLE;
|
||||
}
|
||||
|
||||
/** Type guard for NibbleDisks */
|
||||
export function isWozDisk(disk: Disk): disk is WozDisk {
|
||||
return (disk as WozDisk)?.encoding === ENCODING_BITSTREAM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base format for JSON defined disks
|
||||
*/
|
||||
|
|
|
@ -295,7 +295,6 @@ export default function createDiskFromWoz(options: DiskOptions): WozDisk {
|
|||
encoding: ENCODING_BITSTREAM,
|
||||
format: 'woz',
|
||||
trackMap: tmap?.trackMap || [],
|
||||
tracks: trks?.tracks || [],
|
||||
rawTracks: trks?.rawTracks || [],
|
||||
readOnly: true, //chunks.info.writeProtected === 1;
|
||||
metadata: {
|
||||
|
|
|
@ -4,7 +4,7 @@ import fs from 'fs';
|
|||
import Apple2IO from 'js/apple2io';
|
||||
import DiskII, { Callbacks } from 'js/cards/disk2';
|
||||
import CPU6502 from 'js/cpu6502';
|
||||
import { DriveNumber } from 'js/formats/types';
|
||||
import { DriveNumber, NibbleDisk, WozDisk } from 'js/formats/types';
|
||||
import { byte } from 'js/types';
|
||||
import { toHex } from 'js/util';
|
||||
import { VideoModes } from 'js/videomodes';
|
||||
|
@ -71,7 +71,8 @@ describe('DiskII', () => {
|
|||
state.controllerState.latch = 0x42;
|
||||
state.controllerState.on = true;
|
||||
state.controllerState.q7 = true;
|
||||
state.drives[2].tracks[14][12] = 0x80;
|
||||
const disk2 = state.drives[2].disk as NibbleDisk;
|
||||
disk2.tracks[14][12] = 0x80;
|
||||
state.drives[2].head = 1000;
|
||||
state.drives[2].phase = 3;
|
||||
diskII.setState(state);
|
||||
|
@ -478,21 +479,24 @@ describe('DiskII', () => {
|
|||
it('writes a nibble to the disk', () => {
|
||||
const diskII = new DiskII(mockApple2IO, callbacks);
|
||||
diskII.setBinary(1, 'BYTES_BY_TRACK', 'po', BYTES_BY_TRACK_IMAGE);
|
||||
let track0 = diskII.getState().drives[1].tracks[0];
|
||||
let disk1 = diskII.getState().drives[1].disk as NibbleDisk;
|
||||
let track0 = disk1.tracks[0];
|
||||
expect(track0[0]).toBe(0xFF);
|
||||
|
||||
diskII.ioSwitch(0x89); // turn on the motor
|
||||
diskII.ioSwitch(0x8F, 0x80); // write
|
||||
diskII.ioSwitch(0x8C); // shift
|
||||
|
||||
track0 = diskII.getState().drives[1].tracks[0];
|
||||
disk1 = diskII.getState().drives[1].disk as NibbleDisk;
|
||||
track0 = disk1.tracks[0];
|
||||
expect(track0[0]).toBe(0x80);
|
||||
});
|
||||
|
||||
it('writes two nibbles to the disk', () => {
|
||||
const diskII = new DiskII(mockApple2IO, callbacks);
|
||||
diskII.setBinary(1, 'BYTES_BY_TRACK', 'po', BYTES_BY_TRACK_IMAGE);
|
||||
let track0 = diskII.getState().drives[1].tracks[0];
|
||||
let disk1 = diskII.getState().drives[1].disk as NibbleDisk;
|
||||
let track0 = disk1.tracks[0];
|
||||
expect(track0[0]).toBe(0xFF);
|
||||
|
||||
diskII.ioSwitch(0x89); // turn on the motor
|
||||
|
@ -501,7 +505,8 @@ describe('DiskII', () => {
|
|||
diskII.ioSwitch(0x8F, 0x81); // write
|
||||
diskII.ioSwitch(0x8C); // shift
|
||||
|
||||
track0 = diskII.getState().drives[1].tracks[0];
|
||||
disk1 = diskII.getState().drives[1].disk as NibbleDisk;
|
||||
track0 = disk1.tracks[0];
|
||||
expect(track0[0]).toBe(0x80);
|
||||
expect(track0[1]).toBe(0x81);
|
||||
});
|
||||
|
@ -819,10 +824,10 @@ class TestDiskReader {
|
|||
|
||||
rawTracks() {
|
||||
// NOTE(flan): Hack to access private properties.
|
||||
const disk = this.diskII as unknown as { cur: { rawTracks: Uint8Array[] } };
|
||||
const disk = (this.diskII as unknown as { cur: { disk: WozDisk } }).cur.disk;
|
||||
const result: Uint8Array[] = [];
|
||||
for (let i = 0; i < disk.cur.rawTracks.length; i++) {
|
||||
result[i] = disk.cur.rawTracks[i].slice(0);
|
||||
for (let i = 0; i < disk.rawTracks.length; i++) {
|
||||
result[i] = disk.rawTracks[i].slice(0);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -21,7 +21,7 @@ describe('woz', () => {
|
|||
|
||||
const disk = createDiskFromWoz(options);
|
||||
expect(disk).toEqual({
|
||||
metadata: { name: 'Mock Woz 1' },
|
||||
metadata: { name: 'Mock Woz 1', side: undefined },
|
||||
readOnly: true,
|
||||
encoding: ENCODING_BITSTREAM,
|
||||
format: 'woz',
|
||||
|
@ -31,7 +31,6 @@ describe('woz', () => {
|
|||
1, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
])],
|
||||
tracks: [new Uint8Array([0xD5, 0xAA, 0x96])],
|
||||
info: {
|
||||
bitTiming: 0,
|
||||
bootSector: 0,
|
||||
|
@ -72,7 +71,6 @@ describe('woz', () => {
|
|||
1, 0, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
])],
|
||||
tracks: [new Uint8Array([0xD5, 0xAA, 0x96])],
|
||||
info: {
|
||||
bitTiming: 0,
|
||||
bootSector: 0,
|
||||
|
|
Loading…
Reference in New Issue