diff --git a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/DiskFactory.java b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/DiskFactory.java index e1b1f5a4..5f4e183d 100644 --- a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/DiskFactory.java +++ b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/DiskFactory.java @@ -33,6 +33,33 @@ import org.applecommander.util.DataBuffer; import java.util.ArrayList; import java.util.List; +/** + * The DiskFactory inspects a given Source inspect it to see if it matches filesystem structure(s). + * Invoke via {@link Disks#inspect(Source)} which will return a Context. The Context _can be empty_. + * If this is the case, devices can be created via the {@link Context#blockDevice()} and + * {@link Context#trackSectorDevice()} builders. + *
+ * The builders follow the observation about what each filesystem currently uses: + *
+ * OS         13-sector  16-sector   800K    HDV
+ * =========  =========  ==========  ======  ========
+ * CP/M       -          CP/M        -       -
+ * DOS        Physical   DOS         Pascal  -
+ * Gutenberg  -          DOS         -       -
+ * NakeDOS    -          Physical    -       -
+ * Pascal     -          Pascal      Pascal  -
+ * ProDOS     -          Pascal      Pascal  Pascal
+ * RDOS       Physical   DOS         -       -
+ * 
+ * + */ public interface DiskFactory { void inspect(Context ctx); @@ -40,9 +67,6 @@ public interface DiskFactory { public final Source source; public final NibbleTrackReaderWriter nibbleTrackReaderWriter; public final List disks = new ArrayList<>(); - // Note: These are only set if we *KNOW* what they are. Except DSK images, where both will be set. - public final BlockDevice blockDevice; - public final TrackSectorDevice sectorDevice; public Context(Source source) { this.source = source; @@ -50,26 +74,11 @@ public interface DiskFactory { /* Does it have the WOZ1 or WOZ2 header? */ int signature = source.readBytes(0, 4).readInt(); if (WozImage.WOZ1_MAGIC == signature || WozImage.WOZ2_MAGIC == signature) { - blockDevice = null; nibbleTrackReaderWriter = new WozImage(source); - sectorDevice = identifySectorsPerTrack(nibbleTrackReaderWriter); } else if (source.is(Hint.NIBBLE_SECTOR_ORDER) || source.isApproxEQ(DiskConstants.APPLE_140KB_NIBBLE_DISK)) { - blockDevice = null; nibbleTrackReaderWriter = new NibbleImage(source); - sectorDevice = identifySectorsPerTrack(nibbleTrackReaderWriter); - } else if (source.is(Hint.PRODOS_BLOCK_ORDER) || source.getSize() > DiskConstants.APPLE_400KB_DISK || source.extensionLike("po")) { - nibbleTrackReaderWriter = null; - blockDevice = new ProdosOrderedBlockDevice(source, BlockDevice.STANDARD_BLOCK_SIZE); - sectorDevice = null; - } else if (source.is(Hint.DOS_SECTOR_ORDER) || source.extensionLike("do")) { - nibbleTrackReaderWriter = null; - blockDevice = null; - sectorDevice = new DosOrderedTrackSectorDevice(source, Hint.DOS_SECTOR_ORDER); } else { nibbleTrackReaderWriter = null; - // Could be either - most likely the nebulous "dsk" extension - blockDevice = new ProdosOrderedBlockDevice(source, BlockDevice.STANDARD_BLOCK_SIZE); - sectorDevice = new DosOrderedTrackSectorDevice(source); } } @@ -111,5 +120,141 @@ public interface DiskFactory { // Failure return null; } + + public BlockDeviceBuilder blockDevice() { + return new BlockDeviceBuilder(this); + } + public static class BlockDeviceBuilder { + private Context ctx; + private List devices = new ArrayList<>(); + private BlockDeviceBuilder(Context ctx) { + this.ctx = ctx; + } + public BlockDeviceBuilder include16Sector(Hint hint) { + if (ctx.nibbleTrackReaderWriter != null) { + TrackSectorDevice nibble = ctx.identifySectorsPerTrack(ctx.nibbleTrackReaderWriter); + if (nibble != null) { + TrackSectorDevice converted = switch (hint) { + case DOS_SECTOR_ORDER -> SkewedTrackSectorDevice.physicalToDosSkew(nibble); + case PRODOS_BLOCK_ORDER -> SkewedTrackSectorDevice.physicalToPascalSkew(nibble); + case NIBBLE_SECTOR_ORDER -> nibble; + default -> throw new RuntimeException("wrong hint type: " + hint); + }; + devices.add(new TrackSectorToBlockAdapter(converted, TrackSectorToBlockAdapter.BlockStyle.PRODOS)); + } + } + else if (ctx.source.isApproxEQ(DiskConstants.APPLE_140KB_DISK)) { + if (ctx.source.is(Hint.DOS_SECTOR_ORDER) || ctx.source.extensionLike("do")) { + TrackSectorDevice doDevice = new DosOrderedTrackSectorDevice(ctx.source, Hint.DOS_SECTOR_ORDER); + TrackSectorDevice poDevice = SkewedTrackSectorDevice.dosToPascalSkew(doDevice); + devices.add(new TrackSectorToBlockAdapter(poDevice, TrackSectorToBlockAdapter.BlockStyle.PRODOS)); + } + else if (ctx.source.is(Hint.PRODOS_BLOCK_ORDER) || ctx.source.extensionLike("po")) { + devices.add(new ProdosOrderedBlockDevice(ctx.source, BlockDevice.STANDARD_BLOCK_SIZE)); + } + else { + devices.add(new ProdosOrderedBlockDevice(ctx.source, BlockDevice.STANDARD_BLOCK_SIZE)); + TrackSectorDevice doDevice = new DosOrderedTrackSectorDevice(ctx.source, Hint.DOS_SECTOR_ORDER); + TrackSectorDevice poDevice = SkewedTrackSectorDevice.dosToPascalSkew(doDevice); + devices.add(new TrackSectorToBlockAdapter(poDevice, TrackSectorToBlockAdapter.BlockStyle.PRODOS)); + } + } + return this; + } + public BlockDeviceBuilder include800K() { + if (ctx.source.isApproxEQ(DiskConstants.APPLE_800KB_DISK)) { + devices.add(new ProdosOrderedBlockDevice(ctx.source, BlockDevice.STANDARD_BLOCK_SIZE)); + } + return this; + } + public BlockDeviceBuilder includeHDV() { + if (ctx.source.getSize() > DiskConstants.APPLE_800KB_DISK) { + devices.add(new ProdosOrderedBlockDevice(ctx.source, BlockDevice.STANDARD_BLOCK_SIZE)); + } + return this; + } + public List get() { + return devices; + } + } + + public TrackSectorDeviceBuilder trackSectorDevice() { + return new TrackSectorDeviceBuilder(this); + } + public static class TrackSectorDeviceBuilder { + private Context ctx; + private List devices = new ArrayList<>(); + private TrackSectorDeviceBuilder(Context ctx) { + this.ctx = ctx; + } + public TrackSectorDeviceBuilder include13Sector() { + if (ctx.nibbleTrackReaderWriter != null) { + TrackSectorDevice nibble = ctx.identifySectorsPerTrack(ctx.nibbleTrackReaderWriter); + if (nibble != null && nibble.getGeometry().sectorsPerTrack() == 13) { + devices.add(nibble); + } + } + return this; + } + public TrackSectorDeviceBuilder include16Sector(Hint hint) { + if (ctx.nibbleTrackReaderWriter != null) { + TrackSectorDevice nibble = ctx.identifySectorsPerTrack(ctx.nibbleTrackReaderWriter); + if (nibble != null && nibble.getGeometry().sectorsPerTrack() == 16) { + TrackSectorDevice converted = switch (hint) { + case DOS_SECTOR_ORDER -> SkewedTrackSectorDevice.physicalToDosSkew(nibble); + case PRODOS_BLOCK_ORDER -> SkewedTrackSectorDevice.physicalToPascalSkew(nibble); + case NIBBLE_SECTOR_ORDER -> nibble; + default -> throw new RuntimeException("wrong hint type: " + hint); + }; + devices.add(converted); + } + } else if (ctx.source.isApproxEQ(DiskConstants.APPLE_140KB_DISK)) { + TrackSectorDevice doDevice = null; + TrackSectorDevice poDevice = null; + if (ctx.source.is(Hint.DOS_SECTOR_ORDER) || ctx.source.extensionLike("do")) { + doDevice = new DosOrderedTrackSectorDevice(ctx.source, Hint.DOS_SECTOR_ORDER); + } + else if (ctx.source.is(Hint.PRODOS_BLOCK_ORDER) || ctx.source.extensionLike("po")) { + poDevice = new DosOrderedTrackSectorDevice(ctx.source, Hint.PRODOS_BLOCK_ORDER); + } + else { + doDevice = new DosOrderedTrackSectorDevice(ctx.source, Hint.DOS_SECTOR_ORDER); + poDevice = new DosOrderedTrackSectorDevice(ctx.source, Hint.PRODOS_BLOCK_ORDER); + } + switch (hint) { + case DOS_SECTOR_ORDER -> { + if (doDevice != null) { + devices.add(doDevice); + } + if (poDevice != null) { + TrackSectorDevice tmp = SkewedTrackSectorDevice.pascalToPhysicalSkew(poDevice); + devices.add(SkewedTrackSectorDevice.physicalToDosSkew(tmp)); + } + } + case PRODOS_BLOCK_ORDER -> { + if (doDevice != null) { + TrackSectorDevice tmp = SkewedTrackSectorDevice.dosToPhysicalSkew(doDevice); + devices.add(SkewedTrackSectorDevice.physicalToPascalSkew(tmp)); + } + if (poDevice != null) { + devices.add(poDevice); + } + } + case NIBBLE_SECTOR_ORDER -> { + if (doDevice != null) { + devices.add(SkewedTrackSectorDevice.dosToPhysicalSkew(doDevice)); + } + if (poDevice != null) { + devices.add(SkewedTrackSectorDevice.pascalToPhysicalSkew(poDevice)); + } + } + } + } + return this; + } + public List get() { + return devices; + } + } } } diff --git a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/cpm/CpmDiskFactory.java b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/cpm/CpmDiskFactory.java index 129f0787..bb241d04 100644 --- a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/cpm/CpmDiskFactory.java +++ b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/cpm/CpmDiskFactory.java @@ -19,15 +19,11 @@ */ package com.webcodepro.applecommander.storage.os.cpm; -import com.webcodepro.applecommander.storage.DiskConstants; import com.webcodepro.applecommander.storage.DiskFactory; import org.applecommander.device.*; import org.applecommander.hint.Hint; import org.applecommander.util.DataBuffer; -import java.util.ArrayList; -import java.util.List; - /** * Test this disk for a likely CP/M filesystem. * @see CP/M 2.2 @@ -36,42 +32,18 @@ import java.util.List; public class CpmDiskFactory implements DiskFactory { @Override public void inspect(Context ctx) { - List devices = new ArrayList<>(); - if (ctx.sectorDevice != null) { - if (ctx.sectorDevice.is(Hint.NIBBLE_SECTOR_ORDER)) { - // cheating so I don't need to figure out physical to CP/M skew! - TrackSectorDevice dosSkew = SkewedTrackSectorDevice.physicalToDosSkew(ctx.sectorDevice); - devices.add(SkewedTrackSectorDevice.dosToCpmSkew(dosSkew)); - } - else if (ctx.sectorDevice.is(Hint.DOS_SECTOR_ORDER)) { - devices.add(SkewedTrackSectorDevice.dosToCpmSkew(ctx.sectorDevice)); - } - else if (ctx.sectorDevice.is(Hint.PRODOS_BLOCK_ORDER)) { - devices.add(SkewedTrackSectorDevice.pascalToCpmSkew(ctx.sectorDevice)); - } - else { - // Presumably a DSK image, so DO and PO are possibilities - devices.add(SkewedTrackSectorDevice.dosToCpmSkew(ctx.sectorDevice)); - devices.add(SkewedTrackSectorDevice.pascalToCpmSkew(ctx.sectorDevice)); - } - } - else if (ctx.blockDevice != null) { - if (ctx.blockDevice.getGeometry().blocksOnDevice() == 280) { - TrackSectorDevice device = new BlockToTrackSectorAdapter(ctx.blockDevice, - new ProdosBlockToTrackSectorAdapterStrategy()); - devices.add(SkewedTrackSectorDevice.pascalToCpmSkew(device)); - } - } - // Any devices in the list are expected to be in CP/M block order - devices.forEach(device -> { - if (device.getGeometry().sectorsPerDisk() == 560) { - BlockDevice blockDevice = new TrackSectorToBlockAdapter(device, TrackSectorToBlockAdapter.BlockStyle.CPM); - CpmFormatDisk disk = new CpmFormatDisk(ctx.source.getName(), blockDevice); - if (check(disk)) { - ctx.disks.add(disk); - } - } - }); + ctx.trackSectorDevice() + .include16Sector(Hint.DOS_SECTOR_ORDER) + .get() + .forEach(device -> { + BlockDevice blockDevice = new TrackSectorToBlockAdapter( + SkewedTrackSectorDevice.dosToCpmSkew(device), + TrackSectorToBlockAdapter.BlockStyle.CPM); + CpmFormatDisk disk = new CpmFormatDisk(ctx.source.getName(), blockDevice); + if (check(disk)) { + ctx.disks.add(disk); + } + }); } public boolean check(CpmFormatDisk disk) { diff --git a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/dos33/DosDiskFactory.java b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/dos33/DosDiskFactory.java index 1a6bc6ab..f14dc990 100644 --- a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/dos33/DosDiskFactory.java +++ b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/dos33/DosDiskFactory.java @@ -21,14 +21,11 @@ package com.webcodepro.applecommander.storage.os.dos33; import com.webcodepro.applecommander.storage.DiskFactory; import org.applecommander.device.BlockToTrackSectorAdapter; -import org.applecommander.device.ProdosBlockToTrackSectorAdapterStrategy; -import org.applecommander.device.SkewedTrackSectorDevice; import org.applecommander.device.TrackSectorDevice; import org.applecommander.hint.Hint; import org.applecommander.os.dos.OzdosAdapterStrategy; import org.applecommander.os.dos.UnidosAdapterStrategy; import org.applecommander.util.DataBuffer; -import static com.webcodepro.applecommander.storage.DiskConstants.*; import static com.webcodepro.applecommander.storage.os.dos33.DosFormatDisk.*; import java.util.*; @@ -37,53 +34,45 @@ public class DosDiskFactory implements DiskFactory { @Override public void inspect(Context ctx) { // It seems easiest to gather all possibilities first... - List devices = new ArrayList<>(); - // We need DOS ordered... - if (ctx.sectorDevice != null) { - if (ctx.sectorDevice.is(Hint.NIBBLE_SECTOR_ORDER)) { - if (ctx.sectorDevice.getGeometry().sectorsPerTrack() == 13) { - // 13-sector = DOS 3.2 = physical sector order - devices.add(ctx.sectorDevice); - } - else { - // 16-sector = DOS 3.3 = DOS sector order - devices.add(SkewedTrackSectorDevice.physicalToDosSkew(ctx.sectorDevice)); - } - } - else if (ctx.sectorDevice.is(Hint.DOS_SECTOR_ORDER)) { - devices.add(ctx.sectorDevice); - } - else if (ctx.sectorDevice.is(Hint.PRODOS_BLOCK_ORDER)) { - // Cheating a bit... - TrackSectorDevice tmp = SkewedTrackSectorDevice.pascalToPhysicalSkew(ctx.sectorDevice); - devices.add(SkewedTrackSectorDevice.physicalToDosSkew(tmp)); - } - else { - // Likely a DSK image, need to pick between DO and PO... - TrackSectorDevice device1 = ctx.sectorDevice; - // Cheating a bit... - TrackSectorDevice tmp = SkewedTrackSectorDevice.pascalToPhysicalSkew(ctx.sectorDevice); - TrackSectorDevice device2 = SkewedTrackSectorDevice.physicalToDosSkew(tmp); + final List devices = new ArrayList<>(); - int count1 = count(device1); - int count2 = count(device2); - // Note this assumes DO was the first device in the list to give it an edge - if (count1 >= count2) devices.add(device1); - else devices.add(device2); - } - } - else if (ctx.blockDevice != null) { - if (ctx.blockDevice.getGeometry().blocksOnDevice() == PRODOS_BLOCKS_ON_140KB_DISK) { - devices.add(new BlockToTrackSectorAdapter(ctx.blockDevice, new ProdosBlockToTrackSectorAdapterStrategy())); - } - else if (ctx.blockDevice.getGeometry().blocksOnDevice() == PRODOS_BLOCKS_ON_800KB_DISK) { - devices.add(new BlockToTrackSectorAdapter(ctx.blockDevice, UnidosAdapterStrategy.UNIDOS_DISK_1)); - devices.add(new BlockToTrackSectorAdapter(ctx.blockDevice, UnidosAdapterStrategy.UNIDOS_DISK_2)); - devices.add(new BlockToTrackSectorAdapter(ctx.blockDevice, OzdosAdapterStrategy.OZDOS_DISK_1)); - devices.add(new BlockToTrackSectorAdapter(ctx.blockDevice, OzdosAdapterStrategy.OZDOS_DISK_2)); + // Look for DOS on 13-sector and 16-sector devices: + devices.addAll(ctx.trackSectorDevice() + .include13Sector() + .include16Sector(Hint.DOS_SECTOR_ORDER) + .get()); + if (devices.size() == 2) { + // Likely a DSK image, need to pick between DO and PO... + TrackSectorDevice doDevice = null; + TrackSectorDevice poDevice = null; + for (TrackSectorDevice device : devices) { + if (device.is(Hint.DOS_SECTOR_ORDER) && doDevice == null) { + doDevice = device; + } + else if (device.is(Hint.PRODOS_BLOCK_ORDER) && poDevice == null) { + poDevice = device; + } } + if (doDevice == null || poDevice == null) { + throw new RuntimeException("unexpected situation: device is neither PO or DO -or- we have more than 1"); + } + int doCount = count(doDevice); + int poCount = count(poDevice); + // Keep the one with the most catalog sectors (slight edge to DO) + devices.remove(doCount >= poCount ? poDevice : doDevice); } + // Look for 800K block devices to find UniDOS or OzDOS: + ctx.blockDevice() + .include800K() + .get() + .forEach(blockDevice -> { + devices.add(new BlockToTrackSectorAdapter(blockDevice, UnidosAdapterStrategy.UNIDOS_DISK_1)); + devices.add(new BlockToTrackSectorAdapter(blockDevice, UnidosAdapterStrategy.UNIDOS_DISK_2)); + devices.add(new BlockToTrackSectorAdapter(blockDevice, OzdosAdapterStrategy.OZDOS_DISK_1)); + devices.add(new BlockToTrackSectorAdapter(blockDevice, OzdosAdapterStrategy.OZDOS_DISK_2)); + }); + // ... and then test for DOS VTOC etc. Passing track number along to hopefully handle it later! for (TrackSectorDevice device : devices) { if (check(device)) { diff --git a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/gutenberg/GutenbergDiskFactory.java b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/gutenberg/GutenbergDiskFactory.java index 0044dc1e..d3204dd2 100644 --- a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/gutenberg/GutenbergDiskFactory.java +++ b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/gutenberg/GutenbergDiskFactory.java @@ -21,53 +21,23 @@ package com.webcodepro.applecommander.storage.os.gutenberg; import com.webcodepro.applecommander.storage.DiskConstants; import com.webcodepro.applecommander.storage.DiskFactory; -import org.applecommander.device.BlockToTrackSectorAdapter; -import org.applecommander.device.ProdosBlockToTrackSectorAdapterStrategy; -import org.applecommander.device.SkewedTrackSectorDevice; import org.applecommander.device.TrackSectorDevice; import org.applecommander.hint.Hint; import org.applecommander.util.DataBuffer; -import java.util.ArrayList; -import java.util.List; - import static com.webcodepro.applecommander.storage.os.gutenberg.GutenbergFormatDisk.*; public class GutenbergDiskFactory implements DiskFactory { @Override public void inspect(Context ctx) { - List devices = new ArrayList<>(); - // We need DOS ordered... - if (ctx.sectorDevice != null) { - if (ctx.sectorDevice.is(Hint.NIBBLE_SECTOR_ORDER)) { - devices.add(SkewedTrackSectorDevice.physicalToDosSkew(ctx.sectorDevice)); - } - else if (ctx.sectorDevice.is(Hint.DOS_SECTOR_ORDER)) { - devices.add(ctx.sectorDevice); - } - else if (ctx.sectorDevice.is(Hint.PRODOS_BLOCK_ORDER)) { - // Cheating a bit... - TrackSectorDevice tmp = SkewedTrackSectorDevice.pascalToPhysicalSkew(ctx.sectorDevice); - devices.add(SkewedTrackSectorDevice.physicalToDosSkew(tmp)); - } - else { - // Likely a DSK image - devices.add(ctx.sectorDevice); - // Cheating a bit... - TrackSectorDevice tmp = SkewedTrackSectorDevice.pascalToPhysicalSkew(ctx.sectorDevice); - devices.add(SkewedTrackSectorDevice.physicalToDosSkew(tmp)); - } - } - else if (ctx.blockDevice != null) { - TrackSectorDevice po = new BlockToTrackSectorAdapter(ctx.blockDevice, new ProdosBlockToTrackSectorAdapterStrategy()); - TrackSectorDevice tmp = SkewedTrackSectorDevice.pascalToPhysicalSkew(po); - devices.add(SkewedTrackSectorDevice.physicalToDosSkew(tmp)); - } - devices.forEach(device -> { - if (check(device)) { - ctx.disks.add(new GutenbergFormatDisk(ctx.source.getName(), device)); - } - }); + ctx.trackSectorDevice() + .include16Sector(Hint.DOS_SECTOR_ORDER) + .get() + .forEach(device -> { + if (check(device)) { + ctx.disks.add(new GutenbergFormatDisk(ctx.source.getName(), device)); + } + }); } public boolean check(TrackSectorDevice order) { diff --git a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/nakedos/NakedosDiskFactory.java b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/nakedos/NakedosDiskFactory.java index b0783235..1a36b7b9 100644 --- a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/nakedos/NakedosDiskFactory.java +++ b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/nakedos/NakedosDiskFactory.java @@ -20,46 +20,21 @@ package com.webcodepro.applecommander.storage.os.nakedos; import com.webcodepro.applecommander.storage.DiskFactory; -import org.applecommander.device.BlockToTrackSectorAdapter; -import org.applecommander.device.ProdosBlockToTrackSectorAdapterStrategy; -import org.applecommander.device.SkewedTrackSectorDevice; import org.applecommander.device.TrackSectorDevice; import org.applecommander.hint.Hint; import org.applecommander.util.DataBuffer; -import java.util.ArrayList; -import java.util.List; - public class NakedosDiskFactory implements DiskFactory { @Override public void inspect(Context ctx) { - List devices = new ArrayList<>(); - // NakeDOS expects "physical" sector ordering - if (ctx.sectorDevice != null) { - if (ctx.sectorDevice.is(Hint.NIBBLE_SECTOR_ORDER)) { - devices.add(ctx.sectorDevice); - } - else if (ctx.sectorDevice.is(Hint.DOS_SECTOR_ORDER)) { - devices.add(SkewedTrackSectorDevice.dosToPhysicalSkew(ctx.sectorDevice)); - } - else if (ctx.sectorDevice.is(Hint.PRODOS_BLOCK_ORDER)) { - devices.add(SkewedTrackSectorDevice.pascalToPhysicalSkew(ctx.sectorDevice)); - } - else { - devices.add(SkewedTrackSectorDevice.dosToPhysicalSkew(ctx.sectorDevice)); - devices.add(SkewedTrackSectorDevice.pascalToPhysicalSkew(ctx.sectorDevice)); - } - } - else if (ctx.blockDevice != null) { - devices.add(SkewedTrackSectorDevice.pascalToPhysicalSkew(new BlockToTrackSectorAdapter( - ctx.blockDevice, new ProdosBlockToTrackSectorAdapterStrategy()))); - } - - devices.forEach(device -> { - if (check(device)) { - ctx.disks.add(new NakedosFormatDisk(ctx.source.getName(), device)); - } - }); + ctx.trackSectorDevice() + .include16Sector(Hint.NIBBLE_SECTOR_ORDER) + .get() + .forEach(device -> { + if (check(device)) { + ctx.disks.add(new NakedosFormatDisk(ctx.source.getName(), device)); + } + }); } public boolean check(TrackSectorDevice device) { diff --git a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/pascal/PascalDiskFactory.java b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/pascal/PascalDiskFactory.java index a59e8e84..4d3846e6 100644 --- a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/pascal/PascalDiskFactory.java +++ b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/pascal/PascalDiskFactory.java @@ -22,50 +22,24 @@ package com.webcodepro.applecommander.storage.os.pascal; import com.webcodepro.applecommander.storage.DiskConstants; import com.webcodepro.applecommander.storage.DiskFactory; import org.applecommander.device.BlockDevice; -import org.applecommander.device.SkewedTrackSectorDevice; -import org.applecommander.device.TrackSectorDevice; -import org.applecommander.device.TrackSectorToBlockAdapter; import org.applecommander.hint.Hint; import org.applecommander.util.DataBuffer; -import java.util.ArrayList; -import java.util.List; - /** * Automatic discovery of Pascal volumes. */ public class PascalDiskFactory implements DiskFactory { @Override public void inspect(Context ctx) { - List devices = new ArrayList<>(); - if (ctx.blockDevice != null) { - devices.add(ctx.blockDevice); - } - if (ctx.sectorDevice != null && ctx.sectorDevice.getGeometry().sectorsPerDisk() <= 1600) { - if (ctx.sectorDevice.is(Hint.NIBBLE_SECTOR_ORDER)) { - TrackSectorDevice skewed = SkewedTrackSectorDevice.physicalToPascalSkew(ctx.sectorDevice); - devices.add(new TrackSectorToBlockAdapter(skewed, TrackSectorToBlockAdapter.BlockStyle.PASCAL)); - } - else if (ctx.sectorDevice.is(Hint.DOS_SECTOR_ORDER)) { - TrackSectorDevice skewed = SkewedTrackSectorDevice.dosToPascalSkew(ctx.sectorDevice); - devices.add(new TrackSectorToBlockAdapter(skewed, TrackSectorToBlockAdapter.BlockStyle.PASCAL)); - } - else { - // Likely a DSK image, need to pick between DO and PO... - // Try DO - TrackSectorDevice device1 = SkewedTrackSectorDevice.dosToPascalSkew(ctx.sectorDevice); - devices.add(new TrackSectorToBlockAdapter(device1, TrackSectorToBlockAdapter.BlockStyle.PRODOS)); - // Try PO - TrackSectorDevice device2 = ctx.sectorDevice; - devices.add(new TrackSectorToBlockAdapter(device2, TrackSectorToBlockAdapter.BlockStyle.PRODOS)); - } - } - - devices.forEach(device -> { - if (check(device)) { - ctx.disks.add(new PascalFormatDisk(ctx.source.getName(), device)); - } - }); + ctx.blockDevice() + .include16Sector(Hint.PRODOS_BLOCK_ORDER) + .include800K() + .get() + .forEach(device -> { + if (check(device)) { + ctx.disks.add(new PascalFormatDisk(ctx.source.getName(), device)); + } + }); } /** Check for a likely directory structure. Note that we scan all sizes, even though that is overkill. */ diff --git a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/prodos/ProdosDiskFactory.java b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/prodos/ProdosDiskFactory.java index b00019ef..4f68c200 100644 --- a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/prodos/ProdosDiskFactory.java +++ b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/prodos/ProdosDiskFactory.java @@ -21,59 +21,28 @@ package com.webcodepro.applecommander.storage.os.prodos; import com.webcodepro.applecommander.storage.DiskFactory; import org.applecommander.device.BlockDevice; -import org.applecommander.device.SkewedTrackSectorDevice; -import org.applecommander.device.TrackSectorDevice; -import org.applecommander.device.TrackSectorToBlockAdapter; import org.applecommander.hint.Hint; import org.applecommander.util.DataBuffer; import static com.webcodepro.applecommander.storage.DiskConstants.*; -import java.util.ArrayList; -import java.util.List; - public class ProdosDiskFactory implements DiskFactory { @Override public void inspect(Context ctx) { - // It seems easiest to gather all possibilities first... - List tests = new ArrayList<>(); - if (ctx.blockDevice != null) { - tests.add(new ProdosFormatDisk(ctx.source.getName(), ctx.blockDevice)); - } - if (ctx.sectorDevice != null && ctx.sectorDevice.getGeometry().sectorsPerDisk() <= 1600) { - TrackSectorDevice skewed = null; - if (ctx.sectorDevice.is(Hint.NIBBLE_SECTOR_ORDER)) { - skewed = SkewedTrackSectorDevice.physicalToPascalSkew(ctx.sectorDevice); - BlockDevice device = new TrackSectorToBlockAdapter(skewed, TrackSectorToBlockAdapter.BlockStyle.PRODOS); - tests.add(new ProdosFormatDisk(ctx.source.getName(), device)); - } - else if (ctx.sectorDevice.is(Hint.DOS_SECTOR_ORDER)) { - skewed = SkewedTrackSectorDevice.dosToPascalSkew(ctx.sectorDevice); - BlockDevice device = new TrackSectorToBlockAdapter(skewed, TrackSectorToBlockAdapter.BlockStyle.PRODOS); - tests.add(new ProdosFormatDisk(ctx.source.getName(), device)); - } - else { - // Likely a DSK image, need to pick between DO and PO... - // Try DO - TrackSectorDevice device1 = SkewedTrackSectorDevice.dosToPascalSkew(ctx.sectorDevice); - tests.add(new ProdosFormatDisk(ctx.source.getName(), new TrackSectorToBlockAdapter(device1, - TrackSectorToBlockAdapter.BlockStyle.PRODOS))); - // Try PO - TrackSectorDevice device2 = ctx.sectorDevice; - tests.add(new ProdosFormatDisk(ctx.source.getName(), new TrackSectorToBlockAdapter(device2, - TrackSectorToBlockAdapter.BlockStyle.PRODOS))); - } - } - // ... and then test for ProDOS details: - for (ProdosFormatDisk fdisk : tests) { - if (check(fdisk)) { - ctx.disks.add(fdisk); - } - } + ctx.blockDevice() + .include16Sector(Hint.PRODOS_BLOCK_ORDER) + .include800K() + .includeHDV() + .get() + .forEach(device -> { + if (check(device)) { + ctx.disks.add(new ProdosFormatDisk(ctx.source.getName(), device)); + } + }); } - public boolean check(ProdosFormatDisk fdisk) { + public boolean check(BlockDevice device) { int nextBlock = 2; - DataBuffer volumeDirectory = DataBuffer.wrap(fdisk.readBlock(nextBlock)); + DataBuffer volumeDirectory = device.readBlock(nextBlock); int priorBlock = volumeDirectory.getUnsignedShort(0x00); int storageType = volumeDirectory.getUnsignedByte(0x04) >> 4; int entryLength = volumeDirectory.getUnsignedByte(0x23); @@ -109,7 +78,7 @@ public class ProdosDiskFactory implements DiskFactory { nextBlock = volumeDirectory.getUnsignedShort(0x02); if (nextBlock == 0) break; if (nextBlock >= totalBlocks) return false; - volumeDirectory = DataBuffer.wrap(fdisk.readBlock(nextBlock)); + volumeDirectory = device.readBlock(nextBlock); } return good; } diff --git a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/rdos/RdosDiskFactory.java b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/rdos/RdosDiskFactory.java index 7c15afb7..4c1744a1 100644 --- a/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/rdos/RdosDiskFactory.java +++ b/lib/ac-api/src/main/java/com/webcodepro/applecommander/storage/os/rdos/RdosDiskFactory.java @@ -29,8 +29,6 @@ import org.applecommander.util.DataBuffer; import static com.webcodepro.applecommander.storage.DiskConstants.DOS32_SECTORS_ON_115KB_DISK; import static com.webcodepro.applecommander.storage.os.rdos.RdosFormatDisk.*; -import java.util.ArrayList; -import java.util.List; import java.util.Set; public class RdosDiskFactory implements DiskFactory { @@ -38,50 +36,24 @@ public class RdosDiskFactory implements DiskFactory { @Override public void inspect(Context ctx) { - List devices = new ArrayList<>(); - if (ctx.sectorDevice != null) { - if (ctx.sectorDevice.is(Hint.NIBBLE_SECTOR_ORDER)) { - if (ctx.sectorDevice.getGeometry().sectorsPerTrack() == 13) { - devices.add(ctx.sectorDevice); - } - else { - devices.add(SkewedTrackSectorDevice.physicalToDosSkew(ctx.sectorDevice)); - } - } - else if (ctx.sectorDevice.is(Hint.DOS_SECTOR_ORDER)) { - devices.add(ctx.sectorDevice); - } - else if (ctx.sectorDevice.is(Hint.PRODOS_BLOCK_ORDER)) { - // cheating a bit here - TrackSectorDevice physicalSkew = SkewedTrackSectorDevice.pascalToPhysicalSkew(ctx.sectorDevice); - devices.add(SkewedTrackSectorDevice.physicalToDosSkew(physicalSkew)); - } - else { - // DSK image. Could be DO or PO. - devices.add(ctx.sectorDevice); - // cheating a bit here for PO - TrackSectorDevice physicalSkew = SkewedTrackSectorDevice.pascalToPhysicalSkew(ctx.sectorDevice); - devices.add(SkewedTrackSectorDevice.physicalToDosSkew(physicalSkew)); - } - } - if (ctx.blockDevice != null) { - devices.add(new BlockToTrackSectorAdapter(ctx.blockDevice, new ProdosBlockToTrackSectorAdapterStrategy())); - } - - devices.forEach(device -> { - int sectorsPerTrack = check(device); - if (sectorsPerTrack > 0) { - // Detect if we're a 16 sector disk but RDOS expects only 13 sectors: - if (sectorsPerTrack != device.getGeometry().sectorsPerTrack()) { - // 13-sector disks are in physical order, so fix it: - device = SkewedTrackSectorDevice.dosToPhysicalSkew(device); - // And make the 16-sector disk a fake 13-sector disk: - device = SkewedTrackSectorDevice.truncate16sectorTo13(device); - } - BlockDevice blockDevice = new TrackSectorToBlockAdapter(device, TrackSectorToBlockAdapter.BlockStyle.RDOS); - ctx.disks.add(new RdosFormatDisk(ctx.source.getName(), blockDevice)); - } - }); + ctx.trackSectorDevice() + .include13Sector() + .include16Sector(Hint.DOS_SECTOR_ORDER) + .get() + .forEach(device -> { + int sectorsPerTrack = check(device); + if (sectorsPerTrack > 0) { + // Detect if we're a 16 sector disk but RDOS expects only 13 sectors: + if (sectorsPerTrack != device.getGeometry().sectorsPerTrack()) { + // 13-sector disks are in physical order, so fix it: + device = SkewedTrackSectorDevice.dosToPhysicalSkew(device); + // And make the 16-sector disk a fake 13-sector disk: + device = SkewedTrackSectorDevice.truncate16sectorTo13(device); + } + BlockDevice blockDevice = new TrackSectorToBlockAdapter(device, TrackSectorToBlockAdapter.BlockStyle.RDOS); + ctx.disks.add(new RdosFormatDisk(ctx.source.getName(), blockDevice)); + } + }); } /**