# HG changeset patch # User Paul Boddie # Date 1466364088 -7200 # Node ID 3594df6469c1ac8588478ef9c4703e5c1629046f # Parent 195f22f028483889edfffa0ecbfa75614af61f54 Changed the processing of pixel data and added remarks about pixel layout. diff -r 195f22f02848 -r 3594df6469c1 ULA.txt --- a/ULA.txt Sun Jun 19 17:09:31 2016 +0200 +++ b/ULA.txt Sun Jun 19 21:21:28 2016 +0200 @@ -469,6 +469,37 @@ hardware implementation, and by the time the Electron was planned, it was too late to do anything about this somewhat unfortunate choice. +Pixel Layouts +------------- + +The pixel layouts are as follows: + + Modes Depth (bpp) Pixels (from bits) + ----- ----------- ------------------ + 0, 3, 4, 6 1 7 6 5 4 3 2 1 0 + 1, 5 2 73 62 51 40 + 2 4 7531 6420 + +Since the ULA reads a half-byte at a time, one might expect it to attempt to +produce pixels for every half-byte, as opposed to handling entire bytes. +However, the pixel layout is not conducive to producing pixels as soon as a +half-byte has been read for a given full-byte location: in 1bpp modes the +first four pixels can indeed be produced, but in 2bpp and 4bpp modes the pixel +data is spread across the entire byte in different ways. + +An alternative arrangement might be as follows: + + Modes Depth (bpp) Pixels (from bits) + ----- ----------- ------------------ + 0, 3, 4, 6 1 7 6 5 4 3 2 1 0 + 1, 5 2 76 54 32 10 + 2 4 7654 3210 + +Just as the mode layouts were presumably decided by compatibility with the BBC +Micro, the pixel layouts will have been maintained for similar reasons. +Unfortunately, this layout prevents any optimisation of the ULA for handling +half-byte pixel data generally. + Enhancement: The Missing MODE 4 ------------------------------- diff -r 195f22f02848 -r 3594df6469c1 ula.py --- a/ula.py Sun Jun 19 17:09:31 2016 +0200 +++ b/ula.py Sun Jun 19 21:21:28 2016 +0200 @@ -526,12 +526,17 @@ mode. """ - byte_value = self.data # which should have been read automatically + # Rearrange the byte value. + + byte_value = decode(self.data, self.depth) i = 0 - for colour in decode(byte_value, self.depth): - self.buffer[i] = get_physical_colour(self.palette[colour]) - i += 1 + o = 0 + while i < 8: + colour = value_of_bits(byte_value[i:i+self.depth]) + self.buffer[o] = get_physical_colour(self.palette[colour]) + i += self.depth + o += 1 def wrap_address(self): if self.address >= SCREEN_LIMIT: @@ -551,6 +556,16 @@ if self.cpu_read: self.cpu_data = self.data | self.ram.data +def value_of_bits(bits): + + "Convert the sequence of 'bits' into a value." + + value = 0 + for bit in bits: + value *= 2 + value += bit and 1 or 0 + return value + def get_physical_colour(value): """ @@ -570,11 +585,11 @@ return (value >> 7, value >> 6 & 1, value >> 5 & 1, value >> 4 & 1, value >> 3 & 1, value >> 2 & 1, value >> 1 & 1, value & 1) elif depth == 2: - return (value >> 6 & 2 | value >> 3 & 1, value >> 5 & 2 | value >> 2 & 1, - value >> 4 & 2 | value >> 1 & 1, value >> 3 & 2 | value & 1) + return (value >> 7, value >> 3 & 1, value >> 6 & 1, value >> 2 & 1, + value >> 5 & 1, value >> 1 & 1, value >> 4 & 1, value & 1) elif depth == 4: - return (value >> 4 & 8 | value >> 3 & 4 | value >> 2 & 2 | value >> 1 & 1, - value >> 3 & 8 | value >> 2 & 4 | value >> 1 & 2 | value & 1) + return (value >> 7, value >> 5 & 1, value >> 3 & 1, value >> 1 & 1, + value >> 6 & 1, value >> 4 & 1, value >> 2 & 1, value & 1) else: raise ValueError, "Only depths of 1, 2 and 4 are supported, not %d." % depth