mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2024-11-29 11:49:29 +00:00
Created FileWriter
This commit is contained in:
parent
39269d3b27
commit
032da321c3
@ -175,6 +175,7 @@ public class DiskFactory
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
System.out.println (e.getMessage ());
|
||||||
System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ());
|
System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
107
src/com/bytezone/diskbrowser/prodos/write/ExtendedKeyBlock.java
Normal file
107
src/com/bytezone/diskbrowser/prodos/write/ExtendedKeyBlock.java
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package com.bytezone.diskbrowser.prodos.write;
|
||||||
|
|
||||||
|
import com.bytezone.diskbrowser.utilities.Utility;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
|
public class ExtendedKeyBlock
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
private final ProdosDisk disk;
|
||||||
|
private final byte[] buffer;
|
||||||
|
private final int ptr;
|
||||||
|
|
||||||
|
// int blockNo;
|
||||||
|
|
||||||
|
MiniEntry dataFork;
|
||||||
|
MiniEntry resourceFork;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
public ExtendedKeyBlock (ProdosDisk disk, byte[] buffer, int ptr)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
this.disk = disk;
|
||||||
|
this.buffer = buffer;
|
||||||
|
this.ptr = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
void addMiniEntry (int type, byte storageType, int keyBlock, int blocksUsed, int eof)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
MiniEntry miniEntry = new MiniEntry (storageType, keyBlock, blocksUsed, eof);
|
||||||
|
|
||||||
|
if (type == 1) // enum??
|
||||||
|
dataFork = miniEntry;
|
||||||
|
else
|
||||||
|
resourceFork = miniEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
void read (byte[] buffer)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
if (buffer[ptr] != 0)
|
||||||
|
dataFork = new MiniEntry (buffer, 0);
|
||||||
|
|
||||||
|
if (buffer[ptr + 0x100] != 0)
|
||||||
|
resourceFork = new MiniEntry (buffer, 0x100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
void write ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
if (dataFork != null) // else zero buffer??
|
||||||
|
dataFork.write (buffer, ptr);
|
||||||
|
|
||||||
|
if (resourceFork != null)
|
||||||
|
resourceFork.write (buffer, ptr + 0x100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
class MiniEntry
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
byte storageType; // uses low nibble
|
||||||
|
int keyBlock;
|
||||||
|
int blocksUsed;
|
||||||
|
int eof;
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------//
|
||||||
|
MiniEntry (byte[] buffer, int ptr)
|
||||||
|
// -------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
read (buffer, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------//
|
||||||
|
MiniEntry (byte storageType, int keyBlock, int blocksUsed, int eof)
|
||||||
|
// -------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
this.storageType = storageType;
|
||||||
|
this.keyBlock = keyBlock;
|
||||||
|
this.blocksUsed = blocksUsed;
|
||||||
|
this.eof = eof;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------//
|
||||||
|
void read (byte[] buffer, int ptr)
|
||||||
|
// -------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
storageType = buffer[ptr];
|
||||||
|
keyBlock = Utility.readShort (buffer, ptr + 1);
|
||||||
|
blocksUsed = Utility.readShort (buffer, ptr + 3);
|
||||||
|
eof = Utility.readTriple (buffer, ptr + 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------//
|
||||||
|
void write (byte[] buffer, int ptr)
|
||||||
|
// -------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
buffer[ptr] = storageType;
|
||||||
|
Utility.writeShort (buffer, ptr + 1, keyBlock);
|
||||||
|
Utility.writeShort (buffer, ptr + 3, blocksUsed);
|
||||||
|
Utility.writeTriple (buffer, ptr + 5, eof);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,9 +2,6 @@ package com.bytezone.diskbrowser.prodos.write;
|
|||||||
|
|
||||||
import static com.bytezone.diskbrowser.prodos.ProdosConstants.BLOCK_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.ProdosConstants.ENTRY_SIZE;
|
||||||
import static com.bytezone.diskbrowser.prodos.ProdosConstants.SAPLING;
|
|
||||||
import static com.bytezone.diskbrowser.prodos.ProdosConstants.SEEDLING;
|
|
||||||
import static com.bytezone.diskbrowser.prodos.ProdosConstants.TREE;
|
|
||||||
import static com.bytezone.diskbrowser.prodos.write.ProdosDisk.UNDERLINE;
|
import static com.bytezone.diskbrowser.prodos.write.ProdosDisk.UNDERLINE;
|
||||||
import static com.bytezone.diskbrowser.utilities.Utility.getAppleDate;
|
import static com.bytezone.diskbrowser.utilities.Utility.getAppleDate;
|
||||||
import static com.bytezone.diskbrowser.utilities.Utility.putAppleDate;
|
import static com.bytezone.diskbrowser.utilities.Utility.putAppleDate;
|
||||||
@ -37,9 +34,6 @@ public class FileEntry
|
|||||||
int auxType;
|
int auxType;
|
||||||
int headerPointer;
|
int headerPointer;
|
||||||
|
|
||||||
private IndexBlock indexBlock = null;
|
|
||||||
private MasterIndexBlock masterIndexBlock = null;
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
public FileEntry (ProdosDisk disk, byte[] buffer, int ptr)
|
public FileEntry (ProdosDisk disk, byte[] buffer, int ptr)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@ -112,203 +106,6 @@ public class FileEntry
|
|||||||
writeShort (buffer, ptr + 0x25, headerPointer);
|
writeShort (buffer, ptr + 0x25, headerPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
void writeFile (byte[] dataBuffer) throws DiskFullException
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
this.eof = dataBuffer.length;
|
|
||||||
|
|
||||||
int dataPtr = 0;
|
|
||||||
int remaining = eof;
|
|
||||||
|
|
||||||
while (dataPtr < eof)
|
|
||||||
{
|
|
||||||
int actualBlockNo = allocateNextBlock ();
|
|
||||||
map (dataPtr / BLOCK_SIZE, actualBlockNo);
|
|
||||||
|
|
||||||
int bufferPtr = actualBlockNo * BLOCK_SIZE;
|
|
||||||
int tfr = Math.min (remaining, BLOCK_SIZE);
|
|
||||||
|
|
||||||
System.arraycopy (dataBuffer, dataPtr, buffer, bufferPtr, tfr);
|
|
||||||
|
|
||||||
dataPtr += BLOCK_SIZE;
|
|
||||||
remaining -= BLOCK_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeIndices ();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
void writeRecord (int recordNo, byte[] dataBuffer) throws DiskFullException
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
assert auxType > 0; // record length
|
|
||||||
|
|
||||||
int destPtr = auxType * recordNo;
|
|
||||||
int remaining = Math.min (auxType, dataBuffer.length);
|
|
||||||
int max = destPtr + remaining;
|
|
||||||
int dataPtr = 0;
|
|
||||||
|
|
||||||
if (eof < max)
|
|
||||||
eof = max;
|
|
||||||
|
|
||||||
while (destPtr < max)
|
|
||||||
{
|
|
||||||
int logicalBlockNo = destPtr / BLOCK_SIZE;
|
|
||||||
int blockOffset = destPtr % BLOCK_SIZE;
|
|
||||||
int tfr = Math.min (BLOCK_SIZE - blockOffset, remaining);
|
|
||||||
|
|
||||||
int actualBlockNo = getActualBlockNo (logicalBlockNo);
|
|
||||||
int bufferPtr = actualBlockNo * BLOCK_SIZE + blockOffset;
|
|
||||||
|
|
||||||
System.arraycopy (dataBuffer, dataPtr, buffer, bufferPtr, tfr);
|
|
||||||
|
|
||||||
// System.out.printf ("%7d %5d %5d %5d%n", destPtr, tfr, logicalBlockNo,
|
|
||||||
// blockOffset);
|
|
||||||
|
|
||||||
destPtr += tfr;
|
|
||||||
dataPtr += tfr;
|
|
||||||
remaining -= tfr;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeIndices ();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
int allocateNextBlock () throws DiskFullException
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
blocksUsed++;
|
|
||||||
return disk.allocateNextBlock ();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
int getActualBlockNo (int logicalBlockNo) throws DiskFullException
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
int actualBlockNo = 0;
|
|
||||||
|
|
||||||
switch (storageType)
|
|
||||||
{
|
|
||||||
case TREE:
|
|
||||||
actualBlockNo =
|
|
||||||
masterIndexBlock.get (logicalBlockNo / 256).get (logicalBlockNo % 256);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SAPLING:
|
|
||||||
if (logicalBlockNo < 256)
|
|
||||||
actualBlockNo = indexBlock.get (logicalBlockNo);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SEEDLING:
|
|
||||||
if (logicalBlockNo == 0)
|
|
||||||
actualBlockNo = keyPointer;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actualBlockNo == 0)
|
|
||||||
{
|
|
||||||
actualBlockNo = allocateNextBlock ();
|
|
||||||
map (logicalBlockNo, actualBlockNo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return actualBlockNo;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void writeIndices ()
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
if (storageType == TREE)
|
|
||||||
masterIndexBlock.write (buffer);
|
|
||||||
else if (storageType == SAPLING)
|
|
||||||
indexBlock.write (buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
void map (int logicalBlockNo, int actualBlockNo) throws DiskFullException
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
if (logicalBlockNo > 255) // potential TREE
|
|
||||||
{
|
|
||||||
if (storageType != TREE)
|
|
||||||
{
|
|
||||||
masterIndexBlock = new MasterIndexBlock (allocateNextBlock ());
|
|
||||||
|
|
||||||
if (storageType == SAPLING) // sapling -> tree
|
|
||||||
{
|
|
||||||
masterIndexBlock.set (0, indexBlock);
|
|
||||||
}
|
|
||||||
else if (storageType == SEEDLING) // seedling -> sapling -> tree
|
|
||||||
{
|
|
||||||
indexBlock = new IndexBlock (allocateNextBlock ());
|
|
||||||
indexBlock.set (0, keyPointer);
|
|
||||||
masterIndexBlock.set (0, indexBlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
keyPointer = masterIndexBlock.blockNo;
|
|
||||||
storageType = TREE;
|
|
||||||
indexBlock = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
getIndexBlock (logicalBlockNo / 256).set (logicalBlockNo % 256, actualBlockNo);
|
|
||||||
}
|
|
||||||
else if (logicalBlockNo > 0) // potential SAPLING
|
|
||||||
{
|
|
||||||
if (storageType == TREE) // already a tree
|
|
||||||
{
|
|
||||||
getIndexBlock (0).set (logicalBlockNo, actualBlockNo);
|
|
||||||
}
|
|
||||||
else if (storageType == SAPLING) // already a sapling
|
|
||||||
{
|
|
||||||
indexBlock.set (logicalBlockNo, actualBlockNo);
|
|
||||||
}
|
|
||||||
else // new file or already a seedling
|
|
||||||
{
|
|
||||||
indexBlock = new IndexBlock (allocateNextBlock ());
|
|
||||||
if (storageType == SEEDLING) // seedling -> sapling
|
|
||||||
indexBlock.set (0, keyPointer);
|
|
||||||
|
|
||||||
keyPointer = indexBlock.blockNo;
|
|
||||||
storageType = SAPLING;
|
|
||||||
indexBlock.set (logicalBlockNo, actualBlockNo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (logicalBlockNo == 0) // potential SEEDLING
|
|
||||||
{
|
|
||||||
if (storageType == TREE) // already a tree
|
|
||||||
{
|
|
||||||
getIndexBlock (0).set (0, actualBlockNo);
|
|
||||||
}
|
|
||||||
else if (storageType == SAPLING) // already a sapling
|
|
||||||
{
|
|
||||||
indexBlock.set (0, actualBlockNo);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
keyPointer = actualBlockNo;
|
|
||||||
storageType = SEEDLING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
System.out.println ("Error");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
IndexBlock getIndexBlock (int position) throws DiskFullException
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
IndexBlock indexBlock = masterIndexBlock.get (position);
|
|
||||||
|
|
||||||
if (indexBlock == null)
|
|
||||||
{
|
|
||||||
indexBlock = new IndexBlock (allocateNextBlock ());
|
|
||||||
masterIndexBlock.set (position, indexBlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
return indexBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
String toText ()
|
String toText ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
225
src/com/bytezone/diskbrowser/prodos/write/FileWriter.java
Normal file
225
src/com/bytezone/diskbrowser/prodos/write/FileWriter.java
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
package com.bytezone.diskbrowser.prodos.write;
|
||||||
|
|
||||||
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.BLOCK_SIZE;
|
||||||
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.SAPLING;
|
||||||
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.SEEDLING;
|
||||||
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.TREE;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
|
public class FileWriter
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
private final ProdosDisk disk;
|
||||||
|
private final byte[] buffer;
|
||||||
|
|
||||||
|
private IndexBlock indexBlock = null;
|
||||||
|
private MasterIndexBlock masterIndexBlock = null;
|
||||||
|
|
||||||
|
byte storageType;
|
||||||
|
int keyPointer;
|
||||||
|
int blocksUsed;
|
||||||
|
int eof;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
FileWriter (ProdosDisk disk, byte[] buffer)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
this.disk = disk;
|
||||||
|
this.buffer = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
void writeFile (byte[] dataBuffer, int eof) throws DiskFullException
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
this.eof = eof;
|
||||||
|
|
||||||
|
int dataPtr = 0;
|
||||||
|
int remaining = eof;
|
||||||
|
|
||||||
|
while (dataPtr < eof)
|
||||||
|
{
|
||||||
|
int actualBlockNo = allocateNextBlock ();
|
||||||
|
map (dataPtr / BLOCK_SIZE, actualBlockNo);
|
||||||
|
|
||||||
|
int bufferPtr = actualBlockNo * BLOCK_SIZE;
|
||||||
|
int tfr = Math.min (remaining, BLOCK_SIZE);
|
||||||
|
|
||||||
|
System.arraycopy (dataBuffer, dataPtr, buffer, bufferPtr, tfr);
|
||||||
|
|
||||||
|
dataPtr += BLOCK_SIZE;
|
||||||
|
remaining -= BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeIndices ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
void writeRecord (int recordNo, byte[] dataBuffer, int recordLength)
|
||||||
|
throws DiskFullException
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
assert recordLength > 0;
|
||||||
|
|
||||||
|
int destPtr = recordLength * recordNo;
|
||||||
|
int remaining = Math.min (recordLength, dataBuffer.length);
|
||||||
|
int max = destPtr + remaining;
|
||||||
|
int dataPtr = 0;
|
||||||
|
|
||||||
|
if (eof < max)
|
||||||
|
eof = max;
|
||||||
|
|
||||||
|
while (destPtr < max)
|
||||||
|
{
|
||||||
|
int logicalBlockNo = destPtr / BLOCK_SIZE;
|
||||||
|
int blockOffset = destPtr % BLOCK_SIZE;
|
||||||
|
int tfr = Math.min (BLOCK_SIZE - blockOffset, remaining);
|
||||||
|
|
||||||
|
int actualBlockNo = getActualBlockNo (logicalBlockNo);
|
||||||
|
int bufferPtr = actualBlockNo * BLOCK_SIZE + blockOffset;
|
||||||
|
|
||||||
|
System.arraycopy (dataBuffer, dataPtr, buffer, bufferPtr, tfr);
|
||||||
|
|
||||||
|
destPtr += tfr;
|
||||||
|
dataPtr += tfr;
|
||||||
|
remaining -= tfr;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeIndices ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private int allocateNextBlock () throws DiskFullException
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
blocksUsed++;
|
||||||
|
return disk.allocateNextBlock ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private int getActualBlockNo (int logicalBlockNo) throws DiskFullException
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
int actualBlockNo = 0;
|
||||||
|
|
||||||
|
switch (storageType)
|
||||||
|
{
|
||||||
|
case TREE:
|
||||||
|
actualBlockNo =
|
||||||
|
masterIndexBlock.get (logicalBlockNo / 256).get (logicalBlockNo % 256);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SAPLING:
|
||||||
|
if (logicalBlockNo < 256)
|
||||||
|
actualBlockNo = indexBlock.get (logicalBlockNo);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SEEDLING:
|
||||||
|
if (logicalBlockNo == 0)
|
||||||
|
actualBlockNo = keyPointer;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actualBlockNo == 0)
|
||||||
|
{
|
||||||
|
actualBlockNo = allocateNextBlock ();
|
||||||
|
map (logicalBlockNo, actualBlockNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return actualBlockNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void writeIndices ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
if (storageType == TREE)
|
||||||
|
masterIndexBlock.write (buffer);
|
||||||
|
else if (storageType == SAPLING)
|
||||||
|
indexBlock.write (buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void map (int logicalBlockNo, int actualBlockNo) throws DiskFullException
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
if (logicalBlockNo > 255) // potential TREE
|
||||||
|
{
|
||||||
|
if (storageType != TREE)
|
||||||
|
{
|
||||||
|
masterIndexBlock = new MasterIndexBlock (allocateNextBlock ());
|
||||||
|
|
||||||
|
if (storageType == SAPLING) // sapling -> tree
|
||||||
|
{
|
||||||
|
masterIndexBlock.set (0, indexBlock);
|
||||||
|
}
|
||||||
|
else if (storageType == SEEDLING) // seedling -> sapling -> tree
|
||||||
|
{
|
||||||
|
indexBlock = new IndexBlock (allocateNextBlock ());
|
||||||
|
indexBlock.set (0, keyPointer);
|
||||||
|
masterIndexBlock.set (0, indexBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
keyPointer = masterIndexBlock.blockNo;
|
||||||
|
storageType = TREE;
|
||||||
|
indexBlock = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getIndexBlock (logicalBlockNo / 256).set (logicalBlockNo % 256, actualBlockNo);
|
||||||
|
}
|
||||||
|
else if (logicalBlockNo > 0) // potential SAPLING
|
||||||
|
{
|
||||||
|
if (storageType == TREE) // already a tree
|
||||||
|
{
|
||||||
|
getIndexBlock (0).set (logicalBlockNo, actualBlockNo);
|
||||||
|
}
|
||||||
|
else if (storageType == SAPLING) // already a sapling
|
||||||
|
{
|
||||||
|
indexBlock.set (logicalBlockNo, actualBlockNo);
|
||||||
|
}
|
||||||
|
else // new file or already a seedling
|
||||||
|
{
|
||||||
|
indexBlock = new IndexBlock (allocateNextBlock ());
|
||||||
|
if (storageType == SEEDLING) // seedling -> sapling
|
||||||
|
indexBlock.set (0, keyPointer);
|
||||||
|
|
||||||
|
keyPointer = indexBlock.blockNo;
|
||||||
|
storageType = SAPLING;
|
||||||
|
indexBlock.set (logicalBlockNo, actualBlockNo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (logicalBlockNo == 0) // potential SEEDLING
|
||||||
|
{
|
||||||
|
if (storageType == TREE) // already a tree
|
||||||
|
{
|
||||||
|
getIndexBlock (0).set (0, actualBlockNo);
|
||||||
|
}
|
||||||
|
else if (storageType == SAPLING) // already a sapling
|
||||||
|
{
|
||||||
|
indexBlock.set (0, actualBlockNo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
keyPointer = actualBlockNo;
|
||||||
|
storageType = SEEDLING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
System.out.println ("Error");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private IndexBlock getIndexBlock (int position) throws DiskFullException
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
IndexBlock indexBlock = masterIndexBlock.get (position);
|
||||||
|
|
||||||
|
if (indexBlock == null)
|
||||||
|
{
|
||||||
|
indexBlock = new IndexBlock (allocateNextBlock ());
|
||||||
|
masterIndexBlock.set (position, indexBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return indexBlock;
|
||||||
|
}
|
||||||
|
}
|
@ -187,7 +187,13 @@ public class ProdosDisk
|
|||||||
fileEntry.creationDate = created;
|
fileEntry.creationDate = created;
|
||||||
fileEntry.modifiedDate = modified;
|
fileEntry.modifiedDate = modified;
|
||||||
|
|
||||||
fileEntry.writeFile (dataBuffer);
|
FileWriter fileWriter = new FileWriter (this, buffer);
|
||||||
|
fileWriter.writeFile (dataBuffer, dataBuffer.length);
|
||||||
|
|
||||||
|
fileEntry.storageType = fileWriter.storageType;
|
||||||
|
fileEntry.keyPointer = fileWriter.keyPointer;
|
||||||
|
fileEntry.blocksUsed = fileWriter.blocksUsed;
|
||||||
|
fileEntry.eof = fileWriter.eof;
|
||||||
|
|
||||||
fileEntry.write ();
|
fileEntry.write ();
|
||||||
updateFileCount (fileEntry.headerPointer);
|
updateFileCount (fileEntry.headerPointer);
|
||||||
@ -198,6 +204,31 @@ public class ProdosDisk
|
|||||||
return null; // should be impossible
|
return null; // should be impossible
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
public void addResourceFork (FileEntry fileEntry, byte[] dataBuffer, int eof)
|
||||||
|
throws DiskFullException
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
FileWriter fileWriter = new FileWriter (this, buffer); // create dummy FileEntry
|
||||||
|
fileWriter.writeFile (dataBuffer, eof);
|
||||||
|
|
||||||
|
int blockNo = allocateNextBlock ();
|
||||||
|
|
||||||
|
ExtendedKeyBlock extendedKeyBlock =
|
||||||
|
new ExtendedKeyBlock (this, buffer, blockNo * BLOCK_SIZE);
|
||||||
|
|
||||||
|
extendedKeyBlock.addMiniEntry (1, fileEntry.storageType, fileEntry.keyPointer,
|
||||||
|
fileEntry.blocksUsed, fileEntry.eof);
|
||||||
|
extendedKeyBlock.addMiniEntry (2, fileWriter.storageType, fileWriter.keyPointer,
|
||||||
|
fileWriter.blocksUsed, fileWriter.eof);
|
||||||
|
|
||||||
|
fileEntry.keyPointer = blockNo; // extended key block
|
||||||
|
fileEntry.storageType = 0x05; // extended
|
||||||
|
|
||||||
|
fileEntry.write ();
|
||||||
|
extendedKeyBlock.write ();
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
private boolean verify (String path)
|
private boolean verify (String path)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@ -393,6 +424,16 @@ public class ProdosDisk
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
// private int createExtendedKeyBlock (FileEntry fileEntry) throws DiskFullException
|
||||||
|
// // ---------------------------------------------------------------------------------//
|
||||||
|
// {
|
||||||
|
// int blockNo = allocateNextBlock ();
|
||||||
|
// ExtendedKeyBlock extendedKeyBlock = new ExtendedKeyBlock (blockNo);
|
||||||
|
//
|
||||||
|
// return blockNo;
|
||||||
|
// }
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
int allocateNextBlock () throws DiskFullException
|
int allocateNextBlock () throws DiskFullException
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -57,9 +57,9 @@ class DateTime
|
|||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
int adjustedYear = year + (year > 70 ? 1900 : 2000);
|
int adjustedYear = year + (year > 70 ? 1900 : 2000);
|
||||||
if (day < 1 || day > 31)
|
if (day < 0 || day > 30)
|
||||||
return null;
|
return null;
|
||||||
return LocalDateTime.of (adjustedYear, month + 1, day, hour, minute);
|
return LocalDateTime.of (adjustedYear, month + 1, day + 1, hour, minute);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -16,8 +16,6 @@ class LZW2 extends LZW
|
|||||||
|
|
||||||
this.crc = crc;
|
this.crc = crc;
|
||||||
this.v3eof = eof;
|
this.v3eof = eof;
|
||||||
|
|
||||||
// unpack ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -33,7 +33,6 @@ class MasterHeader
|
|||||||
if (isBin2 (buffer, ptr))
|
if (isBin2 (buffer, ptr))
|
||||||
{
|
{
|
||||||
binary2Header = new Binary2Header (buffer);
|
binary2Header = new Binary2Header (buffer);
|
||||||
System.out.println (binary2Header);
|
|
||||||
ptr += 128;
|
ptr += 128;
|
||||||
bin2 = true;
|
bin2 = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -77,6 +77,7 @@ public class NuFX
|
|||||||
if (record.hasDisk ())
|
if (record.hasDisk ())
|
||||||
++totalDisks;
|
++totalDisks;
|
||||||
}
|
}
|
||||||
|
|
||||||
printSummary ();
|
printSummary ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,14 +97,17 @@ public class NuFX
|
|||||||
|
|
||||||
for (Record record : records)
|
for (Record record : records)
|
||||||
{
|
{
|
||||||
System.out.printf (" %s%n", record.getLine ());
|
System.out.println (record.getLine ());
|
||||||
totalUncompressedSize += record.getUncompressedSize ();
|
totalUncompressedSize += record.getUncompressedSize ();
|
||||||
totalCompressedSize += record.getCompressedSize ();
|
totalCompressedSize += record.getCompressedSize ();
|
||||||
}
|
}
|
||||||
System.out.println (UNDERLINE);
|
System.out.println (UNDERLINE);
|
||||||
System.out.printf (" Uncomp:%7d Comp:%7d %%of orig:%3.0f%%%n",
|
|
||||||
totalUncompressedSize, totalCompressedSize,
|
float pct = 0;
|
||||||
(float) (totalCompressedSize * 100 / totalUncompressedSize));
|
if (totalUncompressedSize > 0)
|
||||||
|
pct = totalCompressedSize * 100 / totalUncompressedSize;
|
||||||
|
System.out.printf (" Uncomp:%7d Comp:%7d %%of orig:%3.0f%%%n%n",
|
||||||
|
totalUncompressedSize, totalCompressedSize, pct);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@ -116,7 +120,7 @@ public class NuFX
|
|||||||
if (record.hasFile ())
|
if (record.hasFile ())
|
||||||
{
|
{
|
||||||
// note: total blocks does not include subdirectory blocks
|
// note: total blocks does not include subdirectory blocks
|
||||||
int blocks = (record.getFileSize () - 1) / 512 + 1;
|
int blocks = (record.getUncompressedSize () - 1) / 512 + 1;
|
||||||
if (blocks == 1) // seedling
|
if (blocks == 1) // seedling
|
||||||
totalBlocks += blocks;
|
totalBlocks += blocks;
|
||||||
else if (blocks <= 256) // sapling
|
else if (blocks <= 256) // sapling
|
||||||
@ -132,6 +136,8 @@ public class NuFX
|
|||||||
{
|
{
|
||||||
if (totalDisks > 0)
|
if (totalDisks > 0)
|
||||||
{
|
{
|
||||||
|
if (debug)
|
||||||
|
System.out.println ("Reading disk");
|
||||||
for (Record record : records)
|
for (Record record : records)
|
||||||
for (Thread thread : record.threads)
|
for (Thread thread : record.threads)
|
||||||
if (thread.hasDisk ())
|
if (thread.hasDisk ())
|
||||||
@ -140,8 +146,8 @@ public class NuFX
|
|||||||
|
|
||||||
if (totalFiles > 0)
|
if (totalFiles > 0)
|
||||||
{
|
{
|
||||||
// should check that files are all in prodos format
|
if (debug)
|
||||||
|
System.out.println ("Reading files");
|
||||||
calculateTotalBlocks ();
|
calculateTotalBlocks ();
|
||||||
int[] diskSizes = { 280, 800, 1600, 3200, 6400, 65536 };
|
int[] diskSizes = { 280, 800, 1600, 3200, 6400, 65536 };
|
||||||
for (int diskSize : diskSizes) // in case we choose a size that is too small
|
for (int diskSize : diskSizes) // in case we choose a size that is too small
|
||||||
@ -184,6 +190,12 @@ public class NuFX
|
|||||||
System.out.printf ("File %s not added%n", fileName);
|
System.out.printf ("File %s not added%n", fileName);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (record.hasResource ())
|
||||||
|
{
|
||||||
|
buffer = record.getResourceData ();
|
||||||
|
System.out.println (HexFormatter.format (buffer));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,11 +203,6 @@ public class NuFX
|
|||||||
|
|
||||||
return disk.getBuffer ();
|
return disk.getBuffer ();
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
e.printStackTrace ();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (DiskFullException e)
|
catch (DiskFullException e)
|
||||||
{
|
{
|
||||||
System.out.println ("disk full: " + diskSize); // go round again
|
System.out.println ("disk full: " + diskSize); // go round again
|
||||||
@ -205,6 +212,11 @@ public class NuFX
|
|||||||
e.printStackTrace ();
|
e.printStackTrace ();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace ();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,6 +148,17 @@ class Record
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
boolean hasResource ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
for (Thread thread : threads)
|
||||||
|
if (thread.hasResource ())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
String getFileName ()
|
String getFileName ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@ -199,6 +210,15 @@ class Record
|
|||||||
return modified.getLocalDateTime ();
|
return modified.getLocalDateTime ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
LocalDateTime getArchived ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
if (archived == null)
|
||||||
|
return null;
|
||||||
|
return archived.getLocalDateTime ();
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
int getFileSystemID ()
|
int getFileSystemID ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@ -239,22 +259,26 @@ class Record
|
|||||||
int getUncompressedSize ()
|
int getUncompressedSize ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
for (Thread thread : threads)
|
int size = 0;
|
||||||
if (thread.hasFile ())
|
|
||||||
return thread.getUncompressedEOF ();
|
|
||||||
|
|
||||||
return 0;
|
for (Thread thread : threads)
|
||||||
|
if (thread.hasFile () || thread.hasResource ())
|
||||||
|
size += thread.getUncompressedEOF ();
|
||||||
|
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
int getCompressedSize ()
|
int getCompressedSize ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
for (Thread thread : threads)
|
int size = 0;
|
||||||
if (thread.hasFile ())
|
|
||||||
return thread.getCompressedEOF ();
|
|
||||||
|
|
||||||
return 0;
|
for (Thread thread : threads)
|
||||||
|
if (thread.hasFile () || thread.hasResource ())
|
||||||
|
size += thread.getCompressedEOF ();
|
||||||
|
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@ -264,6 +288,18 @@ class Record
|
|||||||
for (Thread thread : threads)
|
for (Thread thread : threads)
|
||||||
if (thread.hasFile ())
|
if (thread.hasFile ())
|
||||||
return thread.getData ();
|
return thread.getData ();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
byte[] getResourceData ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
for (Thread thread : threads)
|
||||||
|
if (thread.hasResource ())
|
||||||
|
return thread.getData ();
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,9 +307,17 @@ class Record
|
|||||||
String getLine ()
|
String getLine ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
float pct = getCompressedSize () * 100 / getUncompressedSize ();
|
float pct = 0;
|
||||||
return String.format ("%-27.27s %s $%04X %-15s %s %3.0f%% %7d", getFileName (),
|
if (getUncompressedSize () > 0)
|
||||||
fileTypes[fileType], auxType, created.format2 (),
|
pct = getCompressedSize () * 100 / getUncompressedSize ();
|
||||||
|
String lockedFlag = (access | 0xC3) == 1 ? "+" : " ";
|
||||||
|
String forkedFlag = hasResource () ? "+" : " ";
|
||||||
|
String name = getFileName ();
|
||||||
|
if (name.length () > 27)
|
||||||
|
name = ".." + name.substring (name.length () - 25);
|
||||||
|
|
||||||
|
return String.format ("%s%-27.27s %s%s $%04X %-15s %s %3.0f%% %7d", lockedFlag,
|
||||||
|
name, fileTypes[fileType], forkedFlag, auxType, archived.format2 (),
|
||||||
threadFormats[getThreadFormat ()], pct, getUncompressedSize ());
|
threadFormats[getThreadFormat ()], pct, getUncompressedSize ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ class Thread
|
|||||||
|
|
||||||
private boolean hasDisk;
|
private boolean hasDisk;
|
||||||
private boolean hasFile;
|
private boolean hasFile;
|
||||||
|
private boolean hasResource;
|
||||||
private boolean hasFileName;
|
private boolean hasFileName;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@ -102,6 +103,7 @@ class Thread
|
|||||||
hasDisk = true;
|
hasDisk = true;
|
||||||
break;
|
break;
|
||||||
case 2: // resource fork of file
|
case 2: // resource fork of file
|
||||||
|
hasResource = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,6 +174,13 @@ class Thread
|
|||||||
return hasFile;
|
return hasFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
public boolean hasResource ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
return hasResource;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
public boolean hasFileName ()
|
public boolean hasFileName ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@ -190,7 +199,11 @@ class Thread
|
|||||||
int getFileSize ()
|
int getFileSize ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
|
if (lzw != null)
|
||||||
|
System.out.printf ("%04X v %04X v %04X%n", compressedEOF, uncompressedEOF,
|
||||||
|
lzw.getSize ());
|
||||||
return lzw != null ? lzw.getSize () : uncompressedEOF;
|
return lzw != null ? lzw.getSize () : uncompressedEOF;
|
||||||
|
// return uncompressedEOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
Loading…
Reference in New Issue
Block a user