From 1e6648dc73e6c8b7d1644ea804749d9776833f72 Mon Sep 17 00:00:00 2001 From: Denis Molony Date: Tue, 30 Jul 2019 14:57:59 +1000 Subject: [PATCH] better woz2 support --- .../bytezone/diskbrowser/disk/AppleDisk.java | 27 +- .../diskbrowser/disk/DiskFactory.java | 3 +- .../diskbrowser/nib/DiskAddressField.java | 4 - src/com/bytezone/diskbrowser/nib/Dumper.java | 471 ----------- src/com/bytezone/diskbrowser/nib/WozFile.java | 777 +++++++++++------- .../bytezone/diskbrowser/nib/WozFileOld.java | 360 ++++++++ 6 files changed, 881 insertions(+), 761 deletions(-) delete mode 100644 src/com/bytezone/diskbrowser/nib/Dumper.java create mode 100644 src/com/bytezone/diskbrowser/nib/WozFileOld.java diff --git a/src/com/bytezone/diskbrowser/disk/AppleDisk.java b/src/com/bytezone/diskbrowser/disk/AppleDisk.java index ba35b4f..2a443bc 100755 --- a/src/com/bytezone/diskbrowser/disk/AppleDisk.java +++ b/src/com/bytezone/diskbrowser/disk/AppleDisk.java @@ -15,9 +15,10 @@ import java.util.zip.Checksum; import com.bytezone.common.Utility; import com.bytezone.diskbrowser.applefile.AppleFileSource; +import com.bytezone.diskbrowser.nib.WozFile; import com.bytezone.diskbrowser.nib.NibFile; import com.bytezone.diskbrowser.nib.V2dFile; -import com.bytezone.diskbrowser.nib.WozFile; +import com.bytezone.diskbrowser.nib.WozFileOld; import com.bytezone.diskbrowser.utilities.FileFormatException; import com.bytezone.diskbrowser.utilities.HexFormatter; @@ -240,6 +241,30 @@ public class AppleDisk implements Disk diskBuffer = disk.getDiskBuffer (); } + public AppleDisk (WozFileOld wozFile, int tracks, int sectors) + { + this.tracks = tracks; + this.sectors = sectors; + file = wozFile.file; + diskBuffer = wozFile.getDiskBuffer (); + + if (sectors == 13) + { + trackSize = 0xD00; + sectorSize = 256; + } + else + { + trackSize = 0x1000; + sectorSize = trackSize / sectors; + } + + blocks = tracks * sectors; + hasData = new boolean[blocks]; + + checkSectorsForData (); + } + public AppleDisk (WozFile wozFile, int tracks, int sectors) { this.tracks = tracks; diff --git a/src/com/bytezone/diskbrowser/disk/DiskFactory.java b/src/com/bytezone/diskbrowser/disk/DiskFactory.java index fe8ba88..aa8119a 100755 --- a/src/com/bytezone/diskbrowser/disk/DiskFactory.java +++ b/src/com/bytezone/diskbrowser/disk/DiskFactory.java @@ -234,6 +234,7 @@ public class DiskFactory { try { + // WozFileOld wozDisk = new WozFileOld (file); WozFile wozDisk = new WozFile (file); if (wozDisk.getSectorsPerTrack () == 13) { @@ -241,6 +242,7 @@ public class DiskFactory disk = checkDos (appleDisk); return disk == null ? new DataDisk (appleDisk) : disk; } + if (wozDisk.getSectorsPerTrack () == 16) { AppleDisk appleDisk256 = new AppleDisk (wozDisk, 35, 16); @@ -255,7 +257,6 @@ public class DiskFactory catch (Exception e) { System.out.println (e); - // e.printStackTrace (); return null; } } diff --git a/src/com/bytezone/diskbrowser/nib/DiskAddressField.java b/src/com/bytezone/diskbrowser/nib/DiskAddressField.java index 1dd2c8d..4d14d65 100644 --- a/src/com/bytezone/diskbrowser/nib/DiskAddressField.java +++ b/src/com/bytezone/diskbrowser/nib/DiskAddressField.java @@ -14,10 +14,6 @@ class DiskAddressField track = decode4and4 (buffer, 2); sector = decode4and4 (buffer, 4); checksum = decode4and4 (buffer, 6); - - // if (track == 0) - // for (int i = 0; i < 8; i++) - // System.out.printf ("%02X ", buffer[i]); } // ---------------------------------------------------------------------------------// diff --git a/src/com/bytezone/diskbrowser/nib/Dumper.java b/src/com/bytezone/diskbrowser/nib/Dumper.java deleted file mode 100644 index e61e5d5..0000000 --- a/src/com/bytezone/diskbrowser/nib/Dumper.java +++ /dev/null @@ -1,471 +0,0 @@ -package com.bytezone.diskbrowser.nib; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import com.bytezone.common.Utility; -import com.bytezone.diskbrowser.utilities.HexFormatter; - -// -----------------------------------------------------------------------------------// -public class Dumper -// -----------------------------------------------------------------------------------// -{ - private static final int[] weights = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; - - private static final byte[] address16prologue = - { (byte) 0xD5, (byte) 0xAA, (byte) 0x96 }; - private static final byte[] address13prologue = - { (byte) 0xD5, (byte) 0xAA, (byte) 0xB5 }; - private static final byte[] dataPrologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0xAD }; - private static final byte[] epilogue = { (byte) 0xDE, (byte) 0xAA, (byte) 0xEB }; - - private final DiskReader13Sector diskReader13Sector = new DiskReader13Sector (); - private final DiskReader16Sector diskReader16Sector = new DiskReader16Sector (); - - private int diskSectors; - private int wozVersion; - private byte[] addressPrologue; - - private final boolean debug = false; - - // ---------------------------------------------------------------------------------// - public Dumper (File file) throws DiskNibbleException - // ---------------------------------------------------------------------------------// - { - byte[] buffer = readFile (file); - String header = new String (buffer, 0, 4); - if (!"WOZ1".equals (header) && !"WOZ2".equals (header)) - { - System.out.println ("Not a WOZ disk"); - return; - } - - List tracks = null; - - int ptr = 12; - while (ptr < buffer.length) - { - String chunkId = new String (buffer, ptr, 4); - int size = Utility.getLong (buffer, ptr + 4); - if (debug) - System.out.printf ("%n%s %,9d%n", chunkId, size); - - switch (chunkId) - { - case "INFO": // 60 bytes - info (buffer, ptr); - break; - case "TMAP": // 160 bytes - tmap (buffer, ptr); - break; - case "TRKS": // starts at 248 - tracks = trks (buffer, ptr); - break; - case "META": - meta (buffer, ptr, size); - break; - case "WRIT": - break; - default: - break; - } - ptr += size + 8; - } - - DiskReader diskReader = diskSectors == 13 ? diskReader13Sector : diskReader16Sector; - byte[] diskBuffer = new byte[35 * diskSectors * 256]; - - for (Track track : tracks) - for (Sector sector : track) - if (sector.dataOffset > 0) - sector.pack (diskReader, diskBuffer, - 256 * (sector.trackNo * diskSectors + sector.sector)); - - int tr = 0x11; - int sc = 15; - System.out - .println (HexFormatter.format (diskBuffer, 256 * (tr * diskSectors + sc), 256)); - } - - // ---------------------------------------------------------------------------------// - private void info (byte[] buffer, int ptr) - // ---------------------------------------------------------------------------------// - { - wozVersion = val8 (buffer, ptr + 8); - int diskType = val8 (buffer, ptr + 9); - int writeProtected = val8 (buffer, ptr + 10); - int synchronised = val8 (buffer, ptr + 11); - int cleaned = val8 (buffer, ptr + 12); - String creator = new String (buffer, ptr + 13, 32); - int sides = val8 (buffer, ptr + 45); - int bootSectorFormat = val8 (buffer, ptr + 46); - int optimalBitTiming = val8 (buffer, ptr + 47); - int compatibleHardware = val16 (buffer, ptr + 48); - int requiredRam = val16 (buffer, ptr + 50); - int largestTrack = val16 (buffer, ptr + 52); - - diskSectors = bootSectorFormat == 2 ? 13 : 16; - addressPrologue = diskSectors == 13 ? address13prologue : address16prologue; - - if (debug) - { - String bootSectorFormatText = - bootSectorFormat == 0 ? "Unknown" : bootSectorFormat == 1 ? "16 sector" - : bootSectorFormat == 2 ? "13 sector" : "Hybrid"; - String diskTypeText = diskType == 1 ? "5.25" : "3.5"; - - System.out.printf ("Version ............. %d%n", wozVersion); - System.out.printf ("Disk type ........... %d (%s\")%n", diskType, diskTypeText); - System.out.printf ("Write protected ..... %d%n", writeProtected); - System.out.printf ("Synchronized ........ %d%n", synchronised); - System.out.printf ("Cleaned ............. %d%n", cleaned); - System.out.printf ("Creator ............. %s%n", creator); - System.out.printf ("Sides ............... %d%n", sides); - System.out.printf ("Boot sector format .. %d (%s)%n", bootSectorFormat, - bootSectorFormatText); - System.out.printf ("Optimal bit timing .. %d%n", optimalBitTiming); - System.out.printf ("Compatible hardware . %d%n", compatibleHardware); - System.out.printf ("Required RAM ........ %d%n", requiredRam); - System.out.printf ("Largest track ....... %d%n", largestTrack); - } - } - - // ---------------------------------------------------------------------------------// - private void tmap (byte[] buffer, int ptr) - // ---------------------------------------------------------------------------------// - { - ptr += 8; - } - - // ---------------------------------------------------------------------------------// - private void meta (byte[] buffer, int ptr, int length) - // ---------------------------------------------------------------------------------// - { - ptr += 8; - - if (debug) - { - String metaData = new String (buffer, ptr, length); - String[] chunks = metaData.split ("\n"); - for (String chunk : chunks) - { - String[] parts = chunk.split ("\t"); - if (parts.length >= 2) - System.out.printf ("%-20s %s%n", parts[0], parts[1]); - else - System.out.printf ("%-20s%n", parts[0]); - } - } - } - - // ---------------------------------------------------------------------------------// - private List trks (byte[] rawBuffer, int ptr) - // ---------------------------------------------------------------------------------// - { - List tracks = new ArrayList<> (); - ptr += 8; - for (int i = 0; i < 160; i++) - { - Track trk = new Track (i, rawBuffer, ptr); - if (trk.bitCount == 0) - break; - tracks.add (trk); - ptr += 8; - if (debug) - System.out.printf ("%n$%02X %s%n", i, trk); - } - return tracks; - } - - // ---------------------------------------------------------------------------------// - private int val8 (byte[] buffer, int ptr) - // ---------------------------------------------------------------------------------// - { - return (buffer[ptr] & 0xFF); - } - - // ---------------------------------------------------------------------------------// - private int val16 (byte[] buffer, int ptr) - // ---------------------------------------------------------------------------------// - { - return (buffer[ptr++] & 0xFF) + ((buffer[ptr] & 0xFF) << 8); - } - - // ---------------------------------------------------------------------------------// - private int val32 (byte[] buffer, int ptr) - // ---------------------------------------------------------------------------------// - { - return (buffer[ptr++] & 0xFF) + ((buffer[ptr++] & 0xFF) << 8) - + ((buffer[ptr++] & 0xFF) << 16) + ((buffer[ptr] & 0xFF) << 24); - } - - // ---------------------------------------------------------------------------------// - // decode4and4 - // ---------------------------------------------------------------------------------// - - private int decode4and4 (byte[] buffer, int offset) - { - int odds = ((buffer[offset] & 0xFF) << 1) | 0x01; - int evens = buffer[offset + 1] & 0xFF; - return odds & evens; - } - - // ---------------------------------------------------------------------------------// - private byte[] readFile (File file) - // ---------------------------------------------------------------------------------// - { - try (BufferedInputStream in = new BufferedInputStream (new FileInputStream (file))) - { - return in.readAllBytes (); - } - catch (IOException e) - { - e.printStackTrace (); - return null; - } - } - - // ---------------------------------------------------------------------------------// - public static void main (String[] args) - // ---------------------------------------------------------------------------------// - { - // File file = new File ("/Users/denismolony/code/python/wozardry-2.0/bill.woz"); - File file = new File ("/Users/denismolony/Dropbox/Examples/woz test images/WOZ 2.0/" - + "DOS 3.3 System Master.woz"); - try - { - Dumper dumper = new Dumper (file); - } - catch (Exception e) - { - e.printStackTrace (); - } - } - - // ---------------------------------------------------------------------------------// - class Track implements Iterable - // ---------------------------------------------------------------------------------// - { - int trackNo; - int startingBlock; - int blockCount; - int bitCount; - - byte[] rawBuffer; - byte[] newBuffer; - - int bitIndex; - int byteIndex; - int trackIndex; - int revolutions; - - List sectors = new ArrayList<> (); - - // ---------------------------------------------------------------------------------// - public Track (int trackNo, byte[] rawBuffer, int ptr) - // ---------------------------------------------------------------------------------// - { - this.rawBuffer = rawBuffer; - this.trackNo = trackNo; - - startingBlock = val16 (rawBuffer, ptr); - blockCount = val16 (rawBuffer, ptr + 2); - bitCount = val32 (rawBuffer, ptr + 4); - - if (bitCount == 0) - return; - - byteIndex = startingBlock * 512; - - int offset = -1; - - while (sectors.size () < diskSectors) - { - offset = findNext (addressPrologue, offset + 1); - if (offset < 0) - break; - - Sector sector = new Sector (this, offset); - if (sectors.size () > 0) - checkDuplicates (sector); - sectors.add (sector); - } - } - - // ---------------------------------------------------------------------------------// - private void checkDuplicates (Sector sector1) - // ---------------------------------------------------------------------------------// - { - for (Sector sector : sectors) - if (sector1.sector == sector.sector) - System.out.println ("\n*** duplicate ***\n"); - } - - // ---------------------------------------------------------------------------------// - boolean nextBit () - // ---------------------------------------------------------------------------------// - { - boolean bit = ((rawBuffer[byteIndex] & 0xFF) & weights[bitIndex]) != 0; - - if (++trackIndex >= bitCount) - { - ++revolutions; - trackIndex = 0; - bitIndex = 0; - byteIndex = startingBlock * 512; - } - else if (++bitIndex >= 8) - { - ++byteIndex; - bitIndex = 0; - } - - return bit; - } - - // ---------------------------------------------------------------------------------// - int nextByte () - // ---------------------------------------------------------------------------------// - { - byte b = 0; - while ((b & 0x80) == 0) - { - b <<= 1; - if (nextBit ()) - b |= 0x01; - } - - return b; - } - - // ---------------------------------------------------------------------------------// - void readTrack () - // ---------------------------------------------------------------------------------// - { - if (newBuffer != null) - return; - - int max = (bitCount - 1) / 8 + 1; - max += 520; - newBuffer = new byte[max]; - - for (int i = 0; i < max; i++) - newBuffer[i] = (byte) nextByte (); - } - - // ---------------------------------------------------------------------------------// - int findNext (byte[] key, int start) - // ---------------------------------------------------------------------------------// - { - readTrack (); - - int max = newBuffer.length - key.length; - outer: for (int ptr = start; ptr < max; ptr++) - { - for (int keyPtr = 0; keyPtr < key.length; keyPtr++) - if (newBuffer[ptr + keyPtr] != key[keyPtr]) - continue outer; - return ptr; - } - - return -1; - } - - // ---------------------------------------------------------------------------------// - void packSector (int sector) - // ---------------------------------------------------------------------------------// - { - - } - - // ---------------------------------------------------------------------------------// - void dump () - // ---------------------------------------------------------------------------------// - { - System.out.println (HexFormatter.format (newBuffer)); - } - - // ---------------------------------------------------------------------------------// - @Override - public String toString () - // ---------------------------------------------------------------------------------// - { - StringBuilder text = new StringBuilder (); - text.append (String.format ("Start: %4d, Blocks: %2d, Bits: %,8d%n%n", - startingBlock, blockCount, bitCount)); - int count = 0; - for (Sector sector : sectors) - text.append (String.format ("%2d %s%n", count++, sector)); - text.deleteCharAt (text.length () - 1); - return text.toString (); - } - - // ---------------------------------------------------------------------------------// - @Override - public Iterator iterator () - // ---------------------------------------------------------------------------------// - { - return sectors.iterator (); - } - } - - // ---------------------------------------------------------------------------------// - class Sector - // ---------------------------------------------------------------------------------// - { - Track track; - int trackNo, sector, volume, checksum; - int addressOffset, dataOffset; - - // ---------------------------------------------------------------------------------// - Sector (Track track, int addressOffset) - // ---------------------------------------------------------------------------------// - { - this.track = track; - byte[] buffer = track.newBuffer; - volume = decode4and4 (buffer, addressOffset + 3); - trackNo = decode4and4 (buffer, addressOffset + 5); - sector = decode4and4 (buffer, addressOffset + 7); - checksum = decode4and4 (buffer, addressOffset + 9); - - this.addressOffset = addressOffset; - dataOffset = track.findNext (dataPrologue, addressOffset + 11); - if (dataOffset > addressOffset + 200) - dataOffset = -1; - } - - // ---------------------------------------------------------------------------------// - void dump () - // ---------------------------------------------------------------------------------// - { - System.out.println (); - System.out.println (this); - System.out.println ( - HexFormatter.format (track.newBuffer, addressOffset, 512, addressOffset)); - } - - // ---------------------------------------------------------------------------------// - void pack (DiskReader diskReader, byte[] buffer, int ptr) throws DiskNibbleException - // ---------------------------------------------------------------------------------// - { - byte[] decodedBuffer = diskReader.decodeSector (track.newBuffer, dataOffset + 3); - System.arraycopy (decodedBuffer, 0, buffer, ptr, decodedBuffer.length); - } - - // ---------------------------------------------------------------------------------// - @Override - public String toString () - // ---------------------------------------------------------------------------------// - { - String dataOffsetText = dataOffset < 0 ? "" : String.format ("%04X", dataOffset); - return String.format ( - "Vol: %02X Trk: %02X Sct: %02X Chk: %02X Add: %04X Dat: %s", volume, - trackNo, sector, checksum, addressOffset, dataOffsetText); - } - } -} diff --git a/src/com/bytezone/diskbrowser/nib/WozFile.java b/src/com/bytezone/diskbrowser/nib/WozFile.java index 127bceb..df59901 100644 --- a/src/com/bytezone/diskbrowser/nib/WozFile.java +++ b/src/com/bytezone/diskbrowser/nib/WozFile.java @@ -5,56 +5,56 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.Utility; +// -----------------------------------------------------------------------------------// public class WozFile { - private static final byte[] WOZ1_FILE_HEADER = - { 0x57, 0x4F, 0x5A, 0x31, (byte) 0xFF, 0x0A, 0x0D, 0x0A }; - private static final byte[] WOZ2_FILE_HEADER = - { 0x57, 0x4F, 0x5A, 0x32, (byte) 0xFF, 0x0A, 0x0D, 0x0A }; + private static final byte[] address16prologue = + { (byte) 0xD5, (byte) 0xAA, (byte) 0x96 }; + private static final byte[] address13prologue = + { (byte) 0xD5, (byte) 0xAA, (byte) 0xB5 }; + private static final byte[] dataPrologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0xAD }; + private static final byte[] epilogue = { (byte) 0xDE, (byte) 0xAA, (byte) 0xEB }; + + private static final int BLOCK_SIZE = 512; + private static final int SECTOR_SIZE = 256; private static final int TRK_SIZE = 0x1A00; - private static final int INFO_SIZE = 0x3C; - private static final int TMAP_SIZE = 0xA0; private static final int DATA_SIZE = TRK_SIZE - 10; - private final boolean debug = true; - private final boolean dump = true; - private int diskType; // 5.25 or 3.5 - private int wozVersion; - private int bootSectorFormat; + private final DiskReader13Sector diskReader13Sector = new DiskReader13Sector (); + private final DiskReader16Sector diskReader16Sector = new DiskReader16Sector (); + + private static int[][] interleave = + { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 0, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 15 } }; public final File file; - byte[] diskBuffer; - private final MC3470 mc3470 = new MC3470 (); - private final List nibbleTracks = new ArrayList<> (40); + private int diskSectors; + private int wozVersion; + private byte[] addressPrologue; + private final byte[] diskBuffer; + + private final boolean debug = false; // ---------------------------------------------------------------------------------// - // constructor - // ---------------------------------------------------------------------------------// - public WozFile (File file) throws DiskNibbleException + // ---------------------------------------------------------------------------------// { this.file = file; - byte[] buffer = readFile (); - boolean valid = false; - if (matches (WOZ1_FILE_HEADER, buffer)) - wozVersion = 1; - else if (matches (WOZ2_FILE_HEADER, buffer)) - wozVersion = 2; - else - { - System.out.println (HexFormatter.format (buffer, 0, 20)); + byte[] buffer = readFile (file); + String header = new String (buffer, 0, 4); + if (!"WOZ1".equals (header) && !"WOZ2".equals (header)) throw new DiskNibbleException ("Header error"); - } - int checksum1 = readInt (buffer, 8, 4); + int checksum1 = val32 (buffer, 8); int checksum2 = Utility.crc32 (buffer, 12, buffer.length - 12); if (checksum1 != checksum2) { @@ -63,263 +63,218 @@ public class WozFile throw new DiskNibbleException ("Checksum error"); } + List tracks = null; + int ptr = 12; - read: while (ptr < buffer.length) + while (ptr < buffer.length) { String chunkId = new String (buffer, ptr, 4); - ptr += 4; - int chunkSize = readInt (buffer, ptr, 4); - ptr += 4; - + int size = val32 (buffer, ptr + 4); if (debug) + System.out.printf ("%n%s %,9d%n", chunkId, size); + + switch (chunkId) { - System.out.printf ("Offset : %06X%n", ptr - 8); - System.out.printf ("Chunk ID : %s%n", chunkId); - System.out.printf ("Chunk size: %,d%n", chunkSize); - } - - if ("INFO".equals (chunkId)) - { - if (debug) - { - int diskType = buffer[ptr + 1] & 0xFF; - String diskTypeText = diskType == 1 ? "5.25" : diskType == 2 ? "3.5" : "??"; - - System.out.println (); - System.out.printf ("Version ........... %02X%n", buffer[ptr]); - System.out.printf ("Disk type ......... %02X %s%n", diskType, diskTypeText); - System.out.printf ("Write protected ... %02X%n", buffer[ptr + 2]); - System.out.printf ("Synchronised ...... %02X%n", buffer[ptr + 3]); - System.out.printf ("Cleaned ........... %02X%n", buffer[ptr + 4]); - System.out.printf ("Creator ........... %s%n", - new String (buffer, ptr + 5, 32).trim ()); - - if (wozVersion > 1) - { - int bootFormat = buffer[ptr + 38] & 0xFF; - String bootFormatText = bootFormat == 1 ? "16 sector" - : bootFormat == 2 ? "13 sector" : bootFormat == 3 ? "Both" : "??"; - System.out.printf ("Disk sides ........ %02X%n", buffer[ptr + 37]); - System.out.printf ("Boot format ....... %02X %s%n", bootFormat, - bootFormatText); - System.out.printf ("Optimal timing .... %02X%n", buffer[ptr + 39]); - System.out.printf ("Compatible flags .. %04X%n", - readInt (buffer, ptr + 40, 2)); - System.out.printf ("Minimum RAM ....... %04X%n", - readInt (buffer, ptr + 42, 2)); - System.out.printf ("Largest track ..... %04X%n", - readInt (buffer, ptr + 44, 2)); - } - System.out.println (); - } - - diskType = buffer[ptr + 1] & 0xFF; - if (wozVersion > 1) - bootSectorFormat = buffer[ptr + 38] & 0xFF; - - ptr += INFO_SIZE; - } - else if ("TMAP".equals (chunkId)) - { - if (debug) - { - for (int track = 0; track < 40; track++) - { - for (int qtr = 0; qtr < 4; qtr++) - System.out.printf ("%02X ", buffer[ptr++]); - System.out.println (); - } - System.out.println (); - } - else - ptr += TMAP_SIZE; - } - else if ("TRKS".equals (chunkId)) - { - if (debug) - { - System.out.println ("***********************************************"); - System.out.printf ("* Disk ......... %s%n", file.getName ()); - System.out.println ("***********************************************"); - } - - if (wozVersion == 1) - { - int tracks = chunkSize / TRK_SIZE; - - for (int trackNo = 0; trackNo < tracks; trackNo++) - { - int bytesUsed = readInt (buffer, ptr + DATA_SIZE, 2); - int bitCount = readInt (buffer, ptr + DATA_SIZE + 2, 2); - - if (debug) - { - System.out.println ("***************************************"); - System.out.printf ("* Track ......... %,6d of %,6d *%n", trackNo, - tracks); - System.out.printf ("* Bytes used .... %,6d *%n", bytesUsed); - System.out.printf ("* Bit count .... %,6d *%n", bitCount); - System.out.println ("***************************************"); - } - - try - { - // nibbleTracks.add (mc3470.getNibbleTrack (buffer, ptr, bytesUsed, bitCount)); - List diskSectors = - mc3470.readTrack (buffer, ptr, bytesUsed, bitCount); - - if (trackNo == 0) // create disk buffer - { - if (mc3470.is13Sector ()) - diskBuffer = new byte[35 * 13 * 256]; - else if (mc3470.is16Sector ()) - diskBuffer = new byte[35 * 16 * 256]; - else - { - System.out.println ("unknown disk format"); - break read; - } - } - - mc3470.storeSectors (diskSectors, diskBuffer); - } - catch (Exception e) - { - System.out.println (e); - break read; - } - - ptr += TRK_SIZE; - } - } - else - { - diskBuffer = new byte[(bootSectorFormat == 2 ? 13 : 16) * 35 * 256]; - - for (int trackNo = 0; trackNo < 160; trackNo++) - { - int p = 256 + trackNo * 8; - int startingBlock = readInt (buffer, p, 2); - int blockCount = readInt (buffer, p + 2, 2); - int bitCount = readInt (buffer, p + 4, 4); - - if (debug) - { - System.out.println ("******************************"); - System.out.printf ("* Track ......... %,6d *%n", trackNo); - System.out.printf ("* Start block ... %,6d *%n", startingBlock); - System.out.printf ("* Block count ... %,6d *%n", blockCount); - System.out.printf ("* Bit count .... %,6d *%n", bitCount); - System.out.println ("******************************"); - } - - if (startingBlock == 0) - break; - - try - { - // nibbleTracks.add (mc3470.getNibbleTrack (buffer, ptr, bytesUsed, bitCount)); - List diskSectors = mc3470.readTrack (buffer, - startingBlock * 512, blockCount * 512, bitCount); - - for (RawDiskSector rawDiskSector : diskSectors) - { - System.out.println (rawDiskSector); - rawDiskSector.dump (); - } - - mc3470.storeSectors (diskSectors, diskBuffer); - } - catch (Exception e) - { - System.out.println (e); - break read; - } - } - ptr += chunkSize; - } - } - else if ("META".equals (chunkId)) - { - // System.out.printf ("[%s] %08X%n", chunkId, chunkSize); - // System.out.println (HexFormatter.format (buffer, ptr, chunkSize)); - ptr += chunkSize; - } - else - { - System.out.printf ("Unknown %08X%n", chunkSize); - ptr += chunkSize; + case "INFO": // 60 bytes + info (buffer, ptr); + break; + case "TMAP": // 160 bytes + tmap (buffer, ptr); + break; + case "TRKS": // starts at 248 + tracks = trks (buffer, ptr); + break; + case "META": + meta (buffer, ptr, size); + break; + case "WRIT": + break; + default: + break; } + ptr += size + 8; } - // if (!valid) - // readNibbleTracks (buffer); + DiskReader diskReader = diskSectors == 13 ? diskReader13Sector : diskReader16Sector; + diskBuffer = new byte[35 * diskSectors * 256]; + int ndx = diskSectors == 13 ? 0 : 1; + + for (Track track : tracks) + for (Sector sector : track) + if (sector.dataOffset > 0) + sector.pack (diskReader, diskBuffer, SECTOR_SIZE + * (sector.trackNo * diskSectors + interleave[ndx][sector.sectorNo])); } // ---------------------------------------------------------------------------------// - // readNibbleTracks - // ---------------------------------------------------------------------------------// - - private void readNibbleTracks (byte[] buffer) - { - for (int track = 0; track < 35; track++) - { - int ptr = track * 6656 + 256; - - int bytesUsed = readInt (buffer, ptr + DATA_SIZE, 2); - int bitCount = readInt (buffer, ptr + DATA_SIZE + 2, 2); - - NibbleTrack nibbleTrack = mc3470.getNibbleTrack (buffer, ptr, bytesUsed, bitCount); - nibbleTracks.add (nibbleTrack); - } - } - - // ---------------------------------------------------------------------------------// - // getSectorsPerTrack - // ---------------------------------------------------------------------------------// - - public int getSectorsPerTrack () - { - return mc3470.is13Sector () ? 13 : mc3470.is16Sector () ? 16 : 0; - } - - // ---------------------------------------------------------------------------------// - // readInt - // ---------------------------------------------------------------------------------// - - private int readInt (byte[] buffer, int offset, int length) - { - int shift = 0; - int value = 0; - for (int i = 0; i < length; i++) - { - value |= (buffer[offset + i] & 0xFF) << shift; - shift += 8; - } - return value; - } - - // ---------------------------------------------------------------------------------// - // getDiskBuffer - // ---------------------------------------------------------------------------------// - public byte[] getDiskBuffer () + // ---------------------------------------------------------------------------------// { return diskBuffer; } // ---------------------------------------------------------------------------------// - // readFile + public int getSectorsPerTrack () // ---------------------------------------------------------------------------------// - - private byte[] readFile () { - try + return diskSectors; + } + + // ---------------------------------------------------------------------------------// + private void info (byte[] buffer, int ptr) + // ---------------------------------------------------------------------------------// + { + wozVersion = val8 (buffer, ptr + 8); + + int diskType = val8 (buffer, ptr + 9); + int writeProtected = val8 (buffer, ptr + 10); + int synchronised = val8 (buffer, ptr + 11); + int cleaned = val8 (buffer, ptr + 12); + String creator = new String (buffer, ptr + 13, 32); + + if (debug) { - BufferedInputStream in = new BufferedInputStream (new FileInputStream (file)); - byte[] buffer = in.readAllBytes (); - in.close (); - return buffer; + String diskTypeText = diskType == 1 ? "5.25" : "3.5"; + + System.out.printf ("Version ............. %d%n", wozVersion); + System.out.printf ("Disk type ........... %d (%s\")%n", diskType, diskTypeText); + System.out.printf ("Write protected ..... %d%n", writeProtected); + System.out.printf ("Synchronized ........ %d%n", synchronised); + System.out.printf ("Cleaned ............. %d%n", cleaned); + System.out.printf ("Creator ............. %s%n", creator); + } + + if (wozVersion == 2) + { + int sides = val8 (buffer, ptr + 45); + int bootSectorFormat = val8 (buffer, ptr + 46); + int optimalBitTiming = val8 (buffer, ptr + 47); + int compatibleHardware = val16 (buffer, ptr + 48); + int requiredRam = val16 (buffer, ptr + 50); + int largestTrack = val16 (buffer, ptr + 52); + + setGlobals (bootSectorFormat == 2 ? 13 : 16); + + if (debug) + { + String bootSectorFormatText = + bootSectorFormat == 0 ? "Unknown" : bootSectorFormat == 1 ? "16 sector" + : bootSectorFormat == 2 ? "13 sector" : "Hybrid"; + + System.out.printf ("Sides ............... %d%n", sides); + System.out.printf ("Boot sector format .. %d (%s)%n", bootSectorFormat, + bootSectorFormatText); + System.out.printf ("Optimal bit timing .. %d%n", optimalBitTiming); + System.out.printf ("Compatible hardware . %d%n", compatibleHardware); + System.out.printf ("Required RAM ........ %d%n", requiredRam); + System.out.printf ("Largest track ....... %d%n", largestTrack); + } + } + } + + // ---------------------------------------------------------------------------------// + private void setGlobals (int diskSectors) + // ---------------------------------------------------------------------------------// + { + this.diskSectors = diskSectors; + addressPrologue = diskSectors == 13 ? address13prologue : address16prologue; + } + + // ---------------------------------------------------------------------------------// + private void tmap (byte[] buffer, int ptr) + // ---------------------------------------------------------------------------------// + { + ptr += 8; + } + + // ---------------------------------------------------------------------------------// + private void meta (byte[] buffer, int ptr, int length) + // ---------------------------------------------------------------------------------// + { + ptr += 8; + + if (debug) + { + String metaData = new String (buffer, ptr, length); + String[] chunks = metaData.split ("\n"); + for (String chunk : chunks) + { + String[] parts = chunk.split ("\t"); + if (parts.length >= 2) + System.out.printf ("%-20s %s%n", parts[0], parts[1]); + else + System.out.printf ("%-20s%n", parts[0]); + } + } + } + + // ---------------------------------------------------------------------------------// + private List trks (byte[] rawBuffer, int ptr) + // ---------------------------------------------------------------------------------// + { + List tracks = new ArrayList<> (); + ptr += 8; + + int reclen = wozVersion == 1 ? TRK_SIZE : 8; + int max = wozVersion == 1 ? 35 : 160; + for (int i = 0; i < max; i++) + { + try + { + Track trk = new Track (i, rawBuffer, ptr); + if (trk.bitCount == 0) + break; + tracks.add (trk); + if (debug) + System.out.printf ("%n$%02X %s%n", i, trk); + } + catch (DiskNibbleException e) + { + e.printStackTrace (); + } + ptr += reclen; + } + return tracks; + } + + // ---------------------------------------------------------------------------------// + private int val8 (byte[] buffer, int ptr) + // ---------------------------------------------------------------------------------// + { + return (buffer[ptr] & 0xFF); + } + + // ---------------------------------------------------------------------------------// + private int val16 (byte[] buffer, int ptr) + // ---------------------------------------------------------------------------------// + { + return (buffer[ptr++] & 0xFF) + ((buffer[ptr] & 0xFF) << 8); + } + + // ---------------------------------------------------------------------------------// + private int val32 (byte[] buffer, int ptr) + // ---------------------------------------------------------------------------------// + { + return (buffer[ptr++] & 0xFF) + ((buffer[ptr++] & 0xFF) << 8) + + ((buffer[ptr++] & 0xFF) << 16) + ((buffer[ptr] & 0xFF) << 24); + } + + // ---------------------------------------------------------------------------------// + private int decode4and4 (byte[] buffer, int offset) + // ---------------------------------------------------------------------------------// + { + int odds = ((buffer[offset] & 0xFF) << 1) | 0x01; + int evens = buffer[offset + 1] & 0xFF; + return odds & evens; + } + + // ---------------------------------------------------------------------------------// + private byte[] readFile (File file) + // ---------------------------------------------------------------------------------// + { + try (BufferedInputStream in = new BufferedInputStream (new FileInputStream (file))) + { + return in.readAllBytes (); } catch (IOException e) { @@ -328,33 +283,287 @@ public class WozFile } } - void dump (int trackNo) - { - - } - // ---------------------------------------------------------------------------------// - // matches - // ---------------------------------------------------------------------------------// - - private boolean matches (byte[] b1, byte[] b2) - { - for (int i = 0; i < b1.length; i++) - if (b1[i] != b2[i]) - return false; - return true; - } - public static void main (String[] args) + // ---------------------------------------------------------------------------------// { - File file = new File ("/Users/denismolony/code/python/wozardry-2.0/bill.woz"); + String home = "/Users/denismolony/"; + String wozBase1 = home + "Dropbox/Examples/woz test images/WOZ 1.0/"; + String wozBase2 = home + "Dropbox/Examples/woz test images/WOZ 2.0/"; + File[] files = { new File (home + "code/python/wozardry-2.0/bill.woz"), + new File (wozBase2 + "DOS 3.3 System Master.woz"), + new File (wozBase1 + "DOS 3.3 System Master.woz") }; try { - WozFile wozFile = new WozFile (file); + new WozFile (files[2]); } - catch (DiskNibbleException e) + catch (Exception e) { e.printStackTrace (); } } + + // ---------------------------------------------------------------------------------// + class Track implements Iterable + // ---------------------------------------------------------------------------------// + { + int trackNo; + int startingBlock; + int blockCount; + int bitCount; + + byte[] rawBuffer; + byte[] newBuffer; + + int bitIndex; + int byteIndex; + int trackIndex; + int revolutions; + int bytesUsed; + + List sectors = new ArrayList<> (); + + // ---------------------------------------------------------------------------------// + public Track (int trackNo, byte[] rawBuffer, int ptr) throws DiskNibbleException + // ---------------------------------------------------------------------------------// + { + this.rawBuffer = rawBuffer; + this.trackNo = trackNo; + + if (debug) + System.out.println (HexFormatter.format (rawBuffer, ptr, 512, ptr)); + + if (wozVersion == 1) + { + bytesUsed = val16 (rawBuffer, ptr + DATA_SIZE); + bitCount = val16 (rawBuffer, ptr + DATA_SIZE + 2); + + if (debug) + System.out.println ( + (String.format ("Bytes: %2d, Bits: %,8d%n%n", bytesUsed, bitCount))); + } + else + { + startingBlock = val16 (rawBuffer, ptr); + blockCount = val16 (rawBuffer, ptr + 2); + bitCount = val32 (rawBuffer, ptr + 4); + + if (debug) + System.out.println ((String.format ("Start: %4d, Blocks: %2d, Bits: %,8d%n%n", + startingBlock, blockCount, bitCount))); + } + + if (bitCount == 0) + return; + + resetIndex (); + + if (addressPrologue == null) // WOZ1 + if (findNext (address16prologue, ptr) > 0) + setGlobals (16); + else if (findNext (address13prologue, ptr) > 0) + setGlobals (13); + else + throw new DiskNibbleException ("No address prologue found"); + + int offset = -1; + + while (sectors.size () < diskSectors) + { + offset = findNext (addressPrologue, offset + 1); + if (offset < 0) + break; + + Sector sector = new Sector (this, offset); + if (sectors.size () > 0) + checkDuplicates (sector); + sectors.add (sector); + } + } + + // ---------------------------------------------------------------------------------// + private void checkDuplicates (Sector newSector) + // ---------------------------------------------------------------------------------// + { + for (Sector sector : sectors) + if (sector.isDuplicate (newSector)) + System.out.println ("\n*** duplicate ***\n"); + } + + // ---------------------------------------------------------------------------------// + private void resetIndex () + // ---------------------------------------------------------------------------------// + { + trackIndex = 0; + bitIndex = 0; + + if (wozVersion == 1) + byteIndex = 256 + trackNo * TRK_SIZE; + else + byteIndex = startingBlock * BLOCK_SIZE; + } + + // ---------------------------------------------------------------------------------// + boolean nextBit () + // ---------------------------------------------------------------------------------// + { + boolean bit = (rawBuffer[byteIndex] & (0x80 >>> bitIndex)) != 0; + + if (++trackIndex >= bitCount) + { + ++revolutions; + resetIndex (); + } + else if (++bitIndex >= 8) + { + ++byteIndex; + bitIndex = 0; + } + + return bit; + } + + // ---------------------------------------------------------------------------------// + int nextByte () + // ---------------------------------------------------------------------------------// + { + byte b = 0; + while ((b & 0x80) == 0) + { + b <<= 1; + if (nextBit ()) + b |= 0x01; + } + + return b; + } + + // ---------------------------------------------------------------------------------// + void readTrack () + // ---------------------------------------------------------------------------------// + { + if (newBuffer != null) + return; + + int max = (bitCount - 1) / 8 + 1; + max += 520; + newBuffer = new byte[max]; + + for (int i = 0; i < max; i++) + newBuffer[i] = (byte) nextByte (); + } + + // ---------------------------------------------------------------------------------// + int findNext (byte[] key, int start) + // ---------------------------------------------------------------------------------// + { + readTrack (); + + int max = newBuffer.length - key.length; + outer: for (int ptr = start; ptr < max; ptr++) + { + for (int keyPtr = 0; keyPtr < key.length; keyPtr++) + if (newBuffer[ptr + keyPtr] != key[keyPtr]) + continue outer; + return ptr; + } + + return -1; + } + + // ---------------------------------------------------------------------------------// + void dump () + // ---------------------------------------------------------------------------------// + { + System.out.println (HexFormatter.format (newBuffer)); + } + + // ---------------------------------------------------------------------------------// + @Override + public String toString () + // ---------------------------------------------------------------------------------// + { + StringBuilder text = new StringBuilder (); + if (wozVersion == 1) + text.append (String.format ("Bytes: %2d, Bits: %,8d%n%n", bytesUsed, bitCount)); + else + text.append (String.format ("Start: %4d, Blocks: %2d, Bits: %,8d%n%n", + startingBlock, blockCount, bitCount)); + int count = 0; + for (Sector sector : sectors) + text.append (String.format ("%2d %s%n", count++, sector)); + text.deleteCharAt (text.length () - 1); + return text.toString (); + } + + // ---------------------------------------------------------------------------------// + @Override + public Iterator iterator () + // ---------------------------------------------------------------------------------// + { + return sectors.iterator (); + } + } + + // ---------------------------------------------------------------------------------// + class Sector + // ---------------------------------------------------------------------------------// + { + Track track; + int trackNo, sectorNo, volume, checksum; + int addressOffset, dataOffset; + + // ---------------------------------------------------------------------------------// + Sector (Track track, int addressOffset) + // ---------------------------------------------------------------------------------// + { + this.track = track; + + volume = decode4and4 (track.newBuffer, addressOffset + 3); + trackNo = decode4and4 (track.newBuffer, addressOffset + 5); + sectorNo = decode4and4 (track.newBuffer, addressOffset + 7); + checksum = decode4and4 (track.newBuffer, addressOffset + 9); + + this.addressOffset = addressOffset; + dataOffset = track.findNext (dataPrologue, addressOffset + 11); + if (dataOffset > addressOffset + 200) + dataOffset = -1; + } + + // ---------------------------------------------------------------------------------// + boolean isDuplicate (Sector sector) + // ---------------------------------------------------------------------------------// + { + return this.sectorNo == sector.sectorNo; + } + + // ---------------------------------------------------------------------------------// + void dump () + // ---------------------------------------------------------------------------------// + { + System.out.println (); + System.out.println (this); + System.out.println (HexFormatter.format (track.newBuffer, addressOffset, BLOCK_SIZE, + addressOffset)); + } + + // ---------------------------------------------------------------------------------// + void pack (DiskReader diskReader, byte[] buffer, int ptr) throws DiskNibbleException + // ---------------------------------------------------------------------------------// + { + byte[] decodedBuffer = diskReader.decodeSector (track.newBuffer, dataOffset + 3); + System.arraycopy (decodedBuffer, 0, buffer, ptr, decodedBuffer.length); + } + + // ---------------------------------------------------------------------------------// + @Override + public String toString () + // ---------------------------------------------------------------------------------// + { + String dataOffsetText = dataOffset < 0 ? "" : String.format ("%04X", dataOffset); + return String.format ( + "Vol: %02X Trk: %02X Sct: %02X Chk: %02X Add: %04X Dat: %s", volume, + trackNo, sectorNo, checksum, addressOffset, dataOffsetText); + } + } } diff --git a/src/com/bytezone/diskbrowser/nib/WozFileOld.java b/src/com/bytezone/diskbrowser/nib/WozFileOld.java new file mode 100644 index 0000000..e42fe64 --- /dev/null +++ b/src/com/bytezone/diskbrowser/nib/WozFileOld.java @@ -0,0 +1,360 @@ +package com.bytezone.diskbrowser.nib; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.bytezone.diskbrowser.utilities.HexFormatter; +import com.bytezone.diskbrowser.utilities.Utility; + +public class WozFileOld +{ + private static final byte[] WOZ1_FILE_HEADER = + { 0x57, 0x4F, 0x5A, 0x31, (byte) 0xFF, 0x0A, 0x0D, 0x0A }; + private static final byte[] WOZ2_FILE_HEADER = + { 0x57, 0x4F, 0x5A, 0x32, (byte) 0xFF, 0x0A, 0x0D, 0x0A }; + + private static final int TRK_SIZE = 0x1A00; + private static final int INFO_SIZE = 0x3C; + private static final int TMAP_SIZE = 0xA0; + private static final int DATA_SIZE = TRK_SIZE - 10; + + private final boolean debug = true; + private final boolean dump = true; + private int diskType; // 5.25 or 3.5 + private int wozVersion; + private int bootSectorFormat; + + public final File file; + byte[] diskBuffer; + + private final MC3470 mc3470 = new MC3470 (); + private final List nibbleTracks = new ArrayList<> (40); + + // ---------------------------------------------------------------------------------// + // constructor + // ---------------------------------------------------------------------------------// + + public WozFileOld (File file) throws DiskNibbleException + { + this.file = file; + byte[] buffer = readFile (); + boolean valid = false; + + if (matches (WOZ1_FILE_HEADER, buffer)) + wozVersion = 1; + else if (matches (WOZ2_FILE_HEADER, buffer)) + wozVersion = 2; + else + { + System.out.println (HexFormatter.format (buffer, 0, 20)); + throw new DiskNibbleException ("Header error"); + } + + int checksum1 = readInt (buffer, 8, 4); + int checksum2 = Utility.crc32 (buffer, 12, buffer.length - 12); + if (checksum1 != checksum2) + { + System.out.printf ("Stored checksum : %08X%n", checksum1); + System.out.printf ("Calculated checksum : %08X%n", checksum2); + throw new DiskNibbleException ("Checksum error"); + } + + int ptr = 12; + read: while (ptr < buffer.length) + { + String chunkId = new String (buffer, ptr, 4); + ptr += 4; + int chunkSize = readInt (buffer, ptr, 4); + ptr += 4; + + if (debug) + { + System.out.printf ("Offset : %06X%n", ptr - 8); + System.out.printf ("Chunk ID : %s%n", chunkId); + System.out.printf ("Chunk size: %,d%n", chunkSize); + } + + if ("INFO".equals (chunkId)) + { + if (debug) + { + int diskType = buffer[ptr + 1] & 0xFF; + String diskTypeText = diskType == 1 ? "5.25" : diskType == 2 ? "3.5" : "??"; + + System.out.println (); + System.out.printf ("Version ........... %02X%n", buffer[ptr]); + System.out.printf ("Disk type ......... %02X %s%n", diskType, diskTypeText); + System.out.printf ("Write protected ... %02X%n", buffer[ptr + 2]); + System.out.printf ("Synchronised ...... %02X%n", buffer[ptr + 3]); + System.out.printf ("Cleaned ........... %02X%n", buffer[ptr + 4]); + System.out.printf ("Creator ........... %s%n", + new String (buffer, ptr + 5, 32).trim ()); + + if (wozVersion > 1) + { + int bootFormat = buffer[ptr + 38] & 0xFF; + String bootFormatText = bootFormat == 1 ? "16 sector" + : bootFormat == 2 ? "13 sector" : bootFormat == 3 ? "Both" : "??"; + System.out.printf ("Disk sides ........ %02X%n", buffer[ptr + 37]); + System.out.printf ("Boot format ....... %02X %s%n", bootFormat, + bootFormatText); + System.out.printf ("Optimal timing .... %02X%n", buffer[ptr + 39]); + System.out.printf ("Compatible flags .. %04X%n", + readInt (buffer, ptr + 40, 2)); + System.out.printf ("Minimum RAM ....... %04X%n", + readInt (buffer, ptr + 42, 2)); + System.out.printf ("Largest track ..... %04X%n", + readInt (buffer, ptr + 44, 2)); + } + System.out.println (); + } + + diskType = buffer[ptr + 1] & 0xFF; + if (wozVersion > 1) + bootSectorFormat = buffer[ptr + 38] & 0xFF; + + ptr += INFO_SIZE; + } + else if ("TMAP".equals (chunkId)) + { + if (debug) + { + for (int track = 0; track < 40; track++) + { + for (int qtr = 0; qtr < 4; qtr++) + System.out.printf ("%02X ", buffer[ptr++]); + System.out.println (); + } + System.out.println (); + } + else + ptr += TMAP_SIZE; + } + else if ("TRKS".equals (chunkId)) + { + if (debug) + { + System.out.println ("***********************************************"); + System.out.printf ("* Disk ......... %s%n", file.getName ()); + System.out.println ("***********************************************"); + } + + if (wozVersion == 1) + { + int tracks = chunkSize / TRK_SIZE; + + for (int trackNo = 0; trackNo < tracks; trackNo++) + { + int bytesUsed = readInt (buffer, ptr + DATA_SIZE, 2); + int bitCount = readInt (buffer, ptr + DATA_SIZE + 2, 2); + + if (debug) + { + System.out.println ("***************************************"); + System.out.printf ("* Track ......... %,6d of %,6d *%n", trackNo, + tracks); + System.out.printf ("* Bytes used .... %,6d *%n", bytesUsed); + System.out.printf ("* Bit count .... %,6d *%n", bitCount); + System.out.println ("***************************************"); + } + + try + { + // nibbleTracks.add (mc3470.getNibbleTrack (buffer, ptr, bytesUsed, bitCount)); + List diskSectors = + mc3470.readTrack (buffer, ptr, bytesUsed, bitCount); + + if (trackNo == 0) // create disk buffer + { + if (mc3470.is13Sector ()) + diskBuffer = new byte[35 * 13 * 256]; + else if (mc3470.is16Sector ()) + diskBuffer = new byte[35 * 16 * 256]; + else + { + System.out.println ("unknown disk format"); + break read; + } + } + + mc3470.storeSectors (diskSectors, diskBuffer); + } + catch (Exception e) + { + System.out.println (e); + break read; + } + + ptr += TRK_SIZE; + } + } + else + { + diskBuffer = new byte[(bootSectorFormat == 2 ? 13 : 16) * 35 * 256]; + + for (int trackNo = 0; trackNo < 160; trackNo++) + { + int p = 256 + trackNo * 8; + int startingBlock = readInt (buffer, p, 2); + int blockCount = readInt (buffer, p + 2, 2); + int bitCount = readInt (buffer, p + 4, 4); + + if (debug) + { + System.out.println ("******************************"); + System.out.printf ("* Track ......... %,6d *%n", trackNo); + System.out.printf ("* Start block ... %,6d *%n", startingBlock); + System.out.printf ("* Block count ... %,6d *%n", blockCount); + System.out.printf ("* Bit count .... %,6d *%n", bitCount); + System.out.println ("******************************"); + } + + if (startingBlock == 0) + break; + + try + { + // nibbleTracks.add (mc3470.getNibbleTrack (buffer, ptr, bytesUsed, bitCount)); + List diskSectors = mc3470.readTrack (buffer, + startingBlock * 512, blockCount * 512, bitCount); + + for (RawDiskSector rawDiskSector : diskSectors) + { + System.out.println (rawDiskSector); + rawDiskSector.dump (); + } + + mc3470.storeSectors (diskSectors, diskBuffer); + } + catch (Exception e) + { + System.out.println (e); + break read; + } + } + ptr += chunkSize; + } + } + else if ("META".equals (chunkId)) + { + // System.out.printf ("[%s] %08X%n", chunkId, chunkSize); + // System.out.println (HexFormatter.format (buffer, ptr, chunkSize)); + ptr += chunkSize; + } + else + { + System.out.printf ("Unknown %08X%n", chunkSize); + ptr += chunkSize; + } + } + + // if (!valid) + // readNibbleTracks (buffer); + } + + // ---------------------------------------------------------------------------------// + // readNibbleTracks + // ---------------------------------------------------------------------------------// + + private void readNibbleTracks (byte[] buffer) + { + for (int track = 0; track < 35; track++) + { + int ptr = track * 6656 + 256; + + int bytesUsed = readInt (buffer, ptr + DATA_SIZE, 2); + int bitCount = readInt (buffer, ptr + DATA_SIZE + 2, 2); + + NibbleTrack nibbleTrack = mc3470.getNibbleTrack (buffer, ptr, bytesUsed, bitCount); + nibbleTracks.add (nibbleTrack); + } + } + + // ---------------------------------------------------------------------------------// + // getSectorsPerTrack + // ---------------------------------------------------------------------------------// + + public int getSectorsPerTrack () + { + return mc3470.is13Sector () ? 13 : mc3470.is16Sector () ? 16 : 0; + } + + // ---------------------------------------------------------------------------------// + // readInt + // ---------------------------------------------------------------------------------// + + private int readInt (byte[] buffer, int offset, int length) + { + int shift = 0; + int value = 0; + for (int i = 0; i < length; i++) + { + value |= (buffer[offset + i] & 0xFF) << shift; + shift += 8; + } + return value; + } + + // ---------------------------------------------------------------------------------// + // getDiskBuffer + // ---------------------------------------------------------------------------------// + + public byte[] getDiskBuffer () + { + return diskBuffer; + } + + // ---------------------------------------------------------------------------------// + // readFile + // ---------------------------------------------------------------------------------// + + private byte[] readFile () + { + try + { + BufferedInputStream in = new BufferedInputStream (new FileInputStream (file)); + byte[] buffer = in.readAllBytes (); + in.close (); + return buffer; + } + catch (IOException e) + { + e.printStackTrace (); + return null; + } + } + + void dump (int trackNo) + { + + } + + // ---------------------------------------------------------------------------------// + // matches + // ---------------------------------------------------------------------------------// + + private boolean matches (byte[] b1, byte[] b2) + { + for (int i = 0; i < b1.length; i++) + if (b1[i] != b2[i]) + return false; + return true; + } + + public static void main (String[] args) + { + File file = new File ("/Users/denismolony/code/python/wozardry-2.0/bill.woz"); + try + { + new WozFileOld (file); + } + catch (DiskNibbleException e) + { + e.printStackTrace (); + } + } +}