From c4b4d17f522fa35ca0d3e0ed5970039cebc15f62 Mon Sep 17 00:00:00 2001 From: Denis Molony Date: Sat, 28 May 2022 12:59:25 +1000 Subject: [PATCH] Items and Monsters for Wizardry IV --- .../diskbrowser/wizardry/CodedMessage.java | 2 +- .../bytezone/diskbrowser/wizardry/ItemV4.java | 16 ++++ .../diskbrowser/wizardry/MazeCell.java | 2 +- .../diskbrowser/wizardry/MazeLevel.java | 12 +-- .../diskbrowser/wizardry/MessageBlock.java | 54 +++++------ .../wizardry/{Message.java => MessageV1.java} | 4 +- .../diskbrowser/wizardry/MonsterV4.java | 14 +++ .../diskbrowser/wizardry/PlainMessage.java | 2 +- .../wizardry/Wizardry4BootDisk.java | 90 ++++++++++++++++++- .../wizardry/WizardryScenarioDisk.java | 6 +- 10 files changed, 159 insertions(+), 43 deletions(-) create mode 100644 src/com/bytezone/diskbrowser/wizardry/ItemV4.java rename src/com/bytezone/diskbrowser/wizardry/{Message.java => MessageV1.java} (97%) create mode 100644 src/com/bytezone/diskbrowser/wizardry/MonsterV4.java diff --git a/src/com/bytezone/diskbrowser/wizardry/CodedMessage.java b/src/com/bytezone/diskbrowser/wizardry/CodedMessage.java index b6cadc7..8876164 100755 --- a/src/com/bytezone/diskbrowser/wizardry/CodedMessage.java +++ b/src/com/bytezone/diskbrowser/wizardry/CodedMessage.java @@ -3,7 +3,7 @@ package com.bytezone.diskbrowser.wizardry; import com.bytezone.diskbrowser.utilities.HexFormatter; // -----------------------------------------------------------------------------------// -class CodedMessage extends Message +class CodedMessage extends MessageV1 // -----------------------------------------------------------------------------------// { public static int codeOffset = 185; diff --git a/src/com/bytezone/diskbrowser/wizardry/ItemV4.java b/src/com/bytezone/diskbrowser/wizardry/ItemV4.java new file mode 100644 index 0000000..4ed7d77 --- /dev/null +++ b/src/com/bytezone/diskbrowser/wizardry/ItemV4.java @@ -0,0 +1,16 @@ +package com.bytezone.diskbrowser.wizardry; + +import com.bytezone.diskbrowser.applefile.AbstractFile; + +// -----------------------------------------------------------------------------------// +public class ItemV4 extends AbstractFile +// -----------------------------------------------------------------------------------// +{ + + // ---------------------------------------------------------------------------------// + ItemV4 (String[] names, byte[] buffer, int id) + // ---------------------------------------------------------------------------------// + { + super (names[1], buffer); + } +} diff --git a/src/com/bytezone/diskbrowser/wizardry/MazeCell.java b/src/com/bytezone/diskbrowser/wizardry/MazeCell.java index 66b895c..8ec4dc8 100755 --- a/src/com/bytezone/diskbrowser/wizardry/MazeCell.java +++ b/src/com/bytezone/diskbrowser/wizardry/MazeCell.java @@ -49,7 +49,7 @@ class MazeCell MazeAddress address; MazeAddress addressTo; // if teleport/stairs/chute - public Message message; + public MessageV1 message; public List monsters; public Item itemRequired; public Item itemObtained; diff --git a/src/com/bytezone/diskbrowser/wizardry/MazeLevel.java b/src/com/bytezone/diskbrowser/wizardry/MazeLevel.java index cdeecf4..86c9872 100755 --- a/src/com/bytezone/diskbrowser/wizardry/MazeLevel.java +++ b/src/com/bytezone/diskbrowser/wizardry/MazeLevel.java @@ -24,7 +24,7 @@ public class MazeLevel extends AbstractFile "Rock/Water", "Fizzle", "Message/Item", "Monster" }; public final int level; - private List messages; + private List messages; private List monsters; private List items; @@ -94,7 +94,7 @@ public class MazeLevel extends AbstractFile text.append ("\n\n"); for (MazeAddress address : messageList) { - Message message = getMessage (address.row); + MessageV1 message = getMessage (address.row); if (message != null) { text.append (String.format ("%nMessage: %04X (%d)%n", address.row, address.row)); @@ -318,7 +318,7 @@ public class MazeLevel extends AbstractFile } // ---------------------------------------------------------------------------------// - public void setMessages (List messages) + public void setMessages (List messages) // ---------------------------------------------------------------------------------// { this.messages = messages; @@ -448,7 +448,7 @@ public class MazeLevel extends AbstractFile case 11: // screen message MazeAddress messageAddress = getAddress (b); - Message m = getMessage (messageAddress.row); + MessageV1 m = getMessage (messageAddress.row); if (m != null) cell.message = m; @@ -513,13 +513,13 @@ public class MazeLevel extends AbstractFile } // ---------------------------------------------------------------------------------// - private Message getMessage (int messageNo) + private MessageV1 getMessage (int messageNo) // ---------------------------------------------------------------------------------// { if (messages == null) return null; - for (Message m : messages) + for (MessageV1 m : messages) if (m.match (messageNo)) return m; diff --git a/src/com/bytezone/diskbrowser/wizardry/MessageBlock.java b/src/com/bytezone/diskbrowser/wizardry/MessageBlock.java index a8975dd..ce136f4 100644 --- a/src/com/bytezone/diskbrowser/wizardry/MessageBlock.java +++ b/src/com/bytezone/diskbrowser/wizardry/MessageBlock.java @@ -33,14 +33,27 @@ class MessageBlock extends AbstractFile implements Iterable int firstMessageNo = Utility.getShort (buffer, ptr + i * 2); byte[] data = new byte[512]; System.arraycopy (buffer, i * 512, data, 0, data.length); - MessageDataBlock messageDataBlock = new MessageDataBlock ( - " Message " + firstMessageNo, data, firstMessageNo, huffman); + MessageDataBlock messageDataBlock = + new MessageDataBlock (" Message " + firstMessageNo, data, firstMessageNo, huffman); messageDataBlocks.add (messageDataBlock); } } // ---------------------------------------------------------------------------------// - public String getMessageText (int messageNo) + public byte[] getMessage (int messageNo) + // ---------------------------------------------------------------------------------// + { + for (int i = 0; i < messageDataBlocks.size (); i++) + { + MessageDataBlock messageDataBlock = messageDataBlocks.get (i); + if (messageDataBlock.firstMessageNo > messageNo) + return messageDataBlocks.get (i - 1).getMessage (messageNo); + } + return null; + } + + // ---------------------------------------------------------------------------------// + public String getMessageLine (int messageNo) // ---------------------------------------------------------------------------------// { for (int i = 0; i < messageDataBlocks.size (); i++) @@ -80,38 +93,25 @@ class MessageBlock extends AbstractFile implements Iterable return lines; } - // ---------------------------------------------------------------------------------// - public byte[] getMessage (int messageNo) - // ---------------------------------------------------------------------------------// - { - for (int i = 0; i < messageDataBlocks.size (); i++) - { - MessageDataBlock messageDataBlock = messageDataBlocks.get (i); - if (messageDataBlock.firstMessageNo > messageNo) - return messageDataBlocks.get (i - 1).getMessage (messageNo); - } - return null; - } - // ---------------------------------------------------------------------------------// @Override public String getText () // ---------------------------------------------------------------------------------// { - if (text != null) - return text; - - StringBuilder text = new StringBuilder (); - - for (MessageDataBlock mdb : messageDataBlocks) + if (text == null) { - text.append (mdb); - text.append ("\n"); + StringBuilder sb = new StringBuilder (); + + for (MessageDataBlock mdb : messageDataBlocks) + { + sb.append (mdb); + sb.append ("\n"); + } + + text = sb.toString (); } - this.text = text.toString (); - - return this.text; + return text; } // ---------------------------------------------------------------------------------// diff --git a/src/com/bytezone/diskbrowser/wizardry/Message.java b/src/com/bytezone/diskbrowser/wizardry/MessageV1.java similarity index 97% rename from src/com/bytezone/diskbrowser/wizardry/Message.java rename to src/com/bytezone/diskbrowser/wizardry/MessageV1.java index f7552a2..aa8cce3 100755 --- a/src/com/bytezone/diskbrowser/wizardry/Message.java +++ b/src/com/bytezone/diskbrowser/wizardry/MessageV1.java @@ -6,7 +6,7 @@ import java.util.List; import com.bytezone.diskbrowser.applefile.AbstractFile; // -----------------------------------------------------------------------------------// -abstract class Message extends AbstractFile +abstract class MessageV1 extends AbstractFile // -----------------------------------------------------------------------------------// { private static int nextId = 0; @@ -16,7 +16,7 @@ abstract class Message extends AbstractFile List lines = new ArrayList<> (); // ---------------------------------------------------------------------------------// - Message (byte[] buffer) + MessageV1 (byte[] buffer) // ---------------------------------------------------------------------------------// { super ("Message " + nextId, buffer); diff --git a/src/com/bytezone/diskbrowser/wizardry/MonsterV4.java b/src/com/bytezone/diskbrowser/wizardry/MonsterV4.java new file mode 100644 index 0000000..33cc857 --- /dev/null +++ b/src/com/bytezone/diskbrowser/wizardry/MonsterV4.java @@ -0,0 +1,14 @@ +package com.bytezone.diskbrowser.wizardry; + +import com.bytezone.diskbrowser.applefile.AbstractFile; + +public class MonsterV4 extends AbstractFile +{ + + // ---------------------------------------------------------------------------------// + MonsterV4 (String[] names, byte[] buffer, int id) + // ---------------------------------------------------------------------------------// + { + super (names[2], buffer); + } +} diff --git a/src/com/bytezone/diskbrowser/wizardry/PlainMessage.java b/src/com/bytezone/diskbrowser/wizardry/PlainMessage.java index a292413..336d509 100755 --- a/src/com/bytezone/diskbrowser/wizardry/PlainMessage.java +++ b/src/com/bytezone/diskbrowser/wizardry/PlainMessage.java @@ -3,7 +3,7 @@ package com.bytezone.diskbrowser.wizardry; import com.bytezone.diskbrowser.utilities.HexFormatter; // -----------------------------------------------------------------------------------// -class PlainMessage extends Message +class PlainMessage extends MessageV1 // -----------------------------------------------------------------------------------// { // ---------------------------------------------------------------------------------// diff --git a/src/com/bytezone/diskbrowser/wizardry/Wizardry4BootDisk.java b/src/com/bytezone/diskbrowser/wizardry/Wizardry4BootDisk.java index 68cfd31..95b2892 100644 --- a/src/com/bytezone/diskbrowser/wizardry/Wizardry4BootDisk.java +++ b/src/com/bytezone/diskbrowser/wizardry/Wizardry4BootDisk.java @@ -95,6 +95,8 @@ public class Wizardry4BootDisk extends PascalDisk scenarioHeader = new Header (scenarioNode, this); linkCharacters4 (scenarioNode, fileEntry); linkMazeLevels4 (scenarioNode, fileEntry); + linkMonstersV4 (scenarioNode, fileEntry); + linkItemsV4 (scenarioNode, fileEntry); } } else if (version == 5) @@ -173,6 +175,90 @@ public class Wizardry4BootDisk extends PascalDisk afs.setSectors (allCharacterBlocks); } + // ---------------------------------------------------------------------------------// + private void linkMonstersV4 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry) + // ---------------------------------------------------------------------------------// + { + ScenarioData sd = scenarioHeader.get (Header.MONSTER_AREA); + + byte[] buffer = fileEntry.getDataSource ().buffer; + List blocks = fileEntry.getSectors (); + + DefaultMutableTreeNode monstersNode = linkNode ("Monsters", "Monsters", scenarioNode); + List allMonsterBlocks = new ArrayList<> (); + + String[] monsterNames = new String[4]; + + int ptr = sd.dataOffset * 512; + + for (int i = 0; i < sd.total; i++) + { + byte[] out = huffman.decodeMessage (buffer, ptr, sd.totalBlocks); + + for (int j = 0; j < 4; j++) + monsterNames[j] = messageBlock.getMessageLine (i * 4 + 13000 + j); + + MonsterV4 monster = new MonsterV4 (monsterNames, out, i); + + List monsterBlocks = new ArrayList<> (); + DiskAddress da = blocks.get (ptr / 512); + monsterBlocks.add (da); + addToNode (monster, monstersNode, monsterBlocks); + + if (!allMonsterBlocks.contains (da)) + allMonsterBlocks.add (da); + + ptr += sd.totalBlocks; + } + + DefaultAppleFileSource afs = (DefaultAppleFileSource) monstersNode.getUserObject (); + afs.setSectors (allMonsterBlocks); + } + + // ---------------------------------------------------------------------------------// + private void linkItemsV4 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry) + // ---------------------------------------------------------------------------------// + { + ScenarioData sd = scenarioHeader.get (Header.ITEM_AREA); + + byte[] buffer = fileEntry.getDataSource ().buffer; + List blocks = fileEntry.getSectors (); + + DefaultMutableTreeNode itemsNode = linkNode ("Items", "Items", scenarioNode); + List allItemBlocks = new ArrayList<> (); + + String[] itemNames = new String[2]; + + int ptr = sd.dataOffset * 512; + + for (int i = 0; i < sd.total; i++) + { + byte[] out = huffman.decodeMessage (buffer, ptr, sd.totalBlocks); + + for (int j = 0; j < 2; j++) + { + itemNames[j] = messageBlock.getMessageLine (i * 2 + 14000 + j); + if (itemNames[j] == null) + itemNames[j] = "Not found"; + } + + ItemV4 item = new ItemV4 (itemNames, out, i); + + List itemBlocks = new ArrayList<> (); + DiskAddress da = blocks.get (ptr / 512); + itemBlocks.add (da); + addToNode (item, itemsNode, itemBlocks); + + if (!allItemBlocks.contains (da)) + allItemBlocks.add (da); + + ptr += sd.totalBlocks; + } + + DefaultAppleFileSource afs = (DefaultAppleFileSource) itemsNode.getUserObject (); + afs.setSectors (allItemBlocks); + } + // ---------------------------------------------------------------------------------// private void linkMazeLevels4 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry) // ---------------------------------------------------------------------------------// @@ -343,11 +429,11 @@ public class Wizardry4BootDisk extends PascalDisk int key = Utility.getShort (buffer, offset); if (key > 0) text.append ( - String.format ("%04X %04X * %s%n", offset, key, messageBlock.getMessageText (key))); + String.format ("%04X %04X * %s%n", offset, key, messageBlock.getMessageLine (key))); key = Utility.getShort (buffer, offset + 8); if (key > 0) text.append (String.format ("%04X %04X %s%n", offset + 8, key, - messageBlock.getMessageText (key))); + messageBlock.getMessageLine (key))); } List allOracleBlocks = new ArrayList<> (); diff --git a/src/com/bytezone/diskbrowser/wizardry/WizardryScenarioDisk.java b/src/com/bytezone/diskbrowser/wizardry/WizardryScenarioDisk.java index da3b99f..e04ce0f 100755 --- a/src/com/bytezone/diskbrowser/wizardry/WizardryScenarioDisk.java +++ b/src/com/bytezone/diskbrowser/wizardry/WizardryScenarioDisk.java @@ -33,7 +33,7 @@ public class WizardryScenarioDisk extends PascalDisk public List items; public List characters; public List spells; - public List messages; + public List messages; public List monsters; public List levels; List experiences; @@ -448,7 +448,7 @@ public class WizardryScenarioDisk extends PascalDisk private void extractMessages (DefaultMutableTreeNode node, List sectors) // ---------------------------------------------------------------------------------// { - Message.resetMessageId (); + MessageV1.resetMessageId (); messages = new ArrayList<> (); // Copy first 504 bytes from each sector to a single contiguous buffer @@ -479,7 +479,7 @@ public class WizardryScenarioDisk extends PascalDisk int messageStart = messageEnd - totalBytes; System.arraycopy (buffer, messageStart, newBuffer, 0, totalBytes); - Message m; + MessageV1 m; if (scenarioHeader.scenarioID == 1) m = new PlainMessage (newBuffer); else