Skip to content

Commit 47a373f

Browse files
committed
Fix deselection mask read.
When reading the last bits of a block you need to be careful to make sure that if the bit_shift is going to increase the last byte is the low bits not the high bits.
1 parent 741b4f0 commit 47a373f

File tree

1 file changed

+32
-14
lines changed

1 file changed

+32
-14
lines changed

sc2reader/readers.py

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -383,24 +383,42 @@ def camera_event(self, data, fstamp, pid, event_type):
383383

384384
class GameEventsReader_16561(GameEventsReader_16117):
385385
# Don't want to do this more than once
386-
SINGLE_BIT_MASKS = [0x1 << i for i in range(500)]
386+
SINGLE_BIT_MASKS = [0x1 << i for i in range(2**9)]
387387

388388
def _parse_selection_update(self, data):
389389
update_type = data.read_bits(2)
390390
if update_type == 1:
391-
mask_length = data.read_bits(self.UNIT_INDEX_BITS)
392-
393-
# Mask is written in byte chunks
394-
mask = data.read_bytes(mask_length/8)
395-
if mask_length%8:
396-
mask += chr(data.read_bits(mask_length%8))
397-
398-
# And must be reversed to put the bits in order
399-
bit_mask = sum([ord(c)<<(i*8) for i,c in enumerate(mask)])
400-
401-
# Represent the mask as a simple bit array with
402-
# True => Deselect, False => Keep
403-
mask = [bit_mask & bit for bit in self.SINGLE_BIT_MASKS[:mask_length]]
391+
bits_left = mask_length = data.read_bits(self.UNIT_INDEX_BITS)
392+
393+
mask = list()
394+
bits = data.read_bits(mask_length)
395+
396+
# If the mask_length is not a multiple of 8 the bit_shift on
397+
# the data buffer will change and cause the last byte to be
398+
# an odd length. This correctly sizes the last byte.
399+
shift_diff = (mask_length+data.bit_shift)%8 - data.bit_shift
400+
if shift_diff > 0:
401+
mask = [bits & data.lo_masks[shift_diff]]
402+
bits = bits >> shift_diff
403+
bits_left -= shift_diff
404+
elif shift_diff < 0:
405+
mask = [bits & data.lo_masks[8+shift_diff]]
406+
bits = bits >> (8+shift_diff)
407+
bits_left -= 8+shift_diff
408+
409+
# Now shift the rest of the bits off into the mask in byte-sized
410+
# chunks in reverse order. No idea why it'd be stored like this.
411+
while bits_left!=0:
412+
mask.insert(0,bits & 0xFF)
413+
bits = bits >> 8
414+
bits_left -= 8
415+
416+
# Compile the finished mask into a large integer for bit checks
417+
bit_mask = sum([c<<(i*8) for i,c in enumerate(mask)])
418+
419+
# Change mask representation from an int to a bit array with
420+
# True => Deselect, False => Keep
421+
mask = [(bit_mask & bit != 0) for bit in self.SINGLE_BIT_MASKS[:mask_length]]
404422

405423
elif update_type == 2:
406424
index_count = data.read_bits(self.UNIT_INDEX_BITS)

0 commit comments

Comments
 (0)