194 lines
5.8 KiB
Java
194 lines
5.8 KiB
Java
/*
|
|
* AppleCommander - An Apple ][ image utility.
|
|
* Copyright (C) 2003 by Robert Greene
|
|
* 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.physical;
|
|
|
|
import com.webcodepro.applecommander.storage.Disk;
|
|
|
|
/**
|
|
* Manages the interface between the physical disk image order and the
|
|
* logical operating system specific order. These management objects
|
|
* are intended to be hidden by Disk itself, although the ImageOrder
|
|
* may be changed (overridden).
|
|
* <p>
|
|
* To implement this class, over-ride the block-oriented methods
|
|
* (readBlock, writeBlock) or the track and sector-oriented
|
|
* methods (readSector, writeSector).
|
|
* Ensure that isBlockDevice or isTrackAndSectorDevice is set
|
|
* appropriately.
|
|
* <p>
|
|
* Note that a block is generally assumed to be an Apple ProDOS
|
|
* (or Apple Pascal) formatted volume where a block is 512 bytes.
|
|
* The track and sector device is generally a 140K 5.25" disk,
|
|
* although it may be an 800K 3.5" disk with two 400K DOS volumes.
|
|
* In either case, the sector size will be 256 bytes.
|
|
* <p>
|
|
* At this time, the RDOS block of 256 bytes is managed by the
|
|
* RdosFormatDisk, and the 1024 byte CP/M block is managed by the
|
|
* CpmFormatDisk (the CP/M sector of 128 bytes is largely ignored).
|
|
* <p>
|
|
* Design note: The physical order could alternatively be implemented
|
|
* with a BlockPhysicalOrder structure which includes ProdosOrder
|
|
* and a Track and Sector adapter, as well as a TrackAndSectorPhysicalOrder
|
|
* which includes a NibblePhysicalOrder and DosOrder as well as
|
|
* a Block adapter class. This way, Disk contains two separate classes
|
|
* (block as well as a track/sector) to manage the disk.
|
|
* <p>
|
|
* @author Rob Greene (RobGreene@users.sourceforge.net)
|
|
*/
|
|
public abstract class ImageOrder {
|
|
/**
|
|
* This is the physical copy of the disk image which a particular
|
|
* implementation of ImageOrder will interpret.
|
|
*/
|
|
private ByteArrayImageLayout diskImageManager;
|
|
|
|
/**
|
|
* Construct a ImageOrder.
|
|
*/
|
|
public ImageOrder(ByteArrayImageLayout diskImageManager) {
|
|
setDiskImageManager(diskImageManager);
|
|
}
|
|
|
|
/**
|
|
* Get the physical disk image.
|
|
*/
|
|
public ByteArrayImageLayout getDiskImageManager() {
|
|
return diskImageManager;
|
|
}
|
|
|
|
/**
|
|
* Answer with the physical size of this disk volume.
|
|
*/
|
|
public int getPhysicalSize() {
|
|
return diskImageManager.getPhysicalSize();
|
|
}
|
|
|
|
/**
|
|
* Set the physical disk image.
|
|
*/
|
|
public void setDiskImageManager(ByteArrayImageLayout diskImageManager) {
|
|
this.diskImageManager = diskImageManager;
|
|
}
|
|
|
|
/**
|
|
* Extract a portion of the disk image.
|
|
*/
|
|
public byte[] readBytes(int start, int length) {
|
|
return diskImageManager.readBytes(start, length);
|
|
}
|
|
|
|
/**
|
|
* Write data to the disk image.
|
|
*/
|
|
public void writeBytes(int start, byte[] bytes) {
|
|
diskImageManager.writeBytes(start, bytes);
|
|
}
|
|
|
|
/**
|
|
* Answer with the number of blocks on this device.
|
|
*/
|
|
public int getBlocksOnDevice() {
|
|
return getPhysicalSize() / Disk.BLOCK_SIZE;
|
|
}
|
|
|
|
/**
|
|
* Return the name of this image order.
|
|
*/
|
|
public abstract String getName();
|
|
|
|
/**
|
|
* Read the block from the disk image.
|
|
*/
|
|
public abstract byte[] readBlock(int block);
|
|
|
|
/**
|
|
* Write the block to the disk image.
|
|
*/
|
|
public abstract void writeBlock(int block, byte[] data);
|
|
|
|
/**
|
|
* Indicates that this device is block ordered.
|
|
*/
|
|
public abstract boolean isBlockDevice();
|
|
|
|
/**
|
|
* Indicates that this device is track and sector ordered.
|
|
*/
|
|
public abstract boolean isTrackAndSectorDevice();
|
|
|
|
/**
|
|
* Answer with the number of tracks on this device.
|
|
*/
|
|
public int getTracksPerDisk() {
|
|
return getPhysicalSize() / (getSectorsPerTrack() * Disk.SECTOR_SIZE);
|
|
}
|
|
|
|
/**
|
|
* Answer with the number of sectors per track on this device.
|
|
*/
|
|
public int getSectorsPerTrack() {
|
|
if (isSizeApprox(Disk.APPLE_800KB_DISK)
|
|
|| isSizeApprox(Disk.APPLE_800KB_2IMG_DISK)) {
|
|
return 32;
|
|
}
|
|
return 16;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the specified sector.
|
|
*/
|
|
public abstract byte[] readSector(int track, int sector) throws IllegalArgumentException;
|
|
|
|
/**
|
|
* Write the specified sector.
|
|
*/
|
|
public abstract void writeSector(int track, int sector, byte[] bytes) throws IllegalArgumentException;
|
|
|
|
/**
|
|
* Indicates if the physical disk is approximately this size.
|
|
* Currently hardcoded to allow up to 10 extra bytes at the end of a
|
|
* disk image. Must be at least the requested size!
|
|
*/
|
|
public boolean isSizeApprox(int value) {
|
|
return getPhysicalSize() >= value && getPhysicalSize() <= value + 10;
|
|
}
|
|
|
|
/**
|
|
* Format the media. Formatting at the ImageOrder level deals with
|
|
* low-level issues. A typical ordering just needs to have the image
|
|
* "wiped," and that is the assumed implementation. However, specialized
|
|
* orders - such as a nibbilized disk - need to lay down track and
|
|
* sector markers.
|
|
*/
|
|
public void format() {
|
|
int size = diskImageManager.getPhysicalSize();
|
|
diskImageManager.setDiskImage(new byte[size]);
|
|
}
|
|
|
|
/**
|
|
* Answer with the total number of sectors in a disk.
|
|
* This is used to size the disk and compare sizes instead of using byte counts
|
|
* which can differ.
|
|
*/
|
|
public int getSectorsPerDisk() {
|
|
return getTracksPerDisk() * getSectorsPerTrack();
|
|
}
|
|
}
|