added sectors to Node

This commit is contained in:
Denis Molony 2016-07-19 17:44:42 +10:00
parent edaa7954c7
commit 0108938fe7
4 changed files with 262 additions and 231 deletions

View File

@ -10,232 +10,236 @@ import com.bytezone.diskbrowser.utilities.HexFormatter;
class Dictionary extends AbstractFile
{
Map<Integer, ZString> dictionary;
int totalEntries;
int totalSeparators;
int dictionaryPtr, dictionarySize;
int entryLength;
Header header;
private final Map<Integer, ZString> dictionary;
private final int totalEntries;
private final int totalSeparators;
private final int dictionaryPtr, dictionarySize;
private final int entryLength;
private final Header header;
// this could be a Google Multimap
Map<Integer, List<WordEntry>> synonymList = new TreeMap<Integer, List<WordEntry>> ();
// this could be a Google Multimap
Map<Integer, List<WordEntry>> synonymList = new TreeMap<Integer, List<WordEntry>> ();
public Dictionary (Header header)
{
super ("Dictionary", header.buffer);
this.header = header;
public Dictionary (Header header)
{
super ("Dictionary", header.buffer);
this.header = header;
dictionaryPtr = header.dictionaryOffset;
dictionary = new TreeMap<Integer, ZString> ();
dictionaryPtr = header.dictionaryOffset;
dictionary = new TreeMap<Integer, ZString> ();
totalSeparators = buffer[dictionaryPtr] & 0xFF;
int ptr = dictionaryPtr + totalSeparators + 1;
entryLength = buffer[ptr++] & 0xFF;
totalSeparators = buffer[dictionaryPtr] & 0xFF;
int ptr = dictionaryPtr + totalSeparators + 1;
entryLength = buffer[ptr++] & 0xFF;
totalEntries = header.getWord (ptr);
totalEntries = header.getWord (ptr);
ptr += 2;
int count = 0;
for (int i = 0; i < totalEntries; i++)
{
ZString string = new ZString (buffer, ptr, header);
dictionary.put (ptr, string);
WordEntry wordEntry = new WordEntry (string, count++);
ptr += 2;
int count = 0;
for (int i = 0; i < totalEntries; i++)
{
ZString string = new ZString (buffer, ptr, header);
dictionary.put (ptr, string);
WordEntry wordEntry = new WordEntry (string, count++);
// add the WordEntry to the appropriate list
List<WordEntry> wordEntryList = synonymList.get (wordEntry.key);
if (wordEntryList == null)
{
wordEntryList = new ArrayList<WordEntry> ();
synonymList.put (wordEntry.key, wordEntryList);
}
wordEntryList.add (wordEntry);
// add the WordEntry to the appropriate list
List<WordEntry> wordEntryList = synonymList.get (wordEntry.key);
if (wordEntryList == null)
{
wordEntryList = new ArrayList<WordEntry> ();
synonymList.put (wordEntry.key, wordEntryList);
}
wordEntryList.add (wordEntry);
// check for words with the property flag
if ((buffer[ptr + 4] & 0x10) != 0)
{
int b1 = buffer[ptr + 5] & 0xFF;
int property = (b1 >= 1 && b1 <= 31) ? b1 : buffer[ptr + 6] & 0xFF;
if (header.propertyNames[property] == null
|| header.propertyNames[property].length () > string.value.length ())
header.propertyNames[property] = string.value;
}
ptr += entryLength;
}
// check for words with the property flag
if ((buffer[ptr + 4] & 0x10) != 0)
{
int b1 = buffer[ptr + 5] & 0xFF;
int property = (b1 >= 1 && b1 <= 31) ? b1 : buffer[ptr + 6] & 0xFF;
if (header.propertyNames[property] == null
|| header.propertyNames[property].length () > string.value.length ())
header.propertyNames[property] = string.value;
}
ptr += entryLength;
}
dictionarySize = totalSeparators + 3 + entryLength * totalEntries;
dictionarySize = totalSeparators + 3 + entryLength * totalEntries;
for (int i = 1; i < header.propertyNames.length; i++)
if (header.propertyNames[i] == null)
header.propertyNames[i] = i + "";
}
for (int i = 1; i < header.propertyNames.length; i++)
if (header.propertyNames[i] == null)
header.propertyNames[i] = i + "";
}
public boolean containsWordAt (int address)
{
return dictionary.containsKey (address);
}
public boolean containsWordAt (int address)
{
return dictionary.containsKey (address);
}
public String wordAt (int address)
{
if (dictionary.containsKey (address))
return dictionary.get (address).value;
return "dictionary can't find word @ " + address;
}
public String wordAt (int address)
{
if (dictionary.containsKey (address))
return dictionary.get (address).value;
return "dictionary can't find word @ " + address;
}
public List<String> getVerbs (int value)
{
List<String> words = new ArrayList<String> ();
int ptr = dictionaryPtr + totalSeparators + 4;
public List<String> getVerbs (int value)
{
List<String> words = new ArrayList<String> ();
int ptr = dictionaryPtr + totalSeparators + 4;
for (ZString word : dictionary.values ())
{
int b1 = buffer[ptr + 4] & 0xFF;
int b2 = buffer[ptr + 5] & 0xFF;
int b3 = buffer[ptr + 6] & 0xFF;
// mask seems to be 0x40
if ((b1 == 0x41 && b2 == value) || ((b1 == 0x62 || b1 == 0xC0 || b1 == 0x44) && b3 == value))
words.add (word.value);
ptr += entryLength;
}
return words;
}
for (ZString word : dictionary.values ())
{
int b1 = buffer[ptr + 4] & 0xFF;
int b2 = buffer[ptr + 5] & 0xFF;
int b3 = buffer[ptr + 6] & 0xFF;
// mask seems to be 0x40
if ((b1 == 0x41 && b2 == value)
|| ((b1 == 0x62 || b1 == 0xC0 || b1 == 0x44) && b3 == value))
words.add (word.value);
ptr += entryLength;
}
return words;
}
public List<String> getPrepositions (int value)
{
List<String> words = new ArrayList<String> ();
int ptr = dictionaryPtr + totalSeparators + 4;
public List<String> getPrepositions (int value)
{
List<String> words = new ArrayList<String> ();
int ptr = dictionaryPtr + totalSeparators + 4;
for (ZString word : dictionary.values ())
{
int b1 = buffer[ptr + 4] & 0xFF;
int b2 = buffer[ptr + 5] & 0xFF;
int b3 = buffer[ptr + 6] & 0xFF;
// mask seems to be 0x08
if (((b1 == 0x08 || b1 == 0x18 || b1 == 0x48) && b2 == value)
|| ((b1 == 0x1B || b1 == 0x0C || b1 == 0x2A) && b3 == value))
words.add (word.value);
ptr += entryLength;
}
return words;
}
for (ZString word : dictionary.values ())
{
int b1 = buffer[ptr + 4] & 0xFF;
int b2 = buffer[ptr + 5] & 0xFF;
int b3 = buffer[ptr + 6] & 0xFF;
// mask seems to be 0x08
if (((b1 == 0x08 || b1 == 0x18 || b1 == 0x48) && b2 == value)
|| ((b1 == 0x1B || b1 == 0x0C || b1 == 0x2A) && b3 == value))
words.add (word.value);
ptr += entryLength;
}
return words;
}
@Override
public String getHexDump ()
{
StringBuilder text = new StringBuilder ();
text.append (HexFormatter.format (buffer, dictionaryPtr, dictionarySize));
return text.toString ();
}
@Override
public String getHexDump ()
{
StringBuilder text = new StringBuilder ();
text.append (HexFormatter.format (buffer, dictionaryPtr, dictionarySize));
return text.toString ();
}
@Override
public String getText ()
{
StringBuilder text = new StringBuilder ();
@Override
public String getText ()
{
StringBuilder text = new StringBuilder ();
// text.append (String.format ("Total entries : %,6d%n", totalEntries));
// text.append (String.format ("Separators : %,6d%n", totalSeparators));
// text.append (String.format ("Offset : %,6d %04X%n%n", dictionaryPtr, dictionaryPtr));
// text.append (String.format ("Total entries : %,6d%n", totalEntries));
// text.append (String.format ("Separators : %,6d%n", totalSeparators));
// text.append (String.format ("Offset : %,6d %04X%n%n", dictionaryPtr, dictionaryPtr));
int count = 0;
int ptr = dictionaryPtr + totalSeparators + 4;
int count = 0;
int ptr = dictionaryPtr + totalSeparators + 4;
for (ZString word : dictionary.values ())
{
text.append (String.format ("%04X %3d %-6s %s", ptr, count++, word.value, HexFormatter
.getHexString (buffer, ptr + 4, entryLength - 4)));
int b1 = buffer[ptr + 4] & 0xFF;
int b2 = buffer[ptr + 5] & 0xFF;
int b3 = buffer[ptr + 6] & 0xFF;
if (b1 == 65)
text.append (String.format (" %3d%n", b2));
else if (b1 == 98 || b1 == 0xC0 || b1 == 0x44)
text.append (String.format (" %3d%n", b3));
else
text.append ("\n");
ptr += entryLength;
}
for (ZString word : dictionary.values ())
{
text.append (String
.format ("%04X %3d %-6s %s", ptr, count++, word.value,
HexFormatter.getHexString (buffer, ptr + 4, entryLength - 4)));
int b1 = buffer[ptr + 4] & 0xFF;
int b2 = buffer[ptr + 5] & 0xFF;
int b3 = buffer[ptr + 6] & 0xFF;
if (b1 == 65)
text.append (String.format (" %3d%n", b2));
else if (b1 == 98 || b1 == 0xC0 || b1 == 0x44)
text.append (String.format (" %3d%n", b3));
else
text.append ("\n");
ptr += entryLength;
}
if (true)
{
int lastValue = 0;
for (List<WordEntry> list : synonymList.values ())
{
WordEntry wordEntry = list.get (0);
if (wordEntry.value != lastValue)
{
lastValue = wordEntry.value;
text.append ("\n");
}
if (true)
{
int lastValue = 0;
for (List<WordEntry> list : synonymList.values ())
{
WordEntry wordEntry = list.get (0);
if (wordEntry.value != lastValue)
{
lastValue = wordEntry.value;
text.append ("\n");
}
if (wordEntry.value == 0x80) // nouns are all in one entry
{
for (WordEntry we : list)
text.append (we + "\n");
text.deleteCharAt (text.length () - 1);
}
else
text.append (wordEntry);
if ((buffer[wordEntry.word.startPtr + 4] & 0x10) != 0)
text.append (" property");
text.append ("\n");
}
}
if (wordEntry.value == 0x80) // nouns are all in one entry
{
for (WordEntry we : list)
text.append (we + "\n");
text.deleteCharAt (text.length () - 1);
}
else
text.append (wordEntry);
if ((buffer[wordEntry.word.startPtr + 4] & 0x10) != 0)
text.append (" property");
text.append ("\n");
}
}
text.deleteCharAt (text.length () - 1);
return text.toString ();
}
text.deleteCharAt (text.length () - 1);
return text.toString ();
}
private class WordEntry implements Comparable<WordEntry>
{
ZString word;
int seq;
int value;
int key;
String bits;
private class WordEntry implements Comparable<WordEntry>
{
ZString word;
int seq;
int value;
int key;
String bits;
public WordEntry (ZString word, int seq)
{
this.word = word;
this.seq = seq;
public WordEntry (ZString word, int seq)
{
this.word = word;
this.seq = seq;
// build key from 3 bytes following the word characters
int b1 = buffer[word.startPtr + 4] & 0xFF;
int b2 = buffer[word.startPtr + 5] & 0xFF;
int b3 = buffer[word.startPtr + 6] & 0xFF;
// build key from 3 bytes following the word characters
int b1 = buffer[word.startPtr + 4] & 0xFF;
int b2 = buffer[word.startPtr + 5] & 0xFF;
int b3 = buffer[word.startPtr + 6] & 0xFF;
this.key = (b1 << 16) | (b2 << 8) | b3;
this.value = b1;
this.bits = Integer.toBinaryString (b1);
if (bits.length () < 8)
bits = "00000000".substring (bits.length ()) + bits;
}
this.key = (b1 << 16) | (b2 << 8) | b3;
this.value = b1;
this.bits = Integer.toBinaryString (b1);
if (bits.length () < 8)
bits = "00000000".substring (bits.length ()) + bits;
}
@Override
public int compareTo (WordEntry o)
{
return this.value - o.value;
}
@Override
public int compareTo (WordEntry o)
{
return this.value - o.value;
}
@Override
public String toString ()
{
StringBuilder list = new StringBuilder ("[");
if ((key & 0x0800000) == 0)
{
for (WordEntry we : synonymList.get (key))
list.append (we.word.value + ", ");
list.deleteCharAt (list.length () - 1);
list.deleteCharAt (list.length () - 1);
}
else
list.append (word.value);
list.append ("]");
@Override
public String toString ()
{
StringBuilder list = new StringBuilder ("[");
if ((key & 0x0800000) == 0)
{
for (WordEntry we : synonymList.get (key))
list.append (we.word.value + ", ");
list.deleteCharAt (list.length () - 1);
list.deleteCharAt (list.length () - 1);
}
else
list.append (word.value);
list.append ("]");
StringBuilder text = new StringBuilder ();
text.append (String.format ("%04X %3d %-6s %s %s %s", word.startPtr, seq,
word.value, bits, HexFormatter
.getHexString (buffer, word.startPtr + 4, entryLength - 4), list.toString ()));
return text.toString ();
}
}
StringBuilder text = new StringBuilder ();
text.append (String.format ("%04X %3d %-6s %s %s %s", word.startPtr, seq,
word.value, bits,
HexFormatter.getHexString (buffer, word.startPtr + 4,
entryLength - 4),
list.toString ()));
return text.toString ();
}
}
}

