Woz smoke test

This commit is contained in:
Will Scullin 2021-07-07 19:56:33 -07:00
parent 613410fcd4
commit d1a4bfb35f
No known key found for this signature in database
GPG Key ID: 26DCD1042C6638CD
9 changed files with 303 additions and 16 deletions

View File

@ -63,7 +63,7 @@ function InfoChunk(data) {
creator: stringFromBytes(data, 5, 37)
});
if (this.version === 2) {
if (this.version > 1) {
Object.assign(this, {
sides: data.getUint8(37),
bootSector: data.getUint8(38),
@ -115,8 +115,8 @@ function TrksChunk(data) {
offset = result.offset + 1;
}
this.tracks[trackNo] = track;
this.rawTracks[trackNo] = rawTrack;
this.tracks[trackNo] = new Uint8Array(track);
this.rawTracks[trackNo] = new Uint8Array(rawTrack);
}
return this;
@ -142,6 +142,7 @@ function TrksChunk2(data) {
const bits = data.buffer;
for (trackNo = 0; trackNo < this.trks.length; trackNo++) {
const trk = this.trks[trackNo];
let track = [];
const rawTrack = [];
const start = trk.startBlock * 512;
@ -268,13 +269,15 @@ export default function createDiskFromWoz(options) {
}
chunk = readChunk();
}
} else {
debug('Invalid woz header');
}
debug(chunks);
disk.trackMap = chunks.tmap.trackMap;
disk.tracks = chunks.trks.tracks;
disk.rawTracks = chunks.trks.rawTracks;
disk.trackMap = chunks.tmap?.trackMap || [];
disk.tracks = chunks.trks?.tracks || [];
disk.rawTracks = chunks.trks?.rawTracks || [];
disk.readOnly = true; //chunks.info.writeProtected === 1;
disk.name = chunks.meta?.title || options.name;

View File

@ -1,6 +1,6 @@
import DOS13 from '../../../js/formats/d13';
import { D13O } from '../../../js/formats/format_utils';
import { memory } from '../../../js/types';
import DOS13 from 'js/formats/d13';
import { D13O } from 'js/formats/format_utils';
import { memory } from 'js/types';
import { BYTES_BY_SECTOR, BYTES_BY_TRACK } from './testdata/13sector';
import { expectSequence, findBytes, skipGap } from './util';

View File

@ -1,5 +1,5 @@
import DOS from '../../../js/formats/do';
import { memory } from '../../../js/types';
import DOS from 'js/formats/do';
import { memory } from 'js/types';
import { BYTES_BY_SECTOR, BYTES_BY_TRACK } from './testdata/16sector';
import { expectSequence, findBytes, skipGap } from './util';

View File

@ -1,5 +1,5 @@
import ProDOS from '../../../js/formats/po';
import { memory } from '../../../js/types';
import ProDOS from 'js/formats/po';
import { memory } from 'js/types';
import { BYTES_BY_SECTOR, BYTES_BY_TRACK } from './testdata/16sector';
import { expectSequence, findBytes, skipGap } from './util';

View File

@ -1,4 +1,4 @@
import { memory } from '../../../../js/types';
import { memory } from 'js/types';
function generateBytesInOrder() {
const data: memory[][] = [];

View File

@ -1,4 +1,4 @@
import { memory } from '../../../../js/types';
import { memory } from 'js/types';
function generateBytesInOrder() {
const data: memory[][] = [];

169
test/js/formats/testdata/woz.ts vendored Normal file
View File

@ -0,0 +1,169 @@
import {
numberToBytes,
stringToBytes,
} from '../util';
/**
* Version 1 INFO segment
*/
const mockInfo1 = [
0x01, // Version
0x01, // Disk Type (5.25")
0x00, // Write protected
0x01, // Synchronized
0x00, // Cleaned
...stringToBytes('Apple2JS', ' ', 32),
0x00, 0x00, 0x00, 0x00, // 23 Unused
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
];
/**
* Version 2 INFO segment
*/
const mockInfo2 = [
0x02, // Version
0x01, // Disk Type (5.25")
0x00, // Write protected
0x01, // Synchronized
0x00, // Cleaned
...stringToBytes('Apple2JS', ' ', 32),
0x01, // sides
0x00, // bootSector
0x00, // bitTiming
0x00, 0x00, // compatibleHardware
0x00, 0x00, // requiredRAM
0x00, 0x00, // largest track
0x00, 0x00, 0x00, 0x00, // 14 unused
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
];
/**
* Track map all pointing to track 0
*/
export const mockTMAP = new Array(160);
mockTMAP.fill(0);
/**
* One very small track
*/
// 24 bits of track data, padded
const mockTrackData = new Array(6646);
mockTrackData.fill(0);
mockTrackData[0] = 0xd5;
mockTrackData[1] = 0xaa;
mockTrackData[2] = 0x96;
/**
* Version 1 TRKS structure
*/
const mockTRKS = [
...mockTrackData,
...numberToBytes(3, 2), // Number of bytes
...numberToBytes(24, 2), // Number of bits
...numberToBytes(0xffff, 2), // Splice point
0, // Splice nibble
0, // Splice bit count
...numberToBytes(0, 2), // Reserved
];
/**
* Version 2 TRKS structure
*/
const mockTrackMap = new Array(160 * 8);
mockTrackMap.fill(0);
mockTrackMap[0x00] = 0x03;
mockTrackMap[0x01] = 0x00;
mockTrackMap[0x02] = 0x01;
mockTrackMap[0x03] = 0x00;
mockTrackMap[0x04] = 0x18;
mockTrackMap[0x07] = 0x00;
mockTrackMap[0x08] = 0x00;
mockTrackMap[0x09] = 0x00;
const mockTrackData2 = new Array(512);
mockTrackData2.fill(0);
mockTrackData2[0] = 0xd5;
mockTrackData2[1] = 0xaa;
mockTrackData2[2] = 0x96;
const mockTRKS2 = [
...mockTrackMap,
...mockTrackData2,
];
/**
* META structures
*/
const mockMETA1 = 'title\tMock Woz 1';
const mockMETA2 = 'title\tMock Woz 2';
/**
* Woz Version 1
*/
export const mockWoz1: ArrayBuffer = new Uint8Array([
// Header
...stringToBytes('WOZ1'),
0xff, // 7 bit detection
0x0a, 0x0d, 0x0a, // LF detection
0x00, 0x00, 0x00, 0x00, // CRC
// Info chunk
...stringToBytes('INFO'),
...numberToBytes(60, 4), // Size
...mockInfo1,
// TMAP chunk
...stringToBytes('TMAP'),
...numberToBytes(mockTMAP.length, 4), // Size
...mockTMAP,
// TRKS chunk
...stringToBytes('TRKS'),
...numberToBytes(mockTRKS.length, 4), // Size
...mockTRKS,
// META chunk
...stringToBytes('META'),
...numberToBytes(mockMETA1.length, 4), // Size
...stringToBytes(mockMETA1),
]).buffer;
/**
* Woz Version 2
*/
export const mockWoz2: ArrayBuffer = new Uint8Array([
// Header
...stringToBytes('WOZ2'),
0xff, // 7 bit detection
0x0a, 0x0d, 0x0a, // LF detection
0x00, 0x00, 0x00, 0x00, // CRC
// Info chunk
...stringToBytes('INFO'),
...numberToBytes(mockInfo2.length, 4), // Size
...mockInfo2,
// TMAP chunk
...stringToBytes('TMAP'),
...numberToBytes(mockTMAP.length, 4), // Size
...mockTMAP,
// TRKS chunk
...stringToBytes('TRKS'),
...numberToBytes(mockTRKS2.length, 4), // Size
...mockTRKS2,
// META chunk
...stringToBytes('META'),
...numberToBytes(mockMETA2.length, 4), // Size
...stringToBytes(mockMETA2),
]).buffer;

View File

@ -1,4 +1,4 @@
import { memory } from '../../../js/types';
import { memory } from 'js/types';
export function skipGap(track: memory, start: number = 0): number {
const end = start + 0x100; // no gap is this big
@ -40,3 +40,27 @@ export function findBytes(track: memory, bytes: number[], start: number = 0): nu
}
return -1;
}
export const stringToBytes = (val: string, pad: string = '\0', padLength: number = 0) => {
const result = [];
let idx = 0;
while (idx < val.length) {
result.push(val.charCodeAt(idx) & 0xff);
idx++;
}
while (idx++ < padLength) {
result.push(pad.charCodeAt(0));
}
return result;
};
export const numberToBytes = (val: number, count: number) => {
const result = [];
let idx = 0;
while (idx < count) {
result.push(val & 0xff);
val >>= 8;
idx++;
}
return result;
};

View File

@ -0,0 +1,91 @@
import { WozDisk, ENCODING_BITSTREAM } from 'js/formats/types';
import createDiskFromWoz from 'js/formats/woz';
import {
mockWoz1,
mockWoz2,
mockTMAP
} from './testdata/woz';
describe('woz', () => {
beforeEach(() => {
spyOn(console, 'log');
});
it('can parse Woz version 1', () => {
const options = {
name: 'Unknown',
volume: 254,
readOnly: true,
rawData: mockWoz1
};
const disk = createDiskFromWoz(options) as WozDisk;
expect(disk).toEqual({
name: 'Mock Woz 1',
readOnly: true,
encoding: ENCODING_BITSTREAM,
trackMap: mockTMAP,
rawTracks: [new Uint8Array([
1, 1, 0, 1, 0, 1, 0, 1,
1, 0, 1, 0, 1, 0, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0,
])],
tracks: [new Uint8Array([0xD5, 0xAA, 0x96])],
});
expect(console.log).toHaveBeenCalledWith(expect.objectContaining({
info: {
bitTiming: 0,
bootSector: 0,
cleaned: 0,
compatibleHardware: 0,
creator: 'Apple2JS ',
diskType: 1,
largestTrack: 0,
requiredRAM: 0,
sides: 0,
synchronized: 1,
version: 1,
writeProtected: 0
}
}));
});
it('can parse Woz version 2', () => {
const options = {
name: 'Unknown',
volume: 254,
readOnly: true,
rawData: mockWoz2
};
const disk = createDiskFromWoz(options) as WozDisk;
expect(disk).toEqual({
name: 'Mock Woz 2',
readOnly: true,
encoding: ENCODING_BITSTREAM,
trackMap: mockTMAP,
rawTracks: [new Uint8Array([
1, 1, 0, 1, 0, 1, 0, 1,
1, 0, 1, 0, 1, 0, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0,
])],
tracks: [new Uint8Array([0xD5, 0xAA, 0x96])],
});
expect(console.log).toHaveBeenCalledWith(expect.objectContaining({
info: {
bitTiming: 0,
bootSector: 0,
cleaned: 0,
compatibleHardware: 0,
creator: 'Apple2JS ',
diskType: 1,
largestTrack: 0,
requiredRAM: 0,
sides: 1,
synchronized: 1,
version: 2,
writeProtected: 0
}
}));
});
});