13 sector woz files

This commit is contained in:
Denis Molony 2018-08-07 18:40:06 +10:00
parent cabc613e9a
commit de3012e952
8 changed files with 433 additions and 160 deletions

View File

@ -97,12 +97,13 @@ public abstract class HiResImage extends AbstractFile
protected void createImage ()
{
if (isGif (buffer) || isPng (buffer) || isBmp (buffer))
makeImage ();
else if (monochrome)
createMonochromeImage ();
else
createColourImage ();
if (failureReason.isEmpty ())
if (isGif (buffer) || isPng (buffer) || isBmp (buffer))
makeImage ();
else if (monochrome)
createMonochromeImage ();
else
createColourImage ();
}
abstract void createMonochromeImage ();
@ -252,31 +253,12 @@ public abstract class HiResImage extends AbstractFile
* (as in 10xxxxxx case)
*/
// Super Hi-res IIGS
protected byte[] unpackBytes (byte[] buffer)
{
for (int i = 1; i <= 4; i++)
try
{
byte[] newBuf = new byte[32768 * i]; // keep guessing
unpack (buffer, newBuf);
return newBuf;
}
catch (ArrayIndexOutOfBoundsException e)
{
// try again with a bigger buffer
}
System.out.println ("unpackBytes() failed");
failureReason = "buffer too small";
return new byte[0];
}
// this should call unpackLine()
private void unpack (byte[] buffer, byte[] newBuf) throws ArrayIndexOutOfBoundsException
byte[] unpack (byte[] buffer) throws ArrayIndexOutOfBoundsException
{
// routine found here - http://kpreid.livejournal.com/4319.html
byte[] newBuf = new byte[calculateBufferSize (buffer)];
byte[] fourBuf = new byte[4];
int ptr = 0, newPtr = 0;
@ -314,6 +296,40 @@ public abstract class HiResImage extends AbstractFile
break;
}
}
return newBuf;
}
private int calculateBufferSize (byte[] buffer)
{
int ptr = 0;
int size = 0;
while (ptr < buffer.length)
{
int type = (buffer[ptr] & 0xC0) >> 6; // 0-3
int count = (buffer[ptr++] & 0x3F) + 1; // 1-64
if (type == 0)
{
ptr += count;
size += count;
}
else if (type == 1)
{
ptr++;
size += count;
}
else if (type == 2)
{
ptr += 4;
size += count * 4;
}
else
{
ptr++;
size += count * 4;
}
}
return size;
}
// Super Hi-res IIGS (MAIN in $C0/02)

View File

