2016-08-08 04:53:29 +00:00
|
|
|
package com.bytezone.diskbrowser.wizardry;
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
|
|
|
|
2016-08-09 04:15:44 +00:00
|
|
|
import javax.swing.tree.DefaultMutableTreeNode;
|
|
|
|
import javax.swing.tree.DefaultTreeModel;
|
|
|
|
|
2016-08-14 08:41:19 +00:00
|
|
|
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
2016-08-08 04:53:29 +00:00
|
|
|
import com.bytezone.diskbrowser.disk.AppleDisk;
|
2016-08-14 08:41:19 +00:00
|
|
|
import com.bytezone.diskbrowser.disk.DefaultAppleFileSource;
|
2016-08-08 04:53:29 +00:00
|
|
|
import com.bytezone.diskbrowser.disk.Disk;
|
2016-08-14 08:41:19 +00:00
|
|
|
import com.bytezone.diskbrowser.disk.DiskAddress;
|
2016-08-09 04:15:44 +00:00
|
|
|
import com.bytezone.diskbrowser.pascal.FileEntry;
|
2016-08-08 04:53:29 +00:00
|
|
|
import com.bytezone.diskbrowser.pascal.PascalDisk;
|
|
|
|
import com.bytezone.diskbrowser.utilities.Utility;
|
2016-08-16 06:34:23 +00:00
|
|
|
import com.bytezone.diskbrowser.wizardry.Header.ScenarioData;
|
2016-08-08 04:53:29 +00:00
|
|
|
|
|
|
|
public class Wizardry4BootDisk extends PascalDisk
|
|
|
|
{
|
2016-08-16 06:34:23 +00:00
|
|
|
public Header scenarioHeader;
|
2016-08-08 04:53:29 +00:00
|
|
|
List<AppleDisk> disks = new ArrayList<AppleDisk> ();
|
2016-08-14 08:41:19 +00:00
|
|
|
// protected Disk[] dataDisks;
|
2016-08-09 04:15:44 +00:00
|
|
|
private Relocator relocator;
|
2016-08-16 06:34:23 +00:00
|
|
|
private MessageBlock messageBlock;
|
2016-08-08 04:53:29 +00:00
|
|
|
|
|
|
|
public Wizardry4BootDisk (AppleDisk[] dataDisks)
|
|
|
|
{
|
2016-08-09 04:15:44 +00:00
|
|
|
super (dataDisks[0]);
|
|
|
|
|
2016-08-14 08:41:19 +00:00
|
|
|
// this.dataDisks = dataDisks;
|
2016-08-09 04:15:44 +00:00
|
|
|
|
|
|
|
DefaultTreeModel model = (DefaultTreeModel) catalogTree.getModel ();
|
|
|
|
DefaultMutableTreeNode currentRoot = (DefaultMutableTreeNode) model.getRoot ();
|
2016-08-14 08:41:19 +00:00
|
|
|
|
|
|
|
// get the relocation table
|
2016-08-09 04:15:44 +00:00
|
|
|
DefaultMutableTreeNode relocNode = findNode (currentRoot, "SYSTEM.RELOC");
|
|
|
|
FileEntry fileEntry = (FileEntry) relocNode.getUserObject ();
|
|
|
|
if (fileEntry != null)
|
|
|
|
{
|
|
|
|
relocator =
|
|
|
|
new Relocator (fileEntry.getUniqueName (), fileEntry.getDataSource ().buffer);
|
2016-08-14 08:41:19 +00:00
|
|
|
relocator.createNewBuffer (dataDisks); // create new data buffer
|
2016-08-09 04:15:44 +00:00
|
|
|
fileEntry.setFile (relocator);
|
|
|
|
}
|
2016-08-09 09:09:11 +00:00
|
|
|
|
|
|
|
// reset the code segment so that it rebuilds itself from the new data
|
|
|
|
DefaultMutableTreeNode pascalNode = findNode (currentRoot, "SYSTEM.PASCAL");
|
|
|
|
fileEntry = (FileEntry) pascalNode.getUserObject ();
|
2016-08-14 08:41:19 +00:00
|
|
|
if (fileEntry != null)
|
|
|
|
{
|
2016-08-14 08:50:41 +00:00
|
|
|
fileEntry.setFile (null);
|
|
|
|
fileEntry.getDataSource ();
|
2016-08-14 08:41:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DefaultMutableTreeNode scenarioNode = findNode (currentRoot, "SCENARIO.DATA");
|
|
|
|
fileEntry = (FileEntry) scenarioNode.getUserObject ();
|
|
|
|
if (fileEntry != null)
|
|
|
|
{
|
|
|
|
fileEntry.setFile (null);
|
2016-08-16 06:34:23 +00:00
|
|
|
|
2016-08-14 08:41:19 +00:00
|
|
|
scenarioNode.setAllowsChildren (true);
|
2016-08-16 06:34:23 +00:00
|
|
|
scenarioHeader = new Header (scenarioNode, this);
|
|
|
|
linkMazeLevels (scenarioNode, fileEntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
DefaultMutableTreeNode monstersNode = findNode (currentRoot, "200.MONSTERS");
|
|
|
|
fileEntry = (FileEntry) monstersNode.getUserObject ();
|
|
|
|
if (fileEntry != null)
|
|
|
|
{
|
|
|
|
fileEntry.setFile (null);
|
|
|
|
|
|
|
|
monstersNode.setAllowsChildren (true);
|
|
|
|
linkMonsterImages (monstersNode, fileEntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
DefaultMutableTreeNode messagesNode = findNode (currentRoot, "ASCII.KRN");
|
|
|
|
fileEntry = (FileEntry) messagesNode.getUserObject ();
|
|
|
|
if (fileEntry != null)
|
|
|
|
{
|
|
|
|
messageBlock = new MessageBlock (fileEntry.getDataSource ().buffer);
|
2016-08-16 08:58:42 +00:00
|
|
|
messagesNode.setAllowsChildren (true);
|
|
|
|
for (MessageDataBlock mdb : messageBlock)
|
|
|
|
{
|
|
|
|
List<DiskAddress> messageBlocks = new ArrayList<DiskAddress> ();
|
|
|
|
addToNode (mdb, messagesNode, messageBlocks);
|
|
|
|
}
|
2016-08-16 06:34:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DefaultMutableTreeNode huffNode = findNode (currentRoot, "ASCII.HUFF");
|
|
|
|
fileEntry = (FileEntry) huffNode.getUserObject ();
|
|
|
|
if (fileEntry != null)
|
|
|
|
{
|
2016-08-14 08:41:19 +00:00
|
|
|
|
|
|
|
byte[] buffer = fileEntry.getDataSource ().buffer;
|
|
|
|
|
2016-08-17 02:20:00 +00:00
|
|
|
Huffman huffman = new Huffman ("Huffman tree", buffer);
|
2016-08-16 08:58:42 +00:00
|
|
|
messageBlock.setHuffman (huffman);
|
2016-08-17 02:20:00 +00:00
|
|
|
fileEntry.setFile (huffman);
|
2016-08-14 08:41:19 +00:00
|
|
|
}
|
2016-08-16 06:34:23 +00:00
|
|
|
}
|
2016-08-14 08:41:19 +00:00
|
|
|
|
2016-08-16 06:34:23 +00:00
|
|
|
private void linkMazeLevels (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
|
|
|
|
{
|
|
|
|
ScenarioData mazeData = scenarioHeader.data.get (Header.MAZE_AREA);
|
2016-08-14 08:41:19 +00:00
|
|
|
|
2016-08-16 06:34:23 +00:00
|
|
|
byte[] buffer = fileEntry.getDataSource ().buffer;
|
|
|
|
List<DiskAddress> blocks = fileEntry.getSectors ();
|
|
|
|
|
|
|
|
DefaultMutableTreeNode mazeNode = linkNode ("Maze", "Levels string", scenarioNode);
|
|
|
|
for (int i = 0; i < 15; i++)
|
2016-08-14 08:41:19 +00:00
|
|
|
{
|
2016-08-16 06:34:23 +00:00
|
|
|
byte[] level = new byte[896];
|
|
|
|
System.arraycopy (buffer, mazeData.dataOffset * 512 + i * 1024, level, 0,
|
|
|
|
level.length);
|
|
|
|
|
|
|
|
List<DiskAddress> mazeBlocks = new ArrayList<DiskAddress> ();
|
|
|
|
int ptr = mazeData.dataOffset + i * 2;
|
|
|
|
mazeBlocks.add (blocks.get (ptr));
|
|
|
|
mazeBlocks.add (blocks.get (ptr + 1));
|
|
|
|
addToNode (new MazeLevel (level, i), mazeNode, mazeBlocks);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void linkMonsterImages (DefaultMutableTreeNode monstersNode,
|
|
|
|
FileEntry fileEntry)
|
|
|
|
{
|
|
|
|
byte[] pictureBuffer = fileEntry.getDataSource ().buffer;
|
|
|
|
List<DiskAddress> pictureBlocks = fileEntry.getSectors ();
|
2016-08-14 08:41:19 +00:00
|
|
|
|
2016-08-16 06:34:23 +00:00
|
|
|
int count = 0;
|
|
|
|
for (int block = 0; block < 24; block++)
|
|
|
|
{
|
|
|
|
int ptr = block * 512;
|
|
|
|
for (int pic = 0; pic < 2; pic++)
|
2016-08-14 08:41:19 +00:00
|
|
|
{
|
2016-08-16 06:34:23 +00:00
|
|
|
byte[] buffer = new byte[240];
|
|
|
|
System.arraycopy (pictureBuffer, ptr + pic * 256, buffer, 0, 240);
|
|
|
|
Wiz4Image image = new Wiz4Image ("Image " + count++, buffer);
|
|
|
|
List<DiskAddress> monsterBlocks = new ArrayList<DiskAddress> ();
|
|
|
|
monsterBlocks.add (pictureBlocks.get (block));
|
|
|
|
addToNode (image, monstersNode, monsterBlocks);
|
2016-08-14 08:41:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void addToNode (AbstractFile af, DefaultMutableTreeNode node,
|
2016-08-16 06:34:23 +00:00
|
|
|
List<DiskAddress> blocks)
|
2016-08-14 08:41:19 +00:00
|
|
|
{
|
|
|
|
DefaultAppleFileSource dafs =
|
|
|
|
new DefaultAppleFileSource (af.getName (), af, this, blocks);
|
|
|
|
DefaultMutableTreeNode childNode = new DefaultMutableTreeNode (dafs);
|
|
|
|
node.add (childNode);
|
|
|
|
childNode.setAllowsChildren (false);
|
2016-08-08 04:53:29 +00:00
|
|
|
}
|
|
|
|
|
2016-08-16 06:34:23 +00:00
|
|
|
private DefaultMutableTreeNode linkNode (String name, String text,
|
|
|
|
DefaultMutableTreeNode parent)
|
|
|
|
{
|
|
|
|
DefaultAppleFileSource afs = new DefaultAppleFileSource (name, text, this);
|
|
|
|
DefaultMutableTreeNode node = new DefaultMutableTreeNode (afs);
|
|
|
|
parent.add (node);
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2016-08-14 08:41:19 +00:00
|
|
|
public static boolean isWizardryIVorV (Disk disk, boolean debug)
|
2016-08-08 04:53:29 +00:00
|
|
|
{
|
2016-08-14 08:41:19 +00:00
|
|
|
// Wizardry IV or V boot code
|
2016-08-08 04:53:29 +00:00
|
|
|
byte[] header = { 0x00, (byte) 0xEA, (byte) 0xA9, 0x60, (byte) 0x8D, 0x01, 0x08 };
|
|
|
|
byte[] buffer = disk.readSector (0);
|
|
|
|
|
|
|
|
if (!Utility.matches (buffer, 0, header))
|
|
|
|
return false;
|
|
|
|
|
2016-08-14 08:41:19 +00:00
|
|
|
buffer = disk.readSector (1);
|
|
|
|
if (buffer[510] != 1 || buffer[511] != 0) // disk #1
|
2016-08-08 04:53:29 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|