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

238 lines
8.0 KiB
Java
Raw Normal View History

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-19 09:57:29 +00:00
private final List<AppleDisk> disks = new ArrayList<AppleDisk> ();
2016-08-09 04:15:44 +00:00
private Relocator relocator;
2016-08-16 06:34:23 +00:00
private MessageBlock messageBlock;
2016-08-18 06:35:54 +00:00
private Huffman huffman;
2016-08-19 09:57:29 +00:00
private final int version;
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-19 09:57:29 +00:00
version = dataDisks.length == 6 ? 4 : dataDisks.length == 10 ? 5 : 0;
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
}
2016-08-19 09:57:29 +00:00
if (version == 4)
2016-08-14 08:41:19 +00:00
{
2016-08-19 09:57:29 +00:00
DefaultMutableTreeNode scenarioNode = findNode (currentRoot, "SCENARIO.DATA");
2016-08-22 03:41:43 +00:00
fileEntry = (FileEntry) scenarioNode.getUserObject ();
if (fileEntry != null)
2016-08-19 09:57:29 +00:00
{
2016-08-22 03:41:43 +00:00
fileEntry.setFile (null);
scenarioNode.setAllowsChildren (true);
scenarioHeader = new Header (scenarioNode, this);
linkMazeLevels4 (scenarioNode, fileEntry);
2016-08-19 09:57:29 +00:00
}
2016-08-16 06:34:23 +00:00
}
2016-08-19 09:57:29 +00:00
else if (version == 5)
2016-08-16 06:34:23 +00:00
{
2016-08-19 09:57:29 +00:00
DefaultMutableTreeNode scenarioNode = findNode (currentRoot, "DRAGON.DATA");
2016-08-22 03:41:43 +00:00
fileEntry = (FileEntry) scenarioNode.getUserObject ();
if (fileEntry != null)
{
fileEntry.setFile (null);
scenarioNode.setAllowsChildren (true);
linkMazeLevels5 (scenarioNode, fileEntry);
}
2016-08-19 09:57:29 +00:00
}
2016-08-16 06:34:23 +00:00
2016-08-19 09:57:29 +00:00
if (version == 4)
{
DefaultMutableTreeNode monstersNode = findNode (currentRoot, "200.MONSTERS");
fileEntry = (FileEntry) monstersNode.getUserObject ();
if (fileEntry != null)
{
fileEntry.setFile (null);
monstersNode.setAllowsChildren (true);
linkMonsterImages4 (monstersNode, fileEntry);
}
2016-08-16 06:34:23 +00:00
}
2016-08-22 03:41:43 +00:00
else if (version == 5)
{
DefaultMutableTreeNode monstersNode = findNode (currentRoot, "200.MONSTERS");
fileEntry = (FileEntry) monstersNode.getUserObject ();
if (fileEntry != null)
{
Wiz5Monsters w5monsters =
new Wiz5Monsters ("monsters", fileEntry.getDataSource ().buffer);
fileEntry.setFile (w5monsters);
monstersNode.setAllowsChildren (true);
for (Wiz4Image image : w5monsters.images)
{
List<DiskAddress> monsterBlocks = new ArrayList<DiskAddress> ();
// monsterBlocks.add (pictureBlocks.get (block));
addToNode (image, monstersNode, monsterBlocks);
}
}
}
2016-08-16 06:34:23 +00:00
2016-08-18 06:35:54 +00:00
DefaultMutableTreeNode huffNode = findNode (currentRoot, "ASCII.HUFF");
fileEntry = (FileEntry) huffNode.getUserObject ();
if (fileEntry != null)
{
byte[] buffer = fileEntry.getDataSource ().buffer;
huffman = new Huffman ("Huffman tree", buffer);
fileEntry.setFile (huffman);
}
2016-08-16 06:34:23 +00:00
DefaultMutableTreeNode messagesNode = findNode (currentRoot, "ASCII.KRN");
fileEntry = (FileEntry) messagesNode.getUserObject ();
if (fileEntry != null)
{
2016-08-18 06:35:54 +00:00
messageBlock = new MessageBlock (fileEntry.getDataSource ().buffer, huffman);
2016-08-22 03:41:43 +00:00
fileEntry.setFile (messageBlock);
2016-08-16 08:58:42 +00:00
messagesNode.setAllowsChildren (true);
2016-08-19 09:57:29 +00:00
List<DiskAddress> blocks = fileEntry.getSectors ();
int count = 0;
2016-08-16 08:58:42 +00:00
for (MessageDataBlock mdb : messageBlock)
{
List<DiskAddress> messageBlocks = new ArrayList<DiskAddress> ();
2016-08-19 09:57:29 +00:00
messageBlocks.add (blocks.get (count++));
2016-08-16 08:58:42 +00:00
addToNode (mdb, messagesNode, messageBlocks);
}
2016-08-16 06:34:23 +00:00
}
}
2016-08-14 08:41:19 +00:00
2016-08-19 09:57:29 +00:00
private void linkMazeLevels4 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
2016-08-16 06:34:23 +00:00
{
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-22 03:41:43 +00:00
byte[] level = new byte[0x380]; // 896
2016-08-19 09:57:29 +00:00
int offset = mazeData.dataOffset * 512 + i * 1024;
2016-08-22 03:41:43 +00:00
System.arraycopy (buffer, offset, level, 0, level.length);
2016-08-19 09:57:29 +00:00
2016-08-22 03:41:43 +00:00
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 linkMazeLevels5 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
{
byte[] buffer = fileEntry.getDataSource ().buffer;
List<DiskAddress> blocks = fileEntry.getSectors ();
DefaultMutableTreeNode mazeNode = linkNode ("Maze", "Level 5 mazes", scenarioNode);
for (int i = 0; i < 8; i++)
{
int offset = 6144 + i * 256;
byte[] data = new byte[256];
System.arraycopy (buffer, offset, data, 0, data.length);
MazeGridV5 grid = new MazeGridV5 ("test level " + i, data);
List<DiskAddress> mazeBlocks = new ArrayList<DiskAddress> ();
addToNode (grid, mazeNode, mazeBlocks);
2016-08-16 06:34:23 +00:00
}
}
2016-08-19 09:57:29 +00:00
private void linkMonsterImages4 (DefaultMutableTreeNode monstersNode,
2016-08-16 06:34:23 +00:00
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];
2016-08-22 03:41:43 +00:00
System.arraycopy (pictureBuffer, ptr + pic * 256, buffer, 0, buffer.length);
Wiz4Image image = new Wiz4Image ("Image " + count++, buffer, 5, 6);
2016-08-16 06:34:23 +00:00
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);
childNode.setAllowsChildren (false);
2016-08-19 09:57:29 +00:00
node.add (childNode);
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;
}
}