moved HexBlock to Infocom package

This commit is contained in:
Denis Molony 2016-02-05 18:18:23 +11:00
parent 4ba53dd1b0
commit c4b086a096
9 changed files with 742 additions and 716 deletions

View File

@ -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;
}
}
} }

View File

@ -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

View File

@ -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 ();
} }
} }

View File

@ -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 ();
} }
} }

View File

@ -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 ();
} }
}
} }

View File

@ -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);
} }
} }

View File

@ -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;
}
}
}

View File

@ -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 ();
} }
} }

View File

@ -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;
} }
} }