diff --git a/src/com/bytezone/diskbrowser/disk/NibDisk.java b/src/com/bytezone/diskbrowser/disk/NibDisk.java index 87e040d..0edb640 100644 --- a/src/com/bytezone/diskbrowser/disk/NibDisk.java +++ b/src/com/bytezone/diskbrowser/disk/NibDisk.java @@ -18,19 +18,31 @@ public class NibDisk // .nib files are 232,960 bytes // 6,656 bytes x 35 tracks (0x1A00) + // add 'nib' to TreeBuilder to allow nib files to be selected + public NibDisk (File file) { this.file = file; - byte[] buffer = new byte[6656]; + byte[] trackBuffer = new byte[6656]; try { - byte[] diskBuffer = new byte[10]; BufferedInputStream in = new BufferedInputStream (new FileInputStream (file)); + byte[] test = { (byte) 0xD5, (byte) 0xAA, (byte) 0xB5 }; for (int i = 0; i < 35; i++) { - in.read (buffer); - // System.out.println (HexFormatter.format (buffer)); + in.read (trackBuffer); + // System.out.println (HexFormatter.format (trackBuffer)); + int offset = 0; + while (true) + { + offset = nibbler.findBytes (trackBuffer, offset, test); + if (offset < 0) + break; + System.out.printf ("found at %04X%n", offset); + ++offset; + } + break; // just examine the first track } in.close (); diff --git a/src/com/bytezone/diskbrowser/disk/Nibblizer.java b/src/com/bytezone/diskbrowser/disk/Nibblizer.java index cd780e4..58f07cb 100644 --- a/src/com/bytezone/diskbrowser/disk/Nibblizer.java +++ b/src/com/bytezone/diskbrowser/disk/Nibblizer.java @@ -2,9 +2,9 @@ package com.bytezone.diskbrowser.disk; public class Nibblizer { - private static byte[] addressPrologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0x96 }; - private static byte[] dataPrologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0xAD }; - private static byte[] epilogue = { (byte) 0xDE, (byte) 0xAA, (byte) 0xEB }; + static byte[] addressPrologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0x96 }; + static byte[] dataPrologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0xAD }; + static byte[] epilogue = { (byte) 0xDE, (byte) 0xAA, (byte) 0xEB }; private static byte[] writeTranslateTable = { (byte) 0x96, (byte) 0x97, (byte) 0x9A, (byte) 0x9B, (byte) 0x9D, (byte) 0x9E, @@ -92,7 +92,7 @@ public class Nibblizer public Nibblizer () { - if (false) + if (false) // test with the Beneath Apple Prodos example { byte[] testBuffer = decode6and2 (encode6and2 (xor), 0); @@ -104,24 +104,24 @@ public class Nibblizer } } - public AddressField getAddressField (byte[] buffer, int offset) + AddressField getAddressField (byte[] buffer, int offset) { return new AddressField (buffer, offset); } - public DataField getDataField (byte[] buffer, int offset) + DataField getDataField (byte[] buffer, int offset) { return new DataField (buffer, offset); } - int decode4and4 (byte[] buffer, int offset) + private int decode4and4 (byte[] buffer, int offset) { int odds = ((buffer[offset] & 0xFF) << 1) + 1; int evens = buffer[offset + 1] & 0xFF; return odds & evens; } - byte[] decode6and2 (byte[] buffer, int offset) + private byte[] decode6and2 (byte[] buffer, int offset) { for (int i = 0; i < decode1.length; i++) { @@ -168,7 +168,7 @@ public class Nibblizer return decodedBuffer; } - byte[] encode6and2 (byte[] buffer) + private byte[] encode6and2 (byte[] buffer) { byte[] encodedBuffer = new byte[343]; @@ -210,6 +210,40 @@ public class Nibblizer return bits == 1 ? 2 : bits == 2 ? 1 : bits; } + int skipBytes (byte[] buffer, int offset, byte skipValue) + { + int count = 0; + while (offset < buffer.length && buffer[offset++] == skipValue) + ++count; + return count; + } + + private String listBytes (byte[] buffer, int offset, int length) + { + StringBuilder text = new StringBuilder (); + + int max = Math.min (length + offset, buffer.length); + while (offset < max) + text.append (String.format ("%02X ", buffer[offset++])); + + return text.toString (); + } + + int findBytes (byte[] buffer, int offset, byte[] valueBuffer) + { + int length = valueBuffer.length; + int ptr = offset + length; + + while (ptr < buffer.length) + { + if (matchBytes (buffer, ptr - length, valueBuffer)) + return ptr - length; + ++ptr; + } + + return -1; + } + private boolean matchBytes (byte[] buffer, int offset, byte[] valueBuffer) { for (int i = 0; i < valueBuffer.length; i++) @@ -222,28 +256,6 @@ public class Nibblizer return true; } - int skipBytes (byte[] buffer, int offset, byte skipValue) - { - int count = 0; - while (offset < buffer.length && buffer[offset++] == skipValue) - ++count; - return count; - } - - int listBytes (byte[] buffer, int offset, int length) - { - int count = 0; - for (int i = 0; i < length; i++) - { - if (offset >= buffer.length) - break; - System.out.printf ("%02X ", buffer[offset++]); - ++count; - } - - return count; - } - abstract class Field { protected boolean valid; @@ -287,10 +299,7 @@ public class Nibblizer valid = true; } else - { - listBytes (buffer, offset, 14); - System.out.println (); - } + System.out.println (listBytes (buffer, offset, 14)); length = 14; } @@ -298,6 +307,8 @@ public class Nibblizer class DataField extends Field { + byte[] dataBuffer; + public DataField (byte[] buffer, int offset) { super (buffer, offset); @@ -305,18 +316,17 @@ public class Nibblizer if (matchBytes (buffer, offset, dataPrologue)) { valid = true; + dataBuffer = decode6and2 (buffer, offset + 3); if (!matchBytes (buffer, offset + 346, epilogue)) { System.out.print (" bad data epilogue: "); - listBytes (buffer, offset + 346, 3); - System.out.println (); + System.out.println (listBytes (buffer, offset + 346, 3)); } } else { System.out.print (" bad data prologue: "); - listBytes (buffer, offset, 3); - System.out.println (); + System.out.println (listBytes (buffer, offset, 3)); } length = 349; diff --git a/src/com/bytezone/diskbrowser/disk/V2dDisk.java b/src/com/bytezone/diskbrowser/disk/V2dDisk.java index 10788a7..00ff0f6 100644 --- a/src/com/bytezone/diskbrowser/disk/V2dDisk.java +++ b/src/com/bytezone/diskbrowser/disk/V2dDisk.java @@ -37,14 +37,16 @@ public class V2dDisk private static int[][] interleave = { { 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 }, { 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 } }; + private static final int DOS = 0; private static final int PRODOS = 1; + private static final int TRACK_LENGTH = 6304; + private final Nibblizer nibbler = new Nibblizer (); final File file; final int tracks; - // int actualTracks; final byte[] buffer = new byte[4096 * 35]; @@ -52,6 +54,7 @@ public class V2dDisk { this.file = file; int tracks = 0; + try { byte[] diskBuffer = new byte[10]; @@ -65,21 +68,24 @@ public class V2dDisk assert diskLength + 8 == file.length (); assert "D5NI".equals (id); + byte[] trackHeader = new byte[4]; + byte[] trackData = new byte[TRACK_LENGTH]; + for (int i = 0; i < tracks; i++) { - byte[] trackHeader = new byte[4]; in.read (trackHeader); int trackNumber = HexFormatter.getShortBigEndian (trackHeader, 0); int trackLength = HexFormatter.getShortBigEndian (trackHeader, 2); // 6304 + assert trackLength == TRACK_LENGTH; + + int dataRead = in.read (trackData); + assert dataRead == TRACK_LENGTH; + int fullTrackNo = trackNumber / 4; int halfTrackNo = trackNumber % 4; - byte[] trackData = new byte[trackLength]; - in.read (trackData); - - // only process full tracks - if (halfTrackNo == 0) + if (halfTrackNo == 0) // only process full tracks processTrack (fullTrackNo, trackData, buffer); else System.out.printf ("%s skipping half track %02X / %02X%n", file.getName (), @@ -115,23 +121,17 @@ public class V2dDisk if (!addressField.isValid ()) return false; + assert addressField.track == trackNo; + ptr += addressField.size (); ptr += nibbler.skipBytes (buffer, ptr, (byte) 0xFF); // gap2 DataField dataField = nibbler.getDataField (buffer, ptr); if (!dataField.isValid ()) - { - System.out.printf ("skipping data %02X / %02X%n", addressField.track, - addressField.sector); return false; - } - - // System.out.printf ("decoding track %02X / %02X%n", addressField.track, - // addressField.sector); - byte[] decodedBuffer = nibbler.decode6and2 (buffer, ptr + 3); int offset = addressField.track * 4096 + interleave[DOS][addressField.sector] * 256; - System.arraycopy (decodedBuffer, 0, diskBuffer, offset, 256); + System.arraycopy (dataField.dataBuffer, 0, diskBuffer, offset, 256); ptr += dataField.size (); ptr += nibbler.skipBytes (buffer, ptr, (byte) 0xFF); // gap3 diff --git a/src/com/bytezone/diskbrowser/gui/TreeBuilder.java b/src/com/bytezone/diskbrowser/gui/TreeBuilder.java index f186288..5bc92d6 100755 --- a/src/com/bytezone/diskbrowser/gui/TreeBuilder.java +++ b/src/com/bytezone/diskbrowser/gui/TreeBuilder.java @@ -26,7 +26,7 @@ public class TreeBuilder private static SimpleDateFormat sdf = new SimpleDateFormat ("dd MMM yyyy"); private static final boolean FULL_TREE = false; private static final List suffixes = - Arrays.asList ("po", "dsk", "do", "hdv", "2mg", "v2d", "d13", "sdk", "gz"); + Arrays.asList ("po", "dsk", "do", "hdv", "2mg", "v2d", "nib", "d13", "sdk", "gz"); FileComparator fc = new FileComparator (); JTree tree;