gruesome 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +1 -2
- data/lib/gruesome/cli.rb +62 -62
- data/lib/gruesome/logo.rb +8 -8
- data/lib/gruesome/machine.rb +11 -11
- data/lib/gruesome/version.rb +1 -1
- data/lib/gruesome/z/abbreviation_table.rb +17 -17
- data/lib/gruesome/z/decoder.rb +273 -273
- data/lib/gruesome/z/dictionary.rb +144 -144
- data/lib/gruesome/z/header.rb +40 -40
- data/lib/gruesome/z/instruction.rb +42 -42
- data/lib/gruesome/z/machine.rb +51 -50
- data/lib/gruesome/z/memory.rb +301 -232
- data/lib/gruesome/z/object_table.rb +424 -424
- data/lib/gruesome/z/opcode.rb +489 -491
- data/lib/gruesome/z/opcode_class.rb +9 -9
- data/lib/gruesome/z/operand_type.rb +10 -10
- data/lib/gruesome/z/processor.rb +378 -361
- data/lib/gruesome/z/zscii.rb +307 -307
- data/lib/gruesome.rb +3 -3
- data/spec/z/memory_spec.rb +72 -72
- data/spec/z/processor_spec.rb +1883 -1883
- metadata +3 -3
@@ -3,428 +3,428 @@ require_relative 'memory'
|
|
3
3
|
require_relative 'abbreviation_table'
|
4
4
|
|
5
5
|
module Gruesome
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
6
|
+
module Z
|
7
|
+
class ObjectTable
|
8
|
+
def initialize(memory)
|
9
|
+
@memory = memory
|
10
|
+
@header = Header.new(@memory.contents)
|
11
|
+
@abbreviation_table = AbbreviationTable.new(@memory)
|
12
|
+
|
13
|
+
@address = @header.object_tbl_addr
|
14
|
+
|
15
|
+
if @header.version <= 3
|
16
|
+
# versions 1-3 have 32 entries
|
17
|
+
@num_properties = 31
|
18
|
+
else
|
19
|
+
# versions 4+ have 32 entries
|
20
|
+
@num_properties = 63
|
21
|
+
end
|
22
|
+
|
23
|
+
@object_tree_address = @address + @num_properties*2
|
24
|
+
|
25
|
+
if @header.version <= 3
|
26
|
+
@attributes_size = 4
|
27
|
+
@object_id_size = 1
|
28
|
+
|
29
|
+
# Entry:
|
30
|
+
#
|
31
|
+
# Attributes (4 bytes)
|
32
|
+
# Parent Object ID (1 byte)
|
33
|
+
# Sibling Object ID (1 byte)
|
34
|
+
# Child Object ID (1 byte)
|
35
|
+
# Properties Address (2 bytes)
|
36
|
+
else
|
37
|
+
@attributes_size = 6
|
38
|
+
@object_id_size = 2
|
39
|
+
|
40
|
+
# Entry: (Object IDs are 2 bytes)
|
41
|
+
#
|
42
|
+
# Attributes (6 bytes)
|
43
|
+
# Parent Object ID (2 byte)
|
44
|
+
# Sibling Object ID (2 byte)
|
45
|
+
# Child Object ID (2 byte)
|
46
|
+
# Properties Address (2 bytes)
|
47
|
+
end
|
48
|
+
|
49
|
+
@obj_entry_size = @attributes_size + (@object_id_size * 3) + 2
|
50
|
+
|
51
|
+
# Check machine endianess
|
52
|
+
@endian = [1].pack('S')[0] == 1 ? 'little' : 'big'
|
53
|
+
end
|
54
|
+
|
55
|
+
def property_default(index)
|
56
|
+
index -= 1
|
57
|
+
index %= @num_properties
|
58
|
+
|
59
|
+
# The first thing in the table is the property defaults list
|
60
|
+
# So, simply lookup the 16-bit word at the entry given by index
|
61
|
+
prop_default_addr = @address + index*2
|
62
|
+
@memory.force_readw(prop_default_addr)
|
63
|
+
end
|
64
|
+
|
65
|
+
def object_entry(index)
|
66
|
+
index -= 1
|
67
|
+
obj_entry_addr = @object_tree_address + (index * @obj_entry_size)
|
68
|
+
|
69
|
+
attributes_address = obj_entry_addr
|
70
|
+
cur_addr = attributes_address
|
71
|
+
|
72
|
+
# read the attributes
|
73
|
+
attribute_bytes = []
|
74
|
+
@attributes_size.times do
|
75
|
+
attribute_bytes << @memory.force_readb(cur_addr)
|
76
|
+
cur_addr += 1
|
77
|
+
end
|
78
|
+
|
79
|
+
# read the object ids of associated objects
|
80
|
+
ids = (0..2).map do |i|
|
81
|
+
if @object_id_size == 2
|
82
|
+
id = @memory.force_readw(cur_addr)
|
83
|
+
cur_addr += 2
|
84
|
+
else
|
85
|
+
id = @memory.force_readb(cur_addr)
|
86
|
+
cur_addr += 1
|
87
|
+
end
|
88
|
+
id
|
89
|
+
end
|
90
|
+
|
91
|
+
properties_address = @memory.force_readw(cur_addr)
|
92
|
+
|
93
|
+
# return a hash with the information of the entry
|
94
|
+
{ :attributes_address => attributes_address,
|
95
|
+
:attributes => attribute_bytes,
|
96
|
+
:parent_id => ids[0],
|
97
|
+
:sibling_id => ids[1],
|
98
|
+
:child_id => ids[2],
|
99
|
+
:properties_address => properties_address }
|
100
|
+
end
|
101
|
+
|
102
|
+
def object_get_child(index)
|
103
|
+
object_entry(index)[:child_id]
|
104
|
+
end
|
105
|
+
|
106
|
+
def object_get_sibling(index)
|
107
|
+
object_entry(index)[:sibling_id]
|
108
|
+
end
|
109
|
+
|
110
|
+
def object_get_parent(index)
|
111
|
+
object_entry(index)[:parent_id]
|
112
|
+
end
|
113
|
+
|
114
|
+
def object_set_child(index, child_id)
|
115
|
+
entry = object_entry(index)
|
116
|
+
addr = entry[:attributes_address] + @attributes_size + @object_id_size*2
|
117
|
+
|
118
|
+
if @object_id_size == 1
|
119
|
+
@memory.force_writeb(addr, child_id)
|
120
|
+
else
|
121
|
+
@memory.force_writew(addr, child_id)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def object_set_sibling(index, sibling_id)
|
126
|
+
entry = object_entry(index)
|
127
|
+
addr = entry[:attributes_address] + @attributes_size + @object_id_size
|
128
|
+
|
129
|
+
if @object_id_size == 1
|
130
|
+
@memory.force_writeb(addr, sibling_id)
|
131
|
+
else
|
132
|
+
@memory.force_writew(addr, sibling_id)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def object_set_parent(index, parent_id)
|
137
|
+
entry = object_entry(index)
|
138
|
+
addr = entry[:attributes_address] + @attributes_size
|
139
|
+
|
140
|
+
if @object_id_size == 1
|
141
|
+
@memory.force_writeb(addr, parent_id)
|
142
|
+
else
|
143
|
+
@memory.force_writew(addr, parent_id)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def object_insert_object(index, new_child)
|
148
|
+
# remove child from old parent
|
149
|
+
if object_get_parent(new_child) != 0
|
150
|
+
object_remove_object new_child
|
151
|
+
end
|
152
|
+
|
153
|
+
# add to new parent
|
154
|
+
object_set_sibling(new_child, object_get_child(index))
|
155
|
+
object_set_child(index, new_child)
|
156
|
+
object_set_parent(new_child, index)
|
157
|
+
end
|
158
|
+
|
159
|
+
def object_remove_object(index)
|
160
|
+
old_parent = object_get_parent(index)
|
161
|
+
object_set_parent(index, 0)
|
162
|
+
|
163
|
+
if old_parent != 0
|
164
|
+
current_child = object_get_child(old_parent)
|
165
|
+
if current_child == index
|
166
|
+
# if we are the primary child of our parent, we removed
|
167
|
+
# ourselves... so we have to set a new primary child
|
168
|
+
# to be my sibling
|
169
|
+
object_set_child(old_parent, object_get_sibling(index))
|
170
|
+
else
|
171
|
+
# if not, we are within some list of siblings
|
172
|
+
# we need to remove ourself from this linked list
|
173
|
+
# whose head is current_child
|
174
|
+
|
175
|
+
last = current_child
|
176
|
+
sibling = object_get_sibling(current_child)
|
177
|
+
while sibling != 0
|
178
|
+
if sibling == index
|
179
|
+
# found me!
|
180
|
+
# now, set the sibling of the previous one
|
181
|
+
# to my sibling (removing me from the chain)
|
182
|
+
object_set_sibling(last, object_get_sibling(index))
|
183
|
+
|
184
|
+
# break out of the loop
|
185
|
+
break
|
186
|
+
end
|
187
|
+
last = sibling
|
188
|
+
sibling = object_get_sibling(sibling)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def object_short_text(index)
|
195
|
+
entry = object_entry(index)
|
196
|
+
prop_address = entry[:properties_address]
|
197
|
+
|
198
|
+
# text_len is the maximum number of bytes the string can have
|
199
|
+
text_len = @memory.force_readb(prop_address) * 2
|
200
|
+
chrs = @memory.force_readzstr(prop_address+1, text_len)[1]
|
201
|
+
|
202
|
+
ZSCII.translate(0, @header.version, chrs, @abbreviation_table)
|
203
|
+
end
|
204
|
+
|
205
|
+
def attribute_number_to_byte_bit_pair(attribute_number)
|
206
|
+
# get the byte and bit number
|
207
|
+
#
|
208
|
+
# Note: it counts from the MSB, so it has to
|
209
|
+
# reverse the bit_number by subtracting from 7
|
210
|
+
#
|
211
|
+
# That is, attribute 7 is byte 0, bit 0
|
212
|
+
# attribute 17 is byte 2, bit 6
|
213
|
+
# etc
|
214
|
+
|
215
|
+
byte_number = (attribute_number / 8).to_i
|
216
|
+
bit_number = attribute_number % 8
|
217
|
+
bit_number = 7 - bit_number
|
218
|
+
|
219
|
+
{ :byte => byte_number, :bit => bit_number }
|
220
|
+
end
|
221
|
+
private :attribute_number_to_byte_bit_pair
|
222
|
+
|
223
|
+
def object_has_attribute?(index, attribute_number)
|
224
|
+
entry = object_entry(index)
|
225
|
+
|
226
|
+
location = attribute_number_to_byte_bit_pair(attribute_number)
|
227
|
+
attribute_byte = entry[:attributes][location[:byte]]
|
228
|
+
mask = 1 << location[:bit]
|
229
|
+
|
230
|
+
(attribute_byte & mask) > 0
|
231
|
+
end
|
232
|
+
|
233
|
+
def object_set_attribute(index, attribute_number)
|
234
|
+
entry = object_entry(index)
|
235
|
+
|
236
|
+
location = attribute_number_to_byte_bit_pair(attribute_number)
|
237
|
+
attribute_byte = entry[:attributes][location[:byte]]
|
238
|
+
mask = 1 << location[:bit]
|
239
|
+
|
240
|
+
attribute_byte |= mask
|
241
|
+
|
242
|
+
byte_addr = entry[:attributes_address] + location[:byte]
|
243
|
+
@memory.force_writeb(byte_addr, attribute_byte)
|
244
|
+
end
|
245
|
+
|
246
|
+
def object_clear_attribute(index, attribute_number)
|
247
|
+
entry = object_entry(index)
|
248
|
+
|
249
|
+
location = attribute_number_to_byte_bit_pair(attribute_number)
|
250
|
+
attribute_byte = entry[:attributes][location[:byte]]
|
251
|
+
mask = 1 << location[:bit]
|
252
|
+
|
253
|
+
attribute_byte &= ~mask
|
254
|
+
|
255
|
+
byte_addr = entry[:attributes_address] + location[:byte]
|
256
|
+
@memory.force_writeb(byte_addr, attribute_byte)
|
257
|
+
end
|
258
|
+
|
259
|
+
def object_get_size_and_number(prop_address)
|
260
|
+
size = 0
|
261
|
+
property_number = 0
|
262
|
+
if @header.version <= 3
|
263
|
+
size = @memory.force_readb(prop_address)
|
264
|
+
prop_address += 1
|
265
|
+
|
266
|
+
# when size is 0, this is the end of the list
|
267
|
+
if size == 0
|
268
|
+
return nil
|
269
|
+
end
|
270
|
+
|
271
|
+
# size is considered 32 times the data size minus one
|
272
|
+
# property number is the first 5 bits
|
273
|
+
property_number = size & 0b11111
|
274
|
+
|
275
|
+
size = size >> 5
|
276
|
+
size += 1
|
277
|
+
else
|
278
|
+
# in versions 4+, the size and property number are given
|
279
|
+
# as two bytes.
|
280
|
+
#
|
281
|
+
# if bit 7 is set in the first byte:
|
282
|
+
# The second byte is read where first 6 bits
|
283
|
+
# indicate size, bit 6 is ignored, bit 7 is set
|
284
|
+
# if bit 7 is clear in the first byte:
|
285
|
+
# bit 6 is clear = size of 1
|
286
|
+
# bit 6 is set = size of 2
|
287
|
+
#
|
288
|
+
# property number is first 6 bits of first byte
|
289
|
+
|
290
|
+
first_byte = @memory.force_readb(prop_address)
|
291
|
+
prop_address += 1
|
292
|
+
|
293
|
+
property_number = first_byte & 0b111111
|
294
|
+
if first_byte & 0b10000000 > 0
|
295
|
+
# bit 7 is set
|
296
|
+
second_byte = @memory.force_readb(prop_address)
|
297
|
+
prop_address += 1
|
298
|
+
|
299
|
+
size = second_byte & 0b111111
|
300
|
+
|
301
|
+
# a size of 0 is allowed, and will indicate a size of 64
|
302
|
+
if size == 0
|
303
|
+
size = 64
|
304
|
+
end
|
305
|
+
else
|
306
|
+
# bit 7 is clear
|
307
|
+
if first_byte & 0b1000000 > 0
|
308
|
+
# bit 6 is set
|
309
|
+
size = 2
|
310
|
+
else
|
311
|
+
# bit 6 is clear
|
312
|
+
size = 1
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
{ :size => size, :property_number => property_number, :property_data_address => prop_address }
|
318
|
+
end
|
319
|
+
|
320
|
+
def object_properties(index)
|
321
|
+
entry = object_entry(index)
|
322
|
+
prop_address = entry[:properties_address]
|
323
|
+
|
324
|
+
# get the length of the string in bytes
|
325
|
+
text_len = @memory.force_readb(prop_address) * 2
|
326
|
+
prop_address += 1
|
327
|
+
|
328
|
+
prop_address += text_len
|
329
|
+
|
330
|
+
properties = {}
|
331
|
+
|
332
|
+
while true do
|
333
|
+
entry_info = object_get_size_and_number(prop_address)
|
334
|
+
|
335
|
+
if entry_info == nil
|
336
|
+
break
|
337
|
+
end
|
338
|
+
|
339
|
+
# regardless of version, we now have the property size and the number
|
340
|
+
|
341
|
+
properties[entry_info[:property_number]] = {:size => entry_info[:size], :property_data_address => entry_info[:property_data_address]}
|
342
|
+
prop_address = entry_info[:property_data_address] + entry_info[:size]
|
343
|
+
end
|
344
|
+
|
345
|
+
properties
|
346
|
+
end
|
347
|
+
|
348
|
+
def object_get_property(index, property_number)
|
349
|
+
properties = object_properties(index)
|
350
|
+
|
351
|
+
property_data = []
|
352
|
+
|
353
|
+
property_info = properties[property_number]
|
354
|
+
|
355
|
+
if property_info == nil
|
356
|
+
property_data = nil
|
357
|
+
else
|
358
|
+
address = property_info[:property_data_address]
|
359
|
+
properties[property_number][:size].times do
|
360
|
+
property_data << @memory.force_readb(address)
|
361
|
+
address += 1
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
property_data
|
366
|
+
end
|
367
|
+
|
368
|
+
def object_get_property_addr(index, property_number)
|
369
|
+
properties = object_properties(index)
|
370
|
+
|
371
|
+
property_info = properties[property_number]
|
372
|
+
|
373
|
+
if property_info == nil
|
374
|
+
0
|
375
|
+
else
|
376
|
+
property_info[:property_data_address]
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
def object_get_property_data_size_from_address(address)
|
381
|
+
if @header.version <= 3
|
382
|
+
prop_address = address - 1
|
383
|
+
else
|
384
|
+
first_byte = @memory.force_readb(address-1)
|
385
|
+
|
386
|
+
if first_byte & 0b10000000 > 0
|
387
|
+
prop_address = address - 2
|
388
|
+
else
|
389
|
+
prop_address = address - 1
|
390
|
+
end
|
391
|
+
end
|
392
|
+
object_get_size_and_number(prop_address)[:size]
|
393
|
+
end
|
394
|
+
|
395
|
+
def object_get_property_word(index, property_number)
|
396
|
+
property_data = object_get_property(index, property_number)
|
397
|
+
if property_data == nil
|
398
|
+
property_default(property_number)
|
399
|
+
elsif property_data.size > 1
|
400
|
+
if @endian == 'little'
|
401
|
+
(property_data[1] << 8) | property_data[0]
|
402
|
+
else
|
403
|
+
(property_data[0] << 8) | property_data[1]
|
404
|
+
end
|
405
|
+
else
|
406
|
+
property_data[0]
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
def object_set_property_word(index, property_number, value)
|
411
|
+
properties = object_properties(index)
|
412
|
+
|
413
|
+
property_info = properties[property_number]
|
414
|
+
|
415
|
+
if property_info == nil
|
416
|
+
raise "put_prop attempted to set a property value for a property that did not exist"
|
417
|
+
else
|
418
|
+
if property_info[:size] == 1
|
419
|
+
value &= 0xff
|
420
|
+
@memory.force_writeb(property_info[:property_data_address], value)
|
421
|
+
elsif property_info[:size] == 2
|
422
|
+
@memory.force_writew(property_info[:property_data_address], value)
|
423
|
+
else
|
424
|
+
raise "put_prop attempted to set a property whose data size is larger than a word"
|
425
|
+
end
|
426
|
+
end
|
427
|
+
end
|
428
|
+
end
|
429
|
+
end
|
430
430
|
end
|