1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.zmpp.vm;
24
25 import org.zmpp.base.MemoryAccess;
26
27 /***
28 * This is the default implementation of a ZObject.
29 *
30 * @author Wei-ju Wu
31 * @version 1.0
32 */
33 public class DefaultZObject implements ZObject {
34
35 /***
36 * The property table is defined in the object's context
37 * to make it dependent on a specific instance.
38 */
39 private class PropertyTable {
40
41 /***
42 * Returns this property table's description string address.
43 *
44 * @return the address of the description
45 */
46 public int getDescriptionAddress() {
47
48 return getPropertyTableAddress() + 1;
49 }
50
51 /***
52 * Returns the start address of the actual property entries.
53 *
54 * @return the property entries' start address
55 */
56 private int getPropertyEntriesStart() {
57
58 return getPropertyTableAddress() + getDescriptionHeaderSize();
59 }
60
61 /***
62 * Returns the size of the description header in bytes that is,
63 * the size byte plus the description string size.
64 *
65 * @return the size of the description header
66 */
67 private int getDescriptionHeaderSize() {
68
69 int startAddr = getPropertyTableAddress();
70 return memaccess.readUnsignedByte(startAddr) * 2 + 1;
71 }
72
73 /***
74 * Reads the property size byte at the given address.
75 *
76 * @param address the address of a property size byte
77 * @return the size of the property entry in bytes
78 */
79 private int getPropertySizeAtAddress(int address) {
80
81 return memaccess.readUnsignedByte(address) / 32 + 1;
82 }
83
84 /***
85 * Returns the address of the specified property.
86 *
87 * @param index the property index
88 * @return the address of the specified property
89 */
90 private int getPropertyAddress(int index) {
91
92 int addr = getPropertyEntriesStart();
93 int size = 0;
94
95
96
97 for (int i = 0; i < index; i++) {
98
99 size = getPropertySizeAtAddress(addr);
100 addr += (size + 1);
101 }
102 return addr;
103 }
104
105 /***
106 * Returns the number of properties in this property table.
107 *
108 * @return the number of properties
109 */
110 public int getNumProperties() {
111
112 int row = 0;
113 while (memaccess.readUnsignedByte(getPropertyAddress(row)) > 0) {
114
115 row++;
116 }
117 return row;
118 }
119
120 /***
121 * Returns the size of the property in bytes.
122 *
123 * @param index the property index
124 * @return the size of the specified property in bytes
125 */
126 public int getSize(int index) {
127
128 return getPropertySizeAtAddress(getPropertyAddress(index));
129 }
130
131 /***
132 * Returns the property at the specified row and column position.
133 *
134 * @param index the property index
135 * @param bytenum the byte number
136 * @return the unsigned byte value at the specified position of the
137 * property
138 */
139 public byte getPropertyByte(int index, int bytenum) {
140
141 int addr = getPropertyAddress(index);
142 return memaccess.readByte(addr + 1 + bytenum);
143 }
144
145 /***
146 * Writes a value to the specified property byte.
147 *
148 * @param index the property index
149 * @param bytenum the byte number
150 * @param value the value to set
151 */
152 public void setPropertyByte(int index, int bytenum, byte value) {
153
154 int addr = getPropertyAddress(index);
155 memaccess.writeByte(addr + 1 + bytenum, value);
156 }
157
158 /***
159 * Returns the property number at the specified table index.
160 *
161 * @param index the property table index
162 * @return the property number
163 */
164 public short getPropertyNum(int index) {
165
166 int addr = getPropertyAddress(index);
167 int sizeByte = memaccess.readUnsignedByte(addr);
168 return (short) (sizeByte - 32 * (getPropertySizeAtAddress(addr) - 1));
169 }
170
171 /***
172 * Returns the property table index for the specified property number.
173 *
174 * @param propertyNum the property number
175 * @return the table index
176 */
177 public short getPropertyIndex(int propertyNum) {
178
179 for (int i = 0; i < getNumProperties(); i++) {
180
181 if (getPropertyNum(i) == propertyNum) return (short) i;
182 }
183 return -1;
184 }
185
186 /***
187 * Returns the size of this object's property table in bytes.
188 *
189 * @return the size of the property table in bytes
190 */
191 public int getDataLength() {
192
193 int size = getDescriptionHeaderSize();
194
195 for (int i = 0; i < getNumProperties(); i++) {
196
197 size += (getSize(i) + 1);
198 }
199 return size;
200 }
201 }
202
203 /***
204 * The memory access object.
205 */
206 private MemoryAccess memaccess;
207
208 /***
209 * The address of this Z-object.
210 */
211 int address;
212
213 /***
214 * This object's properties.
215 */
216 private PropertyTable propertyTable;
217
218 /***
219 * Constructor.
220 *
221 * @param address the start address of the object
222 */
223 public DefaultZObject(MemoryAccess memaccess, int address) {
224
225 this.memaccess = memaccess;
226 this.address = address;
227 this.propertyTable = new PropertyTable();
228 }
229
230 /***
231 * The attribute flags, a 32 bit unsigned value as a long.
232 *
233 * @return the attribute flags
234 */
235 private long getAttributeFlags() {
236
237 return memaccess.readUnsigned32(address);
238 }
239
240 /***
241 * Sets a 32 bit unsigned value to the attribute flags.
242 *
243 * @param flags32 the flags value
244 */
245 private void setAttributeFlags(long flags32) {
246
247 memaccess.writeUnsigned32(address, flags32);
248 }
249
250 /***
251 * {@inheritDoc}
252 */
253 public boolean isAttributeSet(int attributeNum) {
254
255 long bitmask = 0x0000000080000000l >> attributeNum;
256 return (getAttributeFlags() & bitmask) != 0;
257 }
258
259 /***
260 * {@inheritDoc}
261 */
262 public void setAttribute(int attributeNum) {
263
264 long bitmask = 0x0000000080000000l >> attributeNum;
265 long value = (getAttributeFlags() | bitmask);
266 setAttributeFlags(value);
267 }
268
269 /***
270 * {@inheritDoc}
271 */
272 public void clearAttribute(int attributeNum) {
273
274 long bitmask = (long) 0xffffffff7fffffffl >> attributeNum;
275 long value = (getAttributeFlags() & bitmask);
276 setAttributeFlags(value);
277 }
278
279 /***
280 * {@inheritDoc}
281 */
282 public int getParent() {
283
284 return memaccess.readUnsignedByte(address + 4);
285 }
286
287 /***
288 * {@inheritDoc}
289 */
290 public void setParent(int parent) {
291
292 memaccess.writeUnsignedByte(address + 4, (short) (parent & 0xff));
293 }
294
295 /***
296 * {@inheritDoc}
297 */
298 public int getSibling() {
299
300 return memaccess.readUnsignedByte(address + 5);
301 }
302
303 /***
304 * {@inheritDoc}
305 */
306 public void setSibling(int sibling) {
307
308 memaccess.writeUnsignedByte(address + 5, (short) (sibling & 0xff));
309 }
310
311 /***
312 * {@inheritDoc}
313 */
314 public int getChild() {
315
316 return memaccess.readUnsignedByte(address + 6);
317 }
318
319 /***
320 * {@inheritDoc}
321 */
322 public void setChild(int child) {
323
324 memaccess.writeUnsignedByte(address + 6, (short) (child & 0xff));
325 }
326
327 /***
328 * {@inheritDoc}
329 */
330 public int getPropertyTableAddress() {
331
332 return memaccess.readUnsignedShort(address + 7);
333 }
334
335 /***
336 * {@inheritDoc}
337 */
338 public int getPropertiesDescriptionAddress() {
339
340 return propertyTable.getDescriptionAddress();
341 }
342
343 /***
344 * {@inheritDoc}
345 */
346 public int getNumProperties() {
347
348 return propertyTable.getNumProperties();
349 }
350
351 /***
352 * {@inheritDoc}
353 */
354 public int getPropertySize(int property) {
355
356 int index = propertyTable.getPropertyIndex(property);
357 return propertyTable.getSize(index);
358 }
359
360 /***
361 * {@inheritDoc}
362 */
363 public byte getPropertyByte(int property, int bytenum) {
364
365 int index = propertyTable.getPropertyIndex(property);
366 return propertyTable.getPropertyByte(index, bytenum);
367 }
368
369 /***
370 * {@inheritDoc}
371 */
372 public int getPropertyAddress(int property) {
373
374 int index = propertyTable.getPropertyIndex(property);
375 return propertyTable.getPropertyAddress(index) + 1;
376 }
377
378 /***
379 * {@inheritDoc}
380 */
381 public boolean isPropertyAvailable(int property) {
382
383 return (propertyTable.getPropertyIndex(property) >= 0);
384 }
385
386 /***
387 * {@inheritDoc}
388 */
389 public int getNextProperty(int property) {
390
391 if (property == 0) {
392
393 return propertyTable.getPropertyNum(0);
394
395 } else {
396
397 int index = propertyTable.getPropertyIndex(property);
398 return propertyTable.getPropertyNum(index + 1);
399 }
400 }
401
402 /***
403 * {@inheritDoc}
404 */
405 public void setPropertyByte(int property, int bytenum, byte value) {
406
407 int index = propertyTable.getPropertyIndex(property);
408 propertyTable.setPropertyByte(index, bytenum, value);
409 }
410 }