View File

@ -28,17 +28,17 @@ class Grammar extends InfocomAbstractFile
super (name, buffer);
this.header = header;
indexPtr = header.staticMemory; // start of the index
tablePtr = header.getWord (indexPtr); // start of the data (end of the index)
indexPtr = header.staticMemory; // start of the index
tablePtr = header.getWord (indexPtr); // start of the data (end of the index)
indexSize = tablePtr - indexPtr;
indexEntries = indexSize / 2;
padding = getPadding ();
int lastEntry = header.getWord (tablePtr - 2); // address of the last data entry
int lastEntry = header.getWord (tablePtr - 2); // address of the last data entry
tableSize = lastEntry + getRecordLength (lastEntry) - tablePtr; // uses padding
actionPtr = tablePtr + tableSize; // start of the action routines
actionSize = getTotalActions () * 2; // uses padding
actionPtr = tablePtr + tableSize; // start of the action routines
actionSize = getTotalActions () * 2; // uses padding
preActionSize = actionSize;
preActionPtr = actionPtr + actionSize;
@ -80,14 +80,14 @@ class Grammar extends InfocomAbstractFile
sentenceGroups.add (sg);
for (Sentence sentence : sg)
{
// add to hashmap
if (!actionList.containsKey (sentence.actionId))
if (!actionList.containsKey (sentence.actionId)) // add to hashmap
actionList.put (sentence.actionId, new ArrayList<Sentence> ());
actionList.get (sentence.actionId).add (sentence);
// add to pre-action routine list
if (sentence.preActionRoutine > 0
if (sentence.preActionRoutine > 0 // add to pre-action routine list
&& !preActionRoutines.contains (sentence.preActionRoutine))
preActionRoutines.add (sentence.preActionRoutine);
// add to action routine list
if (sentence.actionRoutine > 0
&& !actionRoutines.contains (sentence.actionRoutine))
@ -127,9 +127,9 @@ class Grammar extends InfocomAbstractFile
highest = val;
ptr += SENTENCE_LENGTH;
}
ptr += padding; // could be zero or one
ptr += padding; // could be zero or one
}
return highest + 1; // zero-based, so increment it
return highest + 1; // zero-based, so increment it
}
public List<Integer> getActionRoutines ()
@ -268,8 +268,8 @@ class Grammar extends InfocomAbstractFile
int startPtr;
SentenceGroup parent;
int actionId;
int actionRoutine; // mandatory
int preActionRoutine; // optional
int actionRoutine; // mandatory
int preActionRoutine; // optional
String sentenceText;
public Sentence (int ptr, SentenceGroup parent)

