1 /*
2   Prop
3 */
4 
5 #include "prop.h"
6 
7 #include "head.h"
8 #include "mem.h"
9 #include "object.h"
10 #include "shared.h"
11 #include "support.h"
12 #include "var.h"
13 
14 #define STD_PROP_NUM_BITS       5
15 #define PLUS_PROP_NUM_BITS      6
16 #define STD_PROP_NUM_MASK       0x1F
17 #define PLUS_PROP_NUM_MASK      0x3F
18 #define NEXT_BYTE_IS_LENGTH     0x80U
19 #define STD_WORD_MASK           0x20U
20 #define PLUS_WORD_MASK          0x40U
21 
22 #define STD_PROPERTY_LENGTH(p) \
23   (word) ((rd_byte_addr(p) >> STD_PROP_NUM_BITS) + (word) 1)
24 #define PLUS_PROPERTY_LENGTH(p) \
25   PLUS_PROPERTY_NUMBER(p)
26 #define STD_PROPERTY_NUMBER(p) \
27   (rd_byte_addr(p) & STD_PROP_NUM_MASK)
28 #define PLUS_PROPERTY_NUMBER(p) \
29   (byte) (rd_byte_addr(p) & PLUS_PROP_NUM_MASK)
30 #define WORD_MASK \
31   (hd_plus() ? PLUS_WORD_MASK : STD_WORD_MASK)
32 #define PROPERTY_NUMBER(p) \
33   (hd_plus() ? PLUS_PROPERTY_NUMBER(p) : STD_PROPERTY_NUMBER(p))
34 
35 typedef long_word property;
36 
prop_addr(word obj)37 static property prop_addr(word obj)
38 {
39   property p = obj_prop(obj);
40   return p + 2 * (long_word) rd_byte_addr(p) + 1;
41 }
42 
std_next_addr(property p)43 static property std_next_addr(property p)
44 {
45   return p + (long_word) STD_PROPERTY_LENGTH(p)  + 1;
46 }
47 
plus_next_addr(property p)48 static property plus_next_addr(property p)
49 {
50   byte mode = rd_byte_addr(p++);
51   return (mode & NEXT_BYTE_IS_LENGTH) ? p + PLUS_PROPERTY_LENGTH(p) + 1 :
52          (mode & PLUS_WORD_MASK)      ? p + 2 : p + 1;
53 }
54 
next_addr(property p)55 static property next_addr(property p)
56 {
57   return hd_plus() ? plus_next_addr(p) : std_next_addr(p);
58 }
59 
find_prop(word obj,word prop)60 static property find_prop(word obj, word prop)
61 {
62   property p = prop_addr(obj);
63   if(hd_plus())
64     while(PLUS_PROPERTY_NUMBER(p) > prop)
65       p = plus_next_addr(p);
66   else
67     while(STD_PROPERTY_NUMBER(p) > prop)
68       p = std_next_addr(p);
69   return p;
70 }
71 
prop_getprop(word obj_num,word prop_num)72 void prop_getprop(word obj_num, word prop_num)
73 {
74   word prop;
75   property p = find_prop(obj_num, prop_num);
76   word p_num = PROPERTY_NUMBER(p);
77   if(p_num < prop_num)
78     prop = rd_word_addr(hd_object() + (((long_word) prop_num - 1) << 1));
79   else if(rd_byte_addr(p++) & WORD_MASK)
80     prop = rd_word_addr(p);
81   else
82     prop = rd_byte_addr(p);
83   store(prop);
84 }
85 
prop_put_prop(word obj_num,word prop_num,word value)86 void prop_put_prop(word obj_num, word prop_num, word value)
87 {
88   property p = find_prop(obj_num, prop_num);
89   word p_num = PROPERTY_NUMBER(p);
90   if(p_num < prop_num)
91     display((byte *) "Bad property number");
92   else if(rd_byte_addr(p++) & WORD_MASK)
93     wr_word_addr(p, value);
94   else
95     wr_byte_addr(p, value);
96 }
97 
prop_get_next_prop(word obj_num,word prop_num)98 void prop_get_next_prop(word obj_num, word prop_num)
99 {
100   property p;
101   if(prop_num != 0)
102   {
103     p = find_prop(obj_num, prop_num);
104     if(PROPERTY_NUMBER(p) < prop_num)
105       display((byte *) "Bad property number");
106     else
107       p = next_addr(p);
108   }
109   else
110   {
111     p = prop_addr(obj_num);
112   }
113   store(PROPERTY_NUMBER(p));
114 }
115 
prop_get_prop_addr(word obj_num,word prop_num)116 void prop_get_prop_addr(word obj_num, word prop_num)
117 {
118   property p = find_prop(obj_num, prop_num);
119   word p_num = PROPERTY_NUMBER(p);
120   if(p_num < prop_num)
121     store(0);
122   else if(hd_plus() && (rd_byte_addr(p) & NEXT_BYTE_IS_LENGTH))
123     store((word) (p + 2));
124   else
125     store((word) (p + 1));
126 }
127 
prop_get_p_len(word prop)128 void prop_get_p_len(word prop)
129 {
130   property p = (long_word) prop - 1;
131 #if 1 /* BODGE FOR CURSES */
132   if(prop == 0)
133     store(0); else
134 #endif
135   if(!hd_plus())
136     store(STD_PROPERTY_LENGTH((long_word) prop - 1));
137   else if(rd_byte_addr(p) & NEXT_BYTE_IS_LENGTH)
138     store(PLUS_PROPERTY_LENGTH(p));
139   else if(rd_byte_addr(p) & PLUS_WORD_MASK)
140     store(2);
141   else
142     store(1);
143 }
144 
load_word_array(word base,word offset)145 void load_word_array(word base, word offset)
146 {
147   store(rd_word_addr(base + 2 * (long_word) offset));
148 }
149 
load_byte_array(word base,word offset)150 void load_byte_array(word base, word offset)
151 {
152   store(rd_byte_addr(base + (long_word) offset));
153 }
154 
save_word_array(word base,word offset,word value)155 void save_word_array(word base, word offset, word value)
156 {
157   wr_word_addr(base + 2 * (long_word) offset, value);
158 }
159 
save_byte_array(word base,word offset,word value)160 void save_byte_array(word base, word offset, word value)
161 {
162   wr_byte_addr(base + (long_word) offset, value);
163 }
164