mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2024-06-15 19:29:45 +00:00
woz wacking
This commit is contained in:
parent
ff8b66e0fb
commit
bf25050ca3
411
src/com/bytezone/diskbrowser/nib/Dumper.java
Normal file
411
src/com/bytezone/diskbrowser/nib/Dumper.java
Normal file
|
@ -0,0 +1,411 @@
|
||||||
|
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.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 };
|
||||||
|
|
||||||
|
List<Track> tracks;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
public Dumper (File file)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
byte[] buffer = readFile (file);
|
||||||
|
String header = new String (buffer, 0, 4);
|
||||||
|
System.out.println (header);
|
||||||
|
|
||||||
|
int ptr = 12;
|
||||||
|
while (ptr < buffer.length)
|
||||||
|
{
|
||||||
|
String chunkId = new String (buffer, ptr, 4);
|
||||||
|
int size = Utility.getLong (buffer, ptr + 4);
|
||||||
|
System.out.printf ("%n%s %,9d%n", chunkId, size);
|
||||||
|
switch (chunkId)
|
||||||
|
{
|
||||||
|
case "INFO":
|
||||||
|
info (buffer, ptr);
|
||||||
|
break;
|
||||||
|
case "TMAP":
|
||||||
|
tmap (buffer, ptr);
|
||||||
|
break;
|
||||||
|
case "TRKS":
|
||||||
|
tracks = trks (buffer, ptr);
|
||||||
|
break;
|
||||||
|
case "META":
|
||||||
|
meta (buffer, ptr, size);
|
||||||
|
break;
|
||||||
|
case "WRIT":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ptr += size + 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
Track track = tracks.get (0x22);
|
||||||
|
for (Sector sector : track.sectors)
|
||||||
|
sector.dump ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void info (byte[] buffer, int ptr)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
int version = 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);
|
||||||
|
|
||||||
|
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", version);
|
||||||
|
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;
|
||||||
|
String metaData = new String (buffer, ptr, length);
|
||||||
|
// System.out.println (metaData);
|
||||||
|
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;
|
||||||
|
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));
|
||||||
|
byte[] buffer = in.readAllBytes ();
|
||||||
|
in.close ();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
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");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dumper dumper = new Dumper (file);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
class Track
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
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 () < 13) // hard-coded!!
|
||||||
|
{
|
||||||
|
offset = findNext (address13prologue, offset + 1);
|
||||||
|
if (offset < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
Sector sector = new Sector (this, offset);
|
||||||
|
if (sectors.size () > 0)
|
||||||
|
checkDuplicates (sector, sectors.get (sectors.size () - 1));
|
||||||
|
sectors.add (sector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void checkDuplicates (Sector sector1, Sector sector2)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
if (sector1.sector == sector2.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 ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
while (!nextBit ())
|
||||||
|
if (revolutions >= 2)
|
||||||
|
{
|
||||||
|
System.out.println ("looping");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int b = 0x80;
|
||||||
|
for (int i = 6; i >= 0; i--)
|
||||||
|
if (nextBit ())
|
||||||
|
b |= (1 << i);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
byte[] readTrack ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
if (newBuffer != null)
|
||||||
|
return newBuffer;
|
||||||
|
|
||||||
|
int max = (bitCount - 1) / 8 + 1;
|
||||||
|
max += 520;
|
||||||
|
newBuffer = new byte[max];
|
||||||
|
|
||||||
|
for (int i = 0; i < max; i++)
|
||||||
|
newBuffer[i] = (byte) nextByte ();
|
||||||
|
|
||||||
|
return newBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@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 ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ class MC3470
|
||||||
{
|
{
|
||||||
private static final int MAX_DATA = 999;
|
private static final int MAX_DATA = 999;
|
||||||
private final boolean debug = false;
|
private final boolean debug = false;
|
||||||
private final boolean dump = false;
|
private final boolean dump = true;
|
||||||
|
|
||||||
private List<RawDiskSector> diskSectors;
|
private List<RawDiskSector> diskSectors;
|
||||||
|
|
||||||
|
@ -50,6 +50,13 @@ class MC3470
|
||||||
private static final byte[] dataPrologueX = { (byte) 0xD5, (byte) 0xBB, (byte) 0xCF };
|
private static final byte[] dataPrologueX = { (byte) 0xD5, (byte) 0xBB, (byte) 0xCF };
|
||||||
private static final byte[] epilogueX = { (byte) 0xDA, (byte) 0xAA, (byte) 0xEB };
|
private static final byte[] epilogueX = { (byte) 0xDA, (byte) 0xAA, (byte) 0xEB };
|
||||||
|
|
||||||
|
private static final byte[][] master =
|
||||||
|
{ address16prologue, address13prologue, dataPrologue, epilogue, address16prologueX,
|
||||||
|
dataPrologueX, epilogueX };
|
||||||
|
private static final String[] masterNames =
|
||||||
|
{ "Address Prologue 16", "Address Prologue 13", "Data Prologue", "Epilogue",
|
||||||
|
"Address Prologue 16 X", "Data Prologue X", "Epilogue X" };
|
||||||
|
|
||||||
private enum State
|
private enum State
|
||||||
{
|
{
|
||||||
ADDRESS, DATA, OTHER
|
ADDRESS, DATA, OTHER
|
||||||
|
@ -80,7 +87,7 @@ class MC3470
|
||||||
finished = false;
|
finished = false;
|
||||||
int zeroBits = 0;
|
int zeroBits = 0;
|
||||||
|
|
||||||
main: while (inPtr < max && !finished)
|
while (inPtr < max && !finished)
|
||||||
{
|
{
|
||||||
byte b = buffer[inPtr++];
|
byte b = buffer[inPtr++];
|
||||||
|
|
||||||
|
@ -90,7 +97,7 @@ class MC3470
|
||||||
for (int mask = 0x80; mask != 0; mask >>>= 1)
|
for (int mask = 0x80; mask != 0; mask >>>= 1)
|
||||||
{
|
{
|
||||||
value <<= 1; // make space for next bit
|
value <<= 1; // make space for next bit
|
||||||
if ((b & mask) != 0) // is next bit = 1?
|
if ((b & mask) != 0) // is next bit == 1?
|
||||||
{
|
{
|
||||||
value |= 0x01; // store 1
|
value |= 0x01; // store 1
|
||||||
zeroBits = 0; // reset zero counter
|
zeroBits = 0; // reset zero counter
|
||||||
|
@ -126,7 +133,11 @@ class MC3470
|
||||||
if (currentState == State.OTHER)
|
if (currentState == State.OTHER)
|
||||||
checkState ();
|
checkState ();
|
||||||
else if (dataPtr == expectedDataSize) // DATA or ADDRESS is now complete
|
else if (dataPtr == expectedDataSize) // DATA or ADDRESS is now complete
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
System.out.printf ("%s full%n", currentState);
|
||||||
setState (State.OTHER);
|
setState (State.OTHER);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++totalBits == bitCount) // only use this many bits
|
if (++totalBits == bitCount) // only use this many bits
|
||||||
|
@ -138,7 +149,8 @@ class MC3470
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for unfinished data block, we may need to restart from the beginning
|
// check for unfinished data block, we may need to restart from the beginning
|
||||||
if (totalBits == bitCount && currentState == State.DATA && !restarted)
|
// if (totalBits == bitCount && currentState == State.DATA && !restarted)
|
||||||
|
if (totalBits == bitCount && !restarted)
|
||||||
{
|
{
|
||||||
inPtr = offset;
|
inPtr = offset;
|
||||||
restarted = true;
|
restarted = true;
|
||||||
|
@ -149,12 +161,12 @@ class MC3470
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
System.out.println ("**************************************");
|
System.out.println ("***************************");
|
||||||
System.out.printf ("* total bits : %,5d *%n", bitCount);
|
System.out.printf ("* total bits : %,6d *%n", bitCount);
|
||||||
System.out.printf ("* bits used : %,5d *%n", totalBits);
|
System.out.printf ("* bits used : %,6d *%n", totalBits);
|
||||||
System.out.printf ("* total bytes : %,5d *%n", bytesUsed);
|
System.out.printf ("* total bytes : %,6d *%n", bytesUsed);
|
||||||
System.out.printf ("* bytes used : %,5d *%n", totalBytes);
|
System.out.printf ("* bytes used : %,6d *%n", totalBytes);
|
||||||
System.out.println ("**************************************");
|
System.out.println ("***************************");
|
||||||
}
|
}
|
||||||
|
|
||||||
return diskSectors;
|
return diskSectors;
|
||||||
|
@ -243,6 +255,27 @@ class MC3470
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
|
||||||
private boolean match (byte[] pattern)
|
private boolean match (byte[] pattern)
|
||||||
|
{
|
||||||
|
for (int i = 0, j = dataPtr - 3; i < 3; i++, j++)
|
||||||
|
if (pattern[i] != dataBuffer[j])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < master.length; i++)
|
||||||
|
if (debugMatch (master[i]))
|
||||||
|
System.out.printf ("Matched: %02X %02X %02X %s%n", pattern[0], pattern[1],
|
||||||
|
pattern[2], masterNames[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
// debugMatch
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
private boolean debugMatch (byte[] pattern)
|
||||||
{
|
{
|
||||||
for (int i = 0, j = dataPtr - 3; i < 3; i++, j++)
|
for (int i = 0, j = dataPtr - 3; i < 3; i++, j++)
|
||||||
if (pattern[i] != dataBuffer[j])
|
if (pattern[i] != dataBuffer[j])
|
||||||
|
@ -293,24 +326,30 @@ class MC3470
|
||||||
{
|
{
|
||||||
case ADDRESS:
|
case ADDRESS:
|
||||||
if (currentDiskSector != null)
|
if (currentDiskSector != null)
|
||||||
throw new DiskNibbleException ("cannot start ADDRESS: " + currentDiskSector);
|
{
|
||||||
|
System.out.println ("\nskipped: " + currentDiskSector);
|
||||||
|
currentDiskSector = null;
|
||||||
|
}
|
||||||
|
// throw new DiskNibbleException (
|
||||||
|
// "cannot start ADDRESS: " + currentDiskSector + " has no data");
|
||||||
expectedDataSize = 8;
|
expectedDataSize = 8;
|
||||||
if (dump)
|
if (dump)
|
||||||
System.out.print ("ADDRESS ");
|
System.out.print ("\nADDRESS ");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA:
|
case DATA:
|
||||||
if (currentDiskSector == null)
|
if (currentDiskSector == null)
|
||||||
throw new DiskNibbleException ("cannot start DATA without ADDRESS");
|
// throw new DiskNibbleException ("cannot start DATA without ADDRESS");
|
||||||
|
return;
|
||||||
expectedDataSize = diskReader.expectedDataSize ();
|
expectedDataSize = diskReader.expectedDataSize ();
|
||||||
if (dump)
|
if (dump)
|
||||||
System.out.println ("DATA");
|
System.out.println ("\nDATA");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OTHER:
|
case OTHER:
|
||||||
expectedDataSize = MAX_DATA; // what is the maximum filler?
|
expectedDataSize = MAX_DATA; // what is the maximum filler?
|
||||||
if (dump)
|
if (dump)
|
||||||
System.out.println ("OTHER");
|
System.out.println ("\nOTHER");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.bytezone.diskbrowser.nib;
|
package com.bytezone.diskbrowser.nib;
|
||||||
|
|
||||||
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
|
|
||||||
public class RawDiskSector
|
public class RawDiskSector
|
||||||
{
|
{
|
||||||
final DiskAddressField addressField;
|
final DiskAddressField addressField;
|
||||||
|
@ -15,6 +17,11 @@ public class RawDiskSector
|
||||||
this.buffer = buffer;
|
this.buffer = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dump ()
|
||||||
|
{
|
||||||
|
System.out.println (HexFormatter.format (buffer));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString ()
|
public String toString ()
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,7 +22,8 @@ public class WozFile
|
||||||
private static final int TMAP_SIZE = 0xA0;
|
private static final int TMAP_SIZE = 0xA0;
|
||||||
private static final int DATA_SIZE = TRK_SIZE - 10;
|
private static final int DATA_SIZE = TRK_SIZE - 10;
|
||||||
|
|
||||||
private final boolean debug = false;
|
private final boolean debug = true;
|
||||||
|
private final boolean dump = true;
|
||||||
private int diskType; // 5.25 or 3.5
|
private int diskType; // 5.25 or 3.5
|
||||||
private int wozVersion;
|
private int wozVersion;
|
||||||
private int bootSectorFormat;
|
private int bootSectorFormat;
|
||||||
|
@ -81,9 +82,12 @@ public class WozFile
|
||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
|
int diskType = buffer[ptr + 1] & 0xFF;
|
||||||
|
String diskTypeText = diskType == 1 ? "5.25" : diskType == 2 ? "3.5" : "??";
|
||||||
|
|
||||||
System.out.println ();
|
System.out.println ();
|
||||||
System.out.printf ("Version ........... %02X%n", buffer[ptr]);
|
System.out.printf ("Version ........... %02X%n", buffer[ptr]);
|
||||||
System.out.printf ("Disk type ......... %02X%n", buffer[ptr + 1]);
|
System.out.printf ("Disk type ......... %02X %s%n", diskType, diskTypeText);
|
||||||
System.out.printf ("Write protected ... %02X%n", buffer[ptr + 2]);
|
System.out.printf ("Write protected ... %02X%n", buffer[ptr + 2]);
|
||||||
System.out.printf ("Synchronised ...... %02X%n", buffer[ptr + 3]);
|
System.out.printf ("Synchronised ...... %02X%n", buffer[ptr + 3]);
|
||||||
System.out.printf ("Cleaned ........... %02X%n", buffer[ptr + 4]);
|
System.out.printf ("Cleaned ........... %02X%n", buffer[ptr + 4]);
|
||||||
|
@ -92,8 +96,12 @@ public class WozFile
|
||||||
|
|
||||||
if (wozVersion > 1)
|
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 ("Disk sides ........ %02X%n", buffer[ptr + 37]);
|
||||||
System.out.printf ("Boot format ....... %02X%n", buffer[ptr + 38]);
|
System.out.printf ("Boot format ....... %02X %s%n", bootFormat,
|
||||||
|
bootFormatText);
|
||||||
System.out.printf ("Optimal timing .... %02X%n", buffer[ptr + 39]);
|
System.out.printf ("Optimal timing .... %02X%n", buffer[ptr + 39]);
|
||||||
System.out.printf ("Compatible flags .. %04X%n",
|
System.out.printf ("Compatible flags .. %04X%n",
|
||||||
readInt (buffer, ptr + 40, 2));
|
readInt (buffer, ptr + 40, 2));
|
||||||
|
@ -199,6 +207,7 @@ public class WozFile
|
||||||
{
|
{
|
||||||
System.out.println ("******************************");
|
System.out.println ("******************************");
|
||||||
System.out.printf ("* Track ......... %,6d *%n", trackNo);
|
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 ("* Block count ... %,6d *%n", blockCount);
|
||||||
System.out.printf ("* Bit count .... %,6d *%n", bitCount);
|
System.out.printf ("* Bit count .... %,6d *%n", bitCount);
|
||||||
System.out.println ("******************************");
|
System.out.println ("******************************");
|
||||||
|
@ -213,6 +222,12 @@ public class WozFile
|
||||||
List<RawDiskSector> diskSectors = mc3470.readTrack (buffer,
|
List<RawDiskSector> diskSectors = mc3470.readTrack (buffer,
|
||||||
startingBlock * 512, blockCount * 512, bitCount);
|
startingBlock * 512, blockCount * 512, bitCount);
|
||||||
|
|
||||||
|
for (RawDiskSector rawDiskSector : diskSectors)
|
||||||
|
{
|
||||||
|
System.out.println (rawDiskSector);
|
||||||
|
rawDiskSector.dump ();
|
||||||
|
}
|
||||||
|
|
||||||
mc3470.storeSectors (diskSectors, diskBuffer);
|
mc3470.storeSectors (diskSectors, diskBuffer);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -313,6 +328,11 @@ public class WozFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dump (int trackNo)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
// matches
|
// matches
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -324,4 +344,17 @@ public class WozFile
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void main (String[] args)
|
||||||
|
{
|
||||||
|
File file = new File ("/Users/denismolony/code/python/wozardry-2.0/bill.woz");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
WozFile wozFile = new WozFile (file);
|
||||||
|
}
|
||||||
|
catch (DiskNibbleException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace ();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user