diff --git a/documentation/AppleCommander 1.2.3 fixes from John Matthews.html b/documentation/AppleCommander 1.2.3 fixes from John Matthews.html new file mode 100644 index 0000000..bebba82 --- /dev/null +++ b/documentation/AppleCommander 1.2.3 fixes from John Matthews.html @@ -0,0 +1,244 @@ + + +
++ mkdir ac + cd ac + tar -zxvf ac.tgz ++ +Using ac
+ java -jar ac.jar -p140 misc.dsk test ++The -l command lists the directory of a disk image. To examine a disk image named misc.dsk, enter the command:
+ java -jar ac.jar -l misc.dsk ++The -e command lets you examine a file by printing a readable version to standard output. To examine a file named fred on a disk named misc.dsk, enter the command:
+ java -jar ac.jar -e fred misc.dsk+Because binary files are difficult to read, you may want to send the output to a program that can show the data in hexadecimal form:
+
+ java -jar ac.jar -e fred misc.dsk | hexdump+The -g command gets a file in its raw form. To copy a file named fred from misc.dsk to a file named ethel on your file system, enter the command:
+
+ java -jar ac.jar -g fred misc.dsk > ethel+The -p command puts data on a disk image. Suppose ethel is a binary file meant to start at address 2048 ($800). To put the binary file named ethel back into a file named fred with starting address 1028 on the image named misc.dsk:
+
+ cat ethel | java -jar ac.jar -p fred bin 2048 misc.dsk+The -d command deletes a file from an image:
+
+ java -jar ac.jar -p fred misc.dsk+To copy a file from one image to another, do something like this:
+
+ java -jar ac.jar -g fred one.dsk | java -jar ac.jar -p fred bin 2048 another.dsk+For a quick list of ac options, enter the -h command:
+
+ java -jar ac.jar -h+The result is shown:
+
+ AppleCommander command line options: + -l+ +Known problemslist directory of image. + -e export file from image to stdout. + -g get raw file from image to stdout. + -p put stdin + in destname on image, using file type and address. + -d delete file from image. + -p140 create a 140K ProDOS image. + -p800 create a 800K ProDOS image. +
+ /** + * Extract a Pascal date from the buffer.+3. In strage.PascalFileEntry.getFileColumnData use SimpleDateFormat("dd-MMM-yy").
+ * Bits 0-3: month (1-12)
+ * Bits 4-8: day (1-31)
+ * Bits 9-15: year (0-99) + */ + public static Date getPascalDate(byte[] buffer, int offset) { + int pascalDate = getWordValue(buffer, offset); + int month = pascalDate & 0x000f - 1; + int day = (pascalDate & 0x01f0) >> 4; + int year = (pascalDate & 0xfe00) >> 9; + if (year < 50) year+= 2000; + if (year < 100) year+= 1900; + GregorianCalendar gc = new GregorianCalendar(year, month, day); + return gc.getTime(); + } + + /** + * Set a Pascal data to the buffer.
+ * Bits 0-3: month (1-12)
+ * Bits 4-8: day (1-31)
+ * Bits 9-15: year (0-99) + */ + public static void setPascalDate(byte[] buffer, int offset, Date date) { + GregorianCalendar gc = new GregorianCalendar(); + gc.setTime(date); + int month = gc.get(GregorianCalendar.MONTH) + 1; + int day = gc.get(GregorianCalendar.DAY_OF_MONTH); + int year = gc.get(GregorianCalendar.YEAR) % 100; + int pascalDate = (month & 0x000f) + | ((day << 4) & 0x01f0) + | ((year << 9) & 0xfe00); + setWordValue(buffer, offset, pascalDate); + } +
+ int month = ((ymd & 0x01e0) >> 5) - 1; // bits 5-8 ++In setProdosDate add one and fix the year: +
+ month = gc.get(GregorianCalendar.MONTH) + 1; + ... + if (year >= 2000) { + year -= 2000; + } else { + year -= 1900; + } ++8. In ProdosFormatDisk.createFile(), add fileEntry.setKeyPointer(0); if this is a recyled directory entry, a subsequent call to setFileData will try to free blocks that previously belonged to the deleted file. These blocks may have subsequently been allocated to another file.
+ fileEntry.setKeyPointer(0); //may have been recycled ++Also, call setSeedlingFile(), rather than setSaplingFile(). + +9. A file entry needs a header pointer: In ProdosFileEntry add
+ /** + * Set the block number of the block for the directory + * that describes this file. + */ + public void setHeaderPointer(int headerPointer) { + byte[] entry = readFileEntry(); + AppleUtil.setWordValue(entry, 0x25, headerPointer); + writeFileEntry(entry); + } ++10. Initailize header pointer in ProdosFormatDisk.createFile(), add
+ int headerBlock = blockNumber; + ... + fileEntry.setHeaderPointer(headerBlock); ++11. In ProdosFileEntry.delete(), the file count in the entry's directory header should be decremented. [ProDOS Tech. Ref. B.2.2 B.2.3] Also, both the storage type and the name length should be set to zero. [ProDOS Tech. Ref. B.2.4]
+ /** + * Delete the file. + */ + public void delete() { + getDisk().freeBlocks(this); + + //decrement file count in header block + int headerBlock = getHeaderPointer(); + byte[] data = getDisk().readBlock(headerBlock); + int fileCount = AppleUtil.getWordValue(data, 0x25); + if (fileCount != 0) fileCount--; + AppleUtil.setWordValue(data, 0x25, fileCount); + getDisk().writeBlock(headerBlock, data); + + //clear storage type and name length + data = readFileEntry(); + data[0] = 0; + writeFileEntry(data); + } ++12. In TextFileFilter, use PrintWriter for cross-platform line endings:
+ /** + * Process the given FileEntry and return a byte array + * with filtered data; use PrintWriter to get platform + * agnostic line endings. + */ + public byte[] filter(FileEntry fileEntry) { + byte[] fileData = fileEntry.getFileData(); + int offset = 0; + ByteArrayOutputStream byteArray = new + ByteArrayOutputStream(fileData.length); + PrintWriter printWriter = new PrintWriter(byteArray, true); + while (offset < fileData.length) { + char c = (char)(fileData[offset] & 0x7f); + if (c != 0) { + if (c == 0x0d) { //Apple line end + printWriter.println(); + } else { + printWriter.print(c); + } + } + offset++; + } + return byteArray.toByteArray(); + } ++13. Applesoft files require a statign address, usually 2049 ($801); to Prodos FileTypes.properties add:
+ filetype.fc.address=true ++ +Copyright 2003 John B. Matthews