Sort Prodos folders

This commit is contained in:
Denis Molony 2019-09-13 15:32:35 +10:00
parent b7f9b73643
commit 1c53b291dd
9 changed files with 178 additions and 61 deletions

View File

@ -159,7 +159,7 @@ public class SHRPictureFile2 extends HiResImage
break;
default:
System.out.println ("PIC unknown aux " + auxType);
System.out.printf ("PIC unknown aux: %04X%n ", auxType);
failureReason = "unknown PIC aux";
}
}

View File

@ -81,6 +81,8 @@ public class AppleDisk implements Disk
private ActionListener actionListenerList;
private List<DiskAddress> blockList;
private WozFile wozFile;
private final boolean debug = false;
public AppleDisk (File file, int tracks, int sectors) throws FileFormatException
@ -243,6 +245,7 @@ public class AppleDisk implements Disk
public AppleDisk (WozFile wozFile, int tracks, int sectors)
{
this.wozFile = wozFile;
this.tracks = tracks;
this.sectors = sectors;
file = wozFile.file;
@ -654,15 +657,21 @@ public class AppleDisk implements Disk
if (path.startsWith (home))
path = "~" + path.substring (home.length ());
text.append (String.format ("Path............ %s%n", path));
text.append (String.format ("File name....... %s%n", file.getName ()));
text.append (String.format ("File size....... %,d%n", file.length ()));
text.append (String.format ("Tracks.......... %d%n", tracks));
text.append (String.format ("Sectors......... %d%n", sectors));
text.append (String.format ("Blocks.......... %,d%n", blocks));
text.append (String.format ("Track size...... %,d%n", trackSize));
text.append (String.format ("Sector size..... %d%n", sectorSize));
text.append (String.format ("Interleave...... %d", interleave));
text.append (String.format ("Path................. %s%n", path));
text.append (String.format ("File name............ %s%n", file.getName ()));
text.append (String.format ("File size............ %,d%n", file.length ()));
text.append (String.format ("Tracks............... %d%n", tracks));
text.append (String.format ("Sectors.............. %d%n", sectors));
text.append (String.format ("Blocks............... %,d%n", blocks));
text.append (String.format ("Track size........... %,d%n", trackSize));
text.append (String.format ("Sector size.......... %d%n", sectorSize));
text.append (String.format ("Interleave........... %d", interleave));
if (wozFile != null)
{
text.append ("\n\n");
text.append (wozFile);
}
return text.toString ();
}

View File

@ -2,8 +2,8 @@ package com.bytezone.diskbrowser.gui;
/***********************************************************************************************
* Contains a single instance of FileSystemTab, and any number of AppleDiskTab instances.
*
*
*
*
***********************************************************************************************/
import java.awt.Dimension;
@ -50,7 +50,6 @@ class CatalogPanel extends JTabbedPane
private Font font;
private FileSystemTab fileTab;
private final List<AppleDiskTab> diskTabs = new ArrayList<AppleDiskTab> ();
// private final DocumentCreatorFactory lister;
private final DiskAndFileSelector selector = new DiskAndFileSelector ();
private final RedoHandler redoHandler;
private CloseTabAction closeTabAction;
@ -390,7 +389,7 @@ class CatalogPanel extends JTabbedPane
// if (evt.getKey ().equals (PreferencesDialog.prefsCatalogFont))
// font = new Font (evt.getNewValue (), Font.PLAIN, font.getSize ());
// if (evt.getKey ().equals (PreferencesDialog.prefsCatalogFontSize))
// font = new Font (font.getFontName (),
// font = new Font (font.getFontName (),
// Font.PLAIN, Integer.parseInt (evt.getNewValue ()));
// if (fileTab != null)
// fileTab.setTreeFont (font);

View File

