Making PascalFormatDisk use BlockDevice.

This commit is contained in:
Rob Greene
2025-08-28 22:12:30 -05:00
parent db514fbee2
commit ad13e644c2
7 changed files with 66 additions and 49 deletions
@@ -21,7 +21,8 @@ package com.webcodepro.applecommander.storage.os.pascal;
import com.webcodepro.applecommander.storage.DiskConstants;
import com.webcodepro.applecommander.storage.DiskFactory;
import com.webcodepro.applecommander.storage.physical.ImageOrder;
import org.applecommander.device.BlockDevice;
import org.applecommander.device.TrackSectorToBlockAdapter;
import org.applecommander.util.DataBuffer;
/**
@@ -30,22 +31,28 @@ import org.applecommander.util.DataBuffer;
public class PascalDiskFactory implements DiskFactory {
@Override
public void inspect(Context ctx) {
ctx.orders.forEach(order -> {
if (check(order)) {
ctx.disks.add(new PascalFormatDisk(ctx.source.getName(), order));
if (ctx.blockDevice != null) {
if (check(ctx.blockDevice)) {
ctx.disks.add(new PascalFormatDisk(ctx.source.getName(), ctx.blockDevice));
}
});
}
if (ctx.sectorDevice != null && ctx.sectorDevice.getGeometry().sectorsPerDisk() <= 1600) {
BlockDevice device = new TrackSectorToBlockAdapter(ctx.sectorDevice);
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. */
public boolean check(ImageOrder order) {
public boolean check(BlockDevice device) {
boolean good = false;
if (order.getPhysicalSize() >= DiskConstants.APPLE_140KB_DISK) {
if (device.getGeometry().blockSize() >= DiskConstants.PRODOS_BLOCKS_ON_140KB_DISK) {
// Read entire directory for analysis
DataBuffer dir = DataBuffer.create(2048);
for (int block=2; block<6; block++) {
byte[] data = order.readBlock(block);
dir.put((block-2)* DiskConstants.BLOCK_SIZE, DataBuffer.wrap(data));
DataBuffer data = device.readBlock(block);
dir.put((block-2)*DiskConstants.BLOCK_SIZE, data);
}
// Check volume entry
int dFirstBlock = dir.getUnsignedShort(0);
@@ -22,9 +22,13 @@
package com.webcodepro.applecommander.storage.os.pascal;
import com.webcodepro.applecommander.storage.*;
import com.webcodepro.applecommander.storage.physical.ImageOrder;
import com.webcodepro.applecommander.util.AppleUtil;
import com.webcodepro.applecommander.util.TextBundle;
import org.applecommander.device.BlockDevice;
import org.applecommander.source.Source;
import org.applecommander.util.Container;
import org.applecommander.util.DataBuffer;
import static com.webcodepro.applecommander.storage.DiskConstants.*;
import java.util.*;
@@ -36,7 +40,7 @@ import java.util.*;
* @author Rob Greene
* @author John B. Matthews [getFiles(), get/putDirectory(), createFile()]
*/
public class PascalFormatDisk extends FormattedDiskX {
public class PascalFormatDisk extends FormattedDisk implements Container {
private TextBundle textBundle = StorageBundle.getInstance();
/**
* The size of the Pascal file entry.
@@ -113,24 +117,39 @@ public class PascalFormatDisk extends FormattedDiskX {
return !bitmap.get(location); // false = used
}
}
private BlockDevice device;
/**
* Constructor for PascalFormatDisk.
*/
public PascalFormatDisk(String filename, ImageOrder imageOrder) {
super(filename, imageOrder);
public PascalFormatDisk(String filename, BlockDevice device) {
super(filename, device.get(Source.class).orElseThrow());
this.device = device;
}
/**
* Create a PascalFormatDisk.
*/
public static PascalFormatDisk[] create(String filename, String volumeName, ImageOrder imageOrder) {
PascalFormatDisk disk = new PascalFormatDisk(filename, imageOrder);
public static PascalFormatDisk[] create(String filename, String volumeName, BlockDevice device) {
PascalFormatDisk disk = new PascalFormatDisk(filename, device);
disk.format();
disk.setDiskName(volumeName);
return new PascalFormatDisk[] { disk };
}
protected byte[] readBlock(int block) {
return device.readBlock(block).asBytes();
}
protected void writeBlock(int block, byte[] data) {
device.writeBlock(block, DataBuffer.wrap(data));
}
@Override
public <T> Optional<T> get(Class<T> iface) {
return Container.get(iface, device);
}
/**
* Identify the operating system format of this disk.
* @see com.webcodepro.applecommander.storage.FormattedDisk#getFormat()
@@ -554,15 +573,17 @@ public class PascalFormatDisk extends FormattedDiskX {
* @see com.webcodepro.applecommander.storage.FormattedDisk#format()
*/
public void format() {
getImageOrder().format();
writeBootCode();
device.format();
DataBuffer bootBlock = DataBuffer.create(BLOCK_SIZE);
bootBlock.put(0, DataBuffer.wrap(getBootCode()));
device.writeBlock(0, bootBlock);
// Create volume name
byte[] directory = readDirectory();
AppleUtil.setWordValue(directory, 0, 0); // always 0
AppleUtil.setWordValue(directory, 2, 6); // last directory block
AppleUtil.setWordValue(directory, 4, 0); // entry type (0=vol header)
// volume name should have been set in constructor!
int blocks = getImageOrder().getBlocksOnDevice();
int blocks = device.getGeometry().blocksOnDevice();
AppleUtil.setWordValue(directory, 14, blocks);
AppleUtil.setWordValue(directory, 16, 0); // no files
AppleUtil.setWordValue(directory, 18, 0); // first block
@@ -645,16 +666,6 @@ public class PascalFormatDisk extends FormattedDiskX {
return true;
}
/**
* Change to a different ImageOrder. Remains in Pascal format but
* the underlying order can change.
* @see ImageOrder
*/
public void changeImageOrder(ImageOrder imageOrder) {
AppleUtil.changeImageOrderByBlock(getImageOrder(), imageOrder);
setImageOrder(imageOrder);
}
/**
* Writes the raw bytes into the file. This bypasses any special formatting
* of the data (such as prepending the data with a length and/or an address).
@@ -84,9 +84,9 @@ public class DiskWriterTest {
@Test
public void testWriteToPascal140kDisk() throws IOException, DiskException {
Source source = DataBufferSource.create(DiskConstants.APPLE_140KB_DISK, "new-disk").get();
ImageOrder imageOrder = new ProdosOrder(source);
BlockDevice blockDevice = new ProdosOrderedBlockDevice(source, BlockDevice.STANDARD_BLOCK_SIZE);
FormattedDisk[] disks = PascalFormatDisk.create(
"write-test-pascal-140k.po", "TEST", imageOrder); //$NON-NLS-1$ //$NON-NLS-2$
"write-test-pascal-140k.po", "TEST", blockDevice); //$NON-NLS-1$ //$NON-NLS-2$
writeFiles(disks, "code", "text", false); //$NON-NLS-1$ //$NON-NLS-2$
saveDisks(disks);
}
@@ -97,9 +97,9 @@ public class DiskWriterTest {
@Test
public void testWriteToPascal800kDisk() throws DiskFullException, IOException {
Source source = DataBufferSource.create(DiskConstants.APPLE_800KB_DISK, "new-disk").get();
ImageOrder imageOrder = new ProdosOrder(source);
BlockDevice blockDevice = new ProdosOrderedBlockDevice(source, BlockDevice.STANDARD_BLOCK_SIZE);
FormattedDisk[] disks = PascalFormatDisk.create(
"write-test-pascal-800k.po", "TEST", imageOrder); //$NON-NLS-1$ //$NON-NLS-2$
"write-test-pascal-800k.po", "TEST", blockDevice); //$NON-NLS-1$ //$NON-NLS-2$
//writeFiles(disks, "code", "text", false); //$NON-NLS-1$ //$NON-NLS-2$
saveDisks(disks);
}
@@ -189,10 +189,10 @@ public class DiskWriterTest {
@Test
public void testCreateAndDeletePascal140kDisk() throws IOException, DiskException {
Source source = DataBufferSource.create(DiskConstants.APPLE_140KB_DISK, "new-disk").get();
ImageOrder imageOrder = new ProdosOrder(source);
BlockDevice blockDevice = new ProdosOrderedBlockDevice(source, BlockDevice.STANDARD_BLOCK_SIZE);
FormattedDisk[] disks = PascalFormatDisk.create(
"createanddelete-test-pascal-140k.po", "TEST", //$NON-NLS-1$ //$NON-NLS-2$
imageOrder);
blockDevice);
createAndDeleteFiles(disks, "CODE"); //$NON-NLS-1$
saveDisks(disks);
}
@@ -203,10 +203,10 @@ public class DiskWriterTest {
@Test
public void testCreateAndDeletePascal800kDisk() throws IOException, DiskException {
Source source = DataBufferSource.create(DiskConstants.APPLE_800KB_DISK, "new-disk").get();
ImageOrder imageOrder = new ProdosOrder(source);
BlockDevice blockDevice = new ProdosOrderedBlockDevice(source, BlockDevice.STANDARD_BLOCK_SIZE);
FormattedDisk[] disks = PascalFormatDisk.create(
"createanddelete-test-pascal-800k.po", "TEST", //$NON-NLS-1$ //$NON-NLS-2$
imageOrder);
blockDevice);
createAndDeleteFiles(disks, "CODE"); //$NON-NLS-1$
saveDisks(disks);
}
@@ -289,10 +289,10 @@ public class DiskWriterTest {
@Test
public void testCreateDeleteCreatePascalDisk() throws IOException, DiskException {
Source source = DataBufferSource.create(DiskConstants.APPLE_140KB_DISK, "new-disk").get();
ImageOrder imageOrder = new ProdosOrder(source);
BlockDevice blockDevice = new ProdosOrderedBlockDevice(source, BlockDevice.STANDARD_BLOCK_SIZE);
FormattedDisk[] disks = PascalFormatDisk.create(
"createdeletecreate-test-pascal-140k.po", "TEST", //$NON-NLS-1$ //$NON-NLS-2$
imageOrder);
blockDevice);
createDeleteCreate(disks, "CODE"); //$NON-NLS-1$
saveDisks(disks);
}
@@ -21,21 +21,21 @@ package com.webcodepro.applecommander.storage.os.pascal;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.applecommander.device.BlockDevice;
import org.applecommander.device.ProdosOrderedBlockDevice;
import org.applecommander.source.DataBufferSource;
import org.applecommander.source.Source;
import com.webcodepro.applecommander.storage.DiskConstants;
import com.webcodepro.applecommander.storage.DiskFullException;
import com.webcodepro.applecommander.storage.physical.ImageOrder;
import com.webcodepro.applecommander.storage.physical.ProdosOrder;
import org.junit.jupiter.api.Test;
public class PascalFormatDiskTest {
@Test
public void testSanitizeFilename() throws DiskFullException {
Source source = DataBufferSource.create(DiskConstants.APPLE_140KB_DISK, "new-disk").get();
ImageOrder order = new ProdosOrder(source);
PascalFormatDisk[] disks = PascalFormatDisk.create("deleteme.po", "TEST", order);
BlockDevice blockDevice = new ProdosOrderedBlockDevice(source, BlockDevice.STANDARD_BLOCK_SIZE);
PascalFormatDisk[] disks = PascalFormatDisk.create("deleteme.po", "TEST", blockDevice);
PascalFormatDisk disk = disks[0];
assertEquals("FILENAME", disk.getSuggestedFilename("FileName"));
@@ -119,7 +119,7 @@ public class DiskImageWizard extends Wizard {
case FORMAT_OZDOS:
return OzDosFormatDisk.create(name.toString(), imageOrder);
case FORMAT_PASCAL:
return PascalFormatDisk.create(name.toString(), volumeName, imageOrder);
return PascalFormatDisk.create(name.toString(), volumeName, blockDevice);
case FORMAT_PRODOS:
return ProdosFormatDisk.create(name.toString(), volumeName, blockDevice);
case FORMAT_RDOS: