Split NuFX

This commit is contained in:
Denis Molony 2021-03-29 11:04:01 +10:00
parent ce16479742
commit 2168025e80
6 changed files with 254 additions and 218 deletions

View File

@ -152,7 +152,7 @@ public class DiskFactory
System.out.println (" ** sdk **");
try
{
NuFX nuFX = new NuFX (file);
NuFX nuFX = new NuFX (file.toPath ());
File tmp = File.createTempFile ("sdk", null);
FileOutputStream fos = new FileOutputStream (tmp);
fos.write (nuFX.getBuffer ());

View File

@ -0,0 +1,96 @@
package com.bytezone.diskbrowser.utilities;
// -----------------------------------------------------------------------------------//
class Header
// -----------------------------------------------------------------------------------//
{
private final int totalRecords;
private final int version;
private final int eof;
private final int crc;
private final DateTime created;
private final DateTime modified;
boolean bin2;
// ---------------------------------------------------------------------------------//
public Header (byte[] buffer) throws FileFormatException
// ---------------------------------------------------------------------------------//
{
int ptr = 0;
while (true)
{
if (isNuFile (buffer, ptr))
break;
if (isBin2 (buffer, ptr))
{
ptr += 128;
bin2 = true;
continue;
}
throw new FileFormatException ("NuFile not found");
}
crc = Utility.getWord (buffer, ptr + 6);
totalRecords = Utility.getLong (buffer, ptr + 8);
created = new DateTime (buffer, ptr + 12);
modified = new DateTime (buffer, ptr + 20);
version = Utility.getWord (buffer, ptr + 28);
eof = Utility.getLong (buffer, ptr + 38);
byte[] crcBuffer = new byte[40];
System.arraycopy (buffer, ptr + 8, crcBuffer, 0, crcBuffer.length);
if (crc != Utility.getCRC (crcBuffer, 0))
{
System.out.println ("***** Master CRC mismatch *****");
throw new FileFormatException ("Master CRC failed");
}
}
// ---------------------------------------------------------------------------------//
int getTotalRecords ()
// ---------------------------------------------------------------------------------//
{
return totalRecords;
}
// ---------------------------------------------------------------------------------//
private boolean isNuFile (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
if (buffer[ptr] == 0x4E && buffer[ptr + 1] == (byte) 0xF5 && buffer[ptr + 2] == 0x46
&& buffer[ptr + 3] == (byte) 0xE9 && buffer[ptr + 4] == 0x6C
&& buffer[ptr + 5] == (byte) 0xE5)
return true;
return false;
}
// ---------------------------------------------------------------------------------//
private boolean isBin2 (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
if (buffer[ptr] == 0x0A && buffer[ptr + 1] == 0x47 && buffer[ptr + 2] == 0x4C
&& buffer[ptr + 18] == (byte) 0x02)
return true;
return false;
}
// ---------------------------------------------------------------------------------//
@Override
public String toString ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
text.append (String.format ("Master CRC ..... %,d (%04X)%n", crc, crc));
text.append (String.format ("Records ........ %,d%n", totalRecords));
text.append (String.format ("Created ........ %s%n", created.format ()));
text.append (String.format ("Modified ....... %s%n", modified.format ()));
text.append (String.format ("Version ........ %,d%n", version));
text.append (String.format ("Master EOF ..... %,d", eof));
return text.toString ();
}
}

View File

@ -118,7 +118,7 @@ class LZW
for (byte[] track : chunks)
System.arraycopy (track, 0, buffer, trackNumber++ * TRACK_LENGTH, TRACK_LENGTH);
if (crc != NuFX.getCRC (buffer, crcBase))
if (crc != Utility.getCRC (buffer, crcBase))
System.out.println ("\n*** LZW CRC mismatch ***");
return buffer;

View File

