diff --git a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/Disk.java b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/Disk.java index 722c69fd..5fd967b9 100644 --- a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/Disk.java +++ b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/Disk.java @@ -231,8 +231,9 @@ public class Disk { if ((diskImage[0] == 0x32) && (diskImage[1] == 0x49) && (diskImage[2] == 0x4D) && (diskImage[3]) == 0x47) { is2img = true; } - /* Does it have the WOZ header? */ - else if ((diskImage[0] == 0x57) && (diskImage[1] == 0x4f) && (diskImage[2] == 0x5a) && (diskImage[3]) == 0x32) { + /* Does it have the WOZ1 or WOZ2 header? */ + else if ((diskImage[0] == 0x57) && (diskImage[1] == 0x4f) && (diskImage[2] == 0x5a) + && ((diskImage[3] == 0x31) || (diskImage[3] == 0x32))) { isWoz = true; } /* Does it have the DiskCopy 4.2 header? */ diff --git a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/physical/WozOrder.java b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/physical/WozOrder.java index a0a48191..37337ced 100644 --- a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/physical/WozOrder.java +++ b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/physical/WozOrder.java @@ -18,6 +18,9 @@ import java.util.function.Function; import static com.webcodepro.applecommander.storage.physical.NibbleCodec.readSectorFromTrack; public class WozOrder extends ImageOrder { + // The magic bytes are read in little-endian order, so they do appear reversed here. + public static final int WOZ1_MAGIC = 0x315a4f57; + public static final int WOZ2_MAGIC = 0x325a4f57; public static final int INFO_CHUNK_ID = 0x4f464e49; public static final int TMAP_CHUNK_ID = 0x50414d54; public static final int TRKS_CHUNK_ID = 0x534b5254; @@ -34,6 +37,7 @@ public class WozOrder extends ImageOrder { private boolean blockDevice; private boolean trackAndSectorDevice; private int blocksOnDevice; + private Function trackReader = null; private Function blockReader = this::readBlock525; private BiFunction sectorReader = this::readSector525; @@ -45,8 +49,15 @@ public class WozOrder extends ImageOrder { int sig = bb.getInt(); int test = bb.getInt(); - if (sig != 0x325a4f57 || test != 0xa0d0aff) { - throw new RuntimeException("Not a WOZ v2 format file."); + final int testExpected = 0xa0d0aff; + if (sig == WOZ1_MAGIC && test == testExpected) { + this.trackReader = this::readTrackDataWOZ1; + } + else if (sig == WOZ2_MAGIC && test == testExpected) { + this.trackReader = this::readTrackDataWOZ2; + } + else { + throw new RuntimeException("Not a WOZ1 or WOZ2 format file."); } bb.getInt(); // ignoring CRC @@ -214,6 +225,7 @@ public class WozOrder extends ImageOrder { } private void readTrksChunk(byte[] data) { + // Note: WOZ2 only ByteBuffer bb = ByteBuffer.wrap(data); bb.order(ByteOrder.LITTLE_ENDIAN); for (int i=0; i<160; i++) { @@ -222,6 +234,10 @@ public class WozOrder extends ImageOrder { } protected byte[] readTrackData(int track) { + return this.trackReader.apply(track); + } + + protected byte[] readTrackDataWOZ2(int track) { TmapChunk map = tmap.get(track); int trkInfo = map.getOffset00(); if (trkInfo == 255) trkInfo = map.getOffset25(); @@ -232,6 +248,17 @@ public class WozOrder extends ImageOrder { return transformBitstream(rawData, trk.getBitCount()); } + protected byte[] readTrackDataWOZ1(int track) { + final int trackLength = 6656; + int start = 256 + (track * trackLength); + byte[] details = readBytes(start + 6646, 10); + int bytesUsed = AppleUtil.getWordValue(details, 0); + int bitCount = AppleUtil.getWordValue(details, 2); + int end = start + bytesUsed; + byte[] rawData = readBytes(start, end); + return transformBitstream(rawData, bitCount); + } + protected byte[] transformBitstream(byte[] rawData, int bitCount) { // NOTE: Uncertain if we need to track 0's (only 2 allowed by hardware) or not. ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -285,14 +312,18 @@ public class WozOrder extends ImageOrder { byte[] creator = new byte[32]; bb.get(creator); this.creator = new String(creator); - this.diskSides = bb.get(); - this.bootSectorFormat = bb.get(); - this.optimalBitTiming = bb.get(); - this.compatibleHardware = bb.getShort(); - this.requiredRAM = bb.getShort(); - this.largestTrack = bb.getShort(); - this.fluxBlock = bb.getShort(); - this.largestFluxTrack = bb.getShort(); + if (this.version == 2) { + this.diskSides = bb.get(); + this.bootSectorFormat = bb.get(); + this.optimalBitTiming = bb.get(); + this.compatibleHardware = bb.getShort(); + this.requiredRAM = bb.getShort(); + this.largestTrack = bb.getShort(); + } + if (this.version == 3) { + this.fluxBlock = bb.getShort(); + this.largestFluxTrack = bb.getShort(); + } } public int getVersion() { diff --git a/lib/ac-api/src/test/java/com/webcodepro/applecommander/storage/DiskHelperTest.java b/lib/ac-api/src/test/java/com/webcodepro/applecommander/storage/DiskHelperTest.java index 331cf69e..d7693fbb 100644 --- a/lib/ac-api/src/test/java/com/webcodepro/applecommander/storage/DiskHelperTest.java +++ b/lib/ac-api/src/test/java/com/webcodepro/applecommander/storage/DiskHelperTest.java @@ -141,12 +141,20 @@ public class DiskHelperTest { showDirectory(config.getDiskDir() + "/D3151.dsk"); //$NON-NLS-1$ } - @Test - public void testLoadDos33SystemMasterWoz() throws IOException, DiskException { + public void testLoadDos33SystemMasterWoz1() throws IOException, DiskException { FormattedDisk[] disks = showDirectory(config.getDiskDir() + - "/DOS 3.3 System Master.woz"); + "/DOS 3.3 System Master.woz1"); + assertApplesoftFile(disks[0], "HELLO"); //$NON-NLS-1$ + assertIntegerFile(disks[0], "COPY"); //$NON-NLS-1$ + assertBinaryFile(disks[0], "BOOT13"); //$NON-NLS-1$ + } + + @Test + public void testLoadDos33SystemMasterWoz2() throws IOException, DiskException { + FormattedDisk[] disks = showDirectory(config.getDiskDir() + + "/DOS 3.3 System Master.woz2"); assertApplesoftFile(disks[0], "HELLO"); //$NON-NLS-1$ assertIntegerFile(disks[0], "COPY"); //$NON-NLS-1$ assertBinaryFile(disks[0], "BOOT13"); //$NON-NLS-1$ diff --git a/lib/ac-api/src/test/resources/disks/DOS 3.3 System Master.woz1 b/lib/ac-api/src/test/resources/disks/DOS 3.3 System Master.woz1 new file mode 100644 index 00000000..ac8dca39 Binary files /dev/null and b/lib/ac-api/src/test/resources/disks/DOS 3.3 System Master.woz1 differ diff --git a/lib/ac-api/src/test/resources/disks/DOS 3.3 System Master.woz b/lib/ac-api/src/test/resources/disks/DOS 3.3 System Master.woz2 similarity index 100% rename from lib/ac-api/src/test/resources/disks/DOS 3.3 System Master.woz rename to lib/ac-api/src/test/resources/disks/DOS 3.3 System Master.woz2