This commit is contained in:
Denis Molony 2018-08-12 17:16:03 +10:00
parent dc319ebb97
commit 6eb4acc85d
8 changed files with 127 additions and 78 deletions

View File

@ -57,11 +57,10 @@ public class ByteTranslator5and3 extends ByteTranslator
{ {
int val = (b & 0xFF) - 0xAB; // 0 - 84 int val = (b & 0xFF) - 0xAB; // 0 - 84
if (val < 0 || val > 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) byte trans = (byte) (readTranslateTable5and3[val] - 1); // 0 - 31 (5 bits)
if (trans < 0 || trans > 31) if (trans < 0 || trans > 31)
throw new DiskNibbleException ("Trans: " + trans); throw new DiskNibbleException ("5&3 trans: " + trans);
return trans; return trans;
} }
} }

View File

@ -47,10 +47,10 @@ public class ByteTranslator6and2 extends ByteTranslator
{ {
int val = (b & 0xFF) - 0x96; // 0 - 105 int val = (b & 0xFF) - 0x96; // 0 - 105
if (val < 0 || val > 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) byte trans = (byte) (readTranslateTable6and2[val] - 1); // 0 - 63 (6 bits)
if (trans < 0 || trans > 63) if (trans < 0 || trans > 63)
throw new DiskNibbleException ("Trans: " + trans); throw new DiskNibbleException ("6&2 trans: " + trans);
return trans; return trans;
} }
} }

View File

@ -8,21 +8,21 @@ class DiskAddressField
// constructor // constructor
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
DiskAddressField (byte[] buffer, int offset) DiskAddressField (byte[] buffer)
{ {
volume = decode4and4 (buffer, offset); volume = decode4and4 (buffer, 0);
track = decode4and4 (buffer, offset + 2); track = decode4and4 (buffer, 2);
sector = decode4and4 (buffer, offset + 4); sector = decode4and4 (buffer, 4);
checksum = decode4and4 (buffer, offset + 6); checksum = decode4and4 (buffer, 6);
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
// decode4and4 // 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; int evens = buffer[offset + 1] & 0xFF;
return odds & evens; return odds & evens;
} }

View File

@ -23,7 +23,7 @@ public abstract class DiskReader
// abstract functions // abstract functions
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
abstract byte[] decodeSector (byte[] buffer, int ptr); abstract byte[] decodeSector (byte[] buffer);
abstract byte[] encodeSector (byte[] buffer); abstract byte[] encodeSector (byte[] buffer);

View File

@ -10,7 +10,7 @@ public class DiskReader13Sector extends DiskReader
private final byte[] decodeA = new byte[BUFFER_WITH_CHECKSUM_SIZE]; private final byte[] decodeA = new byte[BUFFER_WITH_CHECKSUM_SIZE];
private final byte[] decodeB = new byte[RAW_BUFFER_SIZE]; private final byte[] decodeB = new byte[RAW_BUFFER_SIZE];
private final ByteTranslator byteTranslator53 = new ByteTranslator5and3 (); private final ByteTranslator byteTranslator = new ByteTranslator5and3 ();
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
// constructor // constructor
@ -26,15 +26,16 @@ public class DiskReader13Sector extends DiskReader
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@Override @Override
byte[] decodeSector (byte[] buffer, int offset) byte[] decodeSector (byte[] buffer)
{ {
byte[] decodedBuffer = new byte[BLOCK_SIZE]; byte[] decodedBuffer = new byte[BLOCK_SIZE];
int offset = 0;
try try
{ {
// convert legal disk values to actual 5 bit values // convert legal disk values to actual 5 bit values
for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE; i++) // 411 bytes 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 // reconstruct 410 bytes each with 5 bits
byte chk = 0; byte chk = 0;
@ -75,11 +76,11 @@ public class DiskReader13Sector extends DiskReader
} }
// add last byte // add last byte
decodedBuffer[ptr] = decodedBuffer[ptr] = (byte) (decodeB[255] | ((decodeB[409] & 0x3F) >>> 3));
(byte) (decodeB[255] | ((decodeB[409] & 0x3F) >>> 3));
} }
catch (Exception e) catch (Exception e)
{ {
// e.printStackTrace ();
System.out.println (e); System.out.println (e);
} }

