# HG changeset patch # User Paul Boddie # Date 1466430058 -7200 # Node ID ac3b43bc9447991661434699ebbf0f9f3e8e7d27 # Parent e149e4f2d2f8303e193788855463901bddbb5bf4 Fixed the timing of pixel data decoding. Made the pixel data a plain integer. Employed methods for updating the video output and rotating the pixel data. diff -r e149e4f2d2f8 -r ac3b43bc9447 ula.py --- a/ula.py Mon Jun 20 00:15:20 2016 +0200 +++ b/ula.py Mon Jun 20 15:40:58 2016 +0200 @@ -374,8 +374,8 @@ # Initialise the pixel buffer if appropriate. - if not self.writing_pixels and self.have_pixels: - self.buffer_index = 0 + if self.have_pixels: + self.pdata = decode(self.data, self.depth) self.writing_pixels = 1 # Latch row address, set column address (for ULA access only). @@ -443,10 +443,6 @@ if access_ram: self.data = self.data | self.ram.data self.have_pixels = 1 - - # Rearrange the byte value. - - self.pdata = decode(self.data, self.depth) else: self.cpu_transfer_low() @@ -508,27 +504,31 @@ # For pixels within the frame, obtain and output the value. else: - self.video.colour = self.get_pixel() + self.output_colour_value() # Scale pixels horizontally, only accessing the next pixel value # after the required number of scan positions. if self.x % self.xscale == 0: - self.buffer_index += self.depth + self.next_pixel_value() # Finish writing pixels. if self.x % PIXEL_POSITIONS == 0: self.writing_pixels = 0 - def get_pixel(self): + def output_colour_value(self): """ - Return the current pixel by translating memory content for the current - mode. + Output the colour value for the current pixel by translating memory + content for the current mode. """ - return self.palette[value_of_bits(self.pdata[self.buffer_index:self.buffer_index+self.depth])] + value = value_of_bits(self.pdata, self.depth) + self.video.colour = self.palette[value] + + def next_pixel_value(self): + self.pdata = rotate(self.pdata, self.depth) def wrap_address(self): if self.address >= SCREEN_LIMIT: @@ -548,15 +548,24 @@ if self.cpu_read: self.cpu_data = self.data | self.ram.data -def value_of_bits(bits): +def rotate(value, depth): - "Convert the sequence of 'bits' into a value." + "Return 'value' rotated by the number of bits given by 'depth'." - value = 0 - for bit in bits: - value *= 2 - value += bit and 1 or 0 - return value + field = 8 - depth + top = value >> field + mask = 2 ** (8 - depth) - 1 + rest = value & mask + return (rest << depth) | top + +def value_of_bits(value, depth): + + """ + Convert the upper bits of 'value' to a result, using 'depth' to indicate the + number of bits involved. + """ + + return value >> (8 - depth) def get_physical_colour(value): @@ -574,14 +583,13 @@ """ if depth == 1: - return (value >> 7, value >> 6 & 1, value >> 5 & 1, value >> 4 & 1, - value >> 3 & 1, value >> 2 & 1, value >> 1 & 1, value & 1) + return value elif depth == 2: - return (value >> 7, value >> 3 & 1, value >> 6 & 1, value >> 2 & 1, - value >> 5 & 1, value >> 1 & 1, value >> 4 & 1, value & 1) + return ((value & 128) | ((value & 8) << 3) | ((value & 64) >> 1) | ((value & 4) << 2) | + ((value & 32) >> 2) | ((value & 2) << 1) | ((value & 16) >> 3) | (value & 1)) elif depth == 4: - return (value >> 7, value >> 5 & 1, value >> 3 & 1, value >> 1 & 1, - value >> 6 & 1, value >> 4 & 1, value >> 2 & 1, value & 1) + return ((value & 128) | ((value & 32) << 1) | ((value & 8) << 2) | ((value & 2) << 3) | + ((value & 64) >> 3) | ((value & 16) >> 2) | ((value & 4) >> 1) | (value & 1)) else: raise ValueError, "Only depths of 1, 2 and 4 are supported, not %d." % depth