2015-06-01 09:35:51 +00:00
|
|
|
package com.bytezone.diskbrowser.prodos;
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
import com.bytezone.diskbrowser.disk.DiskAddress;
|
|
|
|
import com.bytezone.diskbrowser.gui.DataSource;
|
2016-02-24 21:11:14 +00:00
|
|
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
2015-06-01 09:35:51 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* There is only one of these - it is always the first entry in the first block.
|
|
|
|
* Every other entry will be either a SubDirectoryHeader or a FileEntry.
|
|
|
|
*/
|
|
|
|
class VolumeDirectoryHeader extends DirectoryHeader
|
|
|
|
{
|
2016-02-28 07:17:58 +00:00
|
|
|
protected final int bitMapBlock;
|
|
|
|
protected int totalBlocks;
|
|
|
|
protected int freeBlocks;
|
|
|
|
protected int usedBlocks;
|
|
|
|
protected int totalBitMapBlocks;
|
2015-06-01 09:35:51 +00:00
|
|
|
|
|
|
|
public VolumeDirectoryHeader (ProdosDisk parentDisk, byte[] entryBuffer)
|
|
|
|
{
|
|
|
|
super (parentDisk, entryBuffer);
|
|
|
|
|
2017-04-22 06:31:25 +00:00
|
|
|
bitMapBlock = HexFormatter.unsignedShort (entryBuffer, 35);
|
|
|
|
totalBlocks = HexFormatter.unsignedShort (entryBuffer, 37);
|
2017-05-08 01:46:28 +00:00
|
|
|
|
|
|
|
// if (totalBlocks == 0xFFFF || totalBlocks == 0x7FFF)
|
|
|
|
// totalBlocks = (int) disk.getFile ().length () / 4096 * 8;// ignore extra bytes
|
|
|
|
|
2015-06-01 09:35:51 +00:00
|
|
|
totalBitMapBlocks = (totalBlocks - 1) / 512 + 1;
|
|
|
|
|
|
|
|
int block = 2;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
dataBlocks.add (disk.getDiskAddress (block));
|
|
|
|
byte[] buffer = disk.readSector (block);
|
2017-04-22 06:31:25 +00:00
|
|
|
block = HexFormatter.unsignedShort (buffer, 2);
|
2015-06-01 09:35:51 +00:00
|
|
|
} while (block > 0);
|
|
|
|
|
|
|
|
// convert the Free Sector Table
|
2017-05-08 01:46:28 +00:00
|
|
|
int bitMapBytes = totalBlocks / 8; // one bit per block
|
2015-06-01 09:35:51 +00:00
|
|
|
byte[] buffer = new byte[bitMapBytes];
|
|
|
|
int bitMapBlocks = (bitMapBytes - 1) / disk.getSectorsPerTrack () + 1;
|
|
|
|
int lastBitMapBlock = bitMapBlock + bitMapBlocks - 1;
|
|
|
|
int ptr = 0;
|
|
|
|
|
|
|
|
for (block = bitMapBlock; block <= lastBitMapBlock; block++)
|
|
|
|
{
|
|
|
|
byte[] temp = disk.readSector (block);
|
|
|
|
int bytesToCopy = buffer.length - ptr;
|
|
|
|
if (bytesToCopy > temp.length)
|
|
|
|
bytesToCopy = temp.length;
|
|
|
|
System.arraycopy (temp, 0, buffer, ptr, bytesToCopy);
|
|
|
|
ptr += bytesToCopy;
|
|
|
|
}
|
|
|
|
|
|
|
|
block = 0;
|
2016-02-28 05:41:30 +00:00
|
|
|
|
2016-02-28 07:17:58 +00:00
|
|
|
// nb1 dual-dos disk needs to use totalBlocks obtained from disk
|
|
|
|
// int max1 = (totalBlocks - 1) / 8 + 1; // bytes required for sector map
|
|
|
|
// nb2 hard disk may be truncated, so use actual number of blocks
|
2016-02-28 05:41:30 +00:00
|
|
|
// int max2 = (disk.getTotalBlocks () - 1) / 8 + 1; // bytes required for sector map
|
|
|
|
|
|
|
|
int max = (Math.min (totalBlocks, disk.getTotalBlocks ()) - 1) / 8 + 1;
|
2017-05-08 01:46:28 +00:00
|
|
|
// System.out.printf ("total blocks %,d%n", totalBlocks);
|
|
|
|
// System.out.printf ("disk blocks %,d%n", disk.getTotalBlocks ());
|
2015-06-01 09:35:51 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < max; i++)
|
|
|
|
{
|
|
|
|
byte b = buffer[i];
|
|
|
|
for (int j = 0; j < 8; j++)
|
|
|
|
{
|
|
|
|
if ((b & 0x80) == 0x80)
|
|
|
|
{
|
|
|
|
freeBlocks++;
|
|
|
|
parentDisk.setSectorFree (block++, true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
usedBlocks++;
|
|
|
|
parentDisk.setSectorFree (block++, false);
|
|
|
|
}
|
|
|
|
b <<= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public DataSource getDataSource ()
|
|
|
|
{
|
|
|
|
List<byte[]> blockList = new ArrayList<byte[]> ();
|
|
|
|
int block = 2;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
byte[] buf = disk.readSector (block);
|
|
|
|
blockList.add (buf);
|
|
|
|
block = HexFormatter.intValue (buf[2], buf[3]); // next block
|
|
|
|
} while (block > 0);
|
|
|
|
|
|
|
|
byte[] fullBuffer = new byte[blockList.size () * 507];
|
|
|
|
int offset = 0;
|
|
|
|
for (byte[] bfr : blockList)
|
|
|
|
{
|
|
|
|
System.arraycopy (bfr, 4, fullBuffer, offset, 507);
|
|
|
|
offset += 507;
|
|
|
|
}
|
|
|
|
return new ProdosDirectory (parentDisk, name, fullBuffer, totalBlocks, freeBlocks,
|
2016-02-24 02:13:52 +00:00
|
|
|
usedBlocks);
|
2015-06-01 09:35:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public List<DiskAddress> getSectors ()
|
|
|
|
{
|
|
|
|
List<DiskAddress> sectors = new ArrayList<DiskAddress> ();
|
|
|
|
sectors.addAll (dataBlocks);
|
|
|
|
return sectors;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString ()
|
|
|
|
{
|
|
|
|
if (false)
|
|
|
|
{
|
|
|
|
String locked = (access == 0x01) ? "*" : " ";
|
2016-03-24 00:17:09 +00:00
|
|
|
String timeC = created == null ? "" : parentDisk.df.format (created.getTime ());
|
2015-06-01 09:35:51 +00:00
|
|
|
return String.format (" %s%-42s %15s", locked, "/" + name, timeC);
|
|
|
|
}
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
}
|