mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2024-06-01 03:41:29 +00:00
Allow partial unpacking of corrupt NuFX disks
This commit is contained in:
parent
90f8657722
commit
a72bdff81d
|
@ -19,6 +19,7 @@ import com.bytezone.diskbrowser.nib.WozFile;
|
||||||
import com.bytezone.diskbrowser.utilities.Binary2;
|
import com.bytezone.diskbrowser.utilities.Binary2;
|
||||||
import com.bytezone.diskbrowser.utilities.FileFormatException;
|
import com.bytezone.diskbrowser.utilities.FileFormatException;
|
||||||
import com.bytezone.diskbrowser.utilities.NuFX;
|
import com.bytezone.diskbrowser.utilities.NuFX;
|
||||||
|
import com.bytezone.diskbrowser.utilities.Utility;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
public class AppleDisk implements Disk
|
public class AppleDisk implements Disk
|
||||||
|
@ -42,6 +43,8 @@ public class AppleDisk implements Disk
|
||||||
private NuFX nuFX;
|
private NuFX nuFX;
|
||||||
private Binary2 bin2;
|
private Binary2 bin2;
|
||||||
private WozFile wozFile;
|
private WozFile wozFile;
|
||||||
|
private PrefixDiskCopy prefixDiskCopy;
|
||||||
|
private Prefix2mg prefix2mg;
|
||||||
|
|
||||||
private int interleave = 0;
|
private int interleave = 0;
|
||||||
private static int[][] interleaveSector = //
|
private static int[][] interleaveSector = //
|
||||||
|
@ -119,7 +122,7 @@ public class AppleDisk implements Disk
|
||||||
{
|
{
|
||||||
if ("2IMG".equals (prefix))
|
if ("2IMG".equals (prefix))
|
||||||
{
|
{
|
||||||
Prefix2mg prefix2mg = new Prefix2mg (buffer);
|
prefix2mg = new Prefix2mg (buffer);
|
||||||
if (debug)
|
if (debug)
|
||||||
System.out.println (prefix2mg);
|
System.out.println (prefix2mg);
|
||||||
|
|
||||||
|
@ -145,7 +148,7 @@ public class AppleDisk implements Disk
|
||||||
}
|
}
|
||||||
else if ("img".equals (suffix) || "dimg".equals (suffix))
|
else if ("img".equals (suffix) || "dimg".equals (suffix))
|
||||||
{
|
{
|
||||||
PrefixDiskCopy prefixDiskCopy = new PrefixDiskCopy (buffer);
|
prefixDiskCopy = new PrefixDiskCopy (buffer);
|
||||||
|
|
||||||
blocks = prefixDiskCopy.getBlocks ();
|
blocks = prefixDiskCopy.getBlocks ();
|
||||||
this.sectorSize = 512;
|
this.sectorSize = 512;
|
||||||
|
@ -741,25 +744,20 @@ public class AppleDisk implements Disk
|
||||||
text.append (String.format ("Blocks............... %,d%n", blocks));
|
text.append (String.format ("Blocks............... %,d%n", blocks));
|
||||||
text.append (String.format ("Track size........... %,d%n", trackSize));
|
text.append (String.format ("Track size........... %,d%n", trackSize));
|
||||||
text.append (String.format ("Sector size.......... %d%n", sectorSize));
|
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)
|
if (wozFile != null)
|
||||||
{
|
|
||||||
text.append ("\n\n");
|
|
||||||
text.append (wozFile);
|
text.append (wozFile);
|
||||||
}
|
|
||||||
else if (nuFX != null)
|
else if (nuFX != null)
|
||||||
{
|
|
||||||
text.append ("\n\n");
|
|
||||||
text.append (nuFX);
|
text.append (nuFX);
|
||||||
}
|
|
||||||
else if (bin2 != null)
|
else if (bin2 != null)
|
||||||
{
|
|
||||||
text.append ("\n\n");
|
|
||||||
text.append (bin2);
|
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 ();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
|
|
@ -140,8 +140,9 @@ public class DiskFactory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("sdk".equals (suffix) || "shk".equals (suffix) // shrinkit disk/file archive
|
if ("sdk".equals (suffix) // NuFX disk
|
||||||
|| "bxy".equals (suffix))
|
|| "shk".equals (suffix) // NuFX files or disk
|
||||||
|
|| "bxy".equals (suffix)) // NuFX in Binary2
|
||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
System.out.println (" ** sdk/shk/bxy **");
|
System.out.println (" ** sdk/shk/bxy **");
|
||||||
|
@ -169,10 +170,11 @@ public class DiskFactory
|
||||||
// e.printStackTrace ();
|
// e.printStackTrace ();
|
||||||
System.out.println (e.getMessage ());
|
System.out.println (e.getMessage ());
|
||||||
System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ());
|
System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ());
|
||||||
|
System.out.println (nuFX);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ("bny".equals (suffix))
|
else if ("bny".equals (suffix)) // Binary2 uncompressed files
|
||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
System.out.println (" ** bny **");
|
System.out.println (" ** bny **");
|
||||||
|
@ -196,6 +198,7 @@ public class DiskFactory
|
||||||
// e.printStackTrace ();
|
// e.printStackTrace ();
|
||||||
System.out.println (e.getMessage ());
|
System.out.println (e.getMessage ());
|
||||||
System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ());
|
System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ());
|
||||||
|
System.out.println (binary2);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
import com.bytezone.diskbrowser.utilities.Utility;
|
import com.bytezone.diskbrowser.utilities.Utility;
|
||||||
|
|
||||||
// https://www.discferret.com/wiki/Apple_DiskCopy_4.2
|
// https://www.discferret.com/wiki/Apple_DiskCopy_4.2
|
||||||
|
// Apple II File Type Notes $E0/0005 (macintosh)
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
public class PrefixDiskCopy
|
public class PrefixDiskCopy
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
|
@ -11,9 +12,11 @@ public class PrefixDiskCopy
|
||||||
private String name;
|
private String name;
|
||||||
private int dataSize;
|
private int dataSize;
|
||||||
private int tagSize;
|
private int tagSize;
|
||||||
private int encoding;
|
private int dataChecksum;
|
||||||
|
private int tagChecksum;
|
||||||
|
private int diskFormat;
|
||||||
private int format;
|
private int format;
|
||||||
private int id;
|
private int id; // should be 0x0100
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
public PrefixDiskCopy (byte[] buffer)
|
public PrefixDiskCopy (byte[] buffer)
|
||||||
|
@ -24,7 +27,9 @@ public class PrefixDiskCopy
|
||||||
name = HexFormatter.getPascalString (buffer, 0);
|
name = HexFormatter.getPascalString (buffer, 0);
|
||||||
dataSize = Utility.getLongBigEndian (buffer, 0x40);
|
dataSize = Utility.getLongBigEndian (buffer, 0x40);
|
||||||
tagSize = Utility.getLongBigEndian (buffer, 0x44);
|
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;
|
format = buffer[0x51] & 0xFF;
|
||||||
id = Utility.getWordBigEndian (buffer, 0x52);
|
id = Utility.getWordBigEndian (buffer, 0x52);
|
||||||
}
|
}
|
||||||
|
@ -43,12 +48,14 @@ public class PrefixDiskCopy
|
||||||
{
|
{
|
||||||
StringBuilder text = new StringBuilder ();
|
StringBuilder text = new StringBuilder ();
|
||||||
|
|
||||||
text.append (String.format ("Name : %s%n", name));
|
text.append (String.format ("Name : %s%n", name));
|
||||||
text.append (String.format ("Data size : %08X (%<,d)%n", dataSize));
|
text.append (String.format ("Data size : %08X (%<,d)%n", dataSize));
|
||||||
text.append (String.format ("Tag size : %08X (%<,d)%n", tagSize));
|
text.append (String.format ("Tag size : %08X (%<,d)%n", tagSize));
|
||||||
text.append (String.format ("Encoding : %02X%n", encoding));
|
text.append (String.format ("Data checksum : %08X (%<,d)%n", dataChecksum));
|
||||||
text.append (String.format ("Format : %02X%n", format));
|
text.append (String.format ("Tag checksum : %08X (%<,d)%n", tagChecksum));
|
||||||
text.append (String.format ("ID : %04X%n", id));
|
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 ();
|
return text.toString ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ public class ProdosDisk
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
static final String UNDERLINE = "------------------------------------------------\n";
|
static final String UNDERLINE = "------------------------------------------------\n";
|
||||||
|
static final String message = "DiskBrowser";
|
||||||
|
|
||||||
private static final int CATALOG_SIZE = 4;
|
private static final int CATALOG_SIZE = 4;
|
||||||
private static final int BITS_PER_BLOCK = 8 * BLOCK_SIZE;
|
private static final int BITS_PER_BLOCK = 8 * BLOCK_SIZE;
|
||||||
|
@ -82,6 +83,7 @@ public class ProdosDisk
|
||||||
allocateNextBlock ();
|
allocateNextBlock ();
|
||||||
|
|
||||||
System.arraycopy (bootSector, 0, buffer, 0, 512);
|
System.arraycopy (bootSector, 0, buffer, 0, 512);
|
||||||
|
System.arraycopy (message.getBytes (), 0, buffer, 768, message.length ());
|
||||||
|
|
||||||
// write 4 catalog blocks
|
// write 4 catalog blocks
|
||||||
for (int i = 0, prevBlockNo = 0; i < CATALOG_SIZE; i++)
|
for (int i = 0, prevBlockNo = 0; i < CATALOG_SIZE; i++)
|
||||||
|
|
|
@ -98,6 +98,7 @@ public class Binary2Header
|
||||||
{
|
{
|
||||||
StringBuilder text = new StringBuilder ();
|
StringBuilder text = new StringBuilder ();
|
||||||
|
|
||||||
|
text.append ("Binary2 Header\n==============\n");
|
||||||
text.append (String.format ("Access ................ %02X%n", accessCode));
|
text.append (String.format ("Access ................ %02X%n", accessCode));
|
||||||
text.append (String.format ("File type ............. %02X%n", fileType));
|
text.append (String.format ("File type ............. %02X%n", fileType));
|
||||||
text.append (String.format ("Aux type .............. %04X%n", auxType));
|
text.append (String.format ("Aux type .............. %04X%n", auxType));
|
||||||
|
|
|
@ -38,13 +38,22 @@ class MasterHeader
|
||||||
// bin2 = true;
|
// bin2 = true;
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (isBin2 (buffer, ptr))
|
if (isBin2 (buffer, ptr))
|
||||||
{
|
{
|
||||||
binary2Header = new Binary2Header (buffer, 0);
|
binary2Header = new Binary2Header (buffer, 0);
|
||||||
ptr += 128;
|
if (binary2Header.fileType == (byte) 0xE0
|
||||||
bin2 = true;
|
&& (binary2Header.auxType == 0x8000 || binary2Header.auxType == 0x8002))
|
||||||
continue;
|
{
|
||||||
|
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");
|
throw new FileFormatException ("NuFile not found");
|
||||||
|
|
|
@ -155,7 +155,17 @@ public class NuFX
|
||||||
int auxType = record.getAuxType ();
|
int auxType = record.getAuxType ();
|
||||||
LocalDateTime created = record.getCreated ();
|
LocalDateTime created = record.getCreated ();
|
||||||
LocalDateTime modified = record.getModified ();
|
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)
|
if (debug)
|
||||||
System.out.printf ("%3d %-35s %02X %,7d %,7d %,7d %s %s%n", ++count,
|
System.out.printf ("%3d %-35s %02X %,7d %,7d %,7d %s %s%n", ++count,
|
||||||
|
@ -175,7 +185,16 @@ public class NuFX
|
||||||
|
|
||||||
if (record.hasResource ())
|
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);
|
disk.addResourceFork (fileEntry, buffer, buffer.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user