Wiz 4 maps

This commit is contained in:
Denis Molony 2016-08-14 18:41:19 +10:00
parent 2036ca4b96
commit c0adaef3e2
12 changed files with 620 additions and 645 deletions

View File

@ -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 ()
{ {

View File

@ -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;
}
}
}

View File

@ -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)

View File

@ -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);
}
} }

View File

@ -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)
{ {

View File

@ -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);

View File

@ -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

View File

@ -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;
}
} }

View 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));
}
}
}

View 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 ();
}
}
}
}

View File

@ -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;

View File

@ -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);