From 8db6489649669e349376f2bcc21cf32b2cb6db3a Mon Sep 17 00:00:00 2001 From: Denis Molony Date: Sun, 25 Apr 2021 12:08:09 +1000 Subject: [PATCH] tidying --- .../diskbrowser/prodos/CatalogEntry.java | 13 +++-- .../diskbrowser/prodos/ProdosConstants.java | 1 + .../prodos/write/DirectoryHeader.java | 9 ++-- .../diskbrowser/prodos/write/FileEntry.java | 2 +- .../diskbrowser/prodos/write/IndexBlock.java | 2 +- .../prodos/write/MasterIndexBlock.java | 2 +- .../diskbrowser/prodos/write/ProdosDisk.java | 47 +++++++++---------- .../prodos/write/SubdirectoryHeader.java | 18 ++++++- .../write/VolumeCatalogFullException.java | 9 ++++ .../bytezone/diskbrowser/utilities/NuFX.java | 6 +++ 10 files changed, 71 insertions(+), 38 deletions(-) create mode 100644 src/com/bytezone/diskbrowser/prodos/write/VolumeCatalogFullException.java diff --git a/src/com/bytezone/diskbrowser/prodos/CatalogEntry.java b/src/com/bytezone/diskbrowser/prodos/CatalogEntry.java index b1b33d9..2c479ae 100755 --- a/src/com/bytezone/diskbrowser/prodos/CatalogEntry.java +++ b/src/com/bytezone/diskbrowser/prodos/CatalogEntry.java @@ -15,16 +15,19 @@ import com.bytezone.diskbrowser.utilities.Utility; abstract class CatalogEntry implements AppleFileSource // -----------------------------------------------------------------------------------// { + Disk disk; ProdosDisk parentDisk; - DirectoryHeader parentDirectory; + String name; int storageType; + LocalDateTime created; int version; int minVersion; int access; + List dataBlocks = new ArrayList<> (); - Disk disk; + DirectoryHeader parentDirectory; // ---------------------------------------------------------------------------------// CatalogEntry (ProdosDisk parentDisk, byte[] entryBuffer) @@ -32,8 +35,10 @@ abstract class CatalogEntry implements AppleFileSource { this.parentDisk = parentDisk; this.disk = parentDisk.getDisk (); + name = HexFormatter.getString (entryBuffer, 1, entryBuffer[0] & 0x0F); storageType = (entryBuffer[0] & 0xF0) >> 4; + created = Utility.getAppleDate (entryBuffer, 24); version = entryBuffer[28] & 0xFF; minVersion = entryBuffer[29] & 0xFF; @@ -63,8 +68,8 @@ abstract class CatalogEntry implements AppleFileSource public boolean contains (DiskAddress da) // ---------------------------------------------------------------------------------// { - for (DiskAddress sector : dataBlocks) - if (sector.matches (da)) + for (DiskAddress diskAddress : dataBlocks) + if (diskAddress.matches (da)) return true; return false; } diff --git a/src/com/bytezone/diskbrowser/prodos/ProdosConstants.java b/src/com/bytezone/diskbrowser/prodos/ProdosConstants.java index f8ccc37..80367dc 100755 --- a/src/com/bytezone/diskbrowser/prodos/ProdosConstants.java +++ b/src/com/bytezone/diskbrowser/prodos/ProdosConstants.java @@ -88,6 +88,7 @@ public interface ProdosConstants "CMD", "OVL", "UD2", "UD3", "UD4", "BAT", "UD6", "UD7", // "PRG", "P16", "INT", "IVR", "BAS", "VAR", "REL", "SYS" }; + static int BLOCK_SIZE = 0x200; static int ENTRY_SIZE = 0x27; static int ENTRIES_PER_BLOCK = 0x0D; static int BLOCK_ENTRY_SIZE = ENTRY_SIZE * ENTRIES_PER_BLOCK; diff --git a/src/com/bytezone/diskbrowser/prodos/write/DirectoryHeader.java b/src/com/bytezone/diskbrowser/prodos/write/DirectoryHeader.java index 049e434..309c5b4 100644 --- a/src/com/bytezone/diskbrowser/prodos/write/DirectoryHeader.java +++ b/src/com/bytezone/diskbrowser/prodos/write/DirectoryHeader.java @@ -1,6 +1,8 @@ package com.bytezone.diskbrowser.prodos.write; -import static com.bytezone.diskbrowser.prodos.write.ProdosDisk.ENTRY_SIZE; +import static com.bytezone.diskbrowser.prodos.ProdosConstants.BLOCK_SIZE; +import static com.bytezone.diskbrowser.prodos.ProdosConstants.ENTRIES_PER_BLOCK; +import static com.bytezone.diskbrowser.prodos.ProdosConstants.ENTRY_SIZE; import static com.bytezone.diskbrowser.utilities.Utility.getAppleDate; import static com.bytezone.diskbrowser.utilities.Utility.putAppleDate; import static com.bytezone.diskbrowser.utilities.Utility.readShort; @@ -12,8 +14,6 @@ import java.time.LocalDateTime; public class DirectoryHeader // -----------------------------------------------------------------------------------// { - static final int BLOCK_SIZE = 512; - ProdosDisk disk; byte[] buffer; int ptr; @@ -25,7 +25,7 @@ public class DirectoryHeader byte minVersion = 0x00; byte access = (byte) 0xE3; byte entryLength = ENTRY_SIZE; - byte entriesPerBlock = 0x0D; + byte entriesPerBlock = ENTRIES_PER_BLOCK; int fileCount; // ---------------------------------------------------------------------------------// @@ -44,6 +44,7 @@ public class DirectoryHeader storageType = (byte) ((buffer[ptr] & 0xF0) >>> 4); int nameLength = buffer[ptr] & 0x0F; fileName = new String (buffer, ptr + 1, nameLength); + creationDate = getAppleDate (buffer, ptr + 0x18); version = buffer[ptr + 0x1C]; minVersion = buffer[ptr + 0x1D]; diff --git a/src/com/bytezone/diskbrowser/prodos/write/FileEntry.java b/src/com/bytezone/diskbrowser/prodos/write/FileEntry.java index 7c1a922..07932b2 100644 --- a/src/com/bytezone/diskbrowser/prodos/write/FileEntry.java +++ b/src/com/bytezone/diskbrowser/prodos/write/FileEntry.java @@ -1,6 +1,6 @@ package com.bytezone.diskbrowser.prodos.write; -import static com.bytezone.diskbrowser.prodos.write.ProdosDisk.BLOCK_SIZE; +import static com.bytezone.diskbrowser.prodos.ProdosConstants.BLOCK_SIZE; import static com.bytezone.diskbrowser.prodos.write.ProdosDisk.UNDERLINE; import static com.bytezone.diskbrowser.utilities.Utility.getAppleDate; import static com.bytezone.diskbrowser.utilities.Utility.putAppleDate; diff --git a/src/com/bytezone/diskbrowser/prodos/write/IndexBlock.java b/src/com/bytezone/diskbrowser/prodos/write/IndexBlock.java index 76493c8..b2ff6c1 100644 --- a/src/com/bytezone/diskbrowser/prodos/write/IndexBlock.java +++ b/src/com/bytezone/diskbrowser/prodos/write/IndexBlock.java @@ -1,6 +1,6 @@ package com.bytezone.diskbrowser.prodos.write; -import static com.bytezone.diskbrowser.prodos.write.ProdosDisk.BLOCK_SIZE; +import static com.bytezone.diskbrowser.prodos.ProdosConstants.BLOCK_SIZE; // -----------------------------------------------------------------------------------// public class IndexBlock diff --git a/src/com/bytezone/diskbrowser/prodos/write/MasterIndexBlock.java b/src/com/bytezone/diskbrowser/prodos/write/MasterIndexBlock.java index 0f3e0d9..ec4a881 100644 --- a/src/com/bytezone/diskbrowser/prodos/write/MasterIndexBlock.java +++ b/src/com/bytezone/diskbrowser/prodos/write/MasterIndexBlock.java @@ -1,6 +1,6 @@ package com.bytezone.diskbrowser.prodos.write; -import static com.bytezone.diskbrowser.prodos.write.ProdosDisk.BLOCK_SIZE; +import static com.bytezone.diskbrowser.prodos.ProdosConstants.BLOCK_SIZE; // -----------------------------------------------------------------------------------// public class MasterIndexBlock diff --git a/src/com/bytezone/diskbrowser/prodos/write/ProdosDisk.java b/src/com/bytezone/diskbrowser/prodos/write/ProdosDisk.java index 5f89273..4b34798 100644 --- a/src/com/bytezone/diskbrowser/prodos/write/ProdosDisk.java +++ b/src/com/bytezone/diskbrowser/prodos/write/ProdosDisk.java @@ -1,6 +1,8 @@ package com.bytezone.diskbrowser.prodos.write; +import static com.bytezone.diskbrowser.prodos.ProdosConstants.BLOCK_SIZE; import static com.bytezone.diskbrowser.prodos.ProdosConstants.ENTRIES_PER_BLOCK; +import static com.bytezone.diskbrowser.prodos.ProdosConstants.ENTRY_SIZE; import static com.bytezone.diskbrowser.prodos.ProdosConstants.FILE_TYPE_DIRECTORY; import static com.bytezone.diskbrowser.prodos.ProdosConstants.SUBDIRECTORY; import static com.bytezone.diskbrowser.prodos.ProdosConstants.SUBDIRECTORY_HEADER; @@ -20,9 +22,9 @@ public class ProdosDisk { static final String UNDERLINE = "------------------------------------------------\n"; - static final int BLOCK_SIZE = 512; + // static final int BLOCK_SIZE = 512; private static final int CATALOG_SIZE = 4; - static final int ENTRY_SIZE = 0x27; + // static final int ENTRY_SIZE = 0x27; private static final int BITS_PER_BLOCK = 8 * BLOCK_SIZE; static final String[] storageTypes = { "Deleted", "Seedling", "Sapling", "Tree", "", "", "", "", "", "", "", "", "", @@ -117,7 +119,8 @@ public class ProdosDisk // ---------------------------------------------------------------------------------// public FileEntry addFile (String path, byte type, int auxType, LocalDateTime created, - LocalDateTime modified, byte[] dataBuffer) throws DiskFullException + LocalDateTime modified, byte[] dataBuffer) + throws DiskFullException, VolumeCatalogFullException // ---------------------------------------------------------------------------------// { // split the full path into an array of subdirectories and a file name @@ -233,7 +236,8 @@ public class ProdosDisk } // ---------------------------------------------------------------------------------// - private FileEntry createSubdirectory (int blockNo, String name) throws DiskFullException + private FileEntry createSubdirectory (int blockNo, String name) + throws DiskFullException, VolumeCatalogFullException // ---------------------------------------------------------------------------------// { FileEntry fileEntry = findFreeSlot (blockNo); @@ -296,7 +300,7 @@ public class ProdosDisk int allocateNextBlock () throws DiskFullException // ---------------------------------------------------------------------------------// { - int nextBlock = getFreeBlock (); + int nextBlock = volumeBitMap.nextSetBit (0); if (nextBlock < 0) throw new DiskFullException ("Disk Full"); @@ -306,17 +310,15 @@ public class ProdosDisk } // ---------------------------------------------------------------------------------// - private int getFreeBlock () + private FileEntry findFreeSlot (int blockNo) + throws DiskFullException, VolumeCatalogFullException // ---------------------------------------------------------------------------------// { - return volumeBitMap.nextSetBit (0); - } + // check for Volume Directory Header full + if (blockNo == 2 && volumeDirectoryHeader.fileCount == 51) + throw new VolumeCatalogFullException ("Volume Directory is full"); // stupid - // ---------------------------------------------------------------------------------// - private FileEntry findFreeSlot (int blockNo) throws DiskFullException - // ---------------------------------------------------------------------------------// - { - // get the subdirectory header before the blockNo possibly changes + // get the subdirectory header before the blockNo can change SubdirectoryHeader subdirectoryHeader = subdirectoryHeaders.get (blockNo); int lastBlockNo = 0; // used for linking directory blocks @@ -338,27 +340,20 @@ public class ProdosDisk blockNo = readShort (buffer, offset + 2); // next block } while (blockNo > 0); + if (subdirectoryHeader == null) // this should be impossible + throw new VolumeCatalogFullException ("Volume Directory is full"); + // no free slots, so add a new catalog block blockNo = allocateNextBlock (); - // update file entry size (if not the Volume Directory) - if (subdirectoryHeader != null) - { - FileEntry fileEntry = - new FileEntry (this, buffer, subdirectoryHeader.parentPointer * BLOCK_SIZE - + (subdirectoryHeader.parentEntry - 1) * ENTRY_SIZE + 4); - fileEntry.read (); - fileEntry.blocksUsed++; - fileEntry.eof += BLOCK_SIZE; - fileEntry.modifiedDate = LocalDateTime.now (); - fileEntry.write (); - } - // update links int ptr = blockNo * BLOCK_SIZE; writeShort (buffer, lastBlockNo * BLOCK_SIZE + 2, blockNo); // point to next block writeShort (buffer, ptr, lastBlockNo); // point to previous block + // update parent's file entry size (this is the subdirectory file entry + subdirectoryHeader.updateParentFileEntry (); + return new FileEntry (this, buffer, ptr + 4); // first slot in new block } diff --git a/src/com/bytezone/diskbrowser/prodos/write/SubdirectoryHeader.java b/src/com/bytezone/diskbrowser/prodos/write/SubdirectoryHeader.java index bd115d6..ad900d2 100644 --- a/src/com/bytezone/diskbrowser/prodos/write/SubdirectoryHeader.java +++ b/src/com/bytezone/diskbrowser/prodos/write/SubdirectoryHeader.java @@ -1,10 +1,13 @@ package com.bytezone.diskbrowser.prodos.write; -import static com.bytezone.diskbrowser.prodos.write.ProdosDisk.ENTRY_SIZE; +import static com.bytezone.diskbrowser.prodos.ProdosConstants.BLOCK_SIZE; +import static com.bytezone.diskbrowser.prodos.ProdosConstants.ENTRY_SIZE; import static com.bytezone.diskbrowser.prodos.write.ProdosDisk.UNDERLINE; import static com.bytezone.diskbrowser.utilities.Utility.readShort; import static com.bytezone.diskbrowser.utilities.Utility.writeShort; +import java.time.LocalDateTime; + // -----------------------------------------------------------------------------------// public class SubdirectoryHeader extends DirectoryHeader // -----------------------------------------------------------------------------------// @@ -23,6 +26,19 @@ public class SubdirectoryHeader extends DirectoryHeader access = (byte) 0xC3; } + // ---------------------------------------------------------------------------------// + void updateParentFileEntry () + // ---------------------------------------------------------------------------------// + { + FileEntry fileEntry = new FileEntry (disk, buffer, + parentPointer * BLOCK_SIZE + (parentEntry - 1) * ENTRY_SIZE + 4); + fileEntry.read (); + fileEntry.blocksUsed++; + fileEntry.eof += BLOCK_SIZE; + fileEntry.modifiedDate = LocalDateTime.now (); + fileEntry.write (); + } + // ---------------------------------------------------------------------------------// @Override void read () diff --git a/src/com/bytezone/diskbrowser/prodos/write/VolumeCatalogFullException.java b/src/com/bytezone/diskbrowser/prodos/write/VolumeCatalogFullException.java new file mode 100644 index 0000000..2a672a1 --- /dev/null +++ b/src/com/bytezone/diskbrowser/prodos/write/VolumeCatalogFullException.java @@ -0,0 +1,9 @@ +package com.bytezone.diskbrowser.prodos.write; + +public class VolumeCatalogFullException extends Exception +{ + public VolumeCatalogFullException (String message) + { + super (message); + } +} diff --git a/src/com/bytezone/diskbrowser/utilities/NuFX.java b/src/com/bytezone/diskbrowser/utilities/NuFX.java index 8996cea..c5526b4 100644 --- a/src/com/bytezone/diskbrowser/utilities/NuFX.java +++ b/src/com/bytezone/diskbrowser/utilities/NuFX.java @@ -10,6 +10,7 @@ import java.util.List; import com.bytezone.diskbrowser.prodos.write.DiskFullException; import com.bytezone.diskbrowser.prodos.write.FileEntry; import com.bytezone.diskbrowser.prodos.write.ProdosDisk; +import com.bytezone.diskbrowser.prodos.write.VolumeCatalogFullException; // -----------------------------------------------------------------------------------// public class NuFX @@ -152,6 +153,11 @@ public class NuFX { System.out.println ("disk full: " + diskSize); // go round again } + catch (VolumeCatalogFullException e) + { + e.printStackTrace (); + return null; + } } }