mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2024-06-10 02:29:27 +00:00
method header lines
This commit is contained in:
parent
5b640cbb1c
commit
6b3c7011d3
|
@ -11,7 +11,9 @@ import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||||
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
||||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
abstract class CatalogEntry implements AppleFileSource
|
abstract class CatalogEntry implements AppleFileSource
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
protected AbstractFile file;
|
protected AbstractFile file;
|
||||||
protected final PascalDisk parent;
|
protected final PascalDisk parent;
|
||||||
|
@ -23,7 +25,9 @@ abstract class CatalogEntry implements AppleFileSource
|
||||||
protected int bytesUsedInLastBlock;
|
protected int bytesUsedInLastBlock;
|
||||||
protected final List<DiskAddress> blocks = new ArrayList<> ();
|
protected final List<DiskAddress> blocks = new ArrayList<> ();
|
||||||
|
|
||||||
public CatalogEntry (PascalDisk parent, byte[] buffer)
|
// ---------------------------------------------------------------------------------//
|
||||||
|
CatalogEntry (PascalDisk parent, byte[] buffer)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
|
||||||
|
@ -39,8 +43,10 @@ abstract class CatalogEntry implements AppleFileSource
|
||||||
blocks.add (disk.getDiskAddress (i));
|
blocks.add (disk.getDiskAddress (i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public boolean contains (DiskAddress da)
|
public boolean contains (DiskAddress da)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
for (DiskAddress sector : blocks)
|
for (DiskAddress sector : blocks)
|
||||||
if (sector.matches (da))
|
if (sector.matches (da))
|
||||||
|
@ -48,27 +54,35 @@ abstract class CatalogEntry implements AppleFileSource
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public List<DiskAddress> getSectors ()
|
public List<DiskAddress> getSectors ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
List<DiskAddress> sectors = new ArrayList<> (blocks);
|
List<DiskAddress> sectors = new ArrayList<> (blocks);
|
||||||
return sectors;
|
return sectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public FormattedDisk getFormattedDisk ()
|
public FormattedDisk getFormattedDisk ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public String getUniqueName ()
|
public String getUniqueName ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public String toString ()
|
public String toString ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
int size = lastBlock - firstBlock;
|
int size = lastBlock - firstBlock;
|
||||||
String fileTypeText = fileType < 0 || fileType >= parent.fileTypes.length ? "????"
|
String fileTypeText = fileType < 0 || fileType >= parent.fileTypes.length ? "????"
|
||||||
|
|
|
@ -2,15 +2,26 @@ package com.bytezone.diskbrowser.pascal;
|
||||||
|
|
||||||
import javax.swing.tree.DefaultMutableTreeNode;
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.applefile.*;
|
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||||
|
import com.bytezone.diskbrowser.applefile.AssemblerProgram;
|
||||||
|
import com.bytezone.diskbrowser.applefile.Charset;
|
||||||
|
import com.bytezone.diskbrowser.applefile.DefaultAppleFile;
|
||||||
|
import com.bytezone.diskbrowser.applefile.PascalCode;
|
||||||
|
import com.bytezone.diskbrowser.applefile.PascalInfo;
|
||||||
|
import com.bytezone.diskbrowser.applefile.PascalSegment;
|
||||||
|
import com.bytezone.diskbrowser.applefile.PascalText;
|
||||||
import com.bytezone.diskbrowser.utilities.FileFormatException;
|
import com.bytezone.diskbrowser.utilities.FileFormatException;
|
||||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
public class FileEntry extends CatalogEntry
|
public class FileEntry extends CatalogEntry
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
private DefaultMutableTreeNode node;
|
private DefaultMutableTreeNode node;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
public FileEntry (PascalDisk parent, byte[] buffer)
|
public FileEntry (PascalDisk parent, byte[] buffer)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
super (parent, buffer);
|
super (parent, buffer);
|
||||||
|
|
||||||
|
@ -30,18 +41,24 @@ public class FileEntry extends CatalogEntry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
void setNode (DefaultMutableTreeNode node)
|
void setNode (DefaultMutableTreeNode node)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
this.node = node;
|
this.node = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
public void setFile (AbstractFile file)
|
public void setFile (AbstractFile file)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
this.file = file;
|
this.file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public AbstractFile getDataSource ()
|
public AbstractFile getDataSource ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
if (file != null)
|
if (file != null)
|
||||||
return file;
|
return file;
|
||||||
|
@ -99,7 +116,9 @@ public class FileEntry extends CatalogEntry
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
private byte[] getExactBuffer ()
|
private byte[] getExactBuffer ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
byte[] buffer = parent.getDisk ().readSectors (blocks);
|
byte[] buffer = parent.getDisk ().readSectors (blocks);
|
||||||
byte[] exactBuffer;
|
byte[] exactBuffer;
|
||||||
|
|
|
@ -9,19 +9,25 @@ import com.bytezone.diskbrowser.disk.Disk;
|
||||||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
class PascalCatalogSector extends AbstractSector
|
class PascalCatalogSector extends AbstractSector
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
private final DateFormat df = DateFormat.getDateInstance (DateFormat.SHORT);
|
private final DateFormat df = DateFormat.getDateInstance (DateFormat.SHORT);
|
||||||
private static String[] fileTypes =
|
private static String[] fileTypes =
|
||||||
{ "Volume", "Bad", "Code", "Text", "Info", "Data", "Graf", "Foto", "SecureDir" };
|
{ "Volume", "Bad", "Code", "Text", "Info", "Data", "Graf", "Foto", "SecureDir" };
|
||||||
|
|
||||||
public PascalCatalogSector (Disk disk, byte[] buffer, List<DiskAddress> diskAddress)
|
// ---------------------------------------------------------------------------------//
|
||||||
|
PascalCatalogSector (Disk disk, byte[] buffer, List<DiskAddress> diskAddress)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
super (disk, buffer);
|
super (disk, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public String createText ()
|
public String createText ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
StringBuilder text = getHeader ("Pascal Catalog Sectors");
|
StringBuilder text = getHeader ("Pascal Catalog Sectors");
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,17 @@ import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||||
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
||||||
import com.bytezone.diskbrowser.gui.DataSource;
|
import com.bytezone.diskbrowser.gui.DataSource;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
class PascalCodeObject implements AppleFileSource
|
class PascalCodeObject implements AppleFileSource
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
private final PascalDisk parent;
|
private final PascalDisk parent;
|
||||||
private final AbstractFile segment;
|
private final AbstractFile segment;
|
||||||
private final List<DiskAddress> blocks = new ArrayList<> ();
|
private final List<DiskAddress> blocks = new ArrayList<> ();
|
||||||
|
|
||||||
public PascalCodeObject (PascalDisk parent, PascalSegment segment, int firstBlock)
|
// ---------------------------------------------------------------------------------//
|
||||||
|
PascalCodeObject (PascalDisk parent, PascalSegment segment, int firstBlock)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.segment = segment;
|
this.segment = segment;
|
||||||
|
@ -30,26 +34,34 @@ class PascalCodeObject implements AppleFileSource
|
||||||
blocks.add (disk.getDiskAddress (i));
|
blocks.add (disk.getDiskAddress (i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public DataSource getDataSource ()
|
public DataSource getDataSource ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public FormattedDisk getFormattedDisk ()
|
public FormattedDisk getFormattedDisk ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public List<DiskAddress> getSectors ()
|
public List<DiskAddress> getSectors ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
return blocks;
|
return blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public boolean contains (DiskAddress da)
|
public boolean contains (DiskAddress da)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
for (DiskAddress sector : blocks)
|
for (DiskAddress sector : blocks)
|
||||||
if (sector.matches (da))
|
if (sector.matches (da))
|
||||||
|
@ -57,14 +69,18 @@ class PascalCodeObject implements AppleFileSource
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public String getUniqueName ()
|
public String getUniqueName ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
return segment.getName (); // this should be fileName/segmentName
|
return segment.getName (); // this should be fileName/segmentName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public String toString ()
|
public String toString ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
return segment.getName ();
|
return segment.getName ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,286 +1,310 @@
|
||||||
package com.bytezone.diskbrowser.pascal;
|
package com.bytezone.diskbrowser.pascal;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.tree.DefaultMutableTreeNode;
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.applefile.AppleFileSource;
|
import com.bytezone.diskbrowser.applefile.AppleFileSource;
|
||||||
import com.bytezone.diskbrowser.applefile.BootSector;
|
import com.bytezone.diskbrowser.applefile.BootSector;
|
||||||
import com.bytezone.diskbrowser.disk.*;
|
import com.bytezone.diskbrowser.disk.AbstractFormattedDisk;
|
||||||
import com.bytezone.diskbrowser.gui.DataSource;
|
import com.bytezone.diskbrowser.disk.AppleDisk;
|
||||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
import com.bytezone.diskbrowser.disk.DefaultAppleFileSource;
|
||||||
import com.bytezone.diskbrowser.wizardry.Relocator;
|
import com.bytezone.diskbrowser.disk.DefaultSector;
|
||||||
|
import com.bytezone.diskbrowser.disk.Disk;
|
||||||
public class PascalDisk extends AbstractFormattedDisk
|
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||||
{
|
import com.bytezone.diskbrowser.disk.SectorType;
|
||||||
static final int CATALOG_ENTRY_SIZE = 26;
|
import com.bytezone.diskbrowser.gui.DataSource;
|
||||||
private final DateFormat df = DateFormat.getDateInstance (DateFormat.SHORT);
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
private final VolumeEntry volumeEntry;
|
import com.bytezone.diskbrowser.wizardry.Relocator;
|
||||||
private final PascalCatalogSector diskCatalogSector;
|
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
protected Relocator relocator;
|
public class PascalDisk extends AbstractFormattedDisk
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
final String[] fileTypes =
|
{
|
||||||
{ "Volume", "Bad ", "Code", "Text", "Info", "Data", "Graf", "Foto", "SecureDir" };
|
static final int CATALOG_ENTRY_SIZE = 26;
|
||||||
|
private final DateFormat df = DateFormat.getDateInstance (DateFormat.SHORT);
|
||||||
SectorType diskBootSector = new SectorType ("Boot", Color.lightGray);
|
private final VolumeEntry volumeEntry;
|
||||||
SectorType catalogSector = new SectorType ("Catalog", Color.magenta);
|
private final PascalCatalogSector diskCatalogSector;
|
||||||
SectorType dataSector = new SectorType ("Data", new Color (0, 200, 0)); // green
|
|
||||||
SectorType codeSector = new SectorType ("Code", Color.red);
|
protected Relocator relocator;
|
||||||
SectorType textSector = new SectorType ("Text", Color.blue);
|
|
||||||
SectorType infoSector = new SectorType ("Info", Color.orange);
|
final String[] fileTypes =
|
||||||
SectorType grafSector = new SectorType ("Graf", Color.cyan);
|
{ "Volume", "Bad ", "Code", "Text", "Info", "Data", "Graf", "Foto", "SecureDir" };
|
||||||
SectorType fotoSector = new SectorType ("Foto", Color.gray);
|
|
||||||
SectorType badSector = new SectorType ("Bad", Color.darkGray);
|
SectorType diskBootSector = new SectorType ("Boot", Color.lightGray);
|
||||||
|
SectorType catalogSector = new SectorType ("Catalog", Color.magenta);
|
||||||
SectorType[] sectors = { catalogSector, badSector, codeSector, textSector, infoSector,
|
SectorType dataSector = new SectorType ("Data", new Color (0, 200, 0)); // green
|
||||||
dataSector, grafSector, fotoSector };
|
SectorType codeSector = new SectorType ("Code", Color.red);
|
||||||
|
SectorType textSector = new SectorType ("Text", Color.blue);
|
||||||
public PascalDisk (Disk disk)
|
SectorType infoSector = new SectorType ("Info", Color.orange);
|
||||||
{
|
SectorType grafSector = new SectorType ("Graf", Color.cyan);
|
||||||
super (disk);
|
SectorType fotoSector = new SectorType ("Foto", Color.gray);
|
||||||
|
SectorType badSector = new SectorType ("Bad", Color.darkGray);
|
||||||
sectorTypesList.add (diskBootSector);
|
|
||||||
sectorTypesList.add (catalogSector);
|
SectorType[] sectors = { catalogSector, badSector, codeSector, textSector, infoSector,
|
||||||
sectorTypesList.add (dataSector);
|
dataSector, grafSector, fotoSector };
|
||||||
sectorTypesList.add (codeSector);
|
|
||||||
sectorTypesList.add (textSector);
|
// ---------------------------------------------------------------------------------//
|
||||||
sectorTypesList.add (infoSector);
|
public PascalDisk (Disk disk)
|
||||||
sectorTypesList.add (grafSector);
|
// ---------------------------------------------------------------------------------//
|
||||||
sectorTypesList.add (fotoSector);
|
{
|
||||||
sectorTypesList.add (badSector);
|
super (disk);
|
||||||
|
|
||||||
List<DiskAddress> blocks = disk.getDiskAddressList (0, 1); // B0, B1
|
sectorTypesList.add (diskBootSector);
|
||||||
this.bootSector = new BootSector (disk, disk.readSectors (blocks), "Pascal");
|
sectorTypesList.add (catalogSector);
|
||||||
|
sectorTypesList.add (dataSector);
|
||||||
for (int i = 0; i < 2; i++)
|
sectorTypesList.add (codeSector);
|
||||||
if (!disk.isSectorEmpty (i))
|
sectorTypesList.add (textSector);
|
||||||
{
|
sectorTypesList.add (infoSector);
|
||||||
sectorTypes[i] = diskBootSector;
|
sectorTypesList.add (grafSector);
|
||||||
freeBlocks.set (i, false);
|
sectorTypesList.add (fotoSector);
|
||||||
}
|
sectorTypesList.add (badSector);
|
||||||
|
|
||||||
for (int i = 2; i < disk.getTotalBlocks (); i++)
|
List<DiskAddress> blocks = disk.getDiskAddressList (0, 1); // B0, B1
|
||||||
freeBlocks.set (i, true);
|
this.bootSector = new BootSector (disk, disk.readSectors (blocks), "Pascal");
|
||||||
|
|
||||||
byte[] buffer = disk.readSector (2);
|
for (int i = 0; i < 2; i++)
|
||||||
byte[] data = new byte[CATALOG_ENTRY_SIZE];
|
if (!disk.isSectorEmpty (i))
|
||||||
System.arraycopy (buffer, 0, data, 0, CATALOG_ENTRY_SIZE);
|
{
|
||||||
volumeEntry = new VolumeEntry (this, data);
|
sectorTypes[i] = diskBootSector;
|
||||||
|
freeBlocks.set (i, false);
|
||||||
DefaultMutableTreeNode root = getCatalogTreeRoot ();
|
}
|
||||||
DefaultMutableTreeNode volumeNode = new DefaultMutableTreeNode (volumeEntry);
|
|
||||||
root.add (volumeNode);
|
for (int i = 2; i < disk.getTotalBlocks (); i++)
|
||||||
|
freeBlocks.set (i, true);
|
||||||
List<DiskAddress> sectors = new ArrayList<> ();
|
|
||||||
int max = Math.min (volumeEntry.lastBlock, disk.getTotalBlocks ());
|
byte[] buffer = disk.readSector (2);
|
||||||
for (int i = 2; i < max; i++)
|
byte[] data = new byte[CATALOG_ENTRY_SIZE];
|
||||||
{
|
System.arraycopy (buffer, 0, data, 0, CATALOG_ENTRY_SIZE);
|
||||||
DiskAddress da = disk.getDiskAddress (i);
|
volumeEntry = new VolumeEntry (this, data);
|
||||||
if (!disk.isSectorEmpty (da))
|
|
||||||
sectorTypes[i] = catalogSector;
|
DefaultMutableTreeNode root = getCatalogTreeRoot ();
|
||||||
sectors.add (da);
|
DefaultMutableTreeNode volumeNode = new DefaultMutableTreeNode (volumeEntry);
|
||||||
freeBlocks.set (i, false);
|
root.add (volumeNode);
|
||||||
}
|
|
||||||
|
List<DiskAddress> sectors = new ArrayList<> ();
|
||||||
diskCatalogSector =
|
int max = Math.min (volumeEntry.lastBlock, disk.getTotalBlocks ());
|
||||||
new PascalCatalogSector (disk, disk.readSectors (sectors), sectors);
|
for (int i = 2; i < max; i++)
|
||||||
|
{
|
||||||
// read the catalog
|
DiskAddress da = disk.getDiskAddress (i);
|
||||||
List<DiskAddress> addresses = new ArrayList<> ();
|
if (!disk.isSectorEmpty (da))
|
||||||
for (int i = 2; i < max; i++)
|
sectorTypes[i] = catalogSector;
|
||||||
addresses.add (disk.getDiskAddress (i));
|
sectors.add (da);
|
||||||
buffer = disk.readSectors (addresses);
|
freeBlocks.set (i, false);
|
||||||
|
}
|
||||||
// loop through each catalog entry (what if there are deleted files?)
|
|
||||||
for (int i = 1; i <= volumeEntry.totalFiles; i++)
|
diskCatalogSector =
|
||||||
{
|
new PascalCatalogSector (disk, disk.readSectors (sectors), sectors);
|
||||||
int ptr = i * CATALOG_ENTRY_SIZE;
|
|
||||||
data = new byte[CATALOG_ENTRY_SIZE];
|
// read the catalog
|
||||||
System.arraycopy (buffer, ptr, data, 0, CATALOG_ENTRY_SIZE);
|
List<DiskAddress> addresses = new ArrayList<> ();
|
||||||
FileEntry fileEntry = new FileEntry (this, data);
|
for (int i = 2; i < max; i++)
|
||||||
|
addresses.add (disk.getDiskAddress (i));
|
||||||
fileEntries.add (fileEntry);
|
buffer = disk.readSectors (addresses);
|
||||||
DefaultMutableTreeNode node = new DefaultMutableTreeNode (fileEntry);
|
|
||||||
fileEntry.setNode (node);
|
// loop through each catalog entry (what if there are deleted files?)
|
||||||
|
for (int i = 1; i <= volumeEntry.totalFiles; i++)
|
||||||
if (fileEntry.fileType == 2)
|
{
|
||||||
{
|
int ptr = i * CATALOG_ENTRY_SIZE;
|
||||||
node.setAllowsChildren (true);
|
data = new byte[CATALOG_ENTRY_SIZE];
|
||||||
fileEntry.getDataSource (); // build segments
|
System.arraycopy (buffer, ptr, data, 0, CATALOG_ENTRY_SIZE);
|
||||||
}
|
FileEntry fileEntry = new FileEntry (this, data);
|
||||||
else
|
|
||||||
node.setAllowsChildren (false);
|
fileEntries.add (fileEntry);
|
||||||
|
DefaultMutableTreeNode node = new DefaultMutableTreeNode (fileEntry);
|
||||||
volumeNode.add (node);
|
fileEntry.setNode (node);
|
||||||
for (int j = fileEntry.firstBlock; j < fileEntry.lastBlock; j++)
|
|
||||||
freeBlocks.set (j, false);
|
if (fileEntry.fileType == 2)
|
||||||
}
|
{
|
||||||
|
node.setAllowsChildren (true);
|
||||||
volumeNode.setUserObject (getCatalog ());
|
fileEntry.getDataSource (); // build segments
|
||||||
makeNodeVisible (volumeNode.getFirstLeaf ());
|
}
|
||||||
}
|
else
|
||||||
|
node.setAllowsChildren (false);
|
||||||
public static boolean isCorrectFormat (AppleDisk disk, boolean debug)
|
|
||||||
{
|
volumeNode.add (node);
|
||||||
disk.setInterleave (1); // should only ever be Prodos
|
for (int j = fileEntry.firstBlock; j < fileEntry.lastBlock; j++)
|
||||||
if (checkFormat (disk, debug))
|
freeBlocks.set (j, false);
|
||||||
return true;
|
}
|
||||||
disk.setInterleave (0); // see SANE Disk 2.po
|
|
||||||
if (checkFormat (disk, debug))
|
volumeNode.setUserObject (getCatalog ());
|
||||||
return true;
|
makeNodeVisible (volumeNode.getFirstLeaf ());
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
public static boolean checkFormat (AppleDisk disk, boolean debug)
|
public static boolean isCorrectFormat (AppleDisk disk, boolean debug)
|
||||||
{
|
// ---------------------------------------------------------------------------------//
|
||||||
byte[] buffer = disk.readSector (2);
|
{
|
||||||
int nameLength = buffer[6] & 0xFF;
|
disk.setInterleave (1); // should only ever be Prodos
|
||||||
if (nameLength < 1 || nameLength > 7)
|
if (checkFormat (disk, debug))
|
||||||
{
|
return true;
|
||||||
if (debug)
|
disk.setInterleave (0); // see SANE Disk 2.po
|
||||||
System.out.println ("bad name length : " + nameLength);
|
if (checkFormat (disk, debug))
|
||||||
return false;
|
return true;
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
if (debug)
|
|
||||||
{
|
// ---------------------------------------------------------------------------------//
|
||||||
String name = HexFormatter.getPascalString (buffer, 6);
|
public static boolean checkFormat (AppleDisk disk, boolean debug)
|
||||||
System.out.println ("Name ok : " + name);
|
// ---------------------------------------------------------------------------------//
|
||||||
}
|
{
|
||||||
|
byte[] buffer = disk.readSector (2);
|
||||||
int from = HexFormatter.intValue (buffer[0], buffer[1]);
|
int nameLength = buffer[6] & 0xFF;
|
||||||
int to = HexFormatter.intValue (buffer[2], buffer[3]);
|
if (nameLength < 1 || nameLength > 7)
|
||||||
if (from != 0 || to != 6)
|
{
|
||||||
{
|
if (debug)
|
||||||
if (debug)
|
System.out.println ("bad name length : " + nameLength);
|
||||||
System.out.printf ("from: %d, to: %d%n", from, to);
|
return false;
|
||||||
return false; // will only work for floppies!
|
}
|
||||||
}
|
|
||||||
|
if (debug)
|
||||||
int blocks = HexFormatter.intValue (buffer[14], buffer[15]);
|
{
|
||||||
if (blocks > 280)
|
String name = HexFormatter.getPascalString (buffer, 6);
|
||||||
{
|
System.out.println ("Name ok : " + name);
|
||||||
if (debug)
|
}
|
||||||
System.out.printf ("Blocks > 280: %d%n", blocks);
|
|
||||||
// return false;
|
int from = HexFormatter.intValue (buffer[0], buffer[1]);
|
||||||
}
|
int to = HexFormatter.intValue (buffer[2], buffer[3]);
|
||||||
|
if (from != 0 || to != 6)
|
||||||
List<DiskAddress> addresses = new ArrayList<> ();
|
{
|
||||||
for (int i = 2; i < to; i++)
|
if (debug)
|
||||||
addresses.add (disk.getDiskAddress (i));
|
System.out.printf ("from: %d, to: %d%n", from, to);
|
||||||
buffer = disk.readSectors (addresses);
|
return false; // will only work for floppies!
|
||||||
|
}
|
||||||
int files = HexFormatter.intValue (buffer[16], buffer[17]);
|
|
||||||
if (files < 0 || files > 77)
|
int blocks = HexFormatter.intValue (buffer[14], buffer[15]);
|
||||||
{
|
if (blocks > 280)
|
||||||
if (debug)
|
{
|
||||||
System.out.printf ("Files: %d%n", files);
|
if (debug)
|
||||||
return false;
|
System.out.printf ("Blocks > 280: %d%n", blocks);
|
||||||
}
|
// return false;
|
||||||
|
}
|
||||||
if (debug)
|
|
||||||
System.out.println ("Files found : " + files);
|
List<DiskAddress> addresses = new ArrayList<> ();
|
||||||
|
for (int i = 2; i < to; i++)
|
||||||
for (int i = 1; i <= files; i++)
|
addresses.add (disk.getDiskAddress (i));
|
||||||
{
|
buffer = disk.readSectors (addresses);
|
||||||
int ptr = i * 26;
|
|
||||||
int firstBlock = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]);
|
int files = HexFormatter.intValue (buffer[16], buffer[17]);
|
||||||
int lastBlock = HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 3]);
|
if (files < 0 || files > 77)
|
||||||
int kind = HexFormatter.intValue (buffer[ptr + 4], buffer[ptr + 5]);
|
{
|
||||||
if (lastBlock < firstBlock)
|
if (debug)
|
||||||
return false;
|
System.out.printf ("Files: %d%n", files);
|
||||||
if (kind == 0)
|
return false;
|
||||||
return false;
|
}
|
||||||
nameLength = buffer[ptr + 6] & 0xFF;
|
|
||||||
if (nameLength < 1 || nameLength > 15)
|
if (debug)
|
||||||
return false;
|
System.out.println ("Files found : " + files);
|
||||||
int lastByte = HexFormatter.intValue (buffer[ptr + 22], buffer[ptr + 23]);
|
|
||||||
GregorianCalendar date = HexFormatter.getPascalDate (buffer, 24);
|
for (int i = 1; i <= files; i++)
|
||||||
if (debug)
|
{
|
||||||
System.out.printf ("%4d %4d %d %-15s %d %s%n", firstBlock, lastBlock, kind,
|
int ptr = i * 26;
|
||||||
new String (buffer, ptr + 7, nameLength), lastByte, date);
|
int firstBlock = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]);
|
||||||
}
|
int lastBlock = HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 3]);
|
||||||
|
int kind = HexFormatter.intValue (buffer[ptr + 4], buffer[ptr + 5]);
|
||||||
return true;
|
if (lastBlock < firstBlock)
|
||||||
}
|
return false;
|
||||||
|
if (kind == 0)
|
||||||
@Override
|
return false;
|
||||||
public DataSource getFormattedSector (DiskAddress da)
|
nameLength = buffer[ptr + 6] & 0xFF;
|
||||||
{
|
if (nameLength < 1 || nameLength > 15)
|
||||||
SectorType st = sectorTypes[da.getBlock ()];
|
return false;
|
||||||
if (st == diskBootSector)
|
int lastByte = HexFormatter.intValue (buffer[ptr + 22], buffer[ptr + 23]);
|
||||||
return bootSector;
|
GregorianCalendar date = HexFormatter.getPascalDate (buffer, 24);
|
||||||
if (st == catalogSector)
|
if (debug)
|
||||||
return diskCatalogSector;
|
System.out.printf ("%4d %4d %d %-15s %d %s%n", firstBlock, lastBlock, kind,
|
||||||
String name = getSectorFilename (da);
|
new String (buffer, ptr + 7, nameLength), lastByte, date);
|
||||||
if (name != null)
|
}
|
||||||
return new DefaultSector (name, disk, disk.readSector (da), da);
|
|
||||||
return super.getFormattedSector (da);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// ---------------------------------------------------------------------------------//
|
||||||
public String getSectorFilename (DiskAddress da)
|
@Override
|
||||||
{
|
public DataSource getFormattedSector (DiskAddress da)
|
||||||
for (AppleFileSource ce : fileEntries)
|
// ---------------------------------------------------------------------------------//
|
||||||
if (((CatalogEntry) ce).contains (da))
|
{
|
||||||
return ((CatalogEntry) ce).name;
|
SectorType st = sectorTypes[da.getBlock ()];
|
||||||
return null;
|
if (st == diskBootSector)
|
||||||
}
|
return bootSector;
|
||||||
|
if (st == catalogSector)
|
||||||
@Override
|
return diskCatalogSector;
|
||||||
public List<DiskAddress> getFileSectors (int fileNo)
|
String name = getSectorFilename (da);
|
||||||
{
|
if (name != null)
|
||||||
if (fileNo < 0 || fileNo >= fileEntries.size ())
|
return new DefaultSector (name, disk, disk.readSector (da), da);
|
||||||
return null;
|
return super.getFormattedSector (da);
|
||||||
return fileEntries.get (fileNo).getSectors ();
|
}
|
||||||
}
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
public DataSource getFile (int fileNo)
|
@Override
|
||||||
{
|
public String getSectorFilename (DiskAddress da)
|
||||||
if (fileNo < 0 || fileNo >= fileEntries.size ())
|
// ---------------------------------------------------------------------------------//
|
||||||
return null;
|
{
|
||||||
return fileEntries.get (fileNo).getDataSource ();
|
for (AppleFileSource ce : fileEntries)
|
||||||
}
|
if (((CatalogEntry) ce).contains (da))
|
||||||
|
return ((CatalogEntry) ce).name;
|
||||||
@Override
|
return null;
|
||||||
public AppleFileSource getCatalog ()
|
}
|
||||||
{
|
|
||||||
String newLine = String.format ("%n");
|
// ---------------------------------------------------------------------------------//
|
||||||
String newLine2 = newLine + newLine;
|
@Override
|
||||||
String line = "---- --------------- ---- -------- ------- ---- ---- ----"
|
public List<DiskAddress> getFileSectors (int fileNo)
|
||||||
+ newLine;
|
// ---------------------------------------------------------------------------------//
|
||||||
String date =
|
{
|
||||||
volumeEntry.date == null ? "--" : df.format (volumeEntry.date.getTime ());
|
if (fileNo < 0 || fileNo >= fileEntries.size ())
|
||||||
StringBuilder text = new StringBuilder ();
|
return null;
|
||||||
text.append ("Disk : " + getDisplayPath () + newLine2);
|
return fileEntries.get (fileNo).getSectors ();
|
||||||
text.append ("Volume : " + volumeEntry.name + newLine);
|
}
|
||||||
text.append ("Date : " + date + newLine2);
|
|
||||||
text.append (
|
// ---------------------------------------------------------------------------------//
|
||||||
"Blks Name Type Date Length Frst Last Blks\n");
|
public DataSource getFile (int fileNo)
|
||||||
text.append (line);
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
int usedBlocks = 6;
|
if (fileNo < 0 || fileNo >= fileEntries.size ())
|
||||||
for (AppleFileSource fe : fileEntries)
|
return null;
|
||||||
{
|
return fileEntries.get (fileNo).getDataSource ();
|
||||||
FileEntry ce = (FileEntry) fe;
|
}
|
||||||
int size = ce.lastBlock - ce.firstBlock;
|
|
||||||
usedBlocks += size;
|
// ---------------------------------------------------------------------------------//
|
||||||
date = ce.date == null ? "--" : df.format (ce.date.getTime ());
|
@Override
|
||||||
int bytes = (size - 1) * 512 + ce.bytesUsedInLastBlock;
|
public AppleFileSource getCatalog ()
|
||||||
String fileType = ce.fileType < 0 || ce.fileType >= fileTypes.length ? "????"
|
// ---------------------------------------------------------------------------------//
|
||||||
: fileTypes[ce.fileType];
|
{
|
||||||
text.append (String.format ("%4d %-15s %s %8s %,8d $%03X $%03X $%03X%n",
|
String newLine = String.format ("%n");
|
||||||
size, ce.name, fileType, date, bytes, ce.firstBlock, ce.lastBlock, size));
|
String newLine2 = newLine + newLine;
|
||||||
}
|
String line = "---- --------------- ---- -------- ------- ---- ---- ----"
|
||||||
text.append (line);
|
+ newLine;
|
||||||
text.append (
|
String date =
|
||||||
String.format ("Blocks free : %3d Blocks used : %3d Total blocks : %3d%n",
|
volumeEntry.date == null ? "--" : df.format (volumeEntry.date.getTime ());
|
||||||
(volumeEntry.totalBlocks - usedBlocks), usedBlocks, volumeEntry.totalBlocks));
|
StringBuilder text = new StringBuilder ();
|
||||||
return new DefaultAppleFileSource (volumeEntry.name, text.toString (), this);
|
text.append ("Disk : " + getDisplayPath () + newLine2);
|
||||||
}
|
text.append ("Volume : " + volumeEntry.name + newLine);
|
||||||
|
text.append ("Date : " + date + newLine2);
|
||||||
|
text.append (
|
||||||
|
"Blks Name Type Date Length Frst Last Blks\n");
|
||||||
|
text.append (line);
|
||||||
|
|
||||||
|
int usedBlocks = 6;
|
||||||
|
for (AppleFileSource fe : fileEntries)
|
||||||
|
{
|
||||||
|
FileEntry ce = (FileEntry) fe;
|
||||||
|
int size = ce.lastBlock - ce.firstBlock;
|
||||||
|
usedBlocks += size;
|
||||||
|
date = ce.date == null ? "--" : df.format (ce.date.getTime ());
|
||||||
|
int bytes = (size - 1) * 512 + ce.bytesUsedInLastBlock;
|
||||||
|
String fileType = ce.fileType < 0 || ce.fileType >= fileTypes.length ? "????"
|
||||||
|
: fileTypes[ce.fileType];
|
||||||
|
text.append (String.format ("%4d %-15s %s %8s %,8d $%03X $%03X $%03X%n",
|
||||||
|
size, ce.name, fileType, date, bytes, ce.firstBlock, ce.lastBlock, size));
|
||||||
|
}
|
||||||
|
text.append (line);
|
||||||
|
text.append (
|
||||||
|
String.format ("Blocks free : %3d Blocks used : %3d Total blocks : %3d%n",
|
||||||
|
(volumeEntry.totalBlocks - usedBlocks), usedBlocks, volumeEntry.totalBlocks));
|
||||||
|
return new DefaultAppleFileSource (volumeEntry.name, text.toString (), this);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -4,12 +4,16 @@ import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||||
import com.bytezone.diskbrowser.applefile.DefaultAppleFile;
|
import com.bytezone.diskbrowser.applefile.DefaultAppleFile;
|
||||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
class VolumeEntry extends CatalogEntry
|
class VolumeEntry extends CatalogEntry
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
final int totalFiles;
|
final int totalFiles;
|
||||||
final int totalBlocks;
|
final int totalBlocks;
|
||||||
|
|
||||||
public VolumeEntry (PascalDisk parent, byte[] buffer)
|
// ---------------------------------------------------------------------------------//
|
||||||
|
VolumeEntry (PascalDisk parent, byte[] buffer)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
super (parent, buffer);
|
super (parent, buffer);
|
||||||
|
|
||||||
|
@ -18,8 +22,10 @@ class VolumeEntry extends CatalogEntry
|
||||||
date = HexFormatter.getPascalDate (buffer, 20); // 2 bytes
|
date = HexFormatter.getPascalDate (buffer, 20); // 2 bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public AbstractFile getDataSource ()
|
public AbstractFile getDataSource ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
if (file != null)
|
if (file != null)
|
||||||
return file;
|
return file;
|
||||||
|
|
|
@ -1,74 +1,86 @@
|
||||||
package com.bytezone.diskbrowser.prodos;
|
package com.bytezone.diskbrowser.prodos;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.applefile.AppleFileSource;
|
import com.bytezone.diskbrowser.applefile.AppleFileSource;
|
||||||
import com.bytezone.diskbrowser.disk.Disk;
|
import com.bytezone.diskbrowser.disk.Disk;
|
||||||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||||
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
||||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
|
|
||||||
abstract class CatalogEntry implements AppleFileSource
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
abstract class CatalogEntry implements AppleFileSource
|
||||||
ProdosDisk parentDisk;
|
// -----------------------------------------------------------------------------------//
|
||||||
DirectoryHeader parentDirectory;
|
{
|
||||||
String name;
|
ProdosDisk parentDisk;
|
||||||
int storageType;
|
DirectoryHeader parentDirectory;
|
||||||
GregorianCalendar created;
|
String name;
|
||||||
int version;
|
int storageType;
|
||||||
int minVersion;
|
GregorianCalendar created;
|
||||||
int access;
|
int version;
|
||||||
List<DiskAddress> dataBlocks = new ArrayList<> ();
|
int minVersion;
|
||||||
Disk disk;
|
int access;
|
||||||
|
List<DiskAddress> dataBlocks = new ArrayList<> ();
|
||||||
public CatalogEntry (ProdosDisk parentDisk, byte[] entryBuffer)
|
Disk disk;
|
||||||
{
|
|
||||||
this.parentDisk = parentDisk;
|
// ---------------------------------------------------------------------------------//
|
||||||
this.disk = parentDisk.getDisk ();
|
CatalogEntry (ProdosDisk parentDisk, byte[] entryBuffer)
|
||||||
name = HexFormatter.getString (entryBuffer, 1, entryBuffer[0] & 0x0F);
|
// ---------------------------------------------------------------------------------//
|
||||||
storageType = (entryBuffer[0] & 0xF0) >> 4;
|
{
|
||||||
created = HexFormatter.getAppleDate (entryBuffer, 24);
|
this.parentDisk = parentDisk;
|
||||||
version = entryBuffer[28] & 0xFF;
|
this.disk = parentDisk.getDisk ();
|
||||||
minVersion = entryBuffer[29] & 0xFF;
|
name = HexFormatter.getString (entryBuffer, 1, entryBuffer[0] & 0x0F);
|
||||||
access = entryBuffer[30] & 0xFF;
|
storageType = (entryBuffer[0] & 0xF0) >> 4;
|
||||||
}
|
created = HexFormatter.getAppleDate (entryBuffer, 24);
|
||||||
|
version = entryBuffer[28] & 0xFF;
|
||||||
@Override
|
minVersion = entryBuffer[29] & 0xFF;
|
||||||
public String getUniqueName ()
|
access = entryBuffer[30] & 0xFF;
|
||||||
{
|
}
|
||||||
if (parentDirectory == null)
|
|
||||||
return name;
|
// ---------------------------------------------------------------------------------//
|
||||||
return parentDirectory.getUniqueName () + "/" + name;
|
@Override
|
||||||
}
|
public String getUniqueName ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
{
|
||||||
public FormattedDisk getFormattedDisk ()
|
if (parentDirectory == null)
|
||||||
{
|
return name;
|
||||||
return parentDisk;
|
return parentDirectory.getUniqueName () + "/" + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// ---------------------------------------------------------------------------------//
|
||||||
public boolean contains (DiskAddress da)
|
@Override
|
||||||
{
|
public FormattedDisk getFormattedDisk ()
|
||||||
for (DiskAddress sector : dataBlocks)
|
// ---------------------------------------------------------------------------------//
|
||||||
if (sector.matches (da))
|
{
|
||||||
return true;
|
return parentDisk;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public String toString ()
|
public boolean contains (DiskAddress da)
|
||||||
{
|
// ---------------------------------------------------------------------------------//
|
||||||
StringBuilder text = new StringBuilder ();
|
{
|
||||||
|
for (DiskAddress sector : dataBlocks)
|
||||||
text.append (String.format ("Name .......... %s%n", name));
|
if (sector.matches (da))
|
||||||
text.append (String.format ("Storage type... %02X%n", storageType));
|
return true;
|
||||||
text.append (String.format ("Created ....... %s%n",
|
return false;
|
||||||
created == null ? "" : parentDisk.df.format (created.getTime ())));
|
}
|
||||||
text.append (String.format ("Version ....... %d%n", version));
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
return text.toString ();
|
@Override
|
||||||
}
|
public String toString ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
StringBuilder text = new StringBuilder ();
|
||||||
|
|
||||||
|
text.append (String.format ("Name .......... %s%n", name));
|
||||||
|
text.append (String.format ("Storage type... %02X%n", storageType));
|
||||||
|
text.append (String.format ("Created ....... %s%n",
|
||||||
|
created == null ? "" : parentDisk.df.format (created.getTime ())));
|
||||||
|
text.append (String.format ("Version ....... %d%n", version));
|
||||||
|
|
||||||
|
return text.toString ();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,19 +1,23 @@
|
||||||
package com.bytezone.diskbrowser.prodos;
|
package com.bytezone.diskbrowser.prodos;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
|
|
||||||
abstract class DirectoryHeader extends CatalogEntry
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
abstract class DirectoryHeader extends CatalogEntry
|
||||||
final int entryLength;
|
// -----------------------------------------------------------------------------------//
|
||||||
final int entriesPerBlock;
|
{
|
||||||
final int fileCount;
|
final int entryLength;
|
||||||
|
final int entriesPerBlock;
|
||||||
public DirectoryHeader (ProdosDisk parentDisk, byte[] entryBuffer)
|
final int fileCount;
|
||||||
{
|
|
||||||
super (parentDisk, entryBuffer);
|
// ---------------------------------------------------------------------------------//
|
||||||
|
DirectoryHeader (ProdosDisk parentDisk, byte[] entryBuffer)
|
||||||
entryLength = entryBuffer[31] & 0xFF;
|
// ---------------------------------------------------------------------------------//
|
||||||
entriesPerBlock = entryBuffer[32] & 0xFF;
|
{
|
||||||
fileCount = HexFormatter.intValue (entryBuffer[33], entryBuffer[34]);
|
super (parentDisk, entryBuffer);
|
||||||
}
|
|
||||||
|
entryLength = entryBuffer[31] & 0xFF;
|
||||||
|
entriesPerBlock = entryBuffer[32] & 0xFF;
|
||||||
|
fileCount = HexFormatter.intValue (entryBuffer[33], entryBuffer[34]);
|
||||||
|
}
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,69 +1,75 @@
|
||||||
package com.bytezone.diskbrowser.prodos;
|
package com.bytezone.diskbrowser.prodos;
|
||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.disk.AbstractSector;
|
import com.bytezone.diskbrowser.disk.AbstractSector;
|
||||||
import com.bytezone.diskbrowser.disk.Disk;
|
import com.bytezone.diskbrowser.disk.Disk;
|
||||||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||||
|
|
||||||
class ProdosBitMapSector extends AbstractSector
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
class ProdosBitMapSector extends AbstractSector
|
||||||
private final ProdosDisk parent;
|
// -----------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
ProdosBitMapSector (ProdosDisk parent, Disk disk, byte[] buffer, DiskAddress da)
|
private final ProdosDisk parent;
|
||||||
{
|
|
||||||
super (disk, buffer, da);
|
// ---------------------------------------------------------------------------------//
|
||||||
this.parent = parent;
|
ProdosBitMapSector (ProdosDisk parent, Disk disk, byte[] buffer, DiskAddress da)
|
||||||
}
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
@Override
|
super (disk, buffer, da);
|
||||||
public String createText ()
|
this.parent = parent;
|
||||||
{
|
}
|
||||||
Dimension grid = parent.getGridLayout ();
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
// check range of bits for current block - so far I don't have a disk that needs
|
@Override
|
||||||
// more than a single block
|
public String createText ()
|
||||||
int relativeBlock =
|
// ---------------------------------------------------------------------------------//
|
||||||
diskAddress.getBlock () - parent.getVolumeDirectoryHeader ().bitMapBlock;
|
{
|
||||||
int startBit = relativeBlock * 4096;
|
Dimension grid = parent.getGridLayout ();
|
||||||
// int endBit = startBit + 4096;
|
|
||||||
if (startBit >= grid.width * grid.height)
|
// check range of bits for current block - so far I don't have a disk that needs
|
||||||
return "This sector is not used - the physical file size makes it unnecessary";
|
// more than a single block
|
||||||
|
int relativeBlock =
|
||||||
int width = (grid.width - 1) / 8 + 1; // must be 1-4
|
diskAddress.getBlock () - parent.getVolumeDirectoryHeader ().bitMapBlock;
|
||||||
|
int startBit = relativeBlock * 4096;
|
||||||
StringBuilder text = getHeader ("Volume Bit Map Block");
|
// int endBit = startBit + 4096;
|
||||||
|
if (startBit >= grid.width * grid.height)
|
||||||
if (false)
|
return "This sector is not used - the physical file size makes it unnecessary";
|
||||||
{
|
|
||||||
int block = 0;
|
int width = (grid.width - 1) / 8 + 1; // must be 1-4
|
||||||
for (int row = 0; row < grid.height; row++)
|
|
||||||
{
|
StringBuilder text = getHeader ("Volume Bit Map Block");
|
||||||
int offset = block / 8;
|
|
||||||
StringBuilder details = new StringBuilder ();
|
if (false)
|
||||||
for (int col = 0; col < grid.width; col++)
|
{
|
||||||
details.append (parent.isSectorFree (block++) ? ". " : "X ");
|
int block = 0;
|
||||||
addText (text, buffer, offset, width, details.toString ());
|
for (int row = 0; row < grid.height; row++)
|
||||||
}
|
{
|
||||||
}
|
int offset = block / 8;
|
||||||
else
|
StringBuilder details = new StringBuilder ();
|
||||||
{
|
for (int col = 0; col < grid.width; col++)
|
||||||
int startRow = relativeBlock * 512 / width;
|
details.append (parent.isSectorFree (block++) ? ". " : "X ");
|
||||||
int endRow = startRow + (512 / width);
|
addText (text, buffer, offset, width, details.toString ());
|
||||||
int block = startBit;
|
}
|
||||||
int byteNo = 0;
|
}
|
||||||
// System.out.printf ("Start %d, end %d%n", startRow, endRow);
|
else
|
||||||
for (int row = startRow; row < endRow; row++)
|
{
|
||||||
{
|
int startRow = relativeBlock * 512 / width;
|
||||||
StringBuilder details = new StringBuilder ();
|
int endRow = startRow + (512 / width);
|
||||||
for (int col = 0; col < grid.width; col++)
|
int block = startBit;
|
||||||
details.append (parent.isSectorFree (block++) ? ". " : "X ");
|
int byteNo = 0;
|
||||||
addText (text, buffer, byteNo, width, details.toString ());
|
// System.out.printf ("Start %d, end %d%n", startRow, endRow);
|
||||||
byteNo += width;
|
for (int row = startRow; row < endRow; row++)
|
||||||
}
|
{
|
||||||
}
|
StringBuilder details = new StringBuilder ();
|
||||||
|
for (int col = 0; col < grid.width; col++)
|
||||||
text.deleteCharAt (text.length () - 1);
|
details.append (parent.isSectorFree (block++) ? ". " : "X ");
|
||||||
return text.toString ();
|
addText (text, buffer, byteNo, width, details.toString ());
|
||||||
}
|
byteNo += width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
text.deleteCharAt (text.length () - 1);
|
||||||
|
return text.toString ();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,203 +1,232 @@
|
||||||
package com.bytezone.diskbrowser.prodos;
|
package com.bytezone.diskbrowser.prodos;
|
||||||
|
|
||||||
import static com.bytezone.diskbrowser.prodos.ProdosConstants.*;
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.ENTRY_SIZE;
|
||||||
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.FREE;
|
||||||
import java.util.GregorianCalendar;
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.GSOS_EXTENDED_FILE;
|
||||||
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.PASCAL_ON_PROFILE;
|
||||||
import com.bytezone.diskbrowser.disk.AbstractSector;
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.SAPLING;
|
||||||
import com.bytezone.diskbrowser.disk.Disk;
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.SEEDLING;
|
||||||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.SUBDIRECTORY;
|
||||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.SUBDIRECTORY_HEADER;
|
||||||
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.TREE;
|
||||||
class ProdosCatalogSector extends AbstractSector
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.VOLUME_HEADER;
|
||||||
{
|
|
||||||
private final ProdosDisk parent;
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
ProdosCatalogSector (ProdosDisk parent, Disk disk, byte[] buffer,
|
import com.bytezone.diskbrowser.disk.AbstractSector;
|
||||||
DiskAddress diskAddress)
|
import com.bytezone.diskbrowser.disk.Disk;
|
||||||
{
|
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||||
super (disk, buffer, diskAddress);
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
this.parent = parent;
|
|
||||||
}
|
// -----------------------------------------------------------------------------------//
|
||||||
|
class ProdosCatalogSector extends AbstractSector
|
||||||
@Override
|
// -----------------------------------------------------------------------------------//
|
||||||
public String createText ()
|
{
|
||||||
{
|
private final ProdosDisk parent;
|
||||||
StringBuilder text = getHeader ("Volume Directory Block");
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
addTextAndDecimal (text, buffer, 0, 2, "Previous block");
|
ProdosCatalogSector (ProdosDisk parent, Disk disk, byte[] buffer,
|
||||||
addTextAndDecimal (text, buffer, 2, 2, "Next block");
|
DiskAddress diskAddress)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
for (int i = 4, max = buffer.length - ENTRY_SIZE; i <= max; i += ENTRY_SIZE)
|
{
|
||||||
{
|
super (disk, buffer, diskAddress);
|
||||||
if (buffer[i] == 0 && buffer[i + 1] == 0)
|
this.parent = parent;
|
||||||
break;
|
}
|
||||||
text.append ("\n");
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
// first byte contains the file type (left nybble) and name length (right nybble)
|
@Override
|
||||||
int fileType = (buffer[i] & 0xF0) >> 4;
|
public String createText ()
|
||||||
int nameLength = buffer[i] & 0x0F;
|
// ---------------------------------------------------------------------------------//
|
||||||
String hex1 = String.format ("%02X", buffer[i] & 0xF0);
|
{
|
||||||
String hex2 = String.format ("%02X", nameLength);
|
StringBuilder text = getHeader ("Volume Directory Block");
|
||||||
|
|
||||||
// deleted files set file type and name length to zero, but the file
|
addTextAndDecimal (text, buffer, 0, 2, "Previous block");
|
||||||
// name is still valid
|
addTextAndDecimal (text, buffer, 2, 2, "Next block");
|
||||||
String typeText = hex1 + " = " + getType (buffer[i]);
|
|
||||||
if (fileType == 0)
|
for (int i = 4, max = buffer.length - ENTRY_SIZE; i <= max; i += ENTRY_SIZE)
|
||||||
addText (text, buffer, i, 1, typeText + " : " + getDeletedName (i + 1));
|
{
|
||||||
else
|
if (buffer[i] == 0 && buffer[i + 1] == 0)
|
||||||
addText (text, buffer, i, 1, typeText + ", " + hex2 + " = Name length");
|
break;
|
||||||
|
text.append ("\n");
|
||||||
addText (text, buffer, i + 1, 4,
|
|
||||||
HexFormatter.getString (buffer, i + 1, nameLength));
|
// first byte contains the file type (left nybble) and name length (right nybble)
|
||||||
|
int fileType = (buffer[i] & 0xF0) >> 4;
|
||||||
switch (fileType)
|
int nameLength = buffer[i] & 0x0F;
|
||||||
{
|
String hex1 = String.format ("%02X", buffer[i] & 0xF0);
|
||||||
case FREE:
|
String hex2 = String.format ("%02X", nameLength);
|
||||||
case SEEDLING:
|
|
||||||
case SAPLING:
|
// deleted files set file type and name length to zero, but the file
|
||||||
case TREE:
|
// name is still valid
|
||||||
case PASCAL_ON_PROFILE:
|
String typeText = hex1 + " = " + getType (buffer[i]);
|
||||||
case GSOS_EXTENDED_FILE:
|
if (fileType == 0)
|
||||||
case SUBDIRECTORY:
|
addText (text, buffer, i, 1, typeText + " : " + getDeletedName (i + 1));
|
||||||
text.append (doFileDescription (i));
|
else
|
||||||
break;
|
addText (text, buffer, i, 1, typeText + ", " + hex2 + " = Name length");
|
||||||
case SUBDIRECTORY_HEADER:
|
|
||||||
text.append (doSubdirectoryHeader (i));
|
addText (text, buffer, i + 1, 4,
|
||||||
break;
|
HexFormatter.getString (buffer, i + 1, nameLength));
|
||||||
case VOLUME_HEADER:
|
|
||||||
text.append (doVolumeDirectoryHeader (i));
|
switch (fileType)
|
||||||
break;
|
{
|
||||||
default:
|
case FREE:
|
||||||
text.append ("Unknown\n");
|
case SEEDLING:
|
||||||
}
|
case SAPLING:
|
||||||
}
|
case TREE:
|
||||||
if (text.length () > 0)
|
case PASCAL_ON_PROFILE:
|
||||||
text.deleteCharAt (text.length () - 1);
|
case GSOS_EXTENDED_FILE:
|
||||||
return text.toString ();
|
case SUBDIRECTORY:
|
||||||
}
|
text.append (doFileDescription (i));
|
||||||
|
break;
|
||||||
private String doFileDescription (int offset)
|
case SUBDIRECTORY_HEADER:
|
||||||
{
|
text.append (doSubdirectoryHeader (i));
|
||||||
StringBuilder text = new StringBuilder ();
|
break;
|
||||||
int fileType = buffer[offset + 16] & 0xFF;
|
case VOLUME_HEADER:
|
||||||
int auxType = HexFormatter.unsignedShort (buffer, offset + 31);
|
text.append (doVolumeDirectoryHeader (i));
|
||||||
addText (text, buffer, offset + 16, 1,
|
break;
|
||||||
"File type (" + ProdosConstants.fileTypes[fileType] + ")");
|
default:
|
||||||
addTextAndDecimal (text, buffer, offset + 17, 2, "Key pointer");
|
text.append ("Unknown\n");
|
||||||
addTextAndDecimal (text, buffer, offset + 19, 2, "Blocks used");
|
}
|
||||||
addTextAndDecimal (text, buffer, offset + 21, 3, "EOF");
|
}
|
||||||
GregorianCalendar created = HexFormatter.getAppleDate (buffer, offset + 24);
|
if (text.length () > 0)
|
||||||
String dateC = created == null ? "" : parent.df.format (created.getTime ());
|
text.deleteCharAt (text.length () - 1);
|
||||||
addText (text, buffer, offset + 24, 4, "Creation date : " + dateC);
|
return text.toString ();
|
||||||
addTextAndDecimal (text, buffer, offset + 28, 1, "Version");
|
}
|
||||||
addText (text, buffer, offset + 29, 1, "Minimum version");
|
|
||||||
addText (text, buffer, offset + 30, 1, "Access");
|
// ---------------------------------------------------------------------------------//
|
||||||
addTextAndDecimal (text, buffer, offset + 31, 2,
|
private String doFileDescription (int offset)
|
||||||
"Auxilliary type - " + getAuxilliaryText (fileType, auxType));
|
// ---------------------------------------------------------------------------------//
|
||||||
GregorianCalendar modified = HexFormatter.getAppleDate (buffer, offset + 33);
|
{
|
||||||
String dateM = modified == null ? "" : parent.df.format (modified.getTime ());
|
StringBuilder text = new StringBuilder ();
|
||||||
addText (text, buffer, offset + 33, 4, "Modification date : " + dateM);
|
int fileType = buffer[offset + 16] & 0xFF;
|
||||||
addTextAndDecimal (text, buffer, offset + 37, 2, "Header pointer");
|
int auxType = HexFormatter.unsignedShort (buffer, offset + 31);
|
||||||
return text.toString ();
|
addText (text, buffer, offset + 16, 1,
|
||||||
}
|
"File type (" + ProdosConstants.fileTypes[fileType] + ")");
|
||||||
|
addTextAndDecimal (text, buffer, offset + 17, 2, "Key pointer");
|
||||||
private String doVolumeDirectoryHeader (int offset)
|
addTextAndDecimal (text, buffer, offset + 19, 2, "Blocks used");
|
||||||
{
|
addTextAndDecimal (text, buffer, offset + 21, 3, "EOF");
|
||||||
StringBuilder text = new StringBuilder ();
|
GregorianCalendar created = HexFormatter.getAppleDate (buffer, offset + 24);
|
||||||
addText (text, buffer, offset + 16, 4, "Not used");
|
String dateC = created == null ? "" : parent.df.format (created.getTime ());
|
||||||
text.append (getCommonHeader (offset));
|
addText (text, buffer, offset + 24, 4, "Creation date : " + dateC);
|
||||||
addTextAndDecimal (text, buffer, offset + 35, 2, "Bit map pointer");
|
addTextAndDecimal (text, buffer, offset + 28, 1, "Version");
|
||||||
addTextAndDecimal (text, buffer, offset + 37, 2, "Total blocks");
|
addText (text, buffer, offset + 29, 1, "Minimum version");
|
||||||
return text.toString ();
|
addText (text, buffer, offset + 30, 1, "Access");
|
||||||
}
|
addTextAndDecimal (text, buffer, offset + 31, 2,
|
||||||
|
"Auxilliary type - " + getAuxilliaryText (fileType, auxType));
|
||||||
private String doSubdirectoryHeader (int offset)
|
GregorianCalendar modified = HexFormatter.getAppleDate (buffer, offset + 33);
|
||||||
{
|
String dateM = modified == null ? "" : parent.df.format (modified.getTime ());
|
||||||
StringBuilder text = new StringBuilder ();
|
addText (text, buffer, offset + 33, 4, "Modification date : " + dateM);
|
||||||
addText (text, buffer, offset + 16, 1, "Hex $75");
|
addTextAndDecimal (text, buffer, offset + 37, 2, "Header pointer");
|
||||||
addText (text, buffer, offset + 17, 3, "Not used");
|
return text.toString ();
|
||||||
text.append (getCommonHeader (offset));
|
}
|
||||||
addTextAndDecimal (text, buffer, offset + 35, 2, "Parent block");
|
|
||||||
addTextAndDecimal (text, buffer, offset + 37, 1, "Parent entry number");
|
// ---------------------------------------------------------------------------------//
|
||||||
addTextAndDecimal (text, buffer, offset + 38, 1, "Parent entry length");
|
private String doVolumeDirectoryHeader (int offset)
|
||||||
return text.toString ();
|
// ---------------------------------------------------------------------------------//
|
||||||
}
|
{
|
||||||
|
StringBuilder text = new StringBuilder ();
|
||||||
private String getCommonHeader (int offset)
|
addText (text, buffer, offset + 16, 4, "Not used");
|
||||||
{
|
text.append (getCommonHeader (offset));
|
||||||
StringBuilder text = new StringBuilder ();
|
addTextAndDecimal (text, buffer, offset + 35, 2, "Bit map pointer");
|
||||||
addText (text, buffer, offset + 20, 4, "Not used");
|
addTextAndDecimal (text, buffer, offset + 37, 2, "Total blocks");
|
||||||
GregorianCalendar created = HexFormatter.getAppleDate (buffer, offset + 24);
|
return text.toString ();
|
||||||
String dateC = created == null ? "" : parent.df.format (created.getTime ());
|
}
|
||||||
addText (text, buffer, offset + 24, 4, "Creation date : " + dateC);
|
|
||||||
addText (text, buffer, offset + 28, 1, "Prodos version");
|
// ---------------------------------------------------------------------------------//
|
||||||
addText (text, buffer, offset + 29, 1, "Minimum version");
|
private String doSubdirectoryHeader (int offset)
|
||||||
addText (text, buffer, offset + 30, 1, "Access");
|
// ---------------------------------------------------------------------------------//
|
||||||
addTextAndDecimal (text, buffer, offset + 31, 1, "Entry length");
|
{
|
||||||
addTextAndDecimal (text, buffer, offset + 32, 1, "Entries per block");
|
StringBuilder text = new StringBuilder ();
|
||||||
addTextAndDecimal (text, buffer, offset + 33, 2, "File count");
|
addText (text, buffer, offset + 16, 1, "Hex $75");
|
||||||
|
addText (text, buffer, offset + 17, 3, "Not used");
|
||||||
return text.toString ();
|
text.append (getCommonHeader (offset));
|
||||||
}
|
addTextAndDecimal (text, buffer, offset + 35, 2, "Parent block");
|
||||||
|
addTextAndDecimal (text, buffer, offset + 37, 1, "Parent entry number");
|
||||||
private String getAuxilliaryText (int fileType, int auxType)
|
addTextAndDecimal (text, buffer, offset + 38, 1, "Parent entry length");
|
||||||
{
|
return text.toString ();
|
||||||
switch (fileType)
|
}
|
||||||
{
|
|
||||||
case 0x04:
|
// ---------------------------------------------------------------------------------//
|
||||||
return "record length";
|
private String getCommonHeader (int offset)
|
||||||
case 0xFD:
|
// ---------------------------------------------------------------------------------//
|
||||||
return "address of stored variables";
|
{
|
||||||
case 0x06:
|
StringBuilder text = new StringBuilder ();
|
||||||
case 0xFC:
|
addText (text, buffer, offset + 20, 4, "Not used");
|
||||||
case 0xFF:
|
GregorianCalendar created = HexFormatter.getAppleDate (buffer, offset + 24);
|
||||||
return "load address";
|
String dateC = created == null ? "" : parent.df.format (created.getTime ());
|
||||||
case 0xB3:
|
addText (text, buffer, offset + 24, 4, "Creation date : " + dateC);
|
||||||
return "forked";
|
addText (text, buffer, offset + 28, 1, "Prodos version");
|
||||||
case 0xC1:
|
addText (text, buffer, offset + 29, 1, "Minimum version");
|
||||||
return "PIC";
|
addText (text, buffer, offset + 30, 1, "Access");
|
||||||
case 0xC8:
|
addTextAndDecimal (text, buffer, offset + 31, 1, "Entry length");
|
||||||
return auxType == 0 ? "QuickDraw bitmap font"
|
addTextAndDecimal (text, buffer, offset + 32, 1, "Entries per block");
|
||||||
: auxType == 1 ? "Pointless truetype font" : "??";
|
addTextAndDecimal (text, buffer, offset + 33, 2, "File count");
|
||||||
default:
|
|
||||||
return "???";
|
return text.toString ();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
private String getType (byte flag)
|
private String getAuxilliaryText (int fileType, int auxType)
|
||||||
{
|
// ---------------------------------------------------------------------------------//
|
||||||
switch ((flag & 0xF0) >> 4)
|
{
|
||||||
{
|
switch (fileType)
|
||||||
case FREE:
|
{
|
||||||
return "Deleted";
|
case 0x04:
|
||||||
case SEEDLING:
|
return "record length";
|
||||||
return "Seedling";
|
case 0xFD:
|
||||||
case SAPLING:
|
return "address of stored variables";
|
||||||
return "Sapling";
|
case 0x06:
|
||||||
case TREE:
|
case 0xFC:
|
||||||
return "Tree";
|
case 0xFF:
|
||||||
case PASCAL_ON_PROFILE:
|
return "load address";
|
||||||
return "Pascal area on a Profile HD";
|
case 0xB3:
|
||||||
case GSOS_EXTENDED_FILE:
|
return "forked";
|
||||||
return "GS/OS extended file";
|
case 0xC1:
|
||||||
case SUBDIRECTORY:
|
return "PIC";
|
||||||
return "Subdirectory";
|
case 0xC8:
|
||||||
case SUBDIRECTORY_HEADER:
|
return auxType == 0 ? "QuickDraw bitmap font"
|
||||||
return "Subdirectory Header";
|
: auxType == 1 ? "Pointless truetype font" : "??";
|
||||||
case VOLUME_HEADER:
|
default:
|
||||||
return "Volume Directory Header";
|
return "???";
|
||||||
default:
|
}
|
||||||
return "???";
|
}
|
||||||
}
|
|
||||||
}
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private String getType (byte flag)
|
||||||
// Deleted files leave the name intact, but set the name length to zero
|
// ---------------------------------------------------------------------------------//
|
||||||
private String getDeletedName (int offset)
|
{
|
||||||
{
|
switch ((flag & 0xF0) >> 4)
|
||||||
StringBuilder text = new StringBuilder ();
|
{
|
||||||
for (int i = offset, max = offset + 15; i < max && buffer[i] != 0; i++)
|
case FREE:
|
||||||
text.append ((char) (buffer[i] & 0xFF));
|
return "Deleted";
|
||||||
return text.toString ();
|
case SEEDLING:
|
||||||
}
|
return "Seedling";
|
||||||
|
case SAPLING:
|
||||||
|
return "Sapling";
|
||||||
|
case TREE:
|
||||||
|
return "Tree";
|
||||||
|
case PASCAL_ON_PROFILE:
|
||||||
|
return "Pascal area on a Profile HD";
|
||||||
|
case GSOS_EXTENDED_FILE:
|
||||||
|
return "GS/OS extended file";
|
||||||
|
case SUBDIRECTORY:
|
||||||
|
return "Subdirectory";
|
||||||
|
case SUBDIRECTORY_HEADER:
|
||||||
|
return "Subdirectory Header";
|
||||||
|
case VOLUME_HEADER:
|
||||||
|
return "Volume Directory Header";
|
||||||
|
default:
|
||||||
|
return "???";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deleted files leave the name intact, but set the name length to zero
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private String getDeletedName (int offset)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
StringBuilder text = new StringBuilder ();
|
||||||
|
for (int i = offset, max = offset + 15; i < max && buffer[i] != 0; i++)
|
||||||
|
text.append ((char) (buffer[i] & 0xFF));
|
||||||
|
return text.toString ();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,253 +1,255 @@
|
||||||
package com.bytezone.diskbrowser.prodos;
|
package com.bytezone.diskbrowser.prodos;
|
||||||
|
|
||||||
public interface ProdosConstants
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
public interface ProdosConstants
|
||||||
static int FILE_TYPE_NON = 0x00;
|
// -----------------------------------------------------------------------------------//
|
||||||
static int FILE_TYPE_PCD = 0x02;
|
{
|
||||||
static int FILE_TYPE_TEXT = 0x04;
|
static int FILE_TYPE_NON = 0x00;
|
||||||
static int FILE_TYPE_PDA = 0x05;
|
static int FILE_TYPE_PCD = 0x02;
|
||||||
static int FILE_TYPE_BINARY = 0x06;
|
static int FILE_TYPE_TEXT = 0x04;
|
||||||
static int FILE_TYPE_FNT = 0x07;
|
static int FILE_TYPE_PDA = 0x05;
|
||||||
static int FILE_TYPE_FOT = 0x08; // was Apple /// FotoFile
|
static int FILE_TYPE_BINARY = 0x06;
|
||||||
static int FILE_TYPE_DIRECTORY = 0x0F;
|
static int FILE_TYPE_FNT = 0x07;
|
||||||
static int FILE_TYPE_ADB = 0x19;
|
static int FILE_TYPE_FOT = 0x08; // was Apple /// FotoFile
|
||||||
static int FILE_TYPE_AWP = 0x1A;
|
static int FILE_TYPE_DIRECTORY = 0x0F;
|
||||||
static int FILE_TYPE_ASP = 0x1B;
|
static int FILE_TYPE_ADB = 0x19;
|
||||||
static int FILE_TYPE_DESCRIPTOR_TABLE = 0x42;
|
static int FILE_TYPE_AWP = 0x1A;
|
||||||
static int FILE_TYPE_GWP = 0x50;
|
static int FILE_TYPE_ASP = 0x1B;
|
||||||
static int FILE_TYPE_GEO = 0x82;
|
static int FILE_TYPE_DESCRIPTOR_TABLE = 0x42;
|
||||||
static int FILE_TYPE_IIGS_SOURCE = 0xB0;
|
static int FILE_TYPE_GWP = 0x50;
|
||||||
static int FILE_TYPE_IIGS_OBJECT = 0xB1;
|
static int FILE_TYPE_GEO = 0x82;
|
||||||
static int FILE_TYPE_IIGS_APPLICATION = 0xB3;
|
static int FILE_TYPE_IIGS_SOURCE = 0xB0;
|
||||||
static int FILE_TYPE_IIGS_DEVICE_DRIVER = 0xBB;
|
static int FILE_TYPE_IIGS_OBJECT = 0xB1;
|
||||||
static int FILE_TYPE_LDF = 0xBC;
|
static int FILE_TYPE_IIGS_APPLICATION = 0xB3;
|
||||||
static int FILE_TYPE_GS_BASIC = 0xAB;
|
static int FILE_TYPE_IIGS_DEVICE_DRIVER = 0xBB;
|
||||||
static int FILE_TYPE_GSOS_FILE_SYSTEM_TRANSLATOR = 0xBD;
|
static int FILE_TYPE_LDF = 0xBC;
|
||||||
static int FILE_TYPE_PNT = 0xC0;
|
static int FILE_TYPE_GS_BASIC = 0xAB;
|
||||||
static int FILE_TYPE_PIC = 0xC1;
|
static int FILE_TYPE_GSOS_FILE_SYSTEM_TRANSLATOR = 0xBD;
|
||||||
static int FILE_TYPE_ANI = 0xC2;
|
static int FILE_TYPE_PNT = 0xC0;
|
||||||
static int FILE_TYPE_PAL = 0xC3;
|
static int FILE_TYPE_PIC = 0xC1;
|
||||||
static int FILE_TYPE_FONT = 0xC8;
|
static int FILE_TYPE_ANI = 0xC2;
|
||||||
static int FILE_TYPE_FINDER = 0xC9;
|
static int FILE_TYPE_PAL = 0xC3;
|
||||||
static int FILE_TYPE_ICN = 0xCA;
|
static int FILE_TYPE_FONT = 0xC8;
|
||||||
static int FILE_TYPE_APPLETALK = 0xE2;
|
static int FILE_TYPE_FINDER = 0xC9;
|
||||||
static int FILE_TYPE_PASCAL_VOLUME = 0xEF;
|
static int FILE_TYPE_ICN = 0xCA;
|
||||||
static int FILE_TYPE_USER_DEFINED_1 = 0xF1; // OVL
|
static int FILE_TYPE_APPLETALK = 0xE2;
|
||||||
static int FILE_TYPE_BAT = 0xF5;
|
static int FILE_TYPE_PASCAL_VOLUME = 0xEF;
|
||||||
static int FILE_TYPE_INTEGER_BASIC = 0xFA;
|
static int FILE_TYPE_USER_DEFINED_1 = 0xF1; // OVL
|
||||||
static int FILE_TYPE_INTEGER_BASIC_VARS = 0xFB;
|
static int FILE_TYPE_BAT = 0xF5;
|
||||||
static int FILE_TYPE_APPLESOFT_BASIC = 0xFC;
|
static int FILE_TYPE_INTEGER_BASIC = 0xFA;
|
||||||
static int FILE_TYPE_APPLESOFT_BASIC_VARS = 0xFD;
|
static int FILE_TYPE_INTEGER_BASIC_VARS = 0xFB;
|
||||||
static int FILE_TYPE_RELOCATABLE = 0xFE;
|
static int FILE_TYPE_APPLESOFT_BASIC = 0xFC;
|
||||||
static int FILE_TYPE_SYS = 0xFF;
|
static int FILE_TYPE_APPLESOFT_BASIC_VARS = 0xFD;
|
||||||
|
static int FILE_TYPE_RELOCATABLE = 0xFE;
|
||||||
static int VOLUME_HEADER = 15;
|
static int FILE_TYPE_SYS = 0xFF;
|
||||||
static int SUBDIRECTORY_HEADER = 14;
|
|
||||||
static int SUBDIRECTORY = 13;
|
static int VOLUME_HEADER = 15;
|
||||||
static int GSOS_EXTENDED_FILE = 5; // tech note #25
|
static int SUBDIRECTORY_HEADER = 14;
|
||||||
static int PASCAL_ON_PROFILE = 4; // tech note #25
|
static int SUBDIRECTORY = 13;
|
||||||
static int TREE = 3;
|
static int GSOS_EXTENDED_FILE = 5; // tech note #25
|
||||||
static int SAPLING = 2;
|
static int PASCAL_ON_PROFILE = 4; // tech note #25
|
||||||
static int SEEDLING = 1;
|
static int TREE = 3;
|
||||||
static int FREE = 0;
|
static int SAPLING = 2;
|
||||||
|
static int SEEDLING = 1;
|
||||||
static String[] fileTypes = { //
|
static int FREE = 0;
|
||||||
"NON", "BAD", "PCD", "PTX", "TXT", "PDA", "BIN", "FNT", //
|
|
||||||
"FOT", "BA3", "DA3", "WPF", "SOS", "$0D", "$0E", "DIR", //
|
static String[] fileTypes = { //
|
||||||
"RPD", "RPI", "AFD", "AFM", "AFR", "SCL", "PFS", "$17", //
|
"NON", "BAD", "PCD", "PTX", "TXT", "PDA", "BIN", "FNT", //
|
||||||
"$18", "ADB", "AWP", "ASP", "$1C", "$1D", "$1E", "$1F", //
|
"FOT", "BA3", "DA3", "WPF", "SOS", "$0D", "$0E", "DIR", //
|
||||||
"TDM", "$21", "$22", "$23", "$24", "$25", "$26", "$27", //
|
"RPD", "RPI", "AFD", "AFM", "AFR", "SCL", "PFS", "$17", //
|
||||||
"$28", "$29", "8SC", "8OB", "8IC", "8LD", "P8C", "$2F", //
|
"$18", "ADB", "AWP", "ASP", "$1C", "$1D", "$1E", "$1F", //
|
||||||
"$30", "$31", "$32", "$33", "$34", "$35", "$36", "$37", //
|
"TDM", "$21", "$22", "$23", "$24", "$25", "$26", "$27", //
|
||||||
"$38", "$39", "$3A", "$3B", "$3C", "$3D", "$3E", "$3F", //
|
"$28", "$29", "8SC", "8OB", "8IC", "8LD", "P8C", "$2F", //
|
||||||
"DIC", "OCR", "FTD", "$43", "$44", "$45", "$46", "$47", //
|
"$30", "$31", "$32", "$33", "$34", "$35", "$36", "$37", //
|
||||||
"$48", "$49", "$4A", "$4B", "$4C", "$4D", "$4E", "$4F", //
|
"$38", "$39", "$3A", "$3B", "$3C", "$3D", "$3E", "$3F", //
|
||||||
"GWP", "GSS", "GDB", "DRW", "GDP", "HMD", "EDU", "STN", //
|
"DIC", "OCR", "FTD", "$43", "$44", "$45", "$46", "$47", //
|
||||||
"HLP", "COM", "CFG", "ANM", "MUM", "ENT", "DVU", "FIN", //
|
"$48", "$49", "$4A", "$4B", "$4C", "$4D", "$4E", "$4F", //
|
||||||
"$60", "$61", "$62", "$63", "$64", "$65", "$66", "$67", //
|
"GWP", "GSS", "GDB", "DRW", "GDP", "HMD", "EDU", "STN", //
|
||||||
"$68", "$69", "$6A", "BIO", "$6C", "TDR", "PRE", "HDV", //
|
"HLP", "COM", "CFG", "ANM", "MUM", "ENT", "DVU", "FIN", //
|
||||||
"$70", "$71", "$72", "$73", "$74", "$75", "$76", "$77", //
|
"$60", "$61", "$62", "$63", "$64", "$65", "$66", "$67", //
|
||||||
"$78", "$79", "$7A", "$7B", "$7C", "$7D", "$7E", "$7F", //
|
"$68", "$69", "$6A", "BIO", "$6C", "TDR", "PRE", "HDV", //
|
||||||
"GES", "GEA", "GEO", "GED", "GEF", "GEP", "GEI", "GEX", //
|
"$70", "$71", "$72", "$73", "$74", "$75", "$76", "$77", //
|
||||||
"$88", "GEV", "$8A", "GEC", "GEK", "GEW", "$8E", "$8F", //
|
"$78", "$79", "$7A", "$7B", "$7C", "$7D", "$7E", "$7F", //
|
||||||
"$90", "$91", "$92", "$93", "$94", "$95", "$96", "$97", //
|
"GES", "GEA", "GEO", "GED", "GEF", "GEP", "GEI", "GEX", //
|
||||||
"$98", "$99", "$9A", "$9B", "$9C", "$9D", "$9E", "$9F", //
|
"$88", "GEV", "$8A", "GEC", "GEK", "GEW", "$8E", "$8F", //
|
||||||
"WP ", "$A1", "$A2", "$A3", "$A4", "$A5", "$A6", "$A7", //
|
"$90", "$91", "$92", "$93", "$94", "$95", "$96", "$97", //
|
||||||
"$A8", "$A9", "$AA", "GSB", "TDF", "BDF", "$AE", "$AF", //
|
"$98", "$99", "$9A", "$9B", "$9C", "$9D", "$9E", "$9F", //
|
||||||
"SRC", "OBJ", "LIB", "S16", "RTL", "EXE", "PIF", "TIF", //
|
"WP ", "$A1", "$A2", "$A3", "$A4", "$A5", "$A6", "$A7", //
|
||||||
"NDA", "CDA", "TOL", "DVR", "LDF", "FST", "$BE", "DOC", //
|
"$A8", "$A9", "$AA", "GSB", "TDF", "BDF", "$AE", "$AF", //
|
||||||
"PNT", "PIC", "ANI", "PAL", "$C4", "OOG", "SCR", "CDV", //
|
"SRC", "OBJ", "LIB", "S16", "RTL", "EXE", "PIF", "TIF", //
|
||||||
"FON", "FND", "ICN", "$CB", "$CC", "$CD", "$CE", "$CF", //
|
"NDA", "CDA", "TOL", "DVR", "LDF", "FST", "$BE", "DOC", //
|
||||||
"$D0", "$D1", "$D2", "$D3", "$D4", "MUS", "INS", "MDI", //
|
"PNT", "PIC", "ANI", "PAL", "$C4", "OOG", "SCR", "CDV", //
|
||||||
"SND", "$D9", "$DA", "DBM", "$DC", "DDD", "$DE", "$DF", //
|
"FON", "FND", "ICN", "$CB", "$CC", "$CD", "$CE", "$CF", //
|
||||||
"LBR", "$E1", "ATK", "$E3", "$E4", "$E5", "$E6", "$E7", //
|
"$D0", "$D1", "$D2", "$D3", "$D4", "MUS", "INS", "MDI", //
|
||||||
"$E8", "$E9", "$EA", "$EB", "$EC", "$ED", "R16", "PAR", //
|
"SND", "$D9", "$DA", "DBM", "$DC", "DDD", "$DE", "$DF", //
|
||||||
"CMD", "OVL", "UD2", "UD3", "UD4", "BAT", "UD6", "UD7", //
|
"LBR", "$E1", "ATK", "$E3", "$E4", "$E5", "$E6", "$E7", //
|
||||||
"PRG", "P16", "INT", "IVR", "BAS", "VAR", "REL", "SYS" };
|
"$E8", "$E9", "$EA", "$EB", "$EC", "$ED", "R16", "PAR", //
|
||||||
|
"CMD", "OVL", "UD2", "UD3", "UD4", "BAT", "UD6", "UD7", //
|
||||||
static int ENTRY_SIZE = 39;
|
"PRG", "P16", "INT", "IVR", "BAS", "VAR", "REL", "SYS" };
|
||||||
static int ENTRIES_PER_BLOCK = 13;
|
|
||||||
static int BLOCK_ENTRY_SIZE = ENTRY_SIZE * ENTRIES_PER_BLOCK;
|
static int ENTRY_SIZE = 39;
|
||||||
}
|
static int ENTRIES_PER_BLOCK = 13;
|
||||||
|
static int BLOCK_ENTRY_SIZE = ENTRY_SIZE * ENTRIES_PER_BLOCK;
|
||||||
/* http://www.kreativekorp.com/miscpages/a2info/filetypes.shtml
|
}
|
||||||
*
|
|
||||||
* $00 UNK Unknown
|
/* http://www.kreativekorp.com/miscpages/a2info/filetypes.shtml
|
||||||
* $01 BAD Bad Block File
|
*
|
||||||
* $02 PCD Pascal Code
|
* $00 UNK Unknown
|
||||||
* $03 PTX Pascal Text
|
* $01 BAD Bad Block File
|
||||||
* $04 TXT ASCII Text
|
* $02 PCD Pascal Code
|
||||||
* $05 PDA Pascal Data
|
* $03 PTX Pascal Text
|
||||||
* $06 BIN Binary File
|
* $04 TXT ASCII Text
|
||||||
* $07 FNT Apple III Font
|
* $05 PDA Pascal Data
|
||||||
* $08 FOT HiRes/Double HiRes File
|
* $06 BIN Binary File
|
||||||
* $09 BA3 Apple III BASIC Program
|
* $07 FNT Apple III Font
|
||||||
* $0A DA3 Apple III BASIC Data
|
* $08 FOT HiRes/Double HiRes File
|
||||||
* $0B WPF Generic Word Processor File
|
* $09 BA3 Apple III BASIC Program
|
||||||
* $0C SOS SOS System File
|
* $0A DA3 Apple III BASIC Data
|
||||||
* $0F DIR ProDOS Directory
|
* $0B WPF Generic Word Processor File
|
||||||
* $10 RPD RPS Data
|
* $0C SOS SOS System File
|
||||||
* $11 RPI RPS Index
|
* $0F DIR ProDOS Directory
|
||||||
* $12 AFD AppleFile Discard
|
* $10 RPD RPS Data
|
||||||
* $13 AFM AppleFile Model
|
* $11 RPI RPS Index
|
||||||
* $14 AFR AppleFile Report
|
* $12 AFD AppleFile Discard
|
||||||
* $15 SCL Screen Library
|
* $13 AFM AppleFile Model
|
||||||
* $16 PFS PFS Document
|
* $14 AFR AppleFile Report
|
||||||
* $19 ADB AppleWorks Database
|
* $15 SCL Screen Library
|
||||||
* $1A AWP AppleWorks Word Processor
|
* $16 PFS PFS Document
|
||||||
* $1B ASP AppleWorks Spreadsheet
|
* $19 ADB AppleWorks Database
|
||||||
* $20 TDM Desktop Manager File
|
* $1A AWP AppleWorks Word Processor
|
||||||
* $21 IPS Instant Pascal Source
|
* $1B ASP AppleWorks Spreadsheet
|
||||||
* $22 UPV UCSD Pascal Volume
|
* $20 TDM Desktop Manager File
|
||||||
* $29 3SD SOS Directory
|
* $21 IPS Instant Pascal Source
|
||||||
* $2A 8SC Source Code
|
* $22 UPV UCSD Pascal Volume
|
||||||
* $2B 8OB Object Code
|
* $29 3SD SOS Directory
|
||||||
* $2C 8IC Interpretted Code
|
* $2A 8SC Source Code
|
||||||
* $2D 8LD Language Data
|
* $2B 8OB Object Code
|
||||||
* $2E P8C ProDOS 8 Code Module
|
* $2C 8IC Interpretted Code
|
||||||
* $41 OCR Optical Character Recognition File
|
* $2D 8LD Language Data
|
||||||
* $50 GWP Apple IIgs Word Processor File
|
* $2E P8C ProDOS 8 Code Module
|
||||||
* $51 GSS Apple IIgs Spreadsheet File
|
* $41 OCR Optical Character Recognition File
|
||||||
* $52 GDB Apple IIgs Database File
|
* $50 GWP Apple IIgs Word Processor File
|
||||||
* $53 DRW Object Oriented Graphics File
|
* $51 GSS Apple IIgs Spreadsheet File
|
||||||
* $54 GDP Apple IIgs Desktop Publishing File
|
* $52 GDB Apple IIgs Database File
|
||||||
* $55 HMD HyperMedia
|
* $53 DRW Object Oriented Graphics File
|
||||||
* $56 EDU Educational Program Data
|
* $54 GDP Apple IIgs Desktop Publishing File
|
||||||
* $57 STN Stationery
|
* $55 HMD HyperMedia
|
||||||
* $58 HLP Help File
|
* $56 EDU Educational Program Data
|
||||||
* $59 COM Communications File
|
* $57 STN Stationery
|
||||||
* $5A CFG Configuration File
|
* $58 HLP Help File
|
||||||
* $5B ANM Animation File
|
* $59 COM Communications File
|
||||||
* $5C MUM Multimedia File
|
* $5A CFG Configuration File
|
||||||
* $5D ENT Entertainment Program File
|
* $5B ANM Animation File
|
||||||
* $5E DVU Development Utility File
|
* $5C MUM Multimedia File
|
||||||
* $60 PRE PC Pre-Boot
|
* $5D ENT Entertainment Program File
|
||||||
* $6B BIO PC BIOS
|
* $5E DVU Development Utility File
|
||||||
* $6D DVR PC Driver
|
* $60 PRE PC Pre-Boot
|
||||||
* $6E PRE PC Pre-Boot
|
* $6B BIO PC BIOS
|
||||||
* $6F HDV PC Hard Disk Image
|
* $6D DVR PC Driver
|
||||||
* $77 KES KES Software
|
* $6E PRE PC Pre-Boot
|
||||||
* $7B TLB KES Software
|
* $6F HDV PC Hard Disk Image
|
||||||
* $7F JCP KES Software
|
* $77 KES KES Software
|
||||||
* $80 GeOS System File
|
* $7B TLB KES Software
|
||||||
* $81 GeOS Desk Accessory
|
* $7F JCP KES Software
|
||||||
* $82 GeOS Application
|
* $80 GeOS System File
|
||||||
* $83 GeOS Document
|
* $81 GeOS Desk Accessory
|
||||||
* $84 GeOS Font
|
* $82 GeOS Application
|
||||||
* $85 GeOS Printer Driver
|
* $83 GeOS Document
|
||||||
* $86 GeOS Input Driver
|
* $84 GeOS Font
|
||||||
* $87 GeOS Auxilary Driver
|
* $85 GeOS Printer Driver
|
||||||
* $8B GeOS Clock Driver
|
* $86 GeOS Input Driver
|
||||||
* $8C GeOS Interface Card Driver
|
* $87 GeOS Auxilary Driver
|
||||||
* $8D GeOS Formatting Data
|
* $8B GeOS Clock Driver
|
||||||
* $A0 WP WordPerfect File
|
* $8C GeOS Interface Card Driver
|
||||||
* $A6
|
* $8D GeOS Formatting Data
|
||||||
* $AB GSB Apple IIgs BASIC Program
|
* $A0 WP WordPerfect File
|
||||||
* $AC TDF Apple IIgs BASIC TDF
|
* $A6
|
||||||
* $AD BDF Apple IIgs BASIC Data
|
* $AB GSB Apple IIgs BASIC Program
|
||||||
* $B0 SRC Apple IIgs Source Code
|
* $AC TDF Apple IIgs BASIC TDF
|
||||||
* $B1 OBJ Apple IIgs Object Code
|
* $AD BDF Apple IIgs BASIC Data
|
||||||
* $B2 LIB Apple IIgs Library
|
* $B0 SRC Apple IIgs Source Code
|
||||||
* $B3 S16 Apple IIgs Application Program
|
* $B1 OBJ Apple IIgs Object Code
|
||||||
* $B4 RTL Apple IIgs Runtime Library
|
* $B2 LIB Apple IIgs Library
|
||||||
* $B5 EXE Apple IIgs Shell
|
* $B3 S16 Apple IIgs Application Program
|
||||||
* $B6 PIF Apple IIgs Permanent INIT
|
* $B4 RTL Apple IIgs Runtime Library
|
||||||
* $B7 TIF Apple IIgs Temporary INIT
|
* $B5 EXE Apple IIgs Shell
|
||||||
* $B8 NDA Apple IIgs New Desk Accessory
|
* $B6 PIF Apple IIgs Permanent INIT
|
||||||
* $B9 CDA Apple IIgs Classic Desk Accessory
|
* $B7 TIF Apple IIgs Temporary INIT
|
||||||
* $BA TOL Apple IIgs Tool
|
* $B8 NDA Apple IIgs New Desk Accessory
|
||||||
* $BB DRV Apple IIgs Device Driver
|
* $B9 CDA Apple IIgs Classic Desk Accessory
|
||||||
* $BC LDF Apple IIgs Generic Load File
|
* $BA TOL Apple IIgs Tool
|
||||||
* $BD FST Apple IIgs File System Translator
|
* $BB DRV Apple IIgs Device Driver
|
||||||
* $BF DOC Apple IIgs Document
|
* $BC LDF Apple IIgs Generic Load File
|
||||||
* $C0 PNT Apple IIgs Packed Super HiRes
|
* $BD FST Apple IIgs File System Translator
|
||||||
* $C1 PIC Apple IIgs Super HiRes
|
* $BF DOC Apple IIgs Document
|
||||||
* $C2 ANI PaintWorks Animation
|
* $C0 PNT Apple IIgs Packed Super HiRes
|
||||||
* $C3 PAL PaintWorks Palette
|
* $C1 PIC Apple IIgs Super HiRes
|
||||||
* $C5 OOG Object-Oriented Graphics
|
* $C2 ANI PaintWorks Animation
|
||||||
* $C6 SCR Script
|
* $C3 PAL PaintWorks Palette
|
||||||
* $C7 CDV Apple IIgs Control Panel
|
* $C5 OOG Object-Oriented Graphics
|
||||||
* $C8 FON Apple IIgs Font
|
* $C6 SCR Script
|
||||||
* $C9 FND Apple IIgs Finder Data
|
* $C7 CDV Apple IIgs Control Panel
|
||||||
* $CA ICN Apple IIgs Icon File
|
* $C8 FON Apple IIgs Font
|
||||||
* $D5 MUS Music File
|
* $C9 FND Apple IIgs Finder Data
|
||||||
* $D6 INS Instrument File
|
* $CA ICN Apple IIgs Icon File
|
||||||
* $D7 MDI MIDI File
|
* $D5 MUS Music File
|
||||||
* $D8 SND Apple IIgs Sound File
|
* $D6 INS Instrument File
|
||||||
* $DB DBM DB Master Document
|
* $D7 MDI MIDI File
|
||||||
* $E0 LBR Archive File
|
* $D8 SND Apple IIgs Sound File
|
||||||
* $E2 ATK AppleTalk Data
|
* $DB DBM DB Master Document
|
||||||
* $EE R16 EDASM 816 Relocatable Code
|
* $E0 LBR Archive File
|
||||||
* $EF PAR Pascal Area
|
* $E2 ATK AppleTalk Data
|
||||||
* $F0 CMD ProDOS Command File
|
* $EE R16 EDASM 816 Relocatable Code
|
||||||
* $F1 OVL User Defined 1
|
* $EF PAR Pascal Area
|
||||||
* $F2 User Defined 2
|
* $F0 CMD ProDOS Command File
|
||||||
* $F3 User Defined 3
|
* $F1 OVL User Defined 1
|
||||||
* $F4 User Defined 4
|
* $F2 User Defined 2
|
||||||
* $F5 BAT User Defined 5
|
* $F3 User Defined 3
|
||||||
* $F6 User Defined 6
|
* $F4 User Defined 4
|
||||||
* $F7 User Defined 7
|
* $F5 BAT User Defined 5
|
||||||
* $F8 PRG User Defined 8
|
* $F6 User Defined 6
|
||||||
* $F9 P16 Apple IIgs System File
|
* $F7 User Defined 7
|
||||||
* $FA INT Integer BASIC Program
|
* $F8 PRG User Defined 8
|
||||||
* $FB IVR Integer BASIC Variables
|
* $F9 P16 Apple IIgs System File
|
||||||
* $FC BAS Applesoft BASIC Program
|
* $FA INT Integer BASIC Program
|
||||||
* $FD VAR Applesoft BASIC Variables
|
* $FB IVR Integer BASIC Variables
|
||||||
* $FE REL EDASM Relocatable Code
|
* $FC BAS Applesoft BASIC Program
|
||||||
* $FF SYS ProDOS System File
|
* $FD VAR Applesoft BASIC Variables
|
||||||
*/
|
* $FE REL EDASM Relocatable Code
|
||||||
|
* $FF SYS ProDOS System File
|
||||||
// See also http://www.kreativekorp.com/miscpages/a2info/filetypes.shtml
|
*/
|
||||||
|
|
||||||
/*
|
// See also http://www.kreativekorp.com/miscpages/a2info/filetypes.shtml
|
||||||
* https://groups.google.com/forum/#!topic/comp.sys.apple2/waoYCIbkJKs
|
|
||||||
*
|
/*
|
||||||
* There are a number of disk utilities available that store images of disks that
|
* https://groups.google.com/forum/#!topic/comp.sys.apple2/waoYCIbkJKs
|
||||||
* utilize file systems that are not ProDOS, at the end of a ProDOS volume.
|
*
|
||||||
* There's DOS Master, by Glen Bredon, that stores images of DOS 3.3 disks at the
|
* There are a number of disk utilities available that store images of disks that
|
||||||
* end of a ProDOS volume. Similarly, Pro/Part, by Steven Hirsch, stores images
|
* utilize file systems that are not ProDOS, at the end of a ProDOS volume.
|
||||||
* of CP/M volumes. Also, there's Pascal Partition Manager (PPM) that stores
|
* There's DOS Master, by Glen Bredon, that stores images of DOS 3.3 disks at the
|
||||||
* images of UCSD Pascal volumes. I've decided to refer to the area used to store
|
* end of a ProDOS volume. Similarly, Pro/Part, by Steven Hirsch, stores images
|
||||||
* volume images, by all three of these systems, as a Foreign Volume Area or FVA.
|
* of CP/M volumes. Also, there's Pascal Partition Manager (PPM) that stores
|
||||||
* All three of these systems modify the Block Allocation Map of a ProDOS volume
|
* images of UCSD Pascal volumes. I've decided to refer to the area used to store
|
||||||
* to keep ProDOS from assigning blocks used by FVAs for use by files being
|
* volume images, by all three of these systems, as a Foreign Volume Area or FVA.
|
||||||
* written by ProDOS. Pascal Partition Manager is different from the other two
|
* All three of these systems modify the Block Allocation Map of a ProDOS volume
|
||||||
* in that it has a file type ($EF) and file kind (4) assigned to it by Apple.
|
* to keep ProDOS from assigning blocks used by FVAs for use by files being
|
||||||
* A directory listing of a ProODS volume containing an FVA managed by PPM will
|
* written by ProDOS. Pascal Partition Manager is different from the other two
|
||||||
* show a file name of "PASCAL.AREA". A directory listing of a ProDOS volume
|
* in that it has a file type ($EF) and file kind (4) assigned to it by Apple.
|
||||||
* containing an FVA managed by DOS Master or Pro/Part will show absolutely nothing.
|
* A directory listing of a ProODS volume containing an FVA managed by PPM will
|
||||||
* Running a popular utility named "MR.FIXIT", also by Glen Bredon, against a
|
* show a file name of "PASCAL.AREA". A directory listing of a ProDOS volume
|
||||||
* ProDOS volume containing an FVA will report an error. Specifically, "MR.FIXIT"
|
* containing an FVA managed by DOS Master or Pro/Part will show absolutely nothing.
|
||||||
* will complain that all the blocks used by an FVA as allocated but not in use.
|
* Running a popular utility named "MR.FIXIT", also by Glen Bredon, against a
|
||||||
* To solve this problem for Pro/Part I wrote a Foreign Volume Area utility
|
* ProDOS volume containing an FVA will report an error. Specifically, "MR.FIXIT"
|
||||||
* program that generates a directory entry for the Pro/Part area. That entry has
|
* will complain that all the blocks used by an FVA as allocated but not in use.
|
||||||
* file kind 4, file type $EF, file name "PROPART.AREA" and an auxiliary file
|
* To solve this problem for Pro/Part I wrote a Foreign Volume Area utility
|
||||||
* type $4853 (Steven Hirsch's initials). Today I realized that it's likely that
|
* program that generates a directory entry for the Pro/Part area. That entry has
|
||||||
* the same thing could be done for DOS Master. Study of the source code for
|
* file kind 4, file type $EF, file name "PROPART.AREA" and an auxiliary file
|
||||||
* DOS Master will reveal it that's true. If it is, I propose that "DOS33.AREA"
|
* type $4853 (Steven Hirsch's initials). Today I realized that it's likely that
|
||||||
* be used as the file name and $4247 as the auxiliary type (Glen Bredon's initials).
|
* the same thing could be done for DOS Master. Study of the source code for
|
||||||
* As I compose the text of this message I realize that another solution is to
|
* DOS Master will reveal it that's true. If it is, I propose that "DOS33.AREA"
|
||||||
* modify "MR.FIXIT" to be aware of FVAs. But doing that would not allow someone
|
* be used as the file name and $4247 as the auxiliary type (Glen Bredon's initials).
|
||||||
* doing a directory listing of a ProDOS volume containing an FVA to be aware
|
* As I compose the text of this message I realize that another solution is to
|
||||||
* that the FVA exists.
|
* modify "MR.FIXIT" to be aware of FVAs. But doing that would not allow someone
|
||||||
|
* doing a directory listing of a ProDOS volume containing an FVA to be aware
|
||||||
|
* that the FVA exists.
|
||||||
*/
|
*/
|
|
@ -1,145 +1,145 @@
|
||||||
package com.bytezone.diskbrowser.prodos;
|
package com.bytezone.diskbrowser.prodos;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||||
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
||||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
class ProdosDirectory extends AbstractFile implements ProdosConstants
|
class ProdosDirectory extends AbstractFile implements ProdosConstants
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
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 newLine = String.format ("%n");
|
||||||
private static final String newLine2 = newLine + newLine;
|
private static final String newLine2 = newLine + newLine;
|
||||||
private static final SimpleDateFormat sdf = new SimpleDateFormat ("d-MMM-yy");
|
private static final SimpleDateFormat sdf = new SimpleDateFormat ("d-MMM-yy");
|
||||||
private static final SimpleDateFormat stf = new SimpleDateFormat ("H:mm");
|
private static final SimpleDateFormat stf = new SimpleDateFormat ("H:mm");
|
||||||
|
|
||||||
private final ProdosDisk parentFD;
|
private final ProdosDisk parentFD;
|
||||||
private final int totalBlocks;
|
private final int totalBlocks;
|
||||||
private final int freeBlocks;
|
private final int freeBlocks;
|
||||||
private final int usedBlocks;
|
private final int usedBlocks;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
public ProdosDirectory (FormattedDisk parent, String name, byte[] buffer,
|
ProdosDirectory (FormattedDisk parent, String name, byte[] buffer, int totalBlocks,
|
||||||
int totalBlocks, int freeBlocks, int usedBlocks)
|
int freeBlocks, int usedBlocks)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
super (name, buffer);
|
super (name, buffer);
|
||||||
|
|
||||||
this.parentFD = (ProdosDisk) parent;
|
this.parentFD = (ProdosDisk) parent;
|
||||||
this.totalBlocks = totalBlocks;
|
this.totalBlocks = totalBlocks;
|
||||||
this.freeBlocks = freeBlocks;
|
this.freeBlocks = freeBlocks;
|
||||||
this.usedBlocks = usedBlocks;
|
this.usedBlocks = usedBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
@Override
|
||||||
public String getText ()
|
public String getText ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
StringBuffer text = new StringBuffer ();
|
StringBuffer text = new StringBuffer ();
|
||||||
text.append ("Disk : " + parentFD.getDisplayPath () + newLine2);
|
text.append ("Disk : " + parentFD.getDisplayPath () + newLine2);
|
||||||
for (int i = 0; i < buffer.length; i += 39)
|
for (int i = 0; i < buffer.length; i += 39)
|
||||||
{
|
{
|
||||||
int storageType = (buffer[i] & 0xF0) >> 4;
|
int storageType = (buffer[i] & 0xF0) >> 4;
|
||||||
if (storageType == 0)
|
if (storageType == 0)
|
||||||
continue; // break??
|
continue; // break??
|
||||||
|
|
||||||
int nameLength = buffer[i] & 0x0F;
|
int nameLength = buffer[i] & 0x0F;
|
||||||
String filename = HexFormatter.getString (buffer, i + 1, nameLength);
|
String filename = HexFormatter.getString (buffer, i + 1, nameLength);
|
||||||
String subType = "";
|
String subType = "";
|
||||||
String locked;
|
String locked;
|
||||||
|
|
||||||
switch (storageType)
|
switch (storageType)
|
||||||
{
|
{
|
||||||
case ProdosConstants.VOLUME_HEADER:
|
case ProdosConstants.VOLUME_HEADER:
|
||||||
case ProdosConstants.SUBDIRECTORY_HEADER:
|
case ProdosConstants.SUBDIRECTORY_HEADER:
|
||||||
text.append ("/" + filename + newLine2);
|
text.append ("/" + filename + newLine2);
|
||||||
text.append (" NAME TYPE BLOCKS "
|
text.append (" NAME TYPE BLOCKS "
|
||||||
+ "MODIFIED CREATED ENDFILE SUBTYPE" + newLine2);
|
+ "MODIFIED CREATED ENDFILE SUBTYPE" + newLine2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ProdosConstants.FREE:
|
case ProdosConstants.FREE:
|
||||||
case ProdosConstants.SEEDLING:
|
case ProdosConstants.SEEDLING:
|
||||||
case ProdosConstants.SAPLING:
|
case ProdosConstants.SAPLING:
|
||||||
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:
|
||||||
case ProdosConstants.SUBDIRECTORY:
|
case ProdosConstants.SUBDIRECTORY:
|
||||||
int type = buffer[i + 16] & 0xFF;
|
int type = buffer[i + 16] & 0xFF;
|
||||||
int blocks = HexFormatter.intValue (buffer[i + 19], buffer[i + 20]);
|
int blocks = HexFormatter.intValue (buffer[i + 19], buffer[i + 20]);
|
||||||
|
|
||||||
GregorianCalendar created = HexFormatter.getAppleDate (buffer, i + 24);
|
GregorianCalendar created = HexFormatter.getAppleDate (buffer, i + 24);
|
||||||
String dateC = created == null ? NO_DATE
|
String dateC = created == null ? NO_DATE
|
||||||
: sdf.format (created.getTime ()).toUpperCase ().replace (".", "");
|
: sdf.format (created.getTime ()).toUpperCase ().replace (".", "");
|
||||||
String timeC = created == null ? "" : stf.format (created.getTime ());
|
String timeC = created == null ? "" : stf.format (created.getTime ());
|
||||||
GregorianCalendar modified = HexFormatter.getAppleDate (buffer, i + 33);
|
GregorianCalendar modified = HexFormatter.getAppleDate (buffer, i + 33);
|
||||||
String dateM = modified == null ? NO_DATE
|
String dateM = modified == null ? NO_DATE
|
||||||
: sdf.format (modified.getTime ()).toUpperCase ().replace (".", "");
|
: sdf.format (modified.getTime ()).toUpperCase ().replace (".", "");
|
||||||
String timeM = modified == null ? "" : stf.format (modified.getTime ());
|
String timeM = modified == null ? "" : stf.format (modified.getTime ());
|
||||||
int eof =
|
int eof =
|
||||||
HexFormatter.intValue (buffer[i + 21], buffer[i + 22], buffer[i + 23]);
|
HexFormatter.intValue (buffer[i + 21], buffer[i + 22], buffer[i + 23]);
|
||||||
int fileType = buffer[i + 16] & 0xFF;
|
int fileType = buffer[i + 16] & 0xFF;
|
||||||
locked = (buffer[i + 30] & 0xE0) == 0xE0 ? " " : "*";
|
locked = (buffer[i + 30] & 0xE0) == 0xE0 ? " " : "*";
|
||||||
|
|
||||||
switch (fileType)
|
switch (fileType)
|
||||||
{
|
{
|
||||||
case FILE_TYPE_TEXT:
|
case FILE_TYPE_TEXT:
|
||||||
int aux = HexFormatter.intValue (buffer[i + 31], buffer[i + 32]);
|
int aux = HexFormatter.intValue (buffer[i + 31], buffer[i + 32]);
|
||||||
subType = String.format ("R=%5d", aux);
|
subType = String.format ("R=%5d", aux);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FILE_TYPE_BINARY:
|
case FILE_TYPE_BINARY:
|
||||||
case FILE_TYPE_PNT:
|
case FILE_TYPE_PNT:
|
||||||
case FILE_TYPE_PIC:
|
case FILE_TYPE_PIC:
|
||||||
case FILE_TYPE_FOT:
|
case FILE_TYPE_FOT:
|
||||||
aux = HexFormatter.intValue (buffer[i + 31], buffer[i + 32]);
|
aux = HexFormatter.intValue (buffer[i + 31], buffer[i + 32]);
|
||||||
subType = String.format ("A=$%4X", aux);
|
subType = String.format ("A=$%4X", aux);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FILE_TYPE_AWP:
|
case FILE_TYPE_AWP:
|
||||||
aux = HexFormatter.intValue (buffer[i + 32], buffer[i + 31]); // backwards!
|
aux = HexFormatter.intValue (buffer[i + 32], buffer[i + 31]); // backwards!
|
||||||
if (aux != 0)
|
if (aux != 0)
|
||||||
filename = convert (filename, aux);
|
filename = convert (filename, aux);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
subType = "";
|
subType = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
text.append (String.format ("%s%-15s %3s %5d %9s %5s %9s %5s %8d %7s%n",
|
text.append (String.format ("%s%-15s %3s %5d %9s %5s %9s %5s %8d %7s%n",
|
||||||
locked, filename, ProdosConstants.fileTypes[type], blocks, dateM, timeM,
|
locked, filename, ProdosConstants.fileTypes[type], blocks, dateM, timeM,
|
||||||
dateC, timeC, eof, subType));
|
dateC, timeC, eof, subType));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
text.append (" <Unknown strage type : " + storageType + newLine);
|
text.append (" <Unknown strage type : " + storageType + newLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 ();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
private String convert (String name, int flags)
|
private String convert (String name, int flags)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
char[] newName = name.toCharArray ();
|
char[] newName = name.toCharArray ();
|
||||||
for (int i = 0, weight = 0x8000; i < newName.length; i++, weight >>>= 1)
|
for (int i = 0, weight = 0x8000; i < newName.length; i++, weight >>>= 1)
|
||||||
{
|
{
|
||||||
if ((flags & weight) != 0)
|
if ((flags & weight) != 0)
|
||||||
{
|
{
|
||||||
if (newName[i] == '.')
|
if (newName[i] == '.')
|
||||||
newName[i] = ' ';
|
newName[i] = ' ';
|
||||||
else if (newName[i] >= 'A' && newName[i] <= 'Z')
|
else if (newName[i] >= 'A' && newName[i] <= 'Z')
|
||||||
newName[i] += 32;
|
newName[i] += 32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new String (newName);
|
return new String (newName);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,59 +1,67 @@
|
||||||
package com.bytezone.diskbrowser.prodos;
|
package com.bytezone.diskbrowser.prodos;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.disk.AbstractSector;
|
import com.bytezone.diskbrowser.disk.AbstractSector;
|
||||||
import com.bytezone.diskbrowser.disk.Disk;
|
import com.bytezone.diskbrowser.disk.Disk;
|
||||||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||||
|
|
||||||
// see Prodos 8 Tech note #25
|
// see Prodos 8 Tech note #25
|
||||||
class ProdosExtendedKeySector extends AbstractSector
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
class ProdosExtendedKeySector extends AbstractSector
|
||||||
public ProdosExtendedKeySector (Disk disk, byte[] buffer, DiskAddress diskAddress)
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
super (disk, buffer, diskAddress);
|
// ---------------------------------------------------------------------------------//
|
||||||
}
|
ProdosExtendedKeySector (Disk disk, byte[] buffer, DiskAddress diskAddress)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
@Override
|
{
|
||||||
public String createText ()
|
super (disk, buffer, diskAddress);
|
||||||
{
|
}
|
||||||
StringBuilder text = getHeader ("Prodos Extended Key Block");
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
for (int i = 0; i < 512; i += 256)
|
@Override
|
||||||
{
|
public String createText ()
|
||||||
String type = i == 0 ? "Data" : "Resource";
|
// ---------------------------------------------------------------------------------//
|
||||||
addText (text, buffer, i, 1,
|
{
|
||||||
type + " fork storage type (" + getType (buffer[i]) + ")");
|
StringBuilder text = getHeader ("Prodos Extended Key Block");
|
||||||
addTextAndDecimal (text, buffer, i + 1, 2, "Key block");
|
|
||||||
addTextAndDecimal (text, buffer, i + 3, 2, "Blocks used");
|
for (int i = 0; i < 512; i += 256)
|
||||||
addTextAndDecimal (text, buffer, i + 5, 3, "EOF");
|
{
|
||||||
text.append ("\n");
|
String type = i == 0 ? "Data" : "Resource";
|
||||||
|
addText (text, buffer, i, 1,
|
||||||
// check for Finder Info records
|
type + " fork storage type (" + getType (buffer[i]) + ")");
|
||||||
if (i == 0 && buffer[8] != 0)
|
addTextAndDecimal (text, buffer, i + 1, 2, "Key block");
|
||||||
{
|
addTextAndDecimal (text, buffer, i + 3, 2, "Blocks used");
|
||||||
for (int j = 0; j <= 18; j += 18)
|
addTextAndDecimal (text, buffer, i + 5, 3, "EOF");
|
||||||
{
|
text.append ("\n");
|
||||||
addTextAndDecimal (text, buffer, j + 8, 1, "Size");
|
|
||||||
addTextAndDecimal (text, buffer, j + 9, 1, "Type");
|
// check for Finder Info records
|
||||||
addTextAndDecimal (text, buffer, j + 10, 16, "Finder info");
|
if (i == 0 && buffer[8] != 0)
|
||||||
}
|
{
|
||||||
}
|
for (int j = 0; j <= 18; j += 18)
|
||||||
}
|
{
|
||||||
|
addTextAndDecimal (text, buffer, j + 8, 1, "Size");
|
||||||
return text.toString ();
|
addTextAndDecimal (text, buffer, j + 9, 1, "Type");
|
||||||
}
|
addTextAndDecimal (text, buffer, j + 10, 16, "Finder info");
|
||||||
|
}
|
||||||
private String getType (byte flag)
|
}
|
||||||
{
|
}
|
||||||
switch ((flag & 0x0F))
|
|
||||||
{
|
return text.toString ();
|
||||||
case ProdosConstants.SEEDLING:
|
}
|
||||||
return "Seedling";
|
|
||||||
case ProdosConstants.SAPLING:
|
// ---------------------------------------------------------------------------------//
|
||||||
return "Sapling";
|
private String getType (byte flag)
|
||||||
case ProdosConstants.TREE:
|
// ---------------------------------------------------------------------------------//
|
||||||
return "Tree";
|
{
|
||||||
default:
|
switch ((flag & 0x0F))
|
||||||
return "???";
|
{
|
||||||
}
|
case ProdosConstants.SEEDLING:
|
||||||
}
|
return "Seedling";
|
||||||
|
case ProdosConstants.SAPLING:
|
||||||
|
return "Sapling";
|
||||||
|
case ProdosConstants.TREE:
|
||||||
|
return "Tree";
|
||||||
|
default:
|
||||||
|
return "???";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,42 +1,48 @@
|
||||||
package com.bytezone.diskbrowser.prodos;
|
package com.bytezone.diskbrowser.prodos;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.disk.AbstractSector;
|
import com.bytezone.diskbrowser.disk.AbstractSector;
|
||||||
import com.bytezone.diskbrowser.disk.Disk;
|
import com.bytezone.diskbrowser.disk.Disk;
|
||||||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
|
|
||||||
class ProdosIndexSector extends AbstractSector
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
class ProdosIndexSector extends AbstractSector
|
||||||
private final String name;
|
// -----------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
ProdosIndexSector (String name, Disk disk, byte[] buffer, DiskAddress diskAddress)
|
private final String name;
|
||||||
{
|
|
||||||
super (disk, buffer, diskAddress);
|
// ---------------------------------------------------------------------------------//
|
||||||
this.name = name;
|
ProdosIndexSector (String name, Disk disk, byte[] buffer, DiskAddress diskAddress)
|
||||||
}
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
@Override
|
super (disk, buffer, diskAddress);
|
||||||
public String createText ()
|
this.name = name;
|
||||||
{
|
}
|
||||||
StringBuilder text = getHeader ("Prodos Index Block : " + name);
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
for (int i = 0; i < 256; i++)
|
@Override
|
||||||
{
|
public String createText ()
|
||||||
text.append (
|
// ---------------------------------------------------------------------------------//
|
||||||
String.format ("%02X %02X %02X", i, buffer[i], buffer[i + 256]));
|
{
|
||||||
if (buffer[i] != 0 || buffer[i + 256] != 0)
|
StringBuilder text = getHeader ("Prodos Index Block : " + name);
|
||||||
{
|
|
||||||
int blockNo = HexFormatter.intValue (buffer[i], buffer[i + 256]);
|
for (int i = 0; i < 256; i++)
|
||||||
String valid = disk.isValidAddress (blockNo) ? "" : " *** invalid ***";
|
{
|
||||||
text.append (String.format (" %s%s%n", "block " + blockNo, valid));
|
text.append (
|
||||||
}
|
String.format ("%02X %02X %02X", i, buffer[i], buffer[i + 256]));
|
||||||
else
|
if (buffer[i] != 0 || buffer[i + 256] != 0)
|
||||||
text.append ("\n");
|
{
|
||||||
}
|
int blockNo = HexFormatter.intValue (buffer[i], buffer[i + 256]);
|
||||||
|
String valid = disk.isValidAddress (blockNo) ? "" : " *** invalid ***";
|
||||||
if (text.length () > 0)
|
text.append (String.format (" %s%s%n", "block " + blockNo, valid));
|
||||||
text.deleteCharAt (text.length () - 1);
|
}
|
||||||
|
else
|
||||||
return text.toString ();
|
text.append ("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (text.length () > 0)
|
||||||
|
text.deleteCharAt (text.length () - 1);
|
||||||
|
|
||||||
|
return text.toString ();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,48 +1,58 @@
|
||||||
package com.bytezone.diskbrowser.prodos;
|
package com.bytezone.diskbrowser.prodos;
|
||||||
|
|
||||||
import java.util.List;
|
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.HexFormatter;
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
|
|
||||||
class SubDirectoryHeader extends DirectoryHeader
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
class SubDirectoryHeader extends DirectoryHeader
|
||||||
private final int parentPointer;
|
// -----------------------------------------------------------------------------------//
|
||||||
private final int parentSequence;
|
{
|
||||||
private final int parentSize;
|
private final int parentPointer;
|
||||||
|
private final int parentSequence;
|
||||||
public SubDirectoryHeader (ProdosDisk parentDisk, byte[] entryBuffer, FileEntry parent)
|
private final int parentSize;
|
||||||
{
|
|
||||||
super (parentDisk, entryBuffer);
|
// ---------------------------------------------------------------------------------//
|
||||||
this.parentDirectory = parent.parentDirectory;
|
SubDirectoryHeader (ProdosDisk parentDisk, byte[] entryBuffer, FileEntry parent)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
parentPointer = HexFormatter.intValue (entryBuffer[35], entryBuffer[36]);
|
{
|
||||||
parentSequence = entryBuffer[37] & 0xFF;
|
super (parentDisk, entryBuffer);
|
||||||
parentSize = entryBuffer[38] & 0xFF;
|
this.parentDirectory = parent.parentDirectory;
|
||||||
|
|
||||||
if (false)
|
parentPointer = HexFormatter.intValue (entryBuffer[35], entryBuffer[36]);
|
||||||
System.out.printf ("", parentPointer, parentSequence, parentSize);
|
parentSequence = entryBuffer[37] & 0xFF;
|
||||||
}
|
parentSize = entryBuffer[38] & 0xFF;
|
||||||
|
|
||||||
@Override
|
if (false)
|
||||||
public DataSource getDataSource ()
|
System.out.printf ("", parentPointer, parentSequence, parentSize);
|
||||||
{
|
}
|
||||||
// should this return a directory listing?
|
|
||||||
return null;
|
// ---------------------------------------------------------------------------------//
|
||||||
}
|
@Override
|
||||||
|
public DataSource getDataSource ()
|
||||||
@Override
|
// ---------------------------------------------------------------------------------//
|
||||||
public List<DiskAddress> getSectors ()
|
{
|
||||||
{
|
// should this return a directory listing?
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// ---------------------------------------------------------------------------------//
|
||||||
public String toString ()
|
@Override
|
||||||
{
|
public List<DiskAddress> getSectors ()
|
||||||
String locked = (access == 0x01) ? "*" : " ";
|
// ---------------------------------------------------------------------------------//
|
||||||
return String.format (" %s%-40s %15s", locked, "/" + name,
|
{
|
||||||
parentDisk.df.format (created.getTime ()));
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@Override
|
||||||
|
public String toString ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
String locked = (access == 0x01) ? "*" : " ";
|
||||||
|
return String.format (" %s%-40s %15s", locked, "/" + name,
|
||||||
|
parentDisk.df.format (created.getTime ()));
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,133 +1,143 @@
|
||||||
package com.bytezone.diskbrowser.prodos;
|
package com.bytezone.diskbrowser.prodos;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
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.HexFormatter;
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There is only one of these - it is always the first entry in the first block.
|
* There is only one of these - it is always the first entry in the first block.
|
||||||
* Every other entry will be either a SubDirectoryHeader or a FileEntry.
|
* Every other entry will be either a SubDirectoryHeader or a FileEntry.
|
||||||
*/
|
*/
|
||||||
class VolumeDirectoryHeader extends DirectoryHeader
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
class VolumeDirectoryHeader extends DirectoryHeader
|
||||||
protected final int bitMapBlock;
|
// -----------------------------------------------------------------------------------//
|
||||||
protected int totalBlocks;
|
{
|
||||||
protected int freeBlocks;
|
protected final int bitMapBlock;
|
||||||
protected int usedBlocks;
|
protected int totalBlocks;
|
||||||
protected int totalBitMapBlocks;
|
protected int freeBlocks;
|
||||||
|
protected int usedBlocks;
|
||||||
public VolumeDirectoryHeader (ProdosDisk parentDisk, byte[] entryBuffer)
|
protected int totalBitMapBlocks;
|
||||||
{
|
|
||||||
super (parentDisk, entryBuffer);
|
// ---------------------------------------------------------------------------------//
|
||||||
|
VolumeDirectoryHeader (ProdosDisk parentDisk, byte[] entryBuffer)
|
||||||
bitMapBlock = HexFormatter.unsignedShort (entryBuffer, 35);
|
// ---------------------------------------------------------------------------------//
|
||||||
totalBlocks = HexFormatter.unsignedShort (entryBuffer, 37);
|
{
|
||||||
|
super (parentDisk, entryBuffer);
|
||||||
// if (totalBlocks == 0xFFFF || totalBlocks == 0x7FFF)
|
|
||||||
// totalBlocks = (int) disk.getFile ().length () / 4096 * 8;// ignore extra bytes
|
bitMapBlock = HexFormatter.unsignedShort (entryBuffer, 35);
|
||||||
|
totalBlocks = HexFormatter.unsignedShort (entryBuffer, 37);
|
||||||
totalBitMapBlocks = (totalBlocks - 1) / 512 + 1;
|
|
||||||
|
// if (totalBlocks == 0xFFFF || totalBlocks == 0x7FFF)
|
||||||
int block = 2;
|
// totalBlocks = (int) disk.getFile ().length () / 4096 * 8;// ignore extra bytes
|
||||||
do
|
|
||||||
{
|
totalBitMapBlocks = (totalBlocks - 1) / 512 + 1;
|
||||||
dataBlocks.add (disk.getDiskAddress (block));
|
|
||||||
byte[] buffer = disk.readSector (block);
|
int block = 2;
|
||||||
block = HexFormatter.unsignedShort (buffer, 2);
|
do
|
||||||
} while (block > 0);
|
{
|
||||||
|
dataBlocks.add (disk.getDiskAddress (block));
|
||||||
// convert the Free Sector Table
|
byte[] buffer = disk.readSector (block);
|
||||||
// int bitMapBytes = totalBlocks / 8; // one bit per block
|
block = HexFormatter.unsignedShort (buffer, 2);
|
||||||
int bitMapBytes = (totalBlocks - 1) / 8 + 1; // one bit per block
|
} while (block > 0);
|
||||||
byte[] buffer = new byte[bitMapBytes];
|
|
||||||
int bitMapBlocks = (bitMapBytes - 1) / disk.getSectorsPerTrack () + 1;
|
// convert the Free Sector Table
|
||||||
int lastBitMapBlock = bitMapBlock + bitMapBlocks - 1;
|
// int bitMapBytes = totalBlocks / 8; // one bit per block
|
||||||
int ptr = 0;
|
int bitMapBytes = (totalBlocks - 1) / 8 + 1; // one bit per block
|
||||||
|
byte[] buffer = new byte[bitMapBytes];
|
||||||
for (block = bitMapBlock; block <= lastBitMapBlock; block++)
|
int bitMapBlocks = (bitMapBytes - 1) / disk.getSectorsPerTrack () + 1;
|
||||||
{
|
int lastBitMapBlock = bitMapBlock + bitMapBlocks - 1;
|
||||||
byte[] temp = disk.readSector (block);
|
int ptr = 0;
|
||||||
int bytesToCopy = buffer.length - ptr;
|
|
||||||
if (bytesToCopy > temp.length)
|
for (block = bitMapBlock; block <= lastBitMapBlock; block++)
|
||||||
bytesToCopy = temp.length;
|
{
|
||||||
System.arraycopy (temp, 0, buffer, ptr, bytesToCopy);
|
byte[] temp = disk.readSector (block);
|
||||||
ptr += bytesToCopy;
|
int bytesToCopy = buffer.length - ptr;
|
||||||
}
|
if (bytesToCopy > temp.length)
|
||||||
|
bytesToCopy = temp.length;
|
||||||
block = 0;
|
System.arraycopy (temp, 0, buffer, ptr, bytesToCopy);
|
||||||
|
ptr += bytesToCopy;
|
||||||
// nb1 dual-dos disk needs to use totalBlocks obtained from disk
|
}
|
||||||
// int max1 = (totalBlocks - 1) / 8 + 1; // bytes required for sector map
|
|
||||||
// nb2 hard disk may be truncated, so use actual number of blocks
|
block = 0;
|
||||||
// int max2 = (disk.getTotalBlocks () - 1) / 8 + 1; // bytes required for sector map
|
|
||||||
|
// nb1 dual-dos disk needs to use totalBlocks obtained from disk
|
||||||
int max = (Math.min (totalBlocks, disk.getTotalBlocks ()) - 1) / 8 + 1;
|
// int max1 = (totalBlocks - 1) / 8 + 1; // bytes required for sector map
|
||||||
// System.out.printf ("total blocks %,d%n", totalBlocks);
|
// nb2 hard disk may be truncated, so use actual number of blocks
|
||||||
// System.out.printf ("disk blocks %,d%n", disk.getTotalBlocks ());
|
// int max2 = (disk.getTotalBlocks () - 1) / 8 + 1; // bytes required for sector map
|
||||||
|
|
||||||
for (int i = 0; i < max; i++)
|
int max = (Math.min (totalBlocks, disk.getTotalBlocks ()) - 1) / 8 + 1;
|
||||||
{
|
// System.out.printf ("total blocks %,d%n", totalBlocks);
|
||||||
byte b = buffer[i];
|
// System.out.printf ("disk blocks %,d%n", disk.getTotalBlocks ());
|
||||||
for (int j = 0; j < 8; j++)
|
|
||||||
{
|
for (int i = 0; i < max; i++)
|
||||||
if ((b & 0x80) == 0x80)
|
{
|
||||||
{
|
byte b = buffer[i];
|
||||||
freeBlocks++;
|
for (int j = 0; j < 8; j++)
|
||||||
parentDisk.setSectorFree (block++, true);
|
{
|
||||||
}
|
if ((b & 0x80) == 0x80)
|
||||||
else
|
{
|
||||||
{
|
freeBlocks++;
|
||||||
usedBlocks++;
|
parentDisk.setSectorFree (block++, true);
|
||||||
parentDisk.setSectorFree (block++, false);
|
}
|
||||||
}
|
else
|
||||||
b <<= 1;
|
{
|
||||||
}
|
usedBlocks++;
|
||||||
}
|
parentDisk.setSectorFree (block++, false);
|
||||||
}
|
}
|
||||||
|
b <<= 1;
|
||||||
@Override
|
}
|
||||||
public DataSource getDataSource ()
|
}
|
||||||
{
|
}
|
||||||
List<byte[]> blockList = new ArrayList<> ();
|
|
||||||
int block = 2;
|
// ---------------------------------------------------------------------------------//
|
||||||
do
|
@Override
|
||||||
{
|
public DataSource getDataSource ()
|
||||||
byte[] buf = disk.readSector (block);
|
// ---------------------------------------------------------------------------------//
|
||||||
blockList.add (buf);
|
{
|
||||||
block = HexFormatter.intValue (buf[2], buf[3]); // next block
|
List<byte[]> blockList = new ArrayList<> ();
|
||||||
} while (block > 0);
|
int block = 2;
|
||||||
|
do
|
||||||
byte[] fullBuffer = new byte[blockList.size () * 507];
|
{
|
||||||
int offset = 0;
|
byte[] buf = disk.readSector (block);
|
||||||
for (byte[] bfr : blockList)
|
blockList.add (buf);
|
||||||
{
|
block = HexFormatter.intValue (buf[2], buf[3]); // next block
|
||||||
System.arraycopy (bfr, 4, fullBuffer, offset, 507);
|
} while (block > 0);
|
||||||
offset += 507;
|
|
||||||
}
|
byte[] fullBuffer = new byte[blockList.size () * 507];
|
||||||
return new ProdosDirectory (parentDisk, name, fullBuffer, totalBlocks, freeBlocks,
|
int offset = 0;
|
||||||
usedBlocks);
|
for (byte[] bfr : blockList)
|
||||||
}
|
{
|
||||||
|
System.arraycopy (bfr, 4, fullBuffer, offset, 507);
|
||||||
@Override
|
offset += 507;
|
||||||
public List<DiskAddress> getSectors ()
|
}
|
||||||
{
|
return new ProdosDirectory (parentDisk, name, fullBuffer, totalBlocks, freeBlocks,
|
||||||
List<DiskAddress> sectors = new ArrayList<> ();
|
usedBlocks);
|
||||||
sectors.addAll (dataBlocks);
|
}
|
||||||
return sectors;
|
|
||||||
}
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@Override
|
||||||
@Override
|
public List<DiskAddress> getSectors ()
|
||||||
public String toString ()
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
if (false)
|
List<DiskAddress> sectors = new ArrayList<> ();
|
||||||
{
|
sectors.addAll (dataBlocks);
|
||||||
String locked = (access == 0x01) ? "*" : " ";
|
return sectors;
|
||||||
String timeC = created == null ? "" : parentDisk.df.format (created.getTime ());
|
}
|
||||||
return String.format (" %s%-42s %15s", locked, "/" + name, timeC);
|
|
||||||
}
|
// ---------------------------------------------------------------------------------//
|
||||||
return name;
|
@Override
|
||||||
}
|
public String toString ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
if (false)
|
||||||
|
{
|
||||||
|
String locked = (access == 0x01) ? "*" : " ";
|
||||||
|
String timeC = created == null ? "" : parentDisk.df.format (created.getTime ());
|
||||||
|
return String.format (" %s%-42s %15s", locked, "/" + name, timeC);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user