View File

@ -6,7 +6,7 @@ class Header extends InfocomAbstractFile
{
final String[] propertyNames = new String[32];
File file;
private final File file;
int version;
int highMemory;
int programCounter;
@ -49,7 +49,7 @@ class Header extends InfocomAbstractFile
// do the basic managers
abbreviations = new Abbreviations (this);
dictionary = new Dictionary (this);
globals = new Globals (this); // may display ZStrings
globals = new Globals (this); // may display ZStrings
// set up an empty object to store Routines in
codeManager = new CodeManager (this);
@ -63,9 +63,9 @@ class Header extends InfocomAbstractFile
stringManager = new StringManager ("Strings", buffer, this);
codeManager.addRoutine (programCounter - 1, 0);
codeManager.addActionRoutines (); // obtained from Grammar
codeManager.addCodeRoutines (); // obtained from Object properties
codeManager.addMissingRoutines (); // requires stringPtr to be set
codeManager.addActionRoutines (); // obtained from Grammar
codeManager.addCodeRoutines (); // obtained from Object properties
codeManager.addMissingRoutines (); // requires stringPtr to be set
// add entries for AbstractFile.getHexDump ()
hexBlocks.add (new HexBlock (0, 64, "Header data:"));

View File

@ -4,6 +4,7 @@ import java.awt.Color;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
@ -48,23 +49,37 @@ public class InfocomDisk extends AbstractFormattedDisk
createStoryFile ("Zork1.sf");
DefaultMutableTreeNode root = getCatalogTreeRoot ();
DefaultMutableTreeNode headerNode = null;
DefaultMutableTreeNode abbreviationsNode = null;
DefaultMutableTreeNode codeNode = null;
DefaultMutableTreeNode objectNode = null;
DefaultMutableTreeNode globalsNode = null;
DefaultMutableTreeNode grammarNode = null;
DefaultMutableTreeNode dictionaryNode = null;
DefaultMutableTreeNode stringsNode = null;
header = new Header ("Header", data, disk.getFile ());
addToTree (root, "Header", header, TYPE_LEAF);
addToTree (root, "Abbreviations", header.abbreviations, TYPE_LEAF);
headerNode = addToTree (root, "Header", header, TYPE_LEAF);
DefaultAppleFileSource dafs = (DefaultAppleFileSource) headerNode.getUserObject ();
List<DiskAddress> blocks = new ArrayList<DiskAddress> ();
blocks.add (disk.getDiskAddress (3, 0));
dafs.setSectors (blocks);
abbreviationsNode =
addToTree (root, "Abbreviations", header.abbreviations, TYPE_LEAF);
objectNode = addToTree (root, "Objects", header.objectManager, TYPE_NODE);
header.objectManager.addNodes (objectNode, this);
addToTree (root, "Globals", header.globals, TYPE_LEAF);
addToTree (root, "Grammar", header.grammar, TYPE_LEAF);
addToTree (root, "Dictionary", header.dictionary, TYPE_LEAF);
globalsNode = addToTree (root, "Globals", header.globals, TYPE_LEAF);
grammarNode = addToTree (root, "Grammar", header.grammar, TYPE_LEAF);
dictionaryNode = addToTree (root, "Dictionary", header.dictionary, TYPE_LEAF);
codeNode = addToTree (root, "Code", header.codeManager, TYPE_NODE);
header.codeManager.addNodes (codeNode, this);
addToTree (root, "Strings", header.stringManager, TYPE_LEAF);
stringsNode = addToTree (root, "Strings", header.stringManager, TYPE_LEAF);
PropertyManager pm = new PropertyManager ("Properties", data, header);
pm.addNodes (addToTree (objectNode, "Properties", pm, TYPE_NODE), this);
@ -74,13 +89,17 @@ public class InfocomDisk extends AbstractFormattedDisk
sectorTypes[48] = headerSector;
setSectors (header.abbreviationsTable, header.objectTable, abbreviationsSector);
setSectors (header.objectTable, header.globalsOffset, objectsSector);
setSectors (header.globalsOffset, header.staticMemory, globalsSector);
setSectors (header.staticMemory, header.dictionaryOffset, grammarSector);
setSectors (header.dictionaryOffset, header.highMemory, dictionarySector);
setSectors (header.highMemory, header.stringPointer, codeSector);
setSectors (header.stringPointer, header.fileLength, stringsSector);
setSectorTypes (header.abbreviationsTable, header.objectTable, abbreviationsSector,
abbreviationsNode);
setSectorTypes (header.objectTable, header.globalsOffset, objectsSector, objectNode);
setSectorTypes (header.globalsOffset, header.staticMemory, globalsSector,
globalsNode);
setSectorTypes (header.staticMemory, header.dictionaryOffset, grammarSector,
grammarNode);
setSectorTypes (header.dictionaryOffset, header.highMemory, dictionarySector,
dictionaryNode);
setSectorTypes (header.highMemory, header.stringPointer, codeSector, codeNode);
setSectorTypes (header.stringPointer, header.fileLength, stringsSector, stringsNode);
}
protected void setInfocomSectorTypes ()
@ -101,16 +120,22 @@ public class InfocomDisk extends AbstractFormattedDisk
sectorTypes[track * 16 + sector] = bootSector;
}
private void setSectors (int sectorFrom, int sectorTo, SectorType type)
private void setSectorTypes (int sectorFrom, int sectorTo, SectorType type,
DefaultMutableTreeNode node)
{
DefaultAppleFileSource dafs = (DefaultAppleFileSource) node.getUserObject ();
List<DiskAddress> blocks = new ArrayList<DiskAddress> ();
int blockNo = sectorFrom / disk.getBlockSize () + 48;
int blockTo = sectorTo / disk.getBlockSize () + 48;
while (blockNo <= blockTo)
{
blocks.add (disk.getDiskAddress (blockNo));
if (!disk.isSectorEmpty (blockNo))
sectorTypes[blockNo] = type;
blockNo++;
}
dafs.setSectors (blocks);
}
private int getFileSize ()
@ -162,8 +187,10 @@ public class InfocomDisk extends AbstractFormattedDisk
private DefaultMutableTreeNode addToTree (DefaultMutableTreeNode root, String title,
DataSource af, boolean allowsChildren)
{
DefaultMutableTreeNode node =
new DefaultMutableTreeNode (new DefaultAppleFileSource (title, af, this));
DefaultAppleFileSource dafs = new DefaultAppleFileSource (title, af, this);
// dafs.setSectors (blocks);
DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs);
node.setAllowsChildren (allowsChildren);
root.add (node);
return node;