better woz2 support

This commit is contained in:
Denis Molony 2019-07-30 14:57:59 +10:00
parent 07155c7a35
commit 1e6648dc73
6 changed files with 881 additions and 761 deletions

View File

@ -15,9 +15,10 @@ import java.util.zip.Checksum;
import com.bytezone.common.Utility;
import com.bytezone.diskbrowser.applefile.AppleFileSource;
import com.bytezone.diskbrowser.nib.WozFile;
import com.bytezone.diskbrowser.nib.NibFile;
import com.bytezone.diskbrowser.nib.V2dFile;
import com.bytezone.diskbrowser.nib.WozFile;
import com.bytezone.diskbrowser.nib.WozFileOld;
import com.bytezone.diskbrowser.utilities.FileFormatException;
import com.bytezone.diskbrowser.utilities.HexFormatter;
@ -240,6 +241,30 @@ public class AppleDisk implements Disk
diskBuffer = disk.getDiskBuffer ();
}
public AppleDisk (WozFileOld wozFile, int tracks, int sectors)
{
this.tracks = tracks;
this.sectors = sectors;
file = wozFile.file;
diskBuffer = wozFile.getDiskBuffer ();
if (sectors == 13)
{
trackSize = 0xD00;
sectorSize = 256;
}
else
{
trackSize = 0x1000;
sectorSize = trackSize / sectors;
}
blocks = tracks * sectors;
hasData = new boolean[blocks];
checkSectorsForData ();
}
public AppleDisk (WozFile wozFile, int tracks, int sectors)
{
this.tracks = tracks;

View File

@ -234,6 +234,7 @@ public class DiskFactory
{
try
{
// WozFileOld wozDisk = new WozFileOld (file);
WozFile wozDisk = new WozFile (file);
if (wozDisk.getSectorsPerTrack () == 13)
{
@ -241,6 +242,7 @@ public class DiskFactory
disk = checkDos (appleDisk);
return disk == null ? new DataDisk (appleDisk) : disk;
}
if (wozDisk.getSectorsPerTrack () == 16)
{
AppleDisk appleDisk256 = new AppleDisk (wozDisk, 35, 16);
@ -255,7 +257,6 @@ public class DiskFactory
catch (Exception e)
{
System.out.println (e);
// e.printStackTrace ();
return null;
}
}

View File

@ -14,10 +14,6 @@ class DiskAddressField
track = decode4and4 (buffer, 2);
sector = decode4and4 (buffer, 4);
checksum = decode4and4 (buffer, 6);
// if (track == 0)
// for (int i = 0; i < 8; i++)
// System.out.printf ("%02X ", buffer[i]);
}
// ---------------------------------------------------------------------------------//

View File

@ -1,471 +0,0 @@
package com.bytezone.diskbrowser.nib;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.bytezone.common.Utility;
import com.bytezone.diskbrowser.utilities.HexFormatter;
// -----------------------------------------------------------------------------------//
public class Dumper
// -----------------------------------------------------------------------------------//
{
private static final int[] weights = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
private static final byte[] address16prologue =
{ (byte) 0xD5, (byte) 0xAA, (byte) 0x96 };
private static final byte[] address13prologue =
{ (byte) 0xD5, (byte) 0xAA, (byte) 0xB5 };
private static final byte[] dataPrologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0xAD };
private static final byte[] epilogue = { (byte) 0xDE, (byte) 0xAA, (byte) 0xEB };
private final DiskReader13Sector diskReader13Sector = new DiskReader13Sector ();
private final DiskReader16Sector diskReader16Sector = new DiskReader16Sector ();
private int diskSectors;
private int wozVersion;
private byte[] addressPrologue;
private final boolean debug = false;
// ---------------------------------------------------------------------------------//
public Dumper (File file) throws DiskNibbleException
// ---------------------------------------------------------------------------------//
{
byte[] buffer = readFile (file);
String header = new String (buffer, 0, 4);
if (!"WOZ1".equals (header) && !"WOZ2".equals (header))
{
System.out.println ("Not a WOZ disk");
return;
}
List<Track> tracks = null;
int ptr = 12;
while (ptr < buffer.length)
{
String chunkId = new String (buffer, ptr, 4);
int size = Utility.getLong (buffer, ptr + 4);
if (debug)
System.out.printf ("%n%s %,9d%n", chunkId, size);
switch (chunkId)
{
case "INFO": // 60 bytes
info (buffer, ptr);
break;
case "TMAP": // 160 bytes
tmap (buffer, ptr);
break;
case "TRKS": // starts at 248
tracks = trks (buffer, ptr);
break;
case "META":
meta (buffer, ptr, size);
break;
case "WRIT":
break;
default:
break;
}
ptr += size + 8;
}
DiskReader diskReader = diskSectors == 13 ? diskReader13Sector : diskReader16Sector;
byte[] diskBuffer = new byte[35 * diskSectors * 256];
for (Track track : tracks)
for (Sector sector : track)
if (sector.dataOffset > 0)
sector.pack (diskReader, diskBuffer,
256 * (sector.trackNo * diskSectors + sector.sector));
int tr = 0x11;
int sc = 15;
System.out
.println (HexFormatter.format (diskBuffer, 256 * (tr * diskSectors + sc), 256));
}
// ---------------------------------------------------------------------------------//
private void info (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
wozVersion = val8 (buffer, ptr + 8);
int diskType = val8 (buffer, ptr + 9);
int writeProtected = val8 (buffer, ptr + 10);
int synchronised = val8 (buffer, ptr + 11);
int cleaned = val8 (buffer, ptr + 12);
String creator = new String (buffer, ptr + 13, 32);
int sides = val8 (buffer, ptr + 45);
int bootSectorFormat = val8 (buffer, ptr + 46);
int optimalBitTiming = val8 (buffer, ptr + 47);
int compatibleHardware = val16 (buffer, ptr + 48);
int requiredRam = val16 (buffer, ptr + 50);
int largestTrack = val16 (buffer, ptr + 52);
diskSectors = bootSectorFormat == 2 ? 13 : 16;
addressPrologue = diskSectors == 13 ? address13prologue : address16prologue;
if (debug)
{
String bootSectorFormatText =
bootSectorFormat == 0 ? "Unknown" : bootSectorFormat == 1 ? "16 sector"
: bootSectorFormat == 2 ? "13 sector" : "Hybrid";
String diskTypeText = diskType == 1 ? "5.25" : "3.5";
System.out.printf ("Version ............. %d%n", wozVersion);
System.out.printf ("Disk type ........... %d (%s\")%n", diskType, diskTypeText);
System.out.printf ("Write protected ..... %d%n", writeProtected);
System.out.printf ("Synchronized ........ %d%n", synchronised);
System.out.printf ("Cleaned ............. %d%n", cleaned);
System.out.printf ("Creator ............. %s%n", creator);
System.out.printf ("Sides ............... %d%n", sides);
System.out.printf ("Boot sector format .. %d (%s)%n", bootSectorFormat,
bootSectorFormatText);
System.out.printf ("Optimal bit timing .. %d%n", optimalBitTiming);
System.out.printf ("Compatible hardware . %d%n", compatibleHardware);
System.out.printf ("Required RAM ........ %d%n", requiredRam);
System.out.printf ("Largest track ....... %d%n", largestTrack);
}
}
// ---------------------------------------------------------------------------------//
private void tmap (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
ptr += 8;
}
// ---------------------------------------------------------------------------------//
private void meta (byte[] buffer, int ptr, int length)
// ---------------------------------------------------------------------------------//
{
ptr += 8;
if (debug)
{
String metaData = new String (buffer, ptr, length);
String[] chunks = metaData.split ("\n");
for (String chunk : chunks)
{
String[] parts = chunk.split ("\t");
if (parts.length >= 2)
System.out.printf ("%-20s %s%n", parts[0], parts[1]);
else
System.out.printf ("%-20s%n", parts[0]);
}
}
}
// ---------------------------------------------------------------------------------//
private List<Track> trks (byte[] rawBuffer, int ptr)
// ---------------------------------------------------------------------------------//
{
List<Track> tracks = new ArrayList<> ();
ptr += 8;
for (int i = 0; i < 160; i++)
{
Track trk = new Track (i, rawBuffer, ptr);
if (trk.bitCount == 0)
break;
tracks.add (trk);
ptr += 8;
if (debug)
System.out.printf ("%n$%02X %s%n", i, trk);
}
return tracks;
}
// ---------------------------------------------------------------------------------//
private int val8 (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
return (buffer[ptr] & 0xFF);
}
// ---------------------------------------------------------------------------------//
private int val16 (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
return (buffer[ptr++] & 0xFF) + ((buffer[ptr] & 0xFF) << 8);
}
// ---------------------------------------------------------------------------------//
private int val32 (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
return (buffer[ptr++] & 0xFF) + ((buffer[ptr++] & 0xFF) << 8)
+ ((buffer[ptr++] & 0xFF) << 16) + ((buffer[ptr] & 0xFF) << 24);
}
// ---------------------------------------------------------------------------------//
// decode4and4
// ---------------------------------------------------------------------------------//
private int decode4and4 (byte[] buffer, int offset)
{
int odds = ((buffer[offset] & 0xFF) << 1) | 0x01;
int evens = buffer[offset + 1] & 0xFF;
return odds & evens;
}
// ---------------------------------------------------------------------------------//
private byte[] readFile (File file)
// ---------------------------------------------------------------------------------//
{
try (BufferedInputStream in = new BufferedInputStream (new FileInputStream (file)))
{
return in.readAllBytes ();
}
catch (IOException e)
{
e.printStackTrace ();
return null;
}
}
// ---------------------------------------------------------------------------------//
public static void main (String[] args)
// ---------------------------------------------------------------------------------//
{
// File file = new File ("/Users/denismolony/code/python/wozardry-2.0/bill.woz");
File file = new File ("/Users/denismolony/Dropbox/Examples/woz test images/WOZ 2.0/"
+ "DOS 3.3 System Master.woz");
try
{
Dumper dumper = new Dumper (file);
}
catch (Exception e)
{
e.printStackTrace ();
}
}
// ---------------------------------------------------------------------------------//
class Track implements Iterable<Sector>
// ---------------------------------------------------------------------------------//
{
int trackNo;
int startingBlock;
int blockCount;
int bitCount;
byte[] rawBuffer;
byte[] newBuffer;
int bitIndex;
int byteIndex;
int trackIndex;
int revolutions;
List<Sector> sectors = new ArrayList<> ();
// ---------------------------------------------------------------------------------//
public Track (int trackNo, byte[] rawBuffer, int ptr)
// ---------------------------------------------------------------------------------//
{
this.rawBuffer = rawBuffer;
this.trackNo = trackNo;
startingBlock = val16 (rawBuffer, ptr);
blockCount = val16 (rawBuffer, ptr + 2);
bitCount = val32 (rawBuffer, ptr + 4);
if (bitCount == 0)
return;
byteIndex = startingBlock * 512;
int offset = -1;
while (sectors.size () < diskSectors)
{
offset = findNext (addressPrologue, offset + 1);
if (offset < 0)
break;
Sector sector = new Sector (this, offset);
if (sectors.size () > 0)
checkDuplicates (sector);
sectors.add (sector);
}
}
// ---------------------------------------------------------------------------------//
private void checkDuplicates (Sector sector1)
// ---------------------------------------------------------------------------------//
{
for (Sector sector : sectors)
if (sector1.sector == sector.sector)
System.out.println ("\n*** duplicate ***\n");
}
// ---------------------------------------------------------------------------------//
boolean nextBit ()
// ---------------------------------------------------------------------------------//
{
boolean bit = ((rawBuffer[byteIndex] & 0xFF) & weights[bitIndex]) != 0;
if (++trackIndex >= bitCount)
{
++revolutions;
trackIndex = 0;
bitIndex = 0;
byteIndex = startingBlock * 512;
}
else if (++bitIndex >= 8)
{
++byteIndex;
bitIndex = 0;
}
return bit;
}
// ---------------------------------------------------------------------------------//
int nextByte ()
// ---------------------------------------------------------------------------------//
{
byte b = 0;
while ((b & 0x80) == 0)
{
b <<= 1;
if (nextBit ())
b |= 0x01;
}
return b;
}
// ---------------------------------------------------------------------------------//
void readTrack ()
// ---------------------------------------------------------------------------------//
{
if (newBuffer != null)
return;
int max = (bitCount - 1) / 8 + 1;
max += 520;
newBuffer = new byte[max];
for (int i = 0; i < max; i++)
newBuffer[i] = (byte) nextByte ();
}
// ---------------------------------------------------------------------------------//
int findNext (byte[] key, int start)
// ---------------------------------------------------------------------------------//
{
readTrack ();
int max = newBuffer.length - key.length;
outer: for (int ptr = start; ptr < max; ptr++)
{
for (int keyPtr = 0; keyPtr < key.length; keyPtr++)
if (newBuffer[ptr + keyPtr] != key[keyPtr])
continue outer;
return ptr;
}
return -1;
}
// ---------------------------------------------------------------------------------//
void packSector (int sector)
// ---------------------------------------------------------------------------------//
{
}
// ---------------------------------------------------------------------------------//
void dump ()
// ---------------------------------------------------------------------------------//
{
System.out.println (HexFormatter.format (newBuffer));
}
// ---------------------------------------------------------------------------------//
@Override
public String toString ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
text.append (String.format ("Start: %4d, Blocks: %2d, Bits: %,8d%n%n",
startingBlock, blockCount, bitCount));
int count = 0;
for (Sector sector : sectors)
text.append (String.format ("%2d %s%n", count++, sector));
text.deleteCharAt (text.length () - 1);
return text.toString ();
}
// ---------------------------------------------------------------------------------//
@Override
public Iterator<Sector> iterator ()
// ---------------------------------------------------------------------------------//
{
return sectors.iterator ();
}
}
// ---------------------------------------------------------------------------------//
class Sector
// ---------------------------------------------------------------------------------//
{
Track track;
int trackNo, sector, volume, checksum;
int addressOffset, dataOffset;
// ---------------------------------------------------------------------------------//
Sector (Track track, int addressOffset)
// ---------------------------------------------------------------------------------//
{
this.track = track;
byte[] buffer = track.newBuffer;
volume = decode4and4 (buffer, addressOffset + 3);
trackNo = decode4and4 (buffer, addressOffset + 5);
sector = decode4and4 (buffer, addressOffset + 7);
checksum = decode4and4 (buffer, addressOffset + 9);
this.addressOffset = addressOffset;
dataOffset = track.findNext (dataPrologue, addressOffset + 11);
if (dataOffset > addressOffset + 200)
dataOffset = -1;
}
// ---------------------------------------------------------------------------------//
void dump ()
// ---------------------------------------------------------------------------------//
{
System.out.println ();
System.out.println (this);
System.out.println (
HexFormatter.format (track.newBuffer, addressOffset, 512, addressOffset));
}
// ---------------------------------------------------------------------------------//
void pack (DiskReader diskReader, byte[] buffer, int ptr) throws DiskNibbleException
// ---------------------------------------------------------------------------------//
{
byte[] decodedBuffer = diskReader.decodeSector (track.newBuffer, dataOffset + 3);
System.arraycopy (decodedBuffer, 0, buffer, ptr, decodedBuffer.length);
}
// ---------------------------------------------------------------------------------//
@Override
public String toString ()
// ---------------------------------------------------------------------------------//
{
String dataOffsetText = dataOffset < 0 ? "" : String.format ("%04X", dataOffset);
return String.format (
"Vol: %02X Trk: %02X Sct: %02X Chk: %02X Add: %04X Dat: %s", volume,
trackNo, sector, checksum, addressOffset, dataOffsetText);
}
}
}

