dmolony-DiskBrowser/src/com/bytezone/diskbrowser/cpm/DirectoryEntry.java

222 lines
6.1 KiB
Java
Raw Normal View History

2016-02-24 09:48:09 +00:00
package com.bytezone.diskbrowser.cpm;
2016-02-24 21:27:03 +00:00
import java.util.ArrayList;
import java.util.List;
2016-02-25 01:27:22 +00:00
import com.bytezone.diskbrowser.applefile.AppleFileSource;
2016-02-26 20:39:06 +00:00
import com.bytezone.diskbrowser.applefile.CPMTextFile;
2016-02-25 07:45:24 +00:00
import com.bytezone.diskbrowser.applefile.DefaultAppleFile;
2016-02-25 02:49:12 +00:00
import com.bytezone.diskbrowser.disk.AppleDiskAddress;
import com.bytezone.diskbrowser.disk.Disk;
2016-02-25 01:27:22 +00:00
import com.bytezone.diskbrowser.disk.DiskAddress;
import com.bytezone.diskbrowser.disk.FormattedDisk;
import com.bytezone.diskbrowser.gui.DataSource;
2016-02-24 21:11:14 +00:00
import com.bytezone.diskbrowser.utilities.HexFormatter;
2016-02-24 09:48:09 +00:00
2016-02-25 01:27:22 +00:00
public class DirectoryEntry implements AppleFileSource
2016-02-24 09:48:09 +00:00
{
2016-02-25 07:45:24 +00:00
private final Disk disk;
2016-02-25 01:55:14 +00:00
private final CPMDisk parent;
2016-02-24 09:48:09 +00:00
private final int userNumber;
private final String name;
private final String type;
private final int ex;
private final int s1;
private final int s2;
private final int rc;
private final byte[] blockList = new byte[16];
2016-02-24 21:27:03 +00:00
private final List<DirectoryEntry> entries = new ArrayList<DirectoryEntry> ();
2016-02-25 02:49:12 +00:00
private final List<DiskAddress> blocks = new ArrayList<DiskAddress> ();
2016-02-25 07:45:24 +00:00
private DataSource appleFile;
2016-02-26 23:10:00 +00:00
private final boolean readOnly;
private final boolean systemFile;
2016-02-24 09:48:09 +00:00
2016-02-25 01:55:14 +00:00
public DirectoryEntry (CPMDisk parent, byte[] buffer, int offset)
2016-02-24 09:48:09 +00:00
{
2016-02-25 01:55:14 +00:00
this.parent = parent;
2016-02-25 07:45:24 +00:00
disk = parent.getDisk ();
2016-02-26 23:10:00 +00:00
readOnly = (buffer[offset + 9] & 0x80) != 0;
systemFile = (buffer[offset + 10] & 0x80) != 0;
if (readOnly || systemFile)
{
byte[] typeBuffer = new byte[3];
typeBuffer[0] = (byte) (buffer[offset + 9] & 0x7F);
typeBuffer[1] = (byte) (buffer[offset + 10] & 0x7F);
typeBuffer[2] = buffer[offset + 11];
type = new String (typeBuffer).trim ();
}
else
type = new String (buffer, offset + 9, 3).trim ();
2016-02-24 09:48:09 +00:00
userNumber = buffer[offset] & 0xFF;
name = new String (buffer, offset + 1, 8).trim ();
ex = buffer[offset + 12] & 0xFF;
s2 = buffer[offset + 13] & 0xFF;
s1 = buffer[offset + 14] & 0xFF;
rc = buffer[offset + 15] & 0xFF;
System.arraycopy (buffer, offset + 16, blockList, 0, 16);
2016-02-25 02:49:12 +00:00
Disk disk = parent.getDisk ();
for (byte b : blockList)
{
if (b == 0)
break;
int blockNumber = b * 4 + 48;
for (int i = 0; i < 4; i++)
2016-02-25 23:43:44 +00:00
{
AppleDiskAddress da = new AppleDiskAddress (blockNumber + i, disk);
blocks.add (da);
}
2016-02-25 02:49:12 +00:00
}
}
public String getType ()
{
return type;
2016-02-24 09:48:09 +00:00
}
2016-02-24 21:11:14 +00:00
public boolean matches (DirectoryEntry directoryEntry)
{
return userNumber == directoryEntry.userNumber && name.equals (directoryEntry.name)
&& type.equals (directoryEntry.type);
}
2016-02-24 21:27:03 +00:00
public void add (DirectoryEntry entry)
{
entries.add (entry);
2016-02-25 02:49:12 +00:00
Disk disk = parent.getDisk ();
for (byte b : entry.blockList)
{
if (b == 0)
break;
int blockNumber = b * 4 + 48;
for (int i = 0; i < 4; i++)
blocks.add (new AppleDiskAddress (blockNumber + i, disk));
}
2016-02-24 21:27:03 +00:00
}
2016-02-25 21:49:22 +00:00
@Override
public boolean contains (DiskAddress da)
{
for (DiskAddress sector : blocks)
if (sector.compareTo (da) == 0)
return true;
return false;
}
2016-02-25 01:27:22 +00:00
public String line ()
{
2016-02-25 01:55:14 +00:00
int blocks = ((rc & 0xF0) >> 3) + (((rc & 0x0F) + 7) / 8);
2016-02-25 02:49:12 +00:00
String bytes = HexFormatter.getHexString (blockList, 0, 16);
bytes = bytes.replaceAll ("00", " ");
2016-02-26 03:51:15 +00:00
2016-02-26 23:10:00 +00:00
char ro = readOnly ? '*' : ' ';
char sf = systemFile ? '*' : ' ';
String text =
String.format ("%3d %-8s %-3s %s %s %02X %02X %02X %02X %s",
userNumber, name, type, ro, sf, ex, s2, s1, rc, bytes);
2016-02-25 02:49:12 +00:00
for (DirectoryEntry entry : entries)
2016-02-26 03:09:14 +00:00
text = text + "\n" + entry.line ();
2016-02-26 03:51:15 +00:00
if (ex != 0)
text = " " + text.substring (20);
2016-02-25 02:49:12 +00:00
return text;
2016-02-25 01:27:22 +00:00
}
2016-02-25 01:55:14 +00:00
public String toDetailedString ()
2016-02-24 09:48:09 +00:00
{
StringBuilder text = new StringBuilder ();
text.append (String.format ("User number .... %d%n", userNumber));
text.append (String.format ("File name ...... %s%n", name + "." + type));
text.append (String.format ("Extents lo ..... %d%n", ex));
text.append (String.format ("Extents hi ..... %d%n", s2));
text.append (String.format ("Reserved ....... %d%n", s1));
int blocks = ((rc & 0xF0) >> 3) + (((rc & 0x0F) + 7) / 8);
text.append (String.format ("Records ........ %02X (%d)%n", rc, blocks));
2016-02-24 12:32:36 +00:00
String bytes = HexFormatter.getHexString (blockList, 0, 16);
text.append (String.format ("Allocation ..... %s%n", bytes));
2016-02-24 09:48:09 +00:00
2016-02-24 21:27:03 +00:00
for (DirectoryEntry entry : entries)
{
bytes = HexFormatter.getHexString (entry.blockList, 0, 16);
text.append (String.format (" %s%n", bytes));
}
2016-02-24 09:48:09 +00:00
return text.toString ();
}
2016-02-25 01:27:22 +00:00
@Override
public String getUniqueName ()
{
return name + "." + type;
}
@Override
public DataSource getDataSource ()
{
2016-02-25 07:45:24 +00:00
if (appleFile != null)
return appleFile;
byte[] buffer = disk.readSectors (blocks);
2016-02-26 11:03:29 +00:00
2016-02-25 07:45:24 +00:00
if (buffer.length == 0)
{
appleFile = new DefaultAppleFile (name, buffer);
return appleFile;
}
2016-02-26 11:03:29 +00:00
DirectoryEntry entry = rc == 0x80 ? entries.get (entries.size () - 1) : this;
int len = (entry.ex * 128 + entry.rc) * 128;
byte[] exactBuffer = new byte[len];
System.arraycopy (buffer, 0, exactBuffer, 0, len);
2016-02-26 21:23:05 +00:00
int max = Math.min (256, exactBuffer.length);
int count = 0;
for (int i = 1; i < max; i++)
{
if (exactBuffer[i - 1] == 0x0D && exactBuffer[i] == 0x0A)
++count;
}
2016-02-26 23:10:00 +00:00
if ("COM".equals (type))
appleFile = new DefaultAppleFile (name, exactBuffer, "COM File");
else if ("DVR".equals (type))
appleFile = new DefaultAppleFile (name, exactBuffer, "DVR File");
else if ("ASM".equals (type) || "DOC".equals (type) || "TXT".equals (type)
|| count > 2)
2016-02-26 20:39:06 +00:00
appleFile = new CPMTextFile (name, exactBuffer);
2016-02-26 11:03:29 +00:00
else
appleFile = new DefaultAppleFile (name, exactBuffer, "CPM File : " + type);
2016-02-25 07:45:24 +00:00
return appleFile;
2016-02-25 01:27:22 +00:00
}
@Override
public List<DiskAddress> getSectors ()
{
2016-02-25 02:49:12 +00:00
return blocks;
2016-02-25 01:27:22 +00:00
}
@Override
public FormattedDisk getFormattedDisk ()
{
2016-02-25 01:55:14 +00:00
return parent;
}
@Override
public String toString ()
{
return name + "." + type;
2016-02-25 01:27:22 +00:00
}
2016-02-24 09:48:09 +00:00
}