mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2025-02-16 23:30:52 +00:00
moved HexBlock to Infocom package
This commit is contained in:
parent
4ba53dd1b0
commit
c4b086a096
@ -1,8 +1,6 @@
|
|||||||
package com.bytezone.diskbrowser.applefile;
|
package com.bytezone.diskbrowser.applefile;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
@ -16,7 +14,6 @@ public abstract class AbstractFile implements DataSource
|
|||||||
public byte[] buffer;
|
public byte[] buffer;
|
||||||
AssemblerProgram assembler;
|
AssemblerProgram assembler;
|
||||||
protected BufferedImage image;
|
protected BufferedImage image;
|
||||||
protected List<HexBlock> hexBlocks = new ArrayList<HexBlock> ();
|
|
||||||
|
|
||||||
public AbstractFile (String name, byte[] buffer)
|
public AbstractFile (String name, byte[] buffer)
|
||||||
{
|
{
|
||||||
@ -25,7 +22,7 @@ public abstract class AbstractFile implements DataSource
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getText () // Override this to get a tailored text representation
|
public String getText () // Override this to get a tailored text representation
|
||||||
{
|
{
|
||||||
return "Name : " + name + "\n\nNo text description";
|
return "Name : " + name + "\n\nNo text description";
|
||||||
}
|
}
|
||||||
@ -35,31 +32,16 @@ public abstract class AbstractFile implements DataSource
|
|||||||
{
|
{
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
return "No buffer";
|
return "No buffer";
|
||||||
|
|
||||||
if (assembler == null)
|
if (assembler == null)
|
||||||
this.assembler = new AssemblerProgram (name, buffer, 0);
|
this.assembler = new AssemblerProgram (name, buffer, 0);
|
||||||
|
|
||||||
return assembler.getText ();
|
return assembler.getText ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getHexDump ()
|
public String getHexDump ()
|
||||||
{
|
{
|
||||||
if (hexBlocks.size () > 0)
|
|
||||||
{
|
|
||||||
StringBuilder text = new StringBuilder ();
|
|
||||||
|
|
||||||
for (HexBlock hb : hexBlocks)
|
|
||||||
{
|
|
||||||
if (hb.title != null)
|
|
||||||
text.append (hb.title + "\n\n");
|
|
||||||
text.append (HexFormatter.format (buffer, hb.ptr, hb.size) + "\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
text.deleteCharAt (text.length () - 1);
|
|
||||||
text.deleteCharAt (text.length () - 1);
|
|
||||||
|
|
||||||
return text.toString ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer == null || buffer.length == 0)
|
if (buffer == null || buffer.length == 0)
|
||||||
return "No buffer";
|
return "No buffer";
|
||||||
|
|
||||||
@ -82,18 +64,4 @@ public abstract class AbstractFile implements DataSource
|
|||||||
JPanel panel = new JPanel ();
|
JPanel panel = new JPanel ();
|
||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class HexBlock
|
|
||||||
{
|
|
||||||
public int ptr;
|
|
||||||
public int size;
|
|
||||||
public String title;
|
|
||||||
|
|
||||||
public HexBlock (int ptr, int size, String title)
|
|
||||||
{
|
|
||||||
this.ptr = ptr;
|
|
||||||
this.size = size;
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -45,28 +45,34 @@ public class AssemblerProgram extends AbstractFile
|
|||||||
@Override
|
@Override
|
||||||
public String getHexDump ()
|
public String getHexDump ()
|
||||||
{
|
{
|
||||||
String text = super.getHexDump ();
|
// String text = super.getHexDump ();
|
||||||
|
String text = HexFormatter.format (buffer, 0, buffer.length, loadAddress);
|
||||||
|
|
||||||
if (extraBuffer.length == 0)
|
if (extraBuffer.length == 0)
|
||||||
return text;
|
return text;
|
||||||
|
|
||||||
return text + "\n\n"
|
return text + "\n\n" + HexFormatter.format (extraBuffer, 0, extraBuffer.length,
|
||||||
+ HexFormatter.format (extraBuffer, 0, extraBuffer.length, buffer.length);
|
loadAddress + buffer.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAssembler ()
|
public String getAssembler ()
|
||||||
{
|
{
|
||||||
String text = super.getAssembler ();
|
// String text = super.getAssembler ();
|
||||||
|
if (buffer == null)
|
||||||
|
return "No buffer";
|
||||||
|
if (assembler == null)
|
||||||
|
this.assembler = new AssemblerProgram (name, buffer, loadAddress);
|
||||||
|
// return assembler.getText ();
|
||||||
|
|
||||||
if (extraBuffer.length == 0)
|
if (extraBuffer.length == 0)
|
||||||
return text;
|
return assembler.getText ();
|
||||||
|
|
||||||
String extraName = String.format ("%s (extra)", name);
|
String extraName = String.format ("%s (extra)", name);
|
||||||
AssemblerProgram assemblerProgram =
|
AssemblerProgram assemblerProgram =
|
||||||
new AssemblerProgram (extraName, extraBuffer, buffer.length);
|
new AssemblerProgram (extraName, extraBuffer, loadAddress + buffer.length);
|
||||||
|
|
||||||
return text + "\n\n" + assemblerProgram.getText ();
|
return assembler.getText () + "\n\n" + assemblerProgram.getText ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -3,72 +3,70 @@ package com.bytezone.diskbrowser.infocom;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
class Abbreviations extends InfocomAbstractFile
|
||||||
|
|
||||||
class Abbreviations extends AbstractFile
|
|
||||||
{
|
{
|
||||||
List<ZString> list;
|
List<ZString> list;
|
||||||
Header header;
|
Header header;
|
||||||
int dataPtr;
|
int dataPtr;
|
||||||
int dataSize;
|
int dataSize;
|
||||||
int tablePtr;
|
int tablePtr;
|
||||||
int tableSize;
|
int tableSize;
|
||||||
|
|
||||||
public Abbreviations (Header header)
|
public Abbreviations (Header header)
|
||||||
{
|
{
|
||||||
super ("Abbreviations", header.buffer);
|
super ("Abbreviations", header.buffer);
|
||||||
this.header = header;
|
this.header = header;
|
||||||
|
|
||||||
dataPtr = header.getWord (header.abbreviationsTable) * 2;
|
dataPtr = header.getWord (header.abbreviationsTable) * 2;
|
||||||
dataSize = header.abbreviationsTable - dataPtr;
|
dataSize = header.abbreviationsTable - dataPtr;
|
||||||
tablePtr = header.abbreviationsTable;
|
tablePtr = header.abbreviationsTable;
|
||||||
tableSize = header.objectTable - header.abbreviationsTable;
|
tableSize = header.objectTable - header.abbreviationsTable;
|
||||||
|
|
||||||
// prepare hex dump
|
// prepare hex dump
|
||||||
hexBlocks.add (new HexBlock (dataPtr, dataSize, "Abbreviations data:"));
|
hexBlocks.add (new HexBlock (dataPtr, dataSize, "Abbreviations data:"));
|
||||||
hexBlocks.add (new HexBlock (tablePtr, tableSize, "Abbreviations table:"));
|
hexBlocks.add (new HexBlock (tablePtr, tableSize, "Abbreviations table:"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populate ()
|
private void populate ()
|
||||||
{
|
{
|
||||||
System.out.println ("populating abbreviations");
|
System.out.println ("populating abbreviations");
|
||||||
list = new ArrayList<ZString> ();
|
list = new ArrayList<ZString> ();
|
||||||
|
|
||||||
for (int i = header.abbreviationsTable; i < header.objectTable; i += 2)
|
for (int i = header.abbreviationsTable; i < header.objectTable; i += 2)
|
||||||
{
|
{
|
||||||
int j = header.getWord (i) * 2;
|
int j = header.getWord (i) * 2;
|
||||||
ZString zs = new ZString (buffer, j, header);
|
ZString zs = new ZString (buffer, j, header);
|
||||||
list.add (zs);
|
list.add (zs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAbbreviation (int abbreviationNumber)
|
public String getAbbreviation (int abbreviationNumber)
|
||||||
{
|
{
|
||||||
if (list == null)
|
if (list == null)
|
||||||
populate ();
|
populate ();
|
||||||
return list.get (abbreviationNumber).value;
|
return list.get (abbreviationNumber).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getText ()
|
public String getText ()
|
||||||
{
|
{
|
||||||
if (list == null)
|
if (list == null)
|
||||||
populate ();
|
populate ();
|
||||||
|
|
||||||
StringBuilder text = new StringBuilder ();
|
StringBuilder text = new StringBuilder ();
|
||||||
|
|
||||||
// text.append (String.format ("Data address....%04X %d%n", dataPtr, dataPtr));
|
// text.append (String.format ("Data address....%04X %d%n", dataPtr, dataPtr));
|
||||||
// text.append (String.format ("Data size.......%04X %d%n", dataSize, dataSize));
|
// text.append (String.format ("Data size.......%04X %d%n", dataSize, dataSize));
|
||||||
// text.append (String.format ("Table address...%04X %d%n", tablePtr, tablePtr));
|
// text.append (String.format ("Table address...%04X %d%n", tablePtr, tablePtr));
|
||||||
// text.append (String.format ("Table size......%04X %d (%d words)%n%n", tableSize, tableSize,
|
// text.append (String.format ("Table size......%04X %d (%d words)%n%n", tableSize, tableSize,
|
||||||
// (tableSize / 2)));
|
// (tableSize / 2)));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (ZString word : list)
|
for (ZString word : list)
|
||||||
text.append (String.format ("%3d %s%n", count++, word.value));
|
text.append (String.format ("%3d %s%n", count++, word.value));
|
||||||
if (list.size () > 0)
|
if (list.size () > 0)
|
||||||
text.deleteCharAt (text.length () - 1);
|
text.deleteCharAt (text.length () - 1);
|
||||||
|
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,44 +1,42 @@
|
|||||||
package com.bytezone.diskbrowser.infocom;
|
package com.bytezone.diskbrowser.infocom;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
class Globals extends InfocomAbstractFile
|
||||||
|
|
||||||
class Globals extends AbstractFile
|
|
||||||
{
|
{
|
||||||
static final int TOTAL_GLOBALS = 240;
|
static final int TOTAL_GLOBALS = 240;
|
||||||
Header header;
|
Header header;
|
||||||
int globalsPtr, globalsSize;
|
int globalsPtr, globalsSize;
|
||||||
int arrayPtr, arraySize;
|
int arrayPtr, arraySize;
|
||||||
|
|
||||||
public Globals (Header header)
|
public Globals (Header header)
|
||||||
{
|
{
|
||||||
super ("Globals", header.buffer);
|
super ("Globals", header.buffer);
|
||||||
this.header = header;
|
this.header = header;
|
||||||
|
|
||||||
globalsPtr = header.globalsOffset;
|
globalsPtr = header.globalsOffset;
|
||||||
globalsSize = TOTAL_GLOBALS * 2;
|
globalsSize = TOTAL_GLOBALS * 2;
|
||||||
arrayPtr = globalsPtr + globalsSize;
|
arrayPtr = globalsPtr + globalsSize;
|
||||||
arraySize = header.staticMemory - arrayPtr;
|
arraySize = header.staticMemory - arrayPtr;
|
||||||
|
|
||||||
// add entries for AbstractFile.getHexDump ()
|
// add entries for AbstractFile.getHexDump ()
|
||||||
hexBlocks.add (new HexBlock (globalsPtr, globalsSize, "Globals:"));
|
hexBlocks.add (new HexBlock (globalsPtr, globalsSize, "Globals:"));
|
||||||
hexBlocks.add (new HexBlock (arrayPtr, arraySize, "Arrays:"));
|
hexBlocks.add (new HexBlock (arrayPtr, arraySize, "Arrays:"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getText ()
|
public String getText ()
|
||||||
{
|
{
|
||||||
StringBuilder text = new StringBuilder ();
|
StringBuilder text = new StringBuilder ();
|
||||||
for (int i = 1; i <= TOTAL_GLOBALS; i++)
|
for (int i = 1; i <= TOTAL_GLOBALS; i++)
|
||||||
{
|
{
|
||||||
int value = header.getWord (globalsPtr + i * 2);
|
int value = header.getWord (globalsPtr + i * 2);
|
||||||
text.append (String.format ("G%03d %04X ", i, value));
|
text.append (String.format ("G%03d %04X ", i, value));
|
||||||
int address = value * 2;
|
int address = value * 2;
|
||||||
if (address >= header.stringPointer && address < header.fileLength)
|
if (address >= header.stringPointer && address < header.fileLength)
|
||||||
text.append (header.stringManager.stringAt (address) + "\n");
|
text.append (header.stringManager.stringAt (address) + "\n");
|
||||||
else
|
else
|
||||||
text.append (String.format ("%,6d%n", value));
|
text.append (String.format ("%,6d%n", value));
|
||||||
}
|
}
|
||||||
text.deleteCharAt (text.length () - 1);
|
text.deleteCharAt (text.length () - 1);
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,331 +1,327 @@
|
|||||||
package com.bytezone.diskbrowser.infocom;
|
package com.bytezone.diskbrowser.infocom;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.HexFormatter;
|
import com.bytezone.diskbrowser.HexFormatter;
|
||||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
|
||||||
|
|
||||||
class Grammar extends AbstractFile
|
class Grammar extends InfocomAbstractFile
|
||||||
{
|
{
|
||||||
private static final int SENTENCE_LENGTH = 8;
|
private static final int SENTENCE_LENGTH = 8;
|
||||||
Header header;
|
Header header;
|
||||||
int indexPtr, indexSize;
|
int indexPtr, indexSize;
|
||||||
int tablePtr, tableSize;
|
int tablePtr, tableSize;
|
||||||
int actionPtr, actionSize;
|
int actionPtr, actionSize;
|
||||||
int preActionPtr, preActionSize;
|
int preActionPtr, preActionSize;
|
||||||
int prepositionPtr, prepositionSize;
|
int prepositionPtr, prepositionSize;
|
||||||
int indexEntries;
|
int indexEntries;
|
||||||
int totalPrepositions;
|
int totalPrepositions;
|
||||||
int padding;
|
int padding;
|
||||||
|
|
||||||
List<SentenceGroup> sentenceGroups = new ArrayList<SentenceGroup> ();
|
List<SentenceGroup> sentenceGroups = new ArrayList<SentenceGroup> ();
|
||||||
Map<Integer, List<Sentence>> actionList = new TreeMap<Integer, List<Sentence>> ();
|
Map<Integer, List<Sentence>> actionList = new TreeMap<Integer, List<Sentence>> ();
|
||||||
|
|
||||||
List<Integer> actionRoutines = new ArrayList<Integer> ();
|
List<Integer> actionRoutines = new ArrayList<Integer> ();
|
||||||
List<Integer> preActionRoutines = new ArrayList<Integer> ();
|
List<Integer> preActionRoutines = new ArrayList<Integer> ();
|
||||||
|
|
||||||
public Grammar (String name, byte[] buffer, Header header)
|
public Grammar (String name, byte[] buffer, Header header)
|
||||||
{
|
{
|
||||||
super (name, buffer);
|
super (name, buffer);
|
||||||
this.header = header;
|
this.header = header;
|
||||||
|
|
||||||
indexPtr = header.staticMemory; // start of the index
|
indexPtr = header.staticMemory; // start of the index
|
||||||
tablePtr = header.getWord (indexPtr); // start of the data (end of the index)
|
tablePtr = header.getWord (indexPtr); // start of the data (end of the index)
|
||||||
indexSize = tablePtr - indexPtr;
|
indexSize = tablePtr - indexPtr;
|
||||||
indexEntries = indexSize / 2;
|
indexEntries = indexSize / 2;
|
||||||
|
|
||||||
padding = getPadding ();
|
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
|
tableSize = lastEntry + getRecordLength (lastEntry) - tablePtr; // uses padding
|
||||||
actionPtr = tablePtr + tableSize; // start of the action routines
|
actionPtr = tablePtr + tableSize; // start of the action routines
|
||||||
actionSize = getTotalActions () * 2; // uses padding
|
actionSize = getTotalActions () * 2; // uses padding
|
||||||
|
|
||||||
preActionSize = actionSize;
|
preActionSize = actionSize;
|
||||||
preActionPtr = actionPtr + actionSize;
|
preActionPtr = actionPtr + actionSize;
|
||||||
prepositionPtr = preActionPtr + preActionSize;
|
prepositionPtr = preActionPtr + preActionSize;
|
||||||
|
|
||||||
totalPrepositions = header.getWord (prepositionPtr);
|
totalPrepositions = header.getWord (prepositionPtr);
|
||||||
prepositionSize = totalPrepositions * 4 + 2;
|
prepositionSize = totalPrepositions * 4 + 2;
|
||||||
|
|
||||||
if (false)
|
if (false)
|
||||||
{
|
{
|
||||||
System.out.printf ("indexPtr %,8d %4X%n", indexPtr, indexPtr);
|
System.out.printf ("indexPtr %,8d %4X%n", indexPtr, indexPtr);
|
||||||
System.out.printf ("indexSize %,8d%n", indexSize);
|
System.out.printf ("indexSize %,8d%n", indexSize);
|
||||||
System.out.printf ("indexEntries %,8d%n", indexEntries);
|
System.out.printf ("indexEntries %,8d%n", indexEntries);
|
||||||
System.out.printf ("tablePtr %,8d %4X%n", tablePtr, tablePtr);
|
System.out.printf ("tablePtr %,8d %4X%n", tablePtr, tablePtr);
|
||||||
System.out.printf ("tableSize %,8d%n", tableSize);
|
System.out.printf ("tableSize %,8d%n", tableSize);
|
||||||
System.out.printf ("actionPtr %,8d %4X%n", actionPtr, actionPtr);
|
System.out.printf ("actionPtr %,8d %4X%n", actionPtr, actionPtr);
|
||||||
System.out.printf ("actionSize %,8d%n", actionSize);
|
System.out.printf ("actionSize %,8d%n", actionSize);
|
||||||
System.out.printf ("actionEntries %,8d%n", actionSize / 2);
|
System.out.printf ("actionEntries %,8d%n", actionSize / 2);
|
||||||
System.out.printf ("preActionPtr %,8d %4X%n", preActionPtr, preActionPtr);
|
System.out.printf ("preActionPtr %,8d %4X%n", preActionPtr, preActionPtr);
|
||||||
System.out.printf ("preActionSize %,8d%n", preActionSize);
|
System.out.printf ("preActionSize %,8d%n", preActionSize);
|
||||||
System.out.printf ("prepPtr %,8d %4X%n", prepositionPtr, prepositionPtr);
|
System.out.printf ("prepPtr %,8d %4X%n", prepositionPtr, prepositionPtr);
|
||||||
System.out.printf ("prepSize %,8d%n", prepositionSize);
|
System.out.printf ("prepSize %,8d%n", prepositionSize);
|
||||||
System.out.printf ("totPreps %,8d%n", totalPrepositions);
|
System.out.printf ("totPreps %,8d%n", totalPrepositions);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add entries for AbstractFile.getHexDump ()
|
// add entries for AbstractFile.getHexDump ()
|
||||||
hexBlocks.add (new HexBlock (indexPtr, indexSize, "Index:"));
|
hexBlocks.add (new HexBlock (indexPtr, indexSize, "Index:"));
|
||||||
hexBlocks.add (new HexBlock (tablePtr, tableSize, "Grammar data:"));
|
hexBlocks.add (new HexBlock (tablePtr, tableSize, "Grammar data:"));
|
||||||
hexBlocks.add (new HexBlock (actionPtr, actionSize, "Action routines:"));
|
hexBlocks.add (new HexBlock (actionPtr, actionSize, "Action routines:"));
|
||||||
hexBlocks.add (new HexBlock (preActionPtr, preActionSize, "Pre-action routines:"));
|
hexBlocks.add (new HexBlock (preActionPtr, preActionSize, "Pre-action routines:"));
|
||||||
hexBlocks.add (new HexBlock (prepositionPtr, prepositionSize, "Preposition table:"));
|
hexBlocks.add (new HexBlock (prepositionPtr, prepositionSize, "Preposition table:"));
|
||||||
|
|
||||||
// create SentenceGroup and Sentence objects and action lists
|
// create SentenceGroup and Sentence objects and action lists
|
||||||
int count = 255;
|
int count = 255;
|
||||||
for (int i = 0; i < indexEntries; i++)
|
for (int i = 0; i < indexEntries; i++)
|
||||||
{
|
{
|
||||||
int offset = header.getWord (indexPtr + i * 2);
|
int offset = header.getWord (indexPtr + i * 2);
|
||||||
SentenceGroup sg = new SentenceGroup (count--, offset);
|
SentenceGroup sg = new SentenceGroup (count--, offset);
|
||||||
sentenceGroups.add (sg);
|
sentenceGroups.add (sg);
|
||||||
for (Sentence sentence : sg)
|
for (Sentence sentence : sg)
|
||||||
{
|
{
|
||||||
// add to hashmap
|
// add to hashmap
|
||||||
if (!actionList.containsKey (sentence.actionId))
|
if (!actionList.containsKey (sentence.actionId))
|
||||||
actionList.put (sentence.actionId, new ArrayList<Sentence> ());
|
actionList.put (sentence.actionId, new ArrayList<Sentence> ());
|
||||||
actionList.get (sentence.actionId).add (sentence);
|
actionList.get (sentence.actionId).add (sentence);
|
||||||
// add to pre-action routine list
|
// add to pre-action routine list
|
||||||
if (sentence.preActionRoutine > 0
|
if (sentence.preActionRoutine > 0
|
||||||
&& !preActionRoutines.contains (sentence.preActionRoutine))
|
&& !preActionRoutines.contains (sentence.preActionRoutine))
|
||||||
preActionRoutines.add (sentence.preActionRoutine);
|
preActionRoutines.add (sentence.preActionRoutine);
|
||||||
// add to action routine list
|
// add to action routine list
|
||||||
if (sentence.actionRoutine > 0 && !actionRoutines.contains (sentence.actionRoutine))
|
if (sentence.actionRoutine > 0
|
||||||
actionRoutines.add (sentence.actionRoutine);
|
&& !actionRoutines.contains (sentence.actionRoutine))
|
||||||
}
|
actionRoutines.add (sentence.actionRoutine);
|
||||||
}
|
}
|
||||||
Collections.sort (actionRoutines);
|
}
|
||||||
Collections.sort (preActionRoutines);
|
Collections.sort (actionRoutines);
|
||||||
}
|
Collections.sort (preActionRoutines);
|
||||||
|
}
|
||||||
|
|
||||||
private int getPadding ()
|
private int getPadding ()
|
||||||
{
|
{
|
||||||
// calculate record padding size (Zork has 1 byte padding, Planetfall has 0)
|
// calculate record padding size (Zork has 1 byte padding, Planetfall has 0)
|
||||||
int r1 = header.getWord (indexPtr);
|
int r1 = header.getWord (indexPtr);
|
||||||
int r2 = header.getWord (indexPtr + 2);
|
int r2 = header.getWord (indexPtr + 2);
|
||||||
int sentences = header.getByte (r1);
|
int sentences = header.getByte (r1);
|
||||||
return r2 - r1 - (sentences * SENTENCE_LENGTH) - 1;
|
return r2 - r1 - (sentences * SENTENCE_LENGTH) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getRecordLength (int recordPtr)
|
private int getRecordLength (int recordPtr)
|
||||||
{
|
{
|
||||||
return (buffer[recordPtr] & 0xFF) * SENTENCE_LENGTH + padding + 1;
|
return (buffer[recordPtr] & 0xFF) * SENTENCE_LENGTH + padding + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getTotalActions ()
|
private int getTotalActions ()
|
||||||
{
|
{
|
||||||
// loop through each record in each index entry, and find the highest action number
|
// loop through each record in each index entry, and find the highest action number
|
||||||
int ptr = tablePtr;
|
int ptr = tablePtr;
|
||||||
int highest = 0;
|
int highest = 0;
|
||||||
for (int i = 0; i < indexEntries; i++)
|
for (int i = 0; i < indexEntries; i++)
|
||||||
{
|
{
|
||||||
int totSentences = buffer[ptr++];
|
int totSentences = buffer[ptr++];
|
||||||
for (int j = 0; j < totSentences; j++)
|
for (int j = 0; j < totSentences; j++)
|
||||||
{
|
{
|
||||||
int val = buffer[ptr + 7] & 0xFF;
|
int val = buffer[ptr + 7] & 0xFF;
|
||||||
if (val > highest)
|
if (val > highest)
|
||||||
highest = val;
|
highest = val;
|
||||||
ptr += SENTENCE_LENGTH;
|
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 ()
|
public List<Integer> getActionRoutines ()
|
||||||
{
|
{
|
||||||
List<Integer> routines = new ArrayList<Integer> ();
|
List<Integer> routines = new ArrayList<Integer> ();
|
||||||
routines.addAll (actionRoutines);
|
routines.addAll (actionRoutines);
|
||||||
routines.addAll (preActionRoutines);
|
routines.addAll (preActionRoutines);
|
||||||
return routines;
|
return routines;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getText ()
|
public String getText ()
|
||||||
{
|
{
|
||||||
String line =
|
String line = "-----------------------------------------------------"
|
||||||
"-----------------------------------------------------"
|
+ "-----------------------------------------------------------\n";
|
||||||
+ "-----------------------------------------------------------\n";
|
StringBuilder text = new StringBuilder (
|
||||||
StringBuilder text =
|
sentenceGroups.size () + " Grammar tables\n==================\n\n");
|
||||||
new StringBuilder (sentenceGroups.size () + " Grammar tables\n==================\n\n");
|
|
||||||
|
|
||||||
// add the sentences in their original SentenceGroup sequence
|
// add the sentences in their original SentenceGroup sequence
|
||||||
for (SentenceGroup sg : sentenceGroups)
|
for (SentenceGroup sg : sentenceGroups)
|
||||||
text.append (sg + "\n" + line);
|
text.append (sg + "\n" + line);
|
||||||
|
|
||||||
text.append ("\n" + actionList.size () + " Action groups\n=================\n\n");
|
text.append ("\n" + actionList.size () + " Action groups\n=================\n\n");
|
||||||
|
|
||||||
// add the sentences in their actionId sequence
|
// add the sentences in their actionId sequence
|
||||||
for (List<Sentence> list : actionList.values ())
|
for (List<Sentence> list : actionList.values ())
|
||||||
{
|
{
|
||||||
for (Sentence sentence : list)
|
for (Sentence sentence : list)
|
||||||
text.append (sentence + "\n");
|
text.append (sentence + "\n");
|
||||||
text.append (line);
|
text.append (line);
|
||||||
}
|
}
|
||||||
|
|
||||||
text.append ("\n" + preActionRoutines.size ()
|
text.append ("\n" + preActionRoutines.size ()
|
||||||
+ " Pre-action routines\n======================\n\n");
|
+ " Pre-action routines\n======================\n\n");
|
||||||
|
|
||||||
// add sentences in pre-action routine sequence
|
// add sentences in pre-action routine sequence
|
||||||
for (Integer routine : preActionRoutines)
|
for (Integer routine : preActionRoutines)
|
||||||
{
|
{
|
||||||
for (Sentence sentence : getSentences (routine))
|
for (Sentence sentence : getSentences (routine))
|
||||||
text.append (sentence + "\n");
|
text.append (sentence + "\n");
|
||||||
text.append (line);
|
text.append (line);
|
||||||
}
|
}
|
||||||
|
|
||||||
text.append ("\n" + actionRoutines.size () + " Action routines\n===================\n\n");
|
text.append ("\n" + actionRoutines.size ()
|
||||||
|
+ " Action routines\n===================\n\n");
|
||||||
|
|
||||||
// add sentences in action routine sequence
|
// add sentences in action routine sequence
|
||||||
for (Integer routine : actionRoutines)
|
for (Integer routine : actionRoutines)
|
||||||
{
|
{
|
||||||
for (Sentence sentence : getSentences (routine))
|
for (Sentence sentence : getSentences (routine))
|
||||||
text.append (sentence + "\n");
|
text.append (sentence + "\n");
|
||||||
text.append (line);
|
text.append (line);
|
||||||
}
|
}
|
||||||
|
|
||||||
text.append ("\n" + totalPrepositions + " Prepositions\n===============\n\n");
|
text.append ("\n" + totalPrepositions + " Prepositions\n===============\n\n");
|
||||||
text.append (HexFormatter.getHexString (buffer, prepositionPtr, 2) + "\n");
|
text.append (HexFormatter.getHexString (buffer, prepositionPtr, 2) + "\n");
|
||||||
for (int i = 0, ptr = prepositionPtr + 2; i < totalPrepositions; i++, ptr += 4)
|
for (int i = 0, ptr = prepositionPtr + 2; i < totalPrepositions; i++, ptr += 4)
|
||||||
{
|
{
|
||||||
text.append (HexFormatter.getHexString (buffer, ptr, 4) + " ");
|
text.append (HexFormatter.getHexString (buffer, ptr, 4) + " ");
|
||||||
int id = header.getByte (ptr + 3);
|
int id = header.getByte (ptr + 3);
|
||||||
List<String> preps = header.dictionary.getPrepositions (id);
|
List<String> preps = header.dictionary.getPrepositions (id);
|
||||||
String prepString = makeWordBlock (preps);
|
String prepString = makeWordBlock (preps);
|
||||||
text.append (prepString + "\n");
|
text.append (prepString + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
text.deleteCharAt (text.length () - 1);
|
text.deleteCharAt (text.length () - 1);
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Sentence> getSentences (int routine)
|
private List<Sentence> getSentences (int routine)
|
||||||
{
|
{
|
||||||
List<Sentence> sentences = new ArrayList<Sentence> ();
|
List<Sentence> sentences = new ArrayList<Sentence> ();
|
||||||
|
|
||||||
for (SentenceGroup sg : sentenceGroups)
|
for (SentenceGroup sg : sentenceGroups)
|
||||||
for (Sentence s : sg.sentences)
|
for (Sentence s : sg.sentences)
|
||||||
if (s.actionRoutine == routine || s.preActionRoutine == routine)
|
if (s.actionRoutine == routine || s.preActionRoutine == routine)
|
||||||
sentences.add (s);
|
sentences.add (s);
|
||||||
|
|
||||||
return sentences;
|
return sentences;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String makeWordBlock (List<String> words)
|
private String makeWordBlock (List<String> words)
|
||||||
{
|
{
|
||||||
StringBuilder text = new StringBuilder ("[");
|
StringBuilder text = new StringBuilder ("[");
|
||||||
if (words.size () > 0)
|
if (words.size () > 0)
|
||||||
{
|
{
|
||||||
for (String word : words)
|
for (String word : words)
|
||||||
text.append (word + ", ");
|
text.append (word + ", ");
|
||||||
text.deleteCharAt (text.length () - 1);
|
text.deleteCharAt (text.length () - 1);
|
||||||
text.deleteCharAt (text.length () - 1);
|
text.deleteCharAt (text.length () - 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
text.append ("** not found **");
|
text.append ("** not found **");
|
||||||
text.append ("]");
|
text.append ("]");
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SentenceGroup implements Iterable<Sentence>
|
private class SentenceGroup implements Iterable<Sentence>
|
||||||
{
|
{
|
||||||
int startPtr;
|
int startPtr;
|
||||||
int id;
|
int id;
|
||||||
List<Sentence> sentences = new ArrayList<Sentence> ();
|
List<Sentence> sentences = new ArrayList<Sentence> ();
|
||||||
String verbString; // list of synonyms inside []
|
String verbString; // list of synonyms inside []
|
||||||
|
|
||||||
public SentenceGroup (int id, int ptr)
|
public SentenceGroup (int id, int ptr)
|
||||||
{
|
{
|
||||||
this.startPtr = ptr;
|
this.startPtr = ptr;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|
||||||
int records = buffer[ptr] & 0xFF;
|
int records = buffer[ptr] & 0xFF;
|
||||||
verbString = makeWordBlock (header.dictionary.getVerbs (id));
|
verbString = makeWordBlock (header.dictionary.getVerbs (id));
|
||||||
|
|
||||||
for (int j = 0, offset = startPtr + 1; j < records; j++, offset += SENTENCE_LENGTH)
|
for (int j = 0, offset = startPtr + 1; j < records; j++, offset += SENTENCE_LENGTH)
|
||||||
sentences.add (new Sentence (offset, this));
|
sentences.add (new Sentence (offset, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString ()
|
public String toString ()
|
||||||
{
|
{
|
||||||
StringBuilder text = new StringBuilder ();
|
StringBuilder text = new StringBuilder ();
|
||||||
for (Sentence sentence : sentences)
|
for (Sentence sentence : sentences)
|
||||||
text.append (sentence + "\n");
|
text.append (sentence + "\n");
|
||||||
text.deleteCharAt (text.length () - 1);
|
text.deleteCharAt (text.length () - 1);
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<Sentence> iterator ()
|
public Iterator<Sentence> iterator ()
|
||||||
{
|
{
|
||||||
return sentences.iterator ();
|
return sentences.iterator ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Sentence
|
private class Sentence
|
||||||
{
|
{
|
||||||
int startPtr;
|
int startPtr;
|
||||||
SentenceGroup parent;
|
SentenceGroup parent;
|
||||||
int actionId;
|
int actionId;
|
||||||
int actionRoutine; // mandatory
|
int actionRoutine; // mandatory
|
||||||
int preActionRoutine; // optional
|
int preActionRoutine; // optional
|
||||||
String sentenceText;
|
String sentenceText;
|
||||||
|
|
||||||
public Sentence (int ptr, SentenceGroup parent)
|
public Sentence (int ptr, SentenceGroup parent)
|
||||||
{
|
{
|
||||||
this.startPtr = ptr;
|
this.startPtr = ptr;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
|
||||||
// byte 0 contains the number of objects in the sentence
|
// byte 0 contains the number of objects in the sentence
|
||||||
int totObjects = buffer[ptr++] & 0xFF; // 0-2
|
int totObjects = buffer[ptr++] & 0xFF; // 0-2
|
||||||
|
|
||||||
// build the sentence text from bytes 1-2
|
// build the sentence text from bytes 1-2
|
||||||
StringBuilder sentence = new StringBuilder ();
|
StringBuilder sentence = new StringBuilder ();
|
||||||
for (int k = 0; k < totObjects; k++)
|
for (int k = 0; k < totObjects; k++)
|
||||||
{
|
{
|
||||||
int b = buffer[ptr++] & 0xFF;
|
int b = buffer[ptr++] & 0xFF;
|
||||||
if (b > 0)
|
if (b > 0)
|
||||||
sentence.append (" " + getPrep (b));
|
sentence.append (" " + getPrep (b));
|
||||||
sentence.append (" OBJ");
|
sentence.append (" OBJ");
|
||||||
}
|
}
|
||||||
sentenceText = sentence.toString ();
|
sentenceText = sentence.toString ();
|
||||||
|
|
||||||
// do something with bytes 3-6
|
// do something with bytes 3-6
|
||||||
// ... what that is I have no idea
|
// ... what that is I have no idea
|
||||||
|
|
||||||
// get action pointer from byte 7
|
// get action pointer from byte 7
|
||||||
actionId = buffer[startPtr + 7] & 0xFF;
|
actionId = buffer[startPtr + 7] & 0xFF;
|
||||||
int targetOffset = actionId * 2; // index into the action and pre-action blocks
|
int targetOffset = actionId * 2; // index into the action and pre-action blocks
|
||||||
actionRoutine = header.getWord (actionPtr + targetOffset) * 2;
|
actionRoutine = header.getWord (actionPtr + targetOffset) * 2;
|
||||||
preActionRoutine = header.getWord (preActionPtr + targetOffset) * 2;
|
preActionRoutine = header.getWord (preActionPtr + targetOffset) * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPrep (int value)
|
private String getPrep (int value)
|
||||||
{
|
{
|
||||||
int offset = prepositionPtr + 2 + (totalPrepositions - (255 - value) - 1) * 4;
|
int offset = prepositionPtr + 2 + (totalPrepositions - (255 - value) - 1) * 4;
|
||||||
int address = header.getWord (offset);
|
int address = header.getWord (offset);
|
||||||
return header.dictionary.wordAt (address);
|
return header.dictionary.wordAt (address);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getText ()
|
private String getText ()
|
||||||
{
|
{
|
||||||
return parent.verbString + " " + sentenceText;
|
return parent.verbString + " " + sentenceText;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString ()
|
public String toString ()
|
||||||
{
|
{
|
||||||
StringBuilder text = new StringBuilder (String.format ("%3d %04X ", parent.id, startPtr));
|
StringBuilder text =
|
||||||
text.append (HexFormatter.getHexString (buffer, startPtr, SENTENCE_LENGTH));
|
new StringBuilder (String.format ("%3d %04X ", parent.id, startPtr));
|
||||||
String r1 = preActionRoutine == 0 ? "" : String.format ("R:%05X", preActionRoutine);
|
text.append (HexFormatter.getHexString (buffer, startPtr, SENTENCE_LENGTH));
|
||||||
text.append (String.format (" %-7s R:%05X %s", r1, actionRoutine, getText ()));
|
String r1 = preActionRoutine == 0 ? "" : String.format ("R:%05X", preActionRoutine);
|
||||||
return text.toString ();
|
text.append (String.format (" %-7s R:%05X %s", r1, actionRoutine, getText ()));
|
||||||
}
|
return text.toString ();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,135 +2,137 @@ package com.bytezone.diskbrowser.infocom;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
class Header extends InfocomAbstractFile
|
||||||
|
|
||||||
class Header extends AbstractFile
|
|
||||||
{
|
{
|
||||||
final String[] propertyNames = new String[32];
|
final String[] propertyNames = new String[32];
|
||||||
|
|
||||||
File file;
|
File file;
|
||||||
int version;
|
int version;
|
||||||
int highMemory;
|
int highMemory;
|
||||||
int programCounter;
|
int programCounter;
|
||||||
int dictionaryOffset;
|
int dictionaryOffset;
|
||||||
int objectTable;
|
int objectTable;
|
||||||
int globalsOffset;
|
int globalsOffset;
|
||||||
int staticMemory;
|
int staticMemory;
|
||||||
int abbreviationsTable;
|
int abbreviationsTable;
|
||||||
int fileLength;
|
int fileLength;
|
||||||
int checksum;
|
int checksum;
|
||||||
int stringPointer;
|
int stringPointer;
|
||||||
|
|
||||||
Abbreviations abbreviations;
|
Abbreviations abbreviations;
|
||||||
Dictionary dictionary;
|
Dictionary dictionary;
|
||||||
ObjectManager objectManager;
|
ObjectManager objectManager;
|
||||||
StringManager stringManager;
|
StringManager stringManager;
|
||||||
CodeManager codeManager;
|
CodeManager codeManager;
|
||||||
Globals globals;
|
Globals globals;
|
||||||
Grammar grammar;
|
Grammar grammar;
|
||||||
|
|
||||||
public Header (String name, byte[] buffer, File file)
|
public Header (String name, byte[] buffer, File file)
|
||||||
{
|
{
|
||||||
super (name, buffer);
|
super (name, buffer);
|
||||||
this.file = file;
|
this.file = file;
|
||||||
|
|
||||||
version = getByte (0);
|
version = getByte (0);
|
||||||
highMemory = getWord (4);
|
highMemory = getWord (4);
|
||||||
programCounter = getWord (6);
|
programCounter = getWord (6);
|
||||||
dictionaryOffset = getWord (8);
|
dictionaryOffset = getWord (8);
|
||||||
objectTable = getWord (10);
|
objectTable = getWord (10);
|
||||||
globalsOffset = getWord (12);
|
globalsOffset = getWord (12);
|
||||||
staticMemory = getWord (14);
|
staticMemory = getWord (14);
|
||||||
abbreviationsTable = getWord (24);
|
abbreviationsTable = getWord (24);
|
||||||
checksum = getWord (28);
|
checksum = getWord (28);
|
||||||
fileLength = getWord (26) * 2;
|
fileLength = getWord (26) * 2;
|
||||||
|
|
||||||
if (fileLength == 0)
|
if (fileLength == 0)
|
||||||
fileLength = buffer.length;
|
fileLength = buffer.length;
|
||||||
|
|
||||||
// do the basic managers
|
// do the basic managers
|
||||||
abbreviations = new Abbreviations (this);
|
abbreviations = new Abbreviations (this);
|
||||||
dictionary = new Dictionary (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
|
// set up an empty object to store Routines in
|
||||||
codeManager = new CodeManager (this);
|
codeManager = new CodeManager (this);
|
||||||
|
|
||||||
grammar = new Grammar ("Grammar", buffer, this);
|
grammar = new Grammar ("Grammar", buffer, this);
|
||||||
|
|
||||||
// add all the ZObjects, and analyse them to find stringPtr, DICT etc.
|
// add all the ZObjects, and analyse them to find stringPtr, DICT etc.
|
||||||
objectManager = new ObjectManager (this);
|
objectManager = new ObjectManager (this);
|
||||||
|
|
||||||
// add all the ZStrings
|
// add all the ZStrings
|
||||||
stringManager = new StringManager ("Strings", buffer, this);
|
stringManager = new StringManager ("Strings", buffer, this);
|
||||||
|
|
||||||
codeManager.addRoutine (programCounter - 1, 0);
|
codeManager.addRoutine (programCounter - 1, 0);
|
||||||
codeManager.addActionRoutines (); // obtained from Grammar
|
codeManager.addActionRoutines (); // obtained from Grammar
|
||||||
codeManager.addCodeRoutines (); // obtained from Object properties
|
codeManager.addCodeRoutines (); // obtained from Object properties
|
||||||
codeManager.addMissingRoutines (); // requires stringPtr to be set
|
codeManager.addMissingRoutines (); // requires stringPtr to be set
|
||||||
|
|
||||||
// add entries for AbstractFile.getHexDump ()
|
// add entries for AbstractFile.getHexDump ()
|
||||||
hexBlocks.add (new HexBlock (0, 64, "Header data:"));
|
hexBlocks.add (new HexBlock (0, 64, "Header data:"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAbbreviation (int index)
|
public String getAbbreviation (int index)
|
||||||
{
|
{
|
||||||
return abbreviations.getAbbreviation (index);
|
return abbreviations.getAbbreviation (index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsWordAt (int address)
|
public boolean containsWordAt (int address)
|
||||||
{
|
{
|
||||||
return dictionary.containsWordAt (address);
|
return dictionary.containsWordAt (address);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String wordAt (int address)
|
public String wordAt (int address)
|
||||||
{
|
{
|
||||||
return dictionary.wordAt (address);
|
return dictionary.wordAt (address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getText ()
|
public String getText ()
|
||||||
{
|
{
|
||||||
StringBuilder text = new StringBuilder ();
|
StringBuilder text = new StringBuilder ();
|
||||||
|
|
||||||
text.append (String.format ("Disk name %s%n", file.getName ()));
|
text.append (String.format ("Disk name %s%n", file.getName ()));
|
||||||
text.append (String.format ("Version %d%n", version));
|
text.append (String.format ("Version %d%n", version));
|
||||||
text.append ("\nDynamic memory:\n");
|
text.append ("\nDynamic memory:\n");
|
||||||
text.append (String.format (" Abbreviation table %04X %,6d%n", abbreviationsTable,
|
text.append (String.format (" Abbreviation table %04X %,6d%n",
|
||||||
abbreviationsTable));
|
abbreviationsTable, abbreviationsTable));
|
||||||
text.append (String.format (" Objects table %04X %,6d%n", objectTable, objectTable));
|
text.append (String.format (" Objects table %04X %,6d%n", objectTable,
|
||||||
text.append (String.format (" Global variables %04X %,6d%n", globalsOffset,
|
objectTable));
|
||||||
globalsOffset));
|
text.append (String.format (" Global variables %04X %,6d%n", globalsOffset,
|
||||||
|
globalsOffset));
|
||||||
|
|
||||||
text.append ("\nStatic memory:\n");
|
text.append ("\nStatic memory:\n");
|
||||||
text.append (String
|
text.append (String.format (" Grammar table etc %04X %,6d%n", staticMemory,
|
||||||
.format (" Grammar table etc %04X %,6d%n", staticMemory, staticMemory));
|
staticMemory));
|
||||||
text.append (String.format (" Dictionary %04X %,6d%n", dictionaryOffset,
|
text.append (String.format (" Dictionary %04X %,6d%n", dictionaryOffset,
|
||||||
dictionaryOffset));
|
dictionaryOffset));
|
||||||
text.append ("\nHigh memory:\n");
|
text.append ("\nHigh memory:\n");
|
||||||
text.append (String.format (" ZCode %04X %,6d%n", highMemory, highMemory));
|
text.append (String.format (" ZCode %04X %,6d%n", highMemory,
|
||||||
text.append (String.format (" Program counter %04X %,6d%n", programCounter,
|
highMemory));
|
||||||
programCounter));
|
text.append (String.format (" Program counter %04X %,6d%n", programCounter,
|
||||||
text.append (String.format ("\nFile length %05X %,6d%n", fileLength, fileLength));
|
programCounter));
|
||||||
text.append (String.format ("Checksum %04X %,6d%n", checksum, checksum));
|
text.append (String.format ("\nFile length %05X %,6d%n", fileLength,
|
||||||
text.append (String.format ("%nZString offset %05X %,6d%n", stringPointer,
|
fileLength));
|
||||||
stringPointer));
|
text.append (String.format ("Checksum %04X %,6d%n", checksum,
|
||||||
|
checksum));
|
||||||
|
text.append (String.format ("%nZString offset %05X %,6d%n", stringPointer,
|
||||||
|
stringPointer));
|
||||||
|
|
||||||
text.append (String.format ("Total strings %d%n", stringManager.strings
|
text.append (String.format ("Total strings %d%n",
|
||||||
.size ()));
|
stringManager.strings.size ()));
|
||||||
text.append (String.format ("Total objects %d%n", objectManager.list
|
text.append (String.format ("Total objects %d%n",
|
||||||
.size ()));
|
objectManager.list.size ()));
|
||||||
|
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
int getByte (int offset)
|
int getByte (int offset)
|
||||||
{
|
{
|
||||||
return buffer[offset] & 0xFF;
|
return buffer[offset] & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getWord (int offset)
|
int getWord (int offset)
|
||||||
{
|
{
|
||||||
return ((buffer[offset] << 8) & 0xFF00) | ((buffer[offset + 1]) & 0xFF);
|
return ((buffer[offset] << 8) & 0xFF00) | ((buffer[offset + 1]) & 0xFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package com.bytezone.diskbrowser.infocom;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.bytezone.diskbrowser.HexFormatter;
|
||||||
|
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||||
|
|
||||||
|
public class InfocomAbstractFile extends AbstractFile
|
||||||
|
{
|
||||||
|
protected List<HexBlock> hexBlocks = new ArrayList<HexBlock> ();
|
||||||
|
|
||||||
|
public InfocomAbstractFile (String name, byte[] buffer)
|
||||||
|
{
|
||||||
|
super (name, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHexDump ()
|
||||||
|
{
|
||||||
|
if (hexBlocks.size () > 0)
|
||||||
|
{
|
||||||
|
StringBuilder text = new StringBuilder ();
|
||||||
|
|
||||||
|
for (HexBlock hb : hexBlocks)
|
||||||
|
{
|
||||||
|
if (hb.title != null)
|
||||||
|
text.append (hb.title + "\n\n");
|
||||||
|
text.append (HexFormatter.format (buffer, hb.ptr, hb.size) + "\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
text.deleteCharAt (text.length () - 1);
|
||||||
|
text.deleteCharAt (text.length () - 1);
|
||||||
|
|
||||||
|
return text.toString ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer == null || buffer.length == 0)
|
||||||
|
return "No buffer";
|
||||||
|
|
||||||
|
if (buffer.length <= 99999)
|
||||||
|
return HexFormatter.format (buffer, 0, buffer.length);
|
||||||
|
|
||||||
|
return HexFormatter.format (buffer, 0, 99999);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class HexBlock
|
||||||
|
{
|
||||||
|
public int ptr;
|
||||||
|
public int size;
|
||||||
|
public String title;
|
||||||
|
|
||||||
|
public HexBlock (int ptr, int size, String title)
|
||||||
|
{
|
||||||
|
this.ptr = ptr;
|
||||||
|
this.size = size;
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,91 +6,91 @@ import java.util.List;
|
|||||||
|
|
||||||
import javax.swing.tree.DefaultMutableTreeNode;
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
|
||||||
import com.bytezone.diskbrowser.disk.DefaultAppleFileSource;
|
import com.bytezone.diskbrowser.disk.DefaultAppleFileSource;
|
||||||
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
||||||
|
|
||||||
class ObjectManager extends AbstractFile implements Iterable<ZObject>
|
class ObjectManager extends InfocomAbstractFile implements Iterable<ZObject>
|
||||||
{
|
{
|
||||||
Header header;
|
Header header;
|
||||||
List<ZObject> list;
|
List<ZObject> list;
|
||||||
int defaultsPtr, defaultsSize;
|
int defaultsPtr, defaultsSize;
|
||||||
int tablePtr, tableSize;
|
int tablePtr, tableSize;
|
||||||
int propertyPtr, propertySize;
|
int propertyPtr, propertySize;
|
||||||
ObjectAnalyser analyser;
|
ObjectAnalyser analyser;
|
||||||
|
|
||||||
public ObjectManager (Header header)
|
public ObjectManager (Header header)
|
||||||
{
|
{
|
||||||
super ("Objects", header.buffer);
|
super ("Objects", header.buffer);
|
||||||
this.header = header;
|
this.header = header;
|
||||||
|
|
||||||
defaultsPtr = header.objectTable;
|
defaultsPtr = header.objectTable;
|
||||||
defaultsSize = 62;
|
defaultsSize = 62;
|
||||||
tablePtr = header.objectTable + 62;
|
tablePtr = header.objectTable + 62;
|
||||||
propertyPtr = header.getWord (tablePtr + 7);
|
propertyPtr = header.getWord (tablePtr + 7);
|
||||||
propertySize = header.globalsOffset - propertyPtr;
|
propertySize = header.globalsOffset - propertyPtr;
|
||||||
tableSize = (propertyPtr - tablePtr);
|
tableSize = (propertyPtr - tablePtr);
|
||||||
int totalObjects = tableSize / ZObject.HEADER_SIZE;
|
int totalObjects = tableSize / ZObject.HEADER_SIZE;
|
||||||
list = new ArrayList<ZObject> (tableSize);
|
list = new ArrayList<ZObject> (tableSize);
|
||||||
|
|
||||||
for (int objectNo = 0; objectNo < totalObjects; objectNo++)
|
for (int objectNo = 0; objectNo < totalObjects; objectNo++)
|
||||||
list.add (new ZObject (null, buffer, tablePtr + objectNo * ZObject.HEADER_SIZE, objectNo + 1,
|
list.add (new ZObject (null, buffer, tablePtr + objectNo * ZObject.HEADER_SIZE,
|
||||||
header));
|
objectNo + 1, header));
|
||||||
|
|
||||||
// analyse objects - set stringPtr etc.
|
// analyse objects - set stringPtr etc.
|
||||||
analyser = new ObjectAnalyser (header, this);
|
analyser = new ObjectAnalyser (header, this);
|
||||||
|
|
||||||
// add entries for AbstractFile.getHexDump ()
|
// add entries for AbstractFile.getHexDump ()
|
||||||
hexBlocks.add (new HexBlock (defaultsPtr, defaultsSize, "Property defaults:"));
|
hexBlocks.add (new HexBlock (defaultsPtr, defaultsSize, "Property defaults:"));
|
||||||
hexBlocks.add (new HexBlock (tablePtr, tableSize, "Objects table:"));
|
hexBlocks.add (new HexBlock (tablePtr, tableSize, "Objects table:"));
|
||||||
hexBlocks.add (new HexBlock (propertyPtr, propertySize, "Properties:"));
|
hexBlocks.add (new HexBlock (propertyPtr, propertySize, "Properties:"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addNodes (DefaultMutableTreeNode root, FormattedDisk disk)
|
public void addNodes (DefaultMutableTreeNode root, FormattedDisk disk)
|
||||||
{
|
{
|
||||||
root.setAllowsChildren (true);
|
root.setAllowsChildren (true);
|
||||||
|
|
||||||
for (ZObject zo : list)
|
for (ZObject zo : list)
|
||||||
if (zo.parent == 0)
|
if (zo.parent == 0)
|
||||||
buildObjectTree (zo, root, disk);
|
buildObjectTree (zo, root, disk);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildObjectTree (ZObject object, DefaultMutableTreeNode parentNode,
|
private void buildObjectTree (ZObject object, DefaultMutableTreeNode parentNode,
|
||||||
FormattedDisk disk)
|
FormattedDisk disk)
|
||||||
{
|
{
|
||||||
DefaultMutableTreeNode child =
|
DefaultMutableTreeNode child = new DefaultMutableTreeNode (
|
||||||
new DefaultMutableTreeNode (new DefaultAppleFileSource (object.name, object, disk));
|
new DefaultAppleFileSource (object.name, object, disk));
|
||||||
parentNode.add (child);
|
parentNode.add (child);
|
||||||
if (object.sibling > 0)
|
if (object.sibling > 0)
|
||||||
buildObjectTree (header.objectManager.list.get (object.sibling - 1), parentNode, disk);
|
buildObjectTree (header.objectManager.list.get (object.sibling - 1), parentNode,
|
||||||
if (object.child > 0)
|
disk);
|
||||||
buildObjectTree (header.objectManager.list.get (object.child - 1), child, disk);
|
if (object.child > 0)
|
||||||
else
|
buildObjectTree (header.objectManager.list.get (object.child - 1), child, disk);
|
||||||
child.setAllowsChildren (false);
|
else
|
||||||
}
|
child.setAllowsChildren (false);
|
||||||
|
}
|
||||||
|
|
||||||
public List<Integer> getCodeRoutines ()
|
public List<Integer> getCodeRoutines ()
|
||||||
{
|
{
|
||||||
return analyser.routines;
|
return analyser.routines;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getText ()
|
public String getText ()
|
||||||
{
|
{
|
||||||
StringBuilder text =
|
StringBuilder text =
|
||||||
new StringBuilder (" # Attributes Pr Sb Ch Prop Title\n--- -----------"
|
new StringBuilder (" # Attributes Pr Sb Ch Prop Title\n--- -----------"
|
||||||
+ " -- -- -- ----- -----------------------------\n");
|
+ " -- -- -- ----- -----------------------------\n");
|
||||||
|
|
||||||
int objectNumber = 0;
|
int objectNumber = 0;
|
||||||
for (ZObject zo : list)
|
for (ZObject zo : list)
|
||||||
text.append (String.format ("%3d %s%n", ++objectNumber, zo));
|
text.append (String.format ("%3d %s%n", ++objectNumber, zo));
|
||||||
text.deleteCharAt (text.length () - 1);
|
text.deleteCharAt (text.length () - 1);
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<ZObject> iterator ()
|
public Iterator<ZObject> iterator ()
|
||||||
{
|
{
|
||||||
return list.iterator ();
|
return list.iterator ();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,150 +4,148 @@ import java.util.ArrayList;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
class Routine extends InfocomAbstractFile
|
||||||
|
implements Iterable<Instruction>, Comparable<Routine>
|
||||||
class Routine extends AbstractFile implements Iterable<Instruction>, Comparable<Routine>
|
|
||||||
{
|
{
|
||||||
int startPtr, length, strings, locals;
|
int startPtr, length, strings, locals;
|
||||||
Header header;
|
Header header;
|
||||||
|
|
||||||
List<Parameter> parameters = new ArrayList<Parameter> ();
|
List<Parameter> parameters = new ArrayList<Parameter> ();
|
||||||
List<Instruction> instructions = new ArrayList<Instruction> ();
|
List<Instruction> instructions = new ArrayList<Instruction> ();
|
||||||
List<Integer> calls = new ArrayList<Integer> ();
|
List<Integer> calls = new ArrayList<Integer> ();
|
||||||
List<Integer> calledBy = new ArrayList<Integer> ();
|
List<Integer> calledBy = new ArrayList<Integer> ();
|
||||||
List<Integer> actions = new ArrayList<Integer> (); // not used yet
|
List<Integer> actions = new ArrayList<Integer> (); // not used yet
|
||||||
|
|
||||||
private static final String padding = " ";
|
private static final String padding = " ";
|
||||||
|
|
||||||
public Routine (int ptr, Header header, int caller)
|
public Routine (int ptr, Header header, int caller)
|
||||||
{
|
{
|
||||||
super (String.format ("Routine %05X", ptr), header.buffer);
|
super (String.format ("Routine %05X", ptr), header.buffer);
|
||||||
this.header = header;
|
this.header = header;
|
||||||
|
|
||||||
locals = buffer[ptr] & 0xFF;
|
locals = buffer[ptr] & 0xFF;
|
||||||
if (locals > 15)
|
if (locals > 15)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
startPtr = ptr++; // also used to flag a valid routine
|
startPtr = ptr++; // also used to flag a valid routine
|
||||||
calledBy.add (caller);
|
calledBy.add (caller);
|
||||||
|
|
||||||
for (int i = 1; i <= locals; i++)
|
for (int i = 1; i <= locals; i++)
|
||||||
{
|
{
|
||||||
parameters.add (new Parameter (i, header.getWord (ptr))); // default values
|
parameters.add (new Parameter (i, header.getWord (ptr))); // default values
|
||||||
ptr += 2;
|
ptr += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (buffer[ptr] == 0 || buffer[ptr] == 0x20 || buffer[ptr] == 0x40)
|
if (buffer[ptr] == 0 || buffer[ptr] == 0x20 || buffer[ptr] == 0x40)
|
||||||
{
|
{
|
||||||
System.out.println ("Bad instruction found : " + ptr);
|
System.out.println ("Bad instruction found : " + ptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Instruction instruction = new Instruction (buffer, ptr, header);
|
Instruction instruction = new Instruction (buffer, ptr, header);
|
||||||
instructions.add (instruction);
|
instructions.add (instruction);
|
||||||
|
|
||||||
if (instruction.isCall () && instruction.opcode.callTarget > 0) // not stack-based
|
if (instruction.isCall () && instruction.opcode.callTarget > 0) // not stack-based
|
||||||
calls.add (instruction.opcode.callTarget);
|
calls.add (instruction.opcode.callTarget);
|
||||||
|
|
||||||
if (instruction.isPrint ())
|
if (instruction.isPrint ())
|
||||||
strings++;
|
strings++;
|
||||||
|
|
||||||
ptr += instruction.length ();
|
ptr += instruction.length ();
|
||||||
|
|
||||||
// is it a backwards jump?
|
// is it a backwards jump?
|
||||||
if (instruction.isJump () && instruction.target () < ptr && !moreCode (ptr))
|
if (instruction.isJump () && instruction.target () < ptr && !moreCode (ptr))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// is it an unconditional return?
|
// is it an unconditional return?
|
||||||
if (instruction.isReturn () && !moreCode (ptr))
|
if (instruction.isReturn () && !moreCode (ptr))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
length = ptr - startPtr;
|
length = ptr - startPtr;
|
||||||
|
|
||||||
hexBlocks.add (new HexBlock (startPtr, length, null));
|
hexBlocks.add (new HexBlock (startPtr, length, null));
|
||||||
|
|
||||||
// check for branches outside this routine
|
// check for branches outside this routine
|
||||||
if (true)
|
if (true)
|
||||||
{
|
{
|
||||||
int endPtr = startPtr + length;
|
int endPtr = startPtr + length;
|
||||||
for (Instruction ins : instructions)
|
for (Instruction ins : instructions)
|
||||||
{
|
{
|
||||||
int target =
|
int target = ins.target () > 256 ? ins.target ()
|
||||||
ins.target () > 256 ? ins.target ()
|
: ins.opcode.jumpTarget > 256 ? ins.opcode.jumpTarget : 0;
|
||||||
: ins.opcode.jumpTarget > 256 ? ins.opcode.jumpTarget : 0;
|
if (target == 0)
|
||||||
if (target == 0)
|
continue;
|
||||||
continue;
|
if (ins.isBranch () && (target > endPtr || target < startPtr))
|
||||||
if (ins.isBranch () && (target > endPtr || target < startPtr))
|
System.out.println (ins);
|
||||||
System.out.println (ins);
|
if (ins.isJump () && (target > endPtr || target < startPtr))
|
||||||
if (ins.isJump () && (target > endPtr || target < startPtr))
|
System.out.println (ins);
|
||||||
System.out.println (ins);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// test whether the routine contains any instructions pointing to this address
|
// test whether the routine contains any instructions pointing to this address
|
||||||
private boolean moreCode (int ptr)
|
private boolean moreCode (int ptr)
|
||||||
{
|
{
|
||||||
for (Instruction ins : instructions)
|
for (Instruction ins : instructions)
|
||||||
{
|
{
|
||||||
if (ins.isBranch () && ins.target () == ptr)
|
if (ins.isBranch () && ins.target () == ptr)
|
||||||
return true;
|
return true;
|
||||||
// should this be calling ins.target () ?
|
// should this be calling ins.target () ?
|
||||||
if (ins.isJump () && ins.opcode.jumpTarget == ptr)
|
if (ins.isJump () && ins.opcode.jumpTarget == ptr)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addCaller (int caller)
|
public void addCaller (int caller)
|
||||||
{
|
{
|
||||||
calledBy.add (caller);
|
calledBy.add (caller);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getText ()
|
public String getText ()
|
||||||
{
|
{
|
||||||
StringBuilder text = new StringBuilder ();
|
StringBuilder text = new StringBuilder ();
|
||||||
text.append (String.format ("Called by : %3d%n", calledBy.size ()));
|
text.append (String.format ("Called by : %3d%n", calledBy.size ()));
|
||||||
text.append (String.format ("Calls : %3d%n%n", calls.size ()));
|
text.append (String.format ("Calls : %3d%n%n", calls.size ()));
|
||||||
text.append (String.format ("%s%05X : %d%n", padding, startPtr, locals));
|
text.append (String.format ("%s%05X : %d%n", padding, startPtr, locals));
|
||||||
for (Parameter parameter : parameters)
|
for (Parameter parameter : parameters)
|
||||||
text.append (padding + parameter.toString () + "\n");
|
text.append (padding + parameter.toString () + "\n");
|
||||||
text.append ("\n");
|
text.append ("\n");
|
||||||
for (Instruction instruction : instructions)
|
for (Instruction instruction : instructions)
|
||||||
text.append (instruction + "\n");
|
text.append (instruction + "\n");
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
class Parameter
|
class Parameter
|
||||||
{
|
{
|
||||||
int value;
|
int value;
|
||||||
int sequence;
|
int sequence;
|
||||||
|
|
||||||
public Parameter (int sequence, int value)
|
public Parameter (int sequence, int value)
|
||||||
{
|
{
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.sequence = sequence;
|
this.sequence = sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString ()
|
public String toString ()
|
||||||
{
|
{
|
||||||
return String.format ("%05X : L%02d : %d", (startPtr + (sequence - 1) * 2 + 1), sequence,
|
return String.format ("%05X : L%02d : %d", (startPtr + (sequence - 1) * 2 + 1),
|
||||||
value);
|
sequence, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<Instruction> iterator ()
|
public Iterator<Instruction> iterator ()
|
||||||
{
|
{
|
||||||
return instructions.iterator ();
|
return instructions.iterator ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo (Routine o)
|
public int compareTo (Routine o)
|
||||||
{
|
{
|
||||||
return startPtr - o.startPtr;
|
return startPtr - o.startPtr;
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user