mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2025-02-07 11:30:39 +00:00
13 sector woz files
This commit is contained in:
parent
cabc613e9a
commit
de3012e952
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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++)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user