@ -1,6 +1,5 @@
package com.bytezone.diskbrowser.utilities;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@ -11,10 +10,6 @@ import java.util.List;
public class NuFX
// -----------------------------------------------------------------------------------//
{
private static String[] fileSystems =
{ "", "ProDOS/SOS", "DOS 3.3", "DOS 3.2", "Apple II Pascal", "Macintosh HFS",
"Macintosh MFS", "Lisa File System", "Apple CP/M", "", "MS-DOS", "High Sierra",
"ISO 9660", "AppleShare" };
private Header header;
private final byte[] buffer;
private final boolean debug = false;
@ -30,14 +25,6 @@ public class NuFX
readBuffer ();
}
// ---------------------------------------------------------------------------------//
public NuFX (File file) throws FileFormatException, IOException
// ---------------------------------------------------------------------------------//
{
buffer = Files.readAllBytes (file.toPath ());
readBuffer ();
}
// ---------------------------------------------------------------------------------//
private void readBuffer ()
// ---------------------------------------------------------------------------------//
@ -51,19 +38,19 @@ public class NuFX
if (debug)
System.out.printf ("%s%n%n", header);
for (int rec = 0; rec < header.totalRecords; rec++)
for (int rec = 0; rec < header.getTotalRecords (); rec++)
{
Record record = new Record (dataPtr);
Record record = new Record (buffer, dataPtr);
records.add (record);
if (debug)
System.out.printf ("Record: %d%n%n%s%n%n", rec, record);
dataPtr += record.attributes + record.fileNameLength;
dataPtr += record.getAttributes () + record.getFileNameLength ();
int threadsPtr = dataPtr;
dataPtr += record.totThreads * 16;
dataPtr += record.getTotalThreads () * 16;
for (int i = 0; i < record.totThreads; i++)
for (int i = 0; i < record.getTotalThreads (); i++)
{
Thread thread = new Thread (buffer, threadsPtr + i * 16, dataPtr);
threads.add (thread);
@ -95,202 +82,4 @@ public class NuFX
return thread.toString ();
return "no disk";
}
// ---------------------------------------------------------------------------------//
protected static int getCRC (final byte[] buffer, int base)
// ---------------------------------------------------------------------------------//
{
int crc = base;
for (int j = 0; j < buffer.length; j++)
{
crc = ((crc >>> 8) | (crc << 8)) & 0xFFFF;
crc ^= (buffer[j] & 0xFF);
crc ^= ((crc & 0xFF) >>> 4);
crc ^= (crc << 12) & 0xFFFF;
crc ^= ((crc & 0xFF) << 5) & 0xFFFF;
}
crc &= 0xFFFF;
return crc;
}
// ---------------------------------------------------------------------------------//
class Header
// ---------------------------------------------------------------------------------//
{
private final int totalRecords;
private final int version;
private final int eof;
private final int crc;
private final DateTime created;
private final DateTime modified;
boolean bin2;
public Header (byte[] buffer) throws FileFormatException
{
int ptr = 0;
while (true)
{
if (isNuFile (buffer, ptr))
break;
if (isBin2 (buffer, ptr))
{
ptr += 128;
bin2 = true;
continue;
}
throw new FileFormatException ("NuFile not found");
}
crc = Utility.getWord (buffer, ptr + 6);
totalRecords = Utility.getLong (buffer, ptr + 8);
created = new DateTime (buffer, ptr + 12);
modified = new DateTime (buffer, ptr + 20);
version = Utility.getWord (buffer, ptr + 28);
eof = Utility.getLong (buffer, ptr + 38);
byte[] crcBuffer = new byte[40];
System.arraycopy (buffer, ptr + 8, crcBuffer, 0, crcBuffer.length);
if (crc != getCRC (crcBuffer, 0))
{
System.out.println ("***** Master CRC mismatch *****");
throw new FileFormatException ("Master CRC failed");
}
}
private boolean isNuFile (byte[] buffer, int ptr)
{
if (buffer[ptr] == 0x4E && buffer[ptr + 1] == (byte) 0xF5 && buffer[ptr + 2] == 0x46
&& buffer[ptr + 3] == (byte) 0xE9 && buffer[ptr + 4] == 0x6C
&& buffer[ptr + 5] == (byte) 0xE5)
return true;
return false;
}
private boolean isBin2 (byte[] buffer, int ptr)
{
if (buffer[ptr] == 0x0A && buffer[ptr + 1] == 0x47 && buffer[ptr + 2] == 0x4C
&& buffer[ptr + 18] == (byte) 0x02)
return true;
return false;
}
@Override
public String toString ()
{
StringBuilder text = new StringBuilder ();
text.append (String.format ("Master CRC ..... %,d (%04X)%n", crc, crc));
text.append (String.format ("Records ........ %,d%n", totalRecords));
text.append (String.format ("Created ........ %s%n", created.format ()));
text.append (String.format ("Modified ....... %s%n", modified.format ()));
text.append (String.format ("Version ........ %,d%n", version));
text.append (String.format ("Master EOF ..... %,d", eof));
return text.toString ();
}
}
// ---------------------------------------------------------------------------------//
class Record
// ---------------------------------------------------------------------------------//
{
private final int totThreads;
private final int crc;
private final char separator;
private final int fileSystemID;
private final int attributes;
private final int version;
private final int access;
private final int fileType;
private final int auxType;
private final int storType;
private final DateTime created;
private final DateTime modified;
private final DateTime archived;
private final int optionSize;
private final int fileNameLength;
private final String fileName;
public Record (int dataPtr) throws FileFormatException
{
// check for NuFX
if (!isNuFX (buffer, dataPtr))
throw new FileFormatException ("NuFX not found");
crc = Utility.getWord (buffer, dataPtr + 4);
attributes = Utility.getWord (buffer, dataPtr + 6);
version = Utility.getWord (buffer, dataPtr + 8);
totThreads = Utility.getLong (buffer, dataPtr + 10);
fileSystemID = Utility.getWord (buffer, dataPtr + 14);
separator = (char) (buffer[dataPtr + 16] & 0x00FF);
access = Utility.getLong (buffer, dataPtr + 18);
fileType = Utility.getLong (buffer, dataPtr + 22);
auxType = Utility.getLong (buffer, dataPtr + 26);
storType = Utility.getWord (buffer, dataPtr + 30);
created = new DateTime (buffer, dataPtr + 32);
modified = new DateTime (buffer, dataPtr + 40);
archived = new DateTime (buffer, dataPtr + 48);
optionSize = Utility.getWord (buffer, dataPtr + 56);
fileNameLength = Utility.getWord (buffer, dataPtr + attributes - 2);
int len = attributes + fileNameLength - 6;
byte[] crcBuffer = new byte[len + totThreads * 16];
System.arraycopy (buffer, dataPtr + 6, crcBuffer, 0, crcBuffer.length);
if (crc != getCRC (crcBuffer, 0))
{
System.out.println ("***** Header CRC mismatch *****");
throw new FileFormatException ("Header CRC failed");
}
if (fileNameLength > 0)
{
int start = dataPtr + attributes;
int end = start + fileNameLength;
for (int i = start; i < end; i++)
buffer[i] &= 0x7F;
fileName = new String (buffer, start, fileNameLength);
}
else
fileName = "";
}
private boolean isNuFX (byte[] buffer, int ptr)
{
if (buffer[ptr] == 0x4E && buffer[ptr + 1] == (byte) 0xF5 && buffer[ptr + 2] == 0x46
&& buffer[ptr + 3] == (byte) 0xD8)
return true;
return false;
}
@Override
public String toString ()
{
StringBuilder text = new StringBuilder ();
text.append (String.format ("Header CRC ..... %,d (%04X)%n", crc, crc));
text.append (String.format ("Attributes ..... %d%n", attributes));
text.append (String.format ("Version ........ %d%n", version));
text.append (String.format ("Threads ........ %d%n", totThreads));
text.append (String.format ("File sys id .... %d (%s)%n", fileSystemID,
fileSystems[fileSystemID]));
text.append (String.format ("Separator ...... %s%n", separator));
text.append (String.format ("Access ......... %,d%n", access));
text.append (String.format ("File type ...... %,d%n", fileType));
text.append (String.format ("Aux type ....... %,d%n", auxType));
text.append (String.format ("Stor type ...... %,d%n", storType));
text.append (String.format ("Created ........ %s%n", created.format ()));
text.append (String.format ("Modified ....... %s%n", modified.format ()));
text.append (String.format ("Archived ....... %s%n", archived.format ()));
text.append (String.format ("Option size .... %,d%n", optionSize));
text.append (String.format ("Filename len ... %,d%n", fileNameLength));
text.append (String.format ("Filename ....... %s", fileName));
return text.toString ();
}
}
}

