mirror of
https://github.com/AppleCommander/AppleCommander.git
synced 2026-04-20 03:16:37 +00:00
Adding interface layer in preparation of implementing BlockDevice and TrackSectorDevice.
This commit is contained in:
@@ -24,13 +24,12 @@ import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.webcodepro.applecommander.storage.DiskConstants;
|
||||
import com.webcodepro.applecommander.storage.DiskException;
|
||||
import com.webcodepro.applecommander.storage.FileEntry;
|
||||
import com.webcodepro.applecommander.storage.FormattedDisk;
|
||||
import com.webcodepro.applecommander.storage.*;
|
||||
import com.webcodepro.applecommander.storage.os.dos33.DosFormatDisk;
|
||||
|
||||
import io.github.applecommander.acx.fileutil.FileUtils;
|
||||
import org.applecommander.device.BlockDevice;
|
||||
import org.applecommander.device.TrackSectorDevice;
|
||||
|
||||
public enum SystemType {
|
||||
DOS(OrderType.DOS, SystemType::enforce140KbDisk,
|
||||
@@ -97,23 +96,27 @@ public enum SystemType {
|
||||
}
|
||||
|
||||
static void copyDosSystemTracks(FormattedDisk targetDisk, FormattedDisk source) {
|
||||
TrackSectorDevice sourceDevice = TrackSectorDeviceAdapter.from(source);
|
||||
DosFormatDisk target = (DosFormatDisk)targetDisk;
|
||||
byte[] vtoc = target.readVtoc();
|
||||
int sectorsPerTrack = vtoc[0x35];
|
||||
// Note that this also patches T0 S0 for BOOT0
|
||||
for (int t=0; t<3; t++) {
|
||||
for (int s=0; s<sectorsPerTrack; s++) {
|
||||
target.writeSector(t, s, source.readSector(t, s));
|
||||
byte[] data = sourceDevice.readSector(t, s).asBytes();
|
||||
target.writeSector(t, s, data);
|
||||
target.setSectorUsed(t, s, vtoc);
|
||||
}
|
||||
}
|
||||
target.writeVtoc(vtoc);
|
||||
}
|
||||
static void copyProdosSystemFiles(FormattedDisk target, FormattedDisk source) {
|
||||
BlockDevice targetDevice = BlockDeviceAdapter.from(target);
|
||||
BlockDevice sourceDevice = BlockDeviceAdapter.from(source);
|
||||
// We need to explicitly fix the boot block
|
||||
target.writeBlock(0, source.readBlock(0));
|
||||
target.writeBlock(1, source.readBlock(1));
|
||||
|
||||
targetDevice.writeBlock(0, sourceDevice.readBlock(0));
|
||||
targetDevice.writeBlock(1, sourceDevice.readBlock(1));
|
||||
|
||||
try {
|
||||
FileUtils copier = new FileUtils(false);
|
||||
for (String filename : Arrays.asList("PRODOS", "BASIC.SYSTEM")) {
|
||||
@@ -125,10 +128,12 @@ public enum SystemType {
|
||||
}
|
||||
}
|
||||
static void copyPascalSystemFiles(FormattedDisk target, FormattedDisk source) {
|
||||
BlockDevice targetDevice = BlockDeviceAdapter.from(target);
|
||||
BlockDevice sourceDevice = BlockDeviceAdapter.from(source);
|
||||
// We need to explicitly fix the boot block
|
||||
target.writeBlock(0, source.readBlock(0));
|
||||
target.writeBlock(1, source.readBlock(1));
|
||||
targetDevice.writeBlock(0, sourceDevice.readBlock(0));
|
||||
targetDevice.writeBlock(1, sourceDevice.readBlock(1));
|
||||
|
||||
// TODO; uncertain what files Pascal disks require for booting
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+26
-15
@@ -19,9 +19,14 @@
|
||||
*/
|
||||
package io.github.applecommander.acx.arggroup;
|
||||
|
||||
import com.webcodepro.applecommander.storage.BlockDeviceAdapter;
|
||||
import com.webcodepro.applecommander.storage.FormattedDisk;
|
||||
|
||||
import com.webcodepro.applecommander.storage.TrackSectorDeviceAdapter;
|
||||
import io.github.applecommander.acx.converter.IntegerTypeConverter;
|
||||
import org.applecommander.device.BlockDevice;
|
||||
import org.applecommander.device.TrackSectorDevice;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
import picocli.CommandLine.ArgGroup;
|
||||
import picocli.CommandLine.Option;
|
||||
|
||||
@@ -38,7 +43,8 @@ public class CoordinateSelection {
|
||||
else if (blockCoordinate != null) {
|
||||
return blockCoordinate.read(disk);
|
||||
}
|
||||
return disk.readSector(0, 0);
|
||||
TrackSectorDevice device = TrackSectorDeviceAdapter.from(disk);
|
||||
return device.readSector(0, 0).asBytes();
|
||||
}
|
||||
|
||||
public void write(FormattedDisk disk, byte[] data) {
|
||||
@@ -48,7 +54,8 @@ public class CoordinateSelection {
|
||||
else if (blockCoordinate != null) {
|
||||
blockCoordinate.write(disk, data);
|
||||
}
|
||||
disk.writeSector(0, 0, data);
|
||||
TrackSectorDevice device = TrackSectorDeviceAdapter.from(disk);
|
||||
device.writeSector(0, 0, DataBuffer.wrap(data));
|
||||
}
|
||||
|
||||
public static class SectorCoordinateSelection {
|
||||
@@ -59,9 +66,9 @@ public class CoordinateSelection {
|
||||
converter = IntegerTypeConverter.class)
|
||||
private Integer sector;
|
||||
|
||||
public void validateTrackAndSector(FormattedDisk disk) throws IllegalArgumentException {
|
||||
final int tracksPerDisk = disk.getImageOrder().getTracksPerDisk();
|
||||
final int sectorsPerTrack = disk.getImageOrder().getSectorsPerTrack();
|
||||
public void validateTrackAndSector(TrackSectorDevice device) throws IllegalArgumentException {
|
||||
final int tracksPerDisk = device.getGeometry().tracksOnDisk();
|
||||
final int sectorsPerTrack = device.getGeometry().sectorsPerTrack();
|
||||
|
||||
if (track < 0 || track >= tracksPerDisk) {
|
||||
String errormsg = String.format("The track number(%d) is out of range(0-%d) on this image.", track, tracksPerDisk-1);
|
||||
@@ -75,21 +82,23 @@ public class CoordinateSelection {
|
||||
}
|
||||
|
||||
public byte[] read(FormattedDisk disk) {
|
||||
validateTrackAndSector(disk);
|
||||
return disk.readSector(track, sector);
|
||||
TrackSectorDevice device = TrackSectorDeviceAdapter.from(disk);
|
||||
validateTrackAndSector(device);
|
||||
return device.readSector(track, sector).asBytes();
|
||||
}
|
||||
|
||||
public void write(FormattedDisk disk, byte[] data) {
|
||||
validateTrackAndSector(disk);
|
||||
disk.writeSector(track, sector, data);
|
||||
TrackSectorDevice device = TrackSectorDeviceAdapter.from(disk);
|
||||
validateTrackAndSector(device);
|
||||
device.writeSector(track, sector, DataBuffer.wrap(data));
|
||||
}
|
||||
}
|
||||
public static class BlockCoordinateSelection {
|
||||
@Option(names = { "-b", "--block" }, description = "Block number.", converter = IntegerTypeConverter.class)
|
||||
private Integer block;
|
||||
|
||||
public void validateBlockNum(FormattedDisk disk) throws IllegalArgumentException {
|
||||
final int blocksOnDevice = disk.getImageOrder().getBlocksOnDevice();
|
||||
public void validateBlockNum(BlockDevice device) throws IllegalArgumentException {
|
||||
final int blocksOnDevice = device.getGeometry().blocksOnDevice();
|
||||
|
||||
if (block < 0 || block >= blocksOnDevice) {
|
||||
String errormsg = String.format("The block number(%d) is out of range(0-%d) on this image.", block, blocksOnDevice-1);
|
||||
@@ -98,13 +107,15 @@ public class CoordinateSelection {
|
||||
}
|
||||
|
||||
public byte[] read(FormattedDisk disk) {
|
||||
validateBlockNum(disk);
|
||||
return disk.readBlock(block);
|
||||
BlockDevice device = BlockDeviceAdapter.from(disk);
|
||||
validateBlockNum(device);
|
||||
return device.readBlock(block).asBytes();
|
||||
}
|
||||
|
||||
public void write(FormattedDisk disk, byte[] data) {
|
||||
validateBlockNum(disk);
|
||||
disk.writeBlock(block, data);
|
||||
BlockDevice device = BlockDeviceAdapter.from(disk);
|
||||
validateBlockNum(device);
|
||||
device.writeBlock(block, DataBuffer.wrap(data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,9 @@ import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.webcodepro.applecommander.storage.BlockDeviceAdapter;
|
||||
import com.webcodepro.applecommander.storage.FormattedDisk;
|
||||
import com.webcodepro.applecommander.storage.TrackSectorDeviceAdapter;
|
||||
import com.webcodepro.applecommander.util.AppleUtil;
|
||||
|
||||
import com.webcodepro.applecommander.util.Range;
|
||||
@@ -38,6 +40,8 @@ import io.github.applecommander.disassembler.api.InstructionSet;
|
||||
import io.github.applecommander.disassembler.api.mos6502.InstructionSet6502;
|
||||
import io.github.applecommander.disassembler.api.sweet16.InstructionSetSWEET16;
|
||||
import io.github.applecommander.disassembler.api.switching6502.InstructionSet6502Switching;
|
||||
import org.applecommander.device.BlockDevice;
|
||||
import org.applecommander.device.TrackSectorDevice;
|
||||
import picocli.CommandLine.ArgGroup;
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.Mixin;
|
||||
@@ -55,10 +59,11 @@ public class DumpCommand extends ReadOnlyDiskImageCommandOptions {
|
||||
public int handleCommand() throws Exception {
|
||||
FormattedDisk disk = disks.getFirst();
|
||||
if (options.coordinate.blockRangeSelection != null) {
|
||||
BlockDevice device = BlockDeviceAdapter.from(disk);
|
||||
options.coordinate.blockRangeSelection.blocks.stream().forEach(block -> {
|
||||
validateBlockNum(disk, block);
|
||||
validateBlockNum(device, block);
|
||||
options.includesBootSector = block == 0;
|
||||
byte[] data = disk.readBlock(block);
|
||||
byte[] data = device.readBlock(block).asBytes();
|
||||
System.out.printf("Block #%d:\n", block);
|
||||
System.out.println(output.format(options, data));
|
||||
});
|
||||
@@ -66,10 +71,11 @@ public class DumpCommand extends ReadOnlyDiskImageCommandOptions {
|
||||
}
|
||||
else if (options.coordinate.trackSectorRangeSelection != null) {
|
||||
options.coordinate.trackSectorRangeSelection.tracks.stream().forEach(track -> {
|
||||
TrackSectorDevice device = TrackSectorDeviceAdapter.from(disk);
|
||||
options.coordinate.trackSectorRangeSelection.sectors.stream().forEach(sector -> {
|
||||
validateTrackAndSector(disk, track, sector);
|
||||
validateTrackAndSector(device, track, sector);
|
||||
options.includesBootSector = track == 0 && sector == 0;
|
||||
byte[] data = disk.readSector(track, sector);
|
||||
byte[] data = device.readSector(track, sector).asBytes();
|
||||
System.out.printf("Track %02d, Sector %02d:\n", track, sector);
|
||||
System.out.println(output.format(options, data));
|
||||
});
|
||||
@@ -80,8 +86,8 @@ public class DumpCommand extends ReadOnlyDiskImageCommandOptions {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public void validateBlockNum(FormattedDisk disk, int block) throws IllegalArgumentException {
|
||||
final int blocksOnDevice = disk.getImageOrder().getBlocksOnDevice();
|
||||
public void validateBlockNum(BlockDevice device, int block) throws IllegalArgumentException {
|
||||
final int blocksOnDevice = device.getGeometry().blocksOnDevice();
|
||||
|
||||
if (block < 0 || block >= blocksOnDevice) {
|
||||
String errormsg = String.format("The block number(%d) is out of range(0-%d) on this image.", block, blocksOnDevice-1);
|
||||
@@ -89,9 +95,9 @@ public class DumpCommand extends ReadOnlyDiskImageCommandOptions {
|
||||
}
|
||||
}
|
||||
|
||||
public void validateTrackAndSector(FormattedDisk disk, int track, int sector) throws IllegalArgumentException {
|
||||
final int tracksPerDisk = disk.getImageOrder().getTracksPerDisk();
|
||||
final int sectorsPerTrack = disk.getImageOrder().getSectorsPerTrack();
|
||||
public void validateTrackAndSector(TrackSectorDevice device, int track, int sector) throws IllegalArgumentException {
|
||||
final int tracksPerDisk = device.getGeometry().tracksOnDisk();
|
||||
final int sectorsPerTrack = device.getGeometry().sectorsPerTrack();
|
||||
|
||||
if (track < 0 || track >= tracksPerDisk) {
|
||||
String errormsg = String.format("The track number(%d) is out of range(0-%d) on this image.", track, tracksPerDisk-1);
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
package io.github.applecommander.acx.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -73,7 +72,7 @@ public class ListCommand extends ReadOnlyDiskImageCommandOptions {
|
||||
int display = fileDisplay.format();
|
||||
ListingStrategy listingStrategy = outputType.create(display);
|
||||
|
||||
listingStrategy.first(disks.getFirst().getImageOrder());
|
||||
listingStrategy.first(disks.getFirst());
|
||||
|
||||
FileStreamer.forDisks(disks)
|
||||
.ignoreErrors(true)
|
||||
|
||||
@@ -32,6 +32,8 @@ import com.webcodepro.applecommander.storage.os.pascal.PascalFormatDisk;
|
||||
import com.webcodepro.applecommander.storage.os.prodos.ProdosFormatDisk;
|
||||
import com.webcodepro.applecommander.storage.os.rdos.RdosFormatDisk;
|
||||
import io.github.applecommander.acx.base.ReusableCommandOptions;
|
||||
import org.applecommander.device.BlockDevice;
|
||||
import org.applecommander.device.TrackSectorDevice;
|
||||
import org.applecommander.source.Source;
|
||||
import org.applecommander.source.Sources;
|
||||
|
||||
@@ -423,10 +425,11 @@ public class ScanCommand extends ReusableCommandOptions {
|
||||
}
|
||||
|
||||
private void readAllBlocks(FormattedDisk fdisk) {
|
||||
BlockDevice device = BlockDeviceAdapter.from(fdisk);
|
||||
dataType = "blocks";
|
||||
for (int b = 0; b < fdisk.getBitmapLength() && errors.size() < MAX_ERRORS; b++) {
|
||||
try {
|
||||
fdisk.readBlock(b);
|
||||
device.readBlock(b);
|
||||
dataRead++;
|
||||
} catch (Throwable t) {
|
||||
errors.add(String.format("Unable to read block #%d for disk #%d", b, fdisk.getLogicalDiskNumber()));
|
||||
@@ -447,12 +450,13 @@ public class ScanCommand extends ReusableCommandOptions {
|
||||
}
|
||||
|
||||
private void readAllSectors(FormattedDisk fdisk) {
|
||||
TrackSectorDevice device = TrackSectorDeviceAdapter.from(fdisk);
|
||||
dataType = "sectors";
|
||||
int[] dims = fdisk.getBitmapDimensions();
|
||||
for (int track = 0; track < dims[0] && errors.size() < MAX_ERRORS; track++) {
|
||||
for (int sector = 0; sector < dims[1] && errors.size() < MAX_ERRORS; sector++) {
|
||||
try {
|
||||
fdisk.readSector(track, sector);
|
||||
device.readSector(track, sector);
|
||||
dataRead++;
|
||||
} catch (Throwable t) {
|
||||
errors.add(String.format("Unable to read sector T%d,S%s for disk #%d",
|
||||
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* AppleCommander - An Apple ][ image utility.
|
||||
* Copyright (C) 2025 by Robert Greene and others
|
||||
* robgreene at users.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
package com.webcodepro.applecommander.storage;
|
||||
|
||||
import com.webcodepro.applecommander.storage.physical.ImageOrder;
|
||||
import org.applecommander.capability.Capability;
|
||||
import org.applecommander.device.BlockDevice;
|
||||
import org.applecommander.hint.Hint;
|
||||
import org.applecommander.util.Container;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Temporary transition layer between ImageOrder and BlockDevice.
|
||||
*/
|
||||
public class BlockDeviceAdapter implements BlockDevice {
|
||||
public static BlockDevice from(FormattedDisk disk) {
|
||||
if (disk instanceof Container c) {
|
||||
Optional<BlockDevice> opt = c.get(BlockDevice.class);
|
||||
if (opt.isPresent()) return opt.get();
|
||||
}
|
||||
if (disk instanceof FormattedDiskX x) {
|
||||
return new BlockDeviceAdapter(x.getImageOrder());
|
||||
}
|
||||
throw new RuntimeException("No BlockDevice present: " + disk.getClass().getName());
|
||||
}
|
||||
|
||||
private ImageOrder order;
|
||||
|
||||
private BlockDeviceAdapter(ImageOrder order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Hint hint) {
|
||||
return order.is(hint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean can(Capability capability) {
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Geometry getGeometry() {
|
||||
return new Geometry(STANDARD_BLOCK_SIZE, order.getBlocksOnDevice());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataBuffer readBlock(int block) {
|
||||
return DataBuffer.wrap(order.readBlock(block));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBlock(int block, DataBuffer blockData) {
|
||||
order.writeBlock(block, blockData.asBytes());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* AppleCommander - An Apple ][ image utility.
|
||||
* Copyright (C) 2025 by Robert Greene and others
|
||||
* robgreene at users.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
package com.webcodepro.applecommander.storage;
|
||||
|
||||
import com.webcodepro.applecommander.storage.os.pascal.PascalFormatDisk;
|
||||
import com.webcodepro.applecommander.storage.os.prodos.ProdosFormatDisk;
|
||||
import org.applecommander.device.Device;
|
||||
import org.applecommander.util.Container;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class DeviceAdapter {
|
||||
public static Device from(FormattedDisk disk) {
|
||||
if (disk instanceof FormattedDiskX) {
|
||||
// old school, translate...
|
||||
if (disk instanceof ProdosFormatDisk || disk instanceof PascalFormatDisk) {
|
||||
return BlockDeviceAdapter.from(disk);
|
||||
}
|
||||
else {
|
||||
return TrackSectorDeviceAdapter.from(disk);
|
||||
}
|
||||
}
|
||||
if (disk instanceof Container c) {
|
||||
Optional<Device> opt = c.get(Device.class);
|
||||
if (opt.isPresent()) {
|
||||
return opt.get();
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Unable to locate device for " + disk.getClass().getName());
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,6 @@
|
||||
*/
|
||||
package com.webcodepro.applecommander.storage;
|
||||
|
||||
import com.webcodepro.applecommander.storage.physical.ImageOrder;
|
||||
import com.webcodepro.applecommander.storage.physical.WozOrder;
|
||||
import com.webcodepro.applecommander.util.TextBundle;
|
||||
import org.applecommander.source.Source;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
@@ -133,15 +131,13 @@ public abstract class FormattedDisk implements DirectoryEntry {
|
||||
|
||||
private String filename;
|
||||
private boolean newImage = false;
|
||||
private Source source;
|
||||
private ImageOrder imageOrder = null;
|
||||
private final Source source;
|
||||
|
||||
/**
|
||||
* Constructor for FormattedDisk.
|
||||
*/
|
||||
public FormattedDisk(String filename, ImageOrder imageOrder) {
|
||||
this.imageOrder = imageOrder;
|
||||
this.source = imageOrder.getSource();
|
||||
public FormattedDisk(String filename, Source source) {
|
||||
this.source = source;
|
||||
this.filename = filename;
|
||||
this.newImage = true;
|
||||
}
|
||||
@@ -213,13 +209,10 @@ public abstract class FormattedDisk implements DirectoryEntry {
|
||||
List<DiskInformation> list = new ArrayList<>();
|
||||
list.add(new DiskInformation(textBundle.get("FormattedDisk.FileName"), getFilename())); //$NON-NLS-1$
|
||||
list.add(new DiskInformation(textBundle.get("FormattedDisk.DiskName"), getDiskName())); //$NON-NLS-1$
|
||||
list.add(new DiskInformation(textBundle.get("FormattedDisk.PhysicalSizeInBytes"), getPhysicalSize())); //$NON-NLS-1$
|
||||
list.add(new DiskInformation(textBundle.get("FormattedDisk.FreeSpaceInBytes"), getFreeSpace())); //$NON-NLS-1$
|
||||
list.add(new DiskInformation(textBundle.get("FormattedDisk.UsedSpaceInBytes"), getUsedSpace())); //$NON-NLS-1$
|
||||
list.add(new DiskInformation(textBundle.get("FormattedDisk.PhysicalSizeInKb"), getPhysicalSize() / 1024)); //$NON-NLS-1$
|
||||
list.add(new DiskInformation(textBundle.get("FormattedDisk.FreeSpaceInKb"), getFreeSpace() / 1024)); //$NON-NLS-1$
|
||||
list.add(new DiskInformation(textBundle.get("FormattedDisk.UsedSpaceInKb"), getUsedSpace() / 1024)); //$NON-NLS-1$
|
||||
list.add(new DiskInformation(textBundle.get("FormattedDisk.ArchiveOrder"), getOrderName())); //$NON-NLS-1$
|
||||
list.add(new DiskInformation(textBundle.get("FormattedDisk.DiskFormat"), getFormat())); //$NON-NLS-1$
|
||||
return list;
|
||||
}
|
||||
@@ -326,26 +319,7 @@ public abstract class FormattedDisk implements DirectoryEntry {
|
||||
* there is no backing out!
|
||||
*/
|
||||
public abstract void format();
|
||||
|
||||
/**
|
||||
* Write the AppleCommander boot code to track 0 sector 0 of
|
||||
* the disk. This will work for a floppy, but may cause problems
|
||||
* for other devices.
|
||||
*/
|
||||
protected void writeBootCode() {
|
||||
InputStream inputStream = getClass().
|
||||
getResourceAsStream("/com/webcodepro/applecommander/storage/AppleCommander-boot.dump"); //$NON-NLS-1$
|
||||
if (inputStream != null) {
|
||||
byte[] bootCode = new byte[DiskConstants.SECTOR_SIZE];
|
||||
try {
|
||||
inputStream.read(bootCode, 0, bootCode.length);
|
||||
writeSector(0, 0, bootCode);
|
||||
} catch (IOException ignored) {
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the logical disk number. This can be used to identify
|
||||
* between disks when a format supports multiple logical volumes.
|
||||
@@ -388,14 +362,6 @@ public abstract class FormattedDisk implements DirectoryEntry {
|
||||
public FormattedDisk getFormattedDisk() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the disk image to be its full size. Only invoke this
|
||||
* method if a size does not match exception is thrown.
|
||||
*/
|
||||
public void resizeDiskImage() {
|
||||
resizeDiskImage(getFreeSpace() + getUsedSpace());
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this FormattedDisk supports a disk map.
|
||||
@@ -437,9 +403,6 @@ public abstract class FormattedDisk implements DirectoryEntry {
|
||||
* Returns the source.
|
||||
*/
|
||||
public Source getSource() {
|
||||
if (imageOrder != null) {
|
||||
return imageOrder.getSource();
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
@@ -458,73 +421,6 @@ public abstract class FormattedDisk implements DirectoryEntry {
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the underlying image order.
|
||||
* @return String
|
||||
*/
|
||||
public String getOrderName() {
|
||||
return (imageOrder == null) ? textBundle.get("FormattedDisk.Unknown") : imageOrder.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify the size of this disk.
|
||||
*/
|
||||
public int getPhysicalSize() {
|
||||
if (getImageOrder() instanceof WozOrder) {
|
||||
// Total hack since WOZ is currently a special case.
|
||||
return getImageOrder().getPhysicalSize();
|
||||
}
|
||||
if (getSource() != null) {
|
||||
return getSource().getSize();
|
||||
}
|
||||
return getImageOrder().getPhysicalSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize a disk image up to a larger size. The primary intention is to
|
||||
* "fix" disk images that have been created too small. The primary culprit
|
||||
* is ApplePC HDV images which dynamically grow. Since AppleCommander
|
||||
* works with a byte array, the image must grow to its full size.
|
||||
* @param newSize
|
||||
*/
|
||||
protected void resizeDiskImage(int newSize) {
|
||||
if (newSize < getPhysicalSize()) {
|
||||
throw new IllegalArgumentException(
|
||||
textBundle.get("Disk.ResizeDiskError")); //$NON-NLS-1$
|
||||
}
|
||||
DataBuffer backingBuffer = imageOrder.getSource().get(DataBuffer.class).orElseThrow();
|
||||
backingBuffer.limit(newSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the block from the disk image.
|
||||
*/
|
||||
public byte[] readBlock(int block) {
|
||||
return imageOrder.readBlock(block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the block to the disk image.
|
||||
*/
|
||||
public void writeBlock(int block, byte[] data) {
|
||||
imageOrder.writeBlock(block, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the specified sector.
|
||||
*/
|
||||
public byte[] readSector(int track, int sector) throws IllegalArgumentException {
|
||||
return imageOrder.readSector(track, sector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the specified sector.
|
||||
*/
|
||||
public void writeSector(int track, int sector, byte[] bytes)
|
||||
throws IllegalArgumentException {
|
||||
imageOrder.writeSector(track, sector, bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the disk has changed. Triggered when data is
|
||||
* written and cleared when data is saved.
|
||||
@@ -541,28 +437,6 @@ public abstract class FormattedDisk implements DirectoryEntry {
|
||||
return newImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Answer with the physical ordering of the disk.
|
||||
*/
|
||||
public ImageOrder getImageOrder() {
|
||||
return imageOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the physical ordering of the disk.
|
||||
*/
|
||||
protected void setImageOrder(ImageOrder imageOrder) {
|
||||
this.imageOrder = imageOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the physical ordering of the disk. This must be implemented by all
|
||||
* subclasses. See AppleUtil for common utility methods. (It is assumed that a
|
||||
* disk needs to be copied in the appropriate order - i.e., by track and sector for
|
||||
* a DOS type disk or by blocks in a ProDOS type disk.)
|
||||
*/
|
||||
public abstract void changeImageOrder(ImageOrder 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).
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* AppleCommander - An Apple ][ image utility.
|
||||
* Copyright (C) 2025 by Robert Greene and others
|
||||
* robgreene at users.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
package com.webcodepro.applecommander.storage;
|
||||
|
||||
import com.webcodepro.applecommander.storage.physical.ImageOrder;
|
||||
import com.webcodepro.applecommander.storage.physical.WozOrder;
|
||||
import com.webcodepro.applecommander.util.TextBundle;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This is a transitional component while the various file systems get refitted with devices.
|
||||
* It contains the ImageOrder related functions that will be replaced.
|
||||
*/
|
||||
public abstract class FormattedDiskX extends FormattedDisk {
|
||||
private final TextBundle textBundle = StorageBundle.getInstance();
|
||||
|
||||
private ImageOrder imageOrder = null;
|
||||
|
||||
public FormattedDiskX(String filename, ImageOrder imageOrder) {
|
||||
super(filename, imageOrder.getSource());
|
||||
this.imageOrder = imageOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get disk information. This is intended to be pretty generic -
|
||||
* each disk format can build this as appropriate. Each subclass should
|
||||
* override this method and add its own detail.
|
||||
*/
|
||||
public List<DiskInformation> getDiskInformation() {
|
||||
List<DiskInformation> list = new ArrayList<>(super.getDiskInformation());
|
||||
list.add(new DiskInformation(textBundle.get("FormattedDisk.PhysicalSizeInBytes"), getPhysicalSize()));
|
||||
list.add(new DiskInformation(textBundle.get("FormattedDisk.PhysicalSizeInKb"), getPhysicalSize() / 1024));
|
||||
list.add(new DiskInformation(textBundle.get("FormattedDisk.ArchiveOrder"), getOrderName()));
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the underlying image order.
|
||||
* @return String
|
||||
*/
|
||||
public String getOrderName() {
|
||||
return (imageOrder == null) ? textBundle.get("FormattedDisk.Unknown") : imageOrder.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify the size of this disk.
|
||||
*/
|
||||
public int getPhysicalSize() {
|
||||
if (getImageOrder() instanceof WozOrder) {
|
||||
// Total hack since WOZ is currently a special case.
|
||||
return getImageOrder().getPhysicalSize();
|
||||
}
|
||||
if (getSource() != null) {
|
||||
return getSource().getSize();
|
||||
}
|
||||
return getImageOrder().getPhysicalSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the disk image to be its full size. Only invoke this
|
||||
* method if a size does not match exception is thrown.
|
||||
*/
|
||||
public void resizeDiskImage() {
|
||||
resizeDiskImage(getFreeSpace() + getUsedSpace());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize a disk image up to a larger size. The primary intention is to
|
||||
* "fix" disk images that have been created too small. The primary culprit
|
||||
* is ApplePC HDV images which dynamically grow. Since AppleCommander
|
||||
* works with a byte array, the image must grow to its full size.
|
||||
* @param newSize
|
||||
*/
|
||||
protected void resizeDiskImage(int newSize) {
|
||||
if (newSize < getPhysicalSize()) {
|
||||
throw new IllegalArgumentException(
|
||||
textBundle.get("Disk.ResizeDiskError")); //$NON-NLS-1$
|
||||
}
|
||||
DataBuffer backingBuffer = imageOrder.getSource().get(DataBuffer.class).orElseThrow();
|
||||
backingBuffer.limit(newSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the block from the disk image.
|
||||
*/
|
||||
public byte[] readBlock(int block) {
|
||||
return imageOrder.readBlock(block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the block to the disk image.
|
||||
*/
|
||||
public void writeBlock(int block, byte[] data) {
|
||||
imageOrder.writeBlock(block, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the specified sector.
|
||||
*/
|
||||
public byte[] readSector(int track, int sector) throws IllegalArgumentException {
|
||||
return imageOrder.readSector(track, sector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the specified sector.
|
||||
*/
|
||||
public void writeSector(int track, int sector, byte[] bytes)
|
||||
throws IllegalArgumentException {
|
||||
imageOrder.writeSector(track, sector, bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the AppleCommander boot code to track 0 sector 0 of
|
||||
* the disk. This will work for a floppy, but may cause problems
|
||||
* for other devices.
|
||||
*/
|
||||
protected void writeBootCode() {
|
||||
InputStream inputStream = getClass().
|
||||
getResourceAsStream("/com/webcodepro/applecommander/storage/AppleCommander-boot.dump"); //$NON-NLS-1$
|
||||
if (inputStream != null) {
|
||||
byte[] bootCode = new byte[DiskConstants.SECTOR_SIZE];
|
||||
try {
|
||||
inputStream.read(bootCode, 0, bootCode.length);
|
||||
writeSector(0, 0, bootCode);
|
||||
} catch (IOException ignored) {
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Answer with the physical ordering of the disk.
|
||||
*/
|
||||
public ImageOrder getImageOrder() {
|
||||
return imageOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the physical ordering of the disk.
|
||||
*/
|
||||
protected void setImageOrder(ImageOrder imageOrder) {
|
||||
this.imageOrder = imageOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the physical ordering of the disk. This must be implemented by all
|
||||
* subclasses. See AppleUtil for common utility methods. (It is assumed that a
|
||||
* disk needs to be copied in the appropriate order - i.e., by track and sector for
|
||||
* a DOS type disk or by blocks in a ProDOS type disk.)
|
||||
*/
|
||||
public abstract void changeImageOrder(ImageOrder imageOrder);
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* AppleCommander - An Apple ][ image utility.
|
||||
* Copyright (C) 2025 by Robert Greene and others
|
||||
* robgreene at users.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
package com.webcodepro.applecommander.storage;
|
||||
|
||||
import com.webcodepro.applecommander.storage.os.dos33.OzDosFormatDisk;
|
||||
import com.webcodepro.applecommander.storage.os.dos33.UniDosFormatDisk;
|
||||
import com.webcodepro.applecommander.storage.physical.ImageOrder;
|
||||
import org.applecommander.capability.Capability;
|
||||
import org.applecommander.device.BlockDevice;
|
||||
import org.applecommander.device.BlockToTrackSectorAdapter;
|
||||
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.Container;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class TrackSectorDeviceAdapter implements TrackSectorDevice {
|
||||
public static TrackSectorDevice from(FormattedDisk disk) {
|
||||
if (disk instanceof Container c) {
|
||||
Optional<TrackSectorDevice> opt = c.get(TrackSectorDevice.class);
|
||||
if (opt.isPresent()) return opt.get();
|
||||
}
|
||||
// 800K DOS disks cause some issues, so they are pulled out...
|
||||
return switch (disk) {
|
||||
case UniDosFormatDisk unidos -> {
|
||||
BlockDevice device = BlockDeviceAdapter.from(unidos);
|
||||
yield new BlockToTrackSectorAdapter(device, unidos.getLogicalDiskNumber() == 1
|
||||
? UnidosAdapterStrategy.UNIDOS_DISK_1 : UnidosAdapterStrategy.UNIDOS_DISK_2);
|
||||
}
|
||||
case OzDosFormatDisk ozdos -> {
|
||||
BlockDevice device = BlockDeviceAdapter.from(ozdos);
|
||||
yield new BlockToTrackSectorAdapter(device, ozdos.getLogicalDiskNumber() == 1
|
||||
? OzdosAdapterStrategy.OZDOS_DISK_1 : OzdosAdapterStrategy.OZDOS_DISK_2);
|
||||
}
|
||||
case FormattedDiskX x -> new TrackSectorDeviceAdapter(x.getImageOrder());
|
||||
default -> throw new RuntimeException("No BlockDevice present: " + disk.getClass().getName());
|
||||
};
|
||||
}
|
||||
|
||||
private ImageOrder order;
|
||||
|
||||
private TrackSectorDeviceAdapter(ImageOrder order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Hint hint) {
|
||||
return order.is(hint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean can(Capability capability) {
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Geometry getGeometry() {
|
||||
return new Geometry(order.getTracksPerDisk(), order.getSectorsPerTrack());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataBuffer readSector(int track, int sector) {
|
||||
return DataBuffer.wrap(order.readSector(track, sector));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeSector(int track, int sector, DataBuffer sectorData) {
|
||||
order.writeSector(track, sector, sectorData.asBytes());
|
||||
}
|
||||
}
|
||||
+29
-30
@@ -22,24 +22,19 @@ package com.webcodepro.applecommander.storage.compare;
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.webcodepro.applecommander.storage.DiskGeometry;
|
||||
import com.webcodepro.applecommander.storage.FormattedDisk;
|
||||
import com.webcodepro.applecommander.storage.physical.ImageOrder;
|
||||
import com.webcodepro.applecommander.storage.*;
|
||||
import com.webcodepro.applecommander.util.Range;
|
||||
import com.webcodepro.applecommander.util.filestreamer.FileStreamer;
|
||||
import com.webcodepro.applecommander.util.filestreamer.FileTuple;
|
||||
import com.webcodepro.applecommander.util.filestreamer.TypeOfFile;
|
||||
import com.webcodepro.applecommander.util.readerwriter.FileEntryReader;
|
||||
import org.applecommander.device.BlockDevice;
|
||||
import org.applecommander.device.TrackSectorDevice;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
|
||||
/**
|
||||
* Perform a disk comparison based on selected strategy.
|
||||
@@ -118,20 +113,22 @@ public class DiskDiff {
|
||||
|
||||
/** Compare disks by 512-byte ProDOS/Pascal blocks. */
|
||||
public void compareByBlockGeometry(FormattedDisk formattedDiskA, FormattedDisk formattedDiskB) {
|
||||
ImageOrder orderA = formattedDiskA.getImageOrder();
|
||||
ImageOrder orderB = formattedDiskB.getImageOrder();
|
||||
|
||||
if (orderA.getBlocksOnDevice() != orderB.getBlocksOnDevice()) {
|
||||
results.addError("Different sized disks do not equal. (Blocks: %d <> %d)",
|
||||
orderA.getBlocksOnDevice(), orderB.getBlocksOnDevice());
|
||||
BlockDevice deviceA = BlockDeviceAdapter.from(formattedDiskA);
|
||||
BlockDevice deviceB = BlockDeviceAdapter.from(formattedDiskB);
|
||||
|
||||
int blocksOnDeviceA = deviceA.getGeometry().blocksOnDevice();
|
||||
int blocksOnDeviceB = deviceB.getGeometry().blocksOnDevice();
|
||||
if (blocksOnDeviceA != blocksOnDeviceB) {
|
||||
results.addError("Different sized disks do not equal. (Blocks: %d <> %d)",
|
||||
blocksOnDeviceA, blocksOnDeviceB);
|
||||
return;
|
||||
}
|
||||
|
||||
List<Integer> unequalBlocks = new ArrayList<>();
|
||||
for (int block=0; block<orderA.getBlocksOnDevice(); block++) {
|
||||
byte[] blockA = orderA.readBlock(block);
|
||||
byte[] blockB = orderB.readBlock(block);
|
||||
if (!Arrays.equals(blockA, blockB)) {
|
||||
for (int block=0; block<blocksOnDeviceA; block++) {
|
||||
DataBuffer blockA = deviceA.readBlock(block);
|
||||
DataBuffer blockB = deviceB.readBlock(block);
|
||||
if (!blockA.equals(blockB)) {
|
||||
unequalBlocks.add(block);
|
||||
}
|
||||
}
|
||||
@@ -144,24 +141,26 @@ public class DiskDiff {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Compare disks by 256-byte DOS sectors. */
|
||||
public void compareByTrackSectorGeometry(FormattedDisk formattedDiskA, FormattedDisk formattedDiskB) {
|
||||
ImageOrder orderA = formattedDiskA.getImageOrder();
|
||||
ImageOrder orderB = formattedDiskB.getImageOrder();
|
||||
TrackSectorDevice deviceA = TrackSectorDeviceAdapter.from(formattedDiskA);
|
||||
TrackSectorDevice deviceB = TrackSectorDeviceAdapter.from(formattedDiskB);
|
||||
|
||||
if (orderA.getSectorsPerDisk() != orderB.getSectorsPerDisk()) {
|
||||
int sectorsPerDiskA = deviceA.getGeometry().sectorsPerDisk();
|
||||
int sectorsPerDiskB = deviceB.getGeometry().sectorsPerDisk();
|
||||
if (sectorsPerDiskA != sectorsPerDiskB) {
|
||||
results.addError("Different sized disks do not equal. (Sectors: %d <> %d)",
|
||||
orderA.getSectorsPerDisk(), orderB.getSectorsPerDisk());
|
||||
sectorsPerDiskA, sectorsPerDiskB);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int track=0; track<orderA.getTracksPerDisk(); track++) {
|
||||
for (int track=0; track<deviceA.getGeometry().tracksOnDisk(); track++) {
|
||||
List<Integer> unequalSectors = new ArrayList<>();
|
||||
for (int sector=0; sector<orderA.getSectorsPerTrack(); sector++) {
|
||||
byte[] sectorA = orderA.readSector(track, sector);
|
||||
byte[] sectorB = orderB.readSector(track, sector);
|
||||
if (!Arrays.equals(sectorA, sectorB)) {
|
||||
for (int sector=0; sector<deviceA.getGeometry().sectorsPerTrack(); sector++) {
|
||||
DataBuffer sectorA = deviceA.readSector(track, sector);
|
||||
DataBuffer sectorB = deviceB.readSector(track, sector);
|
||||
if (!sectorA.equals(sectorB)) {
|
||||
unequalSectors.add(sector);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ import java.util.*;
|
||||
* <p>
|
||||
* @author Rob Greene
|
||||
*/
|
||||
public class CpmFormatDisk extends FormattedDisk {
|
||||
public class CpmFormatDisk extends FormattedDiskX {
|
||||
private TextBundle textBundle = StorageBundle.getInstance();
|
||||
/**
|
||||
* The size of the CP/M sector. Assumed to be 128.
|
||||
|
||||
+7
-7
@@ -20,7 +20,7 @@
|
||||
package com.webcodepro.applecommander.storage.os.dos33;
|
||||
|
||||
import com.webcodepro.applecommander.storage.DiskFactory;
|
||||
import com.webcodepro.applecommander.storage.FormattedDisk;
|
||||
import com.webcodepro.applecommander.storage.FormattedDiskX;
|
||||
import com.webcodepro.applecommander.storage.physical.ImageOrder;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
import static com.webcodepro.applecommander.storage.DiskConstants.*;
|
||||
@@ -31,7 +31,7 @@ public class DosDiskFactory implements DiskFactory {
|
||||
@Override
|
||||
public void inspect(Context ctx) {
|
||||
// It seems easiest to gather all possibilities first...
|
||||
List<FormattedDisk> tests = new ArrayList<>();
|
||||
List<FormattedDiskX> tests = new ArrayList<>();
|
||||
if (ctx.orders.size() == 1) {
|
||||
ImageOrder order = ctx.orders.getFirst();
|
||||
if (order.isSizeApprox(APPLE_800KB_DISK)) {
|
||||
@@ -46,8 +46,8 @@ public class DosDiskFactory implements DiskFactory {
|
||||
}
|
||||
else if (ctx.orders.size() == 2) {
|
||||
// Could be either, so count both (should be PO vs DO) and choose the longest catalog
|
||||
FormattedDisk fdisk1 = new DosFormatDisk(ctx.source.getName(), ctx.orders.get(0));
|
||||
FormattedDisk fdisk2 = new DosFormatDisk(ctx.source.getName(), ctx.orders.get(1));
|
||||
FormattedDiskX fdisk1 = new DosFormatDisk(ctx.source.getName(), ctx.orders.get(0));
|
||||
FormattedDiskX fdisk2 = new DosFormatDisk(ctx.source.getName(), ctx.orders.get(1));
|
||||
int count1 = count(fdisk1, 17);
|
||||
int count2 = count(fdisk2, 17);
|
||||
// Note this assumes DO was the first ImageOrder in the list to give it an edge
|
||||
@@ -55,7 +55,7 @@ public class DosDiskFactory implements DiskFactory {
|
||||
else tests.add(fdisk2);
|
||||
}
|
||||
// ... and then test for DOS VTOC etc. Passing track number along to hopefully handle it later!
|
||||
for (FormattedDisk fdisk : tests) {
|
||||
for (FormattedDiskX fdisk : tests) {
|
||||
try {
|
||||
if (check(fdisk, 17)) {
|
||||
ctx.disks.add(fdisk);
|
||||
@@ -69,7 +69,7 @@ public class DosDiskFactory implements DiskFactory {
|
||||
/**
|
||||
* Test this image order by looking for a likely DOS VTOC and set of catalog sectors.
|
||||
*/
|
||||
public boolean check(FormattedDisk disk, final int vtocTrack) {
|
||||
public boolean check(FormattedDiskX disk, final int vtocTrack) {
|
||||
DataBuffer vtoc = DataBuffer.wrap(disk.readSector(vtocTrack, 0));
|
||||
int nextTrack = vtoc.getUnsignedByte(0x01);
|
||||
int nextSector = vtoc.getUnsignedByte(0x02);
|
||||
@@ -123,7 +123,7 @@ public class DosDiskFactory implements DiskFactory {
|
||||
return good;
|
||||
}
|
||||
|
||||
public int count(FormattedDisk disk, final int vtocTrack) {
|
||||
public int count(FormattedDiskX disk, final int vtocTrack) {
|
||||
DataBuffer vtoc = DataBuffer.wrap(disk.readSector(vtocTrack, 0));
|
||||
int nextTrack = vtoc.getUnsignedByte(0x01);
|
||||
int nextSector = vtoc.getUnsignedByte(0x02);
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ import java.util.*;
|
||||
* Changed at: Dec 1, 2017
|
||||
* @author Lisias Toledo
|
||||
*/
|
||||
public class DosFormatDisk extends FormattedDisk {
|
||||
public class DosFormatDisk extends FormattedDiskX {
|
||||
private TextBundle textBundle = StorageBundle.getInstance();
|
||||
/**
|
||||
* Indicates the index of the track in the location array.
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ import java.util.List;
|
||||
* Date created: Dec 17, 2008 04:29:23 PM
|
||||
* @author David Schmidt
|
||||
*/
|
||||
public class GutenbergFormatDisk extends FormattedDisk {
|
||||
public class GutenbergFormatDisk extends FormattedDiskX {
|
||||
private TextBundle textBundle = StorageBundle.getInstance();
|
||||
/**
|
||||
* Indicates the index of the track in the location array.
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ import java.util.List;
|
||||
* Date created: August 5, 2010 10:23:23 AM
|
||||
* @author David Schmidt
|
||||
*/
|
||||
public class NakedosFormatDisk extends FormattedDisk {
|
||||
public class NakedosFormatDisk extends FormattedDiskX {
|
||||
private TextBundle textBundle = StorageBundle.getInstance();
|
||||
/**
|
||||
* Indicates the index of the track in the location array.
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ import java.util.*;
|
||||
* @author Rob Greene
|
||||
* @author John B. Matthews [getFiles(), get/putDirectory(), createFile()]
|
||||
*/
|
||||
public class PascalFormatDisk extends FormattedDisk {
|
||||
public class PascalFormatDisk extends FormattedDiskX {
|
||||
private TextBundle textBundle = StorageBundle.getInstance();
|
||||
/**
|
||||
* The size of the Pascal file entry.
|
||||
|
||||
+4
-4
@@ -20,7 +20,7 @@
|
||||
package com.webcodepro.applecommander.storage.os.prodos;
|
||||
|
||||
import com.webcodepro.applecommander.storage.DiskFactory;
|
||||
import com.webcodepro.applecommander.storage.FormattedDisk;
|
||||
import com.webcodepro.applecommander.storage.FormattedDiskX;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
import static com.webcodepro.applecommander.storage.DiskConstants.*;
|
||||
|
||||
@@ -31,17 +31,17 @@ public class ProdosDiskFactory implements DiskFactory {
|
||||
@Override
|
||||
public void inspect(Context ctx) {
|
||||
// It seems easiest to gather all possibilities first...
|
||||
List<FormattedDisk> tests = new ArrayList<>();
|
||||
List<FormattedDiskX> tests = new ArrayList<>();
|
||||
ctx.orders.forEach(order -> tests.add(new ProdosFormatDisk(ctx.source.getName(), order)));
|
||||
// ... and then test for ProDOS details:
|
||||
for (FormattedDisk fdisk : tests) {
|
||||
for (FormattedDiskX fdisk : tests) {
|
||||
if (check(fdisk)) {
|
||||
ctx.disks.add(fdisk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean check(FormattedDisk fdisk) {
|
||||
public boolean check(FormattedDiskX fdisk) {
|
||||
int nextBlock = 2;
|
||||
DataBuffer volumeDirectory = DataBuffer.wrap(fdisk.readBlock(nextBlock));
|
||||
int priorBlock = volumeDirectory.getUnsignedShort(0x00);
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ import java.util.*;
|
||||
* Changed at: Dec 1, 2017
|
||||
* @author Lisias Toledo
|
||||
*/
|
||||
public class ProdosFormatDisk extends FormattedDisk {
|
||||
public class ProdosFormatDisk extends FormattedDiskX {
|
||||
private TextBundle textBundle = StorageBundle.getInstance();
|
||||
/**
|
||||
* The location of the "next block" pointer in a directory entry.
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ import java.util.Map;
|
||||
* Date created: Oct 7, 2002 2:03:58 PM
|
||||
* @author Rob Greene
|
||||
*/
|
||||
public class RdosFormatDisk extends FormattedDisk {
|
||||
public class RdosFormatDisk extends FormattedDiskX {
|
||||
private TextBundle textBundle = StorageBundle.getInstance();
|
||||
/**
|
||||
* RDOS 2.1/3.2 disks are structured in a different order than DOS 3.3.
|
||||
|
||||
@@ -25,7 +25,6 @@ import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.webcodepro.applecommander.storage.*;
|
||||
import com.webcodepro.applecommander.storage.physical.ImageOrder;
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVPrinter;
|
||||
|
||||
@@ -36,8 +35,11 @@ import com.webcodepro.applecommander.storage.FormattedDisk.FileColumnHeader;
|
||||
import com.webcodepro.applecommander.util.TextBundle;
|
||||
import com.webcodepro.applecommander.util.filestreamer.FileStreamer;
|
||||
import com.webcodepro.applecommander.util.filestreamer.FileTuple;
|
||||
import org.applecommander.device.BlockDevice;
|
||||
import org.applecommander.device.TrackSectorDevice;
|
||||
import org.applecommander.source.Source;
|
||||
import org.applecommander.source.Sources;
|
||||
import org.applecommander.util.Container;
|
||||
|
||||
public class DirectoryLister {
|
||||
private static TextBundle textBundle = UiBundle.getInstance();
|
||||
@@ -62,7 +64,7 @@ public class DirectoryLister {
|
||||
Source source = Sources.create(filename).orElseThrow();
|
||||
DiskFactory.Context ctx = Disks.inspect(source);
|
||||
// Pulling ImageOrder from a FormattedDisk to ensure it's one we chose
|
||||
strategy.first(ctx.disks.getFirst().getImageOrder());
|
||||
strategy.first(ctx.disks.getFirst());
|
||||
|
||||
FileStreamer.forDisks(ctx.disks)
|
||||
.recursive(true)
|
||||
@@ -81,7 +83,7 @@ public class DirectoryLister {
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
public void first(ImageOrder o) {};
|
||||
public void first(FormattedDisk d) {};
|
||||
public void beforeDisk(FormattedDisk d) {}
|
||||
public void afterDisk(FormattedDisk d) {}
|
||||
public void forEach(FileTuple f) {}
|
||||
@@ -169,11 +171,22 @@ public class DirectoryLister {
|
||||
super(display);
|
||||
}
|
||||
@Override
|
||||
public void first(ImageOrder order) {
|
||||
public void first(FormattedDisk disk) {
|
||||
root = new JsonObject();
|
||||
root.addProperty("filename", order.getSource().getName());
|
||||
root.addProperty("order", order.getName());
|
||||
root.addProperty("physicalSize", order.getPhysicalSize());
|
||||
root.addProperty("filename", disk.getFilename());
|
||||
if (disk instanceof FormattedDiskX x) {
|
||||
root.addProperty("order", x.getOrderName());
|
||||
root.addProperty("physicalSize", x.getPhysicalSize());
|
||||
}
|
||||
else if (disk instanceof Container c) {
|
||||
root.addProperty("size", disk.getSource().getSize());
|
||||
if (c.get(BlockDevice.class).isPresent()) {
|
||||
root.addProperty("device", "block device");
|
||||
}
|
||||
else if (c.get(TrackSectorDevice.class).isPresent()) {
|
||||
root.addProperty("device", "track/sector device");
|
||||
}
|
||||
}
|
||||
this.disks = new JsonArray();
|
||||
root.add("disks", disks);
|
||||
}
|
||||
|
||||
@@ -19,11 +19,10 @@
|
||||
*/
|
||||
package org.applecommander.device;
|
||||
|
||||
import org.applecommander.capability.CapabilityProvider;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
|
||||
public interface BlockDevice extends CapabilityProvider {
|
||||
int BLOCK_SIZE = 512;
|
||||
public interface BlockDevice extends Device {
|
||||
int STANDARD_BLOCK_SIZE = 512;
|
||||
|
||||
Geometry getGeometry();
|
||||
DataBuffer readBlock(int block);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package org.applecommander.device;
|
||||
|
||||
import org.applecommander.capability.Capability;
|
||||
import org.applecommander.hint.Hint;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
|
||||
/**
|
||||
@@ -36,6 +37,11 @@ public class BlockToTrackSectorAdapter implements TrackSectorDevice {
|
||||
this.geometry = new Geometry(strategy.getTotalTracks(), strategy.getSectorsPerTrack());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Hint hint) {
|
||||
return device.is(hint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean can(Capability capability) {
|
||||
return device.can(capability);
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* AppleCommander - An Apple ][ image utility.
|
||||
* Copyright (C) 2025 by Robert Greene and others
|
||||
* robgreene at users.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
package org.applecommander.device;
|
||||
|
||||
import org.applecommander.capability.CapabilityProvider;
|
||||
import org.applecommander.hint.HintProvider;
|
||||
|
||||
/**
|
||||
* This is a marker interface for both the BlockDevice and TrackSectorDevice and should
|
||||
* not be implemented directly.
|
||||
*/
|
||||
public interface Device extends HintProvider, CapabilityProvider {
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
package org.applecommander.device;
|
||||
|
||||
import org.applecommander.capability.Capability;
|
||||
import org.applecommander.hint.Hint;
|
||||
import org.applecommander.source.Source;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
|
||||
@@ -32,6 +33,11 @@ public class DosOrderedTrackSectorDevice implements TrackSectorDevice {
|
||||
this.geometry = new Geometry(35, 16); // assumed for now?
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Hint hint) {
|
||||
return hint == Hint.DOS_SECTOR_ORDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean can(Capability capability) {
|
||||
return capability == Capability.WRITE_SECTOR;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package org.applecommander.device;
|
||||
|
||||
import org.applecommander.capability.Capability;
|
||||
import org.applecommander.hint.Hint;
|
||||
import org.applecommander.source.Source;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
|
||||
@@ -32,6 +33,11 @@ public class ProdosOrderedBlockDevice implements BlockDevice {
|
||||
this.geometry = new Geometry(blockSize, blocksOnDevice);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Hint hint) {
|
||||
return hint == Hint.PRODOS_BLOCK_ORDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean can(Capability capability) {
|
||||
return capability == Capability.WRITE_BLOCK;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package org.applecommander.device;
|
||||
|
||||
import org.applecommander.capability.Capability;
|
||||
import org.applecommander.hint.Hint;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
|
||||
public class SkewedTrackSectorDevice implements TrackSectorDevice {
|
||||
@@ -38,6 +39,11 @@ public class SkewedTrackSectorDevice implements TrackSectorDevice {
|
||||
this.sectorSkew = sectorSkew;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Hint hint) {
|
||||
return device.is(hint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean can(Capability capability) {
|
||||
if (capability == Capability.WRITE_SECTOR) {
|
||||
|
||||
@@ -19,17 +19,16 @@
|
||||
*/
|
||||
package org.applecommander.device;
|
||||
|
||||
import org.applecommander.capability.CapabilityProvider;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
|
||||
public interface TrackSectorDevice extends CapabilityProvider {
|
||||
public interface TrackSectorDevice extends Device {
|
||||
int SECTOR_SIZE = 256;
|
||||
|
||||
Geometry getGeometry();
|
||||
DataBuffer readSector(int track, int sector);
|
||||
void writeSector(int track, int sector, DataBuffer data);
|
||||
record Geometry(int tracksOnDisk, int sectorsPerTrack) {
|
||||
int getSectorsPerDisk() {
|
||||
public int sectorsPerDisk() {
|
||||
return tracksOnDisk*sectorsPerTrack;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ package org.applecommander.device;
|
||||
|
||||
import org.applecommander.capability.Capability;
|
||||
import org.applecommander.codec.NibbleDiskCodec;
|
||||
import org.applecommander.hint.Hint;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
|
||||
public class TrackSectorNibbleDevice implements TrackSectorDevice {
|
||||
@@ -41,7 +42,12 @@ public class TrackSectorNibbleDevice implements TrackSectorDevice {
|
||||
this.geometry = new Geometry(trackReaderWriter.getTracksOnDevice(), sectorsPerTrack);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public boolean is(Hint hint) {
|
||||
return hint == Hint.NIBBLE_SECTOR_ORDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean can(Capability capability) {
|
||||
if (capability == Capability.WRITE_SECTOR) {
|
||||
return trackReaderWriter.can(Capability.WRITE_TRACK) && dataCodec.can(Capability.ENCODE);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package org.applecommander.device;
|
||||
|
||||
import org.applecommander.capability.Capability;
|
||||
import org.applecommander.hint.Hint;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
@@ -30,7 +31,12 @@ public class TrackSectorToBlockAdapter implements BlockDevice {
|
||||
|
||||
public TrackSectorToBlockAdapter(TrackSectorDevice device) {
|
||||
this.device = device;
|
||||
this.geometry = new Geometry(BLOCK_SIZE, device.getGeometry().getSectorsPerDisk() / 2);
|
||||
this.geometry = new Geometry(STANDARD_BLOCK_SIZE, device.getGeometry().sectorsPerDisk() / 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Hint hint) {
|
||||
return device.is(hint);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,7 +51,7 @@ public class TrackSectorToBlockAdapter implements BlockDevice {
|
||||
|
||||
@Override
|
||||
public DataBuffer readBlock(int block) {
|
||||
DataBuffer data = DataBuffer.create(BLOCK_SIZE);
|
||||
DataBuffer data = DataBuffer.create(STANDARD_BLOCK_SIZE);
|
||||
operate(block,
|
||||
(t,s) -> data.put(0, device.readSector(t,s)),
|
||||
(t,s) -> data.put(256, device.readSector(t,s)));
|
||||
|
||||
@@ -77,6 +77,21 @@ public class DataBuffer {
|
||||
get(offset, match);
|
||||
return Arrays.equals(data, match);
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof DataBuffer that) {
|
||||
return this.buffer.equals(that.buffer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* A utility method to pull the buffer as bytes.
|
||||
*/
|
||||
public byte[] asBytes() {
|
||||
byte[] data = new byte[limit()];
|
||||
get(0, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
// GET/PUT RELATED FUNCTIONS
|
||||
|
||||
|
||||
@@ -331,8 +331,9 @@ public class DiskWriterTest {
|
||||
writeFile(disk,
|
||||
"This is a test text file create from the DiskWriterTest".getBytes(), //$NON-NLS-1$
|
||||
textType, testText);
|
||||
if (disk.getPhysicalSize() > DiskConstants.APPLE_140KB_DISK
|
||||
&& disk.getPhysicalSize() != DiskConstants.APPLE_140KB_NIBBLE_DISK) {
|
||||
Source source = disk.getSource();
|
||||
if (source.getSize() > DiskConstants.APPLE_140KB_DISK
|
||||
&& source.getSize() != DiskConstants.APPLE_140KB_NIBBLE_DISK) {
|
||||
// create a few big files
|
||||
writeFile(disk, 150000, binaryType, true);
|
||||
writeFile(disk, 300000, binaryType, true);
|
||||
|
||||
+14
-14
@@ -39,6 +39,7 @@ import com.webcodepro.applecommander.util.Host;
|
||||
import com.webcodepro.applecommander.util.StreamUtil;
|
||||
import com.webcodepro.applecommander.util.TextBundle;
|
||||
import io.github.applecommander.applesingle.AppleSingle;
|
||||
import org.applecommander.device.Device;
|
||||
import org.applecommander.hint.Hint;
|
||||
import org.applecommander.source.DataBufferSource;
|
||||
import org.applecommander.source.Source;
|
||||
@@ -1276,12 +1277,7 @@ public class DiskExplorerTab {
|
||||
changeOrderToolItem.setImage(imageManager.get(ImageManager.ICON_CHANGE_IMAGE_ORDER));
|
||||
changeOrderToolItem.setText(textBundle.get("ChangeDiskOrderToolItem")); //$NON-NLS-1$
|
||||
changeOrderToolItem.setToolTipText(textBundle.get("ChangeDiskOrderHoverText")); //$NON-NLS-1$
|
||||
ImageOrder imageOrder = disks[0].getImageOrder();
|
||||
changeOrderToolItem.setEnabled(
|
||||
(imageOrder.isBlockDevice()
|
||||
&& imageOrder.getBlocksOnDevice() == DiskConstants.PRODOS_BLOCKS_ON_140KB_DISK)
|
||||
|| (imageOrder.isTrackAndSectorDevice()
|
||||
&& imageOrder.getSectorsPerDisk() == DiskConstants.DOS33_SECTORS_ON_140KB_DISK));
|
||||
changeOrderToolItem.setEnabled(disks[0].getSource().isApproxEQ(DiskConstants.APPLE_140KB_DISK));
|
||||
changeOrderToolItem.addSelectionListener(
|
||||
new DropDownSelectionListener(getChangeImageOrderMenu()));
|
||||
changeOrderToolItem.addSelectionListener(new SelectionAdapter () {
|
||||
@@ -1807,7 +1803,8 @@ public class DiskExplorerTab {
|
||||
*/
|
||||
protected void changeImageOrder(String extension, ImageOrder newImageOrder) {
|
||||
try {
|
||||
disks[0].changeImageOrder(newImageOrder);
|
||||
FormattedDiskX diskx = (FormattedDiskX) disks[0];
|
||||
diskx.changeImageOrder(newImageOrder);
|
||||
String filename = disks[0].getFilename();
|
||||
if (filename.toLowerCase().endsWith(".gz")) {
|
||||
int chop = filename.lastIndexOf(".", filename.length()-4); //$NON-NLS-1$
|
||||
@@ -1840,15 +1837,15 @@ public class DiskExplorerTab {
|
||||
Menu menu = new Menu(shell, SWT.NONE);
|
||||
menu.addMenuListener(new MenuAdapter() {
|
||||
public void menuShown(MenuEvent event) {
|
||||
ImageOrder order = getDisk(0).getImageOrder();
|
||||
Device device = DeviceAdapter.from(getDisk(0));
|
||||
Menu theMenu = (Menu) event.getSource();
|
||||
MenuItem[] subItems = theMenu.getItems();
|
||||
// Nibble Order (*.nib)
|
||||
subItems[0].setSelection(order.is(Hint.NIBBLE_SECTOR_ORDER));
|
||||
subItems[0].setSelection(device.is(Hint.NIBBLE_SECTOR_ORDER));
|
||||
// DOS Order (*.dsk)
|
||||
subItems[1].setSelection(order.is(Hint.DOS_SECTOR_ORDER));
|
||||
subItems[1].setSelection(device.is(Hint.DOS_SECTOR_ORDER));
|
||||
// ProDOS Order (*.po)
|
||||
subItems[2].setSelection(order.is(Hint.PRODOS_BLOCK_ORDER));
|
||||
subItems[2].setSelection(device.is(Hint.PRODOS_BLOCK_ORDER));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1856,7 +1853,8 @@ public class DiskExplorerTab {
|
||||
item.setText(textBundle.get("ChangeToNibbleOrderMenuItem")); //$NON-NLS-1$
|
||||
item.addSelectionListener(new SelectionAdapter() {
|
||||
public void widgetSelected(SelectionEvent event) {
|
||||
if (!getDisk(0).getImageOrder().is(Hint.NIBBLE_SECTOR_ORDER)) {
|
||||
Device device = DeviceAdapter.from(getDisk(0));
|
||||
if (!device.is(Hint.NIBBLE_SECTOR_ORDER)) {
|
||||
NibbleOrder nibbleOrder = new NibbleOrder(
|
||||
DataBufferSource.create(DiskConstants.APPLE_140KB_NIBBLE_DISK, "new-image.nib").get());
|
||||
nibbleOrder.format();
|
||||
@@ -1869,7 +1867,8 @@ public class DiskExplorerTab {
|
||||
item.setText(textBundle.get("ChangeToDosOrderMenuItem")); //$NON-NLS-1$
|
||||
item.addSelectionListener(new SelectionAdapter() {
|
||||
public void widgetSelected(SelectionEvent event) {
|
||||
if (!getDisk(0).getImageOrder().is(Hint.DOS_SECTOR_ORDER)) {
|
||||
Device device = DeviceAdapter.from(getDisk(0));
|
||||
if (!device.is(Hint.DOS_SECTOR_ORDER)) {
|
||||
changeImageOrder("dsk", new DosOrder( //$NON-NLS-1$
|
||||
DataBufferSource.create(DiskConstants.APPLE_140KB_DISK, "new-image.dsk").get()));
|
||||
}
|
||||
@@ -1880,7 +1879,8 @@ public class DiskExplorerTab {
|
||||
item.setText(textBundle.get("ChangeToProdosOrderMenuItem")); //$NON-NLS-1$
|
||||
item.addSelectionListener(new SelectionAdapter() {
|
||||
public void widgetSelected(SelectionEvent event) {
|
||||
if (!getDisk(0).getImageOrder().is(Hint.PRODOS_BLOCK_ORDER)) {
|
||||
Device device = DeviceAdapter.from(getDisk(0));
|
||||
if (!device.is(Hint.PRODOS_BLOCK_ORDER)) {
|
||||
changeImageOrder("po", new ProdosOrder( //$NON-NLS-1$
|
||||
DataBufferSource.create(DiskConstants.APPLE_140KB_DISK, "new-image.po").get()));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user