View File

@ -5,56 +5,56 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.bytezone.diskbrowser.utilities.HexFormatter;
import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------//
public class WozFile
{
private static final byte[] WOZ1_FILE_HEADER =
{ 0x57, 0x4F, 0x5A, 0x31, (byte) 0xFF, 0x0A, 0x0D, 0x0A };
private static final byte[] WOZ2_FILE_HEADER =
{ 0x57, 0x4F, 0x5A, 0x32, (byte) 0xFF, 0x0A, 0x0D, 0x0A };
private static final byte[] address16prologue =
{ (byte) 0xD5, (byte) 0xAA, (byte) 0x96 };
private static final byte[] address13prologue =
{ (byte) 0xD5, (byte) 0xAA, (byte) 0xB5 };
private static final byte[] dataPrologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0xAD };
private static final byte[] epilogue = { (byte) 0xDE, (byte) 0xAA, (byte) 0xEB };
private static final int BLOCK_SIZE = 512;
private static final int SECTOR_SIZE = 256;
private static final int TRK_SIZE = 0x1A00;
private static final int INFO_SIZE = 0x3C;
private static final int TMAP_SIZE = 0xA0;
private static final int DATA_SIZE = TRK_SIZE - 10;
private final boolean debug = true;
private final boolean dump = true;
private int diskType; // 5.25 or 3.5
private int wozVersion;
private int bootSectorFormat;
private final DiskReader13Sector diskReader13Sector = new DiskReader13Sector ();
private final DiskReader16Sector diskReader16Sector = new DiskReader16Sector ();
private static int[][] interleave =
{ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
{ 0, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 15 } };
public final File file;
byte[] diskBuffer;
private final MC3470 mc3470 = new MC3470 ();
private final List<NibbleTrack> nibbleTracks = new ArrayList<> (40);
private int diskSectors;
private int wozVersion;
private byte[] addressPrologue;
private final byte[] diskBuffer;
private final boolean debug = false;
// ---------------------------------------------------------------------------------//
// constructor
// ---------------------------------------------------------------------------------//
public WozFile (File file) throws DiskNibbleException
// ---------------------------------------------------------------------------------//
{
this.file = file;
byte[] buffer = readFile ();
boolean valid = false;
if (matches (WOZ1_FILE_HEADER, buffer))
wozVersion = 1;
else if (matches (WOZ2_FILE_HEADER, buffer))
wozVersion = 2;
else
{
System.out.println (HexFormatter.format (buffer, 0, 20));
byte[] buffer = readFile (file);
String header = new String (buffer, 0, 4);
if (!"WOZ1".equals (header) && !"WOZ2".equals (header))
throw new DiskNibbleException ("Header error");
}
int checksum1 = readInt (buffer, 8, 4);
int checksum1 = val32 (buffer, 8);
int checksum2 = Utility.crc32 (buffer, 12, buffer.length - 12);
if (checksum1 != checksum2)
{
@ -63,263 +63,218 @@ public class WozFile
throw new DiskNibbleException ("Checksum error");
}
List<Track> tracks = null;
int ptr = 12;
read: while (ptr < buffer.length)
while (ptr < buffer.length)
{
String chunkId = new String (buffer, ptr, 4);
ptr += 4;
int chunkSize = readInt (buffer, ptr, 4);
ptr += 4;
int size = val32 (buffer, ptr + 4);
if (debug)
System.out.printf ("%n%s %,9d%n", chunkId, size);
switch (chunkId)
{
System.out.printf ("Offset : %06X%n", ptr - 8);
System.out.printf ("Chunk ID : %s%n", chunkId);
System.out.printf ("Chunk size: %,d%n", chunkSize);
}
if ("INFO".equals (chunkId))
{
if (debug)
{
int diskType = buffer[ptr + 1] & 0xFF;
String diskTypeText = diskType == 1 ? "5.25" : diskType == 2 ? "3.5" : "??";
System.out.println ();
System.out.printf ("Version ........... %02X%n", buffer[ptr]);
System.out.printf ("Disk type ......... %02X %s%n", diskType, diskTypeText);
System.out.printf ("Write protected ... %02X%n", buffer[ptr + 2]);
System.out.printf ("Synchronised ...... %02X%n", buffer[ptr + 3]);
System.out.printf ("Cleaned ........... %02X%n", buffer[ptr + 4]);
System.out.printf ("Creator ........... %s%n",
new String (buffer, ptr + 5, 32).trim ());
if (wozVersion > 1)
{
int bootFormat = buffer[ptr + 38] & 0xFF;
String bootFormatText = bootFormat == 1 ? "16 sector"
: bootFormat == 2 ? "13 sector" : bootFormat == 3 ? "Both" : "??";
System.out.printf ("Disk sides ........ %02X%n", buffer[ptr + 37]);
System.out.printf ("Boot format ....... %02X %s%n", bootFormat,
bootFormatText);
System.out.printf ("Optimal timing .... %02X%n", buffer[ptr + 39]);
System.out.printf ("Compatible flags .. %04X%n",
readInt (buffer, ptr + 40, 2));
System.out.printf ("Minimum RAM ....... %04X%n",
readInt (buffer, ptr + 42, 2));
System.out.printf ("Largest track ..... %04X%n",
readInt (buffer, ptr + 44, 2));
}
System.out.println ();
}
diskType = buffer[ptr + 1] & 0xFF;
if (wozVersion > 1)
bootSectorFormat = buffer[ptr + 38] & 0xFF;
ptr += INFO_SIZE;
}
else if ("TMAP".equals (chunkId))
{
if (debug)
{
for (int track = 0; track < 40; track++)
{
for (int qtr = 0; qtr < 4; qtr++)
System.out.printf ("%02X ", buffer[ptr++]);
System.out.println ();
}
System.out.println ();
}
else
ptr += TMAP_SIZE;
}
else if ("TRKS".equals (chunkId))
{
if (debug)
{
System.out.println ("***********************************************");
System.out.printf ("* Disk ......... %s%n", file.getName ());
System.out.println ("***********************************************");
}
if (wozVersion == 1)
{
int tracks = chunkSize / TRK_SIZE;
for (int trackNo = 0; trackNo < tracks; trackNo++)
{
int bytesUsed = readInt (buffer, ptr + DATA_SIZE, 2);
int bitCount = readInt (buffer, ptr + DATA_SIZE + 2, 2);
if (debug)
{
System.out.println ("***************************************");
System.out.printf ("* Track ......... %,6d of %,6d *%n", trackNo,
tracks);
System.out.printf ("* Bytes used .... %,6d *%n", bytesUsed);
System.out.printf ("* Bit count .... %,6d *%n", bitCount);
System.out.println ("***************************************");
}
try
{
// nibbleTracks.add (mc3470.getNibbleTrack (buffer, ptr, bytesUsed, bitCount));
List<RawDiskSector> diskSectors =
mc3470.readTrack (buffer, ptr, bytesUsed, bitCount);
if (trackNo == 0) // create disk buffer
{
if (mc3470.is13Sector ())
diskBuffer = new byte[35 * 13 * 256];
else if (mc3470.is16Sector ())
diskBuffer = new byte[35 * 16 * 256];
else
{
System.out.println ("unknown disk format");
break read;
}
}
mc3470.storeSectors (diskSectors, diskBuffer);
}
catch (Exception e)
{
System.out.println (e);
break read;
}
ptr += TRK_SIZE;
}
}
else
{
diskBuffer = new byte[(bootSectorFormat == 2 ? 13 : 16) * 35 * 256];
for (int trackNo = 0; trackNo < 160; trackNo++)
{
int p = 256 + trackNo * 8;
int startingBlock = readInt (buffer, p, 2);
int blockCount = readInt (buffer, p + 2, 2);
int bitCount = readInt (buffer, p + 4, 4);
if (debug)
{
System.out.println ("******************************");
System.out.printf ("* Track ......... %,6d *%n", trackNo);
System.out.printf ("* Start block ... %,6d *%n", startingBlock);
System.out.printf ("* Block count ... %,6d *%n", blockCount);
System.out.printf ("* Bit count .... %,6d *%n", bitCount);
System.out.println ("******************************");
}
if (startingBlock == 0)
break;
try
{
// nibbleTracks.add (mc3470.getNibbleTrack (buffer, ptr, bytesUsed, bitCount));
List<RawDiskSector> diskSectors = mc3470.readTrack (buffer,
startingBlock * 512, blockCount * 512, bitCount);
for (RawDiskSector rawDiskSector : diskSectors)
{
System.out.println (rawDiskSector);
rawDiskSector.dump ();
}
mc3470.storeSectors (diskSectors, diskBuffer);
}
catch (Exception e)
{
System.out.println (e);
break read;
}
}
ptr += chunkSize;
}
}
else if ("META".equals (chunkId))
{
// System.out.printf ("[%s] %08X%n", chunkId, chunkSize);
// System.out.println (HexFormatter.format (buffer, ptr, chunkSize));
ptr += chunkSize;
}
else
{
System.out.printf ("Unknown %08X%n", chunkSize);
ptr += chunkSize;
case "INFO": // 60 bytes
info (buffer, ptr);
break;
case "TMAP": // 160 bytes
tmap (buffer, ptr);
break;
case "TRKS": // starts at 248
tracks = trks (buffer, ptr);
break;
case "META":
meta (buffer, ptr, size);
break;
case "WRIT":
break;
default:
break;
}
ptr += size + 8;
}
// if (!valid)
// readNibbleTracks (buffer);
DiskReader diskReader = diskSectors == 13 ? diskReader13Sector : diskReader16Sector;
diskBuffer = new byte[35 * diskSectors * 256];
int ndx = diskSectors == 13 ? 0 : 1;
for (Track track : tracks)
for (Sector sector : track)
if (sector.dataOffset > 0)
sector.pack (diskReader, diskBuffer, SECTOR_SIZE
* (sector.trackNo * diskSectors + interleave[ndx][sector.sectorNo]));
}
// ---------------------------------------------------------------------------------//
// readNibbleTracks
// ---------------------------------------------------------------------------------//
private void readNibbleTracks (byte[] buffer)
{
for (int track = 0; track < 35; track++)
{
int ptr = track * 6656 + 256;
int bytesUsed = readInt (buffer, ptr + DATA_SIZE, 2);
int bitCount = readInt (buffer, ptr + DATA_SIZE + 2, 2);
NibbleTrack nibbleTrack = mc3470.getNibbleTrack (buffer, ptr, bytesUsed, bitCount);
nibbleTracks.add (nibbleTrack);
}
}
// ---------------------------------------------------------------------------------//
// getSectorsPerTrack
// ---------------------------------------------------------------------------------//
public int getSectorsPerTrack ()
{
return mc3470.is13Sector () ? 13 : mc3470.is16Sector () ? 16 : 0;
}
// ---------------------------------------------------------------------------------//
// readInt
// ---------------------------------------------------------------------------------//
private int readInt (byte[] buffer, int offset, int length)
{
int shift = 0;
int value = 0;
for (int i = 0; i < length; i++)
{
value |= (buffer[offset + i] & 0xFF) << shift;
shift += 8;
}
return value;
}
// ---------------------------------------------------------------------------------//
// getDiskBuffer
// ---------------------------------------------------------------------------------//
public byte[] getDiskBuffer ()
// ---------------------------------------------------------------------------------//
{
return diskBuffer;
}
// ---------------------------------------------------------------------------------//
// readFile
public int getSectorsPerTrack ()
// ---------------------------------------------------------------------------------//
private byte[] readFile ()
{
try
return diskSectors;
}
// ---------------------------------------------------------------------------------//
private void info (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
wozVersion = val8 (buffer, ptr + 8);
int diskType = val8 (buffer, ptr + 9);
int writeProtected = val8 (buffer, ptr + 10);
int synchronised = val8 (buffer, ptr + 11);
int cleaned = val8 (buffer, ptr + 12);
String creator = new String (buffer, ptr + 13, 32);
if (debug)
{
BufferedInputStream in = new BufferedInputStream (new FileInputStream (file));
byte[] buffer = in.readAllBytes ();
in.close ();
return buffer;
String diskTypeText = diskType == 1 ? "5.25" : "3.5";
System.out.printf ("Version ............. %d%n", wozVersion);
System.out.printf ("Disk type ........... %d (%s\")%n", diskType, diskTypeText);
System.out.printf ("Write protected ..... %d%n", writeProtected);
System.out.printf ("Synchronized ........ %d%n", synchronised);
System.out.printf ("Cleaned ............. %d%n", cleaned);
System.out.printf ("Creator ............. %s%n", creator);
}
if (wozVersion == 2)
{
int sides = val8 (buffer, ptr + 45);
int bootSectorFormat = val8 (buffer, ptr + 46);
int optimalBitTiming = val8 (buffer, ptr + 47);
int compatibleHardware = val16 (buffer, ptr + 48);
int requiredRam = val16 (buffer, ptr + 50);
int largestTrack = val16 (buffer, ptr + 52);
setGlobals (bootSectorFormat == 2 ? 13 : 16);
if (debug)
{
String bootSectorFormatText =
bootSectorFormat == 0 ? "Unknown" : bootSectorFormat == 1 ? "16 sector"
: bootSectorFormat == 2 ? "13 sector" : "Hybrid";
System.out.printf ("Sides ............... %d%n", sides);
System.out.printf ("Boot sector format .. %d (%s)%n", bootSectorFormat,
bootSectorFormatText);
System.out.printf ("Optimal bit timing .. %d%n", optimalBitTiming);
System.out.printf ("Compatible hardware . %d%n", compatibleHardware);
System.out.printf ("Required RAM ........ %d%n", requiredRam);
System.out.printf ("Largest track ....... %d%n", largestTrack);
}
}
}
// ---------------------------------------------------------------------------------//
private void setGlobals (int diskSectors)
// ---------------------------------------------------------------------------------//
{
this.diskSectors = diskSectors;
addressPrologue = diskSectors == 13 ? address13prologue : address16prologue;
}
// ---------------------------------------------------------------------------------//
private void tmap (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
ptr += 8;
}
// ---------------------------------------------------------------------------------//
private void meta (byte[] buffer, int ptr, int length)
// ---------------------------------------------------------------------------------//
{
ptr += 8;
if (debug)
{
String metaData = new String (buffer, ptr, length);
String[] chunks = metaData.split ("\n");
for (String chunk : chunks)
{
String[] parts = chunk.split ("\t");
if (parts.length >= 2)
System.out.printf ("%-20s %s%n", parts[0], parts[1]);
else
System.out.printf ("%-20s%n", parts[0]);
}
}
}
// ---------------------------------------------------------------------------------//
private List<Track> trks (byte[] rawBuffer, int ptr)
// ---------------------------------------------------------------------------------//
{
List<Track> tracks = new ArrayList<> ();
ptr += 8;
int reclen = wozVersion == 1 ? TRK_SIZE : 8;
int max = wozVersion == 1 ? 35 : 160;
for (int i = 0; i < max; i++)
{
try
{
Track trk = new Track (i, rawBuffer, ptr);
if (trk.bitCount == 0)
break;
tracks.add (trk);
if (debug)
System.out.printf ("%n$%02X %s%n", i, trk);
}
catch (DiskNibbleException e)
{
e.printStackTrace ();
}
ptr += reclen;
}
return tracks;
}
// ---------------------------------------------------------------------------------//
private int val8 (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
return (buffer[ptr] & 0xFF);
}
// ---------------------------------------------------------------------------------//
private int val16 (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
return (buffer[ptr++] & 0xFF) + ((buffer[ptr] & 0xFF) << 8);
}
// ---------------------------------------------------------------------------------//
private int val32 (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
return (buffer[ptr++] & 0xFF) + ((buffer[ptr++] & 0xFF) << 8)
+ ((buffer[ptr++] & 0xFF) << 16) + ((buffer[ptr] & 0xFF) << 24);
}
// ---------------------------------------------------------------------------------//
private int decode4and4 (byte[] buffer, int offset)
// ---------------------------------------------------------------------------------//
{
int odds = ((buffer[offset] & 0xFF) << 1) | 0x01;
int evens = buffer[offset + 1] & 0xFF;
return odds & evens;
}
// ---------------------------------------------------------------------------------//
private byte[] readFile (File file)
// ---------------------------------------------------------------------------------//
{
try (BufferedInputStream in = new BufferedInputStream (new FileInputStream (file)))
{
return in.readAllBytes ();
}
catch (IOException e)
{
@ -328,33 +283,287 @@ public class WozFile
}
}
void dump (int trackNo)
{
}
// ---------------------------------------------------------------------------------//
// matches
// ---------------------------------------------------------------------------------//
private boolean matches (byte[] b1, byte[] b2)
{
for (int i = 0; i < b1.length; i++)
if (b1[i] != b2[i])
return false;
return true;
}
public static void main (String[] args)
// ---------------------------------------------------------------------------------//
{
File file = new File ("/Users/denismolony/code/python/wozardry-2.0/bill.woz");
String home = "/Users/denismolony/";
String wozBase1 = home + "Dropbox/Examples/woz test images/WOZ 1.0/";
String wozBase2 = home + "Dropbox/Examples/woz test images/WOZ 2.0/";
File[] files = { new File (home + "code/python/wozardry-2.0/bill.woz"),
new File (wozBase2 + "DOS 3.3 System Master.woz"),
new File (wozBase1 + "DOS 3.3 System Master.woz") };
try
{
WozFile wozFile = new WozFile (file);
new WozFile (files[2]);
}
catch (DiskNibbleException e)
catch (Exception e)
{
e.printStackTrace ();
}
}
// ---------------------------------------------------------------------------------//
class Track implements Iterable<Sector>
// ---------------------------------------------------------------------------------//
{
int trackNo;
int startingBlock;
int blockCount;
int bitCount;
byte[] rawBuffer;
byte[] newBuffer;
int bitIndex;
int byteIndex;
int trackIndex;
int revolutions;
int bytesUsed;
List<Sector> sectors = new ArrayList<> ();
// ---------------------------------------------------------------------------------//
public Track (int trackNo, byte[] rawBuffer, int ptr) throws DiskNibbleException
// ---------------------------------------------------------------------------------//
{
this.rawBuffer = rawBuffer;
this.trackNo = trackNo;
if (debug)
System.out.println (HexFormatter.format (rawBuffer, ptr, 512, ptr));
if (wozVersion == 1)
{
bytesUsed = val16 (rawBuffer, ptr + DATA_SIZE);
bitCount = val16 (rawBuffer, ptr + DATA_SIZE + 2);
if (debug)
System.out.println (
(String.format ("Bytes: %2d, Bits: %,8d%n%n", bytesUsed, bitCount)));
}
else
{
startingBlock = val16 (rawBuffer, ptr);
blockCount = val16 (rawBuffer, ptr + 2);
bitCount = val32 (rawBuffer, ptr + 4);
if (debug)
System.out.println ((String.format ("Start: %4d, Blocks: %2d, Bits: %,8d%n%n",
startingBlock, blockCount, bitCount)));
}
if (bitCount == 0)
return;
resetIndex ();
if (addressPrologue == null) // WOZ1
if (findNext (address16prologue, ptr) > 0)
setGlobals (16);
else if (findNext (address13prologue, ptr) > 0)
setGlobals (13);
else
throw new DiskNibbleException ("No address prologue found");
int offset = -1;
while (sectors.size () < diskSectors)
{
offset = findNext (addressPrologue, offset + 1);
if (offset < 0)
break;
Sector sector = new Sector (this, offset);
if (sectors.size () > 0)
checkDuplicates (sector);
sectors.add (sector);
}
}
// ---------------------------------------------------------------------------------//
private void checkDuplicates (Sector newSector)
// ---------------------------------------------------------------------------------//
{
for (Sector sector : sectors)
if (sector.isDuplicate (newSector))
System.out.println ("\n*** duplicate ***\n");
}
// ---------------------------------------------------------------------------------//
private void resetIndex ()
// ---------------------------------------------------------------------------------//
{
trackIndex = 0;
bitIndex = 0;
if (wozVersion == 1)
byteIndex = 256 + trackNo * TRK_SIZE;
else
byteIndex = startingBlock * BLOCK_SIZE;
}
// ---------------------------------------------------------------------------------//
boolean nextBit ()
// ---------------------------------------------------------------------------------//
{
boolean bit = (rawBuffer[byteIndex] & (0x80 >>> bitIndex)) != 0;
if (++trackIndex >= bitCount)
{
++revolutions;
resetIndex ();
}
else if (++bitIndex >= 8)
{
++byteIndex;
bitIndex = 0;
}
return bit;
}
// ---------------------------------------------------------------------------------//
int nextByte ()
// ---------------------------------------------------------------------------------//
{
byte b = 0;
while ((b & 0x80) == 0)
{
b <<= 1;
if (nextBit ())
b |= 0x01;
}
return b;
}
// ---------------------------------------------------------------------------------//
void readTrack ()
// ---------------------------------------------------------------------------------//
{
if (newBuffer != null)
return;
int max = (bitCount - 1) / 8 + 1;
max += 520;
newBuffer = new byte[max];
for (int i = 0; i < max; i++)
newBuffer[i] = (byte) nextByte ();
}
// ---------------------------------------------------------------------------------//
int findNext (byte[] key, int start)
// ---------------------------------------------------------------------------------//
{
readTrack ();
int max = newBuffer.length - key.length;
outer: for (int ptr = start; ptr < max; ptr++)
{
for (int keyPtr = 0; keyPtr < key.length; keyPtr++)
if (newBuffer[ptr + keyPtr] != key[keyPtr])
continue outer;
return ptr;
}
return -1;
}
// ---------------------------------------------------------------------------------//
void dump ()
// ---------------------------------------------------------------------------------//
{
System.out.println (HexFormatter.format (newBuffer));
}
// ---------------------------------------------------------------------------------//
@Override
public String toString ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
if (wozVersion == 1)
text.append (String.format ("Bytes: %2d, Bits: %,8d%n%n", bytesUsed, bitCount));
else
text.append (String.format ("Start: %4d, Blocks: %2d, Bits: %,8d%n%n",
startingBlock, blockCount, bitCount));
int count = 0;
for (Sector sector : sectors)
text.append (String.format ("%2d %s%n", count++, sector));
text.deleteCharAt (text.length () - 1);
return text.toString ();
}
// ---------------------------------------------------------------------------------//
@Override
public Iterator<Sector> iterator ()
// ---------------------------------------------------------------------------------//
{
return sectors.iterator ();
}
}
// ---------------------------------------------------------------------------------//
class Sector
// ---------------------------------------------------------------------------------//
{
Track track;
int trackNo, sectorNo, volume, checksum;
int addressOffset, dataOffset;
// ---------------------------------------------------------------------------------//
Sector (Track track, int addressOffset)
// ---------------------------------------------------------------------------------//
{
this.track = track;
volume = decode4and4 (track.newBuffer, addressOffset + 3);
trackNo = decode4and4 (track.newBuffer, addressOffset + 5);
sectorNo = decode4and4 (track.newBuffer, addressOffset + 7);
checksum = decode4and4 (track.newBuffer, addressOffset + 9);
this.addressOffset = addressOffset;
dataOffset = track.findNext (dataPrologue, addressOffset + 11);
if (dataOffset > addressOffset + 200)
dataOffset = -1;
}
// ---------------------------------------------------------------------------------//
boolean isDuplicate (Sector sector)
// ---------------------------------------------------------------------------------//
{
return this.sectorNo == sector.sectorNo;
}
// ---------------------------------------------------------------------------------//
void dump ()
// ---------------------------------------------------------------------------------//
{
System.out.println ();
System.out.println (this);
System.out.println (HexFormatter.format (track.newBuffer, addressOffset, BLOCK_SIZE,
addressOffset));
}
// ---------------------------------------------------------------------------------//
void pack (DiskReader diskReader, byte[] buffer, int ptr) throws DiskNibbleException
// ---------------------------------------------------------------------------------//
{
byte[] decodedBuffer = diskReader.decodeSector (track.newBuffer, dataOffset + 3);
System.arraycopy (decodedBuffer, 0, buffer, ptr, decodedBuffer.length);
}
// ---------------------------------------------------------------------------------//
@Override
public String toString ()
// ---------------------------------------------------------------------------------//
{
String dataOffsetText = dataOffset < 0 ? "" : String.format ("%04X", dataOffset);
return String.format (
"Vol: %02X Trk: %02X Sct: %02X Chk: %02X Add: %04X Dat: %s", volume,
trackNo, sectorNo, checksum, addressOffset, dataOffsetText);
}
}
}

