diff --git a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/Disk.java b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/Disk.java index b783c71..56eb21d 100644 --- a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/Disk.java +++ b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/Disk.java @@ -278,7 +278,7 @@ public class Disk { rc = 0; } else { imageOrder = proDosOrder; - if (knownProDOSOrder || isProdosFormat() || isDosFormat()) { + if (knownProDOSOrder || isProdosFormat() || isDosFormat() || isRdos33Format()) { rc = 0; } } @@ -791,9 +791,20 @@ public class Disk { if (!is140KbDisk()) return false; byte[] block = readSector(0, 0x0d); String id = AppleUtil.getString(block, 0xe0, 4); - return "RDOS".equals(id); //$NON-NLS-1$ + return "RDOS".equals(id) || isRdos33Format(); //$NON-NLS-1$ } + /** + * Test the disk format to see if this is a RDOS 33 formatted + * disk. + */ + public boolean isRdos33Format() { + if (!is140KbDisk()) return false; + byte[] block = readSector(1, 0x0); + String id = AppleUtil.getString(block, 0x0, 6); + return "RDOS 3".equals(id); //$NON-NLS-1$ + } + /** * Test the disk format to see if this is a WP formatted * disk. diff --git a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/rdos/RdosFormatDisk.java b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/rdos/RdosFormatDisk.java index 7c7ef37..8c9a03b 100644 --- a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/rdos/RdosFormatDisk.java +++ b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/rdos/RdosFormatDisk.java @@ -30,20 +30,21 @@ import com.webcodepro.applecommander.storage.FileEntry; import com.webcodepro.applecommander.storage.FormattedDisk; import com.webcodepro.applecommander.storage.StorageBundle; import com.webcodepro.applecommander.storage.physical.ImageOrder; +import com.webcodepro.applecommander.storage.physical.ProdosOrder; import com.webcodepro.applecommander.util.AppleUtil; import com.webcodepro.applecommander.util.TextBundle; /** * Manages a disk that is in the RDOS format. *

- * Note that the RDOS block interleave is different than the standard DOS 3.3 format. + * Note that the RDOS 2.1/3.2 block interleave is different than the standard DOS 3.3 format. * Thus, when the image is made, the sectors are skewed differently - use readRdosBlock * to read the appropriate block number. *

* Also note that the operating system is itself the first file. Block #0 is really * track 0, sector 0 - meaning that the first file should not (cannot) be deleted. *

- * RDOS appears to have been placed on 13 sector disks. This limits the number of blocks + * RDOS 2.1/3.2 was placed on 13 sector disks. This limits the number of blocks * to 455. It also may also cause incompatibilities with other formats and other cracks. *

* Date created: Oct 7, 2002 2:03:58 PM @@ -52,7 +53,7 @@ import com.webcodepro.applecommander.util.TextBundle; public class RdosFormatDisk extends FormattedDisk { private TextBundle textBundle = StorageBundle.getInstance(); /** - * The RDOS disks are structured in a different order than DOS 3.3. + * RDOS 2.1/3.2 disks are structured in a different order than DOS 3.3. * This table interpolates between the RDOS ordering and the DOS * ordering. It appears that RDOS may use the physical sector number * instead of the logical sector. @@ -66,15 +67,38 @@ public class RdosFormatDisk extends FormattedDisk { */ public static final int ENTRY_LENGTH = 0x20; /** - * Specifies the number of blocks on the disk. + * Specifies the number of tracks on the disk. * RDOS apparantly only worked on 5.25" disks. */ - public static final int BLOCKS_ON_DISK = 455; + public static final int TRACKS_ON_DISK = 35; + /** + * Number of sectors used by catalog. + * FIXME: some sources say 10, others say 11. RDOS 3.3 may support 16. + */ + public static final int CATALOG_SECTORS = 10; /** * The known filetypes for a RDOS disk. */ public static final String[] filetypes = { "B", "A", "T" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + /** + * 13 sectors for RDOS 2.1/3.2, native sectoring (16) for RDOS 3.3 + */ + private int SectorsPerTrack() { + if (getImageOrder() instanceof ProdosOrder) { + return getImageOrder().getSectorsPerTrack(); + } else { + return 13; + } + } + + /** + * 455 blocks for RDOS 2.1/3.2, 560 for RDOS 3.3 + */ + private int BlocksOnDisk() { + return TRACKS_ON_DISK * SectorsPerTrack(); + } + /** * Use this inner interface for managing the disk usage data. * This off-loads format-specific implementation to the implementing class. @@ -93,13 +117,13 @@ public class RdosFormatDisk extends FormattedDisk { private int location = -1; private BitSet bitmap = null; public boolean hasNext() { - return location == -1 || location < BLOCKS_ON_DISK - 1; + return location == -1 || location < BlocksOnDisk() - 1; } public void next() { if (bitmap == null) { - bitmap = new BitSet(BLOCKS_ON_DISK); + bitmap = new BitSet(BlocksOnDisk()); // mark all blocks as unused - for (int b=0; b - * Note that sectorSkew has the full 16 sectors, even though RDOS + * Note that sectorSkew has the full 16 sectors, even though RDOS 2.1/3.2 * itself is a 13 sector format. */ public byte[] readRdosBlock(int block) { - int track = block / 13; - int sector = sectorSkew[block % 13]; + int s = SectorsPerTrack(); + int track = block / s; + int sector = block % s; + if (s == 13) { + sector = sectorSkew[sector]; + } return readSector(track, sector); } /** - * Write an RDOS block. The sector skewing for RDOS seems to be different. + * Write an RDOS block. The sector skewing for RDOS2.1/3/2 is different. * This routine will convert the block number to a DOS track and sector, * handling the sector change-over. The writeSector method then should * take care of various image formats. @@ -165,8 +193,12 @@ public class RdosFormatDisk extends FormattedDisk { * itself is a 13 sector format. */ public void writeRdosBlock(int block, byte[] data) { - int track = block / 13; - int sector = sectorSkew[block % 13]; + int s = SectorsPerTrack(); + int track = block / s; + int sector = block % s; + if (s == 13) { + sector = sectorSkew[sector]; + } writeSector(track, sector, data); } @@ -174,8 +206,15 @@ public class RdosFormatDisk extends FormattedDisk { * RDOS really does not have a disk name. Fake one. */ public String getDiskName() { - byte[] block = readRdosBlock(4); - return AppleUtil.getString(block, 0xe0, 0x20); + if (SectorsPerTrack() == 13) { + /* Use the comment/tag added in the 13->16 sector conversion */ + byte[] block = readRdosBlock(4); + return AppleUtil.getString(block, 0xe0, 0x20); + } else { + /* Use the name of the OS (catalog entry zero) */ + byte[] block = readSector(1, 0x0); + return AppleUtil.getString(block, 0x0, 0x18); + } } /** @@ -183,8 +222,8 @@ public class RdosFormatDisk extends FormattedDisk { */ public List getFiles() { List files = new ArrayList<>(); - for (int b=13; b<23; b++) { - byte[] data = readRdosBlock(b); + for (int b=0; b getDiskInformation() { List list = super.getDiskInformation(); - list.add(new DiskInformation(textBundle.get("TotalBlocks"), BLOCKS_ON_DISK)); //$NON-NLS-1$ + list.add(new DiskInformation(textBundle.get("TotalBlocks"), BlocksOnDisk())); //$NON-NLS-1$ list.add(new DiskInformation(textBundle.get("FreeBlocks"), getFreeBlocks())); //$NON-NLS-1$ list.add(new DiskInformation(textBundle.get("UsedBlocks"), getUsedBlocks())); //$NON-NLS-1$ return list; @@ -407,6 +450,7 @@ public class RdosFormatDisk extends FormattedDisk { * would be) and executes that code for the directory. * AppleCommander will need to either clone the code or write * its own routine. This is RDOS block #25. + * FIXME - Doesn't handle native 16-sector (RDOS 3.3) format. * @see com.webcodepro.applecommander.storage.FormattedDisk#format() */ public void format() { diff --git a/lib/ac-api/src/main/resources/com/webcodepro/applecommander/storage/StorageBundle.properties b/lib/ac-api/src/main/resources/com/webcodepro/applecommander/storage/StorageBundle.properties index 04b730b..d11b430 100644 --- a/lib/ac-api/src/main/resources/com/webcodepro/applecommander/storage/StorageBundle.properties +++ b/lib/ac-api/src/main/resources/com/webcodepro/applecommander/storage/StorageBundle.properties @@ -69,6 +69,7 @@ NibbleOrder.InvalidPhysicalSectorError=Unable to locate physical sector {0} on t # RdosFormatDisk RdosFormatDisk.Rdos21=RDOS 2.1 +RdosFormatDisk.Rdos33=RDOS 3.3 RdosFormatDisk.Size=Size RdosFormatDisk.StartingBlock=Starting Block RdosFormatDisk.Address=Address diff --git a/lib/ac-api/src/test/java/com/webcodepro/applecommander/storage/DiskHelperTest.java b/lib/ac-api/src/test/java/com/webcodepro/applecommander/storage/DiskHelperTest.java index 93ab10e..a45ccca 100644 --- a/lib/ac-api/src/test/java/com/webcodepro/applecommander/storage/DiskHelperTest.java +++ b/lib/ac-api/src/test/java/com/webcodepro/applecommander/storage/DiskHelperTest.java @@ -89,6 +89,21 @@ public class DiskHelperTest { showDirectory(config.getDiskDir() + "/SSIsave.dsk"); //$NON-NLS-1$ } + @Test + public void testPhanta31() throws IOException, DiskException { + FormattedDisk[] disks = showDirectory(config.getDiskDir() + + "/PHANTA31.DSK"); //$NON-NLS-1$ + assertApplesoftFile(disks[0], "PHANTASIE III"); //$NON-NLS-1$ + assertBinaryFile(disks[0], "TWN31"); //$NON-NLS-1$ + assertTextFile(disks[0], "ITEM"); //$NON-NLS-1$ + assertGraphicsFile(disks[0], "ICE DRAGON"); //$NON-NLS-1$ + } + + @Test + public void testPhanta32() throws IOException, DiskException { + showDirectory(config.getDiskDir() + "/PHANTA32.DSK"); //$NON-NLS-1$ + } + @Test public void testPhan2d1() throws IOException, DiskException { FormattedDisk[] disks = showDirectory(config.getDiskDir() diff --git a/lib/ac-api/src/test/resources/disks/PHANTA31.DSK b/lib/ac-api/src/test/resources/disks/PHANTA31.DSK new file mode 100644 index 0000000..1a3f028 Binary files /dev/null and b/lib/ac-api/src/test/resources/disks/PHANTA31.DSK differ diff --git a/lib/ac-api/src/test/resources/disks/PHANTA32.DSK b/lib/ac-api/src/test/resources/disks/PHANTA32.DSK new file mode 100644 index 0000000..c7ca7dd Binary files /dev/null and b/lib/ac-api/src/test/resources/disks/PHANTA32.DSK differ