@ -55,6 +55,8 @@ public class SHRPictureFile1 extends HiResImage
case "SuperConvert":
case "EOA ": // DeluxePaint
case "Platinum Paint":
case "VSDV":
case "VSMK":
blocks.add (new Block (kind, data));
break;
@ -184,6 +186,7 @@ public class SHRPictureFile1 extends HiResImage
public String getText ()
{
StringBuilder text = new StringBuilder (super.getText ());
text.append ("\n\n");
for (Block block : blocks)
{

View File

@ -46,12 +46,12 @@ public class SHRPictureFile2 extends HiResImage
byte[] data = new byte[buffer.length - 0x222];
System.arraycopy (buffer, 0x0222, data, 0, data.length);
this.buffer = unpackBytes (data);
this.buffer = unpack (data);
break;
case 1: // packed version of PIC/$00
this.buffer = unpackBytes (buffer);
this.buffer = unpack (buffer);
controlBytes = new byte[200];
System.arraycopy (this.buffer, 32000, controlBytes, 0, controlBytes.length);
@ -69,7 +69,7 @@ public class SHRPictureFile2 extends HiResImage
// Apple IIGS Tech Note #46
// https://www.prepressure.com/library/file-formats/pict
this.buffer = unpackBytes (buffer);
this.buffer = unpack (buffer);
int mode = HexFormatter.unsignedShort (this.buffer, 0);
int rect1 = HexFormatter.unsignedLong (this.buffer, 2);
int rect2 = HexFormatter.unsignedLong (this.buffer, 6);
@ -96,7 +96,7 @@ public class SHRPictureFile2 extends HiResImage
data = new byte[buffer.length - 6404]; // skip APP. and color tables
System.arraycopy (buffer, 6404, data, 0, data.length);
this.buffer = unpackBytes (data);
this.buffer = unpack (data);
break;
case 4096: // seems to be a PIC/$00
@ -180,7 +180,6 @@ public class SHRPictureFile2 extends HiResImage
boolean mode320 = true;
boolean fillMode = false;
ColorTable colorTable = null;
// boolean flag = false;
for (int line = 0; line < 200; line++)
{

View File

@ -231,10 +231,33 @@ public class AppleDisk implements Disk
this.tracks = tracks;
this.sectors = sectors;
file = disk.file;
diskBuffer = disk.diskBuffer;
trackSize = 4096;
sectorSize = trackSize / sectors;
if (sectors == 13)
{
trackSize = 0xD00;
sectorSize = 256;
diskBuffer = new byte[116480];
int ptr = 0;
for (int track = 0; track < 35; track++)
{
for (int sector = 0; sector < 13; sector++)
{
int ptr2 = track * 0xD00 + sector * 0x100;
System.arraycopy (disk.diskBuffer, ptr, diskBuffer, ptr2, 0x100);
// System.out.printf ("Copying %04X -> %04X%n", ptr, ptr2);
ptr += 0x100;
}
ptr += 0x300; // skip 3 sectors
}
}
else
{
trackSize = 4096;
diskBuffer = disk.diskBuffer;
sectorSize = trackSize / sectors;
}
blocks = tracks * sectors;
hasData = new boolean[blocks];
@ -381,12 +404,12 @@ public class AppleDisk implements Disk
public byte[] readSectors (List<DiskAddress> daList)
{
byte[] buffer = new byte[daList.size () * sectorSize];
int bufferOffset = 0;
int ptr = 0;
for (DiskAddress da : daList)
{
if (da != null && da.getBlock () > 0) // sparse text files may have gaps
readBuffer (da, buffer, bufferOffset);
bufferOffset += sectorSize;
if (da != null && da.getBlock () > 0) // sparse text/PNT/PIC files may have gaps
readBuffer (da, buffer, ptr);
ptr += sectorSize;
}
return buffer;
}

View File

@ -232,6 +232,12 @@ public class DiskFactory
try
{
WozDisk wozDisk = new WozDisk (file);
if (wozDisk.sectorsPerTrack == 13)
{
AppleDisk appleDisk = new AppleDisk (wozDisk, 35, 13);
disk = checkDos (appleDisk);
return disk == null ? new DataDisk (appleDisk) : disk;
}
AppleDisk appleDisk256 = new AppleDisk (wozDisk, 35, 16);
disk = checkDos (appleDisk256);
if (disk == null)

View File

@ -2,7 +2,8 @@ package com.bytezone.diskbrowser.disk;
class Nibblizer
{
private static byte[] addressPrologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0x96 };
private static byte[] addressPrologue32 = { (byte) 0xD5, (byte) 0xAA, (byte) 0xB5 };
private static byte[] addressPrologue33 = { (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 };
@ -11,10 +12,22 @@ class Nibblizer
private static final int BLOCK_SIZE = 256;
private static final int TRACK_SIZE = 4096;
private static final int RAW_BUFFER_SIZE = 342;
private static final int BUFFER_WITH_CHECKSUM_SIZE = RAW_BUFFER_SIZE + 1;
private static final int RAW_BUFFER_SIZE_DOS_33 = 342;
private static final int RAW_BUFFER_SIZE_DOS_32 = 410;
private static final int BUFFER_WITH_CHECKSUM_SIZE_DOS_33 = RAW_BUFFER_SIZE_DOS_33 + 1;
private static final int BUFFER_WITH_CHECKSUM_SIZE_DOS_32 = RAW_BUFFER_SIZE_DOS_32 + 1;
private static byte[] writeTranslateTable =
// 32 valid bytes that can be stored on a disk (plus 0xAA and 0xD5)
private static byte[] writeTranslateTable5and3 =
{ (byte) 0xAB, (byte) 0xAD, (byte) 0xAE, (byte) 0xAF, (byte) 0xB5, (byte) 0xB6,
(byte) 0xB7, (byte) 0xBA, (byte) 0xBB, (byte) 0xBD, (byte) 0xBE, (byte) 0xBF,
(byte) 0xD6, (byte) 0xD7, (byte) 0xDA, (byte) 0xDB, //
(byte) 0xDD, (byte) 0xDE, (byte) 0xDF, (byte) 0xEA, (byte) 0xEB, (byte) 0xED,
(byte) 0xEE, (byte) 0xEF, (byte) 0xF5, (byte) 0xF6, (byte) 0xF7, (byte) 0xFA,
(byte) 0xFB, (byte) 0xFD, (byte) 0xFE, (byte) 0xFF };
// 64 valid bytes that can be stored on a disk (plus 0xAA and 0xD5)
private static byte[] writeTranslateTable6and2 =
{ (byte) 0x96, (byte) 0x97, (byte) 0x9A, (byte) 0x9B, (byte) 0x9D, (byte) 0x9E,
(byte) 0x9F, (byte) 0xA6, (byte) 0xA7, (byte) 0xAB, (byte) 0xAC, (byte) 0xAD,
(byte) 0xAE, (byte) 0xAF, (byte) 0xB2, (byte) 0xB3, //
@ -28,22 +41,44 @@ class Nibblizer
(byte) 0xF5, (byte) 0xF6, (byte) 0xF7, (byte) 0xF9, (byte) 0xFA, (byte) 0xFB,
(byte) 0xFC, (byte) 0xFD, (byte) 0xFE, (byte) 0xFF };
private static byte[] readTranslateTable = new byte[106]; // skip first 150 blanks
private static byte[] readTranslateTable5and3 = new byte[85]; // skip first 171 blanks
private static byte[] readTranslateTable6and2 = new byte[106]; // skip first 150 blanks
static
{
for (int i = 0; i < writeTranslateTable.length; i++)
for (int i = 0; i < writeTranslateTable5and3.length; i++)
{
int j = (writeTranslateTable[i] & 0xFF) - 0x96; // skip first 150 blanks
readTranslateTable[j] = (byte) (i + 1); // offset by 1 to avoid zero
int j = (writeTranslateTable5and3[i] & 0xFF) - 0xAB; // skip first 171 blanks
readTranslateTable5and3[j] = (byte) (i + 1); // offset by 1 to avoid zero
}
for (int i = 0; i < writeTranslateTable6and2.length; i++)
{
int j = (writeTranslateTable6and2[i] & 0xFF) - 0x96; // skip first 150 blanks
readTranslateTable6and2[j] = (byte) (i + 1); // offset by 1 to avoid zero
}
}
private final byte[] decode1 = new byte[BUFFER_WITH_CHECKSUM_SIZE];
private final byte[] decode2 = new byte[RAW_BUFFER_SIZE];
private final byte[] decodeDos33a = new byte[BUFFER_WITH_CHECKSUM_SIZE_DOS_33];
private final byte[] decodeDos33b = new byte[RAW_BUFFER_SIZE_DOS_33];
private final byte[] encode1 = new byte[RAW_BUFFER_SIZE];
private final byte[] encode2 = new byte[BUFFER_WITH_CHECKSUM_SIZE];
private final byte[] encodeDos33a = new byte[RAW_BUFFER_SIZE_DOS_33];
private final byte[] encodeDos33b = new byte[BUFFER_WITH_CHECKSUM_SIZE_DOS_33];
private final byte[] decodeDos32a = new byte[BUFFER_WITH_CHECKSUM_SIZE_DOS_32];
private final byte[] decodeDos32b = new byte[RAW_BUFFER_SIZE_DOS_32];
enum DosVersion
{
DOS_3_2, DOS_3_3
}
private DosVersion currentDosVersion;
int sectorsPerTrack;
// ---------------------------------------------------------------------------------//
// processTrack
// ---------------------------------------------------------------------------------//
boolean processTrack (int trackNo, byte[] buffer, byte[] diskBuffer)
{
@ -51,62 +86,102 @@ class Nibblizer
int totalSectors = 0;
boolean[] sectorsFound = new boolean[16];
while (ptr < buffer.length)
try
{
ptr = findBytes (buffer, ptr, addressPrologue);
if (ptr < 0)
while (ptr < buffer.length)
{
System.out.printf ("Track: %02X - Address prologue not found%n", trackNo);
return false;
int ptr2 = findBytes (buffer, ptr, addressPrologue33);
if (ptr2 >= 0)
{
currentDosVersion = DosVersion.DOS_3_3;
sectorsPerTrack = 16;
}
else
{
ptr2 = findBytes (buffer, ptr, addressPrologue32);
if (ptr2 >= 0)
{
currentDosVersion = DosVersion.DOS_3_2;
sectorsPerTrack = 13;
}
else
{
System.out.printf ("Track: %02X/%02X - Address prologue not found%n", trackNo,
totalSectors);
return false;
}
}
ptr = ptr2;
AddressField addressField = getAddressField (buffer, ptr);
if (!addressField.isValid ())
{
System.out.printf ("Track: %02X - Invalid address field%n", trackNo);
return false;
}
if (addressField.track != trackNo)
{
System.out.printf ("Track: %02X - Wrong track found (%02X)%n", trackNo,
addressField.track);
return false;
}
if (sectorsFound[addressField.sector])
{
System.out.printf ("Track: %02X - Sector already processes (%02X)%n", trackNo,
addressField.sector);
return false;
}
sectorsFound[addressField.sector] = true;
assert addressField.track == trackNo;
ptr += addressField.size ();
ptr = findBytes (buffer, ptr, dataPrologue);
if (ptr < 0)
{
System.out.printf ("Track: %02X - Data prologue not found%n", trackNo);
return false;
}
DataField dataField = getDataField (buffer, ptr);
if (!dataField.isValid ())
{
System.out.printf ("Track: %02X - Invalid data field%n", trackNo);
return false;
}
int offset = addressField.track * TRACK_SIZE;
if (currentDosVersion == DosVersion.DOS_3_2)
offset += addressField.sector * BLOCK_SIZE;
else
offset += interleave[addressField.sector] * BLOCK_SIZE;
System.arraycopy (dataField.dataBuffer, 0, diskBuffer, offset, BLOCK_SIZE);
++totalSectors;
if (currentDosVersion == DosVersion.DOS_3_2 && totalSectors == 13)
break;
if (currentDosVersion == DosVersion.DOS_3_3 && totalSectors == 16)
break;
ptr += dataField.size ();
}
AddressField addressField = getAddressField (buffer, ptr);
if (!addressField.isValid ())
{
System.out.printf ("Track: %02X - Invalid address field%n", trackNo);
return false;
}
if (addressField.track != trackNo)
{
System.out.printf ("Track: %02X - Wrong track found (%02X)%n", trackNo,
addressField.track);
return false;
}
if (sectorsFound[addressField.sector])
{
System.out.printf ("Track: %02X - Sector already processes (%02X)%n", trackNo,
addressField.sector);
return false;
}
sectorsFound[addressField.sector] = true;
assert addressField.track == trackNo;
ptr += addressField.size ();
ptr = findBytes (buffer, ptr, dataPrologue);
if (ptr < 0)
{
System.out.printf ("Track: %02X - Data prologue not found%n", trackNo);
return false;
}
DataField dataField = getDataField (buffer, ptr);
if (!dataField.isValid ())
{
System.out.printf ("Track: %02X - Invalid data field%n", trackNo);
return false;
}
int offset =
addressField.track * TRACK_SIZE + interleave[addressField.sector] * BLOCK_SIZE;
System.arraycopy (dataField.dataBuffer, 0, diskBuffer, offset, BLOCK_SIZE);
if (++totalSectors == 16)
break;
ptr += dataField.size ();
}
if (totalSectors != 16)
catch (Exception e)
{
e.printStackTrace ();
}
if (currentDosVersion == DosVersion.DOS_3_2 && totalSectors != 13)
{
System.out.printf ("Track: %02X - Sectors found: %02X%n", trackNo, totalSectors);
return false;
}
if (currentDosVersion == DosVersion.DOS_3_3 && totalSectors != 16)
{
System.out.printf ("Track: %02X - Sectors found: %02X%n", trackNo, totalSectors);
return false;
@ -115,16 +190,28 @@ class Nibblizer
return true;
}
// ---------------------------------------------------------------------------------//
// getAddressField
// ---------------------------------------------------------------------------------//
private AddressField getAddressField (byte[] buffer, int offset)
{
return new AddressField (buffer, offset);
}
// ---------------------------------------------------------------------------------//
// getDataField
// ---------------------------------------------------------------------------------//
private DataField getDataField (byte[] buffer, int offset)
{
return new DataField (buffer, offset);
}
// ---------------------------------------------------------------------------------//
// decode4and4
// ---------------------------------------------------------------------------------//
private int decode4and4 (byte[] buffer, int offset)
{
int odds = ((buffer[offset] & 0xFF) << 1) + 1;
@ -132,50 +219,122 @@ class Nibblizer
return odds & evens;
}
// ---------------------------------------------------------------------------------//
// decode5and3
// ---------------------------------------------------------------------------------//
private byte[] decode5and3 (byte[] buffer, int offset)
{
for (int i = 0; i <= 410; i++)
decodeDos32a[i] = getByte (buffer[offset++]);
// reconstruct 410 bytes each with 5 bits
byte chk = 0;
int ptr = 0;
for (int i = 409; i >= 256; i--) // 154 bytes
chk = decodeDos32b[i] = (byte) (decodeDos32a[ptr++] ^ chk);
for (int i = 0; i < 256; i++) // 256 bytes
chk = decodeDos32b[i] = (byte) (decodeDos32a[ptr++] ^ chk);
assert (chk ^ decodeDos32a[ptr]) == 0;
// rearrange 410 bytes into 256
byte[] decodedBuffer = new byte[BLOCK_SIZE];
byte[] k = new byte[8];
ptr = 0;
int[] lines = { 0, 51, 102, 153, 204, 256, 307, 358 };
for (int i = 50; i >= 0; i--)
{
for (int j = 0; j < 8; j++)
k[j] = decodeDos32b[i + lines[j]];
k[0] |= (k[5] & 0xE0) >>> 5;
k[1] |= (k[6] & 0xE0) >>> 5;
k[2] |= (k[7] & 0xE0) >>> 5;
k[3] |= (k[5] & 0x10) >>> 2;
k[3] |= (k[6] & 0x10) >>> 3;
k[3] |= (k[7] & 0x10) >>> 4;
k[4] |= (k[5] & 0x08) >>> 1;
k[4] |= (k[6] & 0x08) >>> 2;
k[4] |= (k[7] & 0x08) >>> 3;
for (int j = 0; j < 5; j++)
decodedBuffer[ptr++] = k[j];
}
// last byte not yet tested
decodedBuffer[255] = (byte) (decodeDos32b[255] | (decodeDos32b[409] >>> 3));
return decodedBuffer;
}
private byte getByte (byte b)
{
int val = (b & 0xFF) - 0xAB; // 0 - 84
assert val >= 0 && val <= 84;
byte trans = (byte) (readTranslateTable5and3[val] - 1); // 0 - 31 (5 bits)
assert trans >= 0 && trans <= 31;
return (byte) (trans << 3); // left justify 5 bits
}
// ---------------------------------------------------------------------------------//
// decode6and2
// ---------------------------------------------------------------------------------//
private byte[] decode6and2 (byte[] buffer, int offset)
{
for (int i = 0; i < decode1.length; i++)
// convert legal disk values to actual 6 bit values
for (int i = 0; i < decodeDos33a.length; i++) // 343 bytes
{
int val = (buffer[offset++] & 0xFF) - 150;
byte trans = readTranslateTable[val];
assert trans != 0;
decode1[i] = (byte) ((trans - 1) << 2); // readjust by 1 (see above)
int val = (buffer[offset++] & 0xFF) - 0x96; // 0 - 105
assert val >= 0 && val <= 105;
byte trans = (byte) (readTranslateTable6and2[val] - 1); // 0 - 63 (6 bits)
assert trans >= 0 && trans <= 63;
decodeDos33a[i] = (byte) (trans << 2); // left-justify 6 bits
}
// reconstruct 342 bytes each with 6 bits
byte chk = 0;
for (int i = RAW_BUFFER_SIZE; i > 0; i--)
{
decode2[i - 1] = (byte) (decode1[i] ^ chk);
chk = decode2[i - 1];
}
for (int i = decodeDos33b.length - 1; i >= 0; i--) // 342 bytes
chk = decodeDos33b[i] = (byte) (decodeDos33a[i + 1] ^ chk);
assert (chk ^ decodeDos33a[0]) == 0;
byte[] decodedBuffer = new byte[BLOCK_SIZE];
// rearrange 342 bytes into 256
byte[] decodedBuffer = new byte[BLOCK_SIZE]; // 256 bytes
// move 6 bits into place
for (int i = 0; i < BLOCK_SIZE; i++)
decodedBuffer[i] = decode2[i + 86];
decodedBuffer[i] = decodeDos33b[i + 86];
for (int i = 0; i < 86; i++)
// reattach each byte's last 2 bits
for (int i = 0, j = 86, k = 172; i < 86; i++, j++, k++)
{
byte val = decode2[i];
byte val = decodeDos33b[i];
decodedBuffer[i] |= reverse ((val & 0x0C) >> 2);
decodedBuffer[i + 86] |= reverse ((val & 0x30) >> 4);
decodedBuffer[j] |= reverse ((val & 0x30) >> 4);
if (i < 84)
decodedBuffer[i + 172] |= reverse ((val & 0xC0) >> 6);
if (k < BLOCK_SIZE)
decodedBuffer[k] |= reverse ((val & 0xC0) >> 6);
}
return decodedBuffer;
}
// ---------------------------------------------------------------------------------//
// encode6and2
// ---------------------------------------------------------------------------------//
// convert 256 data bytes into 342 translated bytes plus a checksum
private byte[] encode6and2 (byte[] buffer)
{
byte[] encodedBuffer = new byte[BUFFER_WITH_CHECKSUM_SIZE];
byte[] encodedBuffer = new byte[BUFFER_WITH_CHECKSUM_SIZE_DOS_33];
// move data buffer down to make room for the 86 extra bytes
for (int i = 0; i < BLOCK_SIZE; i++)
encode1[i + 86] = buffer[i];
encodeDos33a[i + 86] = buffer[i];
// build extra 86 bytes from the bits stripped from the data bytes
for (int i = 0; i < 86; i++)
@ -186,34 +345,42 @@ class Nibblizer
if (i < 84)
{
int b3 = reverse (buffer[i + 172] & 0x03) << 6;
encode1[i] = (byte) (b1 | b2 | b3);
encodeDos33a[i] = (byte) (b1 | b2 | b3);
}
else
encode1[i] = (byte) (b1 | b2);
encodeDos33a[i] = (byte) (b1 | b2);
}
// convert into checksum bytes
byte checksum = 0;
for (int i = 0; i < RAW_BUFFER_SIZE; i++)
for (int i = 0; i < RAW_BUFFER_SIZE_DOS_33; i++)
{
encode2[i] = (byte) (checksum ^ encode1[i]);
checksum = encode1[i];
encodeDos33b[i] = (byte) (checksum ^ encodeDos33a[i]);
checksum = encodeDos33a[i];
}
encode2[RAW_BUFFER_SIZE] = checksum; // add checksum to the end
encodeDos33b[RAW_BUFFER_SIZE_DOS_33] = checksum; // add checksum to the end
// remove two bits and convert to translated bytes
for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE; i++)
encodedBuffer[i] = writeTranslateTable[(encode2[i] & 0xFC) / 4];
for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE_DOS_33; i++)
encodedBuffer[i] = writeTranslateTable6and2[(encodeDos33b[i] & 0xFC) / 4];
return encodedBuffer;
}
// ---------------------------------------------------------------------------------//
// reverse
// ---------------------------------------------------------------------------------//
// reverse 2 bits - 0 <= bits <= 3
private static int reverse (int bits)
{
return bits == 1 ? 2 : bits == 2 ? 1 : bits;
}
// ---------------------------------------------------------------------------------//
// listBytes
// ---------------------------------------------------------------------------------//
private String listBytes (byte[] buffer, int offset, int length)
{
StringBuilder text = new StringBuilder ();
@ -225,9 +392,13 @@ class Nibblizer
return text.toString ();
}
// ---------------------------------------------------------------------------------//
// findBytes
// ---------------------------------------------------------------------------------//
static int findBytes (byte[] buffer, int offset, byte[] valueBuffer)
{
while (offset + valueBuffer.length < buffer.length)
while (offset + valueBuffer.length <= buffer.length)
{
if (matchBytes (buffer, offset, valueBuffer))
return offset;
@ -237,19 +408,37 @@ class Nibblizer
return -1;
}
// ---------------------------------------------------------------------------------//
// matchBytes
// ---------------------------------------------------------------------------------//
private static boolean matchBytes (byte[] buffer, int offset, byte[] valueBuffer)
{
if (buffer.length - offset < valueBuffer.length)
if ((buffer.length - offset) < valueBuffer.length)
return false;
int ptr = 0;
while (ptr < valueBuffer.length)
if (buffer[offset++] != valueBuffer[ptr++])
return false;
try
{
while (ptr < valueBuffer.length)
if (buffer[offset++] != valueBuffer[ptr++])
return false;
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println ("Error in matchBytes");
e.printStackTrace ();
return false;
}
return true;
}
// ---------------------------------------------------------------------------------//
// Field
// ---------------------------------------------------------------------------------//
private abstract class Field
{
protected boolean valid;
@ -281,6 +470,10 @@ class Nibblizer
}
}
// ---------------------------------------------------------------------------------//
// AddressField
// ---------------------------------------------------------------------------------//
private class AddressField extends Field
{
int track, sector, volume, checksum;
@ -289,17 +482,17 @@ class Nibblizer
{
super (buffer, offset);
if (matchBytes (buffer, offset, addressPrologue))
// && matchBytes (buffer, offset + 11, epilogue))
{
volume = decode4and4 (buffer, offset + 3);
track = decode4and4 (buffer, offset + 5);
sector = decode4and4 (buffer, offset + 7);
checksum = decode4and4 (buffer, offset + 9);
valid = true;
}
else
System.out.println (listBytes (buffer, offset, 14));
// if (matchBytes (buffer, offset, addressPrologue33))
// // && matchBytes (buffer, offset + 11, epilogue))
// {
volume = decode4and4 (buffer, offset + 3);
track = decode4and4 (buffer, offset + 5);
sector = decode4and4 (buffer, offset + 7);
checksum = decode4and4 (buffer, offset + 9);
valid = true;
// }
// else
// System.out.println (listBytes (buffer, offset, 14));
length = 14;
}
@ -312,6 +505,10 @@ class Nibblizer
}
}
// ---------------------------------------------------------------------------------//
// DataField
// ---------------------------------------------------------------------------------//
private class DataField extends Field
{
byte[] dataBuffer;
@ -323,7 +520,10 @@ class Nibblizer
if (matchBytes (buffer, offset, dataPrologue))
{
valid = true;
dataBuffer = decode6and2 (buffer, offset + 3);
if (currentDosVersion == DosVersion.DOS_3_3)
dataBuffer = decode6and2 (buffer, offset + 3);
else if (currentDosVersion == DosVersion.DOS_3_2)
dataBuffer = decode5and3 (buffer, offset + 3);
}
else
{

View File

@ -5,6 +5,7 @@ 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
@ -16,6 +17,8 @@ class WozDisk
private static byte[] header =
{ 0x57, 0x4F, 0x5A, 0x31, (byte) 0xFF, 0x0a, 0x0D, 0x0A };
private final boolean debug = false;
private int diskType; // 5.25 or 3.5
int sectorsPerTrack;
final File file;
final byte[] diskBuffer = new byte[4096 * 35];
@ -34,7 +37,7 @@ class WozDisk
throw new Exception ("Header error");
int cs1 = readInt (buffer, 8, 4);
int cs2 = Utility.crc32 (buffer, 12, 256 - 12 + 35 * TRK_SIZE);
int cs2 = Utility.crc32 (buffer, 12, buffer.length - 12);
if (cs1 != cs2)
{
System.out.printf ("Checksum : %08X%n", cs1);
@ -62,6 +65,7 @@ class WozDisk
System.out.printf ("Creator ........... %s%n%n",
new String (buffer, ptr + 5, 32));
}
diskType = buffer[ptr + 1] & 0xFF;
ptr += INFO_SIZE;
}
else if ("TMAP".equals (chunkId))
@ -81,20 +85,31 @@ class WozDisk
}
else if ("TRKS".equals (chunkId))
{
if (debug)
System.out.println ("Reading TRKS");
int tracks = chunkSize / TRK_SIZE;
for (int track = 0; track < tracks; track++)
{
int bytesUsed = readInt (buffer, ptr + DATA_SIZE, 2);
int bitCount = readInt (buffer, ptr + DATA_SIZE + 2, 2);
byte[] trackData = new byte[bytesUsed];
readTrack (buffer, ptr, trackData, bytesUsed);
if (debug)
{
System.out.printf ("Bytes used .... %,6d%n", bytesUsed);
System.out.printf ("Bit count .... %,6d%n", bitCount);
}
byte[] trackData = readTrack (buffer, ptr, bytesUsed, bitCount);
if (!nibbler.processTrack (track, trackData, diskBuffer))
{
System.out.println ("Nibblizer failure");
if (debug)
System.out.println (HexFormatter.format (trackData));
break read;
}
ptr += TRK_SIZE;
if (track == 0)
sectorsPerTrack = nibbler.sectorsPerTrack;
}
}
else if ("META".equals (chunkId))
@ -130,32 +145,42 @@ class WozDisk
// readTrack
// ---------------------------------------------------------------------------------//
private void readTrack (byte[] buffer, int offset, byte[] trackData, int bytesUsed)
private byte[] readTrack (byte[] buffer, int offset, int bytesUsed, int bitCount)
{
byte[] trackData = new byte[bytesUsed];
int value = 0;
int ptr = 0;
final int max = offset + bytesUsed;
int count = 0;
for (int i = offset; i < offset + bytesUsed; i++)
for (int i = offset; i < max; i++)
{
int b = buffer[i] & 0xFF;
for (int mask = 0x80; mask > 0; mask >>>= 1)
{
int bit = (b & mask) == 0 ? 0 : 1;
value <<= 1;
value |= bit;
if ((b & mask) != 0)
value |= 1;
++count;
if ((value & 0x80) != 0) // is hi-bit set?
{
trackData[ptr++] = (byte) (value & 0xFF);
trackData[ptr++] = (byte) value;
value = 0;
}
}
}
if (value != 0)
System.out.printf ("Value not used: %01X", value);
// assert value == 0;
System.out.printf ("********** Value not used: %01X%n", value);
if (debug && bitCount != count)
{
System.out.printf ("BitCount: %,4d%n", bitCount);
System.out.printf ("Actual : %,4d%n", count);
}
return trackData;
}
// ---------------------------------------------------------------------------------//

View File

@ -98,9 +98,10 @@ public class Utility
public static int crc32 (byte[] buffer, int offset, int length)
{
int crc = 0xFFFFFFFF; // one's complement
int crc = 0xFFFFFFFF; // one's complement of zero
int eof = offset + length;
for (int i = offset; i < offset + length; i++)
for (int i = offset; i < eof; i++)
crc = crc32_tab[(crc ^ buffer[i]) & 0xFF] ^ (crc >>> 8);
return ~crc; // one's complement