View File

@ -0,0 +1,133 @@
package com.bytezone.diskbrowser.utilities;
// -----------------------------------------------------------------------------------//
class Record
// -----------------------------------------------------------------------------------//
{
private static String[] fileSystems =
{ "", "ProDOS/SOS", "DOS 3.3", "DOS 3.2", "Apple II Pascal", "Macintosh HFS",
"Macintosh MFS", "Lisa File System", "Apple CP/M", "", "MS-DOS", "High Sierra",
"ISO 9660", "AppleShare" };
private final int totThreads;
private final int crc;
private final char separator;
private final int fileSystemID;
private final int attributes;
private final int version;
private final int access;
private final int fileType;
private final int auxType;
private final int storType;
private final DateTime created;
private final DateTime modified;
private final DateTime archived;
private final int optionSize;
private final int fileNameLength;
private final String fileName;
// ---------------------------------------------------------------------------------//
public Record (byte[] buffer, int dataPtr) throws FileFormatException
// ---------------------------------------------------------------------------------//
{
// check for NuFX
if (!isNuFX (buffer, dataPtr))
throw new FileFormatException ("NuFX not found");
crc = Utility.getWord (buffer, dataPtr + 4);
attributes = Utility.getWord (buffer, dataPtr + 6);
version = Utility.getWord (buffer, dataPtr + 8);
totThreads = Utility.getLong (buffer, dataPtr + 10);
fileSystemID = Utility.getWord (buffer, dataPtr + 14);
separator = (char) (buffer[dataPtr + 16] & 0x00FF);
access = Utility.getLong (buffer, dataPtr + 18);
fileType = Utility.getLong (buffer, dataPtr + 22);
auxType = Utility.getLong (buffer, dataPtr + 26);
storType = Utility.getWord (buffer, dataPtr + 30);
created = new DateTime (buffer, dataPtr + 32);
modified = new DateTime (buffer, dataPtr + 40);
archived = new DateTime (buffer, dataPtr + 48);
optionSize = Utility.getWord (buffer, dataPtr + 56);
fileNameLength = Utility.getWord (buffer, dataPtr + attributes - 2);
int len = attributes + fileNameLength - 6;
byte[] crcBuffer = new byte[len + totThreads * 16];
System.arraycopy (buffer, dataPtr + 6, crcBuffer, 0, crcBuffer.length);
if (crc != Utility.getCRC (crcBuffer, 0))
{
System.out.println ("***** Header CRC mismatch *****");
throw new FileFormatException ("Header CRC failed");
}
if (fileNameLength > 0)
{
int start = dataPtr + attributes;
int end = start + fileNameLength;
for (int i = start; i < end; i++)
buffer[i] &= 0x7F;
fileName = new String (buffer, start, fileNameLength);
}
else
fileName = "";
}
// ---------------------------------------------------------------------------------//
private boolean isNuFX (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
if (buffer[ptr] == 0x4E && buffer[ptr + 1] == (byte) 0xF5 && buffer[ptr + 2] == 0x46
&& buffer[ptr + 3] == (byte) 0xD8)
return true;
return false;
}
// ---------------------------------------------------------------------------------//
int getAttributes ()
// ---------------------------------------------------------------------------------//
{
return attributes;
}
// ---------------------------------------------------------------------------------//
int getFileNameLength ()
// ---------------------------------------------------------------------------------//
{
return fileNameLength;
}
// ---------------------------------------------------------------------------------//
int getTotalThreads ()
// ---------------------------------------------------------------------------------//
{
return totThreads;
}
// ---------------------------------------------------------------------------------//
@Override
public String toString ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
text.append (String.format ("Header CRC ..... %,d (%04X)%n", crc, crc));
text.append (String.format ("Attributes ..... %d%n", attributes));
text.append (String.format ("Version ........ %d%n", version));
text.append (String.format ("Threads ........ %d%n", totThreads));
text.append (String.format ("File sys id .... %d (%s)%n", fileSystemID,
fileSystems[fileSystemID]));
text.append (String.format ("Separator ...... %s%n", separator));
text.append (String.format ("Access ......... %,d%n", access));
text.append (String.format ("File type ...... %,d%n", fileType));
text.append (String.format ("Aux type ....... %,d%n", auxType));
text.append (String.format ("Stor type ...... %,d%n", storType));
text.append (String.format ("Created ........ %s%n", created.format ()));
text.append (String.format ("Modified ....... %s%n", modified.format ()));
text.append (String.format ("Archived ....... %s%n", archived.format ()));
text.append (String.format ("Option size .... %,d%n", optionSize));
text.append (String.format ("Filename len ... %,d%n", fileNameLength));
text.append (String.format ("Filename ....... %s", fileName));
return text.toString ();
}
}

View File

@ -365,6 +365,24 @@ public class Utility
return checksum.getValue ();
}
// ---------------------------------------------------------------------------------//
protected static int getCRC (final byte[] buffer, int base)
// ---------------------------------------------------------------------------------//
{
int crc = base;
for (int j = 0; j < buffer.length; j++)
{
crc = ((crc >>> 8) | (crc << 8)) & 0xFFFF;
crc ^= (buffer[j] & 0xFF);
crc ^= ((crc & 0xFF) >>> 4);
crc ^= (crc << 12) & 0xFFFF;
crc ^= ((crc & 0xFF) << 5) & 0xFFFF;
}
crc &= 0xFFFF;
return crc;
}
// ---------------------------------------------------------------------------------//
public static int crc32 (byte[] buffer, int offset, int length)
// ---------------------------------------------------------------------------------//