2020-02-11 07:29:55 +00:00
|
|
|
package com.bytezone.diskbrowser.wizardry;
|
|
|
|
|
|
|
|
import java.awt.Color;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
import javax.swing.tree.DefaultMutableTreeNode;
|
|
|
|
import javax.swing.tree.DefaultTreeModel;
|
|
|
|
|
|
|
|
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
|
|
|
import com.bytezone.diskbrowser.applefile.AppleFileSource;
|
|
|
|
import com.bytezone.diskbrowser.disk.DefaultAppleFileSource;
|
|
|
|
import com.bytezone.diskbrowser.disk.DefaultDataSource;
|
|
|
|
import com.bytezone.diskbrowser.disk.Disk;
|
|
|
|
import com.bytezone.diskbrowser.disk.DiskAddress;
|
|
|
|
import com.bytezone.diskbrowser.disk.SectorType;
|
|
|
|
import com.bytezone.diskbrowser.gui.DataSource;
|
|
|
|
import com.bytezone.diskbrowser.pascal.PascalDisk;
|
|
|
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
2020-06-26 03:29:46 +00:00
|
|
|
import com.bytezone.diskbrowser.utilities.Utility;
|
2020-02-11 07:29:55 +00:00
|
|
|
import com.bytezone.diskbrowser.wizardry.Character.Attributes;
|
|
|
|
import com.bytezone.diskbrowser.wizardry.Character.Statistics;
|
|
|
|
import com.bytezone.diskbrowser.wizardry.Header.ScenarioData;
|
|
|
|
import com.bytezone.diskbrowser.wizardry.Spell.SpellType;
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
public class WizardryScenarioDisk extends PascalDisk
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
public Header scenarioHeader;
|
|
|
|
|
|
|
|
public List<AbstractImage> images;
|
|
|
|
public List<Item> items;
|
|
|
|
public List<Character> characters;
|
|
|
|
public List<Spell> spells;
|
2022-05-28 02:59:25 +00:00
|
|
|
public List<MessageV1> messages;
|
2020-02-11 07:29:55 +00:00
|
|
|
public List<Monster> monsters;
|
|
|
|
public List<MazeLevel> levels;
|
|
|
|
List<ExperienceLevel> experiences;
|
|
|
|
List<Reward> rewards;
|
|
|
|
|
|
|
|
// leave these here until I decide whether to use them or not
|
|
|
|
SectorType mazeSector = new SectorType ("Maze", Color.lightGray);
|
|
|
|
SectorType monsterSector = new SectorType ("Monsters", Color.black);
|
|
|
|
SectorType itemSector = new SectorType ("Items", Color.blue);
|
|
|
|
SectorType characterSector = new SectorType ("Characters", Color.magenta);
|
|
|
|
SectorType spellSector = new SectorType ("Spells", Color.orange);
|
|
|
|
SectorType messageSector = new SectorType ("Messages", Color.cyan);
|
|
|
|
SectorType imageSector = new SectorType ("Images", Color.red);
|
|
|
|
SectorType experienceSector = new SectorType ("Experience", Color.darkGray);
|
|
|
|
SectorType treasureSector = new SectorType ("Treasure", Color.pink);
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
public WizardryScenarioDisk (Disk disk)
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
super (disk);
|
|
|
|
|
|
|
|
if (false)
|
|
|
|
{
|
|
|
|
sectorTypesList.add (mazeSector);
|
|
|
|
sectorTypesList.add (monsterSector);
|
|
|
|
sectorTypesList.add (itemSector);
|
|
|
|
sectorTypesList.add (characterSector);
|
|
|
|
sectorTypesList.add (spellSector);
|
|
|
|
sectorTypesList.add (messageSector);
|
|
|
|
sectorTypesList.add (imageSector);
|
|
|
|
sectorTypesList.add (experienceSector);
|
|
|
|
sectorTypesList.add (treasureSector);
|
|
|
|
}
|
|
|
|
|
|
|
|
CodedMessage.codeOffset = 185;
|
|
|
|
Monster.counter = 0;
|
|
|
|
Item.counter = 0;
|
|
|
|
|
|
|
|
DefaultTreeModel model = (DefaultTreeModel) catalogTree.getModel ();
|
|
|
|
DefaultMutableTreeNode currentRoot = (DefaultMutableTreeNode) model.getRoot ();
|
|
|
|
DefaultMutableTreeNode dataNode = findNode (currentRoot, "SCENARIO.DATA");
|
|
|
|
DefaultMutableTreeNode msgNode = findNode (currentRoot, "SCENARIO.MESGS");
|
|
|
|
if (dataNode == null || msgNode == null)
|
|
|
|
{
|
|
|
|
System.out.println ("Wizardry data or msg node not found");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
dataNode.setAllowsChildren (true);
|
|
|
|
msgNode.setAllowsChildren (true);
|
|
|
|
|
|
|
|
scenarioHeader = new Header (dataNode, this);
|
|
|
|
|
|
|
|
// Process SCENARIO.MESGS (requires scenario)
|
|
|
|
AppleFileSource afs = (AppleFileSource) msgNode.getUserObject ();
|
|
|
|
// DefaultMutableTreeNode node = linkNode ("Messages", "Messages string", msgNode);
|
|
|
|
extractMessages (msgNode, afs.getSectors ());
|
|
|
|
// makeNodeVisible (node);
|
|
|
|
|
|
|
|
// Process SCENARIO.DATA (requires scenario and messages)
|
|
|
|
afs = (AppleFileSource) dataNode.getUserObject ();
|
|
|
|
List<DiskAddress> sectors = afs.getSectors ();
|
|
|
|
|
|
|
|
extractItems (linkNode ("Items", "Items string", dataNode), sectors);
|
|
|
|
extractRewards (linkNode ("Rewards", "Treasure string", dataNode), sectors);
|
|
|
|
extractMonsters (linkNode ("Monsters", "Monsters string", dataNode), sectors);
|
|
|
|
extractCharacters (linkNode ("Characters", "Characters string", dataNode), sectors);
|
|
|
|
extractImages (linkNode ("Images", "Images string", dataNode), sectors);
|
2022-03-10 06:21:18 +00:00
|
|
|
extractExperienceLevels (linkNode ("Experience", "Experience string", dataNode), sectors);
|
2020-02-11 07:29:55 +00:00
|
|
|
// node = linkNode ("Spells", "Spells string", dataNode);
|
|
|
|
DefaultMutableTreeNode node = null;
|
|
|
|
extractSpells (node, sectors);
|
|
|
|
extractLevels (linkNode ("Maze", "Levels string", dataNode), sectors);
|
|
|
|
// Make the Spells node (and its siblings) visible
|
|
|
|
// makeNodeVisible (node);
|
|
|
|
|
|
|
|
// add information about each characters' baggage, spells known etc.
|
|
|
|
for (Character c : characters)
|
|
|
|
{
|
|
|
|
c.linkItems (items);
|
|
|
|
c.linkSpells (spells);
|
|
|
|
int type = c.getStatistics ().typeInt;
|
|
|
|
c.linkExperience (experiences.get (type));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
2022-03-10 06:21:18 +00:00
|
|
|
private DefaultMutableTreeNode linkNode (String name, String text, DefaultMutableTreeNode parent)
|
2020-02-11 07:29:55 +00:00
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
DefaultAppleFileSource afs = new DefaultAppleFileSource (name, text, this);
|
|
|
|
DefaultMutableTreeNode node = new DefaultMutableTreeNode (afs);
|
|
|
|
parent.add (node);
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
public static boolean isWizardryFormat (Disk disk, boolean debug)
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
2020-04-10 23:47:52 +00:00
|
|
|
byte[] buffer = disk.readBlock (2);
|
2021-05-19 08:13:17 +00:00
|
|
|
int totalFiles = Utility.getShort (buffer, 16);
|
2022-05-27 08:30:30 +00:00
|
|
|
|
2020-02-11 07:29:55 +00:00
|
|
|
if (totalFiles != 3)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (int i = 1, ptr = 32; i <= totalFiles; i++, ptr += 26)
|
|
|
|
{
|
|
|
|
String text = HexFormatter.getPascalString (buffer, ptr);
|
|
|
|
if (!text.equals ("SCENARIO.DATA") && !text.equals ("SCENARIO.MESGS")
|
|
|
|
&& !text.equals ("WIZARDRY.CODE"))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
@Override
|
|
|
|
public AppleFileSource getFile (String fileName)
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
// System.out.println ("Wizardry disk looking for : " + fileName);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
public String getCatalogText ()
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
@Override
|
|
|
|
public List<DiskAddress> getFileSectors (int fileNo)
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
@Override
|
|
|
|
public DataSource getFile (int fileNo)
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
private void extractRewards (DefaultMutableTreeNode node, List<DiskAddress> sectors)
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
List<DiskAddress> nodeSectors = new ArrayList<> ();
|
|
|
|
ScenarioData sd = scenarioHeader.data.get (Header.TREASURE_TABLE_AREA);
|
|
|
|
rewards = new ArrayList<> (sd.total);
|
|
|
|
int max = sd.totalBlocks / 2;
|
|
|
|
|
|
|
|
int seq = 0;
|
|
|
|
for (int i = 0; i < max; i++)
|
|
|
|
{
|
|
|
|
List<DiskAddress> blocks = getTwoBlocks (sd, i, sectors);
|
|
|
|
nodeSectors.addAll (blocks);
|
2020-04-10 23:47:52 +00:00
|
|
|
byte[] buffer = disk.readBlocks (blocks);
|
2020-02-11 07:29:55 +00:00
|
|
|
seq = addReward (buffer, blocks, node, seq);
|
|
|
|
}
|
|
|
|
|
|
|
|
StringBuilder text = new StringBuilder ();
|
|
|
|
for (Reward t : rewards)
|
|
|
|
text.append (t.getDump () + "\n");
|
|
|
|
|
|
|
|
DefaultAppleFileSource afs = (DefaultAppleFileSource) node.getUserObject ();
|
|
|
|
afs.setSectors (nodeSectors);
|
|
|
|
DefaultDataSource dds = (DefaultDataSource) afs.getDataSource ();
|
|
|
|
dds.text = text.toString ();
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
2022-03-10 06:21:18 +00:00
|
|
|
private int addReward (byte[] buffer, List<DiskAddress> blocks, DefaultMutableTreeNode node,
|
|
|
|
int seq)
|
2020-02-11 07:29:55 +00:00
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
int recLen = 168;
|
|
|
|
for (int ptr = 0; ptr < 1008; ptr += recLen)
|
|
|
|
{
|
|
|
|
byte[] data2 = new byte[recLen];
|
|
|
|
System.arraycopy (buffer, ptr, data2, 0, recLen);
|
|
|
|
|
|
|
|
Reward tt = new Reward ("Type " + seq, data2, seq++, items);
|
|
|
|
rewards.add (tt);
|
|
|
|
addToNode (tt, node, blocks, treasureSector);
|
|
|
|
}
|
|
|
|
return seq;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
private void extractCharacters (DefaultMutableTreeNode node, List<DiskAddress> sectors)
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
List<DiskAddress> nodeSectors = new ArrayList<> ();
|
|
|
|
ScenarioData sd = scenarioHeader.data.get (Header.CHARACTER_AREA);
|
|
|
|
characters = new ArrayList<> (sd.total);
|
|
|
|
int max = sd.totalBlocks / 2;
|
2022-03-10 06:21:18 +00:00
|
|
|
// if (max < sd.total)
|
|
|
|
// System.out.println ("Characters short in Wizardry disk");
|
2020-02-11 07:29:55 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < max; i++)
|
|
|
|
{
|
|
|
|
List<DiskAddress> blocks = getTwoBlocks (sd, i, sectors);
|
|
|
|
nodeSectors.addAll (blocks);
|
2020-04-10 23:47:52 +00:00
|
|
|
byte[] buffer = disk.readBlocks (blocks);
|
2020-02-11 07:29:55 +00:00
|
|
|
addCharacters (buffer, blocks, node);
|
|
|
|
}
|
|
|
|
|
|
|
|
StringBuilder text = new StringBuilder ();
|
|
|
|
text.append ("Name Age Align Race Type "
|
|
|
|
+ "HP St In Pi Vi Ag Lu Status\n");
|
|
|
|
text.append ("------------- ---- -------- -------- ---------- "
|
|
|
|
+ "-- -- -- -- -- -- -- ------\n");
|
|
|
|
for (Character ch : characters)
|
|
|
|
{
|
|
|
|
Statistics stats = ch.getStatistics ();
|
|
|
|
Attributes att = ch.getAttributes ();
|
2022-03-10 06:21:18 +00:00
|
|
|
text.append (String.format ("%-15s %2d %-8s %-8s %-8s %3d", ch, (stats.ageInWeeks / 52),
|
|
|
|
stats.alignment, stats.race, stats.type, stats.hitsMax));
|
|
|
|
text.append (String.format (" %2d %2d %2d %2d %2d %2d", att.strength, att.intelligence,
|
|
|
|
att.piety, att.vitality, att.agility, att.luck));
|
|
|
|
text.append (String.format (" %5s %s%n", stats.status, ch.isOut () ? "* OUT *" : ""));
|
2020-02-11 07:29:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DefaultAppleFileSource afs = (DefaultAppleFileSource) node.getUserObject ();
|
|
|
|
afs.setSectors (nodeSectors);
|
|
|
|
DefaultDataSource dds = (DefaultDataSource) afs.getDataSource ();
|
|
|
|
dds.text = text.toString ();
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
2022-03-10 06:21:18 +00:00
|
|
|
private void addCharacters (byte[] buffer, List<DiskAddress> blocks, DefaultMutableTreeNode node)
|
2020-02-11 07:29:55 +00:00
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
int recLen = 208;
|
|
|
|
for (int ptr = 0; ptr < 832; ptr += recLen)
|
|
|
|
{
|
|
|
|
int nameLength = buffer[ptr] & 0xFF;
|
2022-03-10 06:21:18 +00:00
|
|
|
if (nameLength == 0xC3)
|
2022-03-31 02:04:23 +00:00
|
|
|
return;
|
|
|
|
|
2020-02-11 07:29:55 +00:00
|
|
|
String name = HexFormatter.getString (buffer, ptr + 1, nameLength);
|
2022-03-31 02:04:23 +00:00
|
|
|
if (name.isEmpty () || ("UNSET".equals (name) && buffer[ptr + 40] == 0x07)) // 7 = LOST
|
2022-03-28 03:55:49 +00:00
|
|
|
continue;
|
2020-02-11 07:29:55 +00:00
|
|
|
|
|
|
|
byte[] data2 = new byte[recLen];
|
|
|
|
System.arraycopy (buffer, ptr, data2, 0, recLen);
|
|
|
|
|
|
|
|
Character c = new Character (name, data2, scenarioHeader.scenarioID);
|
|
|
|
characters.add (c);
|
|
|
|
addToNode (c, node, blocks, characterSector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
private void extractMonsters (DefaultMutableTreeNode node, List<DiskAddress> sectors)
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
List<DiskAddress> nodeSectors = new ArrayList<> ();
|
|
|
|
ScenarioData sd = scenarioHeader.data.get (Header.MONSTER_AREA);
|
|
|
|
monsters = new ArrayList<> (sd.total);
|
|
|
|
int max = sd.totalBlocks / 2;
|
|
|
|
|
|
|
|
for (int i = 0; i < max; i++)
|
|
|
|
{
|
|
|
|
List<DiskAddress> blocks = getTwoBlocks (sd, i, sectors);
|
|
|
|
nodeSectors.addAll (blocks);
|
2020-04-10 23:47:52 +00:00
|
|
|
byte[] buffer = disk.readBlocks (blocks);
|
2020-02-11 07:29:55 +00:00
|
|
|
addMonsters (buffer, blocks, node);
|
|
|
|
}
|
|
|
|
|
|
|
|
StringBuilder text = new StringBuilder ();
|
|
|
|
for (int block = 0; block < 4; block++)
|
|
|
|
{
|
|
|
|
text.append (" ID Name\n");
|
|
|
|
text.append ("--- ---------------");
|
|
|
|
for (int i = 0; i < 24; i++)
|
|
|
|
text.append (" --");
|
|
|
|
text.append ("\n");
|
|
|
|
for (Monster m : monsters)
|
|
|
|
text.append (m.getDump (block) + "\n");
|
|
|
|
text.append ("\n");
|
|
|
|
}
|
|
|
|
DefaultAppleFileSource afs = (DefaultAppleFileSource) node.getUserObject ();
|
|
|
|
afs.setSectors (nodeSectors);
|
|
|
|
DefaultDataSource dds = (DefaultDataSource) afs.getDataSource ();
|
|
|
|
dds.text = text.toString ();
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
2022-03-10 06:21:18 +00:00
|
|
|
private void addMonsters (byte[] buffer, List<DiskAddress> blocks, DefaultMutableTreeNode node)
|
2020-02-11 07:29:55 +00:00
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
int recLen = 158;
|
|
|
|
for (int ptr = 0; ptr < 948; ptr += recLen)
|
|
|
|
{
|
|
|
|
int nameLength = buffer[ptr + 32] & 0xFF;
|
|
|
|
if (nameLength == 0 || nameLength == 255)
|
|
|
|
break;
|
|
|
|
String itemName = HexFormatter.getString (buffer, ptr + 33, nameLength);
|
|
|
|
|
|
|
|
byte[] data2 = new byte[recLen];
|
|
|
|
System.arraycopy (buffer, ptr, data2, 0, recLen);
|
|
|
|
|
2022-03-31 02:04:23 +00:00
|
|
|
Monster m = new Monster (itemName, data2, rewards, monsters, scenarioHeader.scenarioID);
|
2020-02-11 07:29:55 +00:00
|
|
|
monsters.add (m);
|
|
|
|
addToNode (m, node, blocks, monsterSector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
private void extractItems (DefaultMutableTreeNode node, List<DiskAddress> sectors)
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
List<DiskAddress> nodeSectors = new ArrayList<> ();
|
|
|
|
ScenarioData sd = scenarioHeader.data.get (Header.ITEM_AREA);
|
|
|
|
items = new ArrayList<> (sd.total);
|
|
|
|
int max = sd.totalBlocks / 2;
|
|
|
|
|
|
|
|
for (int i = 0; i < max; i++)
|
|
|
|
{
|
|
|
|
List<DiskAddress> blocks = getTwoBlocks (sd, i, sectors);
|
|
|
|
nodeSectors.addAll (blocks);
|
2020-04-10 23:47:52 +00:00
|
|
|
byte[] buffer = disk.readBlocks (blocks);
|
2020-02-11 07:29:55 +00:00
|
|
|
addItems (buffer, blocks, node);
|
|
|
|
}
|
|
|
|
|
|
|
|
StringBuilder text = new StringBuilder ();
|
2022-04-06 08:05:37 +00:00
|
|
|
for (int block = 0; block < 2; block++)
|
2020-02-11 07:29:55 +00:00
|
|
|
{
|
2022-04-06 08:05:37 +00:00
|
|
|
text.append (" ID Name ");
|
|
|
|
for (int i = 0; i < 24; i++)
|
|
|
|
text.append (String.format ("%2d ", i));
|
|
|
|
text.append ("\n--- ---------------");
|
2020-02-11 07:29:55 +00:00
|
|
|
for (int i = 0; i < 24; i++)
|
|
|
|
text.append (" --");
|
|
|
|
text.append ("\n");
|
|
|
|
for (Item item : items)
|
|
|
|
text.append (item.getDump (block) + "\n");
|
|
|
|
text.append ("\n");
|
|
|
|
}
|
|
|
|
DefaultAppleFileSource afs = (DefaultAppleFileSource) node.getUserObject ();
|
|
|
|
afs.setSectors (nodeSectors);
|
|
|
|
DefaultDataSource dds = (DefaultDataSource) afs.getDataSource ();
|
|
|
|
dds.text = text.toString ();
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
2022-03-10 06:21:18 +00:00
|
|
|
private void addItems (byte[] buffer, List<DiskAddress> blocks, DefaultMutableTreeNode node)
|
2020-02-11 07:29:55 +00:00
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
int recLen = 78;
|
|
|
|
for (int ptr = 0; ptr < 1014; ptr += recLen)
|
|
|
|
{
|
|
|
|
if (buffer[ptr] == 0)
|
|
|
|
break;
|
|
|
|
String itemName = HexFormatter.getPascalString (buffer, ptr);
|
|
|
|
|
|
|
|
byte[] data2 = new byte[recLen];
|
|
|
|
System.arraycopy (buffer, ptr, data2, 0, recLen);
|
|
|
|
|
|
|
|
Item i = new Item (itemName, data2);
|
|
|
|
items.add (i);
|
|
|
|
addToNode (i, node, blocks, itemSector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
private void extractSpells (DefaultMutableTreeNode node, List<DiskAddress> sectors)
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
spells = new ArrayList<> ();
|
|
|
|
List<DiskAddress> blocks = new ArrayList<> (2);
|
|
|
|
int offset = scenarioHeader.scenarioID <= 2 ? 4 : 1;
|
|
|
|
blocks.add (sectors.get (offset));
|
|
|
|
blocks.add (sectors.get (offset + 1));
|
|
|
|
|
|
|
|
SpellType spellType = SpellType.MAGE;
|
|
|
|
for (DiskAddress da : blocks)
|
|
|
|
{
|
2020-04-10 23:47:52 +00:00
|
|
|
byte[] buffer = disk.readBlock (da);
|
2020-02-11 07:29:55 +00:00
|
|
|
int level = 1;
|
|
|
|
int ptr = -1;
|
|
|
|
while (ptr < 255)
|
|
|
|
{
|
|
|
|
ptr++;
|
|
|
|
int start = ptr;
|
|
|
|
while (ptr < 256 && buffer[ptr] != 0x0D)
|
|
|
|
ptr++;
|
|
|
|
if (ptr == start)
|
|
|
|
break;
|
|
|
|
String spell = HexFormatter.getString (buffer, start, ptr - start);
|
|
|
|
if (spell.startsWith ("*"))
|
|
|
|
{
|
|
|
|
spell = spell.substring (1);
|
|
|
|
++level;
|
|
|
|
}
|
|
|
|
Spell s = Spell.getSpell (spell, spellType, level, buffer);
|
|
|
|
spells.add (s);
|
|
|
|
// addToNode (s, node, da, spellSector);
|
|
|
|
}
|
|
|
|
spellType = SpellType.PRIEST;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
private void extractMessages (DefaultMutableTreeNode node, List<DiskAddress> sectors)
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
2022-05-28 02:59:25 +00:00
|
|
|
MessageV1.resetMessageId ();
|
2020-02-11 07:29:55 +00:00
|
|
|
messages = new ArrayList<> ();
|
|
|
|
|
|
|
|
// Copy first 504 bytes from each sector to a single contiguous buffer
|
|
|
|
int recordLength = 42;
|
|
|
|
int max = recordLength * 12;
|
|
|
|
byte[] buffer = new byte[sectors.size () * max];
|
|
|
|
int offset = 0;
|
|
|
|
|
|
|
|
for (DiskAddress da : sectors)
|
|
|
|
{
|
2020-04-10 23:47:52 +00:00
|
|
|
byte[] tempBuffer = disk.readBlock (da);
|
2020-02-11 07:29:55 +00:00
|
|
|
System.arraycopy (tempBuffer, 0, buffer, offset, max);
|
|
|
|
offset += max;
|
|
|
|
}
|
|
|
|
|
|
|
|
// int id = 0;
|
|
|
|
int totalLines = 0;
|
|
|
|
|
|
|
|
for (int ptr = 0; ptr < buffer.length; ptr += recordLength)
|
|
|
|
{
|
|
|
|
int sequence = buffer[ptr + recordLength - 2];
|
|
|
|
++totalLines;
|
2022-03-26 08:07:17 +00:00
|
|
|
if (sequence == 1) // end of message
|
2020-02-11 07:29:55 +00:00
|
|
|
{
|
|
|
|
int totalBytes = totalLines * recordLength;
|
|
|
|
byte[] newBuffer = new byte[totalBytes];
|
|
|
|
int messageEnd = ptr + recordLength;
|
|
|
|
int messageStart = messageEnd - totalBytes;
|
|
|
|
System.arraycopy (buffer, messageStart, newBuffer, 0, totalBytes);
|
|
|
|
|
2022-05-28 02:59:25 +00:00
|
|
|
MessageV1 m;
|
2020-02-11 07:29:55 +00:00
|
|
|
if (scenarioHeader.scenarioID == 1)
|
|
|
|
m = new PlainMessage (newBuffer);
|
|
|
|
else
|
|
|
|
m = new CodedMessage (newBuffer);
|
|
|
|
messages.add (m);
|
|
|
|
|
|
|
|
List<DiskAddress> messageBlocks = new ArrayList<> ();
|
|
|
|
int lastBlock = -1;
|
|
|
|
for (int p2 = messageStart; p2 < messageEnd; p2 += recordLength)
|
|
|
|
{
|
|
|
|
int blockNo = p2 / max;
|
|
|
|
offset = p2 % max;
|
|
|
|
if (blockNo != lastBlock)
|
|
|
|
{
|
|
|
|
messageBlocks.add (sectors.get (blockNo));
|
|
|
|
lastBlock = blockNo;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
addToNode (m, node, messageBlocks, messageSector);
|
|
|
|
// id += totalLines;
|
|
|
|
totalLines = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
private void extractLevels (DefaultMutableTreeNode node, List<DiskAddress> sectors)
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
List<DiskAddress> nodeSectors = new ArrayList<> ();
|
|
|
|
ScenarioData sd = scenarioHeader.data.get (Header.MAZE_AREA);
|
|
|
|
levels = new ArrayList<> (sd.total);
|
|
|
|
int max = sd.totalBlocks / 2;
|
|
|
|
|
|
|
|
for (int i = 0; i < max; i++)
|
|
|
|
{
|
|
|
|
List<DiskAddress> blocks = getTwoBlocks (sd, i, sectors);
|
|
|
|
nodeSectors.addAll (blocks);
|
2020-04-10 23:47:52 +00:00
|
|
|
byte[] buffer = disk.readBlocks (blocks);
|
2020-02-11 07:29:55 +00:00
|
|
|
byte[] data2 = new byte[896];
|
|
|
|
System.arraycopy (buffer, 0, data2, 0, data2.length);
|
|
|
|
// System.out.println (HexFormatter.format (data2));
|
|
|
|
|
|
|
|
MazeLevel mazeLevel = new MazeLevel (data2, i + 1);
|
|
|
|
mazeLevel.setMessages (messages);
|
|
|
|
mazeLevel.setMonsters (monsters);
|
|
|
|
mazeLevel.setItems (items);
|
|
|
|
levels.add (mazeLevel);
|
|
|
|
addToNode (mazeLevel, node, blocks, mazeSector);
|
|
|
|
}
|
|
|
|
|
|
|
|
StringBuilder text = new StringBuilder ();
|
|
|
|
for (MazeLevel level : levels)
|
|
|
|
text.append (level.getName () + "\n");
|
|
|
|
|
|
|
|
DefaultAppleFileSource afs = (DefaultAppleFileSource) node.getUserObject ();
|
|
|
|
afs.setSectors (nodeSectors);
|
|
|
|
DefaultDataSource dds = (DefaultDataSource) afs.getDataSource ();
|
|
|
|
dds.text = text.toString ();
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
private void extractImages (DefaultMutableTreeNode node, List<DiskAddress> sectors)
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
List<DiskAddress> nodeSectors = new ArrayList<> ();
|
|
|
|
ScenarioData sd = scenarioHeader.data.get (Header.IMAGE_AREA);
|
|
|
|
int max = sd.totalBlocks;
|
|
|
|
images = new ArrayList<> ();
|
|
|
|
|
|
|
|
for (int i = 0; i < max; i++)
|
|
|
|
{
|
|
|
|
DiskAddress da = sectors.get (sd.dataOffset + i);
|
|
|
|
nodeSectors.add (da);
|
2020-04-10 23:47:52 +00:00
|
|
|
byte[] buffer = disk.readBlock (da);
|
2020-02-11 07:29:55 +00:00
|
|
|
byte[] exactBuffer = new byte[480];
|
|
|
|
System.arraycopy (buffer, 0, exactBuffer, 0, exactBuffer.length);
|
|
|
|
|
|
|
|
String name = "Unknown";
|
|
|
|
for (Monster m : monsters)
|
|
|
|
if (m.imageID == i)
|
|
|
|
{
|
|
|
|
name = m.genericName;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
AbstractImage mi = scenarioHeader.scenarioID < 3 ? new Image (name, buffer)
|
|
|
|
: new ImageV2 (name, exactBuffer);
|
|
|
|
images.add (mi);
|
|
|
|
addToNode (mi, node, da, imageSector);
|
|
|
|
}
|
|
|
|
|
|
|
|
StringBuilder text = new StringBuilder ();
|
|
|
|
for (AbstractImage image : images)
|
|
|
|
text.append (image.getName () + "\n");
|
|
|
|
|
|
|
|
DefaultAppleFileSource afs = (DefaultAppleFileSource) node.getUserObject ();
|
|
|
|
afs.setSectors (nodeSectors);
|
|
|
|
DefaultDataSource dds = (DefaultDataSource) afs.getDataSource ();
|
|
|
|
dds.text = text.toString ();
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
2022-03-10 06:21:18 +00:00
|
|
|
private void extractExperienceLevels (DefaultMutableTreeNode node, List<DiskAddress> sectors)
|
2020-02-11 07:29:55 +00:00
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
List<DiskAddress> nodeSectors = new ArrayList<> ();
|
|
|
|
ScenarioData sd = scenarioHeader.data.get (Header.EXPERIENCE_AREA);
|
|
|
|
experiences = new ArrayList<> (sd.total);
|
|
|
|
int max = sd.totalBlocks / 2;
|
|
|
|
|
2022-03-13 22:46:56 +00:00
|
|
|
int count = 0;
|
|
|
|
String[] classes =
|
|
|
|
{ "FIGHTER", "MAGE", "PRIEST", "THIEF", "BISHOP", "SAMURAI", "LORD", "NINJA" };
|
|
|
|
|
2020-02-11 07:29:55 +00:00
|
|
|
for (int i = 0; i < max; i++)
|
|
|
|
{
|
|
|
|
List<DiskAddress> blocks = getTwoBlocks (sd, i, sectors);
|
|
|
|
nodeSectors.addAll (blocks);
|
2020-04-10 23:47:52 +00:00
|
|
|
byte[] buffer = disk.readBlocks (blocks);
|
2020-02-11 07:29:55 +00:00
|
|
|
|
|
|
|
for (int ptr = 0; ptr <= buffer.length; ptr += 78)
|
|
|
|
{
|
|
|
|
if (buffer[ptr] == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
byte[] newBuffer = new byte[78];
|
|
|
|
System.arraycopy (buffer, ptr, newBuffer, 0, newBuffer.length);
|
2022-03-13 22:46:56 +00:00
|
|
|
ExperienceLevel el = new ExperienceLevel (classes[count++], newBuffer);
|
2020-02-11 07:29:55 +00:00
|
|
|
experiences.add (el);
|
|
|
|
addToNode (el, node, blocks, experienceSector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DefaultAppleFileSource afs = (DefaultAppleFileSource) node.getUserObject ();
|
|
|
|
afs.setSectors (nodeSectors);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
private void addToNode (AbstractFile af, DefaultMutableTreeNode node, DiskAddress block,
|
|
|
|
SectorType type)
|
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
List<DiskAddress> blocks = new ArrayList<> (1);
|
|
|
|
blocks.add (block);
|
|
|
|
addToNode (af, node, blocks, type);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
2022-03-10 06:21:18 +00:00
|
|
|
private void addToNode (AbstractFile af, DefaultMutableTreeNode node, List<DiskAddress> blocks,
|
|
|
|
SectorType type)
|
2020-02-11 07:29:55 +00:00
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
2022-03-10 06:21:18 +00:00
|
|
|
DefaultAppleFileSource dafs = new DefaultAppleFileSource (af.getName (), af, this, blocks);
|
2020-02-11 07:29:55 +00:00
|
|
|
DefaultMutableTreeNode childNode = new DefaultMutableTreeNode (dafs);
|
|
|
|
node.add (childNode);
|
|
|
|
childNode.setAllowsChildren (false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------//
|
2022-03-10 06:21:18 +00:00
|
|
|
private List<DiskAddress> getTwoBlocks (ScenarioData sd, int i, List<DiskAddress> sectors)
|
2020-02-11 07:29:55 +00:00
|
|
|
// ---------------------------------------------------------------------------------//
|
|
|
|
{
|
|
|
|
List<DiskAddress> blocks = new ArrayList<> (2);
|
|
|
|
blocks.add (sectors.get (sd.dataOffset + i * 2));
|
|
|
|
blocks.add (sectors.get (sd.dataOffset + i * 2 + 1));
|
|
|
|
return blocks;
|
|
|
|
}
|
2015-06-01 09:35:51 +00:00
|
|
|
}
|