Skip to content

Commit

Permalink
Lots of work on the object table and implemented some opcodes
Browse files Browse the repository at this point in the history
  • Loading branch information
Alan Bucior committed Mar 9, 2015
1 parent 5701c9b commit b3e23ab
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 70 deletions.
2 changes: 0 additions & 2 deletions Build1/zmachine/zmachine/Memory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ public void load(string filename)
}

}


//assign given byte value @ hex address location
public void setByte(uint address, byte val)
{
Expand Down
142 changes: 98 additions & 44 deletions Build1/zmachine/zmachine/ObjectTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ public int getDefaultProperty(int property) // Rewrite this so that it only
tp += (property - 1) * 2;
int defaultProperty = tp_getWord();
return defaultProperty;
}

}
public int getObjectTable()
{
tp = memory.getWord((uint)Memory.ADDR_OBJECTS + (31 * 2));
Expand All @@ -40,74 +39,129 @@ public int getPropertyTableAddress(int objectId)

tp = getObjectAddress(objectId) + 7;
int propertyTableAddress = tp_getWord();
/* Each object has its own property table. Each of these can be anywhere in dynamic memory
* (indeed, a game can legally change an object's properties table address in play, provided the new address points to another valid properties table).
* The header of a property table is as follows:
*
* text-length text of short name of object
* -----byte---- --some even number of bytes---
* where the text-length is the number of 2-byte words making up the text, which is stored in the usual format.
* (This means that an object's short name is limited to 765 Z-characters.) After the header, the properties are listed in descending numerical order.
* (This order is essential and is not a matter of convention.)
In Versions 1 to 3, each property is stored as a block:
* size byte the actual property data
* ---between 1 and 8 bytes--
* where the size byte is arranged as 32 times the number of data bytes minus one, plus the property number.
* A property list is terminated by a size byte of 0. (It is otherwise illegal for a size byte to be a multiple of 32.) */
return propertyTableAddress;
}

public int getObjectAddress(int objectId)
public int getObjectAddress(int objectId) // take an objectId and consult the objectTable
{

getObjectTable();
tp += 9 * (objectId - 1); // tp will already be set at the start of the object table
int objectAddress = tp;
// each object is 9 bytes above the previous
// take an objectId and consult the objectTable
int objectAddress = tp; // each object is 9 bytes above the previous

return objectAddress;
}

public int getObjectPropertyAddress(int objectId, int property)
{
int propertyAddress;
tp = getPropertyTableAddress(objectId);
int text_length = tp_getByte(); // Read the first byte of the property address, figure out the text-length, then skip forward to the first property address.
tp += (text_length * 2); // skip past header

for (int i = 1; i < property; i++)
int sizeByte = tp_getByte(); // get initial sizeByte (property 1)
while (sizeByte > 0)
{
int text_length = tp_getByte(); // Read the first byte of the property address, figure out the text-length, then skip forward to the next property address. Do this i times.
tp += tp * (text_length * 2);
int propertyId = sizeByte & 31;
int propLen = (sizeByte / 32) + 1;
if (property == propertyId)
{
propertyAddress = tp;
return propertyAddress;
}
tp += propLen;
sizeByte = tp_getByte();
}
propertyAddress = tp;
return propertyAddress;
return 0;
}
public int getNextObjectPropertyIdAfter(int objectId, int property)
{
int propLen;
int nextPropertyId;
byte sizeByte;
// Since we are not at the start of the property we want...
tp = getObjectPropertyAddress(objectId, property); // Set pointer to start of given property
sizeByte = memory.getByte((uint)tp - 1); // Find length of property
propLen = getObjectPropertyLengthFromAddress(tp);

if (sizeByte == 0) // No next property
return 0;

tp += propLen; // Move pointer to start next property and skip header
nextPropertyId = tp_getByte() & 31; // Read next property number

return nextPropertyId;
}
public int getObjectPropertyLengthFromAddress(int propertyAddress)
{
tp = memory.getWord((uint)propertyAddress);
int sizeByte = memory.getByte((uint)propertyAddress - 1); // arranged as 32 times the number of data bytes minus one, plus the property number
return sizeByte;

int propLen = (sizeByte / 32) + 1;
return propLen;
}

