From 6eb4acc85da853980c862385105de7e871edd6cc Mon Sep 17 00:00:00 2001 From: Denis Molony Date: Sun, 12 Aug 2018 17:16:03 +1000 Subject: [PATCH] nibbling --- .../diskbrowser/disk/ByteTranslator5and3.java | 5 +- .../diskbrowser/disk/ByteTranslator6and2.java | 4 +- .../diskbrowser/disk/DiskAddressField.java | 14 +- .../bytezone/diskbrowser/disk/DiskReader.java | 2 +- .../diskbrowser/disk/DiskReader13Sector.java | 11 +- .../diskbrowser/disk/DiskReader16Sector.java | 23 ++-- src/com/bytezone/diskbrowser/disk/MC3470.java | 125 ++++++++++++------ .../bytezone/diskbrowser/disk/WozDisk.java | 21 ++- 8 files changed, 127 insertions(+), 78 deletions(-) diff --git a/src/com/bytezone/diskbrowser/disk/ByteTranslator5and3.java b/src/com/bytezone/diskbrowser/disk/ByteTranslator5and3.java index 74dee84..c5cce10 100644 --- a/src/com/bytezone/diskbrowser/disk/ByteTranslator5and3.java +++ b/src/com/bytezone/diskbrowser/disk/ByteTranslator5and3.java @@ -57,11 +57,10 @@ public class ByteTranslator5and3 extends ByteTranslator { int val = (b & 0xFF) - 0xAB; // 0 - 84 if (val < 0 || val > 84) - throw new DiskNibbleException ("Val: " + val); + throw new DiskNibbleException ("5&3 val: " + val); byte trans = (byte) (readTranslateTable5and3[val] - 1); // 0 - 31 (5 bits) if (trans < 0 || trans > 31) - throw new DiskNibbleException ("Trans: " + trans); + throw new DiskNibbleException ("5&3 trans: " + trans); return trans; } - } diff --git a/src/com/bytezone/diskbrowser/disk/ByteTranslator6and2.java b/src/com/bytezone/diskbrowser/disk/ByteTranslator6and2.java index c605a83..6dbcf29 100644 --- a/src/com/bytezone/diskbrowser/disk/ByteTranslator6and2.java +++ b/src/com/bytezone/diskbrowser/disk/ByteTranslator6and2.java @@ -47,10 +47,10 @@ public class ByteTranslator6and2 extends ByteTranslator { int val = (b & 0xFF) - 0x96; // 0 - 105 if (val < 0 || val > 105) - throw new DiskNibbleException ("Val: " + val); + throw new DiskNibbleException ("6&2 val: " + val); byte trans = (byte) (readTranslateTable6and2[val] - 1); // 0 - 63 (6 bits) if (trans < 0 || trans > 63) - throw new DiskNibbleException ("Trans: " + trans); + throw new DiskNibbleException ("6&2 trans: " + trans); return trans; } } diff --git a/src/com/bytezone/diskbrowser/disk/DiskAddressField.java b/src/com/bytezone/diskbrowser/disk/DiskAddressField.java index a1ff083..ad2bf14 100644 --- a/src/com/bytezone/diskbrowser/disk/DiskAddressField.java +++ b/src/com/bytezone/diskbrowser/disk/DiskAddressField.java @@ -8,21 +8,21 @@ class DiskAddressField // constructor // ---------------------------------------------------------------------------------// - DiskAddressField (byte[] buffer, int offset) + DiskAddressField (byte[] buffer) { - volume = decode4and4 (buffer, offset); - track = decode4and4 (buffer, offset + 2); - sector = decode4and4 (buffer, offset + 4); - checksum = decode4and4 (buffer, offset + 6); + volume = decode4and4 (buffer, 0); + track = decode4and4 (buffer, 2); + sector = decode4and4 (buffer, 4); + checksum = decode4and4 (buffer, 6); } // ---------------------------------------------------------------------------------// // decode4and4 // ---------------------------------------------------------------------------------// - int decode4and4 (byte[] buffer, int offset) + private int decode4and4 (byte[] buffer, int offset) { - int odds = ((buffer[offset] & 0xFF) << 1) + 1; + int odds = ((buffer[offset] & 0xFF) << 1) | 0x01; int evens = buffer[offset + 1] & 0xFF; return odds & evens; } diff --git a/src/com/bytezone/diskbrowser/disk/DiskReader.java b/src/com/bytezone/diskbrowser/disk/DiskReader.java index 77ca203..7c5a7ed 100644 --- a/src/com/bytezone/diskbrowser/disk/DiskReader.java +++ b/src/com/bytezone/diskbrowser/disk/DiskReader.java @@ -23,7 +23,7 @@ public abstract class DiskReader // abstract functions // ---------------------------------------------------------------------------------// - abstract byte[] decodeSector (byte[] buffer, int ptr); + abstract byte[] decodeSector (byte[] buffer); abstract byte[] encodeSector (byte[] buffer); diff --git a/src/com/bytezone/diskbrowser/disk/DiskReader13Sector.java b/src/com/bytezone/diskbrowser/disk/DiskReader13Sector.java index 790f146..4610849 100644 --- a/src/com/bytezone/diskbrowser/disk/DiskReader13Sector.java +++ b/src/com/bytezone/diskbrowser/disk/DiskReader13Sector.java @@ -10,7 +10,7 @@ public class DiskReader13Sector extends DiskReader private final byte[] decodeA = new byte[BUFFER_WITH_CHECKSUM_SIZE]; private final byte[] decodeB = new byte[RAW_BUFFER_SIZE]; - private final ByteTranslator byteTranslator53 = new ByteTranslator5and3 (); + private final ByteTranslator byteTranslator = new ByteTranslator5and3 (); // ---------------------------------------------------------------------------------// // constructor @@ -26,15 +26,16 @@ public class DiskReader13Sector extends DiskReader // ---------------------------------------------------------------------------------// @Override - byte[] decodeSector (byte[] buffer, int offset) + byte[] decodeSector (byte[] buffer) { byte[] decodedBuffer = new byte[BLOCK_SIZE]; + int offset = 0; try { // convert legal disk values to actual 5 bit values for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE; i++) // 411 bytes - decodeA[i] = (byte) (byteTranslator53.decode (buffer[offset++]) << 3); + decodeA[i] = (byte) (byteTranslator.decode (buffer[offset++]) << 3); // reconstruct 410 bytes each with 5 bits byte chk = 0; @@ -75,11 +76,11 @@ public class DiskReader13Sector extends DiskReader } // add last byte - decodedBuffer[ptr] = - (byte) (decodeB[255] | ((decodeB[409] & 0x3F) >>> 3)); + decodedBuffer[ptr] = (byte) (decodeB[255] | ((decodeB[409] & 0x3F) >>> 3)); } catch (Exception e) { + // e.printStackTrace (); System.out.println (e); } diff --git a/src/com/bytezone/diskbrowser/disk/DiskReader16Sector.java b/src/com/bytezone/diskbrowser/disk/DiskReader16Sector.java index 86a0c5e..69a54aa 100644 --- a/src/com/bytezone/diskbrowser/disk/DiskReader16Sector.java +++ b/src/com/bytezone/diskbrowser/disk/DiskReader16Sector.java @@ -13,7 +13,7 @@ public class DiskReader16Sector extends DiskReader private final byte[] encodeA = new byte[RAW_BUFFER_SIZE]; private final byte[] encodeB = new byte[BUFFER_WITH_CHECKSUM_SIZE]; - private final ByteTranslator byteTranslator62 = new ByteTranslator6and2 (); + private final ByteTranslator byteTranslator = new ByteTranslator6and2 (); private static int[] interleave = { 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 }; @@ -32,29 +32,21 @@ public class DiskReader16Sector extends DiskReader // ---------------------------------------------------------------------------------// @Override - byte[] decodeSector (byte[] buffer, int offset) + byte[] decodeSector (byte[] buffer) { // rearrange 342 bytes into 256 - byte[] decodedBuffer = new byte[BLOCK_SIZE]; // 256 bytes + byte[] decodedBuffer = new byte[BLOCK_SIZE]; // 256 bytes + int offset = 0; try { - if (offset + BUFFER_WITH_CHECKSUM_SIZE >= buffer.length) - throw new DiskNibbleException ( - String.format ("Buffer not long enough (need %d, found %d)", - BUFFER_WITH_CHECKSUM_SIZE, buffer.length - offset)); - // convert legal disk values to actual 6 bit values for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE; i++) // 343 bytes - { - if (offset == buffer.length) - offset = 0; - decodeA[i] = (byte) (byteTranslator62.decode (buffer[offset++]) << 2); - } + decodeA[i] = (byte) (byteTranslator.decode (buffer[offset++]) << 2); // reconstruct 342 bytes each with 6 bits byte chk = 0; - for (int i = decodeB.length - 1; i >= 0; i--) // 342 bytes + for (int i = decodeB.length - 1; i >= 0; i--) // 342 bytes chk = decodeB[i] = (byte) (decodeA[i + 1] ^ chk); if ((chk ^ decodeA[0]) != 0) throw new DiskNibbleException ("Checksum failed"); @@ -78,6 +70,7 @@ public class DiskReader16Sector extends DiskReader catch (Exception e) { System.out.println (e); + // e.printStackTrace (); } return decodedBuffer; @@ -124,7 +117,7 @@ public class DiskReader16Sector extends DiskReader // remove two bits and convert to translated bytes for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE; i++) - encodedBuffer[i] = byteTranslator62.encode (encodeB[i]); + encodedBuffer[i] = byteTranslator.encode (encodeB[i]); return encodedBuffer; } diff --git a/src/com/bytezone/diskbrowser/disk/MC3470.java b/src/com/bytezone/diskbrowser/disk/MC3470.java index 1d29f40..4ae9e84 100644 --- a/src/com/bytezone/diskbrowser/disk/MC3470.java +++ b/src/com/bytezone/diskbrowser/disk/MC3470.java @@ -3,21 +3,27 @@ package com.bytezone.diskbrowser.disk; import java.util.ArrayList; import java.util.List; +import com.bytezone.diskbrowser.utilities.HexFormatter; + class MC3470 { + private static final int EMPTY = 999; private final boolean debug = false; + private final boolean dump = false; private final List diskSectors = new ArrayList<> (); private State currentState; private DiskSector currentDiskSector; private int expectedDataSize; + private boolean finished; + private boolean restarted; private DiskReader diskReader; private final DiskReader diskReader16 = new DiskReader16Sector (); private final DiskReader diskReader13 = new DiskReader13Sector (); - private final byte[] dataBuffer = new byte[500]; + private final byte[] dataBuffer = new byte[EMPTY]; private int dataPtr = 0; private enum State @@ -38,17 +44,22 @@ class MC3470 diskSectors.clear (); currentDiskSector = null; currentState = State.OTHER; - expectedDataSize = 200; + expectedDataSize = EMPTY; + finished = false; + restarted = false; int value = 0; + dataPtr = 0; if (debug) { System.out.printf ("%nOffset : %06X%n", offset); System.out.printf ("Bytes used: %06X%n", bytesUsed); + System.out.printf ("Bit count : %06X%n", bitCount); + System.out.printf ("remaining : %06X%n", bitCount % 8); } - int inPtr = offset; - while (inPtr < max) + int inPtr = offset; // keep offset in case we have to loop around + while (!finished && inPtr < max) { int b = buffer[inPtr++] & 0xFF; for (int mask = 0x80; mask != 0; mask >>>= 1) @@ -57,29 +68,36 @@ class MC3470 if ((b & mask) != 0) value |= 1; - ++totalBits; - if ((value & 0x80) != 0) // is hi-bit set? { + if (dump) + { + if (dataPtr % 16 == 0) + System.out.printf ("%n%04X: ", dataPtr); + System.out.printf ("%02X ", value); + } + dataBuffer[dataPtr++] = (byte) value; checkState (value); value = 0; } + + if (++totalBits == bitCount) + break; } - if (inPtr == max && currentState == State.DATA) + + if (inPtr == max && currentState == State.DATA && !restarted) { - System.out.println ("Unfinished business"); + inPtr = offset; + restarted = true; } } - // if (bytesUsed > outputBuffer.length) - // { - // System.out.printf ("Bytes used %,5d%n", bytesUsed); - // System.out.printf ("Buffer size %,5d%n", outPtr); - // } - - if (value != 0) - System.out.printf ("********** Value not used: %01X%n", value); + if (debug) + { + System.out.printf ("total bits : %d%n", bitCount); + System.out.printf ("bits used : %d%n", totalBits); + } } // ---------------------------------------------------------------------------------// @@ -148,7 +166,7 @@ class MC3470 if (dataPtr == expectedDataSize) { if (currentState == State.OTHER) - throw new DiskNibbleException ("No address or data prologues found"); + throw new DiskNibbleException ("No address or data blocks found"); setState (State.OTHER); } } @@ -161,40 +179,67 @@ class MC3470 { if (currentState == newState && currentState == State.OTHER) return; - assert currentState != newState; + assert currentState != newState : currentState + " -> " + newState; switch (currentState) // this state is now finished { case ADDRESS: - currentDiskSector = new DiskSector (new DiskAddressField (dataBuffer, 0)); + currentDiskSector = new DiskSector (new DiskAddressField (dataBuffer)); + if (dump) + System.out.println (currentDiskSector); break; case DATA: - currentDiskSector.setBuffer (diskReader.decodeSector (dataBuffer, 0)); - diskSectors.add (currentDiskSector); + if (currentDiskSector != null) + { + currentDiskSector.setBuffer (diskReader.decodeSector (dataBuffer)); + diskSectors.add (currentDiskSector); + currentDiskSector = null; + if (diskSectors.size () == diskReader.sectorsPerTrack) + finished = true; + } + else + { + if (debug) + { + System.out.printf ("cannot store %d DATA no ADDRESS", dataPtr); + System.out.println (HexFormatter.format (dataBuffer, 0, dataPtr)); + } + } break; case OTHER: break; } + switch (newState) // this state is now starting + { + case ADDRESS: + if (dump) + System.out.print ("ADDRESS "); + expectedDataSize = 8; + break; + + case DATA: + if (dump) + System.out.println ("DATA"); + if (debug && currentDiskSector == null) + { + System.out.println ("starting DATA with no ADDRESS"); + System.out.println (HexFormatter.format (dataBuffer, 0, dataPtr)); + } + expectedDataSize = diskReader.expectedDataSize (); + break; + + case OTHER: + if (dump) + System.out.println ("OTHER"); + expectedDataSize = EMPTY; // what is the maximum filler? + break; + } + currentState = newState; dataPtr = 0; // start collecting new buffer - - switch (currentState) // this state is now starting - { - case ADDRESS: - expectedDataSize = 8; - break; - - case DATA: - expectedDataSize = diskReader.expectedDataSize (); - break; - - case OTHER: - expectedDataSize = 200; // what is the maximum filler? - break; - } } // ---------------------------------------------------------------------------------// @@ -203,7 +248,9 @@ class MC3470 private boolean isPrologue () { - return dataPtr >= 3 && dataBuffer[dataPtr - 3] == (byte) 0xD5 + return dataPtr >= 3 + && (dataBuffer[dataPtr - 3] == (byte) 0xD5 + || dataBuffer[dataPtr - 3] == (byte) 0xD4) // non-standard && dataBuffer[dataPtr - 2] == (byte) 0xAA; } @@ -213,7 +260,9 @@ class MC3470 private boolean isEpilogue () { - return dataPtr >= 3 && dataBuffer[dataPtr - 3] == (byte) 0xDE + return dataPtr >= 3 + && (dataBuffer[dataPtr - 3] == (byte) 0xDE + || dataBuffer[dataPtr - 3] == (byte) 0xDA) // non-standard && dataBuffer[dataPtr - 2] == (byte) 0xAA; } diff --git a/src/com/bytezone/diskbrowser/disk/WozDisk.java b/src/com/bytezone/diskbrowser/disk/WozDisk.java index d13235c..f0af30b 100644 --- a/src/com/bytezone/diskbrowser/disk/WozDisk.java +++ b/src/com/bytezone/diskbrowser/disk/WozDisk.java @@ -5,7 +5,6 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.Utility; class WozDisk @@ -87,7 +86,11 @@ class WozDisk else if ("TRKS".equals (chunkId)) { if (debug) - System.out.println ("Reading TRKS"); + { + System.out.println ("***************************************"); + System.out.printf ("* Disk ......... %s%n", file.getName ()); + System.out.println ("***************************************"); + } int tracks = chunkSize / TRK_SIZE; for (int trackNo = 0; trackNo < tracks; trackNo++) @@ -97,8 +100,11 @@ class WozDisk if (debug) { - System.out.printf ("Bytes used .... %,6d%n", bytesUsed); - System.out.printf ("Bit count .... %,6d%n", bitCount); + System.out.println ("******************************"); + System.out.printf ("* Track ......... %,6d *%n", trackNo); + System.out.printf ("* Bytes used .... %,6d *%n", bytesUsed); + System.out.printf ("* Bit count .... %,6d *%n", bitCount); + System.out.println ("******************************"); } try @@ -115,6 +121,7 @@ class WozDisk { System.out.println ("unknown disk format"); break read; + // continue; } } @@ -124,7 +131,7 @@ class WozDisk { // e.printStackTrace (); System.out.println (e); - break read; + // break read; } ptr += TRK_SIZE; @@ -132,8 +139,8 @@ class WozDisk } else if ("META".equals (chunkId)) { - System.out.printf ("[%s] %08X%n", chunkId, chunkSize); - System.out.println (HexFormatter.format (buffer, ptr, chunkSize)); + // System.out.printf ("[%s] %08X%n", chunkId, chunkSize); + // System.out.println (HexFormatter.format (buffer, ptr, chunkSize)); ptr += chunkSize; } else