mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2024-11-25 16:34:00 +00:00
nibbling
This commit is contained in:
parent
dc319ebb97
commit
6eb4acc85d
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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<DiskSector> 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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user