View File

@ -13,7 +13,7 @@ public class DiskReader16Sector extends DiskReader
private final byte[] encodeA = new byte[RAW_BUFFER_SIZE]; private final byte[] encodeA = new byte[RAW_BUFFER_SIZE];
private final byte[] encodeB = new byte[BUFFER_WITH_CHECKSUM_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 = 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 };
@ -32,25 +32,17 @@ public class DiskReader16Sector extends DiskReader
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@Override @Override
byte[] decodeSector (byte[] buffer, int offset) byte[] decodeSector (byte[] buffer)
{ {
// rearrange 342 bytes into 256 // 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 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 // convert legal disk values to actual 6 bit values
for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE; i++) // 343 bytes for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE; i++) // 343 bytes
{ decodeA[i] = (byte) (byteTranslator.decode (buffer[offset++]) << 2);
if (offset == buffer.length)
offset = 0;
decodeA[i] = (byte) (byteTranslator62.decode (buffer[offset++]) << 2);
}
// reconstruct 342 bytes each with 6 bits // reconstruct 342 bytes each with 6 bits
byte chk = 0; byte chk = 0;
@ -78,6 +70,7 @@ public class DiskReader16Sector extends DiskReader
catch (Exception e) catch (Exception e)
{ {
System.out.println (e); System.out.println (e);
// e.printStackTrace ();
} }
return decodedBuffer; return decodedBuffer;
@ -124,7 +117,7 @@ public class DiskReader16Sector extends DiskReader
// remove two bits and convert to translated bytes // remove two bits and convert to translated bytes
for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE; i++) for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE; i++)
encodedBuffer[i] = byteTranslator62.encode (encodeB[i]); encodedBuffer[i] = byteTranslator.encode (encodeB[i]);
return encodedBuffer; return encodedBuffer;
} }

View File

