diff --git a/src/com/bytezone/diskbrowser/utilities/DateTime.java b/src/com/bytezone/diskbrowser/utilities/DateTime.java index fe4594d..027803c 100644 --- a/src/com/bytezone/diskbrowser/utilities/DateTime.java +++ b/src/com/bytezone/diskbrowser/utilities/DateTime.java @@ -1,6 +1,7 @@ package com.bytezone.diskbrowser.utilities; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; // -----------------------------------------------------------------------------------// class DateTime @@ -10,6 +11,8 @@ class DateTime "Aug", "Sep", "Oct", "Nov", "Dec" }; private static String[] days = { "", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; + private static final DateTimeFormatter dtf = + DateTimeFormatter.ofPattern ("dd-LLL-yy HH:mm"); private final int second; private final int minute; @@ -41,6 +44,14 @@ class DateTime days[weekDay], day, months[month], year); } + // ---------------------------------------------------------------------------------// + public String format2 () + // ---------------------------------------------------------------------------------// + { + LocalDateTime dateTime = getLocalDateTime (); + return dateTime == null ? "" : getLocalDateTime ().format (dtf); + } + // ---------------------------------------------------------------------------------// public LocalDateTime getLocalDateTime () // ---------------------------------------------------------------------------------// diff --git a/src/com/bytezone/diskbrowser/utilities/LZW.java b/src/com/bytezone/diskbrowser/utilities/LZW.java index 0064004..dda1583 100644 --- a/src/com/bytezone/diskbrowser/utilities/LZW.java +++ b/src/com/bytezone/diskbrowser/utilities/LZW.java @@ -5,7 +5,7 @@ import java.util.List; import java.util.Objects; // -----------------------------------------------------------------------------------// -class LZW +abstract class LZW // -----------------------------------------------------------------------------------// { static final String[] st = new String[0x1000]; @@ -24,7 +24,9 @@ class LZW private int ptr; private int startPtr; - byte[] bytes; + byte[] buffer; + + boolean unpacked; // ---------------------------------------------------------------------------------// static @@ -38,9 +40,13 @@ class LZW LZW (byte[] buffer) // ---------------------------------------------------------------------------------// { - bytes = Objects.requireNonNull (buffer); + this.buffer = Objects.requireNonNull (buffer); } + // ---------------------------------------------------------------------------------// + abstract void unpack (); + // ---------------------------------------------------------------------------------// + // ---------------------------------------------------------------------------------// void setBuffer (int ptr) // ---------------------------------------------------------------------------------// @@ -77,7 +83,7 @@ class LZW { if (bitsLeft == 0) { - byteBuffer = bytes[ptr++] & 0xFF; + byteBuffer = buffer[ptr++] & 0xFF; bitsLeft = 8; } @@ -117,6 +123,11 @@ class LZW int getSize () // ---------------------------------------------------------------------------------// { + if (!unpacked) + { + unpack (); + unpacked = true; + } return chunks.size () * TRACK_LENGTH; } @@ -124,6 +135,12 @@ class LZW byte[] getData () // ---------------------------------------------------------------------------------// { + if (!unpacked) + { + unpack (); + unpacked = true; + } + byte[] buffer = new byte[getSize ()]; int trackNumber = 0; diff --git a/src/com/bytezone/diskbrowser/utilities/LZW1.java b/src/com/bytezone/diskbrowser/utilities/LZW1.java index 1e710b7..85e62c0 100644 --- a/src/com/bytezone/diskbrowser/utilities/LZW1.java +++ b/src/com/bytezone/diskbrowser/utilities/LZW1.java @@ -9,7 +9,14 @@ class LZW1 extends LZW // ---------------------------------------------------------------------------------// { super (buffer); + // unpack (); + } + // ---------------------------------------------------------------------------------// + @Override + void unpack () + // ---------------------------------------------------------------------------------// + { crc = Utility.getWord (buffer, 0); crcBase = 0; diff --git a/src/com/bytezone/diskbrowser/utilities/LZW2.java b/src/com/bytezone/diskbrowser/utilities/LZW2.java index c203a72..77f8bc7 100644 --- a/src/com/bytezone/diskbrowser/utilities/LZW2.java +++ b/src/com/bytezone/diskbrowser/utilities/LZW2.java @@ -17,6 +17,14 @@ class LZW2 extends LZW this.crc = crc; this.v3eof = eof; + // unpack (); + } + + // ---------------------------------------------------------------------------------// + @Override + void unpack () + // ---------------------------------------------------------------------------------// + { crcBase = 0xFFFF; codeWord = 0; diff --git a/src/com/bytezone/diskbrowser/utilities/MasterHeader.java b/src/com/bytezone/diskbrowser/utilities/MasterHeader.java index 366bc38..8c852e5 100644 --- a/src/com/bytezone/diskbrowser/utilities/MasterHeader.java +++ b/src/com/bytezone/diskbrowser/utilities/MasterHeader.java @@ -70,6 +70,41 @@ class MasterHeader return totalRecords; } + // ---------------------------------------------------------------------------------// + String getCreated () + // ---------------------------------------------------------------------------------// + { + return created.format (); + } + + // ---------------------------------------------------------------------------------// + String getModified () + // ---------------------------------------------------------------------------------// + { + return modified.format (); + } + + // ---------------------------------------------------------------------------------// + String getCreated2 () + // ---------------------------------------------------------------------------------// + { + return created.format2 (); + } + + // ---------------------------------------------------------------------------------// + String getModified2 () + // ---------------------------------------------------------------------------------// + { + return modified.format2 (); + } + + // ---------------------------------------------------------------------------------// + long getEof () + // ---------------------------------------------------------------------------------// + { + return eof; + } + // ---------------------------------------------------------------------------------// private boolean isBin2 (byte[] buffer, int ptr) // ---------------------------------------------------------------------------------// diff --git a/src/com/bytezone/diskbrowser/utilities/NuFX.java b/src/com/bytezone/diskbrowser/utilities/NuFX.java index d096f8b..e34e48a 100644 --- a/src/com/bytezone/diskbrowser/utilities/NuFX.java +++ b/src/com/bytezone/diskbrowser/utilities/NuFX.java @@ -16,9 +16,12 @@ import com.bytezone.diskbrowser.prodos.write.VolumeCatalogFullException; public class NuFX // -----------------------------------------------------------------------------------// { + private static final String UNDERLINE = + "------------------------------------------------------" + + "-----------------------"; private MasterHeader masterHeader; private final byte[] buffer; - private final boolean debug = true; + private final boolean debug = false; private final List records = new ArrayList<> (); private int totalFiles; @@ -70,13 +73,13 @@ public class NuFX ++totalFiles; // note: total blocks does not include subdirectory blocks - int blocks = (record.getFileSize () - 1) / 512 + 1; - if (blocks == 1) // seedling - totalBlocks += blocks; - else if (blocks <= 256) // sapling - totalBlocks += blocks + 1; - else // tree - totalBlocks += blocks + (blocks / 256) + 2; + // int blocks = (record.getFileSize () - 1) / 512 + 1; + // if (blocks == 1) // seedling + // totalBlocks += blocks; + // else if (blocks <= 256) // sapling + // totalBlocks += blocks + 1; + // else // tree + // totalBlocks += blocks + (blocks / 256) + 2; volumeName.storePath (record.getFileName ()); } @@ -84,6 +87,53 @@ public class NuFX if (record.hasDisk ()) ++totalDisks; } + printSummary (); + } + + // ---------------------------------------------------------------------------------// + void printSummary () + // ---------------------------------------------------------------------------------// + { + System.out.printf (" %s Created:%s Mod:%s Recs:%5d%n%n", + volumeName.getFileName (), masterHeader.getCreated2 (), + masterHeader.getModified2 (), masterHeader.getTotalRecords ()); + System.out.println (" Name Type Auxtyp Archived" + + " Fmat Size Un-Length"); + System.out.println (UNDERLINE); + + int totalUncompressedSize = 0; + int totalCompressedSize = 0; + + for (Record record : records) + { + System.out.printf (" %s%n", record.getLine ()); + totalUncompressedSize += record.getUncompressedSize (); + totalCompressedSize += record.getCompressedSize (); + } + System.out.println (UNDERLINE); + System.out.printf (" Uncomp:%7d Comp:%7d %%of orig:%3.0f%%%n", + totalUncompressedSize, totalCompressedSize, + (float) (totalCompressedSize * 100 / totalUncompressedSize)); + } + + // ---------------------------------------------------------------------------------// + private void calculateTotalBlocks () + // ---------------------------------------------------------------------------------// + { + totalBlocks = 0; + + for (Record record : records) + if (record.hasFile ()) + { + // note: total blocks does not include subdirectory blocks + int blocks = (record.getFileSize () - 1) / 512 + 1; + if (blocks == 1) // seedling + totalBlocks += blocks; + else if (blocks <= 256) // sapling + totalBlocks += blocks + 1; + else // tree + totalBlocks += blocks + (blocks / 256) + 2; + } } // ---------------------------------------------------------------------------------// @@ -102,6 +152,7 @@ public class NuFX { // should check that files are all in prodos format + calculateTotalBlocks (); int[] diskSizes = { 280, 800, 1600, 3200, 6400, 65536 }; for (int diskSize : diskSizes) // in case we choose a size that is too small { @@ -199,8 +250,10 @@ public class NuFX for (Record record : records) { if (record.hasFile ()) + { System.out.printf ("%3d %-35s %,7d %d %,7d%n", count, record.getFileName (), record.getFileSize (), record.getFileType (), record.getUncompressedSize ()); + } count++; } } @@ -227,12 +280,14 @@ public class NuFX private String volumeName = "DiskBrowser"; private int nameOffset = 0; + private Path path; // -------------------------------------------------------------------------------// VolumeName (Path path) // -------------------------------------------------------------------------------// { - volumeName = path.getFileName ().toString (); + this.path = path; + volumeName = getFileName (); int pos = volumeName.lastIndexOf ('.'); if (pos > 0) volumeName = volumeName.substring (0, pos); @@ -241,6 +296,13 @@ public class NuFX volumeName = volumeName.replace (' ', '.'); } + // -------------------------------------------------------------------------------// + String getFileName () + // -------------------------------------------------------------------------------// + { + return path.getFileName ().toString (); + } + // -------------------------------------------------------------------------------// private void storePath (String fileName) // -------------------------------------------------------------------------------// diff --git a/src/com/bytezone/diskbrowser/utilities/Record.java b/src/com/bytezone/diskbrowser/utilities/Record.java index f762d57..6b81985 100644 --- a/src/com/bytezone/diskbrowser/utilities/Record.java +++ b/src/com/bytezone/diskbrowser/utilities/Record.java @@ -1,11 +1,11 @@ package com.bytezone.diskbrowser.utilities; +import static com.bytezone.diskbrowser.prodos.ProdosConstants.fileTypes; + import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; -import com.bytezone.diskbrowser.prodos.ProdosConstants; - // -----------------------------------------------------------------------------------// class Record // -----------------------------------------------------------------------------------// @@ -20,6 +20,7 @@ class Record "", "", "", "", "", "", "", "Subdirectory" }; private static String[] accessChars = { "D", "R", "B", "", "", "I", "W", "R" }; + private static String threadFormats[] = { "unc", "sq ", "lz1", "lz2", "", "" }; private final int totThreads; private final int crc; @@ -223,6 +224,17 @@ class Record return 0; } + // ---------------------------------------------------------------------------------// + int getThreadFormat () + // ---------------------------------------------------------------------------------// + { + for (Thread thread : threads) + if (thread.hasFile ()) + return thread.threadFormat; + + return 0; + } + // ---------------------------------------------------------------------------------// int getUncompressedSize () // ---------------------------------------------------------------------------------// @@ -234,6 +246,17 @@ class Record return 0; } + // ---------------------------------------------------------------------------------// + int getCompressedSize () + // ---------------------------------------------------------------------------------// + { + for (Thread thread : threads) + if (thread.hasFile ()) + return thread.getCompressedEOF (); + + return 0; + } + // ---------------------------------------------------------------------------------// byte[] getData () // ---------------------------------------------------------------------------------// @@ -244,6 +267,16 @@ class Record return null; } + // ---------------------------------------------------------------------------------// + String getLine () + // ---------------------------------------------------------------------------------// + { + float pct = getCompressedSize () * 100 / getUncompressedSize (); + return String.format ("%-27.27s %s $%04X %-15s %s %3.0f%% %7d", getFileName (), + fileTypes[fileType], auxType, created.format2 (), + threadFormats[getThreadFormat ()], pct, getUncompressedSize ()); + } + // ---------------------------------------------------------------------------------// @Override public String toString () @@ -267,7 +300,7 @@ class Record if (storType < 16) { text.append (String.format ("File type ...... %02X %s%n", fileType, - ProdosConstants.fileTypes[fileType])); + fileTypes[fileType])); text.append (String.format ("Aux type ....... %,d $%<04X%n", auxType)); text.append ( String.format ("Stor type ...... %,d %s%n", storType, storage[storType]));