/* * 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