@ -3,21 +3,27 @@ package com.bytezone.diskbrowser.disk;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.bytezone.diskbrowser.utilities.HexFormatter;
class MC3470 class MC3470
{ {
private static final int EMPTY = 999;
private final boolean debug = false; private final boolean debug = false;
private final boolean dump = false;
private final List<DiskSector> diskSectors = new ArrayList<> (); private final List<DiskSector> diskSectors = new ArrayList<> ();
private State currentState; private State currentState;
private DiskSector currentDiskSector; private DiskSector currentDiskSector;
private int expectedDataSize; private int expectedDataSize;
private boolean finished;
private boolean restarted;
private DiskReader diskReader; private DiskReader diskReader;
private final DiskReader diskReader16 = new DiskReader16Sector (); private final DiskReader diskReader16 = new DiskReader16Sector ();
private final DiskReader diskReader13 = new DiskReader13Sector (); 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 int dataPtr = 0;
private enum State private enum State
@ -38,17 +44,22 @@ class MC3470
diskSectors.clear (); diskSectors.clear ();
currentDiskSector = null; currentDiskSector = null;
currentState = State.OTHER; currentState = State.OTHER;
expectedDataSize = 200; expectedDataSize = EMPTY;
finished = false;
restarted = false;
int value = 0; int value = 0;
dataPtr = 0;
if (debug) if (debug)
{ {
System.out.printf ("%nOffset : %06X%n", offset); System.out.printf ("%nOffset : %06X%n", offset);
System.out.printf ("Bytes used: %06X%n", bytesUsed); 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; int inPtr = offset; // keep offset in case we have to loop around
while (inPtr < max) while (!finished && inPtr < max)
{ {
int b = buffer[inPtr++] & 0xFF; int b = buffer[inPtr++] & 0xFF;
for (int mask = 0x80; mask != 0; mask >>>= 1) for (int mask = 0x80; mask != 0; mask >>>= 1)
@ -57,29 +68,36 @@ class MC3470
if ((b & mask) != 0) if ((b & mask) != 0)
value |= 1; value |= 1;
++totalBits;
if ((value & 0x80) != 0) // is hi-bit set? 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; dataBuffer[dataPtr++] = (byte) value;
checkState (value); checkState (value);
value = 0; 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) if (debug)
// { {
// System.out.printf ("Bytes used %,5d%n", bytesUsed); System.out.printf ("total bits : %d%n", bitCount);
// System.out.printf ("Buffer size %,5d%n", outPtr); System.out.printf ("bits used : %d%n", totalBits);
// } }
if (value != 0)
System.out.printf ("********** Value not used: %01X%n", value);
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -148,7 +166,7 @@ class MC3470
if (dataPtr == expectedDataSize) if (dataPtr == expectedDataSize)
{ {
if (currentState == State.OTHER) 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); setState (State.OTHER);
} }
} }
@ -161,40 +179,67 @@ class MC3470
{ {
if (currentState == newState && currentState == State.OTHER) if (currentState == newState && currentState == State.OTHER)
return; return;
assert currentState != newState; assert currentState != newState : currentState + " -> " + newState;
switch (currentState) // this state is now finished switch (currentState) // this state is now finished
{ {
case ADDRESS: case ADDRESS:
currentDiskSector = new DiskSector (new DiskAddressField (dataBuffer, 0)); currentDiskSector = new DiskSector (new DiskAddressField (dataBuffer));
if (dump)
System.out.println (currentDiskSector);
break; break;
case DATA: case DATA:
currentDiskSector.setBuffer (diskReader.decodeSector (dataBuffer, 0)); if (currentDiskSector != null)
{
currentDiskSector.setBuffer (diskReader.decodeSector (dataBuffer));
diskSectors.add (currentDiskSector); 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; break;
case OTHER: case OTHER:
break; 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; currentState = newState;
dataPtr = 0; // start collecting new buffer 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 () 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; && dataBuffer[dataPtr - 2] == (byte) 0xAA;
} }
@ -213,7 +260,9 @@ class MC3470
private boolean isEpilogue () 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; && dataBuffer[dataPtr - 2] == (byte) 0xAA;
} }

View File

@ -5,7 +5,6 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import com.bytezone.diskbrowser.utilities.HexFormatter;
import com.bytezone.diskbrowser.utilities.Utility; import com.bytezone.diskbrowser.utilities.Utility;
class WozDisk class WozDisk
@ -87,7 +86,11 @@ class WozDisk
else if ("TRKS".equals (chunkId)) else if ("TRKS".equals (chunkId))
{ {
if (debug) 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; int tracks = chunkSize / TRK_SIZE;
for (int trackNo = 0; trackNo < tracks; trackNo++) for (int trackNo = 0; trackNo < tracks; trackNo++)
@ -97,8 +100,11 @@ class WozDisk
if (debug) if (debug)
{ {
System.out.printf ("Bytes used .... %,6d%n", bytesUsed); System.out.println ("******************************");
System.out.printf ("Bit count .... %,6d%n", bitCount); 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 try
@ -115,6 +121,7 @@ class WozDisk
{ {
System.out.println ("unknown disk format"); System.out.println ("unknown disk format");
break read; break read;
// continue;
} }
} }
@ -124,7 +131,7 @@ class WozDisk
{ {
// e.printStackTrace (); // e.printStackTrace ();
System.out.println (e); System.out.println (e);
break read; // break read;
} }
ptr += TRK_SIZE; ptr += TRK_SIZE;
@ -132,8 +139,8 @@ class WozDisk
} }
else if ("META".equals (chunkId)) else if ("META".equals (chunkId))
{ {
System.out.printf ("[%s] %08X%n", chunkId, chunkSize); // System.out.printf ("[%s] %08X%n", chunkId, chunkSize);
System.out.println (HexFormatter.format (buffer, ptr, chunkSize)); // System.out.println (HexFormatter.format (buffer, ptr, chunkSize));
ptr += chunkSize; ptr += chunkSize;
} }
else else