/* * AppleCommander - An Apple ][ image utility. * Copyright (C) 2002 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; import java.util.ArrayList; import java.util.BitSet; import java.util.List; /** * Manages a disk that is in Apple DOS 3.3 format. *
* Date created: Oct 4, 2002 12:29:23 AM
* @author: Rob Greene
*/
public class DosFormatDisk extends FormattedDisk {
/**
* Indicates the length in bytes of the DOS file entry field.
*/
public static final int FILE_DESCRIPTIVE_ENTRY_LENGTH = 35;
/**
* Indicates the index of the track in the location array.
*/
public static final int TRACK_LOCATION_INDEX = 0;
/**
* Indicates the index of the sector in the location array.
*/
public static final int SECTOR_LOCATION_INDEX = 1;
/**
* Use this inner interface for managing the disk usage data.
* This offloads format-specific implementation to the implementing class.
*/
private class DosDiskUsage implements DiskUsage {
private int[] location = null;
public boolean hasNext() {
return location == null
|| (location[TRACK_LOCATION_INDEX] < getTracks()
&& location[SECTOR_LOCATION_INDEX] < getSectors());
}
public void next() {
if (location == null) {
location = new int[2];
} else {
location[SECTOR_LOCATION_INDEX]++;
if (location[SECTOR_LOCATION_INDEX] >= getSectors()) {
location[SECTOR_LOCATION_INDEX] = 0;
location[TRACK_LOCATION_INDEX]++;
}
}
}
/**
* Get the free setting for the bitmap at the current location.
*/
public boolean isFree() {
if (location == null || location.length != 2) {
throw new IllegalArgumentException("Invalid dimension for isFree! Did you call next first?");
}
byte[] vtoc = getVtoc();
byte byt = vtoc[0x38 + (location[TRACK_LOCATION_INDEX] * 4)
+ (location[SECTOR_LOCATION_INDEX] / 8)];
boolean free = AppleUtil.isBitSet(byt, 7 - (location[SECTOR_LOCATION_INDEX] % 8));
return free;
}
public boolean isUsed() {
return !isFree();
}
}
/**
* Constructor for DosFormatDisk.
* @param filename
* @param diskImage
* @param order
*/
public DosFormatDisk(String filename, byte[] diskImage) {
super(filename, diskImage);
}
/**
* Identify the operating system format of this disk as DOS 3.3.
* @see com.webcodepro.applecommander.storage.Disk#getFormat()
*/
public String getFormat() {
return "DOS 3.3";
}
/**
* Retrieve a list of files.
* @see com.webcodepro.applecommander.storage.Disk#getFiles()
*/
public List getFiles() {
List list = new ArrayList();
byte[] vtoc = getVtoc();
int track = AppleUtil.getUnsignedByte(vtoc[1]);
int sector = AppleUtil.getUnsignedByte(vtoc[2]);
while (track != 0) { // iterate through all catalog sectors
byte[] catalogSector = readSector(track, sector);
int offset = 0x0b;
while (offset < 0xff) { // iterate through all entries
byte[] entry = new byte[FILE_DESCRIPTIVE_ENTRY_LENGTH];
System.arraycopy(catalogSector, offset, entry, 0, entry.length);
if (entry[0] != 0) {
list.add(new DosFileEntry(entry, this));
}
offset+= entry.length;
}
track = catalogSector[1];
sector = catalogSector[2];
}
return list;
}
/**
* Identify if this disk format as not capable of having directories.
* @see com.webcodepro.applecommander.storage.Disk#hasDirectories()
*/
public boolean canHaveDirectories() {
return false;
}
/**
* Compute the amount of freespace available on the disk.
* This algorithm completely ignores tracks and sectors by
* running through the entire bitmap stored on the VTOC.
* @see com.webcodepro.applecommander.storage.Disk#getFreeSpace()
*/
public int getFreeSpace() {
return getFreeSectors() * SECTOR_SIZE;
}
/**
* Comput the number of free sectors available on the disk.
*/
public int getFreeSectors() {
byte[] vtoc = getVtoc();
int freeSectors = 0;
for (int offset=0x38; offset<0xff; offset++) {
byte bitmap = vtoc[offset];
freeSectors+= AppleUtil.getBitCount(bitmap);
}
return freeSectors;
}
/**
* Return the amount of used space in bytes.
* @see com.webcodepro.applecommander.storage.Disk#getUsedSpace()
*/
public int getUsedSpace() {
return getUsedSectors() * SECTOR_SIZE;
}
/**
* Compute the number of used sectors on the disk.
*/
public int getUsedSectors() {
return getTotalSectors() - getFreeSectors();
}
/**
* Compute the total number of sectors available on the disk.
*/
public int getTotalSectors() {
int tracks = getTracks();
int sectors = getSectors();
return tracks * sectors;
}
/**
* Return the DOS disk name. Basically, the DISK VOLUME #xxx
* that a CATALOG command would show. Note that Java bytes are
* signed, so a little mojo is in order.
* @see com.webcodepro.applecommander.storage.Disk#getDiskName()
*/
public String getDiskName() {
int volumeNumber = AppleUtil.getUnsignedByte(getVtoc()[0x06]);
return "DISK VOLUME #" + volumeNumber;
}
/**
* Return the VTOC (Volume Table Of Contents).
*/
protected byte[] getVtoc() {
return readSector(0x11, 0);
}
/**
* Get the disk usage bitmap. The size could vary and is stored in the
* VTOC.
* @see com.webcodepro.applecommander.storage.FormattedDisk#getBitmap()
* @deprecated DOS 3.3.po comes up with 448 entries in the bitmap?!
*/
public BitSet getBitmap() {
byte[] vtoc = getVtoc();
int tracks = getTracks();
int sectors = getSectors();
BitSet bitmap = new BitSet(tracks * sectors);
// individually test each track & sector - should handle 140K or 400K disks!
int count = 0;
for (int t=0; t