woz shenanigans

This commit is contained in:
Denis Molony 2019-07-28 16:24:52 +10:00
parent bf25050ca3
commit 07155c7a35
6 changed files with 149 additions and 79 deletions

View File

@ -31,11 +31,11 @@ public abstract class HiResImage extends AbstractFile
// $08 FOT $4001 Packed Double Hi-Res file - ???
// $08 FOT $8066 Fadden Hi-res - FaddenHiResImage
// * $C0 PNT $0000 Paintworks Packed Super Hi-Res - SHRPictureFile2
// * $C0 PNT $0001 Packed IIGS Super Hi-Res Image - SHRPictureFile2
// * $C0 PNT $0000 Paintworks Packed Super Hi-Res - SHRPictureFile2
// * $C0 PNT $0001 Packed IIGS Super Hi-Res Image - SHRPictureFile2
// * $C0 PNT $0002 IIGS Super Hi-Res Picture File (APF) - SHRPictureFile
// $C0 PNT $0003 Packed IIGS QuickDraw II PICT File - SHRPictureFile2 *
// * $C0 PNT $0004 Packed Super Hi-Res 3200 (Brooks) .3201 - SHRPictureFile2
// * $C0 PNT $0004 Packed Super Hi-Res 3200 (Brooks) .3201 - SHRPictureFile2
// $C0 PNT $1000
// $C0 PNT $8000 Drawplus ?
// $C0 PNT $8001 GTv background picture
@ -45,6 +45,7 @@ public abstract class HiResImage extends AbstractFile
// * $C1 PIC $0000 IIGS Super Hi-Res Image - SHRPictureFile2
// $C1 PIC $0001 IIGS QuickDraw II PICT File - SHRPictureFile2 *
// * $C1 PIC $0002 Super Hi-Res 3200 (Brooks) .3200 - SHRPictureFile2
// $C1 PIC $2000 ?
// $C1 PIC $8001 Allison raw image
// $C1 PIC $8002 Thunderscan
// $C1 PIC $8003 DreamGraphix
@ -154,13 +155,13 @@ public abstract class HiResImage extends AbstractFile
}
/*-
* Files of type $08 and any auxiliary type less than or equal to $3FFF contain a
* standard Apple II graphics file in one of several modes. After determining that
* the auxiliary type is not $4000 or $4001 (which have been defined for high-resolution
* and double high-resolution pictures packed with the Apple IIGS PackBytes routine),
* you can determine the mode of the file by examining byte +120 (+$78). The value of
* Files of type $08 and any auxiliary type less than or equal to $3FFF contain a
* standard Apple II graphics file in one of several modes. After determining that
* the auxiliary type is not $4000 or $4001 (which have been defined for high-resolution
* and double high-resolution pictures packed with the Apple IIGS PackBytes routine),
* you can determine the mode of the file by examining byte +120 (+$78). The value of
* this byte, which ranges from zero to seven, is interpreted as follows:
*
*
Mode Page 1 Page 2
280 x 192 Black & White 0 4
280 x 192 Limited Color 1 5
@ -170,6 +171,8 @@ public abstract class HiResImage extends AbstractFile
// SHR see - http://noboot.com/charlie/cb2e_p3.htm
// also: https://groups.google.com/forum/#!topic/comp.sys.apple2/zYhZ5YdNNxQ
@Override
public String getText ()
{
@ -224,6 +227,7 @@ public abstract class HiResImage extends AbstractFile
switch (auxType)
{
case 0:
case 0x2000:
auxText = "Super Hi-res Screen Image";
break;
case 1:

View File

@ -120,6 +120,7 @@ public class SHRPictureFile2 extends HiResImage
{
case 0: // unpacked version of PNT/$01
case 0x4100: // no idea what this is
case 0x2000: // see TotalReplay.2mg
// 00000 - 31999 pixel data 32,000 bytes
// 32000 - 32199 200 control bytes (one per scan line)
// 32200 - 32255 empty

View File

@ -16,11 +16,16 @@ public abstract class DiskReader
this.sectorsPerTrack = sectorsPerTrack;
}
byte[] decodeSector (byte[] buffer) throws DiskNibbleException
{
return decodeSector (buffer, 0);
}
// ---------------------------------------------------------------------------------//
// abstract functions
// ---------------------------------------------------------------------------------//
abstract byte[] decodeSector (byte[] buffer) throws DiskNibbleException;
abstract byte[] decodeSector (byte[] buffer, int offset) throws DiskNibbleException;
abstract byte[] encodeSector (byte[] buffer);

View File

@ -24,10 +24,10 @@ public class DiskReader13Sector extends DiskReader
// ---------------------------------------------------------------------------------//
@Override
byte[] decodeSector (byte[] buffer) throws DiskNibbleException
byte[] decodeSector (byte[] buffer, int offset) throws DiskNibbleException
{
byte[] decodedBuffer = new byte[BLOCK_SIZE];
int offset = 0;
// int offset = 0;
// convert legal disk values to actual 5 bit values
for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE; i++) // 411 bytes

View File

@ -30,11 +30,11 @@ public class DiskReader16Sector extends DiskReader
// ---------------------------------------------------------------------------------//
@Override
byte[] decodeSector (byte[] buffer) throws DiskNibbleException
byte[] decodeSector (byte[] buffer, int offset) throws DiskNibbleException
{
// rearrange 342 bytes into 256
byte[] decodedBuffer = new byte[BLOCK_SIZE]; // 256 bytes
int offset = 0;
// int offset = 0;
// convert legal disk values to actual 6 bit values
for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE; i++) // 343 bytes

View File

@ -5,6 +5,7 @@ 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;
@ -23,31 +24,46 @@ public class Dumper
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;
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)
public Dumper (File file) throws DiskNibbleException
// ---------------------------------------------------------------------------------//
{
byte[] buffer = readFile (file);
String header = new String (buffer, 0, 4);
System.out.println (header);
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);
System.out.printf ("%n%s %,9d%n", chunkId, size);
if (debug)
System.out.printf ("%n%s %,9d%n", chunkId, size);
switch (chunkId)
{
case "INFO":
case "INFO": // 60 bytes
info (buffer, ptr);
break;
case "TMAP":
case "TMAP": // 160 bytes
tmap (buffer, ptr);
break;
case "TRKS":
case "TRKS": // starts at 248
tracks = trks (buffer, ptr);
break;
case "META":
@ -61,16 +77,26 @@ public class Dumper
ptr += size + 8;
}
Track track = tracks.get (0x22);
for (Sector sector : track.sectors)
sector.dump ();
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)
// ---------------------------------------------------------------------------------//
{
int version = val8 (buffer, ptr + 8);
wozVersion = val8 (buffer, ptr + 8);
int diskType = val8 (buffer, ptr + 9);
int writeProtected = val8 (buffer, ptr + 10);
int synchronised = val8 (buffer, ptr + 11);
@ -83,24 +109,30 @@ public class Dumper
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";
diskSectors = bootSectorFormat == 2 ? 13 : 16;
addressPrologue = diskSectors == 13 ? address13prologue : address16prologue;
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);
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);
}
}
// ---------------------------------------------------------------------------------//
@ -115,16 +147,19 @@ public class Dumper
// ---------------------------------------------------------------------------------//
{
ptr += 8;
String metaData = new String (buffer, ptr, length);
// System.out.println (metaData);
String[] chunks = metaData.split ("\n");
for (String chunk : chunks)
if (debug)
{
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]);
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]);
}
}
}
@ -141,7 +176,8 @@ public class Dumper
break;
tracks.add (trk);
ptr += 8;
System.out.printf ("%n$%02X %s%n", i, trk);
if (debug)
System.out.printf ("%n$%02X %s%n", i, trk);
}
return tracks;
}
@ -183,12 +219,9 @@ public class Dumper
private byte[] readFile (File file)
// ---------------------------------------------------------------------------------//
{
try
try (BufferedInputStream in = new BufferedInputStream (new FileInputStream (file)))
{
BufferedInputStream in = new BufferedInputStream (new FileInputStream (file));
byte[] buffer = in.readAllBytes ();
in.close ();
return buffer;
return in.readAllBytes ();
}
catch (IOException e)
{
@ -201,7 +234,9 @@ public class Dumper
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/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);
@ -213,7 +248,7 @@ public class Dumper
}
// ---------------------------------------------------------------------------------//
class Track
class Track implements Iterable<Sector>
// ---------------------------------------------------------------------------------//
{
int trackNo;
@ -249,25 +284,26 @@ public class Dumper
int offset = -1;
while (sectors.size () < 13) // hard-coded!!
while (sectors.size () < diskSectors)
{
offset = findNext (address13prologue, offset + 1);
offset = findNext (addressPrologue, offset + 1);
if (offset < 0)
break;
Sector sector = new Sector (this, offset);
if (sectors.size () > 0)
checkDuplicates (sector, sectors.get (sectors.size () - 1));
checkDuplicates (sector);
sectors.add (sector);
}
}
// ---------------------------------------------------------------------------------//
private void checkDuplicates (Sector sector1, Sector sector2)
private void checkDuplicates (Sector sector1)
// ---------------------------------------------------------------------------------//
{
if (sector1.sector == sector2.sector)
System.out.println ("\n*** duplicate ***\n");
for (Sector sector : sectors)
if (sector1.sector == sector.sector)
System.out.println ("\n*** duplicate ***\n");
}
// ---------------------------------------------------------------------------------//
@ -296,27 +332,23 @@ public class Dumper
int nextByte ()
// ---------------------------------------------------------------------------------//
{
while (!nextBit ())
if (revolutions >= 2)
{
System.out.println ("looping");
return 0;
}
int b = 0x80;
for (int i = 6; i >= 0; i--)
byte b = 0;
while ((b & 0x80) == 0)
{
b <<= 1;
if (nextBit ())
b |= (1 << i);
b |= 0x01;
}
return b;
}
// ---------------------------------------------------------------------------------//
byte[] readTrack ()
void readTrack ()
// ---------------------------------------------------------------------------------//
{
if (newBuffer != null)
return newBuffer;
return;
int max = (bitCount - 1) / 8 + 1;
max += 520;
@ -324,8 +356,6 @@ public class Dumper
for (int i = 0; i < max; i++)
newBuffer[i] = (byte) nextByte ();
return newBuffer;
}
// ---------------------------------------------------------------------------------//
@ -346,6 +376,20 @@ public class Dumper
return -1;
}
// ---------------------------------------------------------------------------------//
void packSector (int sector)
// ---------------------------------------------------------------------------------//
{
}
// ---------------------------------------------------------------------------------//
void dump ()
// ---------------------------------------------------------------------------------//
{
System.out.println (HexFormatter.format (newBuffer));
}
// ---------------------------------------------------------------------------------//
@Override
public String toString ()
@ -360,6 +404,14 @@ public class Dumper
text.deleteCharAt (text.length () - 1);
return text.toString ();
}
// ---------------------------------------------------------------------------------//
@Override
public Iterator<Sector> iterator ()
// ---------------------------------------------------------------------------------//
{
return sectors.iterator ();
}
}
// ---------------------------------------------------------------------------------//
@ -397,6 +449,14 @@ public class Dumper
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 ()