method header lines

This commit is contained in:
Denis Molony 2020-02-08 18:28:22 +10:00
parent 04557bab39
commit add2b8f946
7 changed files with 1141 additions and 1026 deletions

View File

@ -28,7 +28,9 @@ import com.bytezone.diskbrowser.gui.DataSource;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
import com.bytezone.diskbrowser.utilities.Utility; import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------//
abstract class AbstractCatalogEntry implements AppleFileSource abstract class AbstractCatalogEntry implements AppleFileSource
// -----------------------------------------------------------------------------------//
{ {
protected Disk disk; protected Disk disk;
protected DosDisk dosDisk; protected DosDisk dosDisk;
@ -47,8 +49,9 @@ abstract class AbstractCatalogEntry implements AppleFileSource
private CatalogEntry link; private CatalogEntry link;
public AbstractCatalogEntry (DosDisk dosDisk, DiskAddress catalogSector, // ---------------------------------------------------------------------------------//
byte[] entryBuffer) AbstractCatalogEntry (DosDisk dosDisk, DiskAddress catalogSector, byte[] entryBuffer)
// ---------------------------------------------------------------------------------//
{ {
this.dosDisk = dosDisk; this.dosDisk = dosDisk;
this.disk = dosDisk.getDisk (); this.disk = dosDisk.getDisk ();
@ -88,7 +91,9 @@ abstract class AbstractCatalogEntry implements AppleFileSource
catalogName = getName (base, entryBuffer).replace ("^", ""); catalogName = getName (base, entryBuffer).replace ("^", "");
} }
// ---------------------------------------------------------------------------------//
private String getName (String base, byte[] buffer) private String getName (String base, byte[] buffer)
// ---------------------------------------------------------------------------------//
{ {
StringBuilder text = new StringBuilder (base); StringBuilder text = new StringBuilder (base);
int max = buffer[0] == (byte) 0xFF ? 32 : 33; int max = buffer[0] == (byte) 0xFF ? 32 : 33;
@ -115,7 +120,9 @@ abstract class AbstractCatalogEntry implements AppleFileSource
return text.toString (); return text.toString ();
} }
// ---------------------------------------------------------------------------------//
protected String getFileType () protected String getFileType ()
// ---------------------------------------------------------------------------------//
{ {
switch (fileType) switch (fileType)
{ {
@ -143,15 +150,19 @@ abstract class AbstractCatalogEntry implements AppleFileSource
// maybe this should be in the FormattedDisk // maybe this should be in the FormattedDisk
// maybe DiskAddress should have a 'valid' flag // maybe DiskAddress should have a 'valid' flag
// ---------------------------------------------------------------------------------//
protected DiskAddress getValidAddress (byte[] buffer, int offset) protected DiskAddress getValidAddress (byte[] buffer, int offset)
// ---------------------------------------------------------------------------------//
{ {
if (disk.isValidAddress (buffer[offset], buffer[offset + 1])) if (disk.isValidAddress (buffer[offset], buffer[offset + 1]))
return disk.getDiskAddress (buffer[offset], buffer[offset + 1]); return disk.getDiskAddress (buffer[offset], buffer[offset + 1]);
return null; return null;
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public DataSource getDataSource () public DataSource getDataSource ()
// ---------------------------------------------------------------------------------//
{ {
if (appleFile != null) if (appleFile != null)
return appleFile; return appleFile;
@ -297,7 +308,9 @@ abstract class AbstractCatalogEntry implements AppleFileSource
return appleFile; return appleFile;
} }
// ---------------------------------------------------------------------------------//
private byte[] getExactBuffer (byte[] buffer) private byte[] getExactBuffer (byte[] buffer)
// ---------------------------------------------------------------------------------//
{ {
byte[] exactBuffer; byte[] exactBuffer;
@ -319,14 +332,18 @@ abstract class AbstractCatalogEntry implements AppleFileSource
return exactBuffer; return exactBuffer;
} }
// ---------------------------------------------------------------------------------//
private boolean isRunCommand (byte[] buffer) private boolean isRunCommand (byte[] buffer)
// ---------------------------------------------------------------------------------//
{ {
// see Stargate - Disk 1, Side A.woz // see Stargate - Disk 1, Side A.woz
return buffer[0] == 0x4C && buffer[1] == (byte) 0xFC && buffer[2] == (byte) 0xA4 return buffer[0] == 0x4C && buffer[1] == (byte) 0xFC && buffer[2] == (byte) 0xA4
&& buffer[3] == 0x00; && buffer[3] == 0x00;
} }
// ---------------------------------------------------------------------------------//
private boolean isScrunched (int reportedLength) private boolean isScrunched (int reportedLength)
// ---------------------------------------------------------------------------------//
{ {
if ((name.equals ("FLY LOGO") || name.equals ("FLY LOGO SCRUNCHED")) if ((name.equals ("FLY LOGO") || name.equals ("FLY LOGO SCRUNCHED"))
&& reportedLength == 0x14FA) && reportedLength == 0x14FA)
@ -338,8 +355,10 @@ abstract class AbstractCatalogEntry implements AppleFileSource
return false; return false;
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public boolean contains (DiskAddress da) public boolean contains (DiskAddress da)
// ---------------------------------------------------------------------------------//
{ {
for (DiskAddress sector : tsSectors) for (DiskAddress sector : tsSectors)
if (sector.matches (da)) if (sector.matches (da))
@ -354,21 +373,27 @@ abstract class AbstractCatalogEntry implements AppleFileSource
return false; return false;
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public String getUniqueName () public String getUniqueName ()
// ---------------------------------------------------------------------------------//
{ {
// this might not be unique if the file has been deleted // this might not be unique if the file has been deleted
return name; return name;
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public FormattedDisk getFormattedDisk () public FormattedDisk getFormattedDisk ()
// ---------------------------------------------------------------------------------//
{ {
return dosDisk; return dosDisk;
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public List<DiskAddress> getSectors () public List<DiskAddress> getSectors ()
// ---------------------------------------------------------------------------------//
{ {
List<DiskAddress> sectors = new ArrayList<> (); List<DiskAddress> sectors = new ArrayList<> ();
sectors.add (catalogSectorDA); sectors.add (catalogSectorDA);
@ -377,13 +402,17 @@ abstract class AbstractCatalogEntry implements AppleFileSource
return sectors; return sectors;
} }
// ---------------------------------------------------------------------------------//
void link (CatalogEntry catalogEntry) void link (CatalogEntry catalogEntry)
// ---------------------------------------------------------------------------------//
{ {
this.link = catalogEntry; this.link = catalogEntry;
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public String toString () public String toString ()
// ---------------------------------------------------------------------------------//
{ {
return catalogName; return catalogName;
} }

View File

@ -5,13 +5,17 @@ import com.bytezone.diskbrowser.disk.DiskAddress;
import com.bytezone.diskbrowser.dos.DosDisk.FileType; import com.bytezone.diskbrowser.dos.DosDisk.FileType;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
// -----------------------------------------------------------------------------------//
class CatalogEntry extends AbstractCatalogEntry class CatalogEntry extends AbstractCatalogEntry
// -----------------------------------------------------------------------------------//
{ {
private int textFileGaps; private int textFileGaps;
private int length; private int length;
private int address; private int address;
public CatalogEntry (DosDisk dosDisk, DiskAddress catalogSector, byte[] entryBuffer) // ---------------------------------------------------------------------------------//
CatalogEntry (DosDisk dosDisk, DiskAddress catalogSector, byte[] entryBuffer)
// ---------------------------------------------------------------------------------//
{ {
super (dosDisk, catalogSector, entryBuffer); // build lists of ts and data sectors super (dosDisk, catalogSector, entryBuffer); // build lists of ts and data sectors
@ -127,7 +131,9 @@ class CatalogEntry extends AbstractCatalogEntry
} }
} }
public String getDetails () // ---------------------------------------------------------------------------------//
String getDetails ()
// ---------------------------------------------------------------------------------//
{ {
int actualSize = dataSectors.size () + tsSectors.size () - textFileGaps; int actualSize = dataSectors.size () + tsSectors.size () - textFileGaps;
String addressText = address == 0 ? "" : String.format ("$%4X", address); String addressText = address == 0 ? "" : String.format ("$%4X", address);

View File

@ -5,13 +5,17 @@ import com.bytezone.diskbrowser.disk.AppleDiskAddress;
import com.bytezone.diskbrowser.disk.DiskAddress; import com.bytezone.diskbrowser.disk.DiskAddress;
import com.bytezone.diskbrowser.gui.DataSource; import com.bytezone.diskbrowser.gui.DataSource;
// -----------------------------------------------------------------------------------//
class DeletedCatalogEntry extends AbstractCatalogEntry class DeletedCatalogEntry extends AbstractCatalogEntry
// -----------------------------------------------------------------------------------//
{ {
boolean allSectorsAvailable = true; boolean allSectorsAvailable = true;
boolean debug = false; boolean debug = false;
public DeletedCatalogEntry (DosDisk dosDisk, DiskAddress catalogSector, // ---------------------------------------------------------------------------------//
byte[] entryBuffer, int dosVersion) DeletedCatalogEntry (DosDisk dosDisk, DiskAddress catalogSector, byte[] entryBuffer,
int dosVersion)
// ---------------------------------------------------------------------------------//
{ {
super (dosDisk, catalogSector, entryBuffer); super (dosDisk, catalogSector, entryBuffer);
@ -93,15 +97,19 @@ class DeletedCatalogEntry extends AbstractCatalogEntry
allSectorsAvailable = false; allSectorsAvailable = false;
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public String getUniqueName () public String getUniqueName ()
// ---------------------------------------------------------------------------------//
{ {
// name might not be unique if the file has been deleted // name might not be unique if the file has been deleted
return "!" + name; return "!" + name;
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public DataSource getDataSource () public DataSource getDataSource ()
// ---------------------------------------------------------------------------------//
{ {
if (!allSectorsAvailable && appleFile == null) if (!allSectorsAvailable && appleFile == null)
{ {
@ -112,7 +120,9 @@ class DeletedCatalogEntry extends AbstractCatalogEntry
return super.getDataSource (); return super.getDataSource ();
} }
public String getDetails () // ---------------------------------------------------------------------------------//
String getDetails ()
// ---------------------------------------------------------------------------------//
{ {
return String.format ("%-30s %s", name, return String.format ("%-30s %s", name,
allSectorsAvailable ? "Recoverable" : "Not recoverable"); allSectorsAvailable ? "Recoverable" : "Not recoverable");

View File

@ -1,154 +1,167 @@
package com.bytezone.diskbrowser.dos; package com.bytezone.diskbrowser.dos;
import com.bytezone.diskbrowser.disk.AbstractSector; import com.bytezone.diskbrowser.disk.AbstractSector;
import com.bytezone.diskbrowser.disk.Disk; import com.bytezone.diskbrowser.disk.Disk;
import com.bytezone.diskbrowser.disk.DiskAddress; import com.bytezone.diskbrowser.disk.DiskAddress;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
import com.bytezone.diskbrowser.utilities.Utility; import com.bytezone.diskbrowser.utilities.Utility;
class DosCatalogSector extends AbstractSector // -----------------------------------------------------------------------------------//
{ class DosCatalogSector extends AbstractSector
private static final String[] fileTypes = // -----------------------------------------------------------------------------------//
{ "Text file", "Integer Basic program", "Applesoft Basic program", "Binary file", {
"SS file", "Relocatable file", "AA file", "Lisa file" }; private static final String[] fileTypes =
private static int CATALOG_ENTRY_SIZE = 35; { "Text file", "Integer Basic program", "Applesoft Basic program", "Binary file",
"SS file", "Relocatable file", "AA file", "Lisa file" };
private final DosDisk dosDisk; private static int CATALOG_ENTRY_SIZE = 35;
public DosCatalogSector (DosDisk dosDisk, Disk disk, byte[] buffer, private final DosDisk dosDisk;
DiskAddress diskAddress)
{ // ---------------------------------------------------------------------------------//
super (disk, buffer, diskAddress); DosCatalogSector (DosDisk dosDisk, Disk disk, byte[] buffer, DiskAddress diskAddress)
this.dosDisk = dosDisk; // ---------------------------------------------------------------------------------//
} {
super (disk, buffer, diskAddress);
@Override this.dosDisk = dosDisk;
public String createText () }
{
StringBuilder text = // ---------------------------------------------------------------------------------//
getHeader ("DOS " + dosDisk.getVersionText () + " Catalog Sector"); @Override
addText (text, buffer, 0, 1, "Not used"); public String createText ()
addText (text, buffer, 1, 2, "Next catalog track/sector"); // ---------------------------------------------------------------------------------//
addText (text, buffer, 3, 4, "Not used"); {
addText (text, buffer, 7, 4, "Not used"); StringBuilder text =
getHeader ("DOS " + dosDisk.getVersionText () + " Catalog Sector");
boolean dos4 = dosDisk.getVersion () > 3; addText (text, buffer, 0, 1, "Not used");
addText (text, buffer, 1, 2, "Next catalog track/sector");
for (int i = 11; i <= 255; i += CATALOG_ENTRY_SIZE) addText (text, buffer, 3, 4, "Not used");
{ addText (text, buffer, 7, 4, "Not used");
text.append ("\n");
if (dos4) boolean dos4 = dosDisk.getVersion () > 3;
createDos4Text (text, i);
else for (int i = 11; i <= 255; i += CATALOG_ENTRY_SIZE)
createDos3Text (text, i); {
} text.append ("\n");
if (dos4)
text.deleteCharAt (text.length () - 1); createDos4Text (text, i);
return text.toString (); else
} createDos3Text (text, i);
}
private void createDos4Text (StringBuilder text, int i)
{ text.deleteCharAt (text.length () - 1);
int track = buffer[i] & 0x3F; return text.toString ();
int sector = buffer[i + 1] & 0x1F; }
int fileType = buffer[i + 2] & 0x7F;
// ---------------------------------------------------------------------------------//
boolean deleteFlag = (buffer[i] & 0x80) != 0; private void createDos4Text (StringBuilder text, int i)
boolean zeroTrackFlag = (buffer[i] & 0x40) != 0; // ---------------------------------------------------------------------------------//
boolean lockedFlag = (buffer[i + 2] & 0x80) != 0; {
int track = buffer[i] & 0x3F;
if (buffer[i] == 0 && !zeroTrackFlag) int sector = buffer[i + 1] & 0x1F;
{ int fileType = buffer[i + 2] & 0x7F;
addText (text, buffer, i + 0, 2, "");
addText (text, buffer, i + 2, 1, ""); boolean deleteFlag = (buffer[i] & 0x80) != 0;
addText (text, buffer, i + 3, 4, ""); boolean zeroTrackFlag = (buffer[i] & 0x40) != 0;
addText (text, buffer, i + 33, 2, ""); boolean lockedFlag = (buffer[i + 2] & 0x80) != 0;
}
else if (buffer[i] == 0 && !zeroTrackFlag)
{ {
addText (text, buffer, i, 1, addText (text, buffer, i + 0, 2, "");
String.format ("TS list track (%s, %s)", deleteFlag ? "deleted" : "not deleted", addText (text, buffer, i + 2, 1, "");
zeroTrackFlag ? "track zero" : "not track zero")); addText (text, buffer, i + 3, 4, "");
addText (text, buffer, i + 1, 1, "TS list sector"); addText (text, buffer, i + 33, 2, "");
addText (text, buffer, i + 2, 1, }
String.format ("File type (%s)", lockedFlag ? "locked" : "unlocked")); else
addText (text, buffer, i + 3, 4, getName (buffer, i + 3, 24)); {
for (int j = 0; j < 20; j += 4) addText (text, buffer, i, 1,
addText (text, buffer, i + 7 + j, 4, ""); String.format ("TS list track (%s, %s)", deleteFlag ? "deleted" : "not deleted",
addText (text, buffer, i + 27, 3, zeroTrackFlag ? "track zero" : "not track zero"));
"Date/time initialised: " + Utility.getDateTime (buffer, i + 27)); addText (text, buffer, i + 1, 1, "TS list sector");
addText (text, buffer, i + 30, 3, ""); addText (text, buffer, i + 2, 1,
addTextAndDecimal (text, buffer, i + 33, 2, "File size"); String.format ("File type (%s)", lockedFlag ? "locked" : "unlocked"));
} addText (text, buffer, i + 3, 4, getName (buffer, i + 3, 24));
} for (int j = 0; j < 20; j += 4)
addText (text, buffer, i + 7 + j, 4, "");
private void createDos3Text (StringBuilder text, int i) addText (text, buffer, i + 27, 3,
{ "Date/time initialised: " + Utility.getDateTime (buffer, i + 27));
if (buffer[i] == (byte) 0xFF) // file is deleted addText (text, buffer, i + 30, 3, "");
{ addTextAndDecimal (text, buffer, i + 33, 2, "File size");
addText (text, buffer, i, 2, "DEL: file @ " + HexFormatter.format2 (buffer[i + 32]) }
+ " " + HexFormatter.format2 (buffer[i + 1])); }
addText (text, buffer, i + 2, 1, "DEL: File type " + getType (buffer[i + 2]));
if (buffer[i + 3] == 0) // ---------------------------------------------------------------------------------//
addText (text, buffer, i + 3, 4, ""); private void createDos3Text (StringBuilder text, int i)
else // ---------------------------------------------------------------------------------//
addText (text, buffer, i + 3, 4, "DEL: " + getName (buffer, i + 3, 29)); {
addTextAndDecimal (text, buffer, i + 33, 2, "DEL: Sector count"); if (buffer[i] == (byte) 0xFF) // file is deleted
} {
else if (buffer[i] > 0) // file exists addText (text, buffer, i, 2, "DEL: file @ " + HexFormatter.format2 (buffer[i + 32])
{ + " " + HexFormatter.format2 (buffer[i + 1]));
addText (text, buffer, i, 2, "TS list track/sector"); addText (text, buffer, i + 2, 1, "DEL: File type " + getType (buffer[i + 2]));
addText (text, buffer, i + 2, 1, "File type " + getType (buffer[i + 2])); if (buffer[i + 3] == 0)
if (buffer[i + 3] == 0) addText (text, buffer, i + 3, 4, "");
addText (text, buffer, i + 3, 4, ""); else
else addText (text, buffer, i + 3, 4, "DEL: " + getName (buffer, i + 3, 29));
{ addTextAndDecimal (text, buffer, i + 33, 2, "DEL: Sector count");
addText (text, buffer, i + 3, 4, getName (buffer, i + 3, 30)); }
for (int j = 0; j < 24; j += 4) else if (buffer[i] > 0) // file exists
addText (text, buffer, i + j + 7, 4, ""); {
addText (text, buffer, i + 31, 2, ""); addText (text, buffer, i, 2, "TS list track/sector");
} addText (text, buffer, i + 2, 1, "File type " + getType (buffer[i + 2]));
addTextAndDecimal (text, buffer, i + 33, 2, "Sector count"); if (buffer[i + 3] == 0)
} addText (text, buffer, i + 3, 4, "");
else // no file else
{ {
addText (text, buffer, i + 0, 2, ""); addText (text, buffer, i + 3, 4, getName (buffer, i + 3, 30));
addText (text, buffer, i + 2, 1, ""); for (int j = 0; j < 24; j += 4)
addText (text, buffer, i + 3, 4, ""); addText (text, buffer, i + j + 7, 4, "");
addText (text, buffer, i + 33, 2, ""); addText (text, buffer, i + 31, 2, "");
} }
} addTextAndDecimal (text, buffer, i + 33, 2, "Sector count");
}
private String getName (byte[] buffer, int offset, int length) else // no file
{ {
StringBuilder text = new StringBuilder (); addText (text, buffer, i + 0, 2, "");
// int max = buffer[offset] == (byte) 0xFF ? 32 : 33; addText (text, buffer, i + 2, 1, "");
for (int i = offset; i < offset + length; i++) addText (text, buffer, i + 3, 4, "");
{ addText (text, buffer, i + 33, 2, "");
int c = buffer[i] & 0xFF; }
if (c == 136) }
{
if (text.length () > 0) // ---------------------------------------------------------------------------------//
text.deleteCharAt (text.length () - 1); private String getName (byte[] buffer, int offset, int length)
continue; // ---------------------------------------------------------------------------------//
} {
if (c > 127) StringBuilder text = new StringBuilder ();
c -= c < 160 ? 64 : 128; // int max = buffer[offset] == (byte) 0xFF ? 32 : 33;
if (c < 32) // non-printable for (int i = offset; i < offset + length; i++)
text.append ("^" + (char) (c + 64)); {
else int c = buffer[i] & 0xFF;
text.append ((char) c); // standard ascii if (c == 136)
} {
return text.toString (); if (text.length () > 0)
} text.deleteCharAt (text.length () - 1);
continue;
private String getType (byte value) }
{ if (c > 127)
int type = value & 0x7F; c -= c < 160 ? 64 : 128;
boolean locked = (value & 0x80) > 0; if (c < 32) // non-printable
int val = 7; text.append ("^" + (char) (c + 64));
for (int i = 64; i > type; val--, i /= 2) else
; text.append ((char) c); // standard ascii
return "(" + fileTypes[val] + (locked ? ", locked)" : ", unlocked)"); }
} return text.toString ();
}
// ---------------------------------------------------------------------------------//
private String getType (byte value)
// ---------------------------------------------------------------------------------//
{
int type = value & 0x7F;
boolean locked = (value & 0x80) > 0;
int val = 7;
for (int i = 64; i > type; val--, i /= 2)
;
return "(" + fileTypes[val] + (locked ? ", locked)" : ", unlocked)");
}
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,82 +1,92 @@
package com.bytezone.diskbrowser.dos; package com.bytezone.diskbrowser.dos;
import com.bytezone.diskbrowser.disk.AbstractSector; import com.bytezone.diskbrowser.disk.AbstractSector;
import com.bytezone.diskbrowser.disk.Disk; import com.bytezone.diskbrowser.disk.Disk;
import com.bytezone.diskbrowser.disk.DiskAddress; import com.bytezone.diskbrowser.disk.DiskAddress;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
class DosTSListSector extends AbstractSector // -----------------------------------------------------------------------------------//
{ class DosTSListSector extends AbstractSector
private final String name; // -----------------------------------------------------------------------------------//
{
public DosTSListSector (String name, Disk disk, byte[] buffer, DiskAddress diskAddress) private final String name;
{
super (disk, buffer, diskAddress); // ---------------------------------------------------------------------------------//
this.name = name; DosTSListSector (String name, Disk disk, byte[] buffer, DiskAddress diskAddress)
} // ---------------------------------------------------------------------------------//
{
public boolean isValid (DosDisk dosDisk) super (disk, buffer, diskAddress);
{ this.name = name;
// what is the count of blocks? does it match? this sector can't tell, there }
// might be more than one TS list
// ---------------------------------------------------------------------------------//
// validate the sector, throw an exception if invalid public boolean isValid (DosDisk dosDisk)
for (int i = 12; i < buffer.length; i += 2) // ---------------------------------------------------------------------------------//
{ {
DiskAddress da = getValidAddress (buffer, i); // what is the count of blocks? does it match? this sector can't tell, there
if (da == null) // might be more than one TS list
{
System.out.println ("Invalid sector address : null"); // validate the sector, throw an exception if invalid
break; // throw exception? for (int i = 12; i < buffer.length; i += 2)
} {
DiskAddress da = getValidAddress (buffer, i);
if (da.getBlock () > 0 && dosDisk.stillAvailable (da)) if (da == null)
{ {
System.out.println ("Invalid sector address : " + da); System.out.println ("Invalid sector address : null");
break; // throw exception? break; // throw exception?
} }
}
return true; if (da.getBlock () > 0 && dosDisk.stillAvailable (da))
} {
System.out.println ("Invalid sector address : " + da);
// this is in too many places break; // throw exception?
protected DiskAddress getValidAddress (byte[] buffer, int offset) }
{ }
if (disk.isValidAddress (buffer[offset], buffer[offset + 1])) return true;
return disk.getDiskAddress (buffer[offset], buffer[offset + 1]); }
return null;
} // this is in too many places
// ---------------------------------------------------------------------------------//
@Override protected DiskAddress getValidAddress (byte[] buffer, int offset)
public String createText () // ---------------------------------------------------------------------------------//
{ {
DiskAddress da = disk.getDiskAddress (buffer[1], buffer[2]); if (disk.isValidAddress (buffer[offset], buffer[offset + 1]))
String msg = da.matches (diskAddress) ? " (circular reference)" : ""; return disk.getDiskAddress (buffer[offset], buffer[offset + 1]);
return null;
StringBuilder text = getHeader ("TS List Sector : " + name); }
addText (text, buffer, 0, 1, "Not used");
addText (text, buffer, 1, 2, "Next TS list track/sector" + msg); // ---------------------------------------------------------------------------------//
addText (text, buffer, 3, 2, "Not used"); @Override
addTextAndDecimal (text, buffer, 5, 2, "Sector base number"); public String createText ()
addText (text, buffer, 7, 4, "Not used"); // ---------------------------------------------------------------------------------//
addText (text, buffer, 11, 1, "Not used"); {
DiskAddress da = disk.getDiskAddress (buffer[1], buffer[2]);
int sectorBase = HexFormatter.intValue (buffer[5], buffer[6]); String msg = da.matches (diskAddress) ? " (circular reference)" : "";
for (int i = 12; i <= 255; i += 2) StringBuilder text = getHeader ("TS List Sector : " + name);
{ addText (text, buffer, 0, 1, "Not used");
if (buffer[i] == 0 && buffer[i + 1] == 0) addText (text, buffer, 1, 2, "Next TS list track/sector" + msg);
msg = ""; addText (text, buffer, 3, 2, "Not used");
else addTextAndDecimal (text, buffer, 5, 2, "Sector base number");
{ addText (text, buffer, 7, 4, "Not used");
String msg2 = buffer[i] == 0x40 ? " - track zero" : ""; addText (text, buffer, 11, 1, "Not used");
msg = String.format ("Track/sector of file sector %04X (%<,d)%s",
((i - 12) / 2 + sectorBase), msg2); int sectorBase = HexFormatter.intValue (buffer[5], buffer[6]);
}
addText (text, buffer, i, 2, msg); for (int i = 12; i <= 255; i += 2)
} {
if (buffer[i] == 0 && buffer[i + 1] == 0)
text.deleteCharAt (text.length () - 1); msg = "";
return text.toString (); else
} {
String msg2 = buffer[i] == 0x40 ? " - track zero" : "";
msg = String.format ("Track/sector of file sector %04X (%<,d)%s",
((i - 12) / 2 + sectorBase), msg2);
}
addText (text, buffer, i, 2, msg);
}
text.deleteCharAt (text.length () - 1);
return text.toString ();
}
} }

View File

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