This commit is contained in:
Denis Molony 2021-04-25 12:08:09 +10:00
parent e135b65948
commit 8db6489649
10 changed files with 71 additions and 38 deletions

View File

@ -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<DiskAddress> 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;
}

View File

@ -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;

View File

@ -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];

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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 ()

View File

@ -0,0 +1,9 @@
package com.bytezone.diskbrowser.prodos.write;
public class VolumeCatalogFullException extends Exception
{
public VolumeCatalogFullException (String message)
{
super (message);
}
}

View File

@ -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;
}
}
}