diff --git a/src/com/webcodepro/applecommander/storage/cpm/CpmFileEntry.java b/src/com/webcodepro/applecommander/storage/cpm/CpmFileEntry.java index b54c5da..be5d130 100644 --- a/src/com/webcodepro/applecommander/storage/cpm/CpmFileEntry.java +++ b/src/com/webcodepro/applecommander/storage/cpm/CpmFileEntry.java @@ -1,9 +1,11 @@ package com.webcodepro.applecommander.storage.cpm; +import com.webcodepro.applecommander.storage.BinaryFileFilter; import com.webcodepro.applecommander.storage.DiskFullException; import com.webcodepro.applecommander.storage.FileEntry; import com.webcodepro.applecommander.storage.FileFilter; import com.webcodepro.applecommander.storage.FormattedDisk; +import com.webcodepro.applecommander.storage.TextFileFilter; import com.webcodepro.applecommander.util.AppleUtil; import java.text.NumberFormat; @@ -11,13 +13,79 @@ import java.util.ArrayList; import java.util.List; /** - * @author Rob + * Support the CP/M file entry. Note that this may actually contain references + * to multiple file entries via the extent counter. + *
+ * @author Rob Greene
*/
public class CpmFileEntry implements FileEntry {
/**
* The standard CP/M file entry length.
*/
public static final int ENTRY_LENGTH = 0x20;
+ /**
+ * The maximum number of extents per file entry record.
+ */
+ public static final int MAX_EXTENTS_PER_ENTRY = 0x80;
+ /**
+ * The number of bytes used if all records in an extent are filled.
+ * (MAX_EXTENTS_PER_ENTRY * CPM_SECTOR_SIZE)
+ */
+ public static final int ALL_RECORDS_FILLED_SIZE = 16384;
+ /**
+ * The user number (UU) field is to distinguish multiple files with the
+ * same filename. This appears to be primarily with deleted files?
+ */
+ public static final int USER_NUMBER_OFFSET = 0;
+ /**
+ * Offset to beginning of the filename.
+ */
+ public static final int FILENAME_OFFSET = 1;
+ /**
+ * Filename length (excluding extension).
+ */
+ public static final int FILENAME_LENGTH = 8;
+ /**
+ * Offset to beginning of the filetype.
+ */
+ public static final int FILETYPE_OFFSET = 9;
+ /**
+ * Filetype length.
+ */
+ public static final int FILETYPE_LENGTH = 3;
+ /**
+ * Offset to the filetype "T1" entry.
+ * Indicates read-only.
+ */
+ public static final int FILETYPE_T1_OFFSET = FILETYPE_OFFSET;
+ /**
+ * Offset to the filetype "T2" entry.
+ * Indicates system or hidden file.
+ */
+ public static final int FILETYPE_T2_OFFSET = FILETYPE_OFFSET+1;
+ /**
+ * Offset to the filetype "T3" entry.
+ * Backup bit (CP/M 3.1 and later).
+ */
+ public static final int FILETYPE_T3_OFFSET = FILETYPE_OFFSET+2;
+ /**
+ * Offset to the extent counter (EX) field.
+ */
+ public static final int EXTENT_COUNTER_OFFSET = 0xc;
+ /**
+ * Offset to the record count (RC) field.
+ */
+ public static final int RECORD_COUNT_OFFSET = 0xf;
+ /**
+ * Beginning of block allocations.
+ */
+ public static final int ALLOCATION_OFFSET = 0x10;
+ /**
+ * A short collection of known text-type files.
+ */
+ public static final String[] TEXT_FILETYPES = {
+ "TXT", "ASM", "MAC", "DOC", "PRN", "PAS", "ME", "INC", "HLP"
+ };
/**
* Reference to the disk this FileEntry is attached to.
*/
@@ -46,29 +114,52 @@ public class CpmFileEntry implements FileEntry {
* Read the fileEntry bytes from the disk image.
*/
protected byte[] readFileEntry(int number) {
- byte[] data = new byte[2048];
- System.arraycopy(disk.readCpmBlock(0), 0, data, 0, 1024);
- System.arraycopy(disk.readCpmBlock(1), 0, data, 1024, 1024);
+ byte[] data = new byte[2 * CpmFormatDisk.CPM_BLOCKSIZE];
+ System.arraycopy(disk.readCpmBlock(0), 0, data,
+ 0, CpmFormatDisk.CPM_BLOCKSIZE);
+ System.arraycopy(disk.readCpmBlock(1), 0, data,
+ CpmFormatDisk.CPM_BLOCKSIZE, CpmFormatDisk.CPM_BLOCKSIZE);
byte[] entry = new byte[ENTRY_LENGTH];
int offset = ((Integer)offsets.get(number)).intValue();
System.arraycopy(data, offset, entry, 0, ENTRY_LENGTH);
return entry;
}
+
+ /**
+ * Write the fileEntry bytes back to the disk image.
+ */
+ protected void writeFileEntry(int number, byte[] data) {
+ byte[] block = new byte[CpmFormatDisk.CPM_BLOCKSIZE];
+ System.arraycopy(data, 0, block,
+ 0, CpmFormatDisk.CPM_BLOCKSIZE);
+ disk.writeCpmBlock(0, block);
+ System.arraycopy(data, 0, block,
+ CpmFormatDisk.CPM_BLOCKSIZE, CpmFormatDisk.CPM_BLOCKSIZE);
+ disk.writeCpmBlock(1, block);
+ }
/**
* Answer with the name of the file.
* @see com.webcodepro.applecommander.storage.FileEntry#getFilename()
*/
public String getFilename() {
- return AppleUtil.getString(readFileEntry(0), 1, 8).trim();
+ return AppleUtil.getString(readFileEntry(0),
+ FILENAME_OFFSET, FILENAME_LENGTH).trim();
}
/**
+ * Set the filename. Note that this assumes the file extension
+ * is completely separate and does not validate characters that
+ * are being set!
* @see com.webcodepro.applecommander.storage.FileEntry#setFilename(java.lang.String)
*/
public void setFilename(String filename) {
- // TODO Auto-generated method stub
-
+ for (int i=0; i
+ * Note: Assumes that this is a 140K CP/M disk of 35 tracks and
+ * 16 physical sectors.
* @see com.webcodepro.applecommander.storage.FormattedDisk#format()
*/
public void format() {
- // TODO Auto-generated method stub
-
+ byte[] sectorData = new byte[SECTOR_SIZE];
+ for (int i=0; i