mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2025-01-03 13:31:44 +00:00
cleaning infocom code
This commit is contained in:
parent
504d8f467e
commit
01a62e5918
@ -623,6 +623,7 @@ public class AppleDisk implements Disk
|
||||
private int getBufferOffset (DiskAddress da)
|
||||
{
|
||||
assert sectorSize == SECTOR_SIZE;
|
||||
|
||||
return da.getTrack () * trackSize
|
||||
+ interleaveSector[interleave][da.getSector ()] * SECTOR_SIZE;
|
||||
}
|
||||
@ -630,6 +631,7 @@ public class AppleDisk implements Disk
|
||||
private int getBufferOffset (DiskAddress da, int seq)
|
||||
{
|
||||
assert sectorSize == BLOCK_SIZE;
|
||||
|
||||
assert seq == 0 || seq == 1;
|
||||
|
||||
return da.getTrack () * trackSize
|
||||
|
@ -60,10 +60,33 @@ class CodeManager extends AbstractFile
|
||||
return blocks;
|
||||
}
|
||||
|
||||
void addMissingRoutines ()
|
||||
void addRoutines (int programCounter)
|
||||
{
|
||||
addRoutine (programCounter - 1, 0); //
|
||||
addActionRoutines (); // obtained from Grammar
|
||||
addCodeRoutines (); // obtained from Object properties
|
||||
addMissingRoutines (); // requires stringPtr to be set
|
||||
|
||||
if (false)
|
||||
{
|
||||
int ptr = header.highMemory;
|
||||
for (int key : routines.keySet ())
|
||||
{
|
||||
if (ptr % 2 == 1)
|
||||
++ptr;
|
||||
Routine routine = routines.get (key);
|
||||
if (routine.startPtr > ptr)
|
||||
System.out.printf ("skipped %d bytes%n", routine.startPtr - ptr);
|
||||
System.out.println (routine);
|
||||
ptr = routine.startPtr + routine.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addMissingRoutines ()
|
||||
{
|
||||
System.out.printf ("%nWalking the code block%n%n");
|
||||
int total = 0;
|
||||
int total = routines.size ();
|
||||
int ptr = header.highMemory;
|
||||
|
||||
while (ptr < header.stringPointer)
|
||||
@ -71,7 +94,7 @@ class CodeManager extends AbstractFile
|
||||
if (ptr >= 0 && ptr % 2 == 1) // routine must start on a word boundary
|
||||
ptr++;
|
||||
|
||||
if (containsRoutineAt (ptr))
|
||||
if (routines.containsKey (ptr))
|
||||
{
|
||||
ptr += getRoutine (ptr).length;
|
||||
continue;
|
||||
@ -81,18 +104,20 @@ class CodeManager extends AbstractFile
|
||||
if (routine == null)
|
||||
{
|
||||
System.out.printf ("Invalid routine found : %05X%n", ptr);
|
||||
ptr = findNextRoutine (ptr + 1);
|
||||
int nextRoutinePtr = findNextRoutine (ptr + 1);
|
||||
// System.out.println (Utility.getHex (buffer, ptr, nextRoutinePtr - ptr));
|
||||
ptr = nextRoutinePtr;
|
||||
System.out.printf ("skipping to %05X%n", ptr);
|
||||
if (ptr == 0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
total++;
|
||||
ptr += routine.length;
|
||||
}
|
||||
}
|
||||
System.out.printf ("%n%d new routines found by walking the code block%n%n", total);
|
||||
System.out.printf ("%n%d new routines found by walking the code block%n%n",
|
||||
routines.size () - total);
|
||||
}
|
||||
|
||||
private int findNextRoutine (int address)
|
||||
@ -125,12 +150,7 @@ class CodeManager extends AbstractFile
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
boolean containsRoutineAt (int address)
|
||||
{
|
||||
return (routines.containsKey (address));
|
||||
}
|
||||
|
||||
void addCodeRoutines ()
|
||||
private void addCodeRoutines ()
|
||||
{
|
||||
List<Integer> routines = header.objectManager.getCodeRoutines ();
|
||||
System.out.println ("Adding " + routines.size () + " code routines");
|
||||
@ -138,8 +158,9 @@ class CodeManager extends AbstractFile
|
||||
addRoutine (address, 0);
|
||||
}
|
||||
|
||||
void addActionRoutines ()
|
||||
private void addActionRoutines ()
|
||||
{
|
||||
// process actionRoutines and preActionRoutines
|
||||
List<Integer> routines = header.grammar.getActionRoutines ();
|
||||
System.out.println ("Adding " + routines.size () + " action routines");
|
||||
for (Integer address : routines)
|
||||
@ -150,6 +171,7 @@ class CodeManager extends AbstractFile
|
||||
{
|
||||
if (address == 0) // stack-based call
|
||||
return null;
|
||||
|
||||
if (address > header.fileLength)
|
||||
return null;
|
||||
|
||||
@ -163,7 +185,7 @@ class CodeManager extends AbstractFile
|
||||
|
||||
// try to create a new Routine
|
||||
Routine r = new Routine (address, header, caller);
|
||||
if (r.length == 0) // invalid routine
|
||||
if (!r.isValid ())
|
||||
return null;
|
||||
|
||||
// recursively add all routines called by this one
|
||||
|
@ -1,6 +1,11 @@
|
||||
package com.bytezone.diskbrowser.infocom;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
@ -70,6 +75,7 @@ class Grammar extends InfocomAbstractFile
|
||||
hexBlocks.add (new HexBlock (actionPtr, actionSize, "Action routines:"));
|
||||
hexBlocks.add (new HexBlock (preActionPtr, preActionSize, "Pre-action routines:"));
|
||||
hexBlocks.add (new HexBlock (prepositionPtr, prepositionSize, "Preposition table:"));
|
||||
// System.out.println (getHexDump ());
|
||||
|
||||
// create SentenceGroup and Sentence objects and action lists
|
||||
int count = 255;
|
||||
|
@ -73,10 +73,7 @@ class Header extends InfocomAbstractFile
|
||||
// add all the ZStrings
|
||||
stringManager = new StringManager ("Strings", buffer, this);
|
||||
|
||||
codeManager.addRoutine (programCounter - 1, 0);
|
||||
codeManager.addActionRoutines (); // obtained from Grammar
|
||||
codeManager.addCodeRoutines (); // obtained from Object properties
|
||||
codeManager.addMissingRoutines (); // requires stringPtr to be set
|
||||
codeManager.addRoutines (programCounter);
|
||||
|
||||
// add entries for AbstractFile.getHexDump ()
|
||||
hexBlocks.add (new HexBlock (0, 64, "Header data:"));
|
||||
@ -139,6 +136,41 @@ class Header extends InfocomAbstractFile
|
||||
text.append (String.format ("Total objects %d%n",
|
||||
objectManager.getObjects ().size ()));
|
||||
|
||||
text.append (getAlternate ());
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
private String getAlternate ()
|
||||
{
|
||||
StringBuilder text = new StringBuilder ("\n\n");
|
||||
|
||||
text.append (getLine (0, 1, "version"));
|
||||
text.append (getLine (1, 3, "flags 1"));
|
||||
text.append (getLine (4, 2, "high memory"));
|
||||
text.append (getLine (6, 2, "program counter"));
|
||||
text.append (getLine (8, 2, "dictionary"));
|
||||
text.append (getLine (10, 2, "object table"));
|
||||
text.append (getLine (12, 2, "global variables"));
|
||||
text.append (getLine (14, 2, "static memory"));
|
||||
text.append (getLine (16, 2, "flags 2"));
|
||||
text.append (getLine (24, 2, "abbreviations table"));
|
||||
text.append (getLine (26, 2, "length of file (x2 = " + fileLength + ")"));
|
||||
text.append (getLine (28, 2, "checksum"));
|
||||
text.append (getLine (50, 1, "revision number"));
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
private String getLine (int offset, int size, String description)
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
text.append (String.format ("%04X - %04X ", offset, offset + size - 1));
|
||||
for (int i = 0; i < size; i++)
|
||||
text.append (String.format ("%02X ", buffer[offset + i]));
|
||||
while (text.length () < 24)
|
||||
text.append (" ");
|
||||
text.append (description);
|
||||
text.append ("\n");
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,12 @@ import javax.swing.JOptionPane;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AppleFileSource;
|
||||
import com.bytezone.diskbrowser.disk.*;
|
||||
import com.bytezone.diskbrowser.disk.AbstractFormattedDisk;
|
||||
import com.bytezone.diskbrowser.disk.AppleDisk;
|
||||
import com.bytezone.diskbrowser.disk.DefaultAppleFileSource;
|
||||
import com.bytezone.diskbrowser.disk.Disk;
|
||||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||
import com.bytezone.diskbrowser.disk.SectorType;
|
||||
import com.bytezone.diskbrowser.gui.DataSource;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
@ -25,12 +30,11 @@ public class InfocomDisk extends AbstractFormattedDisk
|
||||
private static final boolean TYPE_NODE = true;
|
||||
private static final boolean TYPE_LEAF = false;
|
||||
private byte[] data;
|
||||
// private int version;
|
||||
private final Header header;
|
||||
|
||||
Color green = new Color (0, 200, 0);
|
||||
|
||||
SectorType bootSector = new SectorType ("Boot code", Color.lightGray);
|
||||
SectorType bootSector = new SectorType ("ZIP code", Color.lightGray);
|
||||
SectorType stringsSector = new SectorType ("Strings", Color.magenta);
|
||||
SectorType objectsSector = new SectorType ("Objects", green);
|
||||
SectorType dictionarySector = new SectorType ("Dictionary", Color.blue);
|
||||
|
@ -7,15 +7,15 @@ import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
class Instruction
|
||||
{
|
||||
Opcode opcode;
|
||||
int startPtr;
|
||||
byte[] buffer;
|
||||
final Opcode opcode;
|
||||
private int startPtr;
|
||||
private byte[] buffer;
|
||||
// List<ZString> abbreviations;
|
||||
Header header;
|
||||
private Header header;
|
||||
|
||||
enum OperandType
|
||||
{
|
||||
VAR_STACK, VAR_LOCAL, VAR_GLOBAL, BYTE, WORD, ARG_BRANCH, ARG_STRING
|
||||
VAR_SP, VAR_LOCAL, VAR_GLOBAL, BYTE, WORD, ARG_BRANCH, ARG_STRING
|
||||
}
|
||||
|
||||
static final String[] name2OP =
|
||||
@ -38,26 +38,23 @@ class Instruction
|
||||
"scan_table", "not", "call_vn", "call_vn2", "tokenise", "encode_text",
|
||||
"copy_table", "print_table", "check_arg" };
|
||||
|
||||
public Instruction (byte[] buffer, int ptr, Header header)
|
||||
Instruction (byte[] buffer, int ptr, Header header)
|
||||
{
|
||||
this.buffer = buffer;
|
||||
this.startPtr = ptr;
|
||||
this.header = header;
|
||||
byte b1 = buffer[ptr];
|
||||
|
||||
// long
|
||||
if ((b1 & 0x80) == 0)
|
||||
if ((b1 & 0x80) == 0) // long
|
||||
opcode = new Opcode2OPLong (buffer, ptr);
|
||||
// short
|
||||
else if ((b1 & 0x40) == 0)
|
||||
else if ((b1 & 0x40) == 0) // short
|
||||
{
|
||||
if ((b1 & 0x30) == 0x30)
|
||||
opcode = new Opcode0OP (buffer, ptr);
|
||||
else
|
||||
opcode = new Opcode1OP (buffer, ptr);
|
||||
}
|
||||
// variable
|
||||
else
|
||||
else // variable
|
||||
{
|
||||
if ((b1 & 0x20) == 0)
|
||||
opcode = new Opcode2OPVar (buffer, ptr);
|
||||
@ -66,43 +63,43 @@ class Instruction
|
||||
}
|
||||
}
|
||||
|
||||
public int length ()
|
||||
int length ()
|
||||
{
|
||||
return opcode.length ();
|
||||
}
|
||||
|
||||
public boolean isReturn ()
|
||||
boolean isReturn ()
|
||||
{
|
||||
return opcode.isReturn;
|
||||
}
|
||||
|
||||
public boolean isPrint ()
|
||||
boolean isPrint ()
|
||||
{
|
||||
return opcode.string != null;
|
||||
}
|
||||
|
||||
public boolean isCall ()
|
||||
boolean isCall ()
|
||||
{
|
||||
return opcode.isCall;
|
||||
}
|
||||
|
||||
public boolean isJump ()
|
||||
boolean isJump ()
|
||||
{
|
||||
// could use jumpTarget != 0
|
||||
return (opcode instanceof Opcode1OP && opcode.opcodeNumber == 12);
|
||||
}
|
||||
|
||||
public boolean isBranch ()
|
||||
boolean isBranch ()
|
||||
{
|
||||
return opcode.branch != null;
|
||||
}
|
||||
|
||||
public boolean isStore ()
|
||||
boolean isStore ()
|
||||
{
|
||||
return opcode.store != null;
|
||||
}
|
||||
|
||||
public int target ()
|
||||
int target ()
|
||||
{
|
||||
return isBranch () ? opcode.branch.target : 0;
|
||||
}
|
||||
@ -117,8 +114,10 @@ class Instruction
|
||||
max = 9;
|
||||
extra = "..";
|
||||
}
|
||||
|
||||
String hex = HexFormatter.getHexString (buffer, startPtr, max);
|
||||
return String.format ("%-26s%2s %s", hex, extra, opcode.toString ());
|
||||
|
||||
return String.format ("%05X : %-26s%2s %s", startPtr, hex, extra, opcode.toString ());
|
||||
}
|
||||
|
||||
abstract class Opcode
|
||||
@ -134,7 +133,7 @@ class Instruction
|
||||
int jumpTarget;
|
||||
int callTarget;
|
||||
|
||||
public Opcode ()
|
||||
Opcode ()
|
||||
{
|
||||
operands = new ArrayList<Operand> ();
|
||||
}
|
||||
@ -143,9 +142,9 @@ class Instruction
|
||||
public String toString ()
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
if (false)
|
||||
text.append (HexFormatter.formatNoHeader (buffer, startPtr, length ()) + "\n");
|
||||
text.append (String.format ("%05X : %-12s", startPtr, opcodeName ()));
|
||||
|
||||
text.append (String.format ("%-12s", opcodeName ()));
|
||||
|
||||
if (jumpTarget != 0)
|
||||
text.append (String.format (" L:%05X", jumpTarget));
|
||||
else if (isCall)
|
||||
@ -173,7 +172,7 @@ class Instruction
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
public int length ()
|
||||
int length ()
|
||||
{
|
||||
int length = totalOperandLength + opcodeLength;
|
||||
if (branch != null)
|
||||
@ -185,7 +184,7 @@ class Instruction
|
||||
return length;
|
||||
}
|
||||
|
||||
public abstract String opcodeName ();
|
||||
abstract String opcodeName ();
|
||||
|
||||
private void addOperand (Operand operand)
|
||||
{
|
||||
@ -193,7 +192,7 @@ class Instruction
|
||||
totalOperandLength += operand.length;
|
||||
}
|
||||
|
||||
protected void addOperand (byte[] buffer, int ptr, boolean bit1, boolean bit2)
|
||||
void addOperand (byte[] buffer, int ptr, boolean bit1, boolean bit2)
|
||||
{
|
||||
int offset = ptr + totalOperandLength;
|
||||
if (bit1)
|
||||
@ -207,7 +206,7 @@ class Instruction
|
||||
addOperand (new OperandWord (header.getWord (offset))); // %00
|
||||
}
|
||||
|
||||
protected void addOperand (byte[] buffer, int ptr, boolean bit)
|
||||
void addOperand (byte[] buffer, int ptr, boolean bit)
|
||||
{
|
||||
int address = ptr + totalOperandLength;
|
||||
if (address >= buffer.length)
|
||||
@ -221,7 +220,7 @@ class Instruction
|
||||
addOperand (new OperandByte (buffer[address]));
|
||||
}
|
||||
|
||||
protected void setVariableOperands (int ptr)
|
||||
void setVariableOperands (int ptr)
|
||||
{
|
||||
int value = buffer[ptr + 1] & 0xFF;
|
||||
for (int i = 0; i < 4; i++)
|
||||
@ -235,21 +234,21 @@ class Instruction
|
||||
}
|
||||
}
|
||||
|
||||
protected void setStore (byte[] buffer)
|
||||
void setStore (byte[] buffer)
|
||||
{
|
||||
store = new OperandVariable (buffer[startPtr + totalOperandLength + opcodeLength]);
|
||||
}
|
||||
|
||||
protected void setBranch (byte[] buffer)
|
||||
void setBranch (byte[] buffer)
|
||||
{
|
||||
int offset = startPtr + totalOperandLength + (store == null ? 0 : 1) + opcodeLength;
|
||||
if ((buffer[offset] & 0x40) == 0x40)
|
||||
if ((buffer[offset] & 0x40) != 0)
|
||||
branch = new ArgumentBranch (buffer[offset], offset);
|
||||
else
|
||||
branch = new ArgumentBranch (header.getWord (offset), offset);
|
||||
}
|
||||
|
||||
protected void setZString (byte[] buffer)
|
||||
void setZString (byte[] buffer)
|
||||
{
|
||||
int offset = startPtr + totalOperandLength + opcodeLength;
|
||||
string = new ArgumentString (buffer, offset);
|
||||
@ -258,7 +257,7 @@ class Instruction
|
||||
|
||||
class Opcode0OP extends Opcode
|
||||
{
|
||||
public Opcode0OP (byte[] buffer, int ptr)
|
||||
Opcode0OP (byte[] buffer, int ptr)
|
||||
{
|
||||
opcodeNumber = buffer[ptr] & 0x0F;
|
||||
opcodeLength = 1;
|
||||
@ -286,7 +285,7 @@ class Instruction
|
||||
|
||||
class Opcode1OP extends Opcode
|
||||
{
|
||||
public Opcode1OP (byte[] buffer, int ptr)
|
||||
Opcode1OP (byte[] buffer, int ptr)
|
||||
{
|
||||
opcodeNumber = buffer[ptr] & 0x0F;
|
||||
opcodeLength = 1;
|
||||
@ -315,12 +314,12 @@ class Instruction
|
||||
|
||||
abstract class Opcode2OP extends Opcode
|
||||
{
|
||||
public Opcode2OP ()
|
||||
Opcode2OP ()
|
||||
{
|
||||
opcodeLength = 1;
|
||||
}
|
||||
|
||||
public void setArguments (byte[] buffer)
|
||||
void setArguments (byte[] buffer)
|
||||
{
|
||||
if ((opcodeNumber >= 1 && opcodeNumber <= 7) || opcodeNumber == 10)
|
||||
setBranch (buffer);
|
||||
@ -338,7 +337,7 @@ class Instruction
|
||||
|
||||
class Opcode2OPLong extends Opcode2OP
|
||||
{
|
||||
public Opcode2OPLong (byte[] buffer, int ptr)
|
||||
Opcode2OPLong (byte[] buffer, int ptr)
|
||||
{
|
||||
opcodeNumber = buffer[ptr] & 0x1F;
|
||||
boolean bit1 = ((buffer[ptr] & 0x40) == 0x40);
|
||||
@ -352,7 +351,7 @@ class Instruction
|
||||
|
||||
class Opcode2OPVar extends Opcode2OP
|
||||
{
|
||||
public Opcode2OPVar (byte[] buffer, int ptr)
|
||||
Opcode2OPVar (byte[] buffer, int ptr)
|
||||
{
|
||||
opcodeNumber = buffer[ptr] & 0x1F;
|
||||
opcodeLength = 2;
|
||||
@ -363,7 +362,7 @@ class Instruction
|
||||
|
||||
class OpcodeVar extends Opcode
|
||||
{
|
||||
public OpcodeVar (byte[] buffer, int ptr)
|
||||
OpcodeVar (byte[] buffer, int ptr)
|
||||
{
|
||||
opcodeNumber = buffer[ptr] & 0x1F;
|
||||
opcodeLength = 2;
|
||||
@ -394,7 +393,7 @@ class Instruction
|
||||
|
||||
class OperandWord extends Operand
|
||||
{
|
||||
public OperandWord (int value)
|
||||
OperandWord (int value)
|
||||
{
|
||||
this.value = value;
|
||||
length = 2;
|
||||
@ -410,7 +409,7 @@ class Instruction
|
||||
|
||||
class OperandByte extends Operand
|
||||
{
|
||||
public OperandByte (byte value)
|
||||
OperandByte (byte value)
|
||||
{
|
||||
this.value = value & 0xFF;
|
||||
length = 1;
|
||||
@ -426,13 +425,13 @@ class Instruction
|
||||
|
||||
class OperandVariable extends Operand
|
||||
{
|
||||
public OperandVariable (byte value)
|
||||
OperandVariable (byte value)
|
||||
{
|
||||
this.value = value & 0xFF;
|
||||
length = 1;
|
||||
|
||||
if (value == 0)
|
||||
operandType = OperandType.VAR_STACK;
|
||||
operandType = OperandType.VAR_SP;
|
||||
else if (value <= 15)
|
||||
operandType = OperandType.VAR_LOCAL;
|
||||
else
|
||||
@ -442,8 +441,8 @@ class Instruction
|
||||
@Override
|
||||
public String toString ()
|
||||
{
|
||||
if (operandType == OperandType.VAR_STACK)
|
||||
return ("ToS");
|
||||
if (operandType == OperandType.VAR_SP)
|
||||
return ("SP");
|
||||
if (operandType == OperandType.VAR_LOCAL)
|
||||
return (String.format ("L%02d", value));
|
||||
return String.format ("G%03d", (value - 15));
|
||||
@ -452,13 +451,13 @@ class Instruction
|
||||
|
||||
class ArgumentBranch extends Operand
|
||||
{
|
||||
int target;
|
||||
boolean branchOnTrue;
|
||||
private int target;
|
||||
private boolean branchOnTrue;
|
||||
|
||||
public ArgumentBranch (byte value, int offset)
|
||||
ArgumentBranch (byte value, int offset)
|
||||
{
|
||||
branchOnTrue = (value & 0x80) == 0x80;
|
||||
int val = value & 0x3F; // unsigned
|
||||
branchOnTrue = (value & 0x80) != 0;
|
||||
int val = value & 0x3F; // 0 - 63
|
||||
if (val <= 1)
|
||||
target = val;
|
||||
else
|
||||
@ -467,12 +466,19 @@ class Instruction
|
||||
operandType = OperandType.ARG_BRANCH;
|
||||
}
|
||||
|
||||
public ArgumentBranch (int value, int offset)
|
||||
ArgumentBranch (int value, int offset)
|
||||
{
|
||||
branchOnTrue = (value & 0x8000) == 0x8000;
|
||||
int val = value & 0x3FFF; // signed
|
||||
if (val > 8191)
|
||||
val -= 16384;
|
||||
branchOnTrue = (value & 0x8000) != 0;
|
||||
int val = ((value & 0x3FFF) << 18) >> 18; // signed 14-bit number
|
||||
// int val = value & 0x3FFF; // signed
|
||||
// if (val >= 0x2000)
|
||||
// {
|
||||
// System.out.printf ("%04X -> %d%n", val, (val - 0x4000));
|
||||
// val -= 0x4000;
|
||||
// }
|
||||
// else
|
||||
// System.out.printf ("%04X%n", val);
|
||||
|
||||
target = val + offset;
|
||||
length = 2;
|
||||
operandType = OperandType.ARG_BRANCH;
|
||||
@ -493,11 +499,11 @@ class Instruction
|
||||
|
||||
class ArgumentString extends Operand
|
||||
{
|
||||
ZString text;
|
||||
int startPtr;
|
||||
byte[] buffer;
|
||||
private ZString text;
|
||||
private int startPtr;
|
||||
private byte[] buffer;
|
||||
|
||||
public ArgumentString (byte[] buffer, int offset)
|
||||
ArgumentString (byte[] buffer, int offset)
|
||||
{
|
||||
this.buffer = buffer;
|
||||
text = new ZString (header, offset);
|
||||
|
@ -39,10 +39,7 @@ class ObjectAnalyser
|
||||
pt.addTest (hmc);
|
||||
pt.doTests ();
|
||||
|
||||
// System.out.println ("\nSetting the string pointer\n");
|
||||
|
||||
for (Integer propertyNo : pt)
|
||||
// list of all properties that passed all tests
|
||||
for (Integer propertyNo : pt) // list of all properties that passed all tests
|
||||
list.add (hmc.statistics[propertyNo]);
|
||||
Collections.sort (list);
|
||||
|
||||
@ -88,22 +85,22 @@ class ObjectAnalyser
|
||||
System.out.println ("Routines found : " + totRoutines);
|
||||
}
|
||||
|
||||
public void checkThreeByteProperties ()
|
||||
{
|
||||
for (ZObject object : parent.getObjects ())
|
||||
{
|
||||
for (Property property : object.properties)
|
||||
{
|
||||
if (header.getPropertyName (property.propertyNumber).charAt (0) < 'a'
|
||||
&& property.length == 3)
|
||||
{
|
||||
int address = header.getWord (property.ptr + 1) * 2;
|
||||
System.out.println ("checking " + address);
|
||||
header.codeManager.addRoutine (address, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// private void checkThreeByteProperties ()
|
||||
// {
|
||||
// for (ZObject object : parent.getObjects ())
|
||||
// {
|
||||
// for (Property property : object.properties)
|
||||
// {
|
||||
// if (header.getPropertyName (property.propertyNumber).charAt (0) < 'a'
|
||||
// && property.length == 3)
|
||||
// {
|
||||
// int address = header.getWord (property.ptr + 1) * 2;
|
||||
// System.out.println ("checking " + address);
|
||||
// header.codeManager.addRoutine (address, 0);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// find the property with only dictionary entries
|
||||
public void setDictionary ()
|
||||
|
@ -10,8 +10,6 @@ import com.bytezone.diskbrowser.infocom.Instruction.OperandType;
|
||||
class Routine extends InfocomAbstractFile
|
||||
implements Iterable<Instruction>, Comparable<Routine>
|
||||
{
|
||||
private static final String padding = " ";
|
||||
|
||||
int startPtr, length, strings, locals;
|
||||
|
||||
List<Parameter> parameters = new ArrayList<Parameter> ();
|
||||
@ -28,7 +26,7 @@ class Routine extends InfocomAbstractFile
|
||||
if (locals > 15)
|
||||
{
|
||||
System.out.println ("Too many locals: " + locals);
|
||||
return;
|
||||
return; // startPtr will be zero
|
||||
}
|
||||
|
||||
startPtr = ptr++; // also used to flag a valid routine
|
||||
@ -61,16 +59,19 @@ class Routine extends InfocomAbstractFile
|
||||
if (operand.operandType == OperandType.VAR_GLOBAL)
|
||||
header.globals.addRoutine (this, operand);
|
||||
|
||||
ptr += instruction.length ();
|
||||
ptr += instruction.length (); // point to next instruction
|
||||
if (isTarget (ptr))
|
||||
continue;
|
||||
|
||||
// is it a backwards jump?
|
||||
if (instruction.isJump () && instruction.target () < ptr && !moreCode (ptr))
|
||||
if (instruction.isJump () && instruction.target () < ptr)
|
||||
break;
|
||||
|
||||
// is it an unconditional return?
|
||||
if (instruction.isReturn () && !moreCode (ptr))
|
||||
if (instruction.isReturn ())
|
||||
break;
|
||||
}
|
||||
|
||||
length = ptr - startPtr;
|
||||
|
||||
hexBlocks.add (new HexBlock (startPtr, length, null));
|
||||
@ -79,22 +80,27 @@ class Routine extends InfocomAbstractFile
|
||||
if (true)
|
||||
{
|
||||
int endPtr = startPtr + length;
|
||||
for (Instruction ins : instructions)
|
||||
for (Instruction instruction : instructions)
|
||||
{
|
||||
int target = ins.target () > 256 ? ins.target ()
|
||||
: ins.opcode.jumpTarget > 256 ? ins.opcode.jumpTarget : 0;
|
||||
int target = instruction.target () > 256 ? instruction.target ()
|
||||
: instruction.opcode.jumpTarget > 256 ? instruction.opcode.jumpTarget : 0;
|
||||
if (target == 0)
|
||||
continue;
|
||||
if (ins.isBranch () && (target > endPtr || target < startPtr))
|
||||
System.out.println (ins);
|
||||
if (ins.isJump () && (target > endPtr || target < startPtr))
|
||||
System.out.println (ins);
|
||||
if (instruction.isBranch () && (target > endPtr || target < startPtr))
|
||||
System.out.println (instruction);
|
||||
if (instruction.isJump () && (target > endPtr || target < startPtr))
|
||||
System.out.println (instruction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isValid ()
|
||||
{
|
||||
return startPtr > 0;
|
||||
}
|
||||
|
||||
// test whether the routine contains any instructions pointing to this address
|
||||
private boolean moreCode (int ptr)
|
||||
private boolean isTarget (int ptr)
|
||||
{
|
||||
for (Instruction ins : instructions)
|
||||
{
|
||||
@ -116,17 +122,45 @@ class Routine extends InfocomAbstractFile
|
||||
public String getText ()
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
text.append (String.format ("Called by : %3d%n", calledBy.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 ("Calls : %3d%n", calls.size ()));
|
||||
text.append (String.format ("Length : %3d%n%n", length));
|
||||
|
||||
text.append (String.format ("%05X : %d%n", startPtr, locals));
|
||||
|
||||
for (Parameter parameter : parameters)
|
||||
text.append (padding + parameter.toString () + "\n");
|
||||
text.append (parameter.toString () + "\n");
|
||||
|
||||
text.append ("\n");
|
||||
|
||||
for (Instruction instruction : instructions)
|
||||
text.append (instruction + "\n");
|
||||
|
||||
if (calledBy.size () > 0)
|
||||
{
|
||||
text.append ("\n\nCalled by\n\n");
|
||||
for (int i : calledBy)
|
||||
text.append (String.format ("%05X%n", i));
|
||||
}
|
||||
|
||||
if (calls.size () > 0)
|
||||
{
|
||||
text.append ("\n\nCalls\n\n");
|
||||
for (int i : calls)
|
||||
text.append (String.format ("%05X%n", i));
|
||||
}
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString ()
|
||||
{
|
||||
return String.format ("[Start: %05X, Len: %4d, Strings: %2d, Locals: %2d]", startPtr,
|
||||
length, strings, locals);
|
||||
}
|
||||
|
||||
class Parameter
|
||||
{
|
||||
int value;
|
||||
|
Loading…
Reference in New Issue
Block a user