@ -24,6 +24,7 @@ class DataPanel extends JTabbedPane
AssemblerPreferencesListener
{
private static final int TEXT_WIDTH = 65;
private static final int BACKGROUND = 245;
JTextArea hexText;
JTextArea disassemblyText;
@ -70,6 +71,9 @@ class DataPanel extends JTabbedPane
imagePane =
new JScrollPane (imagePanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
imagePane.setBorder (null);
imagePane.getVerticalScrollBar ().setUnitIncrement (50);
imagePane.getHorizontalScrollBar ().setUnitIncrement (25);
@ -321,7 +325,7 @@ class DataPanel extends JTabbedPane
public ImagePanel ()
{
this.setBackground (Color.gray);
this.setBackground (new Color (BACKGROUND, BACKGROUND, BACKGROUND));
}
private void setImage (BufferedImage image)

View File

@ -30,10 +30,10 @@ class FileSystemTab extends AbstractTab
{
File rootFolder;
public FileSystemTab (File folder, DiskAndFileSelector selector, RedoHandler navMan,
public FileSystemTab (File folder, DiskAndFileSelector selector, RedoHandler redoHandler,
Font font, DiskSelectedEvent diskEvent)
{
super (navMan, selector, font);
super (redoHandler, selector, font);
this.rootFolder = folder;
TreeBuilder tb = new TreeBuilder (folder);
@ -52,7 +52,7 @@ class FileSystemTab extends AbstractTab
}
if (diskEvent != null)
navMan.diskSelected (diskEvent);
redoHandler.diskSelected (diskEvent);
else
System.out.println ("No disk event");
}

View File

@ -1,7 +1,7 @@
package com.bytezone.diskbrowser.nib;
// -----------------------------------------------------------------------------------//
public class DiskReaderGCR extends DiskReader
class DiskReaderGCR extends DiskReader
// -----------------------------------------------------------------------------------//
{
static final int TAG_SIZE = 12;
@ -26,7 +26,7 @@ public class DiskReaderGCR extends DiskReader
// decode four disk bytes into three data bytes (174 * 3 + 2 = 524)
while (true)
{
// ROL checksum
// ROL checksum (also keep left-shifted hi bit)
checksums[2] = (checksums[2] & 0xFF) << 1; // shift left
if ((checksums[2] > 0xFF)) // check for overflow
++checksums[2]; // set bit 0
@ -64,29 +64,29 @@ public class DiskReaderGCR extends DiskReader
byte b2 = (byte) (d2 | (d3 << 6));
// compare disk checksums with calculated checksums
if ((checksums[0] & 0xFF) != (b0 & 0xFF) //
|| (checksums[1] & 0xFF) != (b1 & 0xFF) //
|| (checksums[2] & 0xFF) != (b2 & 0xFF))
if ((byte) (checksums[0] & 0xFF) != b0 //
|| (byte) (checksums[1] & 0xFF) != b1 //
|| (byte) (checksums[2] & 0xFF) != b2)
throw new DiskNibbleException ("Checksum failed");
return outBuffer;
}
// ---------------------------------------------------------------------------------//
private byte checksum (byte diskByte, int[] checksums, int a)
private byte checksum (byte diskByte, int[] checksums, int current)
// ---------------------------------------------------------------------------------//
{
int b = (a + 2) % 3;
int val = (diskByte ^ checksums[b]) & 0xFF;
checksums[a] += val; // prepare next checksum
int prev = (current + 2) % 3;
int val = (diskByte ^ checksums[prev]) & 0xFF;
checksums[current] += val; // add to this checksum
if (checksums[b] > 0xFF) // is there a carry?
if (checksums[prev] > 0xFF) // was there a carry last time?
{
++checksums[a]; // pass it on
checksums[b] &= 0xFF; // back to 8 bits
++checksums[current]; // add it to this checksum
checksums[prev] &= 0xFF; // reset previous carry
}
return (byte) val; // converted data byte
return (byte) val; // converted data byte
}
// ---------------------------------------------------------------------------------//

View File

@ -36,6 +36,7 @@ public class WozFile
public final File file;
private Info info;
private Meta meta;
private int diskSectors;
private byte[] addressPrologue;
@ -70,6 +71,8 @@ public class WozFile
int ptr = 12;
while (ptr < buffer.length)
{
validateChunk (buffer, ptr);
String chunkId = new String (buffer, ptr, 4);
int size = val32 (buffer, ptr + 4);
if (debug1)
@ -80,7 +83,7 @@ public class WozFile
case "INFO": // 60 bytes
info = new Info (buffer, ptr);
if (info.wozVersion >= 2)
setSectors (info.bootSectorFormat == 2 ? 13 : 16);
setPrologue (info.bootSectorFormat == 2 ? 13 : 16);
break;
case "TMAP": // 160 bytes
tmap (buffer, ptr);
@ -89,7 +92,7 @@ public class WozFile
tracks = trks (buffer, ptr);
break;
case "META":
meta (buffer, ptr, size);
meta = new Meta (buffer, ptr, size);
break;
case "WRIT":
break;
@ -124,6 +127,33 @@ public class WozFile
}
}
// ---------------------------------------------------------------------------------//
private boolean validateChunk (byte[] buffer, int ptr) throws DiskNibbleException
// ---------------------------------------------------------------------------------//
{
int size = val32 (buffer, ptr + 4);
if (size <= 0 || size + ptr + 8 > buffer.length)
{
if (info != null)
System.out.println (info);
throw new DiskNibbleException (String.format ("Invalid chunk size: %08X%n", size));
}
for (int i = 0; i < 4; i++)
{
int val = buffer[ptr + i] & 0xFF;
if (val < 'A' || val > 'Z') // not uppercase ascii
{
if (info != null)
System.out.println (info);
throw new DiskNibbleException (
String.format ("Invalid chunk name character: %02X%n", val));
}
}
return true;
}
// ---------------------------------------------------------------------------------//
public byte[] getDiskBuffer ()
// ---------------------------------------------------------------------------------//
@ -160,7 +190,7 @@ public class WozFile
}
// ---------------------------------------------------------------------------------//
private void setSectors (int diskSectors)
private void setPrologue (int diskSectors)
// ---------------------------------------------------------------------------------//
{
this.diskSectors = diskSectors;
@ -174,27 +204,6 @@ public class WozFile
ptr += 8;
}
// ---------------------------------------------------------------------------------//
private void meta (byte[] buffer, int ptr, int length)
// ---------------------------------------------------------------------------------//
{
ptr += 8;
if (debug1)
{
String metaData = new String (buffer, ptr, length);
String[] chunks = metaData.split ("\n");
for (String chunk : chunks)
{
String[] parts = chunk.split ("\t");
if (parts.length >= 2)
System.out.printf ("%-20s %s%n", parts[0], parts[1]);
else
System.out.printf ("%-20s%n", parts[0]);
}
}
}
// ---------------------------------------------------------------------------------//
private List<Track> trks (byte[] rawBuffer, int ptr)
// ---------------------------------------------------------------------------------//
@ -274,6 +283,16 @@ public class WozFile
}
}
// ---------------------------------------------------------------------------------//
@Override
public String toString ()
// ---------------------------------------------------------------------------------//
{
if (meta != null)
return info.toString () + "\n\n" + meta.toString ();
return info.toString ();
}
// ---------------------------------------------------------------------------------//
public static void main (String[] args)
// ---------------------------------------------------------------------------------//
@ -314,7 +333,9 @@ public class WozFile
int requiredRam;
int largestTrack;
// ---------------------------------------------------------------------------------//
Info (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
{
wozVersion = val8 (buffer, ptr + 8);
@ -343,7 +364,7 @@ public class WozFile
public String toString ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
StringBuilder text = new StringBuilder ("WOZ info:\n\n");
String diskTypeText = diskType == 1 ? "5.25" : "3.5";
@ -374,6 +395,46 @@ public class WozFile
}
}
// -----------------------------------------------------------------------------------//
class Meta
// -----------------------------------------------------------------------------------//
{
List<String> lines = new ArrayList<> ();
// ---------------------------------------------------------------------------------//
Meta (byte[] buffer, int ptr, int length)
// ---------------------------------------------------------------------------------//
{
String dots = " ......................";
String metaData = new String (buffer, ptr + 8, length);
String[] chunks = metaData.split ("\n");
for (String chunk : chunks)
{
String[] parts = chunk.split ("\t");
if (parts.length >= 2)
lines.add (String.format ("%-21.21s %s", parts[0] + dots, parts[1]));
else
lines.add (String.format ("%-21.21s", parts[0] + dots));
}
}
// ---------------------------------------------------------------------------------//
@Override
public String toString ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ("WOZ meta:\n\n");
for (String line : lines)
text.append (String.format ("%s%n", line));
if (text.length () > 0)
text.deleteCharAt (text.length () - 1);
return text.toString ();
}
}
// -----------------------------------------------------------------------------------//
class Track implements Iterable<Sector>
// -----------------------------------------------------------------------------------//
@ -428,9 +489,9 @@ public class WozFile
if (addressPrologue == null) // WOZ1
if (findNext (address16prologue, ptr) > 0)
setSectors (16);
setPrologue (16);
else if (findNext (address13prologue, ptr) > 0)
setSectors (13);
setPrologue (13);
else
throw new DiskNibbleException ("No address prologue found");

