mirror of
https://github.com/whscullin/apple2js.git
synced 2024-01-12 14:14:38 +00:00
Woz smoke test
This commit is contained in:
parent
613410fcd4
commit
d1a4bfb35f
|
@ -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;
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
2
test/js/formats/testdata/13sector.ts
vendored
2
test/js/formats/testdata/13sector.ts
vendored
|
@ -1,4 +1,4 @@
|
|||
import { memory } from '../../../../js/types';
|
||||
import { memory } from 'js/types';
|
||||
|
||||
function generateBytesInOrder() {
|
||||
const data: memory[][] = [];
|
||||
|
|
2
test/js/formats/testdata/16sector.ts
vendored
2
test/js/formats/testdata/16sector.ts
vendored
|
@ -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
169
test/js/formats/testdata/woz.ts
vendored
Normal 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;
|
|
@ -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;
|
||||
};
|
||||
|
|
91
test/js/formats/woz.spec.ts
Normal file
91
test/js/formats/woz.spec.ts
Normal 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
|
||||
}
|
||||
}));
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user