diff --git a/src/com/bytezone/diskbrowser/applefile/PascalCode.java b/src/com/bytezone/diskbrowser/applefile/PascalCode.java index f65e01a..86284ba 100755 --- a/src/com/bytezone/diskbrowser/applefile/PascalCode.java +++ b/src/com/bytezone/diskbrowser/applefile/PascalCode.java @@ -4,14 +4,17 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import com.bytezone.diskbrowser.applefile.Relocator.MultiDiskAddress; import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.Utility; public class PascalCode extends AbstractFile implements PascalConstants, Iterable { - List segments = new ArrayList (16); - String comment; + private final List segments = new ArrayList (16); + private final String comment; + private final int blockOffset; + private final Relocator relocator; public static void print () { @@ -20,9 +23,13 @@ public class PascalCode extends AbstractFile PascalConstants.mnemonics[i], PascalConstants.descriptions[i]); } - public PascalCode (String name, byte[] buffer) + public PascalCode (String name, byte[] buffer, int blockOffset, Relocator relocator) { super (name, buffer); + + this.blockOffset = blockOffset; + this.relocator = relocator; + int nonameCounter = 0; if (false) { @@ -54,13 +61,51 @@ public class PascalCode extends AbstractFile text.append ("Segment Dictionary\n==================\n\n"); - text.append ("Slot Addr Blks Len Len Name Kind" + text.append ("Slot Addr Addr Blks Len D:Blk Name Kind" + " Txt Seg Mch Ver I/S I/S\n"); - text.append ("---- ---- ---- ---- ----- -------- ---------------" + text.append ("---- ---- ---- ---- ---- ----- -------- ---------------" + " --- --- --- --- --- ---\n"); + MultiDiskAddress lastMultiDiskAddress = null; + int minBlocks = 0; + int maxBlocks = 0; + for (PascalSegment segment : segments) - text.append (segment.toText () + "\n"); + { + int sizeInBlocks = (segment.size - 1) / 512 + 1; + String multiDiskAddressText = ""; + if (segment.segmentNoHeader == 1) // main segment + { + multiDiskAddressText = String.format ("1:%03X", (segment.blockNo + blockOffset)); + } + else if (relocator != null) + { + if (segment.blockNo >= minBlocks && segment.blockNo < maxBlocks) + { + int offset = segment.blockNo - minBlocks; + multiDiskAddressText = String.format ("%d:%03X", + lastMultiDiskAddress.diskNumber, lastMultiDiskAddress.blockNumber + offset); + } + else + { + int targetBlock = segment.blockNo + blockOffset; + List addresses = relocator.getMultiDiskAddress (targetBlock); + if (addresses.isEmpty ()) + multiDiskAddressText = "."; + else + { + lastMultiDiskAddress = addresses.get (0); + multiDiskAddressText = addresses.get (0).toString (); + if (lastMultiDiskAddress.totalBlocks > sizeInBlocks) + { + minBlocks = segment.blockNo; + maxBlocks = minBlocks + lastMultiDiskAddress.totalBlocks; + } + } + } + } + text.append (segment.toText (blockOffset, multiDiskAddressText) + "\n"); + } text.append ("\nComment : " + comment + "\n\n"); return text.toString (); diff --git a/src/com/bytezone/diskbrowser/applefile/PascalSegment.java b/src/com/bytezone/diskbrowser/applefile/PascalSegment.java index b6ee82d..d48ff3c 100755 --- a/src/com/bytezone/diskbrowser/applefile/PascalSegment.java +++ b/src/com/bytezone/diskbrowser/applefile/PascalSegment.java @@ -8,7 +8,7 @@ import com.bytezone.diskbrowser.utilities.HexFormatter; public class PascalSegment extends AbstractFile implements PascalConstants { - private final int segmentNoHeader; + final int segmentNoHeader; private int segmentNoBody; public int blockNo; @@ -112,16 +112,18 @@ public class PascalSegment extends AbstractFile implements PascalConstants procedures.add (new PascalProcedure (buffer, i)); } - public String toText () + public String toText (int offset, String multiDiskAddress) { int sizeInBlocks = (size - 1) / 512 + 1; String newBlock = newBlockNo > 0 ? String.format ("%02X + %02X = %02X", newBlockNo, sizeInBlocks, (newBlockNo + sizeInBlocks)) : ""; + return String.format ( - " %2d %02X %02X %04X %,6d %-8s %-15s%3d " + " %2d %02X %02X %02X %04X %6s %-8s %-15s%3d " + "%02X %d %d %d %d %s", - slot, blockNo, sizeInBlocks, size, size, name, SegmentKind[segKind], textAddress, - segmentNoHeader, machineType, version, intrinsSegs1, intrinsSegs2, newBlock); + slot, blockNo, (blockNo + offset), sizeInBlocks, size, multiDiskAddress, name, + SegmentKind[segKind], textAddress, segmentNoHeader, machineType, version, + intrinsSegs1, intrinsSegs2, newBlock); } @Override diff --git a/src/com/bytezone/diskbrowser/applefile/Relocator.java b/src/com/bytezone/diskbrowser/applefile/Relocator.java index 9639b2f..7810865 100644 --- a/src/com/bytezone/diskbrowser/applefile/Relocator.java +++ b/src/com/bytezone/diskbrowser/applefile/Relocator.java @@ -26,6 +26,20 @@ public class Relocator extends AbstractFile } } + public List getMultiDiskAddress (int blockNumber) + { + System.out.printf ("searching for %04X%n", blockNumber); + List addresses = new ArrayList (); + + for (DiskRecord diskRecord : diskRecords) + for (DiskSegment diskSegment : diskRecord.diskSegments) + if (diskSegment.logicalBlock == blockNumber) + addresses.add (new MultiDiskAddress (diskRecord.diskNumber, + diskSegment.physicalBlock, diskSegment.segmentLength)); + + return addresses; + } + @Override public String getText () { @@ -46,25 +60,25 @@ public class Relocator extends AbstractFile private class DiskRecord { int diskNumber; - int diskSegments; - List segments = new ArrayList (); + int totDiskSegments; + List diskSegments = new ArrayList (); public DiskRecord (byte[] buffer, int ptr) { diskNumber = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]); - diskSegments = HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 4]); + totDiskSegments = HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 4]); ptr += 4; - for (int i = 0; i < diskSegments; i++) + for (int i = 0; i < totDiskSegments; i++) { - segments.add (new Segment (buffer, ptr)); + diskSegments.add (new DiskSegment (buffer, ptr)); ptr += 6; } } int size () { - return 4 + segments.size () * 6; + return 4 + diskSegments.size () * 6; } @Override @@ -72,25 +86,28 @@ public class Relocator extends AbstractFile { StringBuilder text = new StringBuilder (); + int offset = 0xe2; + text.append (String.format ("Disk number.... %04X%n", diskNumber)); - text.append (String.format ("Segments....... %04X%n%n", diskSegments)); - text.append ("Segment Logical Physical Length\n"); + text.append (String.format ("Segments....... %04X%n%n", totDiskSegments)); + text.append (String.format ( + "Segment Logical Physical Length -%04X -%04X%n", offset, offset)); int count = 1; - for (Segment segment : segments) - text.append (String.format (" %02X %s %n", count++, segment)); + for (DiskSegment segment : diskSegments) + text.append (String.format (" %02X %s %n", count++, segment.toString (offset))); return text.toString (); } } - private class Segment + private class DiskSegment { int logicalBlock; int physicalBlock; int segmentLength; - public Segment (byte[] buffer, int ptr) + public DiskSegment (byte[] buffer, int ptr) { logicalBlock = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]); physicalBlock = HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 3]); @@ -100,9 +117,39 @@ public class Relocator extends AbstractFile @Override public String toString () { - return String.format (" %04X %04X %04X %04X %04X", - logicalBlock, physicalBlock, segmentLength, - (logicalBlock - 0x46), (physicalBlock - 0x46)); + return String.format (" %04X %04X %04X", logicalBlock, physicalBlock, + segmentLength); + } + + public String toString (int offset) + { + int logical = logicalBlock - offset; + int physical = physicalBlock - offset; + if (physical >= 0) + return String.format (" %04X %04X %04X %04X %04X", + logicalBlock, physicalBlock, segmentLength, logical, physical); + return String.format (" %04X %04X %04X", logicalBlock, physicalBlock, + segmentLength); + } + } + + class MultiDiskAddress + { + int diskNumber; + int blockNumber; + int totalBlocks; + + public MultiDiskAddress (int diskNumber, int blockNumber, int totalBlocks) + { + this.diskNumber = diskNumber; + this.blockNumber = blockNumber; + this.totalBlocks = totalBlocks; + } + + @Override + public String toString () + { + return String.format ("%d:%03X", diskNumber, blockNumber); } } } \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/pascal/FileEntry.java b/src/com/bytezone/diskbrowser/pascal/FileEntry.java index 44fbf01..a524257 100644 --- a/src/com/bytezone/diskbrowser/pascal/FileEntry.java +++ b/src/com/bytezone/diskbrowser/pascal/FileEntry.java @@ -7,11 +7,13 @@ import com.bytezone.diskbrowser.utilities.HexFormatter; class FileEntry extends CatalogEntry { int bytesUsedInLastBlock; + private final Relocator relocator; - public FileEntry (PascalDisk parent, byte[] buffer) + public FileEntry (PascalDisk parent, byte[] buffer, Relocator relocator) { super (parent, buffer); + this.relocator = relocator; bytesUsedInLastBlock = HexFormatter.intValue (buffer[22], buffer[23]); date = HexFormatter.getPascalDate (buffer, 24); @@ -67,7 +69,7 @@ class FileEntry extends CatalogEntry case 2: // code (6502 or Pascal) try { - file = new PascalCode (name, buffer); + file = new PascalCode (name, buffer, firstBlock, relocator); } catch (FileFormatException e) { diff --git a/src/com/bytezone/diskbrowser/pascal/PascalDisk.java b/src/com/bytezone/diskbrowser/pascal/PascalDisk.java index 194c2e6..be5e60f 100755 --- a/src/com/bytezone/diskbrowser/pascal/PascalDisk.java +++ b/src/com/bytezone/diskbrowser/pascal/PascalDisk.java @@ -12,6 +12,7 @@ import com.bytezone.diskbrowser.applefile.AppleFileSource; import com.bytezone.diskbrowser.applefile.BootSector; import com.bytezone.diskbrowser.applefile.PascalCode; import com.bytezone.diskbrowser.applefile.PascalSegment; +import com.bytezone.diskbrowser.applefile.Relocator; import com.bytezone.diskbrowser.disk.*; import com.bytezone.diskbrowser.gui.DataSource; import com.bytezone.diskbrowser.utilities.HexFormatter; @@ -22,6 +23,7 @@ public class PascalDisk extends AbstractFormattedDisk private final DateFormat df = DateFormat.getDateInstance (DateFormat.SHORT); private final VolumeEntry volumeEntry; private final PascalCatalogSector diskCatalogSector; + private Relocator relocator; final String[] fileTypes = { "Volume", "Xdsk", "Code", "Text", "Info", "Data", "Graf", "Foto", "SecureDir" }; @@ -99,11 +101,14 @@ public class PascalDisk extends AbstractFormattedDisk data = new byte[CATALOG_ENTRY_SIZE]; System.arraycopy (buffer, ptr, data, 0, CATALOG_ENTRY_SIZE); - FileEntry fileEntry = new FileEntry (this, data); + FileEntry fileEntry = new FileEntry (this, data, relocator); fileEntries.add (fileEntry); DefaultMutableTreeNode node = new DefaultMutableTreeNode (fileEntry); - if (fileEntry.fileType == 2 && fileEntry.getDataSource () instanceof PascalCode) // PascalCode + if (fileEntry.fileType == 5 && fileEntry.getDataSource () instanceof Relocator) + this.relocator = (Relocator) fileEntry.getDataSource (); + + if (fileEntry.fileType == 2 && fileEntry.getDataSource () instanceof PascalCode) { node.setAllowsChildren (true); PascalCode pascalCode = (PascalCode) fileEntry.getDataSource (); @@ -209,7 +214,7 @@ public class PascalDisk extends AbstractFormattedDisk GregorianCalendar date = HexFormatter.getPascalDate (buffer, 24); if (debug) System.out.printf ("%4d %4d %d %-15s %d %s%n", firstBlock, lastBlock, kind, - new String (buffer, ptr + 7, nameLength), lastByte, date); + new String (buffer, ptr + 7, nameLength), lastByte, date); } return true; @@ -258,16 +263,16 @@ public class PascalDisk extends AbstractFormattedDisk { String newLine = String.format ("%n"); String newLine2 = newLine + newLine; - String line = - "---- --------------- ---- -------- ------- ---- ----" + newLine; + String line = "---- --------------- ---- -------- ------- ---- ---- ----" + + newLine; String date = volumeEntry.date == null ? "--" : df.format (volumeEntry.date.getTime ()); StringBuilder text = new StringBuilder (); text.append ("Disk : " + disk.getFile ().getAbsolutePath () + newLine2); text.append ("Volume : " + volumeEntry.name + newLine); text.append ("Date : " + date + newLine2); - text.append ("Blks Name Type Date Length Frst Last" - + newLine); + text.append ( + "Blks Name Type Date Length Frst Last Blks\n"); text.append (line); int usedBlocks = 6; @@ -278,15 +283,14 @@ public class PascalDisk extends AbstractFormattedDisk usedBlocks += size; date = ce.date == null ? "--" : df.format (ce.date.getTime ()); int bytes = (size - 1) * 512 + ce.bytesUsedInLastBlock; - text.append (String.format ("%4d %-15s %s %8s %,8d $%03X $%03X%n", size, - ce.name, fileTypes[ce.fileType], date, bytes, - ce.firstBlock, ce.lastBlock)); + text.append (String.format ("%4d %-15s %s %8s %,8d $%03X $%03X $%03X%n", + size, ce.name, fileTypes[ce.fileType], date, bytes, ce.firstBlock, ce.lastBlock, + size)); } text.append (line); - text.append (String.format ( - "Blocks free : %3d Blocks used : %3d Total blocks : %3d%n", - (volumeEntry.totalBlocks - usedBlocks), usedBlocks, - volumeEntry.totalBlocks)); + text.append ( + String.format ("Blocks free : %3d Blocks used : %3d Total blocks : %3d%n", + (volumeEntry.totalBlocks - usedBlocks), usedBlocks, volumeEntry.totalBlocks)); return new DefaultAppleFileSource (volumeEntry.name, text.toString (), this); } } \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/utilities/HexFormatter.java b/src/com/bytezone/diskbrowser/utilities/HexFormatter.java index d1d27c1..7a514e2 100755 --- a/src/com/bytezone/diskbrowser/utilities/HexFormatter.java +++ b/src/com/bytezone/diskbrowser/utilities/HexFormatter.java @@ -55,6 +55,8 @@ public class HexFormatter { if (line.length () > 0 && i > 0) line.append ("\n"); + if (i > 0 && (i % 0x200) == 0) + line.append ("\n"); // print offset for (int temp = i + startingAddress, max = 65536; max > 0; max /= 16) @@ -106,8 +108,8 @@ public class HexFormatter if (freq[i] > 0) { totalBits += (Integer.bitCount (i) * freq[i]); - line.append (String.format ("%02X %3d %d%n", i, freq[i], - Integer.bitCount (i))); + line.append ( + String.format ("%02X %3d %d%n", i, freq[i], Integer.bitCount (i))); } line.append (String.format ("%nTotal bits : %d%n", totalBits)); }