View Javadoc

1   /*
2    * $Id: Objects.java,v 1.16 2005/10/25 21:40:54 weiju Exp $
3    * 
4    * Created on 25.09.2005
5    * Copyright 2005 by Wei-ju Wu
6    *
7    * This file is part of The Z-machine Preservation Project (ZMPP).
8    *
9    * ZMPP is free software; you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as published by
11   * the Free Software Foundation; either version 2 of the License, or
12   * (at your option) any later version.
13   *
14   * ZMPP is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   *
19   * You should have received a copy of the GNU General Public License
20   * along with ZMPP; if not, write to the Free Software
21   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22   */
23  package org.zmpp.vm;
24  
25  import org.zmpp.base.MemoryAccess;
26  
27  /***
28   * This class represents the object table.
29   * 
30   * @author Wei-ju Wu
31   * @version 1.0
32   */
33  public class Objects implements ObjectTree {
34    
35    /***
36     * The memory access object.
37     */
38    private MemoryAccess memaccess;
39    
40    /***
41     * The object table's start address.
42     */
43    private int address;
44    
45    /***
46     * Constructor.
47     * 
48     * @param memaccess the memory access object
49     * @param address the object table's start address
50     */
51    public Objects(MemoryAccess memaccess, int address) {
52  
53      this.memaccess = memaccess;
54      this.address = address;
55    }
56  
57    /***
58     * {@inheritDoc}
59     */
60    public short getPropertyDefault(int propertyNum) {
61      
62      int index = propertyNum - 1;
63      return memaccess.readShort(address + index * 2);
64    }
65    
66    /***
67     * {@inheritDoc}
68     */
69    public int getNumObjects() {
70      
71      // The information about the number of objects can not directly
72      // read from the header.
73      // We assume that the first object always contains the property table
74      // with the lowest address
75      return (getObject((short) 1).getPropertyTableAddress()
76              - getObjectTreeStart()) / getObjectEntrySize();
77    }
78  
79    /***
80     * {@inheritDoc}
81     */
82    public ZObject getObject(int objectNum) {
83      
84      int objTreeStart = address + getPropertyDefaultsSize();
85      
86      // flags + (parent, sibling, child) + properties
87      return new DefaultZObject(memaccess,
88          objTreeStart + (objectNum - 1)* getObjectEntrySize());
89    }
90  
91    /***
92     * {@inheritDoc}
93     */
94    public void removeObject(int objectNum) {
95      
96      ZObject obj = getObject(objectNum);
97      ZObject parentObj = getObject(obj.getParent());
98      obj.setParent((short) 0);
99      
100     if (parentObj.getChild() == objectNum) {
101       
102       parentObj.setChild(obj.getSibling());
103       
104     } else {
105       
106       // Find the child that comes directly before the removed
107       // node and set the direct sibling of the removed node as
108       // its new sibling
109       ZObject currentChild = getObject(parentObj.getChild());
110       int sibling = currentChild.getSibling();
111       
112       while (sibling != objectNum) {
113         
114         currentChild = getObject(sibling);
115         sibling = currentChild.getSibling();
116       }
117       currentChild.setSibling(obj.getSibling());
118     }
119     obj.setSibling((short) 0);
120   }
121   
122   /***
123    * {@inheritDoc}
124    */
125   public void insertObject(int parentNum, int objectNum) {
126     
127     ZObject parent = getObject(parentNum);
128     ZObject child = getObject(objectNum);
129     
130     // we want to ensure, the child has no old parent relationships
131     if (child.getParent() > 0) {
132       
133       removeObject(objectNum);
134     }
135     
136     int oldChild = parent.getChild();
137     
138     child.setParent(parentNum);
139     parent.setChild(objectNum);
140     child.setSibling(oldChild);
141   }
142   
143   /***
144    * {@inheritDoc}
145    */
146   public int getPropertyLength(int propertyAddress) {
147     
148     if (propertyAddress == 0) return 0; // see standard 1.1
149     
150     short sizebyte = memaccess.readUnsignedByte(propertyAddress - 1);
151     return sizebyte / 32 + 1;
152   }
153   
154   /***
155    * The size of the property defaults section.
156    * 
157    * @return the property defaults section
158    */  
159   private int getPropertyDefaultsSize() {
160     
161     return 31 * 2;
162   }
163   
164   /***
165    * Returns the start address of the object tree section.
166    * 
167    * @return the object tree's start address 
168    */
169   private int getObjectTreeStart() {
170     
171     return address + getPropertyDefaultsSize();
172   }
173   
174   /***
175    * The object entry size in version 3 is always 9.
176    * 
177    * @return the size of an object entry
178    */
179   private int getObjectEntrySize() {
180     
181     return 9;
182   }  
183 }