mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2025-02-20 04:29:02 +00:00
Wiz 4 maps
This commit is contained in:
parent
2036ca4b96
commit
c0adaef3e2
@ -3,7 +3,6 @@ package com.bytezone.diskbrowser.applefile;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.applefile.Relocator.MultiDiskAddress;
|
|
||||||
import com.bytezone.diskbrowser.utilities.FileFormatException;
|
import com.bytezone.diskbrowser.utilities.FileFormatException;
|
||||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
|
|
||||||
@ -12,8 +11,9 @@ public class PascalSegment extends AbstractFile implements PascalConstants
|
|||||||
private final static int BLOCK_SIZE = 512;
|
private final static int BLOCK_SIZE = 512;
|
||||||
final int segmentNoHeader;
|
final int segmentNoHeader;
|
||||||
private int segmentNoBody;
|
private int segmentNoBody;
|
||||||
private final int blockOffset;
|
// private final int blockOffset;
|
||||||
// private final Relocator relocator;
|
// private final Relocator relocator;
|
||||||
|
boolean debug = false;
|
||||||
|
|
||||||
public int blockNo;
|
public int blockNo;
|
||||||
// public int newBlockNo;
|
// public int newBlockNo;
|
||||||
@ -28,14 +28,14 @@ public class PascalSegment extends AbstractFile implements PascalConstants
|
|||||||
private final int slot;
|
private final int slot;
|
||||||
private int totalProcedures;
|
private int totalProcedures;
|
||||||
private List<PascalProcedure> procedures;
|
private List<PascalProcedure> procedures;
|
||||||
private List<MultiDiskAddress> addresses;
|
// private List<MultiDiskAddress> addresses;
|
||||||
|
|
||||||
public PascalSegment (String name, byte[] fullBuffer, int seq, int blockOffset)
|
public PascalSegment (String name, byte[] fullBuffer, int seq, int blockOffset)
|
||||||
{
|
{
|
||||||
super (name, fullBuffer); // sets this.buffer to the full buffer temporarily
|
super (name, fullBuffer); // sets this.buffer to the full buffer temporarily
|
||||||
|
|
||||||
this.slot = seq;
|
this.slot = seq;
|
||||||
this.blockOffset = blockOffset;
|
// this.blockOffset = blockOffset;
|
||||||
// this.relocator = relocator;
|
// this.relocator = relocator;
|
||||||
|
|
||||||
this.blockNo = HexFormatter.intValue (fullBuffer[seq * 4], fullBuffer[seq * 4 + 1]);
|
this.blockNo = HexFormatter.intValue (fullBuffer[seq * 4], fullBuffer[seq * 4 + 1]);
|
||||||
@ -89,18 +89,19 @@ public class PascalSegment extends AbstractFile implements PascalConstants
|
|||||||
{
|
{
|
||||||
buffer = new byte[0];
|
buffer = new byte[0];
|
||||||
}
|
}
|
||||||
else if (offset < fullBuffer.length)
|
else if ((offset + size) < fullBuffer.length)
|
||||||
{
|
{
|
||||||
buffer = new byte[size]; // replaces this.buffer with the segment buffer only
|
buffer = new byte[size]; // replaces this.buffer with the segment buffer only
|
||||||
System.arraycopy (fullBuffer, offset, buffer, 0, size);
|
System.arraycopy (fullBuffer, offset, buffer, 0, size);
|
||||||
totalProcedures = buffer[size - 1] & 0xFF;
|
totalProcedures = buffer[size - 1] & 0xFF;
|
||||||
segmentNoBody = buffer[size - 2] & 0xFF;
|
segmentNoBody = buffer[size - 2] & 0xFF;
|
||||||
|
|
||||||
if (segmentNoHeader == 0)
|
if (debug)
|
||||||
System.out.printf ("Zero segment header in %s seq %d%n", name, seq);
|
if (segmentNoHeader == 0)
|
||||||
else if (segmentNoBody != segmentNoHeader)
|
System.out.printf ("Zero segment header in %s seq %d%n", name, seq);
|
||||||
System.out.println (
|
else if (segmentNoBody != segmentNoHeader)
|
||||||
"Segment number mismatch : " + segmentNoBody + " / " + segmentNoHeader);
|
System.out.println (
|
||||||
|
"Segment number mismatch : " + segmentNoBody + " / " + segmentNoHeader);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -108,10 +109,10 @@ public class PascalSegment extends AbstractFile implements PascalConstants
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMultiDiskAddresses (List<MultiDiskAddress> addresses)
|
// void setMultiDiskAddresses (List<MultiDiskAddress> addresses)
|
||||||
{
|
// {
|
||||||
this.addresses = addresses;
|
// this.addresses = addresses;
|
||||||
}
|
// }
|
||||||
|
|
||||||
private void buildProcedureList ()
|
private void buildProcedureList ()
|
||||||
{
|
{
|
||||||
|
@ -1,364 +0,0 @@
|
|||||||
package com.bytezone.diskbrowser.applefile;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.disk.AppleDisk;
|
|
||||||
import com.bytezone.diskbrowser.disk.Disk;
|
|
||||||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
|
||||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
|
||||||
|
|
||||||
public class Relocator extends AbstractFile
|
|
||||||
{
|
|
||||||
private final int checkByte;
|
|
||||||
private final List<DiskRecord> diskRecords = new ArrayList<DiskRecord> ();
|
|
||||||
private final List<MultiDiskAddress> addresses = new ArrayList<MultiDiskAddress> ();
|
|
||||||
|
|
||||||
private final List<MultiDiskAddress> newAddresses = new ArrayList<MultiDiskAddress> ();
|
|
||||||
private final List<MultiDiskAddress> oldAddresses = new ArrayList<MultiDiskAddress> ();
|
|
||||||
|
|
||||||
private final List<MultiDiskAddress> logicalAddresses =
|
|
||||||
new ArrayList<MultiDiskAddress> ();
|
|
||||||
|
|
||||||
private final byte[] diskBlocks = new byte[0x800];
|
|
||||||
private final int[] diskOffsets = new int[0x800];
|
|
||||||
private final int[] diskOffsets2 = new int[0x800];
|
|
||||||
private final Disk[] dataDisks = new Disk[5];
|
|
||||||
|
|
||||||
public Relocator (String name, byte[] buffer)
|
|
||||||
{
|
|
||||||
super (name, buffer);
|
|
||||||
|
|
||||||
checkByte = HexFormatter.intValue (buffer[0], buffer[1]);
|
|
||||||
|
|
||||||
int ptr = 2; // skip checkByte
|
|
||||||
|
|
||||||
while (buffer[ptr] != 0)
|
|
||||||
{
|
|
||||||
DiskRecord diskRecord = new DiskRecord (buffer, ptr);
|
|
||||||
diskRecords.add (diskRecord);
|
|
||||||
ptr += diskRecord.size ();
|
|
||||||
}
|
|
||||||
|
|
||||||
logicalAddresses.add (new MultiDiskAddress (0, 0, 0, 0x800));
|
|
||||||
|
|
||||||
for (DiskRecord diskRecord : diskRecords)
|
|
||||||
for (DiskSegment diskSegment : diskRecord.diskSegments)
|
|
||||||
{
|
|
||||||
addresses
|
|
||||||
.add (new MultiDiskAddress (diskRecord.diskNumber, diskSegment.logicalBlock,
|
|
||||||
diskSegment.physicalBlock, diskSegment.segmentLength));
|
|
||||||
addLogicalBlock ((byte) diskRecord.diskNumber, diskSegment);
|
|
||||||
}
|
|
||||||
|
|
||||||
getMultiDiskAddress ("BOOT", 0, 2);
|
|
||||||
getMultiDiskAddress ("CATALOG", 2, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void list ()
|
|
||||||
{
|
|
||||||
for (MultiDiskAddress multiDiskAddress : addresses)
|
|
||||||
System.out.printf ("%d %03X %03X %03X %s%n", multiDiskAddress.diskNumber,
|
|
||||||
multiDiskAddress.logicalBlockNumber, multiDiskAddress.physicalBlockNumber,
|
|
||||||
multiDiskAddress.totalBlocks, multiDiskAddress.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addLogicalBlock (byte disk, DiskSegment diskSegment)
|
|
||||||
{
|
|
||||||
int lo = diskSegment.logicalBlock;
|
|
||||||
int hi = diskSegment.logicalBlock + diskSegment.segmentLength;
|
|
||||||
int count = 0;
|
|
||||||
for (int i = lo; i < hi; i++)
|
|
||||||
if (diskBlocks[i] == 0)
|
|
||||||
{
|
|
||||||
diskBlocks[i] = disk;
|
|
||||||
diskOffsets[i] = diskSegment.physicalBlock;
|
|
||||||
diskOffsets2[i] = diskSegment.physicalBlock + count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getLogicalBuffer (DiskAddress da)
|
|
||||||
{
|
|
||||||
int block = da.getBlock ();
|
|
||||||
System.out.println (diskBlocks[block]);
|
|
||||||
Disk disk = dataDisks[diskBlocks[block] - 1];
|
|
||||||
System.out.println (diskOffsets2[block]);
|
|
||||||
System.out.println (disk);
|
|
||||||
return disk.readSector (diskOffsets2[block]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<MultiDiskAddress> getMultiDiskAddress (String name, int blockNumber,
|
|
||||||
int length)
|
|
||||||
{
|
|
||||||
List<MultiDiskAddress> foundAddresses = new ArrayList<MultiDiskAddress> ();
|
|
||||||
newAddresses.clear ();
|
|
||||||
oldAddresses.clear ();
|
|
||||||
// System.out.printf ("%04X %04X %s%n", blockNumber, length, name);
|
|
||||||
|
|
||||||
for (MultiDiskAddress multiDiskAddress : addresses)
|
|
||||||
{
|
|
||||||
if (multiDiskAddress.logicalBlockNumber == blockNumber)
|
|
||||||
{
|
|
||||||
if (multiDiskAddress.totalBlocks == length)
|
|
||||||
{
|
|
||||||
foundAddresses.add (multiDiskAddress);
|
|
||||||
if (multiDiskAddress.name.isEmpty ())
|
|
||||||
multiDiskAddress.name = name;
|
|
||||||
}
|
|
||||||
else if (multiDiskAddress.totalBlocks > length)
|
|
||||||
{
|
|
||||||
MultiDiskAddress newAddress1 = new MultiDiskAddress (
|
|
||||||
multiDiskAddress.diskNumber, multiDiskAddress.logicalBlockNumber,
|
|
||||||
multiDiskAddress.physicalBlockNumber, length, name);
|
|
||||||
MultiDiskAddress newAddress2 = new MultiDiskAddress (
|
|
||||||
multiDiskAddress.diskNumber, multiDiskAddress.logicalBlockNumber + length,
|
|
||||||
multiDiskAddress.physicalBlockNumber + length,
|
|
||||||
multiDiskAddress.totalBlocks - length);
|
|
||||||
oldAddresses.add (multiDiskAddress);
|
|
||||||
newAddresses.add (newAddress1);
|
|
||||||
newAddresses.add (newAddress2);
|
|
||||||
foundAddresses.add (newAddress1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newAddresses.size () > 0)
|
|
||||||
{
|
|
||||||
addresses.addAll (newAddresses);
|
|
||||||
addresses.removeAll (oldAddresses);
|
|
||||||
Collections.sort (addresses);
|
|
||||||
}
|
|
||||||
|
|
||||||
return foundAddresses;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDisks (Disk[] disks)
|
|
||||||
{
|
|
||||||
for (Disk disk : disks)
|
|
||||||
{
|
|
||||||
byte[] buffer = disk.readSector (1);
|
|
||||||
int diskNo = buffer[510] & 0xFF;
|
|
||||||
if (diskNo > 0 && diskNo <= 5)
|
|
||||||
dataDisks[diskNo - 1] = disk;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasData ()
|
|
||||||
{
|
|
||||||
for (Disk disk : dataDisks)
|
|
||||||
if (disk == null)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void createNewBuffer (Disk[] dataDisks)
|
|
||||||
{
|
|
||||||
AppleDisk master = (AppleDisk) dataDisks[0];
|
|
||||||
|
|
||||||
for (int logicalBlock = 0; logicalBlock < diskBlocks.length; logicalBlock++)
|
|
||||||
{
|
|
||||||
int physicalBlock = diskOffsets2[logicalBlock];
|
|
||||||
int diskNo = diskBlocks[logicalBlock];
|
|
||||||
if (diskNo > 0)
|
|
||||||
{
|
|
||||||
Disk disk = dataDisks[diskNo];
|
|
||||||
byte[] temp = disk.readSector (physicalBlock);
|
|
||||||
DiskAddress da = master.getDiskAddress (logicalBlock);
|
|
||||||
master.writeSector (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");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (false)
|
|
||||||
{
|
|
||||||
int previousDiskNumber = 0;
|
|
||||||
for (MultiDiskAddress multiDiskAddress : addresses)
|
|
||||||
{
|
|
||||||
if (multiDiskAddress.diskNumber != previousDiskNumber)
|
|
||||||
{
|
|
||||||
previousDiskNumber = multiDiskAddress.diskNumber;
|
|
||||||
text.append ("\n");
|
|
||||||
text.append ("Disk Logical Physical Size Name\n");
|
|
||||||
text.append ("---- ------- -------- ---- -------------\n");
|
|
||||||
}
|
|
||||||
text.append (String.format (" %d %03X %03X %03X %s%n",
|
|
||||||
multiDiskAddress.diskNumber, multiDiskAddress.logicalBlockNumber,
|
|
||||||
multiDiskAddress.physicalBlockNumber, multiDiskAddress.totalBlocks,
|
|
||||||
multiDiskAddress.name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
text.append ("\n Logical Size Disk Physical");
|
|
||||||
text.append ("\n--------- ---- ---- ---------\n");
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
int size = i - first;
|
|
||||||
if (lastDisk > 0)
|
|
||||||
text.append (String.format ("%03X - %03X %03X %d %03X - %03X%n", first,
|
|
||||||
i - 1, size, lastDisk, lastOffset, lastOffset + size - 1));
|
|
||||||
else
|
|
||||||
text.append (String.format ("%03X - %03X %03X%n", first, i - 1, size));
|
|
||||||
first = i;
|
|
||||||
lastDisk = diskBlocks[i];
|
|
||||||
lastOffset = diskOffsets[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastDisk > 0)
|
|
||||||
{
|
|
||||||
int max = diskBlocks.length;
|
|
||||||
int size = max - first;
|
|
||||||
text.append (String.format ("%03X - %03X %03X %d %03X - %03X%n", first,
|
|
||||||
max - 1, size, lastDisk, lastOffset, lastOffset + size - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
return text.toString ();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DiskRecord
|
|
||||||
{
|
|
||||||
int diskNumber;
|
|
||||||
int totDiskSegments;
|
|
||||||
List<DiskSegment> diskSegments = new ArrayList<DiskSegment> ();
|
|
||||||
|
|
||||||
public DiskRecord (byte[] buffer, int ptr)
|
|
||||||
{
|
|
||||||
diskNumber = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]);
|
|
||||||
totDiskSegments = HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 4]);
|
|
||||||
|
|
||||||
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 Skip Size Logical Physical%n"));
|
|
||||||
text.append (String.format (" --- ---- ---- ----------- -----------%n"));
|
|
||||||
|
|
||||||
int count = 1;
|
|
||||||
int last = 0;
|
|
||||||
int size = 0;
|
|
||||||
|
|
||||||
for (DiskSegment segment : diskSegments)
|
|
||||||
{
|
|
||||||
if (segment.logicalBlock > last)
|
|
||||||
{
|
|
||||||
int end = segment.logicalBlock - 1;
|
|
||||||
size = end - last + 1;
|
|
||||||
}
|
|
||||||
last = segment.logicalBlock + segment.segmentLength;
|
|
||||||
text.append (
|
|
||||||
String.format (" %02X %04X %s %n", count++, size, segment.toString ()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return text.toString ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DiskSegment
|
|
||||||
{
|
|
||||||
int logicalBlock;
|
|
||||||
int physicalBlock;
|
|
||||||
int segmentLength;
|
|
||||||
|
|
||||||
public DiskSegment (byte[] buffer, int ptr)
|
|
||||||
{
|
|
||||||
logicalBlock = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]);
|
|
||||||
physicalBlock = HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 3]);
|
|
||||||
segmentLength = HexFormatter.intValue (buffer[ptr + 4], buffer[ptr + 5]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString ()
|
|
||||||
{
|
|
||||||
return String.format (" %04X %04X - %04X %04X - %04X", segmentLength,
|
|
||||||
logicalBlock, (logicalBlock + segmentLength - 1), physicalBlock,
|
|
||||||
(physicalBlock + segmentLength - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 implements Comparable<MultiDiskAddress>
|
|
||||||
{
|
|
||||||
int diskNumber;
|
|
||||||
int logicalBlockNumber;
|
|
||||||
int physicalBlockNumber;
|
|
||||||
int totalBlocks;
|
|
||||||
String name = "";
|
|
||||||
|
|
||||||
public MultiDiskAddress (int diskNumber, int logicalBlockNumber,
|
|
||||||
int physicalBlockNumber, int totalBlocks)
|
|
||||||
{
|
|
||||||
this.diskNumber = diskNumber;
|
|
||||||
this.logicalBlockNumber = logicalBlockNumber;
|
|
||||||
this.physicalBlockNumber = physicalBlockNumber;
|
|
||||||
this.totalBlocks = totalBlocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MultiDiskAddress (int diskNumber, int logicalBlockNumber,
|
|
||||||
int physicalBlockNumber, int totalBlocks, String name)
|
|
||||||
{
|
|
||||||
this (diskNumber, logicalBlockNumber, physicalBlockNumber, totalBlocks);
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString ()
|
|
||||||
{
|
|
||||||
return String.format ("%d:%03X", diskNumber, physicalBlockNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo (MultiDiskAddress o)
|
|
||||||
{
|
|
||||||
if (this.diskNumber == o.diskNumber)
|
|
||||||
return this.logicalBlockNumber - o.logicalBlockNumber;
|
|
||||||
return this.diskNumber - o.diskNumber;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -388,34 +388,35 @@ public class DiskFactory
|
|||||||
if (debug)
|
if (debug)
|
||||||
System.out.println ("Not a Wizardry 1-3 disk");
|
System.out.println ("Not a Wizardry 1-3 disk");
|
||||||
|
|
||||||
if (Wizardry4BootDisk.isWizardryIV (disk, debug))
|
// check for compressed disk
|
||||||
|
if (file.getName ().endsWith (".tmp"))
|
||||||
|
return new PascalDisk (disk); // complicated joining up compressed disks
|
||||||
|
|
||||||
|
if (Wizardry4BootDisk.isWizardryIVorV (disk, debug))
|
||||||
{
|
{
|
||||||
// collect 4 extra data disks
|
String fileName = file.getAbsolutePath ().toLowerCase ();
|
||||||
AppleDisk[] disks = new AppleDisk[6];
|
int pos = file.getAbsolutePath ().indexOf ('.');
|
||||||
|
char c = fileName.charAt (pos - 1);
|
||||||
|
String suffix = fileName.substring (pos + 1);
|
||||||
|
int requiredDisks = c == '1' ? 6 : c == 'a' ? 10 : 0;
|
||||||
|
|
||||||
disks[0] = new AppleDisk (file, 256, 8); // will become a PascalDisk
|
if (requiredDisks > 0)
|
||||||
disks[1] = new AppleDisk (file, 256, 8); // will remain a DataDisk
|
|
||||||
disks[0].setInterleave (1);
|
|
||||||
disks[1].setInterleave (1);
|
|
||||||
|
|
||||||
for (int i = 2; i < disks.length; i++)
|
|
||||||
{
|
{
|
||||||
String filename = file.getAbsolutePath ().replace ("1.dsk", i + ".dsk");
|
// collect extra data disks
|
||||||
File f = new File (filename);
|
AppleDisk[] disks = new AppleDisk[requiredDisks];
|
||||||
if (f.exists () && f.isFile ())
|
|
||||||
|
disks[0] = new AppleDisk (file, 256, 8); // will become a PascalDisk
|
||||||
|
disks[0].setInterleave (1);
|
||||||
|
|
||||||
|
disks[1] = new AppleDisk (file, 256, 8); // will remain a DataDisk
|
||||||
|
disks[1].setInterleave (1);
|
||||||
|
|
||||||
|
if (pos > 0 && requiredDisks > 0)
|
||||||
{
|
{
|
||||||
AppleDisk dataDisk = new AppleDisk (f, 35, 8);
|
if (collectDataDisks (file.getAbsolutePath (), pos, disks))
|
||||||
dataDisk.setInterleave (1);
|
return new Wizardry4BootDisk (disks);
|
||||||
disks[i] = dataDisk;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PascalDisk pascalDisk = new PascalDisk (disk);
|
|
||||||
return pascalDisk;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Wizardry4BootDisk wiz4 = new Wizardry4BootDisk (disks);
|
|
||||||
return wiz4;
|
|
||||||
}
|
}
|
||||||
if (debug)
|
if (debug)
|
||||||
System.out.println ("Not a Wizardry IV disk");
|
System.out.println ("Not a Wizardry IV disk");
|
||||||
@ -424,6 +425,29 @@ public class DiskFactory
|
|||||||
return pascalDisk;
|
return pascalDisk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean collectDataDisks (String fileName, int dotPos, AppleDisk[] disks)
|
||||||
|
{
|
||||||
|
char c = fileName.charAt (dotPos - 1);
|
||||||
|
String suffix = fileName.substring (dotPos + 1);
|
||||||
|
|
||||||
|
for (int i = 2; i < disks.length; i++)
|
||||||
|
{
|
||||||
|
String old = new String (c + "." + suffix);
|
||||||
|
String rep = new String ((char) (c + i - 1) + "." + suffix);
|
||||||
|
// System.out.printf ("[%s] [%s]%n", old, rep);
|
||||||
|
File f = new File (fileName.replace (old, rep));
|
||||||
|
// System.out.println (f);
|
||||||
|
if (!f.exists () || !f.isFile ())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
AppleDisk dataDisk = new AppleDisk (f, 35, 8);
|
||||||
|
dataDisk.setInterleave (1);
|
||||||
|
disks[i] = dataDisk;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static InfocomDisk checkInfocomDisk (File file)
|
private static InfocomDisk checkInfocomDisk (File file)
|
||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
|
@ -13,15 +13,15 @@ import com.bytezone.diskbrowser.utilities.HexFormatter;
|
|||||||
|
|
||||||
abstract class CatalogEntry implements AppleFileSource
|
abstract class CatalogEntry implements AppleFileSource
|
||||||
{
|
{
|
||||||
|
protected AbstractFile file;
|
||||||
protected final PascalDisk parent;
|
protected final PascalDisk parent;
|
||||||
protected final String name;
|
protected String name;
|
||||||
int firstBlock;
|
protected int firstBlock;
|
||||||
int lastBlock; // block AFTER last used block
|
protected int lastBlock; // block AFTER last used block
|
||||||
int fileType;
|
protected int fileType;
|
||||||
GregorianCalendar date;
|
protected GregorianCalendar date;
|
||||||
int bytesUsedInLastBlock;
|
protected int bytesUsedInLastBlock;
|
||||||
List<DiskAddress> blocks = new ArrayList<DiskAddress> ();
|
protected final List<DiskAddress> blocks = new ArrayList<DiskAddress> ();
|
||||||
AbstractFile file;
|
|
||||||
|
|
||||||
public CatalogEntry (PascalDisk parent, byte[] buffer)
|
public CatalogEntry (PascalDisk parent, byte[] buffer)
|
||||||
{
|
{
|
||||||
@ -34,7 +34,8 @@ abstract class CatalogEntry implements AppleFileSource
|
|||||||
bytesUsedInLastBlock = HexFormatter.intValue (buffer[16], buffer[17]);
|
bytesUsedInLastBlock = HexFormatter.intValue (buffer[16], buffer[17]);
|
||||||
|
|
||||||
Disk disk = parent.getDisk ();
|
Disk disk = parent.getDisk ();
|
||||||
for (int i = firstBlock; i < lastBlock; i++)
|
int max = Math.min (lastBlock, disk.getTotalBlocks ());
|
||||||
|
for (int i = firstBlock; i < max; i++)
|
||||||
blocks.add (disk.getDiskAddress (i));
|
blocks.add (disk.getDiskAddress (i));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,13 +48,6 @@ abstract class CatalogEntry implements AppleFileSource
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString ()
|
|
||||||
{
|
|
||||||
int size = lastBlock - firstBlock;
|
|
||||||
return String.format ("%03d %s %-15s", size, parent.fileTypes[fileType], name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<DiskAddress> getSectors ()
|
public List<DiskAddress> getSectors ()
|
||||||
{
|
{
|
||||||
@ -72,4 +66,11 @@ abstract class CatalogEntry implements AppleFileSource
|
|||||||
{
|
{
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
int size = lastBlock - firstBlock;
|
||||||
|
return String.format ("%03d %s %-15s", size, parent.fileTypes[fileType], name);
|
||||||
|
}
|
||||||
}
|
}
|
@ -8,9 +8,7 @@ import com.bytezone.diskbrowser.utilities.HexFormatter;
|
|||||||
|
|
||||||
public class FileEntry extends CatalogEntry
|
public class FileEntry extends CatalogEntry
|
||||||
{
|
{
|
||||||
int bytesUsedInLastBlock;
|
|
||||||
private DefaultMutableTreeNode node;
|
private DefaultMutableTreeNode node;
|
||||||
AbstractFile file;
|
|
||||||
|
|
||||||
public FileEntry (PascalDisk parent, byte[] buffer)
|
public FileEntry (PascalDisk parent, byte[] buffer)
|
||||||
{
|
{
|
||||||
@ -19,7 +17,8 @@ public class FileEntry extends CatalogEntry
|
|||||||
bytesUsedInLastBlock = HexFormatter.intValue (buffer[22], buffer[23]);
|
bytesUsedInLastBlock = HexFormatter.intValue (buffer[22], buffer[23]);
|
||||||
date = HexFormatter.getPascalDate (buffer, 24);
|
date = HexFormatter.getPascalDate (buffer, 24);
|
||||||
|
|
||||||
for (int i = firstBlock; i < lastBlock; i++)
|
int max = Math.min (lastBlock, parent.getDisk ().getTotalBlocks ());
|
||||||
|
for (int i = firstBlock; i < max; i++)
|
||||||
{
|
{
|
||||||
switch (fileType)
|
switch (fileType)
|
||||||
{
|
{
|
||||||
|
@ -10,10 +10,10 @@ import javax.swing.tree.DefaultMutableTreeNode;
|
|||||||
|
|
||||||
import com.bytezone.diskbrowser.applefile.AppleFileSource;
|
import com.bytezone.diskbrowser.applefile.AppleFileSource;
|
||||||
import com.bytezone.diskbrowser.applefile.BootSector;
|
import com.bytezone.diskbrowser.applefile.BootSector;
|
||||||
import com.bytezone.diskbrowser.applefile.Relocator;
|
|
||||||
import com.bytezone.diskbrowser.disk.*;
|
import com.bytezone.diskbrowser.disk.*;
|
||||||
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.wizardry.Relocator;
|
||||||
|
|
||||||
public class PascalDisk extends AbstractFormattedDisk
|
public class PascalDisk extends AbstractFormattedDisk
|
||||||
{
|
{
|
||||||
@ -52,12 +52,6 @@ public class PascalDisk extends AbstractFormattedDisk
|
|||||||
List<DiskAddress> blocks = disk.getDiskAddressList (0, 1); // B0, B1
|
List<DiskAddress> blocks = disk.getDiskAddressList (0, 1); // B0, B1
|
||||||
this.bootSector = new BootSector (disk, disk.readSectors (blocks), "Pascal");
|
this.bootSector = new BootSector (disk, disk.readSectors (blocks), "Pascal");
|
||||||
|
|
||||||
byte[] buffer = disk.readSector (2);
|
|
||||||
byte[] data = new byte[CATALOG_ENTRY_SIZE];
|
|
||||||
System.arraycopy (buffer, 0, data, 0, CATALOG_ENTRY_SIZE);
|
|
||||||
|
|
||||||
volumeEntry = new VolumeEntry (this, data);
|
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
if (!disk.isSectorEmpty (i))
|
if (!disk.isSectorEmpty (i))
|
||||||
{
|
{
|
||||||
@ -68,8 +62,18 @@ public class PascalDisk extends AbstractFormattedDisk
|
|||||||
for (int i = 2; i < disk.getTotalBlocks (); i++)
|
for (int i = 2; i < disk.getTotalBlocks (); i++)
|
||||||
freeBlocks.set (i, true);
|
freeBlocks.set (i, true);
|
||||||
|
|
||||||
|
byte[] buffer = disk.readSector (2);
|
||||||
|
byte[] data = new byte[CATALOG_ENTRY_SIZE];
|
||||||
|
System.arraycopy (buffer, 0, data, 0, CATALOG_ENTRY_SIZE);
|
||||||
|
volumeEntry = new VolumeEntry (this, data);
|
||||||
|
|
||||||
|
DefaultMutableTreeNode root = getCatalogTreeRoot ();
|
||||||
|
DefaultMutableTreeNode volumeNode = new DefaultMutableTreeNode (volumeEntry);
|
||||||
|
root.add (volumeNode);
|
||||||
|
|
||||||
List<DiskAddress> sectors = new ArrayList<DiskAddress> ();
|
List<DiskAddress> sectors = new ArrayList<DiskAddress> ();
|
||||||
for (int i = 2; i < volumeEntry.lastBlock; i++)
|
int max = Math.min (volumeEntry.lastBlock, disk.getTotalBlocks ());
|
||||||
|
for (int i = 2; i < max; i++)
|
||||||
{
|
{
|
||||||
DiskAddress da = disk.getDiskAddress (i);
|
DiskAddress da = disk.getDiskAddress (i);
|
||||||
if (!disk.isSectorEmpty (da))
|
if (!disk.isSectorEmpty (da))
|
||||||
@ -81,13 +85,9 @@ public class PascalDisk extends AbstractFormattedDisk
|
|||||||
diskCatalogSector =
|
diskCatalogSector =
|
||||||
new PascalCatalogSector (disk, disk.readSectors (sectors), sectors);
|
new PascalCatalogSector (disk, disk.readSectors (sectors), sectors);
|
||||||
|
|
||||||
DefaultMutableTreeNode root = getCatalogTreeRoot ();
|
|
||||||
DefaultMutableTreeNode volumeNode = new DefaultMutableTreeNode (volumeEntry);
|
|
||||||
root.add (volumeNode);
|
|
||||||
|
|
||||||
// read the catalog
|
// read the catalog
|
||||||
List<DiskAddress> addresses = new ArrayList<DiskAddress> ();
|
List<DiskAddress> addresses = new ArrayList<DiskAddress> ();
|
||||||
for (int i = 2; i < volumeEntry.lastBlock; i++)
|
for (int i = 2; i < max; i++)
|
||||||
addresses.add (disk.getDiskAddress (i));
|
addresses.add (disk.getDiskAddress (i));
|
||||||
buffer = disk.readSectors (addresses);
|
buffer = disk.readSectors (addresses);
|
||||||
|
|
||||||
@ -96,9 +96,9 @@ public class PascalDisk extends AbstractFormattedDisk
|
|||||||
{
|
{
|
||||||
int ptr = i * CATALOG_ENTRY_SIZE;
|
int ptr = i * CATALOG_ENTRY_SIZE;
|
||||||
data = new byte[CATALOG_ENTRY_SIZE];
|
data = new byte[CATALOG_ENTRY_SIZE];
|
||||||
|
|
||||||
System.arraycopy (buffer, ptr, data, 0, CATALOG_ENTRY_SIZE);
|
System.arraycopy (buffer, ptr, data, 0, CATALOG_ENTRY_SIZE);
|
||||||
FileEntry fileEntry = new FileEntry (this, data);
|
FileEntry fileEntry = new FileEntry (this, data);
|
||||||
|
|
||||||
fileEntries.add (fileEntry);
|
fileEntries.add (fileEntry);
|
||||||
DefaultMutableTreeNode node = new DefaultMutableTreeNode (fileEntry);
|
DefaultMutableTreeNode node = new DefaultMutableTreeNode (fileEntry);
|
||||||
fileEntry.setNode (node);
|
fileEntry.setNode (node);
|
||||||
@ -106,7 +106,7 @@ public class PascalDisk extends AbstractFormattedDisk
|
|||||||
if (fileEntry.fileType == 2)
|
if (fileEntry.fileType == 2)
|
||||||
{
|
{
|
||||||
node.setAllowsChildren (true);
|
node.setAllowsChildren (true);
|
||||||
fileEntry.getDataSource ();
|
fileEntry.getDataSource (); // build segments
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
node.setAllowsChildren (false);
|
node.setAllowsChildren (false);
|
||||||
|
@ -8,37 +8,14 @@ class VolumeEntry extends CatalogEntry
|
|||||||
{
|
{
|
||||||
final int totalFiles;
|
final int totalFiles;
|
||||||
final int totalBlocks;
|
final int totalBlocks;
|
||||||
final int block1; // first block on the disk (usually 0)
|
|
||||||
final int lastDirectoryBlock; // (plus 1) (usually 6)
|
|
||||||
final int recordType; // 0 = directory
|
|
||||||
final int nameLength;
|
|
||||||
final String name;
|
|
||||||
|
|
||||||
public VolumeEntry (PascalDisk parent, byte[] buffer)
|
public VolumeEntry (PascalDisk parent, byte[] buffer)
|
||||||
{
|
{
|
||||||
super (parent, buffer);
|
super (parent, buffer);
|
||||||
|
|
||||||
block1 = HexFormatter.intValue (buffer[0], buffer[1]); // 0
|
|
||||||
lastDirectoryBlock = HexFormatter.intValue (buffer[2], buffer[3]); // 6
|
|
||||||
recordType = HexFormatter.intValue (buffer[4], buffer[5]); // 0
|
|
||||||
nameLength = buffer[6] & 0xFF;
|
|
||||||
name = HexFormatter.getPascalString (buffer, 6); // 06-0D
|
|
||||||
totalBlocks = HexFormatter.intValue (buffer[14], buffer[15]); // 280
|
totalBlocks = HexFormatter.intValue (buffer[14], buffer[15]); // 280
|
||||||
totalFiles = HexFormatter.intValue (buffer[16], buffer[17]);
|
totalFiles = HexFormatter.intValue (buffer[16], buffer[17]);
|
||||||
firstBlock = HexFormatter.intValue (buffer[18], buffer[19]); // 0
|
|
||||||
date = HexFormatter.getPascalDate (buffer, 20); // 2 bytes
|
date = HexFormatter.getPascalDate (buffer, 20); // 2 bytes
|
||||||
// bytes 0x16 - 0x19 are unused
|
|
||||||
|
|
||||||
if (false)
|
|
||||||
{
|
|
||||||
System.out.printf ("Total files ..... %d%n", totalFiles);
|
|
||||||
System.out.printf ("Total blocks .... %d%n", totalBlocks);
|
|
||||||
System.out.printf ("Block1 .......... %d%n", block1);
|
|
||||||
System.out.printf ("Last block ...... %d%n", lastDirectoryBlock);
|
|
||||||
System.out.printf ("Record type ..... %d%n", recordType);
|
|
||||||
System.out.printf ("Name length ..... %d%n", nameLength);
|
|
||||||
System.out.printf ("Name ............ %s%n", name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -11,206 +11,212 @@ import com.bytezone.diskbrowser.utilities.HexFormatter;
|
|||||||
|
|
||||||
class MazeLevel extends AbstractFile
|
class MazeLevel extends AbstractFile
|
||||||
{
|
{
|
||||||
public int level;
|
public final int level;
|
||||||
private List<Message> messages;
|
private List<Message> messages;
|
||||||
private List<Monster> monsters;
|
private List<Monster> monsters;
|
||||||
private List<Item> items;
|
private List<Item> items;
|
||||||
|
|
||||||
public MazeLevel (byte[] buffer, int level)
|
public MazeLevel (byte[] buffer, int level)
|
||||||
{
|
{
|
||||||
super ("Level " + level, buffer);
|
super ("Level " + level, buffer);
|
||||||
this.level = level;
|
this.level = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BufferedImage getImage ()
|
public BufferedImage getImage ()
|
||||||
{
|
{
|
||||||
Dimension cellSize = new Dimension (22, 22);
|
Dimension cellSize = new Dimension (22, 22);
|
||||||
image =
|
image = new BufferedImage (20 * cellSize.width + 1, 20 * cellSize.height + 1,
|
||||||
new BufferedImage (20 * cellSize.width + 1, 20 * cellSize.height + 1,
|
BufferedImage.TYPE_USHORT_555_RGB);
|
||||||
BufferedImage.TYPE_USHORT_555_RGB);
|
Graphics2D g = image.createGraphics ();
|
||||||
Graphics2D g = image.createGraphics ();
|
g.setRenderingHint (RenderingHints.KEY_ANTIALIASING,
|
||||||
g.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
|
||||||
for (int row = 0; row < 20; row++)
|
for (int row = 0; row < 20; row++)
|
||||||
for (int column = 0; column < 20; column++)
|
for (int column = 0; column < 20; column++)
|
||||||
{
|
{
|
||||||
MazeCell cell = getLocation ((row) % 20, (column) % 20);
|
MazeCell cell = getLocation (row, column);
|
||||||
int x = column * cellSize.width;
|
int x = column * cellSize.width;
|
||||||
int y = image.getHeight () - (row + 1) * cellSize.height - 1;
|
int y = image.getHeight () - (row + 1) * cellSize.height - 1;
|
||||||
cell.draw (g, x, y);
|
cell.draw (g, x, y);
|
||||||
}
|
}
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMessages (List<Message> messages)
|
public void setMessages (List<Message> messages)
|
||||||
{
|
{
|
||||||
this.messages = messages;
|
this.messages = messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMonsters (List<Monster> monsters)
|
public void setMonsters (List<Monster> monsters)
|
||||||
{
|
{
|
||||||
this.monsters = monsters;
|
this.monsters = monsters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setItems (List<Item> items)
|
public void setItems (List<Item> items)
|
||||||
{
|
{
|
||||||
this.items = items;
|
this.items = items;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MazeCell getLocation (int row, int column)
|
public MazeCell getLocation (int row, int column)
|
||||||
{
|
{
|
||||||
MazeAddress address = new MazeAddress (level, row, column);
|
MazeAddress address = new MazeAddress (level, row, column);
|
||||||
MazeCell cell = new MazeCell (address);
|
MazeCell cell = new MazeCell (address);
|
||||||
|
|
||||||
// doors and walls
|
// doors and walls
|
||||||
|
|
||||||
int offset = column * 6 + row / 4; // 6 bytes/column
|
int offset = column * 6 + row / 4; // 6 bytes/column
|
||||||
|
|
||||||
int value = HexFormatter.intValue (buffer[offset]);
|
int value = HexFormatter.intValue (buffer[offset]);
|
||||||
value >>>= (row % 4) * 2;
|
value >>>= (row % 4) * 2;
|
||||||
cell.westWall = ((value & 1) == 1);
|
cell.westWall = ((value & 1) == 1);
|
||||||
value >>>= 1;
|
value >>>= 1;
|
||||||
cell.westDoor = ((value & 1) == 1);
|
cell.westDoor = ((value & 1) == 1);
|
||||||
|
|
||||||
value = HexFormatter.intValue (buffer[offset + 120]);
|
value = HexFormatter.intValue (buffer[offset + 120]);
|
||||||
value >>>= (row % 4) * 2;
|
value >>>= (row % 4) * 2;
|
||||||
cell.southWall = ((value & 1) == 1);
|
cell.southWall = ((value & 1) == 1);
|
||||||
value >>>= 1;
|
value >>>= 1;
|
||||||
cell.southDoor = ((value & 1) == 1);
|
cell.southDoor = ((value & 1) == 1);
|
||||||
|
|
||||||
value = HexFormatter.intValue (buffer[offset + 240]);
|
value = HexFormatter.intValue (buffer[offset + 240]);
|
||||||
value >>>= (row % 4) * 2;
|
value >>>= (row % 4) * 2;
|
||||||
cell.eastWall = ((value & 1) == 1);
|
cell.eastWall = ((value & 1) == 1);
|
||||||
value >>>= 1;
|
value >>>= 1;
|
||||||
cell.eastDoor = ((value & 1) == 1);
|
cell.eastDoor = ((value & 1) == 1);
|
||||||
|
|
||||||
value = HexFormatter.intValue (buffer[offset + 360]);
|
value = HexFormatter.intValue (buffer[offset + 360]);
|
||||||
value >>>= (row % 4) * 2;
|
value >>>= (row % 4) * 2;
|
||||||
cell.northWall = ((value & 1) == 1);
|
cell.northWall = ((value & 1) == 1);
|
||||||
value >>>= 1;
|
value >>>= 1;
|
||||||
cell.northDoor = ((value & 1) == 1);
|
cell.northDoor = ((value & 1) == 1);
|
||||||
|
|
||||||
// monster table
|
// monster table
|
||||||
|
|
||||||
offset = column * 4 + row / 8; // 4 bytes/column, 1 bit/row
|
offset = column * 4 + row / 8; // 4 bytes/column, 1 bit/row
|
||||||
value = HexFormatter.intValue (buffer[offset + 480]);
|
value = HexFormatter.intValue (buffer[offset + 480]);
|
||||||
value >>>= row % 8;
|
value >>>= row % 8;
|
||||||
cell.monsterLair = ((value & 1) == 1);
|
cell.monsterLair = ((value & 1) == 1);
|
||||||
|
|
||||||
// stairs, pits, darkness etc.
|
// stairs, pits, darkness etc.
|
||||||
|
|
||||||
offset = column * 10 + row / 2; // 10 bytes/column, 4 bits/row
|
offset = column * 10 + row / 2; // 10 bytes/column, 4 bits/row
|
||||||
value = HexFormatter.intValue (buffer[offset + 560]);
|
value = HexFormatter.intValue (buffer[offset + 560]);
|
||||||
int b = (row % 2 == 0) ? value % 16 : value / 16;
|
int b = (row % 2 == 0) ? value % 16 : value / 16;
|
||||||
int c = HexFormatter.intValue (buffer[760 + b / 2]);
|
int c = HexFormatter.intValue (buffer[760 + b / 2]);
|
||||||
int d = (b % 2 == 0) ? c % 16 : c / 16;
|
int d = (b % 2 == 0) ? c % 16 : c / 16;
|
||||||
|
|
||||||
switch (d)
|
switch (d)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
cell.stairs = true;
|
cell.stairs = true;
|
||||||
cell.addressTo = getAddress (b);
|
cell.addressTo = getAddress (b);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
cell.pit = true;
|
cell.pit = true;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
cell.chute = true;
|
cell.chute = true;
|
||||||
cell.addressTo = getAddress (b);
|
cell.addressTo = getAddress (b);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
cell.spinner = true;
|
cell.spinner = true;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
cell.darkness = true;
|
cell.darkness = true;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
cell.teleport = true;
|
cell.teleport = true;
|
||||||
cell.addressTo = getAddress (b);
|
cell.addressTo = getAddress (b);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
cell.elevator = true;
|
cell.elevator = true;
|
||||||
cell.elevatorTo = HexFormatter.intValue (buffer[800 + b * 2], buffer[801 + b * 2]);
|
cell.elevatorTo =
|
||||||
cell.elevatorFrom = HexFormatter.intValue (buffer[832 + b * 2], buffer[833 + b * 2]);
|
HexFormatter.intValue (buffer[800 + b * 2], buffer[801 + b * 2]);
|
||||||
break;
|
cell.elevatorFrom =
|
||||||
case 9:
|
HexFormatter.intValue (buffer[832 + b * 2], buffer[833 + b * 2]);
|
||||||
cell.rock = true;
|
break;
|
||||||
break;
|
case 9:
|
||||||
case 10:
|
cell.rock = true;
|
||||||
cell.spellsBlocked = true;
|
break;
|
||||||
break;
|
case 10:
|
||||||
case 11:
|
cell.spellsBlocked = true;
|
||||||
int messageNum = HexFormatter.intValue (buffer[800 + b * 2], buffer[801 + b * 2]);
|
break;
|
||||||
for (Message m : messages)
|
case 11:
|
||||||
if (m.match (messageNum))
|
int messageNum = HexFormatter.intValue (buffer[800 + b * 2], buffer[801 + b * 2]);
|
||||||
{
|
if (messages != null)
|
||||||
cell.message = m;
|
for (Message m : messages)
|
||||||
break;
|
if (m.match (messageNum))
|
||||||
}
|
{
|
||||||
if (cell.message == null)
|
cell.message = m;
|
||||||
System.out.println ("message not found : " + messageNum);
|
break;
|
||||||
cell.messageType = HexFormatter.intValue (buffer[832 + b * 2], buffer[833 + b * 2]);
|
}
|
||||||
|
if (cell.message == null)
|
||||||
|
System.out.println ("message not found : " + messageNum);
|
||||||
|
cell.messageType =
|
||||||
|
HexFormatter.intValue (buffer[832 + b * 2], buffer[833 + b * 2]);
|
||||||
|
|
||||||
int itemID = -1;
|
int itemID = -1;
|
||||||
|
|
||||||
if (cell.messageType == 2) // obtain Item
|
if (cell.messageType == 2 && items != null) // obtain Item
|
||||||
{
|
{
|
||||||
itemID = HexFormatter.intValue (buffer[768 + b * 2], buffer[769 + b * 2]);
|
itemID = HexFormatter.intValue (buffer[768 + b * 2], buffer[769 + b * 2]);
|
||||||
cell.itemObtained = items.get (itemID);
|
cell.itemObtained = items.get (itemID);
|
||||||
}
|
}
|
||||||
if (cell.messageType == 5) // requires Item
|
|
||||||
{
|
|
||||||
itemID = HexFormatter.intValue (buffer[768 + b * 2], buffer[769 + b * 2]);
|
|
||||||
cell.itemRequired = items.get (itemID);
|
|
||||||
}
|
|
||||||
if (cell.messageType == 4)
|
|
||||||
{
|
|
||||||
value = HexFormatter.intValue (buffer[768 + b * 2], buffer[769 + b * 2]);
|
|
||||||
if (value <= 100)
|
|
||||||
{
|
|
||||||
cell.monsterID = value;
|
|
||||||
cell.monsters = monsters;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int val = (value - 64536) * -1;
|
|
||||||
System.out.println ("Value : " + val);
|
|
||||||
// this gives Index error: 20410, Size 104 in Wizardry_III/legacy2.dsk
|
|
||||||
if (val < items.size ())
|
|
||||||
cell.itemObtained = items.get (val); // check this
|
|
||||||
if (cell.itemObtained == null)
|
|
||||||
System.out.printf ("Item %d not found%n", val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 12:
|
|
||||||
cell.monsterID = HexFormatter.intValue (buffer[832 + b * 2], buffer[833 + b * 2]);
|
|
||||||
cell.monsters = monsters;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cell.unknown = d;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cell;
|
if (cell.messageType == 5 && items != null) // requires Item
|
||||||
}
|
{
|
||||||
|
itemID = HexFormatter.intValue (buffer[768 + b * 2], buffer[769 + b * 2]);
|
||||||
|
cell.itemRequired = items.get (itemID);
|
||||||
|
}
|
||||||
|
|
||||||
private MazeAddress getAddress (int a)
|
if (cell.messageType == 4)
|
||||||
{
|
{
|
||||||
int b = a * 2;
|
value = HexFormatter.intValue (buffer[768 + b * 2], buffer[769 + b * 2]);
|
||||||
return new MazeAddress (HexFormatter.intValue (buffer[768 + b], buffer[769 + b]), HexFormatter
|
if (value <= 100)
|
||||||
.intValue (buffer[800 + b], buffer[801 + b]), HexFormatter.intValue (buffer[832 + b],
|
{
|
||||||
buffer[833 + b]));
|
cell.monsterID = value;
|
||||||
}
|
cell.monsters = monsters;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int val = (value - 64536) * -1;
|
||||||
|
System.out.println ("Value : " + val);
|
||||||
|
// this gives Index error: 20410, Size 104 in Wizardry_III/legacy2.dsk
|
||||||
|
if (items != null && val < items.size ())
|
||||||
|
cell.itemObtained = items.get (val); // check this
|
||||||
|
if (cell.itemObtained == null)
|
||||||
|
System.out.printf ("Item %d not found%n", val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
cell.monsterID = HexFormatter.intValue (buffer[832 + b * 2], buffer[833 + b * 2]);
|
||||||
|
cell.monsters = monsters;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cell.unknown = d;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
public int getRows ()
|
return cell;
|
||||||
{
|
}
|
||||||
return 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getColumns ()
|
private MazeAddress getAddress (int a)
|
||||||
{
|
{
|
||||||
return 20;
|
int b = a * 2;
|
||||||
}
|
return new MazeAddress (HexFormatter.intValue (buffer[768 + b], buffer[769 + b]),
|
||||||
|
HexFormatter.intValue (buffer[800 + b], buffer[801 + b]),
|
||||||
|
HexFormatter.intValue (buffer[832 + b], buffer[833 + b]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRows ()
|
||||||
|
{
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getColumns ()
|
||||||
|
{
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
}
|
}
|
215
src/com/bytezone/diskbrowser/wizardry/Relocator.java
Normal file
215
src/com/bytezone/diskbrowser/wizardry/Relocator.java
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
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.HexFormatter;
|
||||||
|
|
||||||
|
public class Relocator extends AbstractFile
|
||||||
|
{
|
||||||
|
private final int checkByte;
|
||||||
|
private final List<DiskRecord> diskRecords = new ArrayList<DiskRecord> ();
|
||||||
|
|
||||||
|
private final int[] diskBlocks = new int[0x800];
|
||||||
|
private final int[] diskOffsets = new int[0x800];
|
||||||
|
|
||||||
|
public Relocator (String name, byte[] buffer)
|
||||||
|
{
|
||||||
|
super (name, buffer);
|
||||||
|
|
||||||
|
checkByte = HexFormatter.intValue (buffer[0], buffer[1]);
|
||||||
|
|
||||||
|
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)
|
||||||
|
addLogicalBlock ((byte) diskRecord.diskNumber, diskSegment);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addLogicalBlock (byte disk, DiskSegment diskSegment)
|
||||||
|
{
|
||||||
|
int lo = diskSegment.logicalBlock;
|
||||||
|
int hi = diskSegment.logicalBlock + diskSegment.segmentLength;
|
||||||
|
|
||||||
|
for (int i = lo, count = 0; i < hi; i++, count++)
|
||||||
|
// if (diskBlocks[i] == 0) // doesn't matter either way
|
||||||
|
{
|
||||||
|
diskBlocks[i] = disk;
|
||||||
|
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.readSector (diskOffsets[logicalBlock]);
|
||||||
|
DiskAddress da = master.getDiskAddress (logicalBlock);
|
||||||
|
master.writeSector (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> ();
|
||||||
|
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;
|
||||||
|
// boolean oddLines = lines.size () % 2 == 1;
|
||||||
|
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)));
|
||||||
|
|
||||||
|
return text.toString ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DiskRecord
|
||||||
|
{
|
||||||
|
int diskNumber;
|
||||||
|
int totDiskSegments;
|
||||||
|
List<DiskSegment> diskSegments = new ArrayList<DiskSegment> ();
|
||||||
|
|
||||||
|
public DiskRecord (byte[] buffer, int ptr)
|
||||||
|
{
|
||||||
|
diskNumber = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]);
|
||||||
|
totDiskSegments = HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 4]);
|
||||||
|
|
||||||
|
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 Skip Size Logical Physical%n"));
|
||||||
|
text.append (String.format (" --- ---- ---- ----------- -----------%n"));
|
||||||
|
|
||||||
|
int count = 1;
|
||||||
|
int last = 0;
|
||||||
|
int skip = 0;
|
||||||
|
|
||||||
|
for (DiskSegment segment : diskSegments)
|
||||||
|
{
|
||||||
|
if (segment.logicalBlock > last)
|
||||||
|
{
|
||||||
|
int end = segment.logicalBlock - 1;
|
||||||
|
skip = end - last + 1;
|
||||||
|
}
|
||||||
|
last = segment.logicalBlock + segment.segmentLength;
|
||||||
|
text.append (String.format (" %02X %04X %s %n", count++, skip, segment));
|
||||||
|
}
|
||||||
|
|
||||||
|
return text.toString ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DiskSegment
|
||||||
|
{
|
||||||
|
int logicalBlock;
|
||||||
|
int physicalBlock;
|
||||||
|
int segmentLength;
|
||||||
|
|
||||||
|
public DiskSegment (byte[] buffer, int ptr)
|
||||||
|
{
|
||||||
|
logicalBlock = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]);
|
||||||
|
physicalBlock = HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 3]);
|
||||||
|
segmentLength = HexFormatter.intValue (buffer[ptr + 4], buffer[ptr + 5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
return String.format (" %04X %04X - %04X %04X - %04X", segmentLength,
|
||||||
|
logicalBlock, (logicalBlock + segmentLength - 1), physicalBlock,
|
||||||
|
(physicalBlock + segmentLength - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
46
src/com/bytezone/diskbrowser/wizardry/Wiz4Image.java
Normal file
46
src/com/bytezone/diskbrowser/wizardry/Wiz4Image.java
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package com.bytezone.diskbrowser.wizardry;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.DataBuffer;
|
||||||
|
|
||||||
|
public class Wiz4Image extends AbstractImage
|
||||||
|
{
|
||||||
|
|
||||||
|
public Wiz4Image (String name, byte[] buffer)
|
||||||
|
{
|
||||||
|
super (name, buffer);
|
||||||
|
|
||||||
|
image = new BufferedImage (42, 40, BufferedImage.TYPE_BYTE_GRAY); // width/height
|
||||||
|
DataBuffer db = image.getRaster ().getDataBuffer ();
|
||||||
|
int element = 0;
|
||||||
|
|
||||||
|
// System.out.println (HexFormatter.format (buffer));
|
||||||
|
|
||||||
|
for (int row = 0; row < 5; row++)
|
||||||
|
{
|
||||||
|
for (int line = 0; line < 8; line++)
|
||||||
|
{
|
||||||
|
for (int col = 0; col < 6; col++)
|
||||||
|
{
|
||||||
|
int ptr = row * 48 + col * 8 + line;
|
||||||
|
{
|
||||||
|
byte b = buffer[ptr];
|
||||||
|
for (int bit = 0; bit < 7; bit++)
|
||||||
|
{
|
||||||
|
if ((b & 0x01) == 0x01)
|
||||||
|
{
|
||||||
|
db.setElem (element, 255);
|
||||||
|
// System.out.print ("X");
|
||||||
|
}
|
||||||
|
// else
|
||||||
|
// System.out.print (".");
|
||||||
|
b >>>= 1;
|
||||||
|
element++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// System.out.println ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,27 +6,33 @@ import java.util.List;
|
|||||||
import javax.swing.tree.DefaultMutableTreeNode;
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
import javax.swing.tree.DefaultTreeModel;
|
import javax.swing.tree.DefaultTreeModel;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.applefile.Relocator;
|
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||||
import com.bytezone.diskbrowser.disk.AppleDisk;
|
import com.bytezone.diskbrowser.disk.AppleDisk;
|
||||||
|
import com.bytezone.diskbrowser.disk.DefaultAppleFileSource;
|
||||||
import com.bytezone.diskbrowser.disk.Disk;
|
import com.bytezone.diskbrowser.disk.Disk;
|
||||||
|
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||||
|
import com.bytezone.diskbrowser.disk.SectorType;
|
||||||
import com.bytezone.diskbrowser.pascal.FileEntry;
|
import com.bytezone.diskbrowser.pascal.FileEntry;
|
||||||
import com.bytezone.diskbrowser.pascal.PascalDisk;
|
import com.bytezone.diskbrowser.pascal.PascalDisk;
|
||||||
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
import com.bytezone.diskbrowser.utilities.Utility;
|
import com.bytezone.diskbrowser.utilities.Utility;
|
||||||
|
|
||||||
public class Wizardry4BootDisk extends PascalDisk
|
public class Wizardry4BootDisk extends PascalDisk
|
||||||
{
|
{
|
||||||
List<AppleDisk> disks = new ArrayList<AppleDisk> ();
|
List<AppleDisk> disks = new ArrayList<AppleDisk> ();
|
||||||
protected Disk[] dataDisks;
|
// protected Disk[] dataDisks;
|
||||||
private Relocator relocator;
|
private Relocator relocator;
|
||||||
|
|
||||||
public Wizardry4BootDisk (AppleDisk[] dataDisks)
|
public Wizardry4BootDisk (AppleDisk[] dataDisks)
|
||||||
{
|
{
|
||||||
super (dataDisks[0]);
|
super (dataDisks[0]);
|
||||||
|
|
||||||
this.dataDisks = dataDisks;
|
// this.dataDisks = dataDisks;
|
||||||
|
|
||||||
DefaultTreeModel model = (DefaultTreeModel) catalogTree.getModel ();
|
DefaultTreeModel model = (DefaultTreeModel) catalogTree.getModel ();
|
||||||
DefaultMutableTreeNode currentRoot = (DefaultMutableTreeNode) model.getRoot ();
|
DefaultMutableTreeNode currentRoot = (DefaultMutableTreeNode) model.getRoot ();
|
||||||
|
|
||||||
|
// get the relocation table
|
||||||
DefaultMutableTreeNode relocNode = findNode (currentRoot, "SYSTEM.RELOC");
|
DefaultMutableTreeNode relocNode = findNode (currentRoot, "SYSTEM.RELOC");
|
||||||
FileEntry fileEntry = (FileEntry) relocNode.getUserObject ();
|
FileEntry fileEntry = (FileEntry) relocNode.getUserObject ();
|
||||||
|
|
||||||
@ -34,27 +40,90 @@ public class Wizardry4BootDisk extends PascalDisk
|
|||||||
{
|
{
|
||||||
relocator =
|
relocator =
|
||||||
new Relocator (fileEntry.getUniqueName (), fileEntry.getDataSource ().buffer);
|
new Relocator (fileEntry.getUniqueName (), fileEntry.getDataSource ().buffer);
|
||||||
relocator.createNewBuffer (dataDisks);
|
relocator.createNewBuffer (dataDisks); // create new data buffer
|
||||||
fileEntry.setFile (relocator);
|
fileEntry.setFile (relocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset the code segment so that it rebuilds itself from the new data
|
// reset the code segment so that it rebuilds itself from the new data
|
||||||
DefaultMutableTreeNode pascalNode = findNode (currentRoot, "SYSTEM.PASCAL");
|
DefaultMutableTreeNode pascalNode = findNode (currentRoot, "SYSTEM.PASCAL");
|
||||||
fileEntry = (FileEntry) pascalNode.getUserObject ();
|
fileEntry = (FileEntry) pascalNode.getUserObject ();
|
||||||
fileEntry.setFile (null);
|
|
||||||
fileEntry.getDataSource ();
|
if (fileEntry != null)
|
||||||
|
{
|
||||||
|
// fileEntry.setFile (null);
|
||||||
|
// fileEntry.getDataSource ();
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultMutableTreeNode scenarioNode = findNode (currentRoot, "SCENARIO.DATA");
|
||||||
|
fileEntry = (FileEntry) scenarioNode.getUserObject ();
|
||||||
|
|
||||||
|
if (fileEntry != null)
|
||||||
|
{
|
||||||
|
fileEntry.setFile (null);
|
||||||
|
scenarioNode.setAllowsChildren (true);
|
||||||
|
|
||||||
|
fileEntry.setFile (null);
|
||||||
|
byte[] buffer = fileEntry.getDataSource ().buffer;
|
||||||
|
|
||||||
|
for (int i = 0; i < 11; i++)
|
||||||
|
{
|
||||||
|
byte[] level = new byte[896];
|
||||||
|
System.out.println (HexFormatter.format (buffer, 0, 512));
|
||||||
|
System.arraycopy (buffer, 0xC600 + i * 1024, level, 0, level.length);
|
||||||
|
MazeLevel maze = new MazeLevel (level, i);
|
||||||
|
|
||||||
|
List<DiskAddress> blocks = new ArrayList<DiskAddress> ();
|
||||||
|
addToNode (maze, scenarioNode, blocks, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultMutableTreeNode monstersNode = findNode (currentRoot, "200.MONSTERS");
|
||||||
|
fileEntry = (FileEntry) monstersNode.getUserObject ();
|
||||||
|
|
||||||
|
if (fileEntry != null)
|
||||||
|
{
|
||||||
|
monstersNode.setAllowsChildren (true);
|
||||||
|
byte[] pictureBuffer = fileEntry.getDataSource ().buffer;
|
||||||
|
List<DiskAddress> pictureBlocks = fileEntry.getSectors ();
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
loop: for (int block = 0; block < 24; block++)
|
||||||
|
{
|
||||||
|
int ptr = block * 512;
|
||||||
|
for (int pic = 0; pic < 2; pic++)
|
||||||
|
{
|
||||||
|
byte[] buffer = new byte[240];
|
||||||
|
System.arraycopy (pictureBuffer, ptr + pic * 256, buffer, 0, 240);
|
||||||
|
Wiz4Image image = new Wiz4Image ("Image " + count++, buffer);
|
||||||
|
List<DiskAddress> blocks = new ArrayList<DiskAddress> ();
|
||||||
|
blocks.add (pictureBlocks.get (block));
|
||||||
|
addToNode (image, monstersNode, blocks, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isWizardryIV (Disk disk, boolean debug)
|
private void addToNode (AbstractFile af, DefaultMutableTreeNode node,
|
||||||
|
List<DiskAddress> blocks, SectorType type)
|
||||||
{
|
{
|
||||||
|
DefaultAppleFileSource dafs =
|
||||||
|
new DefaultAppleFileSource (af.getName (), af, this, blocks);
|
||||||
|
DefaultMutableTreeNode childNode = new DefaultMutableTreeNode (dafs);
|
||||||
|
node.add (childNode);
|
||||||
|
childNode.setAllowsChildren (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isWizardryIVorV (Disk disk, boolean debug)
|
||||||
|
{
|
||||||
|
// Wizardry IV or V boot code
|
||||||
byte[] header = { 0x00, (byte) 0xEA, (byte) 0xA9, 0x60, (byte) 0x8D, 0x01, 0x08 };
|
byte[] header = { 0x00, (byte) 0xEA, (byte) 0xA9, 0x60, (byte) 0x8D, 0x01, 0x08 };
|
||||||
byte[] buffer = disk.readSector (0);
|
byte[] buffer = disk.readSector (0);
|
||||||
|
|
||||||
if (!Utility.matches (buffer, 0, header))
|
if (!Utility.matches (buffer, 0, header))
|
||||||
return false;
|
return false;
|
||||||
buffer = disk.readSector (1);
|
|
||||||
|
|
||||||
if (buffer[510] != 1)
|
buffer = disk.readSector (1);
|
||||||
|
if (buffer[510] != 1 || buffer[511] != 0) // disk #1
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -485,7 +485,8 @@ public class WizardryScenarioDisk extends PascalDisk
|
|||||||
nodeSectors.addAll (blocks);
|
nodeSectors.addAll (blocks);
|
||||||
byte[] buffer = disk.readSectors (blocks);
|
byte[] buffer = disk.readSectors (blocks);
|
||||||
byte[] data2 = new byte[896];
|
byte[] data2 = new byte[896];
|
||||||
System.arraycopy (buffer, 0, data2, 0, 896);
|
System.arraycopy (buffer, 0, data2, 0, data2.length);
|
||||||
|
// System.out.println (HexFormatter.format (data2));
|
||||||
|
|
||||||
MazeLevel model = new MazeLevel (data2, i + 1);
|
MazeLevel model = new MazeLevel (data2, i + 1);
|
||||||
model.setMessages (messages);
|
model.setMessages (messages);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user