dmolony-DiskBrowser/src/com/bytezone/diskbrowser/wizardry/Relocator.java

236 lines
7.4 KiB
Java

package com.bytezone.diskbrowser.wizardry;
import java.util.ArrayList;
import java.util.List;
import com.bytezone.diskbrowser.applefile.AbstractFile;
import com.bytezone.diskbrowser.disk.AppleDisk;
import com.bytezone.diskbrowser.disk.Disk;
import com.bytezone.diskbrowser.disk.DiskAddress;
import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------//
public class Relocator extends AbstractFile
// -----------------------------------------------------------------------------------//
{
private final int checkByte;
private final List<DiskRecord> diskRecords = new ArrayList<> ();
private final int[] diskBlocks = new int[0x800];
private final int[] diskOffsets = new int[0x800];
// ---------------------------------------------------------------------------------//
public Relocator (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
{
super (name, buffer);
checkByte = Utility.getShort (buffer, 0); // no of blocks?
int ptr = 2; // skip checkByte
while (buffer[ptr] != 0)
{
DiskRecord diskRecord = new DiskRecord (buffer, ptr);
diskRecords.add (diskRecord);
ptr += diskRecord.size ();
}
for (DiskRecord diskRecord : diskRecords)
for (DiskSegment diskSegment : diskRecord.diskSegments)
{
int lo = diskSegment.logicalBlock;
int hi = lo + diskSegment.segmentLength;
for (int i = lo, count = 0; i < hi; i++, count++)
if (diskBlocks[i] == 0) // doesn't matter either way
{
if (diskBlocks[i] != 0 && false)
{
System.out.print ("was: ");
System.out.printf ("diskBlocks[%d] = %d%n", i, diskBlocks[i]);
System.out.print ("now: ");
System.out.printf ("diskBlocks[%d] = %d%n", i, diskRecord.diskNumber);
}
diskBlocks[i] = diskRecord.diskNumber;
diskOffsets[i] = diskSegment.physicalBlock + count;
}
}
}
// ---------------------------------------------------------------------------------//
public void createNewBuffer (Disk[] dataDisks)
// ---------------------------------------------------------------------------------//
{
AppleDisk master = (AppleDisk) dataDisks[0];
for (int logicalBlock = 0; logicalBlock < diskBlocks.length; logicalBlock++)
{
int diskNo = diskBlocks[logicalBlock];
if (diskNo > 0)
{
Disk disk = dataDisks[diskNo];
byte[] temp = disk.readBlock (diskOffsets[logicalBlock]);
DiskAddress da = master.getDiskAddress (logicalBlock);
master.writeBlock (da, temp);
}
}
}
// ---------------------------------------------------------------------------------//
@Override
public String getText ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
text.append ("Pascal Relocator\n\n");
text.append (String.format ("Check byte..... %04X%n%n", checkByte));
for (DiskRecord diskRecord : diskRecords)
{
text.append (diskRecord);
text.append ("\n");
}
List<String> lines = new ArrayList<> ();
String heading = " Logical Size Disk Physical";
String underline = "--------- ---- ---- ---------";
int first = 0;
int lastDisk = diskBlocks[0];
int lastOffset = diskOffsets[0];
for (int i = 0; i < diskBlocks.length; i++)
{
if (diskBlocks[i] != lastDisk || diskOffsets[i] != lastOffset + i - first)
{
int size = i - first;
if (lastDisk > 0)
lines.add (String.format ("%03X - %03X %03X %d %03X - %03X", first, i - 1, size,
lastDisk, lastOffset, lastOffset + size - 1));
else
lines.add (String.format ("%03X - %03X %03X", first, i - 1, size));
first = i;
lastDisk = diskBlocks[i];
lastOffset = diskOffsets[i];
}
}
if (lastDisk > 0)
{
int max = diskBlocks.length;
int size = max - first;
lines.add (String.format ("%03X - %03X %03X %d %03X - %03X", first, max - 1, size,
lastDisk, lastOffset, lastOffset + size - 1));
}
for (int i = lines.size () - 1; i >= 0; i--)
{
String line = lines.get (i);
if (line.length () > 20)
break;
lines.remove (i);
}
text.append (String.format (" %s %s%n %s %s%n", heading, heading, underline,
underline));
int offset = (lines.size () + 1) / 2;
int pairs = lines.size () / 2;
for (int i = 0; i < pairs; i++)
text.append (String.format (" %-35s %s%n", lines.get (i), lines.get (i + offset)));
if (offset != pairs)
text.append (String.format (" %s%n", lines.get (pairs)));
// show gaps
if (false)
for (int i = 0; i < 0x22C; i++)
if (diskBlocks[i] == 0)
text.append (String.format ("%04X %3d %3d%n", i, diskBlocks[i], diskOffsets[i]));
return text.toString ();
}
// ---------------------------------------------------------------------------------//
private class DiskRecord
// ---------------------------------------------------------------------------------//
{
int diskNumber;
int totDiskSegments;
List<DiskSegment> diskSegments;
public DiskRecord (byte[] buffer, int ptr)
{
diskNumber = Utility.getShort (buffer, ptr);
totDiskSegments = Utility.getShort (buffer, ptr + 2);
diskSegments = new ArrayList<> (totDiskSegments);
ptr += 4;
for (int i = 0; i < totDiskSegments; i++)
{
diskSegments.add (new DiskSegment (buffer, ptr));
ptr += 6;
}
}
int size ()
{
return 4 + diskSegments.size () * 6;
}
@Override
public String toString ()
{
StringBuilder text = new StringBuilder ();
text.append (String.format ("Disk number.... %04X%n", diskNumber));
text.append (String.format ("Segments....... %04X%n%n", totDiskSegments));
text.append (String.format (" Seg Physical Logical Size Gap%n"));
text.append (String.format (" --- ----------- ----------- ---- ----%n"));
int count = 1;
int last = 0;
int skip = 0;
for (DiskSegment diskSegment : diskSegments)
{
if (diskSegment.logicalBlock > last)
{
int end = diskSegment.logicalBlock - 1;
skip = end - last + 1;
}
last = diskSegment.logicalBlock + diskSegment.segmentLength;
text.append (String.format (" %02X %s %04X%n", count++, diskSegment, skip));
}
return text.toString ();
}
}
// ---------------------------------------------------------------------------------//
private class DiskSegment
// ---------------------------------------------------------------------------------//
{
int logicalBlock;
int physicalBlock;
int segmentLength;
public DiskSegment (byte[] buffer, int ptr)
{
logicalBlock = Utility.getShort (buffer, ptr);
physicalBlock = Utility.getShort (buffer, ptr + 2);
segmentLength = Utility.getShort (buffer, ptr + 4);
}
@Override
public String toString ()
{
return String.format (" %04X - %04X %04X - %04X %04X", physicalBlock,
(physicalBlock + segmentLength - 1), logicalBlock, (logicalBlock + segmentLength - 1),
segmentLength);
}
}
}