This commit is contained in:
Denis Molony 2019-11-03 15:49:01 +10:00
parent 7a9c73ce9c
commit f5cdeb61cb
13 changed files with 285 additions and 48 deletions

View File

@ -11,6 +11,7 @@ public class CharacterRom extends CharacterList
{
private static final int charsX = 16;
private static final int charsY = 6;
private static final int HEADER_LENGTH = 0x100;
String description;
List<Character> characters = new ArrayList<> ();
@ -19,7 +20,7 @@ public class CharacterRom extends CharacterList
public CharacterRom (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
{
super (name, buffer, charsX, charsY, 256);
super (name, buffer, charsX, charsY, HEADER_LENGTH);
description = new String (buffer, 16, 16);

View File

@ -39,10 +39,11 @@ public class Charset extends CharacterList
{
DataBuffer dataBuffer = image.getRaster ().getDataBuffer ();
int element = 0;
ptr += sizeY; // start at the end and move backwards
for (int i = sizeY - 1; i >= 0; i--)
for (int i = 0; i < sizeY; i++)
{
int value = buffer[ptr + i] & 0xFF;
int value = buffer[--ptr] & 0xFF;
for (int j = 0; j < sizeX; j++)
{
dataBuffer.setElem (element++, (value & 0x01) == 0 ? 0 : 0xFF);

View File

@ -14,8 +14,15 @@ import javax.swing.*;
import com.bytezone.diskbrowser.duplicates.RootFolderData;
// -----------------------------------------------------------------------------------//
public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitListener
// -----------------------------------------------------------------------------------//
{
static long start;
static
{
start = System.currentTimeMillis ();
}
private static String[] args;
private static final String windowTitle = "Apple ][ Disk Browser";
private final Preferences prefs = Preferences.userNodeForPackage (this.getClass ());
@ -26,9 +33,12 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
private final RootFolderData rootFolderData = new RootFolderData ();
// ---------------------------------------------------------------------------------//
public DiskBrowser ()
// ---------------------------------------------------------------------------------//
{
super (windowTitle);
System.out.printf ("Start Init: %,5d%n", System.currentTimeMillis () - start);
if (args.length > 0 && "-reset".equals (args[0]))
new WindowState (prefs).clear ();
@ -175,9 +185,12 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
// activate the highest panel now that the listeners are ready
catalogPanel.activate ();
System.out.printf ("End Init : %,5d%n", System.currentTimeMillis () - start);
}
// ---------------------------------------------------------------------------------//
private JPanel addPanel (JComponent pane, String title, String location)
// ---------------------------------------------------------------------------------//
{
JPanel panel = new JPanel (new BorderLayout ());
panel.setBackground (Color.WHITE);
@ -187,27 +200,35 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
return panel;
}
// ---------------------------------------------------------------------------------//
@Override
public void diskSelected (DiskSelectedEvent e)
// ---------------------------------------------------------------------------------//
{
setTitle (windowTitle + e.getFormattedDisk () == null ? ""
: e.getFormattedDisk ().getName ());
}
// ---------------------------------------------------------------------------------//
@Override
public void quit (Preferences preferences)
// ---------------------------------------------------------------------------------//
{
windowSaver.saveWindow ();
}
// ---------------------------------------------------------------------------------//
@Override
public void restore (Preferences preferences)
// ---------------------------------------------------------------------------------//
{
windowSaver = new WindowSaver (prefs, this, "DiskBrowser");
windowSaver.restoreWindow ();
}
// ---------------------------------------------------------------------------------//
public static void main (String[] args)
// ---------------------------------------------------------------------------------//
{
DiskBrowser.args = args;
EventQueue.invokeLater (new Runnable ()
@ -221,17 +242,15 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
});
}
// ---------------------------------------------------------------------------------//
private static void setLookAndFeel ()
// ---------------------------------------------------------------------------------//
{
try
{
UIManager.setLookAndFeel (UIManager.getSystemLookAndFeelClassName ());
if (MAC)
{
UIManager.setLookAndFeel (UIManager.getSystemLookAndFeelClassName ());
System.setProperty ("apple.laf.useScreenMenuBar", "true");
}
else
UIManager.setLookAndFeel ("javax.swing.plaf.nimbus.NimbusLookAndFeel");
}
catch (Exception e)
{
@ -241,17 +260,23 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
List<QuitListener> quitListeners = new ArrayList<> ();
// ---------------------------------------------------------------------------------//
public void addQuitListener (QuitListener listener)
// ---------------------------------------------------------------------------------//
{
quitListeners.add (listener);
}
// ---------------------------------------------------------------------------------//
public void removeQuitListener (QuitListener listener)
// ---------------------------------------------------------------------------------//
{
quitListeners.remove (listener);
}
// ---------------------------------------------------------------------------------//
private void fireQuitEvent ()
// ---------------------------------------------------------------------------------//
{
for (QuitListener listener : quitListeners)
listener.quit (prefs);
@ -259,7 +284,9 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
System.exit (0);
}
// ---------------------------------------------------------------------------------//
private void fireRestoreEvent ()
// ---------------------------------------------------------------------------------//
{
for (QuitListener listener : quitListeners)
listener.restore (prefs);

View File

@ -4,29 +4,39 @@ import java.util.EventObject;
import com.bytezone.diskbrowser.gui.TreeBuilder.FileNode;
// -----------------------------------------------------------------------------------//
public class FileNodeSelectedEvent extends EventObject
// -----------------------------------------------------------------------------------//
{
private final FileNode node;
boolean redo;
// ---------------------------------------------------------------------------------//
public FileNodeSelectedEvent (Object source, FileNode node)
// ---------------------------------------------------------------------------------//
{
super (source);
this.node = node;
}
// ---------------------------------------------------------------------------------//
public FileNode getFileNode ()
// ---------------------------------------------------------------------------------//
{
return node;
}
// ---------------------------------------------------------------------------------//
@Override
public String toString ()
// ---------------------------------------------------------------------------------//
{
return node.file.getAbsolutePath ();
}
// ---------------------------------------------------------------------------------//
public String toText ()
// ---------------------------------------------------------------------------------//
{
return node.file.getAbsolutePath ();
}

View File

@ -19,19 +19,22 @@ import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import com.bytezone.diskbrowser.disk.DiskFactory;
import com.bytezone.diskbrowser.disk.FormattedDisk;
import com.bytezone.diskbrowser.gui.RedoHandler.RedoEvent;
import com.bytezone.diskbrowser.gui.TreeBuilder.FileNode;
// -----------------------------------------------------------------------------------//
class FileSystemTab extends AbstractTab
// -----------------------------------------------------------------------------------//
{
File rootFolder;
// ---------------------------------------------------------------------------------//
public FileSystemTab (File folder, DiskAndFileSelector selector,
RedoHandler redoHandler, Font font, DiskSelectedEvent diskEvent)
// ---------------------------------------------------------------------------------//
{
super (redoHandler, selector, font);
this.rootFolder = folder;
@ -57,22 +60,28 @@ class FileSystemTab extends AbstractTab
System.out.println ("No disk event");
}
// ---------------------------------------------------------------------------------//
public FileSystemTab (File folder, DiskAndFileSelector selector, RedoHandler navMan,
Font font)
// ---------------------------------------------------------------------------------//
{
this (folder, selector, navMan, font, null); // default to first available disk
}
// ---------------------------------------------------------------------------------//
@Override
public void activate ()
// ---------------------------------------------------------------------------------//
{
tree.setSelectionPath (null); // turn off any current selection to force an event
redoHandler.setCurrentData (redoData);
}
// connected to RefreshTreeAction
// ---------------------------------------------------------------------------------//
@Override
public void refresh ()
// ---------------------------------------------------------------------------------//
{
String currentDiskName = ((FileNode) getSelectedObject ()).file.getAbsolutePath ();
TreeBuilder tb = new TreeBuilder (rootFolder);
@ -82,7 +91,9 @@ class FileSystemTab extends AbstractTab
setSelectionListener (tree);
}
// ---------------------------------------------------------------------------------//
void redoEvent (RedoEvent event)
// ---------------------------------------------------------------------------------//
{
DefaultMutableTreeNode node = null;
if (event.type.equals ("FileNodeEvent"))
@ -103,7 +114,9 @@ class FileSystemTab extends AbstractTab
System.out.println ("Disk node not found");
}
// ---------------------------------------------------------------------------------//
void selectDisk (String path)
// ---------------------------------------------------------------------------------//
{
DefaultMutableTreeNode node = findNode (rootFolder.getAbsolutePath () + path);
if (node != null)
@ -114,12 +127,16 @@ class FileSystemTab extends AbstractTab
}
}
// ---------------------------------------------------------------------------------//
private DefaultMutableTreeNode findNode (String absolutePath)
// ---------------------------------------------------------------------------------//
{
return search (getRootNode (), absolutePath);
}
// ---------------------------------------------------------------------------------//
private DefaultMutableTreeNode search (DefaultMutableTreeNode node, String absolutePath)
// ---------------------------------------------------------------------------------//
{
FileNode fn = (FileNode) node.getUserObject ();
@ -153,7 +170,9 @@ class FileSystemTab extends AbstractTab
return null;
}
// ---------------------------------------------------------------------------------//
public void replaceDisk (FormattedDisk disk)
// ---------------------------------------------------------------------------------//
{
// first check currently selected disk
FileNode fn = (FileNode) getSelectedObject ();
@ -172,7 +191,9 @@ class FileSystemTab extends AbstractTab
}
}
// ---------------------------------------------------------------------------------//
private void setSelectionListener (JTree tree)
// ---------------------------------------------------------------------------------//
{
tree.addTreeSelectionListener (new TreeSelectionListener ()
{
@ -195,9 +216,8 @@ class FileSystemTab extends AbstractTab
@Override
public void treeWillExpand (TreeExpansionEvent e) throws ExpandVetoException
{
TreePath path = e.getPath ();
DefaultMutableTreeNode node =
(DefaultMutableTreeNode) path.getLastPathComponent ();
(DefaultMutableTreeNode) e.getPath ().getLastPathComponent ();
FileNode fn = (FileNode) node.getUserObject ();
if (node.getChildCount () == 0)
fn.readFiles ();

View File

@ -252,16 +252,6 @@ public class MenuHandler
interleaveGroup.add (interleave3Item);
saveDiskItem.setAction (saveTempFileAction);
// this is done early because the CatalogPanel creates the previous disk used
// before restore() is called
// what about all the other preferences???
// prodosSortDirectoriesItem
// .setSelected (prefs.getBoolean (PREFS_PRODOS_SORT_DIRECTORIES, true));
// setBasicPreferences ();
// setAssemblerPreferences ();
// setProdosPreferences ();
}
private void setBasicPreferences ()

View File

@ -19,14 +19,18 @@ import com.bytezone.diskbrowser.disk.FormattedDisk;
import com.bytezone.diskbrowser.utilities.FileFormatException;
import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------//
public class TreeBuilder
// -----------------------------------------------------------------------------------//
{
private static SimpleDateFormat sdf = new SimpleDateFormat ("dd MMM yyyy");
private final FileComparator fileComparator = new FileComparator ();
private final JTree tree;
// ---------------------------------------------------------------------------------//
public TreeBuilder (File rootFolder)
// ---------------------------------------------------------------------------------//
{
assert (rootFolder.exists ());
assert (rootFolder.isDirectory ());
@ -43,12 +47,16 @@ public class TreeBuilder
setDiskIcon ("/com/bytezone/diskbrowser/icons/disk.png");
}
// ---------------------------------------------------------------------------------//
public JTree getTree ()
// ---------------------------------------------------------------------------------//
{
return tree;
}
// ---------------------------------------------------------------------------------//
private void addFiles (DefaultMutableTreeNode parentNode, File directory)
// ---------------------------------------------------------------------------------//
{
File[] files = directory.listFiles ();
if (files == null || files.length == 0)
@ -70,7 +78,9 @@ public class TreeBuilder
}
}
// ---------------------------------------------------------------------------------//
private DefaultMutableTreeNode createNode (File file, boolean allowsChildren)
// ---------------------------------------------------------------------------------//
{
FileNode fileNode = new FileNode (file);
DefaultMutableTreeNode newNode = new DefaultMutableTreeNode (fileNode);
@ -79,7 +89,9 @@ public class TreeBuilder
return newNode;
}
// ---------------------------------------------------------------------------------//
private void setDiskIcon (String iconName)
// ---------------------------------------------------------------------------------//
{
URL url = this.getClass ().getResource (iconName);
if (url != null)
@ -98,7 +110,9 @@ public class TreeBuilder
/*
* Class used to control the text displayed by the JTree.
*/
// ---------------------------------------------------------------------------------//
public class FileNode implements DataSource // why does it implement DataSource?
// ---------------------------------------------------------------------------------//
{
DefaultMutableTreeNode parentNode;
public final File file;
@ -109,22 +123,30 @@ public class TreeBuilder
int disks;
boolean showDisks;
// -------------------------------------------------------------------------------//
public FileNode (File file)
// -------------------------------------------------------------------------------//
{
this.file = file;
}
// -------------------------------------------------------------------------------//
public void setTreeNode (DefaultMutableTreeNode node)
// -------------------------------------------------------------------------------//
{
this.parentNode = node;
}
// -------------------------------------------------------------------------------//
public void readFiles ()
// -------------------------------------------------------------------------------//
{
addFiles (parentNode, file);
}
// -------------------------------------------------------------------------------//
public FormattedDisk getFormattedDisk ()
// -------------------------------------------------------------------------------//
{
if (formattedDisk == null)
try
@ -140,7 +162,9 @@ public class TreeBuilder
return formattedDisk;
}
// -------------------------------------------------------------------------------//
public boolean replaceDisk (FormattedDisk disk)
// -------------------------------------------------------------------------------//
{
String path = disk.getDisk ().getFile ().getAbsolutePath ();
if (formattedDisk != null && path.equals (file.getAbsolutePath ()))
@ -151,8 +175,10 @@ public class TreeBuilder
return false;
}
// -------------------------------------------------------------------------------//
@Override
public String toString ()
// -------------------------------------------------------------------------------//
{
String name = file.getName ();
if (name.length () > MAX_NAME_LENGTH)
@ -163,8 +189,10 @@ public class TreeBuilder
return name;
}
// -------------------------------------------------------------------------------//
@Override
public String getText ()
// -------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
@ -200,26 +228,34 @@ public class TreeBuilder
return text.toString ();
}
// -------------------------------------------------------------------------------//
@Override
public String getAssembler ()
// -------------------------------------------------------------------------------//
{
return null;
}
// -------------------------------------------------------------------------------//
@Override
public String getHexDump ()
// -------------------------------------------------------------------------------//
{
return null;
}
// -------------------------------------------------------------------------------//
@Override
public BufferedImage getImage ()
// -------------------------------------------------------------------------------//
{
return null;
}
// -------------------------------------------------------------------------------//
@Override
public JComponent getComponent ()
// -------------------------------------------------------------------------------//
{
return null;
}

View File

@ -16,7 +16,9 @@ import com.bytezone.diskbrowser.utilities.HexFormatter;
// - Populate dataBlocks, indexBlocks, catalogBlock and masterIndexBlock
// - Provide getDataSource ()
// -----------------------------------------------------------------------------------//
class FileEntry extends CatalogEntry implements ProdosConstants
// -----------------------------------------------------------------------------------//
{
private final int fileType;
final int keyPtr;
@ -34,8 +36,10 @@ class FileEntry extends CatalogEntry implements ProdosConstants
private boolean invalid;
private FileEntry link;
// ---------------------------------------------------------------------------------//
public FileEntry (ProdosDisk fDisk, byte[] entryBuffer, DirectoryHeader parent,
int parentBlock)
// ---------------------------------------------------------------------------------//
{
super (fDisk, entryBuffer);
@ -88,14 +92,16 @@ class FileEntry extends CatalogEntry implements ProdosConstants
}
}
// ---------------------------------------------------------------------------------//
private void readForks ()
// ---------------------------------------------------------------------------------//
{
parentDisk.setSectorType (keyPtr, parentDisk.extendedKeySector);
indexBlocks.add (disk.getDiskAddress (keyPtr));
byte[] buffer2 = disk.readSector (keyPtr); // data fork and resource fork
// read 2 mini entries (data fork / resource fork)
// read 2 mini entries (data fork & resource fork)
for (int i = 0; i < 512; i += 256)
{
int storageType = buffer2[i] & 0x0F;
@ -105,10 +111,12 @@ class FileEntry extends CatalogEntry implements ProdosConstants
}
}
// ---------------------------------------------------------------------------------//
private void addDataBlocks (int storageType, int keyPtr)
// ---------------------------------------------------------------------------------//
{
DiskAddress emptyDiskAddress = disk.getDiskAddress (0);
List<Integer> blocks = new ArrayList<Integer> ();
List<Integer> blocks = new ArrayList<> ();
switch (storageType)
{
@ -146,9 +154,11 @@ class FileEntry extends CatalogEntry implements ProdosConstants
}
}
// ---------------------------------------------------------------------------------//
private List<Integer> readIndex (int blockPtr)
// ---------------------------------------------------------------------------------//
{
List<Integer> blocks = new ArrayList<Integer> (256);
List<Integer> blocks = new ArrayList<> (256);
if (blockPtr == 0) // master index contains a zero
for (int i = 0; i < 256; i++)
@ -169,7 +179,9 @@ class FileEntry extends CatalogEntry implements ProdosConstants
return blocks;
}
// ---------------------------------------------------------------------------------//
private List<Integer> readMasterIndex (int keyPtr)
// ---------------------------------------------------------------------------------//
{
masterIndexBlock = disk.getDiskAddress (keyPtr);
parentDisk.setSectorType (keyPtr, parentDisk.masterIndexSector);
@ -182,7 +194,7 @@ class FileEntry extends CatalogEntry implements ProdosConstants
if (buffer[highest] != 0 || buffer[highest + 0x100] != 0)
break;
List<Integer> blocks = new ArrayList<Integer> (highest + 1);
List<Integer> blocks = new ArrayList<> (highest + 1);
for (int i = 0; i <= highest; i++)
{
int blockNo = (buffer[i] & 0xFF) | ((buffer[i + 256] & 0xFF) << 8);
@ -192,7 +204,9 @@ class FileEntry extends CatalogEntry implements ProdosConstants
return blocks;
}
// ---------------------------------------------------------------------------------//
private boolean isValid (int blockNo)
// ---------------------------------------------------------------------------------//
{
if (false)
{
@ -204,8 +218,10 @@ class FileEntry extends CatalogEntry implements ProdosConstants
return disk.isValidAddress (blockNo) && !parentDisk.isSectorFree (blockNo);
}
// ---------------------------------------------------------------------------------//
@Override
public DataSource getDataSource ()
// ---------------------------------------------------------------------------------//
{
if (file != null)
return file;
@ -271,8 +287,7 @@ class FileEntry extends CatalogEntry implements ProdosConstants
file = new OriginalHiResImage (name, exactBuffer, auxType);
else if (endOfFile == 38400 && name.startsWith ("LVL."))
file = new LodeRunner (name, exactBuffer);
else if (auxType == 0x1000 && endOfFile == 0x400
&& CharacterRom.isRom (exactBuffer))
else if (auxType == 0x1000 && CharacterRom.isRom (exactBuffer))
file = new CharacterRom (name, exactBuffer);
else if (auxType == 0 && endOfFile == 0x8000)
{
@ -313,7 +328,7 @@ class FileEntry extends CatalogEntry implements ProdosConstants
break;
case FILE_TYPE_DIRECTORY:
VolumeDirectoryHeader vdh = parentDisk.vdh;
VolumeDirectoryHeader vdh = parentDisk.getVolumeDirectoryHeader ();
file = new ProdosDirectory (parentDisk, name, buffer, vdh.totalBlocks,
vdh.freeBlocks, vdh.usedBlocks);
break;
@ -432,7 +447,9 @@ class FileEntry extends CatalogEntry implements ProdosConstants
return file;
}
// ---------------------------------------------------------------------------------//
private boolean oneOf (int val, int... values)
// ---------------------------------------------------------------------------------//
{
for (int value : values)
if (val == value)
@ -440,7 +457,9 @@ class FileEntry extends CatalogEntry implements ProdosConstants
return false;
}
// ---------------------------------------------------------------------------------//
private byte[] getExactBuffer (byte[] buffer)
// ---------------------------------------------------------------------------------//
{
byte[] exactBuffer;
if (buffer.length < endOfFile)
@ -458,7 +477,9 @@ class FileEntry extends CatalogEntry implements ProdosConstants
return exactBuffer;
}
// ---------------------------------------------------------------------------------//
private DataSource getRandomAccessTextFile ()
// ---------------------------------------------------------------------------------//
{
// Text files with aux (reclen) > 0 are random access, possibly with
// non-contiguous records, so they need to be handled differently
@ -477,7 +498,9 @@ class FileEntry extends CatalogEntry implements ProdosConstants
}
}
// ---------------------------------------------------------------------------------//
private DataSource getTreeTextFile ()
// ---------------------------------------------------------------------------------//
{
List<TextBuffer> buffers = new ArrayList<> ();
List<DiskAddress> addresses = new ArrayList<> ();
@ -508,7 +531,9 @@ class FileEntry extends CatalogEntry implements ProdosConstants
return new TextFile (name, buffers, auxType, endOfFile);
}
// ---------------------------------------------------------------------------------//
private DataSource getSaplingTextFile ()
// ---------------------------------------------------------------------------------//
{
List<TextBuffer> buffers = new ArrayList<> ();
List<DiskAddress> addresses = new ArrayList<> ();
@ -520,7 +545,9 @@ class FileEntry extends CatalogEntry implements ProdosConstants
return new TextFile (name, buffers, auxType, endOfFile);
}
// ---------------------------------------------------------------------------------//
private DataSource getSeedlingTextFile ()
// ---------------------------------------------------------------------------------//
{
byte[] buffer = getBuffer ();
if (endOfFile < buffer.length)
@ -536,7 +563,9 @@ class FileEntry extends CatalogEntry implements ProdosConstants
return new TextFile (name, buffer, auxType, endOfFile);
}
// ---------------------------------------------------------------------------------//
private byte[] getBuffer ()
// ---------------------------------------------------------------------------------//
{
switch (storageType)
{
@ -568,8 +597,10 @@ class FileEntry extends CatalogEntry implements ProdosConstants
}
}
// ---------------------------------------------------------------------------------//
private int readIndexBlock (int indexBlock, List<DiskAddress> addresses,
List<TextBuffer> buffers, int logicalBlock)
// ---------------------------------------------------------------------------------//
{
byte[] indexBuffer = disk.readSector (indexBlock);
for (int j = 0; j < 256; j++)
@ -586,11 +617,14 @@ class FileEntry extends CatalogEntry implements ProdosConstants
}
logicalBlock++;
}
return logicalBlock;
}
// ---------------------------------------------------------------------------------//
@Override
public List<DiskAddress> getSectors ()
// ---------------------------------------------------------------------------------//
{
List<DiskAddress> sectors = new ArrayList<> ();
sectors.add (catalogBlock);
@ -598,11 +632,14 @@ class FileEntry extends CatalogEntry implements ProdosConstants
sectors.add (masterIndexBlock);
sectors.addAll (indexBlocks);
sectors.addAll (dataBlocks);
return sectors;
}
// ---------------------------------------------------------------------------------//
@Override
public boolean contains (DiskAddress da)
// ---------------------------------------------------------------------------------//
{
if (da == null)
return false;
@ -614,20 +651,26 @@ class FileEntry extends CatalogEntry implements ProdosConstants
for (DiskAddress block : dataBlocks)
if (da.matches (block))
return true;
return false;
}
// called from ProdosDisk.processDirectoryBlock
// called from ProdosDisk.processDirectoryBlock, used to link DoubleHires image files
// ---------------------------------------------------------------------------------//
void link (FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{
this.link = fileEntry;
}
// ---------------------------------------------------------------------------------//
@Override
public String toString ()
// ---------------------------------------------------------------------------------//
{
if (ProdosConstants.fileTypes[fileType].equals ("DIR"))
return name;
String locked = (access == 0x00) ? "*" : " ";
if (true)

View File

@ -23,7 +23,8 @@ class ProdosBitMapSector extends AbstractSector
// check range of bits for current block - so far I don't have a disk that needs
// more than a single block
int relativeBlock = diskAddress.getBlock () - parent.vdh.bitMapBlock;
int relativeBlock =
diskAddress.getBlock () - parent.getVolumeDirectoryHeader ().bitMapBlock;
int startBit = relativeBlock * 4096;
// int endBit = startBit + 4096;
if (startBit >= grid.width * grid.height)

View File

@ -1,24 +1,31 @@
package com.bytezone.diskbrowser.prodos;
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
import com.bytezone.diskbrowser.applefile.AbstractFile;
import com.bytezone.diskbrowser.disk.FormattedDisk;
import com.bytezone.diskbrowser.utilities.HexFormatter;
// -----------------------------------------------------------------------------------//
class ProdosDirectory extends AbstractFile implements ProdosConstants
// -----------------------------------------------------------------------------------//
{
private static final String NO_DATE = "<NO DATE>";
private static final String newLine = String.format ("%n");
private static final String newLine2 = newLine + newLine;
private static final SimpleDateFormat sdf = new SimpleDateFormat ("d-MMM-yy");
private static final SimpleDateFormat stf = new SimpleDateFormat ("H:mm");
private final ProdosDisk parentFD;
private final int totalBlocks;
private final int freeBlocks;
private final int usedBlocks;
// ---------------------------------------------------------------------------------//
public ProdosDirectory (FormattedDisk parent, String name, byte[] buffer,
int totalBlocks, int freeBlocks, int usedBlocks)
// ---------------------------------------------------------------------------------//
{
super (name, buffer);
@ -28,8 +35,10 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
this.usedBlocks = usedBlocks;
}
// ---------------------------------------------------------------------------------//
@Override
public String getText ()
// ---------------------------------------------------------------------------------//
{
StringBuffer text = new StringBuffer ();
text.append ("Disk : " + parentFD.getDisplayPath () + newLine2);
@ -65,13 +74,12 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
GregorianCalendar created = HexFormatter.getAppleDate (buffer, i + 24);
String dateC = created == null ? NO_DATE
: parentFD.sdf.format (created.getTime ()).toUpperCase ().replace (".", "");
String timeC = created == null ? "" : parentFD.stf.format (created.getTime ());
: sdf.format (created.getTime ()).toUpperCase ().replace (".", "");
String timeC = created == null ? "" : stf.format (created.getTime ());
GregorianCalendar modified = HexFormatter.getAppleDate (buffer, i + 33);
String dateM = modified == null ? NO_DATE : parentFD.sdf
.format (modified.getTime ()).toUpperCase ().replace (".", "");
String timeM =
modified == null ? "" : parentFD.stf.format (modified.getTime ());
String dateM = modified == null ? NO_DATE
: sdf.format (modified.getTime ()).toUpperCase ().replace (".", "");
String timeM = modified == null ? "" : stf.format (modified.getTime ());
int eof =
HexFormatter.intValue (buffer[i + 21], buffer[i + 22], buffer[i + 23]);
int fileType = buffer[i + 16] & 0xFF;
@ -117,7 +125,9 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
return text.toString ();
}
// ---------------------------------------------------------------------------------//
private String convert (String name, int flags)
// ---------------------------------------------------------------------------------//
{
char[] newName = name.toCharArray ();
for (int i = 0, weight = 0x8000; i < newName.length; i++, weight >>>= 1)

View File

@ -2,7 +2,6 @@ package com.bytezone.diskbrowser.prodos;
import java.awt.Color;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@ -25,8 +24,6 @@ public class ProdosDisk extends AbstractFormattedDisk
static ProdosPreferences prodosPreferences; // set by MenuHandler
final DateFormat df = DateFormat.getInstance ();
final SimpleDateFormat sdf = new SimpleDateFormat ("d-MMM-yy");
final SimpleDateFormat stf = new SimpleDateFormat ("H:mm");
final SectorType dosSector = new SectorType ("Bootstrap Loader", Color.lightGray);
final SectorType catalogSector = new SectorType ("Catalog", new Color (0, 200, 0));
@ -38,9 +35,9 @@ public class ProdosDisk extends AbstractFormattedDisk
final SectorType extendedKeySector = new SectorType ("Extended key", Color.gray);
private final List<DirectoryHeader> headerEntries = new ArrayList<> ();
VolumeDirectoryHeader vdh;
private final DefaultMutableTreeNode volumeNode;
private final NodeComparator nodeComparator = new NodeComparator ();
private VolumeDirectoryHeader vdh;
private static final boolean debug = false;
@ -129,15 +126,15 @@ public class ProdosDisk extends AbstractFormattedDisk
case ProdosConstants.VOLUME_HEADER:
assert headerEntries.size () == 0;
vdh = new VolumeDirectoryHeader (this, entry);
localHeader = vdh;
assert localHeader.entryLength == ProdosConstants.ENTRY_SIZE;
headerEntries.add (localHeader);
assert vdh.entryLength == ProdosConstants.ENTRY_SIZE;
headerEntries.add (vdh);
currentSectorType = catalogSector;
if (!disk.isSectorEmpty (block))
sectorTypes[block] = currentSectorType;
for (int i = 0; i < vdh.totalBitMapBlocks; i++)
sectorTypes[vdh.bitMapBlock + i] = volumeMapSector;
parentNode.setUserObject (vdh); // populate the empty volume node
localHeader = vdh;
break;
case ProdosConstants.SUBDIRECTORY_HEADER:
@ -197,11 +194,11 @@ public class ProdosDisk extends AbstractFormattedDisk
}
// ---------------------------------------------------------------------------------//
public boolean isReservedAddress (int blockNo)
// ---------------------------------------------------------------------------------//
{
return false;
}
// public boolean isReservedAddress (int blockNo)
// // ---------------------------------------------------------------------------------//
// {
// return false;
// }
// ---------------------------------------------------------------------------------//
public static boolean isCorrectFormat (AppleDisk disk)
@ -238,6 +235,13 @@ public class ProdosDisk extends AbstractFormattedDisk
return true;
}
// ---------------------------------------------------------------------------------//
VolumeDirectoryHeader getVolumeDirectoryHeader ()
// ---------------------------------------------------------------------------------//
{
return vdh;
}
// ---------------------------------------------------------------------------------//
public DataSource getFile (int fileNo)
// ---------------------------------------------------------------------------------//

View File

@ -4,45 +4,61 @@ import java.math.BigDecimal;
import java.math.MathContext;
import java.util.GregorianCalendar;
// -----------------------------------------------------------------------------------//
public class HexFormatter
// -----------------------------------------------------------------------------------//
{
private static String[] hex =
{ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" };
private static MathContext mathContext = new MathContext (9);
// ---------------------------------------------------------------------------------//
public static String format (byte[] buffer)
// ---------------------------------------------------------------------------------//
{
return format (buffer, 0, buffer.length);
}
// ---------------------------------------------------------------------------------//
public static String formatNoHeader (byte[] buffer)
// ---------------------------------------------------------------------------------//
{
return formatNoHeader (buffer, 0, buffer.length);
}
// ---------------------------------------------------------------------------------//
public static String format (byte[] buffer, int offset, int length)
// ---------------------------------------------------------------------------------//
{
return format (buffer, offset, length, true, 0);
}
// ---------------------------------------------------------------------------------//
public static String format (byte[] buffer, int offset, int length, int startingAddress)
// ---------------------------------------------------------------------------------//
{
return format (buffer, offset, length, true, startingAddress);
}
// ---------------------------------------------------------------------------------//
public static String formatNoHeader (byte[] buffer, int offset, int length)
// ---------------------------------------------------------------------------------//
{
return format (buffer, offset, length, false, 0);
}
// ---------------------------------------------------------------------------------//
public static String formatNoHeader (byte[] buffer, int offset, int length,
int startingAddress)
// ---------------------------------------------------------------------------------//
{
return format (buffer, offset, length, false, startingAddress);
}
// ---------------------------------------------------------------------------------//
public static String format (byte[] buffer, int offset, int length, boolean header,
int startingAddress)
// ---------------------------------------------------------------------------------//
{
StringBuilder line = new StringBuilder ();
int[] freq = new int[256];
@ -113,7 +129,9 @@ public class HexFormatter
return line.toString ();
}
// ---------------------------------------------------------------------------------//
public static String sanitiseString (byte[] buffer, int offset, int length)
// ---------------------------------------------------------------------------------//
{
StringBuilder trans = new StringBuilder ();
for (int j = offset; j < offset + length; j++)
@ -136,12 +154,16 @@ public class HexFormatter
return trans.toString ();
}
// ---------------------------------------------------------------------------------//
public static String getString (byte[] buffer)
// ---------------------------------------------------------------------------------//
{
return getString (buffer, 0, buffer.length);
}
// ---------------------------------------------------------------------------------//
public static String getString (byte[] buffer, int offset, int length)
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
@ -165,7 +187,9 @@ public class HexFormatter
return text.toString ();
}
// ---------------------------------------------------------------------------------//
public static String getString2 (byte[] buffer, int offset, int length)
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
@ -193,17 +217,23 @@ public class HexFormatter
return text.toString ();
}
// ---------------------------------------------------------------------------------//
public static String getHexString (byte[] buffer, int offset, int length)
// ---------------------------------------------------------------------------------//
{
return getHexString (buffer, offset, length, true);
}
// ---------------------------------------------------------------------------------//
public static String getHexString (byte[] buffer)
// ---------------------------------------------------------------------------------//
{
return getHexString (buffer, 0, buffer.length);
}
// ---------------------------------------------------------------------------------//
public static String getHexString (byte[] buffer, int offset, int length, boolean space)
// ---------------------------------------------------------------------------------//
{
StringBuilder hex = new StringBuilder ();
int max = Math.min (offset + length, buffer.length);
@ -218,8 +248,10 @@ public class HexFormatter
return hex.toString ();
}
// ---------------------------------------------------------------------------------//
public static String getHexStringReversed (byte[] buffer, int offset, int length,
boolean space)
// ---------------------------------------------------------------------------------//
{
StringBuilder hex = new StringBuilder ();
for (int i = length - 1; i >= 0; i--)
@ -233,14 +265,18 @@ public class HexFormatter
return hex.toString ();
}
// ---------------------------------------------------------------------------------//
public static String getBitString (byte b)
// ---------------------------------------------------------------------------------//
{
String s = "0000000" + Integer.toBinaryString (b & 0xFF);
s = s.replaceAll ("0", ".");
return s.substring (s.length () - 8);
}
// ---------------------------------------------------------------------------------//
public static char byteValue (byte b)
// ---------------------------------------------------------------------------------//
{
int c = b & 0xFF;
if (c > 127)
@ -253,7 +289,9 @@ public class HexFormatter
}
// ---------------------------------------------------------------------------------//
public static String format4 (int value)
// ---------------------------------------------------------------------------------//
{
if (value < 0)
return "***err**";
@ -270,12 +308,16 @@ public class HexFormatter
return text.toString ();
}
// ---------------------------------------------------------------------------------//
public static String format3 (int value)
// ---------------------------------------------------------------------------------//
{
return format4 (value).substring (1);
}
// ---------------------------------------------------------------------------------//
public static String format2 (int value)
// ---------------------------------------------------------------------------------//
{
if (value < 0)
value += 256;
@ -283,23 +325,31 @@ public class HexFormatter
return text;
}
// ---------------------------------------------------------------------------------//
public static String format1 (int value)
// ---------------------------------------------------------------------------------//
{
String text = hex[value];
return text;
}
// ---------------------------------------------------------------------------------//
public static int intValue (byte b1, byte b2)
// ---------------------------------------------------------------------------------//
{
return (b1 & 0xFF) + (b2 & 0xFF) * 256;
}
// ---------------------------------------------------------------------------------//
public static int intValue (byte b1, byte b2, byte b3)
// ---------------------------------------------------------------------------------//
{
return (b1 & 0xFF) + (b2 & 0xFF) * 256 + (b3 & 0xFF) * 65536;
}
// ---------------------------------------------------------------------------------//
public static int unsignedLong (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
int val = 0;
for (int i = 3; i >= 0; i--)
@ -310,13 +360,17 @@ public class HexFormatter
return val;
}
// ---------------------------------------------------------------------------------//
public static int signedLong (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
return (((buffer[ptr] & 0xFF) << 24) | ((buffer[ptr] & 0xFF) << 16)
| ((buffer[ptr] & 0xFF) << 8) | (buffer[ptr + 1] & 0xFF));
}
// ---------------------------------------------------------------------------------//
public static int getLongBigEndian (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
int val = 0;
for (int i = 0; i < 4; i++)
@ -327,7 +381,9 @@ public class HexFormatter
return val;
}
// ---------------------------------------------------------------------------------//
public static int unsignedShort (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
if (ptr >= buffer.length)
{
@ -337,7 +393,9 @@ public class HexFormatter
return (buffer[ptr] & 0xFF) | ((buffer[ptr + 1] & 0xFF) << 8);
}
// ---------------------------------------------------------------------------------//
public static int signedShort (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
if (ptr >= buffer.length)
{
@ -347,7 +405,9 @@ public class HexFormatter
return (short) ((buffer[ptr] & 0xFF) | ((buffer[ptr + 1] & 0xFF) << 8));
}
// ---------------------------------------------------------------------------------//
public static int getShortBigEndian (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
int val = 0;
for (int i = 0; i < 2; i++)
@ -358,7 +418,9 @@ public class HexFormatter
return val;
}
// ---------------------------------------------------------------------------------//
public static double getSANEDouble (byte[] buffer, int offset)
// ---------------------------------------------------------------------------------//
{
long bits = 0;
for (int i = 7; i >= 0; i--)
@ -370,7 +432,9 @@ public class HexFormatter
return Double.longBitsToDouble (bits);
}
// ---------------------------------------------------------------------------------//
public static double floatValueOld (byte[] buffer, int offset)
// ---------------------------------------------------------------------------------//
{
double val = 0;
@ -396,7 +460,9 @@ public class HexFormatter
return val;
}
// ---------------------------------------------------------------------------------//
public static double floatValue (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
int exponent = buffer[ptr] & 0x7F; // biased 128
if (exponent == 0)
@ -415,7 +481,9 @@ public class HexFormatter
return negative ? rounded * -1 : rounded;
}
// ---------------------------------------------------------------------------------//
public static GregorianCalendar getAppleDate (byte[] buffer, int offset)
// ---------------------------------------------------------------------------------//
{
int date = HexFormatter.intValue (buffer[offset], buffer[offset + 1]);
if (date > 0)
@ -434,7 +502,9 @@ public class HexFormatter
return null;
}
// ---------------------------------------------------------------------------------//
public static GregorianCalendar getPascalDate (byte[] buffer, int offset)
// ---------------------------------------------------------------------------------//
{
int year = (buffer[offset + 1] & 0xFF);
int day = (buffer[offset] & 0xF0) >> 4;
@ -451,7 +521,9 @@ public class HexFormatter
return new GregorianCalendar (year, month - 1, day);
}
// ---------------------------------------------------------------------------------//
public static String getPascalString (byte[] buffer, int offset)
// ---------------------------------------------------------------------------------//
{
int length = buffer[offset] & 0xFF;
return HexFormatter.getString (buffer, offset + 1, length);

View File

@ -7,7 +7,9 @@ import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
// -----------------------------------------------------------------------------------//
public class Utility
// -----------------------------------------------------------------------------------//
{
public static final List<String> suffixes =
Arrays.asList ("po", "dsk", "do", "hdv", "2mg", "v2d", "d13", "sdk", "woz");
@ -26,25 +28,33 @@ public class Utility
// return false;
// }
// ---------------------------------------------------------------------------------//
public static boolean test (Graphics2D g)
// ---------------------------------------------------------------------------------//
{
return g.getFontRenderContext ().getTransform ()
.equals (AffineTransform.getScaleInstance (2.0, 2.0));
}
// ---------------------------------------------------------------------------------//
static int getLong (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
return getWord (buffer, ptr) + getWord (buffer, ptr + 2) * 0x10000;
}
// ---------------------------------------------------------------------------------//
static int getWord (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
int a = (buffer[ptr + 1] & 0xFF) << 8;
int b = buffer[ptr] & 0xFF;
return a + b;
}
// ---------------------------------------------------------------------------------//
public static boolean find (byte[] buffer, byte[] key)
// ---------------------------------------------------------------------------------//
{
for (int i = 0; i < buffer.length; i++)
{
@ -60,7 +70,9 @@ public class Utility
return false;
}
// ---------------------------------------------------------------------------------//
public static LocalDateTime getDateTime (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
try
{
@ -78,7 +90,9 @@ public class Utility
}
}
// ---------------------------------------------------------------------------------//
public static boolean matches (byte[] buffer, int offset, byte[] key)
// ---------------------------------------------------------------------------------//
{
int ptr = 0;
while (offset < buffer.length && ptr < key.length)
@ -88,12 +102,16 @@ public class Utility
return true;
}
// ---------------------------------------------------------------------------------//
public static int getSuffixNo (String filename)
// ---------------------------------------------------------------------------------//
{
return suffixes.indexOf (getSuffix (filename));
}
// ---------------------------------------------------------------------------------//
public static String getSuffix (String filename)
// ---------------------------------------------------------------------------------//
{
String lcFilename = filename.toLowerCase ();
@ -109,14 +127,18 @@ public class Utility
return lcFilename.substring (dotPos + 1);
}
// ---------------------------------------------------------------------------------//
public static boolean validFileType (String filename)
// ---------------------------------------------------------------------------------//
{
if (filename.startsWith (".")) // ignore invisible files
return false;
return suffixes.contains (getSuffix (filename));
}
// ---------------------------------------------------------------------------------//
public static int crc32 (byte[] buffer, int offset, int length)
// ---------------------------------------------------------------------------------//
{
int crc = 0xFFFFFFFF; // one's complement of zero
int eof = offset + length;