From a72bdff81d551b4a42520ca5a51b817dc5a069f0 Mon Sep 17 00:00:00 2001 From: Denis Molony Date: Thu, 13 May 2021 14:56:56 +1000 Subject: [PATCH] Allow partial unpacking of corrupt NuFX disks --- .../bytezone/diskbrowser/disk/AppleDisk.java | 24 ++++++++---------- .../diskbrowser/disk/DiskFactory.java | 9 ++++--- .../diskbrowser/disk/PrefixDiskCopy.java | 25 ++++++++++++------- .../diskbrowser/prodos/write/ProdosDisk.java | 2 ++ .../diskbrowser/utilities/Binary2Header.java | 1 + .../diskbrowser/utilities/MasterHeader.java | 17 ++++++++++--- .../bytezone/diskbrowser/utilities/NuFX.java | 23 +++++++++++++++-- 7 files changed, 70 insertions(+), 31 deletions(-) diff --git a/src/com/bytezone/diskbrowser/disk/AppleDisk.java b/src/com/bytezone/diskbrowser/disk/AppleDisk.java index bb2e55d..779ddfd 100755 --- a/src/com/bytezone/diskbrowser/disk/AppleDisk.java +++ b/src/com/bytezone/diskbrowser/disk/AppleDisk.java @@ -19,6 +19,7 @@ import com.bytezone.diskbrowser.nib.WozFile; import com.bytezone.diskbrowser.utilities.Binary2; import com.bytezone.diskbrowser.utilities.FileFormatException; import com.bytezone.diskbrowser.utilities.NuFX; +import com.bytezone.diskbrowser.utilities.Utility; // -----------------------------------------------------------------------------------// public class AppleDisk implements Disk @@ -42,6 +43,8 @@ public class AppleDisk implements Disk private NuFX nuFX; private Binary2 bin2; private WozFile wozFile; + private PrefixDiskCopy prefixDiskCopy; + private Prefix2mg prefix2mg; private int interleave = 0; private static int[][] interleaveSector = // @@ -119,7 +122,7 @@ public class AppleDisk implements Disk { if ("2IMG".equals (prefix)) { - Prefix2mg prefix2mg = new Prefix2mg (buffer); + prefix2mg = new Prefix2mg (buffer); if (debug) System.out.println (prefix2mg); @@ -145,7 +148,7 @@ public class AppleDisk implements Disk } else if ("img".equals (suffix) || "dimg".equals (suffix)) { - PrefixDiskCopy prefixDiskCopy = new PrefixDiskCopy (buffer); + prefixDiskCopy = new PrefixDiskCopy (buffer); blocks = prefixDiskCopy.getBlocks (); this.sectorSize = 512; @@ -741,25 +744,20 @@ public class AppleDisk implements Disk text.append (String.format ("Blocks............... %,d%n", blocks)); text.append (String.format ("Track size........... %,d%n", trackSize)); text.append (String.format ("Sector size.......... %d%n", sectorSize)); - text.append (String.format ("Interleave........... %d", interleave)); + text.append (String.format ("Interleave........... %d%n%n", interleave)); if (wozFile != null) - { - text.append ("\n\n"); text.append (wozFile); - } else if (nuFX != null) - { - text.append ("\n\n"); text.append (nuFX); - } else if (bin2 != null) - { - text.append ("\n\n"); text.append (bin2); - } + else if (prefixDiskCopy != null) + text.append (prefixDiskCopy); + else if (prefix2mg != null) + text.append (prefix2mg); - return text.toString (); + return Utility.rtrim (text).toString (); } // ---------------------------------------------------------------------------------// diff --git a/src/com/bytezone/diskbrowser/disk/DiskFactory.java b/src/com/bytezone/diskbrowser/disk/DiskFactory.java index 519fe87..a3a0e60 100755 --- a/src/com/bytezone/diskbrowser/disk/DiskFactory.java +++ b/src/com/bytezone/diskbrowser/disk/DiskFactory.java @@ -140,8 +140,9 @@ public class DiskFactory } } - if ("sdk".equals (suffix) || "shk".equals (suffix) // shrinkit disk/file archive - || "bxy".equals (suffix)) + if ("sdk".equals (suffix) // NuFX disk + || "shk".equals (suffix) // NuFX files or disk + || "bxy".equals (suffix)) // NuFX in Binary2 { if (debug) System.out.println (" ** sdk/shk/bxy **"); @@ -169,10 +170,11 @@ public class DiskFactory // e.printStackTrace (); System.out.println (e.getMessage ()); System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ()); + System.out.println (nuFX); return null; } } - else if ("bny".equals (suffix)) + else if ("bny".equals (suffix)) // Binary2 uncompressed files { if (debug) System.out.println (" ** bny **"); @@ -196,6 +198,7 @@ public class DiskFactory // e.printStackTrace (); System.out.println (e.getMessage ()); System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ()); + System.out.println (binary2); return null; } } diff --git a/src/com/bytezone/diskbrowser/disk/PrefixDiskCopy.java b/src/com/bytezone/diskbrowser/disk/PrefixDiskCopy.java index 406b697..28654a0 100644 --- a/src/com/bytezone/diskbrowser/disk/PrefixDiskCopy.java +++ b/src/com/bytezone/diskbrowser/disk/PrefixDiskCopy.java @@ -4,6 +4,7 @@ import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.Utility; // https://www.discferret.com/wiki/Apple_DiskCopy_4.2 +// Apple II File Type Notes $E0/0005 (macintosh) // -----------------------------------------------------------------------------------// public class PrefixDiskCopy // -----------------------------------------------------------------------------------// @@ -11,9 +12,11 @@ public class PrefixDiskCopy private String name; private int dataSize; private int tagSize; - private int encoding; + private int dataChecksum; + private int tagChecksum; + private int diskFormat; private int format; - private int id; + private int id; // should be 0x0100 // ---------------------------------------------------------------------------------// public PrefixDiskCopy (byte[] buffer) @@ -24,7 +27,9 @@ public class PrefixDiskCopy name = HexFormatter.getPascalString (buffer, 0); dataSize = Utility.getLongBigEndian (buffer, 0x40); tagSize = Utility.getLongBigEndian (buffer, 0x44); - encoding = buffer[0x50] & 0xFF; + dataChecksum = Utility.getLongBigEndian (buffer, 0x48); + tagChecksum = Utility.getLongBigEndian (buffer, 0x4C); + diskFormat = buffer[0x50] & 0xFF; format = buffer[0x51] & 0xFF; id = Utility.getWordBigEndian (buffer, 0x52); } @@ -43,12 +48,14 @@ public class PrefixDiskCopy { StringBuilder text = new StringBuilder (); - text.append (String.format ("Name : %s%n", name)); - text.append (String.format ("Data size : %08X (%<,d)%n", dataSize)); - text.append (String.format ("Tag size : %08X (%<,d)%n", tagSize)); - text.append (String.format ("Encoding : %02X%n", encoding)); - text.append (String.format ("Format : %02X%n", format)); - text.append (String.format ("ID : %04X%n", id)); + text.append (String.format ("Name : %s%n", name)); + text.append (String.format ("Data size : %08X (%<,d)%n", dataSize)); + text.append (String.format ("Tag size : %08X (%<,d)%n", tagSize)); + text.append (String.format ("Data checksum : %08X (%<,d)%n", dataChecksum)); + text.append (String.format ("Tag checksum : %08X (%<,d)%n", tagChecksum)); + text.append (String.format ("Disk format : %02X%n", diskFormat)); + text.append (String.format ("Format byte : %02X%n", format)); + text.append (String.format ("ID : %04X%n", id)); return text.toString (); } diff --git a/src/com/bytezone/diskbrowser/prodos/write/ProdosDisk.java b/src/com/bytezone/diskbrowser/prodos/write/ProdosDisk.java index 67af2fe..b2786be 100644 --- a/src/com/bytezone/diskbrowser/prodos/write/ProdosDisk.java +++ b/src/com/bytezone/diskbrowser/prodos/write/ProdosDisk.java @@ -26,6 +26,7 @@ public class ProdosDisk // -----------------------------------------------------------------------------------// { static final String UNDERLINE = "------------------------------------------------\n"; + static final String message = "DiskBrowser"; private static final int CATALOG_SIZE = 4; private static final int BITS_PER_BLOCK = 8 * BLOCK_SIZE; @@ -82,6 +83,7 @@ public class ProdosDisk allocateNextBlock (); System.arraycopy (bootSector, 0, buffer, 0, 512); + System.arraycopy (message.getBytes (), 0, buffer, 768, message.length ()); // write 4 catalog blocks for (int i = 0, prevBlockNo = 0; i < CATALOG_SIZE; i++) diff --git a/src/com/bytezone/diskbrowser/utilities/Binary2Header.java b/src/com/bytezone/diskbrowser/utilities/Binary2Header.java index a76a93a..f9b933c 100644 --- a/src/com/bytezone/diskbrowser/utilities/Binary2Header.java +++ b/src/com/bytezone/diskbrowser/utilities/Binary2Header.java @@ -98,6 +98,7 @@ public class Binary2Header { StringBuilder text = new StringBuilder (); + text.append ("Binary2 Header\n==============\n"); text.append (String.format ("Access ................ %02X%n", accessCode)); text.append (String.format ("File type ............. %02X%n", fileType)); text.append (String.format ("Aux type .............. %04X%n", auxType)); diff --git a/src/com/bytezone/diskbrowser/utilities/MasterHeader.java b/src/com/bytezone/diskbrowser/utilities/MasterHeader.java index 2225a6e..241aa64 100644 --- a/src/com/bytezone/diskbrowser/utilities/MasterHeader.java +++ b/src/com/bytezone/diskbrowser/utilities/MasterHeader.java @@ -38,13 +38,22 @@ class MasterHeader // bin2 = true; // break; // } - if (isBin2 (buffer, ptr)) { binary2Header = new Binary2Header (buffer, 0); - ptr += 128; - bin2 = true; - continue; + if (binary2Header.fileType == (byte) 0xE0 + && (binary2Header.auxType == 0x8000 || binary2Header.auxType == 0x8002)) + { + ptr += 128; + bin2 = true; + continue; + } + else + { + System.out.printf ("Not NuFX: %02X %04X%n", binary2Header.fileType, + binary2Header.auxType); + System.out.println (binary2Header); + } } throw new FileFormatException ("NuFile not found"); diff --git a/src/com/bytezone/diskbrowser/utilities/NuFX.java b/src/com/bytezone/diskbrowser/utilities/NuFX.java index e65dc7c..c5aa31b 100644 --- a/src/com/bytezone/diskbrowser/utilities/NuFX.java +++ b/src/com/bytezone/diskbrowser/utilities/NuFX.java @@ -155,7 +155,17 @@ public class NuFX int auxType = record.getAuxType (); LocalDateTime created = record.getCreated (); LocalDateTime modified = record.getModified (); - byte[] buffer = record.getData (); + byte[] buffer; + try + { + buffer = record.getData (); + } + catch (Exception e) + { + System.out.println (e.getMessage ()); + System.out.printf ("Failed to unpack: %s%n", fileName); + continue; + } if (debug) System.out.printf ("%3d %-35s %02X %,7d %,7d %,7d %s %s%n", ++count, @@ -175,7 +185,16 @@ public class NuFX if (record.hasResource ()) { - buffer = record.getResourceData (); + try + { + buffer = record.getResourceData (); + } + catch (Exception e) + { + System.out.println (e.getMessage ()); + System.out.printf ("Failed to unpack resource fork: %s%n", fileName); + continue; + } disk.addResourceFork (fileEntry, buffer, buffer.length); } }