This commit is contained in:
Denis Molony 2017-05-12 20:42:20 +10:00
parent c4d789c501
commit a94dab7bb7
7 changed files with 106 additions and 105 deletions

View File

@ -13,21 +13,24 @@ import com.bytezone.diskbrowser.disk.FormattedDisk;
import com.bytezone.diskbrowser.gui.DataSource;
import com.bytezone.diskbrowser.utilities.HexFormatter;
// File Control Block (FCB)
public class DirectoryEntry implements AppleFileSource
{
private final Disk disk;
private final CPMDisk parent;
private DataSource appleFile;
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];
private final int extent;
private final int s1; // reserved
private final int s2; // reserved
private final int recordsUsed; // records used in this extent
private final byte[] blockList = new byte[16]; // allocation blocks used
private final List<DirectoryEntry> entries = new ArrayList<DirectoryEntry> ();
private final List<DiskAddress> blocks = new ArrayList<DiskAddress> ();
private DataSource appleFile;
private final boolean readOnly;
private final boolean systemFile;
@ -36,26 +39,22 @@ public class DirectoryEntry implements AppleFileSource
this.parent = parent;
disk = parent.getDisk ();
// hi-bits of type are used for flags
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 ();
byte[] typeBuffer = new byte[3];
typeBuffer[0] = (byte) (buffer[offset + 9] & 0x7F);
typeBuffer[1] = (byte) (buffer[offset + 10] & 0x7F);
typeBuffer[2] = (byte) (buffer[offset + 11] & 0x7F);
type = new String (typeBuffer).trim ();
userNumber = buffer[offset] & 0xFF;
name = new String (buffer, offset + 1, 8).trim ();
ex = buffer[offset + 12] & 0xFF;
extent = buffer[offset + 12] & 0xFF;
s2 = buffer[offset + 13] & 0xFF;
s1 = buffer[offset + 14] & 0xFF;
rc = buffer[offset + 15] & 0xFF;
recordsUsed = buffer[offset + 15] & 0xFF;
System.arraycopy (buffer, offset + 16, blockList, 0, 16);
Disk disk = parent.getDisk ();
@ -123,11 +122,11 @@ public class DirectoryEntry implements AppleFileSource
String text =
String.format ("%3d %-8s %-3s %s %s %02X %02X %02X %02X %s",
userNumber, name, type, ro, sf, ex, s2, s1, rc, bytes);
userNumber, name, type, ro, sf, extent, s2, s1, recordsUsed, bytes);
for (DirectoryEntry entry : entries)
text = text + "\n" + entry.line ();
if (ex != 0)
if (extent != 0)
text = " " + text.substring (20);
return text;
@ -139,12 +138,12 @@ public class DirectoryEntry implements AppleFileSource
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 lo ..... %d%n", extent));
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));
int blocks = ((recordsUsed & 0xF0) >> 3) + (((recordsUsed & 0x0F) + 7) / 8);
text.append (String.format ("Records ........ %02X (%d)%n", recordsUsed, blocks));
String bytes = HexFormatter.getHexString (blockList, 0, 16);
text.append (String.format ("Allocation ..... %s%n", bytes));
@ -178,8 +177,8 @@ public class DirectoryEntry implements AppleFileSource
return appleFile;
}
DirectoryEntry entry = rc == 0x80 ? entries.get (entries.size () - 1) : this;
int len = (entry.ex * 128 + entry.rc) * 128;
DirectoryEntry entry = recordsUsed == 0x80 ? entries.get (entries.size () - 1) : this;
int len = (entry.extent * 128 + entry.recordsUsed) * 128;
byte[] exactBuffer = new byte[len];
System.arraycopy (buffer, 0, exactBuffer, 0, len);

View File

