mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2024-12-01 09:50:32 +00:00
DOS 4.1 changes
This commit is contained in:
parent
d9b656cfa0
commit
1b5f3f95a9
@ -18,7 +18,7 @@ public class SimpleText2 extends AbstractFile
|
|||||||
|
|
||||||
// store a pointer to each new line
|
// store a pointer to each new line
|
||||||
int ptr = 0;
|
int ptr = 0;
|
||||||
while (buffer[ptr] != -1)
|
while (ptr < buffer.length && buffer[ptr] != -1)
|
||||||
{
|
{
|
||||||
int length = buffer[ptr] & 0xFF;
|
int length = buffer[ptr] & 0xFF;
|
||||||
lineStarts.add (ptr);
|
lineStarts.add (ptr);
|
||||||
@ -37,6 +37,8 @@ public class SimpleText2 extends AbstractFile
|
|||||||
|
|
||||||
for (Integer i : lineStarts)
|
for (Integer i : lineStarts)
|
||||||
text.append (String.format ("%05X %s%n", i, getLine (i)));
|
text.append (String.format ("%05X %s%n", i, getLine (i)));
|
||||||
|
if (text.charAt (text.length () - 1) == '\n')
|
||||||
|
text.deleteCharAt (text.length () - 1);
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,8 +48,8 @@ public class SimpleText2 extends AbstractFile
|
|||||||
StringBuilder text = new StringBuilder ();
|
StringBuilder text = new StringBuilder ();
|
||||||
|
|
||||||
for (Integer i : lineStarts)
|
for (Integer i : lineStarts)
|
||||||
text.append (HexFormatter.formatNoHeader (buffer, i, (buffer[i] & 0xFF) + 1)
|
text.append (
|
||||||
+ "\n");
|
HexFormatter.formatNoHeader (buffer, i, (buffer[i] & 0xFF) + 1) + "\n");
|
||||||
text.append (HexFormatter.formatNoHeader (buffer, buffer.length - 2, 2) + "\n");
|
text.append (HexFormatter.formatNoHeader (buffer, buffer.length - 2, 2) + "\n");
|
||||||
|
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
|
@ -396,7 +396,8 @@ public class AppleDisk implements Disk
|
|||||||
int ptr = 0;
|
int ptr = 0;
|
||||||
for (DiskAddress da : daList)
|
for (DiskAddress da : daList)
|
||||||
{
|
{
|
||||||
if (da != null && da.getBlock () > 0) // sparse text/PNT/PIC files may have gaps
|
// sparse text/PNT/PIC files may have gaps
|
||||||
|
if (da != null && (da.getBlock () > 0 || ((AppleDiskAddress) da).zeroFlag ()))
|
||||||
readBuffer (da, buffer, ptr);
|
readBuffer (da, buffer, ptr);
|
||||||
ptr += sectorSize;
|
ptr += sectorSize;
|
||||||
}
|
}
|
||||||
@ -458,6 +459,9 @@ public class AppleDisk implements Disk
|
|||||||
@Override
|
@Override
|
||||||
public DiskAddress getDiskAddress (int track, int sector)
|
public DiskAddress getDiskAddress (int track, int sector)
|
||||||
{
|
{
|
||||||
|
// track &= 0x3F;
|
||||||
|
// sector &= 0x1F;
|
||||||
|
|
||||||
if (!isValidAddress (track, sector))
|
if (!isValidAddress (track, sector))
|
||||||
{
|
{
|
||||||
System.out.println ("Invalid block : " + track + "/" + sector);
|
System.out.println ("Invalid block : " + track + "/" + sector);
|
||||||
@ -502,10 +506,14 @@ public class AppleDisk implements Disk
|
|||||||
@Override
|
@Override
|
||||||
public boolean isValidAddress (int track, int sector)
|
public boolean isValidAddress (int track, int sector)
|
||||||
{
|
{
|
||||||
|
track &= 0x3F;
|
||||||
|
sector &= 0x1F;
|
||||||
|
|
||||||
if (track < 0 || track >= this.tracks)
|
if (track < 0 || track >= this.tracks)
|
||||||
return false;
|
return false;
|
||||||
if (sector < 0 || sector >= this.sectors)
|
if (sector < 0 || sector >= this.sectors)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ public class AppleDiskAddress implements DiskAddress
|
|||||||
private final int track;
|
private final int track;
|
||||||
private final int sector;
|
private final int sector;
|
||||||
public final Disk owner;
|
public final Disk owner;
|
||||||
|
private boolean zeroFlag;
|
||||||
|
|
||||||
public AppleDiskAddress (Disk owner, int block)
|
public AppleDiskAddress (Disk owner, int block)
|
||||||
{
|
{
|
||||||
@ -19,15 +20,15 @@ public class AppleDiskAddress implements DiskAddress
|
|||||||
public AppleDiskAddress (Disk owner, int track, int sector)
|
public AppleDiskAddress (Disk owner, int track, int sector)
|
||||||
{
|
{
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.track = track;
|
zeroFlag = (track & 0x40) != 0;
|
||||||
this.sector = sector;
|
this.track = track & 0x3F;
|
||||||
this.block = track * owner.getSectorsPerTrack () + sector;
|
this.sector = sector & 0x1F;
|
||||||
|
this.block = this.track * owner.getSectorsPerTrack () + this.sector;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public boolean zeroFlag ()
|
||||||
public String toString ()
|
|
||||||
{
|
{
|
||||||
return String.format ("[Block=%3d, Track=%2d, Sector=%2d]", block, track, sector);
|
return zeroFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -65,4 +66,11 @@ public class AppleDiskAddress implements DiskAddress
|
|||||||
{
|
{
|
||||||
return owner;
|
return owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
return String.format ("[Block=%3d, Track=%2d, Sector=%2d, Zero=%s]", block, track,
|
||||||
|
sector, zeroFlag);
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package com.bytezone.diskbrowser.dos;
|
package com.bytezone.diskbrowser.dos;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -10,6 +11,7 @@ import com.bytezone.diskbrowser.disk.FormattedDisk;
|
|||||||
import com.bytezone.diskbrowser.dos.DosDisk.FileType;
|
import com.bytezone.diskbrowser.dos.DosDisk.FileType;
|
||||||
import com.bytezone.diskbrowser.gui.DataSource;
|
import com.bytezone.diskbrowser.gui.DataSource;
|
||||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
|
import com.bytezone.diskbrowser.utilities.Utility;
|
||||||
|
|
||||||
abstract class AbstractCatalogEntry implements AppleFileSource
|
abstract class AbstractCatalogEntry implements AppleFileSource
|
||||||
{
|
{
|
||||||
@ -22,6 +24,7 @@ abstract class AbstractCatalogEntry implements AppleFileSource
|
|||||||
protected int reportedSize;
|
protected int reportedSize;
|
||||||
protected boolean locked;
|
protected boolean locked;
|
||||||
protected DataSource appleFile;
|
protected DataSource appleFile;
|
||||||
|
protected LocalDateTime lastModified;
|
||||||
|
|
||||||
protected DiskAddress catalogSectorDA;
|
protected DiskAddress catalogSectorDA;
|
||||||
protected final List<DiskAddress> dataSectors = new ArrayList<DiskAddress> ();
|
protected final List<DiskAddress> dataSectors = new ArrayList<DiskAddress> ();
|
||||||
@ -34,33 +37,34 @@ abstract class AbstractCatalogEntry implements AppleFileSource
|
|||||||
{
|
{
|
||||||
this.dosDisk = dosDisk;
|
this.dosDisk = dosDisk;
|
||||||
this.disk = dosDisk.getDisk ();
|
this.disk = dosDisk.getDisk ();
|
||||||
this.disk = dosDisk.getDisk ();
|
|
||||||
this.catalogSectorDA = catalogSector;
|
this.catalogSectorDA = catalogSector;
|
||||||
|
|
||||||
reportedSize = HexFormatter.unsignedShort (entryBuffer, 33);
|
reportedSize = HexFormatter.unsignedShort (entryBuffer, 33);
|
||||||
int type = entryBuffer[2] & 0xFF;
|
|
||||||
locked = (type & 0x80) > 0;
|
|
||||||
|
|
||||||
if ((type & 0x7F) == 0)
|
int type = entryBuffer[2] & 0x7F;
|
||||||
|
locked = (entryBuffer[2] & 0x80) != 0;
|
||||||
|
|
||||||
|
if (type == 0)
|
||||||
fileType = FileType.Text;
|
fileType = FileType.Text;
|
||||||
else if ((type & 0x01) > 0)
|
else if ((type == 0x01))
|
||||||
fileType = FileType.IntegerBasic;
|
fileType = FileType.IntegerBasic;
|
||||||
else if ((type & 0x02) > 0)
|
else if ((type == 0x02))
|
||||||
fileType = FileType.ApplesoftBasic;
|
fileType = FileType.ApplesoftBasic;
|
||||||
else if ((type & 0x04) > 0)
|
else if ((type == 0x04))
|
||||||
fileType = FileType.Binary;
|
fileType = FileType.Binary;
|
||||||
else if ((type & 0x08) > 0)
|
else if ((type == 0x08))
|
||||||
fileType = FileType.SS;
|
fileType = FileType.SS;
|
||||||
else if ((type & 0x10) > 0)
|
else if ((type == 0x10))
|
||||||
fileType = FileType.Relocatable;
|
fileType = FileType.Relocatable;
|
||||||
else if ((type & 0x20) > 0)
|
else if ((type == 0x20))
|
||||||
fileType = FileType.AA;
|
fileType = FileType.AA;
|
||||||
else if ((type & 0x40) > 0)
|
else if ((type == 0x40))
|
||||||
fileType = FileType.BB;
|
fileType = FileType.BB;
|
||||||
else
|
else
|
||||||
System.out.println ("Unknown file type : " + (type & 0x7F));
|
System.out.println ("Unknown file type : " + type);
|
||||||
|
|
||||||
name = getName ("", entryBuffer);
|
name = getName ("", entryBuffer);
|
||||||
|
lastModified = Utility.getDateTime (entryBuffer, 0x1B);
|
||||||
// CATALOG command only formats the LO byte - see Beneath Apple DOS pp4-6
|
// CATALOG command only formats the LO byte - see Beneath Apple DOS pp4-6
|
||||||
String base = String.format ("%s%s %03d ", (locked) ? "*" : " ", getFileType (),
|
String base = String.format ("%s%s %03d ", (locked) ? "*" : " ", getFileType (),
|
||||||
(entryBuffer[33] & 0xFF));
|
(entryBuffer[33] & 0xFF));
|
||||||
@ -71,6 +75,8 @@ abstract class AbstractCatalogEntry implements AppleFileSource
|
|||||||
{
|
{
|
||||||
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;
|
||||||
|
if (dosDisk.getVersion () >= 0x41)
|
||||||
|
max = 27;
|
||||||
for (int i = 3; i < max; i++)
|
for (int i = 3; i < max; i++)
|
||||||
{
|
{
|
||||||
int c = buffer[i] & 0xFF;
|
int c = buffer[i] & 0xFF;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.bytezone.diskbrowser.dos;
|
package com.bytezone.diskbrowser.dos;
|
||||||
|
|
||||||
|
import com.bytezone.diskbrowser.disk.AppleDiskAddress;
|
||||||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
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;
|
||||||
@ -20,7 +21,7 @@ class CatalogEntry extends AbstractCatalogEntry
|
|||||||
DiskAddress da = disk.getDiskAddress (entryBuffer[0], entryBuffer[1]);
|
DiskAddress da = disk.getDiskAddress (entryBuffer[0], entryBuffer[1]);
|
||||||
|
|
||||||
// Loop through all TS-list sectors
|
// Loop through all TS-list sectors
|
||||||
loop: while (da.getBlock () > 0)
|
loop: while (da.getBlock () > 0 || ((AppleDiskAddress) da).zeroFlag ())
|
||||||
{
|
{
|
||||||
if (dosDisk.stillAvailable (da))
|
if (dosDisk.stillAvailable (da))
|
||||||
dosDisk.sectorTypes[da.getBlock ()] = dosDisk.tsListSector;
|
dosDisk.sectorTypes[da.getBlock ()] = dosDisk.tsListSector;
|
||||||
@ -55,7 +56,7 @@ class CatalogEntry extends AbstractCatalogEntry
|
|||||||
sectorBuffer[i], sectorBuffer[i + 1], name.trim ());
|
sectorBuffer[i], sectorBuffer[i + 1], name.trim ());
|
||||||
break loop;
|
break loop;
|
||||||
}
|
}
|
||||||
if (da.getBlock () == 0)
|
if (da.getBlock () == 0 && !((AppleDiskAddress) da).zeroFlag ())
|
||||||
{
|
{
|
||||||
if (fileType != FileType.Text)
|
if (fileType != FileType.Text)
|
||||||
break;
|
break;
|
||||||
@ -132,6 +133,10 @@ class CatalogEntry extends AbstractCatalogEntry
|
|||||||
String lengthText = length == 0 ? "" : String.format ("$%4X %,6d", length, length);
|
String lengthText = length == 0 ? "" : String.format ("$%4X %,6d", length, length);
|
||||||
String message = "";
|
String message = "";
|
||||||
String lockedFlag = (locked) ? "*" : " ";
|
String lockedFlag = (locked) ? "*" : " ";
|
||||||
|
if (dosDisk.dosVTOCSector.dosVersion >= 0x41)
|
||||||
|
{
|
||||||
|
message = lastModified.toString ().replace ('T', ' ');
|
||||||
|
}
|
||||||
if (reportedSize != actualSize)
|
if (reportedSize != actualSize)
|
||||||
message += "Bad size (" + reportedSize + ") ";
|
message += "Bad size (" + reportedSize + ") ";
|
||||||
if (dataSectors.size () == 0)
|
if (dataSectors.size () == 0)
|
||||||
|
@ -4,6 +4,7 @@ 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;
|
||||||
|
|
||||||
class DosCatalogSector extends AbstractSector
|
class DosCatalogSector extends AbstractSector
|
||||||
{
|
{
|
||||||
@ -12,53 +13,104 @@ class DosCatalogSector extends AbstractSector
|
|||||||
"SS file", "Relocatable file", "AA file", "BB file" };
|
"SS file", "Relocatable file", "AA file", "BB file" };
|
||||||
private static int CATALOG_ENTRY_SIZE = 35;
|
private static int CATALOG_ENTRY_SIZE = 35;
|
||||||
|
|
||||||
public DosCatalogSector (Disk disk, byte[] buffer, DiskAddress diskAddress)
|
private final DosDisk dosDisk;
|
||||||
|
|
||||||
|
public DosCatalogSector (DosDisk dosDisk, Disk disk, byte[] buffer,
|
||||||
|
DiskAddress diskAddress)
|
||||||
{
|
{
|
||||||
super (disk, buffer, diskAddress);
|
super (disk, buffer, diskAddress);
|
||||||
|
this.dosDisk = dosDisk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String createText ()
|
public String createText ()
|
||||||
{
|
{
|
||||||
StringBuilder text = getHeader ("Catalog Sector");
|
StringBuilder text =
|
||||||
|
getHeader ("DOS " + dosDisk.getVersionText () + " Catalog Sector");
|
||||||
addText (text, buffer, 0, 1, "Not used");
|
addText (text, buffer, 0, 1, "Not used");
|
||||||
addText (text, buffer, 1, 2, "Next catalog track/sector");
|
addText (text, buffer, 1, 2, "Next catalog track/sector");
|
||||||
addText (text, buffer, 3, 4, "Not used");
|
addText (text, buffer, 3, 4, "Not used");
|
||||||
addText (text, buffer, 7, 4, "Not used");
|
addText (text, buffer, 7, 4, "Not used");
|
||||||
|
|
||||||
|
boolean dos4 = dosDisk.getVersion () > 3;
|
||||||
|
|
||||||
for (int i = 11; i <= 255; i += CATALOG_ENTRY_SIZE)
|
for (int i = 11; i <= 255; i += CATALOG_ENTRY_SIZE)
|
||||||
{
|
{
|
||||||
text.append ("\n");
|
text.append ("\n");
|
||||||
if (true)
|
if (dos4)
|
||||||
|
createDos4Text (text, i);
|
||||||
|
else
|
||||||
|
createDos3Text (text, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
text.deleteCharAt (text.length () - 1);
|
||||||
|
return text.toString ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createDos4Text (StringBuilder text, int i)
|
||||||
{
|
{
|
||||||
if (buffer[i] == (byte) 0xFF)
|
int track = buffer[i] & 0x3F;
|
||||||
|
int sector = buffer[i + 1] & 0x1F;
|
||||||
|
int fileType = buffer[i + 2] & 0x7F;
|
||||||
|
|
||||||
|
boolean deleteFlag = (buffer[i] & 0x80) != 0;
|
||||||
|
boolean zeroTrackFlag = (buffer[i] & 0x40) != 0;
|
||||||
|
boolean lockedFlag = (buffer[i + 2] & 0x80) != 0;
|
||||||
|
|
||||||
|
if (buffer[i] == 0 && !zeroTrackFlag)
|
||||||
{
|
{
|
||||||
addText (text, buffer, i + 0, 2,
|
addText (text, buffer, i + 0, 2, "");
|
||||||
"DEL: file @ " + HexFormatter.format2 (buffer[i + 32]) + " "
|
addText (text, buffer, i + 2, 1, "");
|
||||||
+ HexFormatter.format2 (buffer[i + 1]));
|
addText (text, buffer, i + 3, 4, "");
|
||||||
|
addText (text, buffer, i + 33, 2, "");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addText (text, buffer, i, 1,
|
||||||
|
String.format ("TS list track (%s, %s)", deleteFlag ? "deleted" : "not deleted",
|
||||||
|
zeroTrackFlag ? "track zero" : "not track zero"));
|
||||||
|
addText (text, buffer, i + 1, 1, "TS list sector");
|
||||||
|
addText (text, buffer, i + 2, 1,
|
||||||
|
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, "");
|
||||||
|
addText (text, buffer, i + 27, 3,
|
||||||
|
"Date/time initialised: " + Utility.getDateTime (buffer, i + 27));
|
||||||
|
addText (text, buffer, i + 30, 3, "");
|
||||||
|
addTextAndDecimal (text, buffer, i + 33, 2, "File size");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createDos3Text (StringBuilder text, int i)
|
||||||
|
{
|
||||||
|
if (buffer[i] == (byte) 0xFF) // file is deleted
|
||||||
|
{
|
||||||
|
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]));
|
addText (text, buffer, i + 2, 1, "DEL: 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));
|
addText (text, buffer, i + 3, 4, "DEL: " + getName (buffer, i + 3, 29));
|
||||||
addTextAndDecimal (text, buffer, i + 33, 2, "DEL: Sector count");
|
addTextAndDecimal (text, buffer, i + 33, 2, "DEL: Sector count");
|
||||||
}
|
}
|
||||||
else if (buffer[i] > 0)
|
else if (buffer[i] > 0) // file exists
|
||||||
{
|
{
|
||||||
addText (text, buffer, i + 0, 2, "TS list track/sector");
|
addText (text, buffer, i, 2, "TS list track/sector");
|
||||||
addText (text, buffer, i + 2, 1, "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, getName (buffer, i));
|
addText (text, buffer, i + 3, 4, getName (buffer, i + 3, 30));
|
||||||
for (int j = 0; j < 24; j += 4)
|
for (int j = 0; j < 24; j += 4)
|
||||||
addText (text, buffer, i + j + 7, 4, "");
|
addText (text, buffer, i + j + 7, 4, "");
|
||||||
addText (text, buffer, i + 31, 2, "");
|
addText (text, buffer, i + 31, 2, "");
|
||||||
}
|
}
|
||||||
addTextAndDecimal (text, buffer, i + 33, 2, "Sector count");
|
addTextAndDecimal (text, buffer, i + 33, 2, "Sector count");
|
||||||
}
|
}
|
||||||
else
|
else // no file
|
||||||
{
|
{
|
||||||
addText (text, buffer, i + 0, 2, "");
|
addText (text, buffer, i + 0, 2, "");
|
||||||
addText (text, buffer, i + 2, 1, "");
|
addText (text, buffer, i + 2, 1, "");
|
||||||
@ -66,19 +118,14 @@ class DosCatalogSector extends AbstractSector
|
|||||||
addText (text, buffer, i + 33, 2, "");
|
addText (text, buffer, i + 33, 2, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
text.deleteCharAt (text.length () - 1);
|
private String getName (byte[] buffer, int offset, int length)
|
||||||
return text.toString ();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getName (byte[] buffer, int offset)
|
|
||||||
{
|
{
|
||||||
StringBuilder text = new StringBuilder ();
|
StringBuilder text = new StringBuilder ();
|
||||||
int max = buffer[offset] == (byte) 0xFF ? 32 : 33;
|
// int max = buffer[offset] == (byte) 0xFF ? 32 : 33;
|
||||||
for (int i = 3; i < max; i++)
|
for (int i = offset; i < offset + length; i++)
|
||||||
{
|
{
|
||||||
int c = buffer[i + offset] & 0xFF;
|
int c = buffer[i] & 0xFF;
|
||||||
if (c == 136)
|
if (c == 136)
|
||||||
{
|
{
|
||||||
if (text.length () > 0)
|
if (text.length () > 0)
|
||||||
|
@ -18,7 +18,7 @@ public class DosDisk extends AbstractFormattedDisk
|
|||||||
private static final int CATALOG_TRACK = 17;
|
private static final int CATALOG_TRACK = 17;
|
||||||
private static final int VTOC_SECTOR = 0;
|
private static final int VTOC_SECTOR = 0;
|
||||||
|
|
||||||
private final DosVTOCSector dosVTOCSector;
|
final DosVTOCSector dosVTOCSector;
|
||||||
private final Color green = new Color (0, 200, 0);
|
private final Color green = new Color (0, 200, 0);
|
||||||
private final DefaultMutableTreeNode volumeNode;
|
private final DefaultMutableTreeNode volumeNode;
|
||||||
|
|
||||||
@ -152,6 +152,12 @@ public class DosDisk extends AbstractFormattedDisk
|
|||||||
|
|
||||||
int track = sectorBuffer[1] & 0xFF;
|
int track = sectorBuffer[1] & 0xFF;
|
||||||
int sector = sectorBuffer[2] & 0xFF;
|
int sector = sectorBuffer[2] & 0xFF;
|
||||||
|
if (dosVTOCSector.dosVersion >= 0x41)
|
||||||
|
{
|
||||||
|
track = track & 0x3F;
|
||||||
|
sector = sector & 0x1F;
|
||||||
|
}
|
||||||
|
|
||||||
if (!disk.isValidAddress (track, sector))
|
if (!disk.isValidAddress (track, sector))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -254,6 +260,28 @@ public class DosDisk extends AbstractFormattedDisk
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getVersionText ()
|
||||||
|
{
|
||||||
|
switch (getVersion ())
|
||||||
|
{
|
||||||
|
case 0x01:
|
||||||
|
return "3.1";
|
||||||
|
case 0x02:
|
||||||
|
return "3.2";
|
||||||
|
case 0x03:
|
||||||
|
return "3.3";
|
||||||
|
case 0x41:
|
||||||
|
return "4.1";
|
||||||
|
default:
|
||||||
|
return "??";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVersion ()
|
||||||
|
{
|
||||||
|
return dosVTOCSector.dosVersion;
|
||||||
|
}
|
||||||
|
|
||||||
private static int checkFormat (AppleDisk disk)
|
private static int checkFormat (AppleDisk disk)
|
||||||
{
|
{
|
||||||
byte[] buffer = disk.readSector (0x11, 0x00);
|
byte[] buffer = disk.readSector (0x11, 0x00);
|
||||||
@ -272,10 +300,10 @@ public class DosDisk extends AbstractFormattedDisk
|
|||||||
// // return 0;
|
// // return 0;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
int version = buffer[3];
|
int version = buffer[3] & 0xFF;
|
||||||
if (version < -1 || version > 4)
|
if (version > 0x42 && version != 0xFF)
|
||||||
{
|
{
|
||||||
System.out.println ("Bad version : " + buffer[3]);
|
System.out.printf ("Bad version : %02X%n", version);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,7 +375,7 @@ public class DosDisk extends AbstractFormattedDisk
|
|||||||
if (type == tsListSector)
|
if (type == tsListSector)
|
||||||
return new DosTSListSector (getSectorFilename (da), disk, buffer, da);
|
return new DosTSListSector (getSectorFilename (da), disk, buffer, da);
|
||||||
if (type == catalogSector)
|
if (type == catalogSector)
|
||||||
return new DosCatalogSector (disk, buffer, da);
|
return new DosCatalogSector (this, disk, buffer, da);
|
||||||
if (type == dataSector)
|
if (type == dataSector)
|
||||||
return new DefaultSector (
|
return new DefaultSector (
|
||||||
"Data Sector at " + address + " : " + getSectorFilename (da), disk, buffer, da);
|
"Data Sector at " + address + " : " + getSectorFilename (da), disk, buffer, da);
|
||||||
@ -369,7 +397,7 @@ public class DosDisk extends AbstractFormattedDisk
|
|||||||
{
|
{
|
||||||
String newLine = String.format ("%n");
|
String newLine = String.format ("%n");
|
||||||
String line = "- --- --- ------------------------------ ----- -------------"
|
String line = "- --- --- ------------------------------ ----- -------------"
|
||||||
+ " -- ---- ----------------" + newLine;
|
+ " -- ---- -------------------" + newLine;
|
||||||
StringBuilder text = new StringBuilder ();
|
StringBuilder text = new StringBuilder ();
|
||||||
text.append (String.format ("Disk : %s%n%n", getAbsolutePath ()));
|
text.append (String.format ("Disk : %s%n%n", getAbsolutePath ()));
|
||||||
text.append ("L Typ Len Name Addr"
|
text.append ("L Typ Len Name Addr"
|
||||||
|
@ -4,12 +4,13 @@ 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;
|
||||||
|
|
||||||
class DosVTOCSector extends AbstractSector
|
class DosVTOCSector extends AbstractSector
|
||||||
{
|
{
|
||||||
DosDisk parentDisk;
|
DosDisk parentDisk;
|
||||||
int volume;
|
int volume;
|
||||||
int DOSVersion;
|
int dosVersion; // 1, 2, 3 or 0x41...
|
||||||
int maxTSPairs;
|
int maxTSPairs;
|
||||||
int lastAllocTrack;
|
int lastAllocTrack;
|
||||||
int direction;
|
int direction;
|
||||||
@ -25,7 +26,7 @@ class DosVTOCSector extends AbstractSector
|
|||||||
super (disk, buffer, diskAddress);
|
super (disk, buffer, diskAddress);
|
||||||
|
|
||||||
this.parentDisk = parentDisk;
|
this.parentDisk = parentDisk;
|
||||||
DOSVersion = buffer[3];
|
dosVersion = buffer[3];
|
||||||
volume = buffer[6] & 0xFF;
|
volume = buffer[6] & 0xFF;
|
||||||
maxTSPairs = buffer[39];
|
maxTSPairs = buffer[39];
|
||||||
lastAllocTrack = buffer[48];
|
lastAllocTrack = buffer[48];
|
||||||
@ -38,6 +39,63 @@ class DosVTOCSector extends AbstractSector
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String createText ()
|
public String createText ()
|
||||||
|
{
|
||||||
|
return dosVersion <= 3 ? createDosText () : createOtherText ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createOtherText ()
|
||||||
|
{
|
||||||
|
StringBuilder text = getHeader ("DOS 4.1 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");
|
||||||
|
addText (text, buffer, 7, 1, "Volume type " + (char) (buffer[7] & 0x7F));
|
||||||
|
|
||||||
|
int ptr = 8;
|
||||||
|
addText (text, buffer, ptr, 4, "Volume name: " + getName (buffer, ptr));
|
||||||
|
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, "Not used");
|
||||||
|
|
||||||
|
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 ().isSectorEmpty (0);
|
||||||
|
for (int i = 0x38; i <= 0xC3; i += 4)
|
||||||
|
{
|
||||||
|
String extra = "";
|
||||||
|
if (i == 0x38 && bootSectorEmpty)
|
||||||
|
extra = "(unusable)";
|
||||||
|
else if (i == 124)
|
||||||
|
extra = "(VTOC and Catalog)";
|
||||||
|
addText (text, buffer, i, 4, String.format ("Track %02X %s %s", (i - 56) / 4,
|
||||||
|
getBitmap (buffer[i], buffer[i + 1]), extra));
|
||||||
|
}
|
||||||
|
|
||||||
|
text.deleteCharAt (text.length () - 1);
|
||||||
|
|
||||||
|
return text.toString ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createDosText ()
|
||||||
{
|
{
|
||||||
StringBuilder text = getHeader ("VTOC Sector");
|
StringBuilder text = getHeader ("VTOC Sector");
|
||||||
addText (text, buffer, 0, 1, "Not used");
|
addText (text, buffer, 0, 1, "Not used");
|
||||||
@ -138,11 +196,35 @@ class DosVTOCSector extends AbstractSector
|
|||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// duplicate of DosCatalogSector.getName()
|
||||||
|
private String getName (byte[] buffer, int offset)
|
||||||
|
{
|
||||||
|
StringBuilder text = new StringBuilder ();
|
||||||
|
int max = 24;
|
||||||
|
for (int i = 0; i < max; i++)
|
||||||
|
{
|
||||||
|
int c = buffer[i + offset] & 0xFF;
|
||||||
|
if (c == 136)
|
||||||
|
{
|
||||||
|
if (text.length () > 0)
|
||||||
|
text.deleteCharAt (text.length () - 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c > 127)
|
||||||
|
c -= c < 160 ? 64 : 128;
|
||||||
|
if (c < 32) // non-printable
|
||||||
|
text.append ("^" + (char) (c + 64));
|
||||||
|
else
|
||||||
|
text.append ((char) c); // standard ascii
|
||||||
|
}
|
||||||
|
return text.toString ();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString ()
|
public String toString ()
|
||||||
{
|
{
|
||||||
StringBuffer text = new StringBuffer ();
|
StringBuffer text = new StringBuffer ();
|
||||||
text.append ("DOS version : 3." + DOSVersion);
|
text.append ("DOS version : 3." + dosVersion);
|
||||||
text.append ("\nVolume : " + volume);
|
text.append ("\nVolume : " + volume);
|
||||||
text.append ("\nMax TS pairs : " + maxTSPairs);
|
text.append ("\nMax TS pairs : " + maxTSPairs);
|
||||||
text.append ("\nLast allocated T : " + lastAllocTrack);
|
text.append ("\nLast allocated T : " + lastAllocTrack);
|
||||||
|
@ -7,6 +7,7 @@ import java.util.Collections;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.bytezone.diskbrowser.disk.AppleDiskAddress;
|
||||||
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.disk.FormattedDisk;
|
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
||||||
@ -152,7 +153,7 @@ class DiskLayoutSelection implements Iterable<DiskAddress>
|
|||||||
highlights.clear ();
|
highlights.clear ();
|
||||||
if (list != null)
|
if (list != null)
|
||||||
for (DiskAddress da : list)
|
for (DiskAddress da : list)
|
||||||
if (da != null && da.getBlock () > 0)
|
if (da != null && (da.getBlock () > 0 || ((AppleDiskAddress) da).zeroFlag ()))
|
||||||
highlights.add (da);
|
highlights.add (da);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@ package com.bytezone.diskbrowser.utilities;
|
|||||||
|
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.AffineTransform;
|
import java.awt.geom.AffineTransform;
|
||||||
|
import java.time.DateTimeException;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -58,6 +60,24 @@ public class Utility
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static LocalDateTime getDateTime (byte[] buffer, int ptr)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int[] val = new int[6];
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
val[i] = Integer.parseInt (String.format ("%02X", buffer[ptr + i] & 0xFF));
|
||||||
|
|
||||||
|
LocalDateTime date =
|
||||||
|
LocalDateTime.of (val[3] + 2000, val[5], val[4], val[2], val[1], val[0]);
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
catch (DateTimeException e)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean matches (byte[] buffer, int offset, byte[] key)
|
public static boolean matches (byte[] buffer, int offset, byte[] key)
|
||||||
{
|
{
|
||||||
int ptr = 0;
|
int ptr = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user