dmolony-DiskBrowser/src/com/bytezone/diskbrowser/dos/DosVTOCSector.java

225 lines
8.3 KiB
Java
Executable File

package com.bytezone.diskbrowser.dos;
import com.bytezone.diskbrowser.disk.AbstractSector;
import com.bytezone.diskbrowser.disk.Disk;
import com.bytezone.diskbrowser.disk.DiskAddress;
import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------//
class DosVTOCSector extends AbstractSector
// -----------------------------------------------------------------------------------//
{
DosDisk parentDisk;
int volume;
int dosVersion; // 1, 2, 3 or 0x41, 0x42, 0x43...
int maxTSPairs;
int lastAllocTrack;
int direction;
int freeSectors;
int usedSectors;
int sectorSize;
int maxSectors;
int maxTracks;
// ---------------------------------------------------------------------------------//
DosVTOCSector (DosDisk parentDisk, Disk disk, byte[] buffer, DiskAddress diskAddress)
// ---------------------------------------------------------------------------------//
{
super (disk, buffer, diskAddress);
this.parentDisk = parentDisk;
dosVersion = buffer[3];
volume = buffer[6] & 0xFF;
maxTSPairs = buffer[39];
lastAllocTrack = buffer[48];
direction = buffer[49];
maxTracks = buffer[52] & 0xFF;
maxSectors = buffer[53] & 0xFF;
sectorSize = Utility.getShort (buffer, 54);
flagSectors ();
}
// ---------------------------------------------------------------------------------//
@Override
public String createText ()
// ---------------------------------------------------------------------------------//
{
return dosVersion <= 3 ? createDos3Text () : createDos4Text ();
}
// ---------------------------------------------------------------------------------//
private String createDos3Text ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = getHeader ("VTOC Sector");
addText (text, buffer, 0, 1, "Not used");
addText (text, buffer, 1, 2, "First directory track/sector");
addText (text, buffer, 3, 1, "DOS release number");
addText (text, buffer, 4, 2, "Not used");
addTextAndDecimal (text, buffer, 6, 1, "Diskette volume");
addText (text, buffer, 7, 4, "Not used");
addText (text, buffer, 11, 4, "Not used");
addText (text, buffer, 15, 4, "Not used");
addText (text, buffer, 19, 4, "Not used");
addText (text, buffer, 23, 4, "Not used");
addText (text, buffer, 27, 4, "Not used");
addText (text, buffer, 31, 4, "Not used");
addText (text, buffer, 35, 4, "Not used");
addTextAndDecimal (text, buffer, 39, 1, "Maximum TS pairs");
addText (text, buffer, 40, 4, "Not used");
addText (text, buffer, 44, 4, "Not used");
addTextAndDecimal (text, buffer, 48, 1, "Last allocated track");
addText (text, buffer, 49, 1, "Direction to look when allocating the next file");
addText (text, buffer, 50, 2, "Not used");
addTextAndDecimal (text, buffer, 52, 1, "Maximum tracks");
if (maxTracks != disk.getTotalTracks ())
{
text.deleteCharAt (text.length () - 1);
text.append (String.format (" <-- Should be 0x%02X !!%n",
disk.getTotalTracks ()));
}
addTextAndDecimal (text, buffer, 53, 1, "Maximum sectors");
addTextAndDecimal (text, buffer, 54, 2, "Bytes per sector");
boolean bootSectorEmpty = parentDisk.getDisk ().isBlockEmpty (0);
int firstSector = 0x38;
int max = maxTracks * 4 + firstSector;
for (int i = firstSector; i < max; i += 4)
{
String extra = "";
if (i == firstSector && bootSectorEmpty)
extra = "(unusable)";
String bits = getBitmap (buffer, i);
int track = (i - firstSector) / 4;
addText (text, buffer, i, 4,
String.format ("Track %02X %s %s", track, bits, extra));
}
text.deleteCharAt (text.length () - 1);
return text.toString ();
}
// ---------------------------------------------------------------------------------//
private String createDos4Text ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = getHeader ("DOS 4 VTOC Sector");
addText (text, buffer, 0, 1, "Not used");
addText (text, buffer, 1, 2, "First directory track/sector");
addText (text, buffer, 3, 1, "DOS release number");
addText (text, buffer, 4, 1, "Build number");
addText (text, buffer, 5, 1, "Ram DOS " + (char) (buffer[5] & 0x7F));
addTextAndDecimal (text, buffer, 6, 1, "Diskette volume");
String diskType =
buffer[7] == (byte) 0xC4 ? " = Data" : buffer[7] == (byte) 0xC2 ? " = Boot" : "";
addText (text, buffer, 7, 1, "Volume type: " + (char) (buffer[7] & 0x7F) + diskType);
int ptr = 8;
addText (text, buffer, ptr, 4,
"Volume name: " + DosCatalogSector.getName (buffer, ptr, 30));
for (int j = 4; j < 24; j += 4)
addText (text, buffer, ptr + j, 4, "");
addText (text, buffer, 0x20, 3,
"Date/time initialised: " + Utility.getDateTime (buffer, 0x20));
addText (text, buffer, 0x23, 3, "");
addText (text, buffer, 0x26, 1, "VTOC Phase");
addTextAndDecimal (text, buffer, 0x27, 1, "Maximum TS pairs");
addText (text, buffer, 0x28, 2, "Volume library");
addText (text, buffer, 0x2A, 3,
"Date/time modified: " + Utility.getDateTime (buffer, 0x2A));
addText (text, buffer, 0x2D, 3, "");
addTextAndDecimal (text, buffer, 0x30, 1, "Last allocated track");
addText (text, buffer, 0x31, 1, "Direction to look when allocating the next file");
addText (text, buffer, 0x32, 2, "Not used");
addTextAndDecimal (text, buffer, 0x34, 1, "Maximum tracks");
addTextAndDecimal (text, buffer, 0x35, 1, "Maximum sectors");
addTextAndDecimal (text, buffer, 0x36, 2, "Bytes per sector");
boolean bootSectorEmpty = parentDisk.getDisk ().isBlockEmpty (0);
int firstSector = 0x38;
int max = maxTracks * 4 + firstSector;
for (int i = firstSector; i < max; i += 4)
{
String extra = "";
if (i == firstSector && bootSectorEmpty)
extra = "(unusable)";
else if (i == 124)
extra = "(VTOC and Catalog)";
addText (text, buffer, i, 4, String.format ("Track %02X %s %s",
(i - firstSector) / 4, getBitmap (buffer, i), extra));
}
text.deleteCharAt (text.length () - 1);
return text.toString ();
}
// ---------------------------------------------------------------------------------//
private String getBitmap (byte[] buffer, int offset)
// ---------------------------------------------------------------------------------//
{
int value = Utility.getLongBigEndian (buffer, offset);
String bits = "0000000000000000000000000000000" + Integer.toBinaryString (value);
bits = bits.substring (bits.length () - 32);
bits = bits.substring (0, maxSectors);
bits = bits.replace ('0', 'X');
bits = bits.replace ('1', '.');
return new StringBuilder (bits).reverse ().toString ();
}
// ---------------------------------------------------------------------------------//
private void flagSectors ()
// ---------------------------------------------------------------------------------//
{
int firstSector = 0x38;
int max = disk.getTotalTracks () * 4 + firstSector;
for (int i = firstSector; i < max; i += 4)
{
int track = (i - firstSector) / 4;
String bits = getBitmap (buffer, i);
int blockNo = track * maxSectors;
char[] chars = bits.toCharArray ();
for (int sector = 0; sector < maxSectors; sector++)
{
if (chars[sector] == '.')
{
parentDisk.setSectorFree (blockNo, true);
++freeSectors;
}
else
{
parentDisk.setSectorFree (blockNo, false);
++usedSectors;
}
++blockNo;
}
}
}
// ---------------------------------------------------------------------------------//
@Override
public String toString ()
// ---------------------------------------------------------------------------------//
{
StringBuffer text = new StringBuffer ();
text.append ("DOS version : 3." + dosVersion);
text.append ("\nVolume : " + volume);
text.append ("\nMax TS pairs : " + maxTSPairs);
text.append ("\nLast allocated T : " + lastAllocTrack);
text.append ("\nDirection : " + direction);
return text.toString ();
}
}