View File

@ -0,0 +1,360 @@
package com.bytezone.diskbrowser.nib;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.bytezone.diskbrowser.utilities.HexFormatter;
import com.bytezone.diskbrowser.utilities.Utility;
public class WozFileOld
{
private static final byte[] WOZ1_FILE_HEADER =
{ 0x57, 0x4F, 0x5A, 0x31, (byte) 0xFF, 0x0A, 0x0D, 0x0A };
private static final byte[] WOZ2_FILE_HEADER =
{ 0x57, 0x4F, 0x5A, 0x32, (byte) 0xFF, 0x0A, 0x0D, 0x0A };
private static final int TRK_SIZE = 0x1A00;
private static final int INFO_SIZE = 0x3C;
private static final int TMAP_SIZE = 0xA0;
private static final int DATA_SIZE = TRK_SIZE - 10;
private final boolean debug = true;
private final boolean dump = true;
private int diskType; // 5.25 or 3.5
private int wozVersion;
private int bootSectorFormat;
public final File file;
byte[] diskBuffer;
private final MC3470 mc3470 = new MC3470 ();
private final List<NibbleTrack> nibbleTracks = new ArrayList<> (40);
// ---------------------------------------------------------------------------------//
// constructor
// ---------------------------------------------------------------------------------//
public WozFileOld (File file) throws DiskNibbleException
{
this.file = file;
byte[] buffer = readFile ();
boolean valid = false;
if (matches (WOZ1_FILE_HEADER, buffer))
wozVersion = 1;
else if (matches (WOZ2_FILE_HEADER, buffer))
wozVersion = 2;
else
{
System.out.println (HexFormatter.format (buffer, 0, 20));
throw new DiskNibbleException ("Header error");
}
int checksum1 = readInt (buffer, 8, 4);
int checksum2 = Utility.crc32 (buffer, 12, buffer.length - 12);
if (checksum1 != checksum2)
{
System.out.printf ("Stored checksum : %08X%n", checksum1);
System.out.printf ("Calculated checksum : %08X%n", checksum2);
throw new DiskNibbleException ("Checksum error");
}
int ptr = 12;
read: while (ptr < buffer.length)
{
String chunkId = new String (buffer, ptr, 4);
ptr += 4;
int chunkSize = readInt (buffer, ptr, 4);
ptr += 4;
if (debug)
{
System.out.printf ("Offset : %06X%n", ptr - 8);
System.out.printf ("Chunk ID : %s%n", chunkId);
System.out.printf ("Chunk size: %,d%n", chunkSize);
}
if ("INFO".equals (chunkId))
{
if (debug)
{
int diskType = buffer[ptr + 1] & 0xFF;
String diskTypeText = diskType == 1 ? "5.25" : diskType == 2 ? "3.5" : "??";
System.out.println ();
System.out.printf ("Version ........... %02X%n", buffer[ptr]);
System.out.printf ("Disk type ......... %02X %s%n", diskType, diskTypeText);
System.out.printf ("Write protected ... %02X%n", buffer[ptr + 2]);
System.out.printf ("Synchronised ...... %02X%n", buffer[ptr + 3]);
System.out.printf ("Cleaned ........... %02X%n", buffer[ptr + 4]);
System.out.printf ("Creator ........... %s%n",
new String (buffer, ptr + 5, 32).trim ());
if (wozVersion > 1)
{
int bootFormat = buffer[ptr + 38] & 0xFF;
String bootFormatText = bootFormat == 1 ? "16 sector"
: bootFormat == 2 ? "13 sector" : bootFormat == 3 ? "Both" : "??";
System.out.printf ("Disk sides ........ %02X%n", buffer[ptr + 37]);
System.out.printf ("Boot format ....... %02X %s%n", bootFormat,
bootFormatText);
System.out.printf ("Optimal timing .... %02X%n", buffer[ptr + 39]);
System.out.printf ("Compatible flags .. %04X%n",
readInt (buffer, ptr + 40, 2));
System.out.printf ("Minimum RAM ....... %04X%n",
readInt (buffer, ptr + 42, 2));
System.out.printf ("Largest track ..... %04X%n",
readInt (buffer, ptr + 44, 2));
}
System.out.println ();
}
diskType = buffer[ptr + 1] & 0xFF;
if (wozVersion > 1)
bootSectorFormat = buffer[ptr + 38] & 0xFF;
ptr += INFO_SIZE;
}
else if ("TMAP".equals (chunkId))
{
if (debug)
{
for (int track = 0; track < 40; track++)
{
for (int qtr = 0; qtr < 4; qtr++)
System.out.printf ("%02X ", buffer[ptr++]);
System.out.println ();
}
System.out.println ();
}
else
ptr += TMAP_SIZE;
}
else if ("TRKS".equals (chunkId))
{
if (debug)
{
System.out.println ("***********************************************");
System.out.printf ("* Disk ......... %s%n", file.getName ());
System.out.println ("***********************************************");
}
if (wozVersion == 1)
{
int tracks = chunkSize / TRK_SIZE;
for (int trackNo = 0; trackNo < tracks; trackNo++)
{
int bytesUsed = readInt (buffer, ptr + DATA_SIZE, 2);
int bitCount = readInt (buffer, ptr + DATA_SIZE + 2, 2);
if (debug)
{
System.out.println ("***************************************");
System.out.printf ("* Track ......... %,6d of %,6d *%n", trackNo,
tracks);
System.out.printf ("* Bytes used .... %,6d *%n", bytesUsed);
System.out.printf ("* Bit count .... %,6d *%n", bitCount);
System.out.println ("***************************************");
}
try
{
// nibbleTracks.add (mc3470.getNibbleTrack (buffer, ptr, bytesUsed, bitCount));
List<RawDiskSector> diskSectors =
mc3470.readTrack (buffer, ptr, bytesUsed, bitCount);
if (trackNo == 0) // create disk buffer
{
if (mc3470.is13Sector ())
diskBuffer = new byte[35 * 13 * 256];
else if (mc3470.is16Sector ())
diskBuffer = new byte[35 * 16 * 256];
else
{
System.out.println ("unknown disk format");
break read;
}
}
mc3470.storeSectors (diskSectors, diskBuffer);
}
catch (Exception e)
{
System.out.println (e);
break read;
}
ptr += TRK_SIZE;
}
}
else
{
diskBuffer = new byte[(bootSectorFormat == 2 ? 13 : 16) * 35 * 256];
for (int trackNo = 0; trackNo < 160; trackNo++)
{
int p = 256 + trackNo * 8;
int startingBlock = readInt (buffer, p, 2);
int blockCount = readInt (buffer, p + 2, 2);
int bitCount = readInt (buffer, p + 4, 4);
if (debug)
{
System.out.println ("******************************");
System.out.printf ("* Track ......... %,6d *%n", trackNo);
System.out.printf ("* Start block ... %,6d *%n", startingBlock);
System.out.printf ("* Block count ... %,6d *%n", blockCount);
System.out.printf ("* Bit count .... %,6d *%n", bitCount);
System.out.println ("******************************");
}
if (startingBlock == 0)
break;
try
{
// nibbleTracks.add (mc3470.getNibbleTrack (buffer, ptr, bytesUsed, bitCount));
List<RawDiskSector> diskSectors = mc3470.readTrack (buffer,
startingBlock * 512, blockCount * 512, bitCount);
for (RawDiskSector rawDiskSector : diskSectors)
{
System.out.println (rawDiskSector);
rawDiskSector.dump ();
}
mc3470.storeSectors (diskSectors, diskBuffer);
}
catch (Exception e)
{
System.out.println (e);
break read;
}
}
ptr += chunkSize;
}
}
else if ("META".equals (chunkId))
{
// System.out.printf ("[%s] %08X%n", chunkId, chunkSize);
// System.out.println (HexFormatter.format (buffer, ptr, chunkSize));
ptr += chunkSize;
}
else
{
System.out.printf ("Unknown %08X%n", chunkSize);
ptr += chunkSize;
}
}
// if (!valid)
// readNibbleTracks (buffer);
}
// ---------------------------------------------------------------------------------//
// readNibbleTracks
// ---------------------------------------------------------------------------------//
private void readNibbleTracks (byte[] buffer)
{
for (int track = 0; track < 35; track++)
{
int ptr = track * 6656 + 256;
int bytesUsed = readInt (buffer, ptr + DATA_SIZE, 2);
int bitCount = readInt (buffer, ptr + DATA_SIZE + 2, 2);
NibbleTrack nibbleTrack = mc3470.getNibbleTrack (buffer, ptr, bytesUsed, bitCount);
nibbleTracks.add (nibbleTrack);
}
}
// ---------------------------------------------------------------------------------//
// getSectorsPerTrack
// ---------------------------------------------------------------------------------//
public int getSectorsPerTrack ()
{
return mc3470.is13Sector () ? 13 : mc3470.is16Sector () ? 16 : 0;
}
// ---------------------------------------------------------------------------------//
// readInt
// ---------------------------------------------------------------------------------//
private int readInt (byte[] buffer, int offset, int length)
{
int shift = 0;
int value = 0;
for (int i = 0; i < length; i++)
{
value |= (buffer[offset + i] & 0xFF) << shift;
shift += 8;
}
return value;
}
// ---------------------------------------------------------------------------------//
// getDiskBuffer
// ---------------------------------------------------------------------------------//
public byte[] getDiskBuffer ()
{
return diskBuffer;
}
// ---------------------------------------------------------------------------------//
// readFile
// ---------------------------------------------------------------------------------//
private byte[] readFile ()
{
try
{
BufferedInputStream in = new BufferedInputStream (new FileInputStream (file));
byte[] buffer = in.readAllBytes ();
in.close ();
return buffer;
}
catch (IOException e)
{
e.printStackTrace ();
return null;
}
}
void dump (int trackNo)
{
}
// ---------------------------------------------------------------------------------//
// matches
// ---------------------------------------------------------------------------------//
private boolean matches (byte[] b1, byte[] b2)
{
for (int i = 0; i < b1.length; i++)
if (b1[i] != b2[i])
return false;
return true;
}
public static void main (String[] args)
{
File file = new File ("/Users/denismolony/code/python/wozardry-2.0/bill.woz");
try
{
new WozFileOld (file);
}
catch (DiskNibbleException e)
{
e.printStackTrace ();
}
}
}