public int getObjectProperty(int objectId, int property)
{
// each property is stored as a block
//size byte the actual property data
//---between 1 and 8 bytes--

int propertyAddress = getObjectPropertyAddress(objectId, property);
int[] propertyList = new int[8];

for (int i = 0; i < getObjectPropertyLengthFromAddress(propertyAddress); i++)
if (propertyAddress == 0)
{
propertyList[i] = tp_getByte();
return getDefaultProperty(property);
}
// From here, we read past the header based on the length in getObjectPropertyLengthFromAddress(int propertyAddress)
// After the header, the properties are listed in descending numerical order.
// each property is stored as a block
//size byte the actual property data
//---between 1 and 8 bytes--
return propertyList[property]; // When we refer to the "property", is it a list of values? Is it the whole thing? If so, how do I return 8 bytes of data nicely?

int propertyData;
int propLen = getObjectPropertyLengthFromAddress(propertyAddress); // get size of property

if (propLen == 1) // Return size of property (byte or word)
propertyData = tp_getByte();
else
propertyData = tp_getWord();

return propertyData;
}
public bool getObjectAttribute(int objectId, int attributeId)
{
tp = getObjectAddress(objectId);
bool [] attributes = new bool[32];
byte attributeSegment;

// Why not just make a boolean array of the attributes?!
for (int i = 0; i < 4; i++)
{
attributeSegment = tp_getByte();
for (int j = 0; j < 8; j++)
{
attributes[i * 8 + j] = Convert.ToBoolean((attributeSegment >> (7 - j)) & 0x01);// Take the next byte and cut the first (MSB) value off the top. Add to boolean array attribute[]
}
}

return attributes[attributeId];
}
public void setObjectAttribute(int objectId, int attributeId, bool value)
{
byte a; // If can find the right byte in the memory, I can bitwise AND or OR to clear or fill it.
uint address = (uint)getObjectAddress(objectId);
uint attributeSegment = (uint)(attributeId / 4); // The byte of the attribute header that we are working in
int attributeShift = attributeId % 8;

if (value == true)
{
a = memory.getByte(address + attributeSegment); // If
a |= (byte)(1 << attributeShift);
}
else
{
a = memory.getByte(address + attributeSegment);
a &= (byte)(1 << attributeShift);
}
memory.setByte(address, a);

}
public void setObjectProperty(int objectId, int property, int value)
{
getObjectPropertyAddress(objectId, property);

}

// --------------------------
public byte tp_getByte()
Expand All @@ -127,9 +181,9 @@ public ushort tp_getWord()
public String objectName(int objectId)
{
Machine.StringAndReadLength str = new Machine.StringAndReadLength();
getObjectAddress(objectId);
int byteNumber = tp_getByte();
str = Machine.getZSCII((uint)objectId, (uint)byteNumber);
getPropertyTableAddress(objectId); // An object's name is stored in the header of its property table, and is given in the text-length.
int byteNumber = tp_getByte(); // The first byte is the text-length number of words in the short name
str = Machine.getZSCII((uint)getPropertyTableAddress(objectId), (uint)byteNumber);
String objectName = str.str;
return objectName;
}
Expand Down
10 changes: 5 additions & 5 deletions Build1/zmachine/zmachine/ObjectTableFunctions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ DONE public int getDefaultProperty(int property)

DONE public int getObjectPropertyAddr(int objectId, int property)

public int getNextObjectPropertyIdAfter(int objectId, int property)
DONE public int getNextObjectPropertyIdAfter(int objectId, int property)

DONE? public int getObjectProperty(int objectId, int property)
DONE public int getObjectProperty(int objectId, int property)

public void setObjectProperty(int objectId, int property, int value)

In Progress public int getObjectPropertyLengthFromAddress(int propertyAddress)
DONE public int getObjectPropertyLengthFromAddress(int propertyAddress)

public boolean getObjectAttribute(int objectId, int attributeId)
DONE public boolean getObjectAttribute(int objectId, int attributeId)

public void setObjectAttribute(int objectId, int attributeId, int value)
DONE public void setObjectAttribute(int objectId, int attributeId, int value)

public int getParent(int objectId)