View File

@ -100,7 +100,7 @@ class FileEntry extends CatalogEntry implements ProdosConstants
{
int storageType = buffer2[i] & 0x0F;
int keyBlock = HexFormatter.unsignedShort (buffer2, i + 1);
// int eof = HexFormatter.intValue (buffer2[i + 3], buffer2[i + 4], buffer2[i + 5]);
int eof = HexFormatter.intValue (buffer2[i + 3], buffer2[i + 4], buffer2[i + 5]);
addDataBlocks (storageType, keyBlock);
}
}
@ -265,7 +265,7 @@ class FileEntry extends CatalogEntry implements ProdosConstants
else if (endOfFile == 0x4000 && auxType == 0x4000)
file = new DoubleHiResImage (name, exactBuffer);
else if (oneOf (endOfFile, 0x1FF8, 0x1FFF, 0x2000, 0x4000)
&& oneOf (auxType, 0x1FFF, 0x2000, 0x4000))
&& oneOf (auxType, 0x1FFF, 0x2000, 0x4000, 0x6000))
file = new OriginalHiResImage (name, exactBuffer, auxType);
else if (endOfFile == 38400 && name.startsWith ("LVL."))
file = new LodeRunner (name, exactBuffer);

View File

@ -7,6 +7,7 @@ import java.util.ArrayList;
import java.util.List;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import com.bytezone.diskbrowser.applefile.AppleFileSource;
import com.bytezone.diskbrowser.applefile.BootSector;
@ -31,6 +32,7 @@ public class ProdosDisk extends AbstractFormattedDisk
private final List<DirectoryHeader> headerEntries = new ArrayList<DirectoryHeader> ();
protected VolumeDirectoryHeader vdh;
private final DefaultMutableTreeNode volumeNode;
private static final boolean debug = false;
@ -56,7 +58,7 @@ public class ProdosDisk extends AbstractFormattedDisk
bootSector = new BootSector (disk, buffer, "Prodos", da);
DefaultMutableTreeNode root = getCatalogTreeRoot ();
DefaultMutableTreeNode volumeNode = new DefaultMutableTreeNode ("empty volume node");
volumeNode = new DefaultMutableTreeNode ("empty volume node");
root.add (volumeNode);
processDirectoryBlock (2, null, volumeNode);
@ -73,6 +75,48 @@ public class ProdosDisk extends AbstractFormattedDisk
else if (stillAvailable (da2))
falseNegatives++;
}
sort (volumeNode);
((DefaultTreeModel) catalogTree.getModel ()).reload ();
}
public void sort (DefaultMutableTreeNode node)
{
for (int base = 0; base < node.getChildCount (); base++)
{
DefaultMutableTreeNode baseNode = (DefaultMutableTreeNode) node.getChildAt (base);
if (!baseNode.isLeaf ())
{
sort (baseNode);
continue;
}
String childName = ((FileEntry) baseNode.getUserObject ()).name;
DefaultMutableTreeNode smallestNode = null;
String smallestName = childName;
int smallestPos = -1;
for (int j = base + 1; j < node.getChildCount (); j++)
{
DefaultMutableTreeNode compareNode = (DefaultMutableTreeNode) node.getChildAt (j);
if (!compareNode.isLeaf ())
continue;
String compareName = ((FileEntry) compareNode.getUserObject ()).name;
if (smallestName.compareToIgnoreCase (compareName) > 0)
{
smallestNode = compareNode;
smallestName = compareName;
smallestPos = j;
}
}
if (smallestNode != null)
{
node.insert (baseNode, smallestPos);
node.insert (smallestNode, base);
}
}
}
private void processDirectoryBlock (int block, FileEntry parent,