initial shk support
This commit is contained in:
parent
6aa882ecbd
commit
2cb40b84e4
|
@ -67,7 +67,7 @@ public interface ProdosConstants
|
|||
"$48", "$49", "$4A", "$4B", "$4C", "$4D", "$4E", "$4F", //
|
||||
"GWP", "GSS", "GDB", "DRW", "GDP", "HMD", "EDU", "STN", //
|
||||
"HLP", "COM", "CFG", "ANM", "MUM", "ENT", "DVU", "FIN", //
|
||||
"$60", "$61", "$62", "$63", "$64", "$65", "$66", "$67", //
|
||||
"$60", "$61", "$62", "$63", "$64", "$65", "NCF", "$67", //
|
||||
"$68", "$69", "$6A", "BIO", "$6C", "TDR", "PRE", "HDV", //
|
||||
"$70", "$71", "$72", "$73", "$74", "$75", "$76", "$77", //
|
||||
"$78", "$79", "$7A", "$7B", "$7C", "$7D", "$7E", "$7F", //
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package com.bytezone.diskbrowser.prodos.write;
|
||||
|
||||
public class DiskFullException extends Exception
|
||||
{
|
||||
public DiskFullException (String message)
|
||||
{
|
||||
super (message);
|
||||
}
|
||||
}
|
|
@ -98,7 +98,7 @@ public class FileEntry
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void writeFile (byte[] dataBuffer)
|
||||
void writeFile (byte[] dataBuffer) throws DiskFullException
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.eof = dataBuffer.length;
|
||||
|
@ -124,7 +124,7 @@ public class FileEntry
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void writeRecord (int recordNo, byte[] dataBuffer)
|
||||
void writeRecord (int recordNo, byte[] dataBuffer) throws DiskFullException
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
assert auxType > 0; // record length
|
||||
|
@ -160,7 +160,7 @@ public class FileEntry
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
int allocateNextBlock ()
|
||||
int allocateNextBlock () throws DiskFullException
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
blocksUsed++;
|
||||
|
@ -168,7 +168,7 @@ public class FileEntry
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
int getActualBlockNo (int logicalBlockNo)
|
||||
int getActualBlockNo (int logicalBlockNo) throws DiskFullException
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int actualBlockNo = 0;
|
||||
|
@ -211,7 +211,7 @@ public class FileEntry
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void map (int logicalBlockNo, int actualBlockNo)
|
||||
void map (int logicalBlockNo, int actualBlockNo) throws DiskFullException
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (logicalBlockNo > 255) // potential TREE
|
||||
|
@ -280,7 +280,7 @@ public class FileEntry
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
IndexBlock getIndexBlock (int position)
|
||||
IndexBlock getIndexBlock (int position) throws DiskFullException
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
IndexBlock indexBlock = masterIndexBlock.get (position);
|
||||
|
|
|
@ -33,7 +33,7 @@ public class ProdosDisk
|
|||
private Map<Integer, SubdirectoryHeader> subdirectoryHeaders = new HashMap<> ();
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public ProdosDisk (int blocks, String volumeName) throws IOException
|
||||
public ProdosDisk (int blocks, String volumeName) throws IOException, DiskFullException
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
try (DataInputStream in = new DataInputStream (ProdosDisk.class.getClassLoader ()
|
||||
|
@ -63,7 +63,7 @@ public class ProdosDisk
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void createCatalog (String volumeName)
|
||||
void createCatalog (String volumeName) throws DiskFullException
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
// reserve two boot blocks
|
||||
|
@ -112,7 +112,8 @@ public class ProdosDisk
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public FileEntry addFile (String path, int type, byte[] dataBuffer)
|
||||
public FileEntry addFile (String path, byte type, int auxType, LocalDateTime created,
|
||||
LocalDateTime modified, byte[] dataBuffer) throws DiskFullException
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
String[] subdirectories;
|
||||
|
@ -158,7 +159,10 @@ public class ProdosDisk
|
|||
fileEntry.version = 0x00;
|
||||
fileEntry.minVersion = 0x00;
|
||||
fileEntry.headerPointer = catalogBlockNo;
|
||||
fileEntry.fileType = 4; // text
|
||||
fileEntry.fileType = type;
|
||||
fileEntry.auxType = auxType;
|
||||
fileEntry.creationDate = created;
|
||||
fileEntry.modifiedDate = modified;
|
||||
|
||||
fileEntry.writeFile (dataBuffer);
|
||||
|
||||
|
@ -221,7 +225,7 @@ public class ProdosDisk
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private FileEntry createSubdirectory (int blockNo, String name)
|
||||
private FileEntry createSubdirectory (int blockNo, String name) throws DiskFullException
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
FileEntry fileEntry = findFreeSlot (blockNo);
|
||||
|
@ -281,10 +285,15 @@ public class ProdosDisk
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
int allocateNextBlock ()
|
||||
int allocateNextBlock () throws DiskFullException
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int nextBlock = getFreeBlock ();
|
||||
if (nextBlock < 0)
|
||||
{
|
||||
throw new DiskFullException ("Full");
|
||||
}
|
||||
|
||||
volumeBitMap.set (nextBlock, false); // mark as unavailable
|
||||
|
||||
return nextBlock;
|
||||
|
@ -298,7 +307,7 @@ public class ProdosDisk
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private FileEntry findFreeSlot (int blockNo)
|
||||
private FileEntry findFreeSlot (int blockNo) throws DiskFullException
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
SubdirectoryHeader subdirectoryHeader = subdirectoryHeaders.get (blockNo);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.bytezone.diskbrowser.utilities;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class DateTime
|
||||
// -----------------------------------------------------------------------------------//
|
||||
|
@ -39,6 +41,14 @@ class DateTime
|
|||
days[weekDay], day, months[month], year);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public LocalDateTime getLocalDateTime ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int adjustedYear = year + (year > 70 ? 1900 : 2000);
|
||||
return LocalDateTime.of (adjustedYear, month + 1, day, hour, minute);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String toString ()
|
||||
|
|
|
@ -4,9 +4,11 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.bytezone.diskbrowser.prodos.write.DiskFullException;
|
||||
import com.bytezone.diskbrowser.prodos.write.ProdosDisk;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
|
@ -55,11 +57,7 @@ public class NuFX
|
|||
dataPtr += thread.getCompressedEOF ();
|
||||
|
||||
if (debug)
|
||||
{
|
||||
System.out.printf ("Thread: %d%n%n%s%n%n", i, thread);
|
||||
// if (rec == 122 && thread.hasFile ())
|
||||
// System.out.println (HexFormatter.format (thread.getData ()));
|
||||
}
|
||||
}
|
||||
|
||||
if (record.hasFile ())
|
||||
|
@ -82,10 +80,9 @@ public class NuFX
|
|||
}
|
||||
else if (totalFiles > 0)
|
||||
{
|
||||
// listFiles ();
|
||||
try
|
||||
{
|
||||
ProdosDisk disk = new ProdosDisk (1600, "DISKBROWSER");
|
||||
ProdosDisk disk = new ProdosDisk (3200, "DISKBROWSER");
|
||||
int count = 0;
|
||||
for (Record record : records)
|
||||
{
|
||||
|
@ -93,15 +90,17 @@ public class NuFX
|
|||
{
|
||||
String fileName = record.getFileName ();
|
||||
int fileSize = record.getFileSize ();
|
||||
int fileType = record.getFileType ();
|
||||
byte fileType = (byte) record.getFileType ();
|
||||
int eof = record.getUncompressedSize ();
|
||||
int auxType = record.getAuxType ();
|
||||
LocalDateTime created = record.getCreated ();
|
||||
LocalDateTime modified = record.getModified ();
|
||||
byte[] buffer = record.getData ();
|
||||
System.out.printf ("%3d %-35s %,7d %d %,7d %d%n", ++count, fileName,
|
||||
fileSize, fileType, eof, buffer.length);
|
||||
if (fileType == 4 && count > 10 && count < 16)
|
||||
{
|
||||
disk.addFile (fileName, fileType, buffer);
|
||||
}
|
||||
|
||||
System.out.printf ("%3d %-35s %,7d %02X %,7d %,7d %,7d %s %s%n",
|
||||
++count, fileName, fileSize, fileType, eof, auxType, buffer.length,
|
||||
created, modified);
|
||||
disk.addFile (fileName, fileType, auxType, created, modified, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,6 +112,10 @@ public class NuFX
|
|||
{
|
||||
e.printStackTrace ();
|
||||
}
|
||||
catch (DiskFullException e)
|
||||
{
|
||||
e.printStackTrace ();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -176,7 +179,7 @@ public class NuFX
|
|||
public static void main (String[] args) throws FileFormatException, IOException
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
File file = new File ("/Users/denismolony/Dropbox/Examples/SHK/Applenet20.shk");
|
||||
File file = new File ("/Users/denismolony/Dropbox/Examples/SHK/DiversiCopy.3.1.shk");
|
||||
|
||||
NuFX nufx = new NuFX (file.toPath ());
|
||||
System.out.println (nufx);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.bytezone.diskbrowser.utilities;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -159,7 +160,12 @@ class Record
|
|||
{
|
||||
for (Thread thread : threads)
|
||||
if (thread.hasFileName ())
|
||||
{
|
||||
String fileName = thread.getFileName ();
|
||||
if (separator != '/')
|
||||
return fileName.replace (separator, '/');
|
||||
return thread.getFileName ();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
@ -171,6 +177,31 @@ class Record
|
|||
return fileType;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
int getAuxType ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return auxType;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
LocalDateTime getCreated ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (created == null)
|
||||
return null;
|
||||
return created.getLocalDateTime ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
LocalDateTime getModified ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (modified == null)
|
||||
return null;
|
||||
return modified.getLocalDateTime ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
int getFileSize ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -214,7 +245,7 @@ class Record
|
|||
bits = bits.substring (bits.length () - 8);
|
||||
String decode = Utility.matchFlags (access, accessChars);
|
||||
|
||||
text.append (String.format ("Header CRC ..... %,d (%04X)%n", crc, crc));
|
||||
text.append (String.format ("Header CRC ..... %,d (%<04X)%n", crc));
|
||||
text.append (String.format ("Attributes ..... %d%n", attributes));
|
||||
text.append (String.format ("Version ........ %d%n", version));
|
||||
text.append (String.format ("Threads ........ %d%n", totThreads));
|
||||
|
|
|
@ -195,12 +195,33 @@ public class Utility
|
|||
int minute = buffer[offset + 2] & 0x3F;
|
||||
int hour = buffer[offset + 3] & 0x1F;
|
||||
|
||||
if (month < 1 || month > 12)
|
||||
{
|
||||
System.out.printf ("Invalid month: %d%n", month);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (hour > 23)
|
||||
{
|
||||
System.out.printf ("Invalid hour: %d%n", hour);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (year < 70)
|
||||
year += 2000;
|
||||
else
|
||||
year += 1900;
|
||||
return LocalDateTime.of (year, month - 1, day, hour, minute);
|
||||
|
||||
try
|
||||
{
|
||||
return LocalDateTime.of (year, month - 1, day, hour, minute);
|
||||
}
|
||||
catch (DateTimeException e)
|
||||
{
|
||||
System.out.println ("Bad date/time");
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -249,14 +270,15 @@ public class Utility
|
|||
public static int readShort (byte[] buffer, int ptr)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return buffer[ptr] | buffer[ptr + 1] << 8;
|
||||
return (buffer[ptr] & 0xFF) | (buffer[ptr + 1] & 0xFF) << 8;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public static int readTriple (byte[] buffer, int ptr)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return buffer[ptr] | buffer[ptr + 1] << 8 | buffer[ptr + 2] << 16;
|
||||
return (buffer[ptr] & 0xFF) | (buffer[ptr + 1] & 0xFF) << 8
|
||||
| (buffer[ptr + 2] & 0xFF) << 16;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
|
Loading…
Reference in New Issue