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