From 07155c7a35f517c7be73e60a49f11dee35535ea3 Mon Sep 17 00:00:00 2001 From: Denis Molony Date: Sun, 28 Jul 2019 16:24:52 +1000 Subject: [PATCH] woz shenanigans --- .../diskbrowser/applefile/HiResImage.java | 22 +- .../applefile/SHRPictureFile2.java | 1 + .../bytezone/diskbrowser/nib/DiskReader.java | 7 +- .../diskbrowser/nib/DiskReader13Sector.java | 4 +- .../diskbrowser/nib/DiskReader16Sector.java | 4 +- src/com/bytezone/diskbrowser/nib/Dumper.java | 190 ++++++++++++------ 6 files changed, 149 insertions(+), 79 deletions(-) diff --git a/src/com/bytezone/diskbrowser/applefile/HiResImage.java b/src/com/bytezone/diskbrowser/applefile/HiResImage.java index 80e6e65..03216b7 100644 --- a/src/com/bytezone/diskbrowser/applefile/HiResImage.java +++ b/src/com/bytezone/diskbrowser/applefile/HiResImage.java @@ -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: diff --git a/src/com/bytezone/diskbrowser/applefile/SHRPictureFile2.java b/src/com/bytezone/diskbrowser/applefile/SHRPictureFile2.java index e16aeba..ea165b0 100644 --- a/src/com/bytezone/diskbrowser/applefile/SHRPictureFile2.java +++ b/src/com/bytezone/diskbrowser/applefile/SHRPictureFile2.java @@ -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 diff --git a/src/com/bytezone/diskbrowser/nib/DiskReader.java b/src/com/bytezone/diskbrowser/nib/DiskReader.java index 1265ad4..8f09e84 100644 --- a/src/com/bytezone/diskbrowser/nib/DiskReader.java +++ b/src/com/bytezone/diskbrowser/nib/DiskReader.java @@ -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); diff --git a/src/com/bytezone/diskbrowser/nib/DiskReader13Sector.java b/src/com/bytezone/diskbrowser/nib/DiskReader13Sector.java index 5fe4b8e..d59db5e 100644 --- a/src/com/bytezone/diskbrowser/nib/DiskReader13Sector.java +++ b/src/com/bytezone/diskbrowser/nib/DiskReader13Sector.java @@ -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 diff --git a/src/com/bytezone/diskbrowser/nib/DiskReader16Sector.java b/src/com/bytezone/diskbrowser/nib/DiskReader16Sector.java index 3e151a7..254754c 100644 --- a/src/com/bytezone/diskbrowser/nib/DiskReader16Sector.java +++ b/src/com/bytezone/diskbrowser/nib/DiskReader16Sector.java @@ -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 diff --git a/src/com/bytezone/diskbrowser/nib/Dumper.java b/src/com/bytezone/diskbrowser/nib/Dumper.java index 52fdb84..e61e5d5 100644 --- a/src/com/bytezone/diskbrowser/nib/Dumper.java +++ b/src/com/bytezone/diskbrowser/nib/Dumper.java @@ -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 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 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 // ---------------------------------------------------------------------------------// { 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 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 ()