@ -54,18 +54,18 @@ class FileEntry extends CatalogEntry implements ProdosConstants
switch (storageType)
{
case TYPE_SEEDLING:
case SEEDLING:
addDataBlocks (storageType, keyPtr);
break;
case TYPE_SAPLING:
case SAPLING:
if (isGSOSFile ()) // not sure why this exists
traverseGEOSIndex (keyPtr);
else
addDataBlocks (storageType, keyPtr);
break;
case TYPE_TREE:
case TREE:
masterIndexBlock = disk.getDiskAddress (keyPtr);
if (isGSOSFile ()) // not sure why this exists
traverseGEOSMasterIndex (keyPtr);
@ -73,7 +73,7 @@ class FileEntry extends CatalogEntry implements ProdosConstants
addDataBlocks (storageType, keyPtr);
break;
case TYPE_GSOS_EXTENDED_FILE:
case GSOS_EXTENDED_FILE:
parentDisk.setSectorType (keyPtr, parentDisk.extendedKeySector);
indexBlocks.add (disk.getDiskAddress (keyPtr));
@ -90,17 +90,17 @@ class FileEntry extends CatalogEntry implements ProdosConstants
}
break;
case TYPE_SUBDIRECTORY:
case SUBDIRECTORY:
int block = keyPtr;
do
{
dataBlocks.add (disk.getDiskAddress (block));
byte[] buffer = disk.readSector (block);
block = HexFormatter.intValue (buffer[2], buffer[3]);
block = HexFormatter.unsignedShort (buffer, 2);
} while (block > 0);
break;
case TYPE_PASCAL_ON_PROFILE:
case PASCAL_ON_PROFILE:
indexBlocks.add (disk.getDiskAddress (keyPtr));
break;
@ -116,15 +116,15 @@ class FileEntry extends CatalogEntry implements ProdosConstants
switch (storageType)
{
case TYPE_SEEDLING:
case SEEDLING:
blocks.add (keyPtr);
break;
case TYPE_SAPLING:
case SAPLING:
blocks.addAll (readIndex (keyPtr));
break;
case TYPE_TREE:
case TREE:
for (Integer indexBlock : readMasterIndex (keyPtr))
blocks.addAll (readIndex (indexBlock));
break;
@ -140,8 +140,8 @@ class FileEntry extends CatalogEntry implements ProdosConstants
dataBlocks.add (emptyDiskAddress);
else
{
dataBlocks.add (disk.getDiskAddress (block));
parentDisk.setSectorType (block, parentDisk.dataSector);
dataBlocks.add (disk.getDiskAddress (block));
}
}
}
@ -155,11 +155,12 @@ class FileEntry extends CatalogEntry implements ProdosConstants
blocks.add (0);
else
{
byte[] buffer = disk.readSector (blockPtr);
for (int i = 0; i < 256; i++)
blocks.add ((buffer[i] & 0xFF) | ((buffer[i + 256] & 0xFF) << 8));
parentDisk.setSectorType (blockPtr, parentDisk.indexSector);
indexBlocks.add (disk.getDiskAddress (blockPtr));
byte[] buffer = disk.readSector (blockPtr);
for (int i = 0; i < 256; i++)
blocks.add ((buffer[i] & 0xFF) | ((buffer[i + 0x100] & 0xFF) << 8));
}
return blocks;
@ -167,23 +168,24 @@ class FileEntry extends CatalogEntry implements ProdosConstants
private List<Integer> readMasterIndex (int blockPtr)
{
List<Integer> blocks = new ArrayList<Integer> (128);
byte[] buffer = disk.readSector (blockPtr); // master index
parentDisk.setSectorType (blockPtr, parentDisk.masterIndexSector);
indexBlocks.add (disk.getDiskAddress (blockPtr));
int max = 128;
while (max-- > 0)
if (buffer[max] != 0 || buffer[max + 256] != 0)
byte[] buffer = disk.readSector (blockPtr); // master index
int highest = 0x80;
while (highest-- > 0) // decrement after test
if (buffer[highest] != 0 || buffer[highest + 0x100] != 0)
break;
for (int i = 0; i <= max; i++)
List<Integer> blocks = new ArrayList<Integer> (highest + 1);
for (int i = 0; i <= highest; i++)
blocks.add ((buffer[i] & 0xFF) | ((buffer[i + 256] & 0xFF) << 8));
return blocks;
}
// should be removed
private boolean isGSOSFile ()
{
return ((fileType & 0xF0) == 0x80);
@ -403,11 +405,11 @@ class FileEntry extends CatalogEntry implements ProdosConstants
switch (storageType)
{
case TYPE_TREE:
case TREE:
return getTreeTextFile ();
case TYPE_SAPLING:
case SAPLING:
return getSaplingTextFile ();
case TYPE_SEEDLING:
case SEEDLING:
return getSeedlingTextFile ();
default:
System.out.println ("Impossible: text file: " + storageType);
@ -478,12 +480,12 @@ class FileEntry extends CatalogEntry implements ProdosConstants
{
switch (storageType)
{
case TYPE_SEEDLING:
case TYPE_SAPLING:
case TYPE_TREE:
case SEEDLING:
case SAPLING:
case TREE:
return disk.readSectors (dataBlocks);
case TYPE_SUBDIRECTORY:
case SUBDIRECTORY:
byte[] fullBuffer = new byte[dataBlocks.size () * BLOCK_ENTRY_SIZE];
int offset = 0;
for (DiskAddress da : dataBlocks)
@ -494,10 +496,10 @@ class FileEntry extends CatalogEntry implements ProdosConstants
}
return fullBuffer;
case TYPE_GSOS_EXTENDED_FILE:
case GSOS_EXTENDED_FILE:
return disk.readSectors (dataBlocks); // data and resource forks concatenated
case TYPE_PASCAL_ON_PROFILE:
case PASCAL_ON_PROFILE:
return disk.readSectors (dataBlocks);
default:
@ -510,12 +512,12 @@ class FileEntry extends CatalogEntry implements ProdosConstants
{
switch (storageType)
{
case TYPE_SEEDLING:
case SEEDLING:
System.out.println ("Seedling GEOS file : " + name); // not sure if possible
return disk.readSectors (dataBlocks);
case TYPE_SAPLING:
case SAPLING:
return getIndexFile (keyPtr);
case TYPE_TREE:
case TREE:
return getMasterIndexFile (keyPtr);
default:
System.out.println ("Unknown storage type for GEOS file : " + storageType);

View File

@ -53,19 +53,19 @@ class ProdosCatalogSector extends AbstractSector
switch (fileType)
{
case TYPE_FREE:
case TYPE_SEEDLING:
case TYPE_SAPLING:
case TYPE_TREE:
case TYPE_PASCAL_ON_PROFILE:
case TYPE_GSOS_EXTENDED_FILE:
case TYPE_SUBDIRECTORY:
case FREE:
case SEEDLING:
case SAPLING:
case TREE:
case PASCAL_ON_PROFILE:
case GSOS_EXTENDED_FILE:
case SUBDIRECTORY:
text.append (doFileDescription (i));
break;
case TYPE_SUBDIRECTORY_HEADER:
case SUBDIRECTORY_HEADER:
text.append (doSubdirectoryHeader (i));
break;
case TYPE_DIRECTORY_HEADER:
case VOLUME_HEADER:
text.append (doVolumeDirectoryHeader (i));
break;
default:
@ -169,23 +169,23 @@ class ProdosCatalogSector extends AbstractSector
{
switch ((flag & 0xF0) >> 4)
{
case TYPE_FREE:
case FREE:
return "Deleted";
case TYPE_SEEDLING:
case SEEDLING:
return "Seedling";
case TYPE_SAPLING:
case SAPLING:
return "Sapling";
case TYPE_TREE:
case TREE:
return "Tree";
case TYPE_PASCAL_ON_PROFILE:
case PASCAL_ON_PROFILE:
return "Pascal area on a Profile HD";
case TYPE_GSOS_EXTENDED_FILE:
case GSOS_EXTENDED_FILE:
return "GS/OS extended file";
case TYPE_SUBDIRECTORY:
case SUBDIRECTORY:
return "Subdirectory";
case TYPE_SUBDIRECTORY_HEADER:
case SUBDIRECTORY_HEADER:
return "Subdirectory Header";
case TYPE_DIRECTORY_HEADER:
case VOLUME_HEADER:
return "Volume Directory Header";
default:
return "???";

View File

@ -32,15 +32,15 @@ public interface ProdosConstants
int FILE_TYPE_RELOCATABLE = 0xFE;
int FILE_TYPE_SYS = 0xFF;
int TYPE_DIRECTORY_HEADER = 15;
int TYPE_SUBDIRECTORY_HEADER = 14;
int TYPE_SUBDIRECTORY = 13;
int TYPE_GSOS_EXTENDED_FILE = 5; // tech note #25
int TYPE_PASCAL_ON_PROFILE = 4; // tech note #25
int TYPE_TREE = 3;
int TYPE_SAPLING = 2;
int TYPE_SEEDLING = 1;
int TYPE_FREE = 0;
int VOLUME_HEADER = 15;
int SUBDIRECTORY_HEADER = 14;
int SUBDIRECTORY = 13;
int GSOS_EXTENDED_FILE = 5; // tech note #25
int PASCAL_ON_PROFILE = 4; // tech note #25
int TREE = 3;
int SAPLING = 2;
int SEEDLING = 1;
int FREE = 0;
String[] fileTypes = { //
"NON", "BAD", "PCD", "PTX", "TXT", "PDA", "BIN", "FNT", //

View File

@ -46,20 +46,20 @@ class ProdosDirectory extends AbstractFile
switch (storageType)
{
case ProdosConstants.TYPE_DIRECTORY_HEADER:
case ProdosConstants.TYPE_SUBDIRECTORY_HEADER:
case ProdosConstants.VOLUME_HEADER:
case ProdosConstants.SUBDIRECTORY_HEADER:
text.append ("/" + filename + newLine2);
text.append (" NAME TYPE BLOCKS "
+ "MODIFIED CREATED ENDFILE SUBTYPE" + newLine2);
break;
case ProdosConstants.TYPE_FREE:
case ProdosConstants.TYPE_SEEDLING:
case ProdosConstants.TYPE_SAPLING:
case ProdosConstants.TYPE_TREE:
case ProdosConstants.TYPE_PASCAL_ON_PROFILE:
case ProdosConstants.TYPE_GSOS_EXTENDED_FILE:
case ProdosConstants.TYPE_SUBDIRECTORY:
case ProdosConstants.FREE:
case ProdosConstants.SEEDLING:
case ProdosConstants.SAPLING:
case ProdosConstants.TREE:
case ProdosConstants.PASCAL_ON_PROFILE:
case ProdosConstants.GSOS_EXTENDED_FILE:
case ProdosConstants.SUBDIRECTORY:
int type = buffer[i + 16] & 0xFF;
int blocks = HexFormatter.intValue (buffer[i + 19], buffer[i + 20]);

View File

@ -98,7 +98,7 @@ public class ProdosDisk extends AbstractFormattedDisk
switch (storageType)
{
case ProdosConstants.TYPE_DIRECTORY_HEADER:
case ProdosConstants.VOLUME_HEADER:
assert headerEntries.size () == 0;
vdh = new VolumeDirectoryHeader (this, entry);
localHeader = vdh;
@ -112,7 +112,7 @@ public class ProdosDisk extends AbstractFormattedDisk
parentNode.setUserObject (vdh); // populate the empty volume node
break;
case ProdosConstants.TYPE_SUBDIRECTORY_HEADER:
case ProdosConstants.SUBDIRECTORY_HEADER:
localHeader = new SubDirectoryHeader (this, entry, parent);
headerEntries.add (localHeader);
currentSectorType = subcatalogSector;
@ -120,7 +120,7 @@ public class ProdosDisk extends AbstractFormattedDisk
sectorTypes[block] = currentSectorType;
break;
case ProdosConstants.TYPE_SUBDIRECTORY:
case ProdosConstants.SUBDIRECTORY:
FileEntry ce = new FileEntry (this, entry, localHeader, block);
fileEntries.add (ce);
DefaultMutableTreeNode directoryNode = new DefaultMutableTreeNode (ce);
@ -129,11 +129,11 @@ public class ProdosDisk extends AbstractFormattedDisk
processDirectoryBlock (ce.keyPtr, ce, directoryNode); // Recursion !!
break;
case ProdosConstants.TYPE_SEEDLING:
case ProdosConstants.TYPE_SAPLING:
case ProdosConstants.TYPE_TREE:
case ProdosConstants.TYPE_PASCAL_ON_PROFILE:
case ProdosConstants.TYPE_GSOS_EXTENDED_FILE:
case ProdosConstants.SEEDLING:
case ProdosConstants.SAPLING:
case ProdosConstants.TREE:
case ProdosConstants.PASCAL_ON_PROFILE:
case ProdosConstants.GSOS_EXTENDED_FILE:
FileEntry fe = new FileEntry (this, entry, localHeader, block);
fileEntries.add (fe);
DefaultMutableTreeNode node = new DefaultMutableTreeNode (fe);

View File

@ -46,11 +46,11 @@ class ProdosExtendedKeySector extends AbstractSector
{
switch ((flag & 0x0F))
{
case ProdosConstants.TYPE_SEEDLING:
case ProdosConstants.SEEDLING:
return "Seedling";
case ProdosConstants.TYPE_SAPLING:
case ProdosConstants.SAPLING:
return "Sapling";
case ProdosConstants.TYPE_TREE:
case ProdosConstants.TREE:
return "Tree";
default:
return "???";