2021-04-27 11:26:09 +00:00
|
|
|
package com.bytezone.diskbrowser.applefile;
|
2020-02-09 13:13:33 +00:00
|
|
|
|
2021-04-17 07:33:27 +00:00
|
|
|
import java.time.LocalDateTime;
|
2021-04-27 11:26:09 +00:00
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
import java.util.List;
|
2020-02-09 13:13:33 +00:00
|
|
|
|
|
|
|
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
2021-04-27 11:26:09 +00:00
|
|
|
import com.bytezone.diskbrowser.prodos.DirectoryHeader;
|
|
|
|
import com.bytezone.diskbrowser.prodos.ProdosConstants;
|
|
|
|
import com.bytezone.diskbrowser.prodos.ProdosDisk;
|
2020-02-09 13:13:33 +00:00
|
|
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
2020-06-26 03:29:46 +00:00
|
|
|
import com.bytezone.diskbrowser.utilities.Utility;
|
2020-02-09 13:13:33 +00:00
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------//
|
2021-04-27 11:26:09 +00:00
|
|
|
public class ProdosDirectory extends AbstractFile implements ProdosConstants
|
2020-02-09 13:13:33 +00:00
|
|
|
// -----------------------------------------------------------------------------------//
|
|
|
|
{
|
2021-04-27 11:26:09 +00:00
|
|
|
static final DateTimeFormatter df = DateTimeFormatter.ofPattern ("d-LLL-yy");
|
|
|
|
static final DateTimeFormatter tf = DateTimeFormatter.ofPattern ("H:mm");
|
2021-05-01 23:38:24 +00:00
|
|
|
static final String UNDERLINE =
|
|
|
|
"----------------------------------------------------\n";
|
2021-04-27 11:26:09 +00:00
|
|
|
|
2020-02-09 13:13:33 +00:00
|
|
|
private static final String NO_DATE = "<NO DATE>";
|
|
|
|
|
|
|
|
private final ProdosDisk parentFD;
|
|
|
|
private final int totalBlocks;
|
|
|
|
private final int freeBlocks;
|
|
|
|
private final int usedBlocks;
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
2021-04-27 11:26:09 +00:00
|
|
|
public ProdosDirectory (FormattedDisk parent, String name, byte[] buffer,
|
|
|
|
int totalBlocks, int freeBlocks, int usedBlocks)
|
2020-02-09 13:13:33 +00:00
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
super (name, buffer);
|
|
|
|
|
|
|
|
this.parentFD = (ProdosDisk) parent;
|
|
|
|
this.totalBlocks = totalBlocks;
|
|
|
|
this.freeBlocks = freeBlocks;
|
|
|
|
this.usedBlocks = usedBlocks;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
@Override
|
|
|
|
public String getText ()
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
2021-04-27 11:26:09 +00:00
|
|
|
if (showDebugText)
|
|
|
|
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");
|
2021-04-15 07:27:20 +00:00
|
|
|
for (int i = 0; i < buffer.length; i += ENTRY_SIZE)
|
2020-02-09 13:13:33 +00:00
|
|
|
{
|
|
|
|
int storageType = (buffer[i] & 0xF0) >> 4;
|
|
|
|
if (storageType == 0)
|
|
|
|
continue; // break??
|
|
|
|
|
|
|
|
int nameLength = buffer[i] & 0x0F;
|
|
|
|
String filename = HexFormatter.getString (buffer, i + 1, nameLength);
|
|
|
|
String subType = "";
|
|
|
|
String locked;
|
|
|
|
|
|
|
|
switch (storageType)
|
|
|
|
{
|
2021-04-15 07:27:20 +00:00
|
|
|
case VOLUME_HEADER:
|
|
|
|
case SUBDIRECTORY_HEADER:
|
|
|
|
String root = storageType == VOLUME_HEADER ? "/" : "";
|
2021-04-27 11:26:09 +00:00
|
|
|
text.append (root + filename + "\n\n");
|
2020-02-09 13:13:33 +00:00
|
|
|
text.append (" NAME TYPE BLOCKS "
|
2021-04-27 11:26:09 +00:00
|
|
|
+ "MODIFIED CREATED ENDFILE SUBTYPE" + "\n\n");
|
2020-02-09 13:13:33 +00:00
|
|
|
break;
|
|
|
|
|
2021-04-15 07:27:20 +00:00
|
|
|
case FREE:
|
|
|
|
case SEEDLING:
|
|
|
|
case SAPLING:
|
|
|
|
case TREE:
|
|
|
|
case PASCAL_ON_PROFILE:
|
|
|
|
case GSOS_EXTENDED_FILE:
|
|
|
|
case SUBDIRECTORY:
|
2020-02-09 13:13:33 +00:00
|
|
|
int type = buffer[i + 16] & 0xFF;
|
2021-05-19 08:13:17 +00:00
|
|
|
int blocks = Utility.getShort (buffer, i + 19);
|
2020-02-09 13:13:33 +00:00
|
|
|
|
2021-04-17 07:33:27 +00:00
|
|
|
LocalDateTime createdDate = Utility.getAppleDate (buffer, i + 24);
|
|
|
|
LocalDateTime modifiedDate = Utility.getAppleDate (buffer, i + 33);
|
|
|
|
|
2021-04-27 11:26:09 +00:00
|
|
|
String dateC =
|
|
|
|
createdDate == null ? NO_DATE : createdDate.format (df).toUpperCase ();
|
|
|
|
String dateM =
|
|
|
|
modifiedDate == null ? NO_DATE : modifiedDate.format (df).toUpperCase ();
|
2021-04-17 07:33:27 +00:00
|
|
|
|
2021-04-27 11:26:09 +00:00
|
|
|
String timeC = createdDate == null ? "" : createdDate.format (tf);
|
|
|
|
String timeM = modifiedDate == null ? "" : modifiedDate.format (tf);
|
2021-04-17 07:33:27 +00:00
|
|
|
|
2020-06-26 03:29:46 +00:00
|
|
|
int eof = Utility.intValue (buffer[i + 21], buffer[i + 22], buffer[i + 23]);
|
2020-02-09 13:13:33 +00:00
|
|
|
int fileType = buffer[i + 16] & 0xFF;
|
|
|
|
locked = (buffer[i + 30] & 0xE0) == 0xE0 ? " " : "*";
|
|
|
|
|
|
|
|
switch (fileType)
|
|
|
|
{
|
|
|
|
case FILE_TYPE_TEXT:
|
2021-05-19 08:13:17 +00:00
|
|
|
int aux = Utility.getShort (buffer, i + 31);
|
2020-02-09 13:13:33 +00:00
|
|
|
subType = String.format ("R=%5d", aux);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FILE_TYPE_BINARY:
|
|
|
|
case FILE_TYPE_PNT:
|
|
|
|
case FILE_TYPE_PIC:
|
|
|
|
case FILE_TYPE_FOT:
|
2021-05-19 08:13:17 +00:00
|
|
|
aux = Utility.getShort (buffer, i + 31);
|
2020-02-09 13:13:33 +00:00
|
|
|
subType = String.format ("A=$%4X", aux);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FILE_TYPE_AWP:
|
2021-04-27 11:26:09 +00:00
|
|
|
aux = Utility.intValue (buffer[i + 32], buffer[i + 31]); // backwards!
|
2020-02-09 13:13:33 +00:00
|
|
|
if (aux != 0)
|
|
|
|
filename = convert (filename, aux);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
subType = "";
|
|
|
|
}
|
|
|
|
|
2021-05-05 03:10:33 +00:00
|
|
|
String forkFlag = storageType == 5 ? "+" : " ";
|
|
|
|
text.append (String.format ("%s%-15s %3s%s %5d %9s %5s %9s %5s %8d %7s%n",
|
|
|
|
locked, filename, ProdosConstants.fileTypes[type], forkFlag, blocks, dateM,
|
|
|
|
timeM, dateC, timeC, eof, subType));
|
2020-02-09 13:13:33 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2021-04-27 11:26:09 +00:00
|
|
|
text.append (" <Unknown strage type : " + storageType + "\n");
|
2020-02-09 13:13:33 +00:00
|
|
|
}
|
|
|
|
}
|
2021-04-27 11:26:09 +00:00
|
|
|
|
2020-02-09 13:13:33 +00:00
|
|
|
text.append (
|
|
|
|
String.format ("%nBLOCKS FREE:%5d BLOCKS USED:%5d TOTAL BLOCKS:%5d%n",
|
|
|
|
freeBlocks, usedBlocks, totalBlocks));
|
2021-04-27 11:26:09 +00:00
|
|
|
|
2020-02-09 13:13:33 +00:00
|
|
|
return text.toString ();
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
private String convert (String name, int flags)
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
char[] newName = name.toCharArray ();
|
|
|
|
for (int i = 0, weight = 0x8000; i < newName.length; i++, weight >>>= 1)
|
|
|
|
{
|
|
|
|
if ((flags & weight) != 0)
|
|
|
|
{
|
|
|
|
if (newName[i] == '.')
|
|
|
|
newName[i] = ' ';
|
|
|
|
else if (newName[i] >= 'A' && newName[i] <= 'Z')
|
|
|
|
newName[i] += 32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return new String (newName);
|
|
|
|
}
|
2015-06-01 09:35:51 +00:00
|
|
|
}
|