From 1f3894f162d7800a65eef88c024436662f5c4f00 Mon Sep 17 00:00:00 2001 From: Denis Molony Date: Tue, 16 Aug 2016 16:34:23 +1000 Subject: [PATCH] Wiz4 messages --- .../diskbrowser/utilities/HexFormatter.java | 2 +- .../bytezone/diskbrowser/wizardry/Header.java | 374 +++++++++--------- .../diskbrowser/wizardry/Huffman.java | 69 ++++ .../diskbrowser/wizardry/MessageBlock.java | 58 +++ .../wizardry/MessageDataBlock.java | 130 ++++++ .../wizardry/Wizardry4BootDisk.java | 122 ++++-- .../wizardry/WizardryScenarioDisk.java | 12 +- 7 files changed, 545 insertions(+), 222 deletions(-) create mode 100644 src/com/bytezone/diskbrowser/wizardry/Huffman.java create mode 100644 src/com/bytezone/diskbrowser/wizardry/MessageBlock.java create mode 100644 src/com/bytezone/diskbrowser/wizardry/MessageDataBlock.java diff --git a/src/com/bytezone/diskbrowser/utilities/HexFormatter.java b/src/com/bytezone/diskbrowser/utilities/HexFormatter.java index 7a514e2..f29c082 100755 --- a/src/com/bytezone/diskbrowser/utilities/HexFormatter.java +++ b/src/com/bytezone/diskbrowser/utilities/HexFormatter.java @@ -55,7 +55,7 @@ public class HexFormatter { if (line.length () > 0 && i > 0) line.append ("\n"); - if (i > 0 && (i % 0x200) == 0) + if (i > offset && (i % 0x200) == 0) line.append ("\n"); // print offset diff --git a/src/com/bytezone/diskbrowser/wizardry/Header.java b/src/com/bytezone/diskbrowser/wizardry/Header.java index 57933ce..cf65569 100755 --- a/src/com/bytezone/diskbrowser/wizardry/Header.java +++ b/src/com/bytezone/diskbrowser/wizardry/Header.java @@ -14,214 +14,226 @@ import com.bytezone.diskbrowser.utilities.HexFormatter; class Header { - static String[] typeText = - { "header", "maze", "monsters", "rewards", "items", "characters", "images", "char levels" }; - static String[] scenarioNames = - { "PROVING GROUNDS OF THE MAD OVERLORD!", "THE KNIGHT OF DIAMONDS", - "THE LEGACY OF LLYLGAMYN" }; + static String[] typeText = { "header", "maze", "monsters", "rewards", "items", + "characters", "images", "char levels" }; + static String[] scenarioNames = + { "PROVING GROUNDS OF THE MAD OVERLORD!", "THE KNIGHT OF DIAMONDS", + "THE LEGACY OF LLYLGAMYN", "THE RETURN OF WERDNA" }; - static final int MAZE_AREA = 1; - static final int MONSTER_AREA = 2; - static final int TREASURE_TABLE_AREA = 3; - static final int ITEM_AREA = 4; - static final int CHARACTER_AREA = 5; - static final int IMAGE_AREA = 6; - static final int EXPERIENCE_AREA = 7; + static final int MAZE_AREA = 1; + static final int MONSTER_AREA = 2; + static final int TREASURE_TABLE_AREA = 3; + static final int ITEM_AREA = 4; + static final int CHARACTER_AREA = 5; + static final int IMAGE_AREA = 6; + static final int EXPERIENCE_AREA = 7; - String scenarioTitle; - public int scenarioID; - List data = new ArrayList (8); - FormattedDisk owner; + String scenarioTitle; + public int scenarioID; + List data = new ArrayList (8); + FormattedDisk owner; - public Header (DefaultMutableTreeNode dataNode, FormattedDisk owner) - { - this.owner = owner; + public Header (DefaultMutableTreeNode dataNode, FormattedDisk owner) + { + this.owner = owner; - AppleFileSource afs = (AppleFileSource) dataNode.getUserObject (); - List sectors = afs.getSectors (); - DefaultAppleFile daf = (DefaultAppleFile) afs.getDataSource (); - scenarioTitle = HexFormatter.getPascalString (daf.buffer, 0); + AppleFileSource afs = (AppleFileSource) dataNode.getUserObject (); + List sectors = afs.getSectors (); + DefaultAppleFile daf = (DefaultAppleFile) afs.getDataSource (); + scenarioTitle = HexFormatter.getPascalString (daf.buffer, 0); - while (scenarioID < scenarioNames.length) - if (scenarioNames[scenarioID++].equals (scenarioTitle)) - break; - assert (scenarioID <= scenarioNames.length) : "Invalid scenario ID : " + scenarioID; + while (scenarioID < scenarioNames.length) + if (scenarioNames[scenarioID++].equals (scenarioTitle)) + break; - for (int i = 0; i < 8; i++) - data.add (new ScenarioData (daf.buffer, i, sectors)); + if (scenarioID > scenarioNames.length) + System.out.println ("Invalid scenario ID : " + scenarioID + " " + scenarioTitle); - StringBuilder text = - new StringBuilder ("Data type Offset Size Units ???\n" - + "------------ ------ ----- ----- -----\n"); + for (int i = 0; i < 8; i++) + data.add (new ScenarioData (daf.buffer, i, sectors)); - for (ScenarioData sd : data) - text.append (sd + "\n"); + StringBuilder text = new StringBuilder ("Data type Offset Size Units ???\n" + + "------------ ------ ----- ----- -----\n"); - daf.setText (text.toString ()); + for (ScenarioData sd : data) + text.append (sd + "\n"); - text = new StringBuilder (scenarioTitle + "\n\n"); + daf.setText (text.toString ()); - int ptr = 106; - while (daf.buffer[ptr] != -1) - { - text.append (HexFormatter.getPascalString (daf.buffer, ptr) + "\n"); - ptr += 10; - } + text = new StringBuilder (scenarioTitle + "\n\n"); - DefaultAppleFileSource dafs = new DefaultAppleFileSource ("Header", text.toString (), owner); - dafs.setSectors (data.get (0).sectors); - DefaultMutableTreeNode headerNode = new DefaultMutableTreeNode (dafs); - dataNode.add (headerNode); + int ptr = 106; + while (daf.buffer[ptr] != -1) + { + text.append (HexFormatter.getPascalString (daf.buffer, ptr) + "\n"); + ptr += 10; + } - int totalBlocks = data.get (0).sectors.size (); - linkText ("Text", data.get (0).sectors.get (0), headerNode); - if (scenarioID < 3) - { - linkPictures ("Alphabet", data.get (0).sectors.get (1), headerNode); - linkPictures ("Graphics", data.get (0).sectors.get (2), headerNode); - linkPictures ("Unknown", data.get (0).sectors.get (3), headerNode); - } - linkSpells ("Mage spells", data.get (0).sectors.get (totalBlocks - 2), headerNode); - linkSpells ("Priest spells", data.get (0).sectors.get (totalBlocks - 1), headerNode); + DefaultAppleFileSource dafs = + new DefaultAppleFileSource ("Header", text.toString (), owner); + dafs.setSectors (data.get (0).sectors); + DefaultMutableTreeNode headerNode = new DefaultMutableTreeNode (dafs); + dataNode.add (headerNode); - if (false && scenarioID <= 2) - { - System.out.println (printChars (daf.buffer, 1)); - System.out.println (printChars (daf.buffer, 2)); - } - } + if (scenarioID > 3) + return; - private void linkText (String title, DiskAddress da, DefaultMutableTreeNode headerNode) - { - List blocks = new ArrayList (); - blocks.add (da); + int totalBlocks = data.get (0).sectors.size (); + linkText ("Text", data.get (0).sectors.get (0), headerNode); - StringBuilder text = new StringBuilder (scenarioTitle + "\n\n"); + if (scenarioID < 3) + { + linkPictures ("Alphabet", data.get (0).sectors.get (1), headerNode); + linkPictures ("Graphics", data.get (0).sectors.get (2), headerNode); + linkPictures ("Unknown", data.get (0).sectors.get (3), headerNode); + } - int ptr = 106; - byte[] buffer = owner.getDisk ().readSector (da); - while (buffer[ptr] != -1) - { - text.append (HexFormatter.getPascalString (buffer, ptr) + "\n"); - ptr += 10; - } - ptr += 2; - text.append ("\n"); - while (ptr < 512) - { - int value = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]); - text.append (String.format ("%04X %,6d%n", value, value)); - ptr += 2; - } + linkSpells ("Mage spells", data.get (0).sectors.get (totalBlocks - 2), headerNode); + linkSpells ("Priest spells", data.get (0).sectors.get (totalBlocks - 1), headerNode); - DefaultAppleFileSource dafs = new DefaultAppleFileSource (title, text.toString (), owner); - dafs.setSectors (blocks); - DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs); - node.setAllowsChildren (false); - headerNode.add (node); - } + if (false && scenarioID <= 2) + { + System.out.println (printChars (daf.buffer, 1)); + System.out.println (printChars (daf.buffer, 2)); + } + } - private void linkPictures (String title, DiskAddress da, DefaultMutableTreeNode headerNode) - { - List blocks = new ArrayList (); - blocks.add (da); + private void linkText (String title, DiskAddress da, DefaultMutableTreeNode headerNode) + { + List blocks = new ArrayList (); + blocks.add (da); - byte[] buffer = owner.getDisk ().readSector (da); - String text = printChars (buffer, 0); + StringBuilder text = new StringBuilder (scenarioTitle + "\n\n"); - DefaultAppleFileSource dafs = new DefaultAppleFileSource (title, text, owner); - dafs.setSectors (blocks); - DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs); - node.setAllowsChildren (false); - headerNode.add (node); - } + int ptr = 106; + byte[] buffer = owner.getDisk ().readSector (da); + while (buffer[ptr] != -1) + { + text.append (HexFormatter.getPascalString (buffer, ptr) + "\n"); + ptr += 10; + } + ptr += 2; + text.append ("\n"); + while (ptr < 512) + { + int value = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]); + text.append (String.format ("%04X %,6d%n", value, value)); + ptr += 2; + } - private void linkSpells (String title, DiskAddress da, DefaultMutableTreeNode headerNode) - { - List blocks = new ArrayList (); - blocks.add (da); - int level = 1; + DefaultAppleFileSource dafs = + new DefaultAppleFileSource (title, text.toString (), owner); + dafs.setSectors (blocks); + DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs); + node.setAllowsChildren (false); + headerNode.add (node); + } - StringBuilder list = new StringBuilder ("Level " + level + ":\n"); - byte[] buffer = owner.getDisk ().readSector (da); - String text = HexFormatter.getString (buffer, 0, 512); - String[] spells = text.split ("\n"); - for (String s : spells) - { - if (s.length () == 0) - break; - if (s.startsWith ("*")) - { - s = s.substring (1); - level++; - list.append ("\nLevel " + level + ":\n"); - } - list.append (" " + s + "\n"); - } + private void linkPictures (String title, DiskAddress da, + DefaultMutableTreeNode headerNode) + { + List blocks = new ArrayList (); + blocks.add (da); - DefaultAppleFileSource dafs = new DefaultAppleFileSource (title, list.toString (), owner); - dafs.setSectors (blocks); - DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs); - node.setAllowsChildren (false); - headerNode.add (node); - } + byte[] buffer = owner.getDisk ().readSector (da); + String text = printChars (buffer, 0); - private String printChars (byte[] buffer, int block) - { - StringBuilder text = new StringBuilder (); - for (int i = block * 512; i < (block + 1) * 512; i += 64) - { - for (int line = 0; line < 8; line++) - { - for (int j = 0; j < 8; j++) - { - int value = HexFormatter.intValue (buffer[i + line + j * 8]); - for (int bit = 0; bit < 7; bit++) - { - if ((value & 0x01) == 1) - text.append ("O"); - else - text.append ("."); - value >>= 1; - } - text.append (" "); - } - text.append ("\n"); - } - text.append ("\n"); - } - return text.toString (); - } + DefaultAppleFileSource dafs = new DefaultAppleFileSource (title, text, owner); + dafs.setSectors (blocks); + DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs); + node.setAllowsChildren (false); + headerNode.add (node); + } - // this could be the base factory class for all Wizardry types - class ScenarioData - { - int dunno; - int total; - int totalBlocks; - int dataOffset; - int type; - List sectors; + private void linkSpells (String title, DiskAddress da, + DefaultMutableTreeNode headerNode) + { + List blocks = new ArrayList (); + blocks.add (da); + int level = 1; - public ScenarioData (byte[] buffer, int seq, List sectors) - { - int offset = 42 + seq * 2; - dunno = HexFormatter.intValue (buffer[offset]); - total = HexFormatter.intValue (buffer[offset + 16]); - totalBlocks = HexFormatter.intValue (buffer[offset + 32]); - dataOffset = HexFormatter.intValue (buffer[offset + 48]); - type = seq; + StringBuilder list = new StringBuilder ("Level " + level + ":\n"); + byte[] buffer = owner.getDisk ().readSector (da); + String text = HexFormatter.getString (buffer, 0, 512); + String[] spells = text.split ("\n"); + for (String s : spells) + { + if (s.length () == 0) + break; + if (s.startsWith ("*")) + { + s = s.substring (1); + level++; + list.append ("\nLevel " + level + ":\n"); + } + list.append (" " + s + "\n"); + } - this.sectors = new ArrayList (totalBlocks); - for (int i = dataOffset, max = dataOffset + totalBlocks; i < max; i++) - this.sectors.add (sectors.get (i)); - } + DefaultAppleFileSource dafs = + new DefaultAppleFileSource (title, list.toString (), owner); + dafs.setSectors (blocks); + DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs); + node.setAllowsChildren (false); + headerNode.add (node); + } - @Override - public String toString () - { - return String.format ("%-15s %3d %3d %3d %3d", typeText[type], dataOffset, - totalBlocks, total, dunno); - } - } + private String printChars (byte[] buffer, int block) + { + StringBuilder text = new StringBuilder (); + for (int i = block * 512; i < (block + 1) * 512; i += 64) + { + for (int line = 0; line < 8; line++) + { + for (int j = 0; j < 8; j++) + { + int value = HexFormatter.intValue (buffer[i + line + j * 8]); + for (int bit = 0; bit < 7; bit++) + { + if ((value & 0x01) == 1) + text.append ("O"); + else + text.append ("."); + value >>= 1; + } + text.append (" "); + } + text.append ("\n"); + } + text.append ("\n"); + } + return text.toString (); + } + + // this could be the base factory class for all Wizardry types + class ScenarioData + { + int dunno; + int total; + int totalBlocks; + int dataOffset; + int type; + List sectors; + + public ScenarioData (byte[] buffer, int seq, List sectors) + { + int offset = 42 + seq * 2; + dunno = HexFormatter.intValue (buffer[offset]); + total = HexFormatter.intValue (buffer[offset + 16]); + totalBlocks = HexFormatter.intValue (buffer[offset + 32]); + dataOffset = HexFormatter.intValue (buffer[offset + 48]); + type = seq; + + this.sectors = new ArrayList (totalBlocks); + for (int i = dataOffset, max = dataOffset + totalBlocks; i < max; i++) + if (i < sectors.size ()) + this.sectors.add (sectors.get (i)); + } + + @Override + public String toString () + { + return String.format ("%-15s %3d %3d %3d %3d", typeText[type], dataOffset, + totalBlocks, total, dunno); + } + } } \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/wizardry/Huffman.java b/src/com/bytezone/diskbrowser/wizardry/Huffman.java new file mode 100644 index 0000000..07efe2b --- /dev/null +++ b/src/com/bytezone/diskbrowser/wizardry/Huffman.java @@ -0,0 +1,69 @@ +package com.bytezone.diskbrowser.wizardry; + +public class Huffman +{ + private final byte[] tree; + private final byte[] left; + private final byte[] right; + + private int bit = 0; + private int msgPtr = 0; + private int b = 0; + private byte[] message; + + public Huffman (byte[] buffer) + { + tree = new byte[256]; + left = new byte[256]; + right = new byte[256]; + + System.arraycopy (buffer, 0, tree, 0, 256); + System.arraycopy (buffer, 256, left, 0, 256); + System.arraycopy (buffer, 512, right, 0, 256); + } + + public String getMessage (byte[] message) + { + this.message = message; + bit = 0; + msgPtr = 0; + b = 0; + + int len = getChar (); + StringBuilder text = new StringBuilder (); + for (int i = 0; i < len; i++) + text.append ((char) getChar ()); + return text.toString (); + } + + private byte getChar () + { + int treePtr = 0; + + while (true) + { + if (bit == 0) + { + bit = 8; + b = message[msgPtr++] & 0xFF; + } + + int thisBit = b % 2; + b /= 2; + bit--; + + if (thisBit == 0) // take right path + { + if ((tree[treePtr] & 0x02) != 0) // if has right leaf + return right[treePtr]; + treePtr = right[treePtr]; // go to right node + } + else // take left path + { + if ((tree[treePtr] & 0x01) != 0) // if has left leaf + return left[treePtr]; + treePtr = left[treePtr]; // go to left node + } + } + } +} \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/wizardry/MessageBlock.java b/src/com/bytezone/diskbrowser/wizardry/MessageBlock.java new file mode 100644 index 0000000..259a7ae --- /dev/null +++ b/src/com/bytezone/diskbrowser/wizardry/MessageBlock.java @@ -0,0 +1,58 @@ +package com.bytezone.diskbrowser.wizardry; + +import java.util.ArrayList; +import java.util.List; + +import com.bytezone.common.Utility; + +public class MessageBlock +{ + private final byte[] buffer; + private final int indexOffset; + private final int indexLength; + + private final List messageDataBlocks = + new ArrayList (); + + public MessageBlock (byte[] buffer) + { + this.buffer = buffer; + + indexOffset = Utility.getWord (buffer, 0); + indexLength = Utility.getWord (buffer, 2); + + int ptr = indexOffset * 512; + + for (int i = 0, max = indexLength / 2; i < max; i++) + { + int firstMessageNo = Utility.getWord (buffer, ptr + i * 2); + MessageDataBlock messageDataBlock = + new MessageDataBlock (buffer, i * 512, firstMessageNo); + messageDataBlocks.add (messageDataBlock); + } + } + + 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 int getBlock (int msgNo) + // { + // int ptr = indexOffset * 512; + // + // for (int i = 0; i < indexLength; i += 2) + // { + // int msg = Utility.getWord (buffer, ptr + i); + // if (msg > msgNo) + // return i - 1; + // } + // return indexLength - 1; + // } +} \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/wizardry/MessageDataBlock.java b/src/com/bytezone/diskbrowser/wizardry/MessageDataBlock.java new file mode 100644 index 0000000..9c97f9f --- /dev/null +++ b/src/com/bytezone/diskbrowser/wizardry/MessageDataBlock.java @@ -0,0 +1,130 @@ +package com.bytezone.diskbrowser.wizardry; + +import java.util.ArrayList; +import java.util.List; + +import com.bytezone.common.Utility; +import com.bytezone.diskbrowser.utilities.HexFormatter; + +public class MessageDataBlock +{ + private final byte[] buffer; + private final int offset; + final int firstMessageNo; + + private final int groupCount; + private final List messages = new ArrayList (); + + public MessageDataBlock (byte[] buffer, int offset, int firstMessageNo) + { + this.buffer = buffer; + this.offset = offset; + this.firstMessageNo = firstMessageNo; + + boolean debug = firstMessageNo == 0; + + if (debug) + { + System.out.println (HexFormatter.format (buffer, offset, 512)); + System.out.println (); + } + + int ptr = offset + 0x1FF; // last byte in block + groupCount = buffer[ptr--] & 0xFF; + + int currentMessageNo = firstMessageNo; + int totalMessageBytes = 0; + + for (int i = 0, max = groupCount - 1; i < groupCount; i++, max--) + { + int huffBytes = buffer[ptr]; + + for (int j = 0; j < huffBytes; j++) + { + int messageLength = buffer[ptr - j - 1] & 0xFF; + totalMessageBytes += messageLength; + Message message = new Message (currentMessageNo + j, + offset + totalMessageBytes - messageLength, messageLength); + messages.add (message); + } + + ptr -= huffBytes; + currentMessageNo += huffBytes; + + ptr--; + + if (max > 0) + { + byte gap = buffer[ptr--]; + int skip = gap & 0xFF; + + if ((gap & 0x80) != 0) // is high bit set? + { + gap &= 0x7F; + int gap2 = buffer[ptr--] & 0xFF; + skip = gap * 256 + gap2; + } + + skip--; + currentMessageNo += skip; + } + } + + if (debug) + System.out.println (this); + } + + byte[] getMessage (int messageNo) + { + for (Message message : messages) + if (message.msgNo == messageNo) + { + byte[] returnMessage = new byte[message.length]; + System.arraycopy (buffer, message.offset, returnMessage, 0, message.length); + return returnMessage; + } + return null; + } + + @Override + public String toString () + { + StringBuilder text = new StringBuilder (); + + for (Message message : messages) + { + text.append (message); + text.append ("\n"); + } + + if (text.length () > 0) + text.deleteCharAt (text.length () - 1); + + return text.toString (); + } + + class Message + { + final int msgNo; + final int offset; + final int length; + + public Message (int msgNo, int offset, int length) + { + this.msgNo = msgNo; + this.offset = offset; + this.length = length; + } + + @Override + public String toString () + { + StringBuilder text = new StringBuilder (); + + String data = Utility.getHex (buffer, offset, length); + text.append (String.format ("%5d: %02X %02X : %s", msgNo, offset, length, data)); + + return text.toString (); + } + } +} \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/wizardry/Wizardry4BootDisk.java b/src/com/bytezone/diskbrowser/wizardry/Wizardry4BootDisk.java index a8f623a..55fd7ab 100644 --- a/src/com/bytezone/diskbrowser/wizardry/Wizardry4BootDisk.java +++ b/src/com/bytezone/diskbrowser/wizardry/Wizardry4BootDisk.java @@ -11,16 +11,18 @@ import com.bytezone.diskbrowser.disk.AppleDisk; import com.bytezone.diskbrowser.disk.DefaultAppleFileSource; 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.PascalDisk; import com.bytezone.diskbrowser.utilities.Utility; +import com.bytezone.diskbrowser.wizardry.Header.ScenarioData; public class Wizardry4BootDisk extends PascalDisk { + public Header scenarioHeader; List disks = new ArrayList (); // protected Disk[] dataDisks; private Relocator relocator; + private MessageBlock messageBlock; public Wizardry4BootDisk (AppleDisk[] dataDisks) { @@ -34,7 +36,6 @@ public class Wizardry4BootDisk extends PascalDisk // get the relocation table DefaultMutableTreeNode relocNode = findNode (currentRoot, "SYSTEM.RELOC"); FileEntry fileEntry = (FileEntry) relocNode.getUserObject (); - if (fileEntry != null) { relocator = @@ -46,7 +47,6 @@ public class Wizardry4BootDisk extends PascalDisk // reset the code segment so that it rebuilds itself from the new data DefaultMutableTreeNode pascalNode = findNode (currentRoot, "SYSTEM.PASCAL"); fileEntry = (FileEntry) pascalNode.getUserObject (); - if (fileEntry != null) { fileEntry.setFile (null); @@ -55,54 +55,99 @@ public class Wizardry4BootDisk extends PascalDisk DefaultMutableTreeNode scenarioNode = findNode (currentRoot, "SCENARIO.DATA"); fileEntry = (FileEntry) scenarioNode.getUserObject (); - if (fileEntry != null) { fileEntry.setFile (null); + scenarioNode.setAllowsChildren (true); - - byte[] buffer = fileEntry.getDataSource ().buffer; - - for (int i = 0; i < 14; 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 blocks = new ArrayList (); - addToNode (maze, scenarioNode, blocks, null); - } + scenarioHeader = new Header (scenarioNode, this); + linkMazeLevels (scenarioNode, fileEntry); } DefaultMutableTreeNode monstersNode = findNode (currentRoot, "200.MONSTERS"); fileEntry = (FileEntry) monstersNode.getUserObject (); - if (fileEntry != null) { - monstersNode.setAllowsChildren (true); - byte[] pictureBuffer = fileEntry.getDataSource ().buffer; - List pictureBlocks = fileEntry.getSectors (); + fileEntry.setFile (null); - int count = 0; - loop: for (int block = 0; block < 24; block++) + 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); + } + + DefaultMutableTreeNode huffNode = findNode (currentRoot, "ASCII.HUFF"); + fileEntry = (FileEntry) huffNode.getUserObject (); + if (fileEntry != null) + { + // byte[] tree = new byte[256]; + // byte[] left = new byte[256]; + // byte[] right = new byte[256]; + + byte[] buffer = fileEntry.getDataSource ().buffer; + + // System.arraycopy (buffer, 0, tree, 0, 256); + // System.arraycopy (buffer, 256, left, 0, 256); + // System.arraycopy (buffer, 512, right, 0, 256); + Huffman huffman = new Huffman (buffer); + + System.out.println (huffman.getMessage (messageBlock.getMessage (2043))); + System.out.println (huffman.getMessage (messageBlock.getMessage (2044))); + System.out.println (huffman.getMessage (messageBlock.getMessage (2045))); + } + } + + private void linkMazeLevels (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry) + { + ScenarioData mazeData = scenarioHeader.data.get (Header.MAZE_AREA); + + byte[] buffer = fileEntry.getDataSource ().buffer; + List blocks = fileEntry.getSectors (); + + DefaultMutableTreeNode mazeNode = linkNode ("Maze", "Levels string", scenarioNode); + for (int i = 0; i < 15; i++) + { + byte[] level = new byte[896]; + System.arraycopy (buffer, mazeData.dataOffset * 512 + i * 1024, level, 0, + level.length); + + List mazeBlocks = new ArrayList (); + 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 pictureBlocks = fileEntry.getSectors (); + + int count = 0; + for (int block = 0; block < 24; block++) + { + int ptr = block * 512; + for (int pic = 0; pic < 2; pic++) { - 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 blocks = new ArrayList (); - blocks.add (pictureBlocks.get (block)); - addToNode (image, monstersNode, blocks, null); - } + byte[] buffer = new byte[240]; + System.arraycopy (pictureBuffer, ptr + pic * 256, buffer, 0, 240); + Wiz4Image image = new Wiz4Image ("Image " + count++, buffer); + List monsterBlocks = new ArrayList (); + monsterBlocks.add (pictureBlocks.get (block)); + addToNode (image, monstersNode, monsterBlocks); } } } private void addToNode (AbstractFile af, DefaultMutableTreeNode node, - List blocks, SectorType type) + List blocks) { DefaultAppleFileSource dafs = new DefaultAppleFileSource (af.getName (), af, this, blocks); @@ -111,6 +156,15 @@ public class Wizardry4BootDisk extends PascalDisk childNode.setAllowsChildren (false); } + 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; + } + public static boolean isWizardryIVorV (Disk disk, boolean debug) { // Wizardry IV or V boot code diff --git a/src/com/bytezone/diskbrowser/wizardry/WizardryScenarioDisk.java b/src/com/bytezone/diskbrowser/wizardry/WizardryScenarioDisk.java index 3bd3275..1797902 100755 --- a/src/com/bytezone/diskbrowser/wizardry/WizardryScenarioDisk.java +++ b/src/com/bytezone/diskbrowser/wizardry/WizardryScenarioDisk.java @@ -488,12 +488,12 @@ public class WizardryScenarioDisk extends PascalDisk System.arraycopy (buffer, 0, data2, 0, data2.length); // System.out.println (HexFormatter.format (data2)); - MazeLevel model = new MazeLevel (data2, i + 1); - model.setMessages (messages); - model.setMonsters (monsters); - model.setItems (items); - levels.add (model); - addToNode (model, node, blocks, mazeSector); + 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 ();