Expand Down
20 changes: 11 additions & 9 deletions Build1/zmachine/zmachine/OpcodeHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public class op_and : OpcodeHandler_2OP
public class op_test_attr : OpcodeHandler_2OP
{
public override String name() { return "op_test_attr"; }
public override void run(Machine machine,ushort v1, ushort v2) { machine.branch((v1 & v2) == v2); }
public override void run(Machine machine, ushort v1, ushort v2) { fail_unimplemented(machine); }
}
public class op_set_attr : OpcodeHandler_2OP
{
Expand Down Expand Up @@ -275,7 +275,7 @@ public class op_not : OpcodeHandler_1OP
public class op_print_addr : OpcodeHandler_1OP
{
public override String name() { return "op_print_addr"; }
public override void run(Machine machine,ushort v1) { fail_unimplemented(machine); }
public override void run(Machine machine,ushort v1) { Console.WriteLine(machine.getZSCII(v1, 0)); }
}
public class op_remove_obj : OpcodeHandler_1OP
{
Expand Down Expand Up @@ -304,7 +304,7 @@ public override void run(Machine machine, ushort v1)
public class op_print_paddr : OpcodeHandler_1OP
{
public override String name() { return "op_print_paddr"; }
public override void run(Machine machine,ushort v1) { fail_unimplemented(machine); }
public override void run(Machine machine, ushort v1) { Console.Write(machine.getZSCII((uint)v1 * 2, 0)); }
}
public class op_load : OpcodeHandler_1OP
{
Expand All @@ -326,12 +326,16 @@ public class op_rfalse : OpcodeHandler_0OP
public class op_print : OpcodeHandler_0OP
{
public override String name() { return "op_print"; }
public override void run(Machine machine) { fail_unimplemented(machine); }
public override void run(Machine machine) { Console.Write(machine.getZSCII(machine.pc_getWord(), 0)); }
}
public class op_print_ret : OpcodeHandler_0OP
{
public override String name() { return "op_print_ret"; }
public override void run(Machine machine) { fail_unimplemented(machine); }
public override void run(Machine machine)
{
Console.WriteLine(machine.getZSCII(machine.pc_getWord(), 0));
machine.popRoutineData(1);
}
}
public class op_nop : OpcodeHandler_0OP
{
Expand Down Expand Up @@ -427,16 +431,14 @@ public class op_sread : OpcodeHandler_OPVAR
public class op_print_char : OpcodeHandler_OPVAR
{
public override String name() { return "op_print_char"; }
public override void run(Machine machine,List<ushort> operands) { fail_unimplemented(machine); }
public override void run(Machine machine, List<ushort> operands) { Console.Write(machine.getZChar(operands[0])); }
}
public class op_print_num : OpcodeHandler_OPVAR
{
public override String name() { return "op_print_num"; }
public override void run(Machine machine,List<ushort> operands)
{
if (operands[0] < 0)
Console.Write("-");
Console.Write(operands[0]);
Console.Write((short)operands[0]);
}
}
public class op_random : OpcodeHandler_OPVAR
Expand Down
20 changes: 10 additions & 10 deletions Build1/zmachine/zmachine/zmachinestatus.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,17 @@ Unimplemented: (** = easy. Good next steps)
1OP:130 get_child object -> (result) ?(label)
1OP:131 get_parent object -> (result)
1OP:132 get_prop_len property-address -> (result)
1OP:135 print_addr byte-address-of-string
1OP:137 remove_obj object
1OP:138 print_obj object
1OP:141 print_paddr packed-address-of-string
0OP:178 print (literal-string)
0OP:179 print_ret (literal-string)
1OP:138 print_obj object
VAR:227 put_prop object property value
VAR:228 sread text parse
VAR:229 print_char output-character-code
VAR:228 sread text parse

In progress:
1OP:142 load (variable) -> (result)
2OP:7 test bitmap flags ?(label)
VAR:230 print_num value
1OP:135 print_addr byte-address-of-string
1OP:141 print_paddr packed-address-of-string
0OP:178 print (literal-string)
0OP:179 print_ret (literal-string)
VAR:229 print_char output-character-code

Done:

Expand All @@ -34,6 +31,7 @@ Done:
2OP:3 jg a b ?(label)
2OP:4 dec_chk (variable) value ?(label)
2OP:5 inc_chk (variable) value ?(label)
2OP:7 test bitmap flags ?(label)
2OP:8 or a b -> (result)
2OP:9 and a b -> (result)
2OP:13 store (variable) value
Expand All @@ -49,6 +47,7 @@ Done:
1OP:134 dec (variable)
1OP:139 ret value
1OP:140 jump ?(label)
1OP:142 load (variable) -> (result)
1OP:143 not value -> (result) <- Wasn't actually implemented until v4
0OP:176 rtrue
0OP:177 rfalse
Expand All @@ -60,6 +59,7 @@ Done:
VAR:224 call routine ...0 to 3 args... -> (result)
VAR:225 storew array word-index value
VAR:226 storeb array byte-index value
VAR:230 print_num value
VAR:231 random range -> (result)
VAR:232 push value
VAR:233 pull (variable)
Expand Down

0 comments on commit b3e23ab

Please sign in to comment.