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

View File

@ -39,10 +39,11 @@ public class Charset extends CharacterList
{ {
DataBuffer dataBuffer = image.getRaster ().getDataBuffer (); DataBuffer dataBuffer = image.getRaster ().getDataBuffer ();
int element = 0; 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++) for (int j = 0; j < sizeX; j++)
{ {
dataBuffer.setElem (element++, (value & 0x01) == 0 ? 0 : 0xFF); dataBuffer.setElem (element++, (value & 0x01) == 0 ? 0 : 0xFF);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,24 +1,31 @@
package com.bytezone.diskbrowser.prodos; package com.bytezone.diskbrowser.prodos;
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 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, public ProdosDirectory (FormattedDisk parent, String name, byte[] buffer,
int totalBlocks, int freeBlocks, int usedBlocks) int totalBlocks, int freeBlocks, int usedBlocks)
// ---------------------------------------------------------------------------------//
{ {
super (name, buffer); super (name, buffer);
@ -28,8 +35,10 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
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);
@ -65,13 +74,12 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
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
: parentFD.sdf.format (created.getTime ()).toUpperCase ().replace (".", ""); : sdf.format (created.getTime ()).toUpperCase ().replace (".", "");
String timeC = created == null ? "" : parentFD.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 : parentFD.sdf String dateM = modified == null ? NO_DATE
.format (modified.getTime ()).toUpperCase ().replace (".", ""); : sdf.format (modified.getTime ()).toUpperCase ().replace (".", "");
String timeM = String timeM = modified == null ? "" : stf.format (modified.getTime ());
modified == null ? "" : parentFD.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;
@ -117,7 +125,9 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
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)

View File

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

View File

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

View File

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