mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2024-06-07 12:29:30 +00:00
debug output for prodos catalogs
This commit is contained in:
parent
0032b0c2bb
commit
bb1a7af6c8
|
@ -106,7 +106,6 @@ public abstract class AbstractFile implements DataSource
|
||||||
public JComponent getComponent ()
|
public JComponent getComponent ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
JPanel panel = new JPanel ();
|
return new JPanel ();
|
||||||
return panel;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,19 +1,25 @@
|
||||||
package com.bytezone.diskbrowser.prodos;
|
package com.bytezone.diskbrowser.applefile;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
|
||||||
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
||||||
|
import com.bytezone.diskbrowser.prodos.DirectoryHeader;
|
||||||
|
import com.bytezone.diskbrowser.prodos.ProdosConstants;
|
||||||
|
import com.bytezone.diskbrowser.prodos.ProdosDisk;
|
||||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
import com.bytezone.diskbrowser.utilities.Utility;
|
import com.bytezone.diskbrowser.utilities.Utility;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
class ProdosDirectory extends AbstractFile implements ProdosConstants
|
public class ProdosDirectory extends AbstractFile implements ProdosConstants
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
|
static final DateTimeFormatter df = DateTimeFormatter.ofPattern ("d-LLL-yy");
|
||||||
|
static final DateTimeFormatter tf = DateTimeFormatter.ofPattern ("H:mm");
|
||||||
|
static final String UNDERLINE = "--------------------------------------------------\n";
|
||||||
|
|
||||||
private static final String NO_DATE = "<NO DATE>";
|
private static final String NO_DATE = "<NO DATE>";
|
||||||
private static final String newLine = String.format ("%n");
|
|
||||||
private static final String newLine2 = newLine + newLine;
|
|
||||||
|
|
||||||
private final ProdosDisk parentFD;
|
private final ProdosDisk parentFD;
|
||||||
private final int totalBlocks;
|
private final int totalBlocks;
|
||||||
|
@ -21,8 +27,8 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
|
||||||
private final int usedBlocks;
|
private final int usedBlocks;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
ProdosDirectory (FormattedDisk parent, String name, byte[] buffer, int totalBlocks,
|
public ProdosDirectory (FormattedDisk parent, String name, byte[] buffer,
|
||||||
int freeBlocks, int usedBlocks)
|
int totalBlocks, int freeBlocks, int usedBlocks)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
super (name, buffer);
|
super (name, buffer);
|
||||||
|
@ -38,8 +44,38 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
|
||||||
public String getText ()
|
public String getText ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
StringBuffer text = new StringBuffer ();
|
if (showDebugText)
|
||||||
text.append ("File : " + parentFD.getDisplayPath () + newLine2);
|
return getDebugText ();
|
||||||
|
else
|
||||||
|
return getDirectoryText ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private String getDebugText ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
List<DirectoryHeader> directoryHeaders = parentFD.getDirectoryHeaders ();
|
||||||
|
StringBuilder text = new StringBuilder ();
|
||||||
|
|
||||||
|
for (DirectoryHeader directoryHeader : directoryHeaders)
|
||||||
|
{
|
||||||
|
text.append (UNDERLINE);
|
||||||
|
text.append (directoryHeader.getText ());
|
||||||
|
text.append ("\n");
|
||||||
|
text.append (UNDERLINE);
|
||||||
|
directoryHeader.listFileEntries (text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return text.toString ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private String getDirectoryText ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
StringBuilder text = new StringBuilder ();
|
||||||
|
|
||||||
|
text.append ("File : " + parentFD.getDisplayPath () + "\n\n");
|
||||||
for (int i = 0; i < buffer.length; i += ENTRY_SIZE)
|
for (int i = 0; i < buffer.length; i += ENTRY_SIZE)
|
||||||
{
|
{
|
||||||
int storageType = (buffer[i] & 0xF0) >> 4;
|
int storageType = (buffer[i] & 0xF0) >> 4;
|
||||||
|
@ -56,9 +92,9 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
|
||||||
case VOLUME_HEADER:
|
case VOLUME_HEADER:
|
||||||
case SUBDIRECTORY_HEADER:
|
case SUBDIRECTORY_HEADER:
|
||||||
String root = storageType == VOLUME_HEADER ? "/" : "";
|
String root = storageType == VOLUME_HEADER ? "/" : "";
|
||||||
text.append (root + filename + newLine2);
|
text.append (root + filename + "\n\n");
|
||||||
text.append (" NAME TYPE BLOCKS "
|
text.append (" NAME TYPE BLOCKS "
|
||||||
+ "MODIFIED CREATED ENDFILE SUBTYPE" + newLine2);
|
+ "MODIFIED CREATED ENDFILE SUBTYPE" + "\n\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FREE:
|
case FREE:
|
||||||
|
@ -74,13 +110,13 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
|
||||||
LocalDateTime createdDate = Utility.getAppleDate (buffer, i + 24);
|
LocalDateTime createdDate = Utility.getAppleDate (buffer, i + 24);
|
||||||
LocalDateTime modifiedDate = Utility.getAppleDate (buffer, i + 33);
|
LocalDateTime modifiedDate = Utility.getAppleDate (buffer, i + 33);
|
||||||
|
|
||||||
String dateC = createdDate == null ? NO_DATE
|
String dateC =
|
||||||
: createdDate.format (ProdosDisk.df).toUpperCase ();
|
createdDate == null ? NO_DATE : createdDate.format (df).toUpperCase ();
|
||||||
String dateM = modifiedDate == null ? NO_DATE
|
String dateM =
|
||||||
: modifiedDate.format (ProdosDisk.df).toUpperCase ();
|
modifiedDate == null ? NO_DATE : modifiedDate.format (df).toUpperCase ();
|
||||||
|
|
||||||
String timeC = createdDate == null ? "" : createdDate.format (ProdosDisk.tf);
|
String timeC = createdDate == null ? "" : createdDate.format (tf);
|
||||||
String timeM = modifiedDate == null ? "" : modifiedDate.format (ProdosDisk.tf);
|
String timeM = modifiedDate == null ? "" : modifiedDate.format (tf);
|
||||||
|
|
||||||
int eof = Utility.intValue (buffer[i + 21], buffer[i + 22], buffer[i + 23]);
|
int eof = Utility.intValue (buffer[i + 21], buffer[i + 22], buffer[i + 23]);
|
||||||
int fileType = buffer[i + 16] & 0xFF;
|
int fileType = buffer[i + 16] & 0xFF;
|
||||||
|
@ -102,7 +138,7 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FILE_TYPE_AWP:
|
case FILE_TYPE_AWP:
|
||||||
aux = Utility.intValue (buffer[i + 32], buffer[i + 31]); // backwards!
|
aux = Utility.intValue (buffer[i + 32], buffer[i + 31]); // backwards!
|
||||||
if (aux != 0)
|
if (aux != 0)
|
||||||
filename = convert (filename, aux);
|
filename = convert (filename, aux);
|
||||||
break;
|
break;
|
||||||
|
@ -117,12 +153,14 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
text.append (" <Unknown strage type : " + storageType + newLine);
|
text.append (" <Unknown strage type : " + storageType + "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
text.append (
|
text.append (
|
||||||
String.format ("%nBLOCKS FREE:%5d BLOCKS USED:%5d TOTAL BLOCKS:%5d%n",
|
String.format ("%nBLOCKS FREE:%5d BLOCKS USED:%5d TOTAL BLOCKS:%5d%n",
|
||||||
freeBlocks, usedBlocks, totalBlocks));
|
freeBlocks, usedBlocks, totalBlocks));
|
||||||
|
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,8 @@ public class SegmentHeader
|
||||||
String loadname;
|
String loadname;
|
||||||
String segname;
|
String segname;
|
||||||
|
|
||||||
|
boolean debug = false;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
public SegmentHeader (byte[] buffer, int offset)
|
public SegmentHeader (byte[] buffer, int offset)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -79,7 +81,8 @@ public class SegmentHeader
|
||||||
else
|
else
|
||||||
segname = "not finished";
|
segname = "not finished";
|
||||||
|
|
||||||
System.out.println (this);
|
if (debug)
|
||||||
|
System.out.println (this);
|
||||||
|
|
||||||
int ptr = offset + dispdata;
|
int ptr = offset + dispdata;
|
||||||
while (true)
|
while (true)
|
||||||
|
@ -89,25 +92,33 @@ public class SegmentHeader
|
||||||
|
|
||||||
if (recType > 0 && recType <= 0xDF)
|
if (recType > 0 && recType <= 0xDF)
|
||||||
{
|
{
|
||||||
System.out.printf ("Const: %02X%n", recType);
|
if (debug)
|
||||||
System.out.println (HexFormatter.format (buffer, ptr, recType + 1, ptr));
|
{
|
||||||
|
System.out.printf ("Const: %02X%n", recType);
|
||||||
|
System.out.println (HexFormatter.format (buffer, ptr, recType + 1, ptr));
|
||||||
|
}
|
||||||
ptr += recType + 1;
|
ptr += recType + 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.printf ("%02X ", recType);
|
if (debug)
|
||||||
|
System.out.printf ("%02X ", recType);
|
||||||
|
|
||||||
switch (recType)
|
switch (recType)
|
||||||
{
|
{
|
||||||
case 0x00: // END
|
case 0x00: // END
|
||||||
System.out.println ("END");
|
if (debug)
|
||||||
|
System.out.println ("END");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xE0: // ALIGN
|
case 0xE0: // ALIGN
|
||||||
System.out.printf ("ALIGN:%n");
|
if (debug)
|
||||||
|
System.out.printf ("ALIGN:%n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xE1: // ORG
|
case 0xE1: // ORG
|
||||||
System.out.printf ("ORG:%n");
|
if (debug)
|
||||||
|
System.out.printf ("ORG:%n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xE2: // RELOC
|
case 0xE2: // RELOC
|
||||||
|
@ -115,8 +126,9 @@ public class SegmentHeader
|
||||||
int bitShift = buffer[ptr + 2] & 0xFF;
|
int bitShift = buffer[ptr + 2] & 0xFF;
|
||||||
int segmentOffset = Utility.getLong (buffer, ptr + 3);
|
int segmentOffset = Utility.getLong (buffer, ptr + 3);
|
||||||
int value = Utility.getLong (buffer, ptr + 7);
|
int value = Utility.getLong (buffer, ptr + 7);
|
||||||
System.out.printf ("RELOC: %02X %02X %08X %08X%n", bytesRelocated, bitShift,
|
if (debug)
|
||||||
segmentOffset, value);
|
System.out.printf ("RELOC: %02X %02X %08X %08X%n", bytesRelocated, bitShift,
|
||||||
|
segmentOffset, value);
|
||||||
ptr += 11;
|
ptr += 11;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -127,72 +139,88 @@ public class SegmentHeader
|
||||||
int fileNo = Utility.getWord (buffer, ptr + 7);
|
int fileNo = Utility.getWord (buffer, ptr + 7);
|
||||||
int segNo = Utility.getWord (buffer, ptr + 9);
|
int segNo = Utility.getWord (buffer, ptr + 9);
|
||||||
int subroutineOffset = Utility.getLong (buffer, ptr + 11);
|
int subroutineOffset = Utility.getLong (buffer, ptr + 11);
|
||||||
System.out.printf ("INTERSEG: %02X %02X %08X %04X %04X %08X%n", count1, count2,
|
if (debug)
|
||||||
operandOffset, fileNo, segNo, subroutineOffset);
|
System.out.printf ("INTERSEG: %02X %02X %08X %04X %04X %08X%n", count1,
|
||||||
|
count2, operandOffset, fileNo, segNo, subroutineOffset);
|
||||||
ptr += 15;
|
ptr += 15;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xE4: // USING
|
case 0xE4: // USING
|
||||||
System.out.printf ("USING:%n");
|
if (debug)
|
||||||
|
System.out.printf ("USING:%n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xE5: // STRONG
|
case 0xE5: // STRONG
|
||||||
System.out.printf ("STRONG:%n");
|
if (debug)
|
||||||
|
System.out.printf ("STRONG:%n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xE6: // GLOBAL
|
case 0xE6: // GLOBAL
|
||||||
System.out.printf ("GLOBAL:%n");
|
if (debug)
|
||||||
|
System.out.printf ("GLOBAL:%n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xE7: // GEQU
|
case 0xE7: // GEQU
|
||||||
System.out.printf ("GEQU:%n");
|
if (debug)
|
||||||
|
System.out.printf ("GEQU:%n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xE8: // MEM
|
case 0xE8: // MEM
|
||||||
System.out.printf ("MEM:%n");
|
if (debug)
|
||||||
|
System.out.printf ("MEM:%n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xEB: // EXPR
|
case 0xEB: // EXPR
|
||||||
System.out.printf ("EXPR:%n");
|
if (debug)
|
||||||
|
System.out.printf ("EXPR:%n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xEC: // ZEXPR
|
case 0xEC: // ZEXPR
|
||||||
System.out.printf ("ZEXPR:%n");
|
if (debug)
|
||||||
|
System.out.printf ("ZEXPR:%n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xED: // BEXPR
|
case 0xED: // BEXPR
|
||||||
System.out.printf ("BEXPR:%n");
|
if (debug)
|
||||||
|
System.out.printf ("BEXPR:%n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xEE: // RELEXPR
|
case 0xEE: // RELEXPR
|
||||||
System.out.printf ("RELEXPR:%n");
|
if (debug)
|
||||||
|
System.out.printf ("RELEXPR:%n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xEF: // LOCAL
|
case 0xEF: // LOCAL
|
||||||
System.out.printf ("LOCAL:%n");
|
if (debug)
|
||||||
|
System.out.printf ("LOCAL:%n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xF0: // EQU
|
case 0xF0: // EQU
|
||||||
String label = HexFormatter.getPascalString (buffer, ptr + 1);
|
String label = HexFormatter.getPascalString (buffer, ptr + 1);
|
||||||
System.out.printf ("EQU: %s%n", label);
|
if (debug)
|
||||||
|
System.out.printf ("EQU: %s%n", label);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xF1: // DS
|
case 0xF1: // DS
|
||||||
System.out.printf ("DS:%n");
|
if (debug)
|
||||||
|
System.out.printf ("DS:%n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xF2: // LCONST
|
case 0xF2: // LCONST
|
||||||
int constLength = Utility.getLong (buffer, ptr + 1);
|
int constLength = Utility.getLong (buffer, ptr + 1);
|
||||||
System.out.printf ("Const: %04X%n", constLength);
|
if (debug)
|
||||||
|
System.out.printf ("Const: %04X%n", constLength);
|
||||||
ptr += constLength + 5;
|
ptr += constLength + 5;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 0xF3: // LEXPR
|
case 0xF3: // LEXPR
|
||||||
System.out.printf ("LEXPR:%n");
|
if (debug)
|
||||||
|
System.out.printf ("LEXPR:%n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xF4: // ENTRY
|
case 0xF4: // ENTRY
|
||||||
System.out.printf ("ENTRY:%n");
|
if (debug)
|
||||||
|
System.out.printf ("ENTRY:%n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xF5: // cRELOC
|
case 0xF5: // cRELOC
|
||||||
|
@ -200,8 +228,9 @@ public class SegmentHeader
|
||||||
int cBitShift = buffer[ptr + 2] & 0xFF;
|
int cBitShift = buffer[ptr + 2] & 0xFF;
|
||||||
int cSegmentOffset = Utility.getWord (buffer, ptr + 3);
|
int cSegmentOffset = Utility.getWord (buffer, ptr + 3);
|
||||||
int cValue = Utility.getWord (buffer, ptr + 5);
|
int cValue = Utility.getWord (buffer, ptr + 5);
|
||||||
System.out.printf ("cRELOC: %02X %02X %08X %08X%n", cBytesRelocated, cBitShift,
|
if (debug)
|
||||||
cSegmentOffset, cValue);
|
System.out.printf ("cRELOC: %02X %02X %08X %08X%n", cBytesRelocated,
|
||||||
|
cBitShift, cSegmentOffset, cValue);
|
||||||
ptr += 7;
|
ptr += 7;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -211,15 +240,17 @@ public class SegmentHeader
|
||||||
int cOperandOffset = Utility.getWord (buffer, ptr + 3);
|
int cOperandOffset = Utility.getWord (buffer, ptr + 3);
|
||||||
int cSegNo = buffer[ptr + 5] & 0xFF;
|
int cSegNo = buffer[ptr + 5] & 0xFF;
|
||||||
int cSubroutineOffset = Utility.getWord (buffer, ptr + 6);
|
int cSubroutineOffset = Utility.getWord (buffer, ptr + 6);
|
||||||
System.out.printf ("cINTERSEG: %02X %02X %04X %02X %04X%n", cCount1, cCount2,
|
if (debug)
|
||||||
cOperandOffset, cSegNo, cSubroutineOffset);
|
System.out.printf ("cINTERSEG: %02X %02X %04X %02X %04X%n", cCount1, cCount2,
|
||||||
|
cOperandOffset, cSegNo, cSubroutineOffset);
|
||||||
ptr += 8;
|
ptr += 8;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 0xF7: // SUPER
|
case 0xF7: // SUPER
|
||||||
int superLength = Utility.getLong (buffer, ptr + 1);
|
int superLength = Utility.getLong (buffer, ptr + 1);
|
||||||
int recordType = buffer[ptr + 5] & 0xFF;
|
int recordType = buffer[ptr + 5] & 0xFF;
|
||||||
System.out.printf ("Super type %02X%n", recordType);
|
if (debug)
|
||||||
|
System.out.printf ("Super type %02X%n", recordType);
|
||||||
ptr += superLength + 5;
|
ptr += superLength + 5;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -228,7 +259,8 @@ public class SegmentHeader
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println ();
|
if (debug)
|
||||||
|
System.out.println ();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,33 +290,18 @@ public class SegmentHeader
|
||||||
kindPrivate = (segAttr & 0x40) != 0;
|
kindPrivate = (segAttr & 0x40) != 0;
|
||||||
kindStatic = (segAttr & 0x80) == 0;
|
kindStatic = (segAttr & 0x80) == 0;
|
||||||
|
|
||||||
switch (segType)
|
kindWhereText = switch (segType)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0x00 -> "Code Segment";
|
||||||
kindWhereText = "Code Segment";
|
case 0x01 -> "Data Segment";
|
||||||
break;
|
case 0x02 -> "Jump Table Segment";
|
||||||
case 1:
|
case 0x04 -> "Pathname Segment";
|
||||||
kindWhereText = "Data Segment";
|
case 0x08 -> "Library Dictionary Segment";
|
||||||
break;
|
case 0x10 -> "Initialization Segment";
|
||||||
case 2:
|
case 0x11 -> "Absolute Bank Segment";
|
||||||
kindWhereText = "Jump Table Segment";
|
case 0x12 -> "Direct Page / Stack Segment";
|
||||||
break;
|
default -> "Unknown";
|
||||||
case 4:
|
};
|
||||||
kindWhereText = "Pathname Segment";
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
kindWhereText = "Library Dictionary Segment";
|
|
||||||
break;
|
|
||||||
case 0x10:
|
|
||||||
kindWhereText = "Initialization Segment";
|
|
||||||
break;
|
|
||||||
case 0x11:
|
|
||||||
kindWhereText = "Absolute Bank Segment";
|
|
||||||
break;
|
|
||||||
case 0x12:
|
|
||||||
kindWhereText = "Direct Page / Stack Segment";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
|
|
@ -169,15 +169,11 @@ public class DiskFactory
|
||||||
suffix = "dsk";
|
suffix = "dsk";
|
||||||
compressed = true;
|
compressed = true;
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
e.printStackTrace ();
|
e.printStackTrace ();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
catch (FileFormatException e)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FormattedDisk disk = null;
|
FormattedDisk disk = null;
|
||||||
|
|
|
@ -6,6 +6,7 @@ public class TextPreferences
|
||||||
{
|
{
|
||||||
public boolean showTextOffsets;
|
public boolean showTextOffsets;
|
||||||
public boolean showHeader = true;
|
public boolean showHeader = true;
|
||||||
|
public boolean merlinFormat = true;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
|
@ -15,7 +16,8 @@ public class TextPreferences
|
||||||
StringBuilder text = new StringBuilder ();
|
StringBuilder text = new StringBuilder ();
|
||||||
|
|
||||||
text.append (String.format ("Show offsets .......... %s%n", showTextOffsets));
|
text.append (String.format ("Show offsets .......... %s%n", showTextOffsets));
|
||||||
text.append (String.format ("Show header ........... %s", showHeader));
|
text.append (String.format ("Show header ........... %s%n", showHeader));
|
||||||
|
text.append (String.format ("Show .S as Merlin ..... %s", merlinFormat));
|
||||||
|
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,9 @@ abstract class CatalogEntry implements AppleFileSource
|
||||||
Disk disk;
|
Disk disk;
|
||||||
ProdosDisk parentDisk;
|
ProdosDisk parentDisk;
|
||||||
|
|
||||||
|
int blockNo;
|
||||||
|
int entryNo;
|
||||||
|
|
||||||
String name;
|
String name;
|
||||||
int storageType;
|
int storageType;
|
||||||
|
|
||||||
|
@ -30,11 +33,13 @@ abstract class CatalogEntry implements AppleFileSource
|
||||||
DirectoryHeader parentDirectory;
|
DirectoryHeader parentDirectory;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
CatalogEntry (ProdosDisk parentDisk, byte[] entryBuffer)
|
CatalogEntry (ProdosDisk parentDisk, byte[] entryBuffer, int blockNo, int entryNo)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
this.parentDisk = parentDisk;
|
this.parentDisk = parentDisk;
|
||||||
this.disk = parentDisk.getDisk ();
|
this.disk = parentDisk.getDisk ();
|
||||||
|
this.blockNo = blockNo;
|
||||||
|
this.entryNo = entryNo;
|
||||||
|
|
||||||
name = HexFormatter.getString (entryBuffer, 1, entryBuffer[0] & 0x0F);
|
name = HexFormatter.getString (entryBuffer, 1, entryBuffer[0] & 0x0F);
|
||||||
storageType = (entryBuffer[0] & 0xF0) >> 4;
|
storageType = (entryBuffer[0] & 0xF0) >> 4;
|
||||||
|
@ -45,6 +50,20 @@ abstract class CatalogEntry implements AppleFileSource
|
||||||
access = entryBuffer[30] & 0xFF;
|
access = entryBuffer[30] & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
public String getName ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
public String getText ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
return String.format ("%04X:%02X %-15s %02X", blockNo, entryNo, name, storageType);
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public String getUniqueName ()
|
public String getUniqueName ()
|
||||||
|
|
|
@ -3,7 +3,7 @@ package com.bytezone.diskbrowser.prodos;
|
||||||
import com.bytezone.diskbrowser.utilities.Utility;
|
import com.bytezone.diskbrowser.utilities.Utility;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
abstract class DirectoryHeader extends CatalogEntry
|
public abstract class DirectoryHeader extends CatalogEntry
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
final int entryLength;
|
final int entryLength;
|
||||||
|
@ -11,13 +11,55 @@ abstract class DirectoryHeader extends CatalogEntry
|
||||||
final int fileCount;
|
final int fileCount;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
DirectoryHeader (ProdosDisk parentDisk, byte[] entryBuffer)
|
DirectoryHeader (ProdosDisk parentDisk, byte[] entryBuffer, int blockNo, int entryNo)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
super (parentDisk, entryBuffer);
|
super (parentDisk, entryBuffer, blockNo, entryNo);
|
||||||
|
|
||||||
entryLength = entryBuffer[31] & 0xFF;
|
entryLength = entryBuffer[31] & 0xFF;
|
||||||
entriesPerBlock = entryBuffer[32] & 0xFF;
|
entriesPerBlock = entryBuffer[32] & 0xFF;
|
||||||
fileCount = Utility.intValue (entryBuffer[33], entryBuffer[34]);
|
fileCount = Utility.intValue (entryBuffer[33], entryBuffer[34]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@Override
|
||||||
|
public String getText ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
return String.format ("%s %04X", super.getText (), fileCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
public void listFileEntries (StringBuilder text)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
int blockNo = this.blockNo;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
byte[] buffer = disk.readBlock (blockNo);
|
||||||
|
int ptr = 4;
|
||||||
|
int entryNo = 1;
|
||||||
|
for (int i = 0; i < 13; i++)
|
||||||
|
{
|
||||||
|
int nameLength = buffer[ptr] & 0x0F;
|
||||||
|
int storageType = (buffer[ptr] & 0xF0) >>> 4;
|
||||||
|
if (nameLength > 0 && storageType < 0x0E)
|
||||||
|
{
|
||||||
|
String name = new String (buffer, ptr + 1, nameLength);
|
||||||
|
int blocksUsed = Utility.intValue (buffer[ptr + 0x13], buffer[ptr + 0x14]);
|
||||||
|
int fileType = buffer[ptr + 0x10] & 0xFF;
|
||||||
|
int keyPointer = Utility.intValue (buffer[ptr + 0x11], buffer[ptr + 0x12]);
|
||||||
|
int headerPointer = Utility.intValue (buffer[ptr + 0x25], buffer[ptr + 0x26]);
|
||||||
|
text.append (String.format ("%04X:%02X %-15s %02X %04X %02X %04X %04X%n",
|
||||||
|
blockNo, entryNo, name, storageType, blocksUsed, fileType, keyPointer,
|
||||||
|
headerPointer));
|
||||||
|
}
|
||||||
|
ptr += 0x27;
|
||||||
|
++entryNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockNo = Utility.intValue (buffer[2], buffer[3]);
|
||||||
|
} while (blockNo != 0);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -28,6 +28,7 @@ import com.bytezone.diskbrowser.applefile.MerlinSource;
|
||||||
import com.bytezone.diskbrowser.applefile.ObjectModule;
|
import com.bytezone.diskbrowser.applefile.ObjectModule;
|
||||||
import com.bytezone.diskbrowser.applefile.OriginalHiResImage;
|
import com.bytezone.diskbrowser.applefile.OriginalHiResImage;
|
||||||
import com.bytezone.diskbrowser.applefile.PascalArea;
|
import com.bytezone.diskbrowser.applefile.PascalArea;
|
||||||
|
import com.bytezone.diskbrowser.applefile.ProdosDirectory;
|
||||||
import com.bytezone.diskbrowser.applefile.QuickDrawFont;
|
import com.bytezone.diskbrowser.applefile.QuickDrawFont;
|
||||||
import com.bytezone.diskbrowser.applefile.SHRPictureFile1;
|
import com.bytezone.diskbrowser.applefile.SHRPictureFile1;
|
||||||
import com.bytezone.diskbrowser.applefile.SHRPictureFile2;
|
import com.bytezone.diskbrowser.applefile.SHRPictureFile2;
|
||||||
|
@ -69,10 +70,10 @@ class FileEntry extends CatalogEntry implements ProdosConstants
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
FileEntry (ProdosDisk fDisk, byte[] entryBuffer, DirectoryHeader parent,
|
FileEntry (ProdosDisk fDisk, byte[] entryBuffer, DirectoryHeader parent,
|
||||||
int parentBlock)
|
int parentBlock, int entryNo)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
super (fDisk, entryBuffer);
|
super (fDisk, entryBuffer, parentBlock, entryNo);
|
||||||
|
|
||||||
assert parent != null;
|
assert parent != null;
|
||||||
this.parentDirectory = parent;
|
this.parentDirectory = parent;
|
||||||
|
@ -547,6 +548,7 @@ class FileEntry extends CatalogEntry implements ProdosConstants
|
||||||
file = new ErrorMessageFile (name, buffer, e);
|
file = new ErrorMessageFile (name, buffer, e);
|
||||||
e.printStackTrace ();
|
e.printStackTrace ();
|
||||||
}
|
}
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.bytezone.diskbrowser.prodos;
|
package com.bytezone.diskbrowser.prodos;
|
||||||
|
|
||||||
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.ENTRY_SIZE;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -29,7 +31,6 @@ public class ProdosDisk extends AbstractFormattedDisk
|
||||||
{
|
{
|
||||||
static ProdosPreferences prodosPreferences; // set by MenuHandler
|
static ProdosPreferences prodosPreferences; // set by MenuHandler
|
||||||
|
|
||||||
// final DateFormat df = DateFormat.getInstance ();
|
|
||||||
static final DateTimeFormatter df = DateTimeFormatter.ofPattern ("d-LLL-yy");
|
static final DateTimeFormatter df = DateTimeFormatter.ofPattern ("d-LLL-yy");
|
||||||
static final DateTimeFormatter tf = DateTimeFormatter.ofPattern ("H:mm");
|
static final DateTimeFormatter tf = DateTimeFormatter.ofPattern ("H:mm");
|
||||||
|
|
||||||
|
@ -119,7 +120,7 @@ public class ProdosDisk extends AbstractFormattedDisk
|
||||||
sectorTypes[block] = currentSectorType;
|
sectorTypes[block] = currentSectorType;
|
||||||
|
|
||||||
int max = disk.getBlockSize () - ProdosConstants.ENTRY_SIZE;
|
int max = disk.getBlockSize () - ProdosConstants.ENTRY_SIZE;
|
||||||
for (int ptr = 4; ptr < max; ptr += ProdosConstants.ENTRY_SIZE)
|
for (int ptr = 4, entryNo = 0; ptr < max; ptr += ENTRY_SIZE, entryNo++)
|
||||||
{
|
{
|
||||||
int storageType = (sectorBuffer[ptr] & 0xF0) >> 4;
|
int storageType = (sectorBuffer[ptr] & 0xF0) >> 4;
|
||||||
if (storageType == 0) // deleted or unused
|
if (storageType == 0) // deleted or unused
|
||||||
|
@ -145,7 +146,7 @@ public class ProdosDisk extends AbstractFormattedDisk
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ProdosConstants.SUBDIRECTORY_HEADER:
|
case ProdosConstants.SUBDIRECTORY_HEADER:
|
||||||
localHeader = new SubDirectoryHeader (this, entry, parent);
|
localHeader = new SubDirectoryHeader (this, entry, parent, block);
|
||||||
headerEntries.add (localHeader);
|
headerEntries.add (localHeader);
|
||||||
currentSectorType = subcatalogSector;
|
currentSectorType = subcatalogSector;
|
||||||
if (!disk.isBlockEmpty (block))
|
if (!disk.isBlockEmpty (block))
|
||||||
|
@ -153,7 +154,8 @@ public class ProdosDisk extends AbstractFormattedDisk
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ProdosConstants.SUBDIRECTORY:
|
case ProdosConstants.SUBDIRECTORY:
|
||||||
FileEntry fileEntry = new FileEntry (this, entry, localHeader, block);
|
FileEntry fileEntry =
|
||||||
|
new FileEntry (this, entry, localHeader, block, entryNo);
|
||||||
fileEntries.add (fileEntry);
|
fileEntries.add (fileEntry);
|
||||||
DefaultMutableTreeNode directoryNode = new DefaultMutableTreeNode (fileEntry);
|
DefaultMutableTreeNode directoryNode = new DefaultMutableTreeNode (fileEntry);
|
||||||
directoryNode.setAllowsChildren (true);
|
directoryNode.setAllowsChildren (true);
|
||||||
|
@ -166,7 +168,7 @@ public class ProdosDisk extends AbstractFormattedDisk
|
||||||
case ProdosConstants.TREE:
|
case ProdosConstants.TREE:
|
||||||
case ProdosConstants.PASCAL_ON_PROFILE:
|
case ProdosConstants.PASCAL_ON_PROFILE:
|
||||||
case ProdosConstants.GSOS_EXTENDED_FILE:
|
case ProdosConstants.GSOS_EXTENDED_FILE:
|
||||||
fileEntry = new FileEntry (this, entry, localHeader, block);
|
fileEntry = new FileEntry (this, entry, localHeader, block, entryNo);
|
||||||
fileEntries.add (fileEntry);
|
fileEntries.add (fileEntry);
|
||||||
DefaultMutableTreeNode node = new DefaultMutableTreeNode (fileEntry);
|
DefaultMutableTreeNode node = new DefaultMutableTreeNode (fileEntry);
|
||||||
node.setAllowsChildren (false);
|
node.setAllowsChildren (false);
|
||||||
|
@ -200,13 +202,6 @@ public class ProdosDisk extends AbstractFormattedDisk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
// public boolean isReservedAddress (int blockNo)
|
|
||||||
// // ---------------------------------------------------------------------------------//
|
|
||||||
// {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
public static boolean isCorrectFormat (AppleDisk disk)
|
public static boolean isCorrectFormat (AppleDisk disk)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -242,6 +237,13 @@ public class ProdosDisk extends AbstractFormattedDisk
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
public List<DirectoryHeader> getDirectoryHeaders ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
return headerEntries;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
VolumeDirectoryHeader getVolumeDirectoryHeader ()
|
VolumeDirectoryHeader getVolumeDirectoryHeader ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -255,6 +257,7 @@ public class ProdosDisk extends AbstractFormattedDisk
|
||||||
{
|
{
|
||||||
if (fileNo == 0)
|
if (fileNo == 0)
|
||||||
return volumeDirectoryHeader.getDataSource ();
|
return volumeDirectoryHeader.getDataSource ();
|
||||||
|
|
||||||
return fileEntries.get (fileNo - 1).getDataSource ();
|
return fileEntries.get (fileNo - 1).getDataSource ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,22 +4,27 @@ import java.util.List;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||||
import com.bytezone.diskbrowser.gui.DataSource;
|
import com.bytezone.diskbrowser.gui.DataSource;
|
||||||
import com.bytezone.diskbrowser.utilities.Utility;
|
import com.bytezone.diskbrowser.utilities.Utility;;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
class SubDirectoryHeader extends DirectoryHeader
|
public class SubDirectoryHeader extends DirectoryHeader
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
private final int parentPointer;
|
private final int parentPointer;
|
||||||
private final int parentSequence;
|
private final int parentSequence;
|
||||||
private final int parentSize;
|
private final int parentSize;
|
||||||
|
|
||||||
|
private final int blockNo;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
SubDirectoryHeader (ProdosDisk parentDisk, byte[] entryBuffer, FileEntry parent)
|
SubDirectoryHeader (ProdosDisk parentDisk, byte[] entryBuffer, FileEntry parent,
|
||||||
|
int blockNo)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
super (parentDisk, entryBuffer);
|
super (parentDisk, entryBuffer, blockNo, 1);
|
||||||
|
|
||||||
this.parentDirectory = parent.parentDirectory;
|
this.parentDirectory = parent.parentDirectory;
|
||||||
|
this.blockNo = blockNo;
|
||||||
|
|
||||||
parentPointer = Utility.intValue (entryBuffer[35], entryBuffer[36]);
|
parentPointer = Utility.intValue (entryBuffer[35], entryBuffer[36]);
|
||||||
parentSequence = entryBuffer[37] & 0xFF;
|
parentSequence = entryBuffer[37] & 0xFF;
|
||||||
|
@ -46,6 +51,22 @@ class SubDirectoryHeader extends DirectoryHeader
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
public int getBlockNo ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
return blockNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@Override
|
||||||
|
public String getText ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
return String.format ("%s %04X:%02X", super.getText (), parentPointer,
|
||||||
|
parentSequence);
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public String toString ()
|
public String toString ()
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
package com.bytezone.diskbrowser.prodos;
|
package com.bytezone.diskbrowser.prodos;
|
||||||
|
|
||||||
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.BLOCK_SIZE;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.bytezone.diskbrowser.applefile.ProdosDirectory;
|
||||||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||||
import com.bytezone.diskbrowser.gui.DataSource;
|
import com.bytezone.diskbrowser.gui.DataSource;
|
||||||
import com.bytezone.diskbrowser.utilities.Utility;
|
import com.bytezone.diskbrowser.utilities.Utility;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
class VolumeDirectoryHeader extends DirectoryHeader
|
public class VolumeDirectoryHeader extends DirectoryHeader
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
protected final int bitMapBlock;
|
protected final int bitMapBlock;
|
||||||
|
@ -21,15 +24,12 @@ class VolumeDirectoryHeader extends DirectoryHeader
|
||||||
VolumeDirectoryHeader (ProdosDisk parentDisk, byte[] entryBuffer)
|
VolumeDirectoryHeader (ProdosDisk parentDisk, byte[] entryBuffer)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
super (parentDisk, entryBuffer);
|
super (parentDisk, entryBuffer, 2, 1);
|
||||||
|
|
||||||
bitMapBlock = Utility.unsignedShort (entryBuffer, 35);
|
bitMapBlock = Utility.unsignedShort (entryBuffer, 35);
|
||||||
totalBlocks = Utility.unsignedShort (entryBuffer, 37);
|
totalBlocks = Utility.unsignedShort (entryBuffer, 37);
|
||||||
|
|
||||||
// if (totalBlocks == 0xFFFF || totalBlocks == 0x7FFF)
|
totalBitMapBlocks = (totalBlocks - 1) / BLOCK_SIZE + 1;
|
||||||
// totalBlocks = (int) disk.getFile ().length () / 4096 * 8;// ignore extra bytes
|
|
||||||
|
|
||||||
totalBitMapBlocks = (totalBlocks - 1) / 512 + 1;
|
|
||||||
|
|
||||||
int block = 2;
|
int block = 2;
|
||||||
do
|
do
|
||||||
|
@ -90,7 +90,7 @@ class VolumeDirectoryHeader extends DirectoryHeader
|
||||||
{
|
{
|
||||||
byte[] buf = disk.readBlock (block);
|
byte[] buf = disk.readBlock (block);
|
||||||
blockList.add (buf);
|
blockList.add (buf);
|
||||||
block = Utility.intValue (buf[2], buf[3]); // next block
|
block = Utility.intValue (buf[2], buf[3]); // next block
|
||||||
} while (block > 0);
|
} while (block > 0);
|
||||||
|
|
||||||
byte[] fullBuffer = new byte[blockList.size () * 507];
|
byte[] fullBuffer = new byte[blockList.size () * 507];
|
||||||
|
@ -100,6 +100,7 @@ class VolumeDirectoryHeader extends DirectoryHeader
|
||||||
System.arraycopy (bfr, 4, fullBuffer, offset, 507);
|
System.arraycopy (bfr, 4, fullBuffer, offset, 507);
|
||||||
offset += 507;
|
offset += 507;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ProdosDirectory (parentDisk, name, fullBuffer, totalBlocks, freeBlocks,
|
return new ProdosDirectory (parentDisk, name, fullBuffer, totalBlocks, freeBlocks,
|
||||||
usedBlocks);
|
usedBlocks);
|
||||||
}
|
}
|
||||||
|
@ -114,6 +115,14 @@ class VolumeDirectoryHeader extends DirectoryHeader
|
||||||
return sectors;
|
return sectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@Override
|
||||||
|
public String getText ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
return String.format ("%s %04X %02X", super.getText (), totalBlocks, bitMapBlock);
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public String toString ()
|
public String toString ()
|
||||||
|
|
|
@ -14,6 +14,7 @@ import java.time.LocalDateTime;
|
||||||
public class DirectoryHeader
|
public class DirectoryHeader
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
|
static final String UNDERLINE = "--------------------------------------------";
|
||||||
ProdosDisk disk;
|
ProdosDisk disk;
|
||||||
byte[] buffer;
|
byte[] buffer;
|
||||||
int ptr;
|
int ptr;
|
||||||
|
@ -70,6 +71,49 @@ public class DirectoryHeader
|
||||||
writeShort (buffer, ptr + 0x21, fileCount);
|
writeShort (buffer, ptr + 0x21, fileCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
void list ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
System.out.println (UNDERLINE);
|
||||||
|
System.out.println (toText ());
|
||||||
|
System.out.println (UNDERLINE);
|
||||||
|
|
||||||
|
int blockNo = ptr / BLOCK_SIZE;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int offset = blockNo * BLOCK_SIZE;
|
||||||
|
int ptr = offset + 4;
|
||||||
|
for (int i = 0; i < ENTRIES_PER_BLOCK; i++)
|
||||||
|
{
|
||||||
|
int storageType = (buffer[ptr] & 0xF0) >>> 4;
|
||||||
|
int nameLength = buffer[ptr] & 0x0F;
|
||||||
|
if (nameLength != 0 && storageType < 0x0E)
|
||||||
|
{
|
||||||
|
FileEntry fileEntry = new FileEntry (disk, buffer, ptr);
|
||||||
|
fileEntry.read ();
|
||||||
|
System.out.println (fileEntry.toText ());
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr += ENTRY_SIZE;
|
||||||
|
}
|
||||||
|
blockNo = readShort (buffer, offset + 2);
|
||||||
|
} while (blockNo > 0);
|
||||||
|
System.out.println ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
String toText ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
int block = ptr / BLOCK_SIZE;
|
||||||
|
int entry = ((ptr % BLOCK_SIZE) - 4) / 39 + 1;
|
||||||
|
|
||||||
|
return String.format ("%04X:%02X %-15s %02X %04X", block, entry, fileName,
|
||||||
|
storageType, fileCount);
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public String toString ()
|
public String toString ()
|
||||||
|
|
|
@ -309,6 +309,17 @@ public class FileEntry
|
||||||
return indexBlock;
|
return indexBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
String toText ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
int block = ptr / BLOCK_SIZE;
|
||||||
|
int entry = ((ptr % BLOCK_SIZE) - 4) / 39 + 1;
|
||||||
|
|
||||||
|
return String.format ("%04X:%02X %-15s %02X %04X %02X %04X %04X", block, entry,
|
||||||
|
fileName, storageType, blocksUsed, fileType, keyPointer, headerPointer);
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public String toString ()
|
public String toString ()
|
||||||
|
|
|
@ -14,10 +14,10 @@ import java.io.IOException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
public class ProdosDisk
|
public class ProdosDisk
|
||||||
|
@ -38,7 +38,7 @@ public class ProdosDisk
|
||||||
private final byte[] bootSector = new byte[BLOCK_SIZE];
|
private final byte[] bootSector = new byte[BLOCK_SIZE];
|
||||||
|
|
||||||
private VolumeDirectoryHeader volumeDirectoryHeader;
|
private VolumeDirectoryHeader volumeDirectoryHeader;
|
||||||
private Map<Integer, SubdirectoryHeader> subdirectoryHeaders = new HashMap<> ();
|
private Map<Integer, SubdirectoryHeader> subdirectoryHeaders = new TreeMap<> ();
|
||||||
private List<String> paths = new ArrayList<> ();
|
private List<String> paths = new ArrayList<> ();
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -126,9 +126,11 @@ public class ProdosDisk
|
||||||
throws DiskFullException, VolumeCatalogFullException
|
throws DiskFullException, VolumeCatalogFullException
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
|
if (path.isBlank ())
|
||||||
|
throw new IllegalArgumentException ("Path is empty");
|
||||||
|
|
||||||
// save path for verification
|
// save path for verification
|
||||||
paths.add (path);
|
paths.add (path);
|
||||||
System.out.printf ("Path: %s%n", path);
|
|
||||||
|
|
||||||
// split the full path into an array of subdirectories and a file name
|
// split the full path into an array of subdirectories and a file name
|
||||||
String[] subdirectories;
|
String[] subdirectories;
|
||||||
|
@ -249,13 +251,23 @@ public class ProdosDisk
|
||||||
{
|
{
|
||||||
for (SubdirectoryHeader subdirectoryHeader : subdirectoryHeaders.values ())
|
for (SubdirectoryHeader subdirectoryHeader : subdirectoryHeaders.values ())
|
||||||
{
|
{
|
||||||
System.out.printf ("%-35s%n", subdirectoryHeader.fileName);
|
// System.out.printf ("%-35s%n", subdirectoryHeader.fileName);
|
||||||
FileEntry fileEntry = subdirectoryHeader.getParentFileEntry ();
|
FileEntry fileEntry = subdirectoryHeader.getParentFileEntry ();
|
||||||
if (!fileEntry.fileName.equals (subdirectoryHeader.fileName))
|
if (!fileEntry.fileName.equals (subdirectoryHeader.fileName))
|
||||||
System.out.println ("fail");
|
System.out.printf ("fail: %s%n", subdirectoryHeader.fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
void display ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
volumeDirectoryHeader.list ();
|
||||||
|
|
||||||
|
for (SubdirectoryHeader subdirectoryHeader : subdirectoryHeaders.values ())
|
||||||
|
subdirectoryHeader.list ();
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
public void close ()
|
public void close ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -278,7 +290,8 @@ public class ProdosDisk
|
||||||
}
|
}
|
||||||
System.out.println ();
|
System.out.println ();
|
||||||
}
|
}
|
||||||
verify ();
|
// verify ();
|
||||||
|
// display ();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
|
|
@ -2,7 +2,6 @@ package com.bytezone.diskbrowser.prodos.write;
|
||||||
|
|
||||||
import static com.bytezone.diskbrowser.prodos.ProdosConstants.BLOCK_SIZE;
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.BLOCK_SIZE;
|
||||||
import static com.bytezone.diskbrowser.prodos.ProdosConstants.ENTRY_SIZE;
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.ENTRY_SIZE;
|
||||||
import static com.bytezone.diskbrowser.prodos.write.ProdosDisk.UNDERLINE;
|
|
||||||
import static com.bytezone.diskbrowser.utilities.Utility.readShort;
|
import static com.bytezone.diskbrowser.utilities.Utility.readShort;
|
||||||
import static com.bytezone.diskbrowser.utilities.Utility.writeShort;
|
import static com.bytezone.diskbrowser.utilities.Utility.writeShort;
|
||||||
|
|
||||||
|
@ -92,6 +91,14 @@ public class SubdirectoryHeader extends DirectoryHeader
|
||||||
buffer[ptr + 0x26] = parentEntryLength;
|
buffer[ptr + 0x26] = parentEntryLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@Override
|
||||||
|
String toText ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
return String.format ("%s %04X:%02X", super.toText (), parentPointer, parentEntry);
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public String toString ()
|
public String toString ()
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.bytezone.diskbrowser.prodos.write;
|
package com.bytezone.diskbrowser.prodos.write;
|
||||||
|
|
||||||
import static com.bytezone.diskbrowser.prodos.write.ProdosDisk.UNDERLINE;
|
|
||||||
import static com.bytezone.diskbrowser.utilities.Utility.readShort;
|
import static com.bytezone.diskbrowser.utilities.Utility.readShort;
|
||||||
import static com.bytezone.diskbrowser.utilities.Utility.writeShort;
|
import static com.bytezone.diskbrowser.utilities.Utility.writeShort;
|
||||||
|
|
||||||
|
@ -42,6 +41,14 @@ public class VolumeDirectoryHeader extends DirectoryHeader
|
||||||
writeShort (buffer, ptr + 0x25, totalBlocks);
|
writeShort (buffer, ptr + 0x25, totalBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@Override
|
||||||
|
String toText ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
return String.format ("%-29s %04X %04X", super.toText (), totalBlocks, bitMapPointer);
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public String toString ()
|
public String toString ()
|
||||||
|
|
|
@ -44,7 +44,8 @@ class LZW2 extends LZW
|
||||||
setBuffer (buffer, ptr); // prepare to read n-bit integers
|
setBuffer (buffer, ptr); // prepare to read n-bit integers
|
||||||
byte[] lzwBuffer = undoLZW (rleLength);
|
byte[] lzwBuffer = undoLZW (rleLength);
|
||||||
|
|
||||||
assert (chunkLength - 4) == bytesRead ();
|
if ((chunkLength - 4) != bytesRead ())
|
||||||
|
System.out.printf ("Invalid chunk length%n");
|
||||||
|
|
||||||
if (rleLength == TRACK_LENGTH) // no run length encoding
|
if (rleLength == TRACK_LENGTH) // no run length encoding
|
||||||
chunks.add (lzwBuffer);
|
chunks.add (lzwBuffer);
|
||||||
|
|
|
@ -47,7 +47,9 @@ class MasterHeader
|
||||||
reserved = Utility.getWord (buffer, ptr + 30);
|
reserved = Utility.getWord (buffer, ptr + 30);
|
||||||
eof = Utility.getLong (buffer, ptr + 38);
|
eof = Utility.getLong (buffer, ptr + 38);
|
||||||
|
|
||||||
assert reserved == 0;
|
// assert reserved == 0;
|
||||||
|
// if (reserved != 0)
|
||||||
|
// System.out.printf ("Reserved for zero, actual: %02X%n", reserved);
|
||||||
|
|
||||||
byte[] crcBuffer = new byte[40];
|
byte[] crcBuffer = new byte[40];
|
||||||
System.arraycopy (buffer, ptr + 8, crcBuffer, 0, crcBuffer.length);
|
System.arraycopy (buffer, ptr + 8, crcBuffer, 0, crcBuffer.length);
|
||||||
|
@ -87,6 +89,7 @@ class MasterHeader
|
||||||
text.append (String.format ("Created ........ %s%n", created.format ()));
|
text.append (String.format ("Created ........ %s%n", created.format ()));
|
||||||
text.append (String.format ("Modified ....... %s%n", modified.format ()));
|
text.append (String.format ("Modified ....... %s%n", modified.format ()));
|
||||||
text.append (String.format ("Version ........ %,d%n", version));
|
text.append (String.format ("Version ........ %,d%n", version));
|
||||||
|
text.append (String.format ("Reserved ....... %016X%n", reserved));
|
||||||
text.append (String.format ("Master EOF ..... %,d", eof));
|
text.append (String.format ("Master EOF ..... %,d", eof));
|
||||||
|
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
|
|
|
@ -118,6 +118,12 @@ public class NuFX
|
||||||
if (record.hasFile ())
|
if (record.hasFile ())
|
||||||
{
|
{
|
||||||
String fileName = volumeName.convert (record.getFileName ());
|
String fileName = volumeName.convert (record.getFileName ());
|
||||||
|
if (!record.isValidFileSystem ())
|
||||||
|
{
|
||||||
|
System.out.printf ("File %s is file system %s%n", fileName,
|
||||||
|
record.getFileSystemName ());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// int fileSize = record.getFileSize ();
|
// int fileSize = record.getFileSize ();
|
||||||
byte fileType = (byte) record.getFileType ();
|
byte fileType = (byte) record.getFileType ();
|
||||||
int eof = record.getUncompressedSize ();
|
int eof = record.getUncompressedSize ();
|
||||||
|
|
|
@ -86,6 +86,13 @@ class Record
|
||||||
fileName = "";
|
fileName = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
boolean isValidFileSystem ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
return fileSystemID <= 4 || fileSystemID == 8;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
int getAttributes ()
|
int getAttributes ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -198,6 +205,13 @@ class Record
|
||||||
return fileSystemID;
|
return fileSystemID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
String getFileSystemName ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
return fileSystems[fileSystemID];
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
int getFileSize ()
|
int getFileSize ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
|
|
@ -52,7 +52,8 @@ class Thread
|
||||||
{
|
{
|
||||||
case 0: // uncompressed
|
case 0: // uncompressed
|
||||||
break;
|
break;
|
||||||
case 1: // Huffman Squeeze
|
case 1: // Huffman Squeeze - see archivers folder
|
||||||
|
System.out.printf ("Huffman squeeze");
|
||||||
break;
|
break;
|
||||||
case 2: // Dynamic LZW/1
|
case 2: // Dynamic LZW/1
|
||||||
lzw = new LZW1 (data);
|
lzw = new LZW1 (data);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user