{"id":59,"date":"2022-07-04T13:31:12","date_gmt":"2022-07-04T13:31:12","guid":{"rendered":"https:\/\/blogs.scummvm.org\/quote58\/?p=59"},"modified":"2022-07-04T13:31:12","modified_gmt":"2022-07-04T13:31:12","slug":"one-bit-two-bit-red-bit-blue-bit","status":"publish","type":"post","link":"https:\/\/blogs.scummvm.org\/quote58\/2022\/07\/04\/one-bit-two-bit-red-bit-blue-bit\/","title":{"rendered":"One bit, Two bit, Red bit, Blue bit"},"content":{"rendered":"<h2><strong>Welcome back!<\/strong><\/h2>\n<p>Last week I mentioned that the next step would be to work on translating Kernal.gs and Driver.gs. These files contain many important functions for the entire game engine, including the main game loop and the initialization before it. These two files are distinct in the context of the apple IIGS, but for our purposes many functions in Driver are not needed (hardware specific interaction that is handled differently by ScummVM such as user input), and the remaining ones are not distinct enough from Kernal to require their own file. The functions from both of them are core to the engine in general, so they will all be methods of the main engine class anyway.<\/p>\n<p>I have been wanting to discuss my process and methodology for translating the engine structure, but I haven&#8217;t found quite the right way to phrase it just yet, so I will leave that to another time.<br \/>\nFor this post, I would instead like us to move our scope from the engine as a whole, all the way down to the individual bits and bytes for a moment.<\/p>\n<p>I think we have some interesting things to <strong>nyble<\/strong> on for a little <strong>bit<\/strong>. Don&#8217;t worry though! I didn&#8217;t <strong>byte<\/strong> off more than I can chew. Compared to last week, this will be much less <strong>word<\/strong>y. So hopefully you won&#8217;t find yourself scrolling at <strong>double<\/strong> time because it&#8217;s getting too <strong>long<\/strong>.<\/p>\n<p>Alright I think got all the puns out of my system, lets get into it.<\/p>\n<hr \/>\n<h3><strong>What&#8217;s in a palette?<br \/>\n<\/strong><\/h3>\n<p>The example we will use for this, will be all about processing the palette. The Immortal uses the Apple IIGS High-res mode at 320&#215;200, which allows for 4bpp (bits per pixel) colour depth. What this means, is that every pixel on the screen gets a total of 4 bits to express the colour it will display. With 4 bits only having up to 0xF (15), it can pick from a palette of 16 total colours. The Apple IIGS was capable of displaying 4096 unique colours, (0xFFF) in hex. This means that each of the unique colours can be described with 12 bits, 0x000-0xFFF. However the smallest container of memory available to work with is a byte, which is 8 bits. So to store a single colour, you need 2 bytes. This means that a palette gets stored in memory as a sequence of 16 words, and each pixel is a 4 bit reference to the index of one entry.<img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-67\" src=\"https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-1.45.31-AM.png\" alt=\"\" width=\"2588\" height=\"1484\" srcset=\"https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-1.45.31-AM.png 2588w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-1.45.31-AM-300x172.png 300w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-1.45.31-AM-1024x587.png 1024w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-1.45.31-AM-768x440.png 768w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-1.45.31-AM-1536x881.png 1536w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-1.45.31-AM-2048x1174.png 2048w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-1.45.31-AM-1568x899.png 1568w\" sizes=\"auto, (max-width: 2588px) 100vw, 2588px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>We will come back to this in a second. First, how does ScummVM handle palette data compared to the Apple IIGS? We&#8217;ll talk more about what an image actually is in a later post, but the important part for this post is that ScummVM has the ability to simulate the colour memory of computers from this time. This is represented as an array of up to 256 entries, where every entry is 3 bytes representing the Red, Green, and Blue intensity (brightness) of a given palette entry, with the final byte of the palette being used for transparency. This allows for 16 palettes of 16 colours each. For the Apple IIGS however, we only need a single palette. ScummVM is able to apply this palette to a &#8216;surface&#8217;, which presents the game screen. This means that to take the palette from the game, and apply it to the ScummVM surface, we need to extract those 4 bit colour values and turn them into RGB bytes for the surface.<\/p>\n<p>This is a good example of simple bit manipulation because it only requires that we separate the parts of the word, and make it fit the size of the RGB data. So let&#8217;s take a quick look at that:<\/p>\n<p><em>void ImmortalEngine::setColors(uint16 pal[]) {<\/em><br \/>\n<em>\u00a0 \u00a0 \/\/ The RGB palette is 3 bytes per entry, and each byte is a colour<\/em><br \/>\n<em>\u00a0 \u00a0 for (int i = 0; i &lt; 16; i++) {<\/em><\/p>\n<p><em>\u00a0 \u00a0 \u00a0 \u00a0 \/\/ Check for negative<\/em><br \/>\n<em>\u00a0 \u00a0 \u00a0 \u00a0 if (pal[i] &lt; kMaskNeg) {<\/em><\/p>\n<p><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 _palRGB[(i * 3)] = ((pal[i] &amp; kMaskRed) &gt;&gt; 4);<\/em><br \/>\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 _palRGB[(i * 3) + 1] = ((pal[i] &amp; kMaskGreen));<\/em><br \/>\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 _palRGB[(i * 3) + 2] = (pal[i] &amp; kMaskBlue) &lt;&lt; 4;<\/em><br \/>\n<em>\u00a0 \u00a0 \u00a0 \u00a0 }<\/em><br \/>\n<em>}<\/em><br \/>\n<em>\u00a0 \u00a0 \/\/ Palette index to update first is 0, and there are 16 colours to update<\/em><br \/>\n<em>\u00a0 \u00a0 g_system-&gt;getPaletteManager()-&gt;setPalette(_palRGB, 0, 16);<\/em><br \/>\n<em>\u00a0 \u00a0 g_system-&gt;updateScreen();<\/em><br \/>\n<em>}<\/em><\/p>\n<p>This function takes in a palette\u00a0<em>pal<\/em> which is an array of 16 uint16 (2 unsigned bytes), and loops over it. It does a check for the value being a negative (in the context of 65816, the negative status flag is triggered on values 0x8000-0xFFFF) so that this routine can update specific colours alone by masking the other entries with 0xFFFF values. If we have a palette value that is supposed to be used to update the current surface palette, we break it up into its component colours. To do this, we will need to use the &amp; (AND) operator to mask only the 4 bits that represent each colour, and assign those bits separately to each byte of the RGB palette. So, remembering the position of each colour as a nyble in the word, we could say for example: byte RED = pal[i] &amp; 0x0F00;<br \/>\nHowever, masking the bits doesn&#8217;t change their position, it just isolates them. Because the red bits are in the first nyble of the second byte, the value we get returned is still 2 bytes long, which is bigger than the single byte we want to assign it to. To change the position of bits within a value, we can use another bitwise operator, &gt;&gt; (LSR). This operator will &#8216;shift&#8217; all the bits in a value to the right a specific number of times, discarding the bits whose position is being moved into by the bits next to them. This is more or less equivalent to dividing the number by 2 each time. Now we can just count the number of bits required to move it into position. So for red, to get it to the end of the value so that it can be used as a single byte, we can say: byte RED = (pal[i] &amp; 0x0F00)\u00a0<em>&gt;&gt; 8<\/em><em>;<\/em><br \/>\nOne more thing needs to be kept in mind though, and that is the fact that the RGB bytes used by ScummVM have a much larger range of intensity. They can use 8 bits, so they can be any brightness from 0 to 255, where as the colour value represented by the palette used by The Immortal only has 4 bits, and therefor only ranges from 0 to 15. So we need to multiply the native colour value by 4 extra bits to get the proportionate RGB value. To do this we can say: byte RED = ((pal[i] &amp; 0x0F00) &gt;&gt; 8) <em>&lt;&lt; 4;<\/em><br \/>\nAt this point we can see the statement can be simplified. The position of the red bits is 8 bits away from it&#8217;s native value in the new byte, but it&#8217;s only 4 bits away from the larger value we need to turn it into anyway. So finally we can combine them and instead say: <em>_palRGB[(i * 3)] = ((pal[i] &amp; kMaskRed) &gt;&gt; 4);<\/p>\n<p><\/em>This is all well and good for extracting colour values to simply store them somewhere else. But what about when we need to extract the colour values, do something to them, and then put them back? Well this is something games have to do frequently, and if there is something assembly language is exceedingly good at, it&#8217;s bitwise operations. So let&#8217;s take an example of a function from the game that has to extract, manipulate, and put back colour values in the palette, the colour fade routine.<\/p>\n<p>&nbsp;<\/p>\n<hr \/>\n<h3><strong>Colour Fade<\/strong><\/h3>\n<p>The routine has quite a few operations, so for the sake of clarity, and not directly transcribing the source, I have written just the important operations and filled in where context was removed:<\/p>\n<div><em>*with these assumptions: PAL is a pointer to the first entry of the palette, y is the current index when iterating over it, MULTIPLY is a routine that multiplies two 16bit values (A * X) and returns just the first byte of the 32bit result, and MULTIPLIER is the factor to change the colour by for a given iteration*<\/em><\/div>\n<div><em>ldx MULTIPLIER<\/em><\/div>\n<div><em>lda [PAL],y<\/em><\/div>\n<div><em>and #$f<\/em><\/div>\n<div><em>jsr MULTIPLY<\/em><\/div>\n<div><em>xba<\/em><\/div>\n<div><em>and #$f<\/em><\/div>\n<div><em>sta RESULT<\/em><\/div>\n<div><em>ldx MULTIPLIER<\/em><\/div>\n<div><em>lda [PAL],y<\/em><\/div>\n<div><em>lsr #4<\/em><\/div>\n<div><em>and #$f<\/em><\/div>\n<div><em>jsr MULTIPLY<\/em><\/div>\n<div><em>xba<\/em><\/div>\n<div><em>and #$f<\/em><\/div>\n<div><em>asl #4<\/em><\/div>\n<div><em>ora RESULT<\/em><\/div>\n<div><em>sta RESULT<\/em><\/div>\n<div><em>ldx MULTIPLIER<\/em><\/div>\n<div><em>lda [PAL],y<\/em><\/div>\n<div><em>xba<\/em><\/div>\n<div><em>and #$f<\/em><\/div>\n<div><em>jsr MULTIPLY<\/em><\/div>\n<div><em>xba<\/em><\/div>\n<div><em>and #$f<\/em><\/div>\n<div><em>xba<\/em><\/div>\n<div><em>ora RESULT<\/em><\/div>\n<div><em>sta [NEW_PAL],y<\/em><\/div>\n<p>Alright, let&#8217;s analyze this code snippet:<br \/>\nThe purpose of this loop is to fade each colour within each entry in the palette, and store them to an output palette which used by the hardware. It achieves this the same way regardless of direction. The part I want to highlight is the bit manipulation, so to save some time I&#8217;ll explain the over arching logic for how it does this.<br \/>\nThe colours need to fade to or from black, with the other point being whatever the original colour value was. So if the original colour was 2, and it is fading to black, it only needs to step down by 2. But if another colour is 14, then it needs to step down by a factor 7 times larger than the first colour. And for a fade to look good, it should feel like the image as a whole is getting darker at the same rate. Otherwise the colour with value 2 will be gone instantly but the really bright colours will be there for much longer, making the imagine darken in an uneven way. To put it another way, the brightness should change, but not the contrast between colours. However, if every colour gets darker by 10%\u00a0<em>of their original value<\/em>, then the contrast between colours doesn&#8217;t change. The values will move up or down proportionally, and each colour will get to zero at roughly the same time.<img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-69\" src=\"https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-4.47.41-AM.png\" alt=\"\" width=\"2612\" height=\"998\" srcset=\"https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-4.47.41-AM.png 2612w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-4.47.41-AM-300x115.png 300w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-4.47.41-AM-1024x391.png 1024w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-4.47.41-AM-768x293.png 768w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-4.47.41-AM-1536x587.png 1536w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-4.47.41-AM-2048x783.png 2048w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-4.47.41-AM-1568x599.png 1568w\" sizes=\"auto, (max-width: 2612px) 100vw, 2612px\" \/><br \/>\nBut, we don&#8217;t have hardware based division on the 65816 outside of LSR. So how do we get a percentage? We multiply by the percentage and then simply disregard the bytes beyond the whole number. Okay, let&#8217;s see what it does to these numbers:<\/p>\n<p>We can start by grouping the operations by the overall purpose. We can see <em>lda [PAL],y<\/em> at three different points. These will be start for each group of operations. We need to extra three colours, and we load the original value three times. Let&#8217;s take a look at the first group, and list out the logic:<\/p>\n<div><em>LDX MULTIPLIER -&gt; LDA [PAL],y -&gt; AND #$000F -&gt; JSR MULTIPLY -&gt; XBA -&gt; AND #$000F -&gt; STA RESULT<\/em><\/p>\n<p>Remembering that MULTIPLIER being loaded into X just prepares the MULTIPLY routine with a multiplicand, we can write this as:<br \/>\n<em>From the palette entry, take just the nyble containing the blue value -&gt; multiply the blue value by the percentage out of 0x100 (256) -&gt; flip the byte order of the result and take just the last nyble -&gt; store to the blue portion of the final value.<\/p>\n<p><\/em>The first part is pretty simple, we take the blue and multiply it up. The next bit is where it gets interesting. XBA will flip the byte order (as discussed in a previous post), making XXYY -&gt; YYXX. This can be used in all kinds of ways, but here we get to see it used to perform a clever shortcut for division. After the multiplication, we have B*percent of 0x100. So from 000B we get 0BBB. But we only want 0B00, we only want 4 bits of precision, not 12. We can remove the extra bits by masking, but we still need to get B into a form we can use, that being 4 bits. Normally we would LSR 8 times, but XBA lets us do the sort of thing you don&#8217;t get to do much in a higher level (for good reason), it lets us use a fundamentally different mechanic to get the same result. It can&#8217;t be overstated how much of a difference this kind of thing can be. We can look at the number of cycles per operation and compare (3 + 2 = 5 vs 2 * 8 = 16), but it doesn&#8217;t really illustrate the point, because it&#8217;s not just about being more efficient with the same tool, it&#8217;s more like one way is a pencil, and the other is a pair of scissors.<img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-72\" src=\"https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-6.59.51-AM.png\" alt=\"\" width=\"2132\" height=\"1356\" srcset=\"https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-6.59.51-AM.png 2132w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-6.59.51-AM-300x191.png 300w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-6.59.51-AM-1024x651.png 1024w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-6.59.51-AM-768x488.png 768w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-6.59.51-AM-1536x977.png 1536w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-6.59.51-AM-2048x1303.png 2048w, https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Screen-Shot-2022-07-04-at-6.59.51-AM-1568x997.png 1568w\" sizes=\"auto, (max-width: 2132px) 100vw, 2132px\" \/><\/div>\n<div>So with XBA, all that&#8217;s left is to mask for the first nyble, and we have the blue portion. The next bit is mostly straightforward:<\/p>\n<div><\/div>\n<div><em>LDX MULTIPLIER -&gt;\u00a0<\/em><em>LDA [PAL],y -&gt;\u00a0<\/em><em>LSR #4 -&gt;\u00a0<\/em><em>AND #$000F -&gt;\u00a0<\/em><em>JSR MULTIPLY -&gt;\u00a0<\/em><em>XBA -&gt;\u00a0<\/em><em>AND #$000F -&gt;\u00a0<\/em><em>ASL #4 -&gt;\u00a0<\/em><em>ORA RESULT -&gt; STA<\/em><em>\u00a0RESULT<br \/>\n<\/em><\/div>\n<\/div>\n<div><\/div>\n<div>However we also see a | (OR) operation being used at the end. This could be understood as:<br \/>\n<em>From the palette entry, shift over by one nyble and grab just that -&gt; multiply by percentage -&gt; grab the whole number like before -&gt; shift into position that green needs to be for the final value, and then apply those bits to the in-progress final value.<\/p>\n<p><\/em>And finally, we have one that uses all those things together to get the green portion:<\/div>\n<div><\/div>\n<div><em>LDX MULTIPLIER -&gt; LDA [PAL],y -&gt; XBA -&gt; AND #$000F -&gt; JSR MULTIPLY -&gt; XBA -&gt; AND #$000F -&gt; XBA -&gt; ORA RESULT -&gt; STA [NEW_PAL],y<\/em><\/div>\n<div><\/div>\n<div>This one needs to grab the 3rd nyble right away, so it&#8217;s the expected XBA + AND #$000F. Same thing after the multiplication because it leaves what we need in the same position. And then finally, we can once again use XBA to skip the math, this time in the opposite direction, taking 000R and making it 0R00 in 3 cycles instead of 16.<\/p>\n<p>For the sake of preserving the specific bit logic of the original, I&#8217;ve added a function for now that performs the same operation as XBA. This allows the logic to look very similar in C, and makes sure any inaccuracies from tricks like that get preserved. I will likely remove it later on and simplify logic for this kind of thing once everything is translated accurately initially.<br \/>\n<em>*mult16() is just so I don&#8217;t have (uint16) everywhere, the multiplication itself is the same*<br \/>\n\/\/ Blue = 0RGB -&gt; 000B -&gt; 0BBB -&gt; BB0B -&gt; 000B<\/em><br \/>\n<em>result = (xba(mult16((result &amp; kMaskFirst), count))) &amp; kMaskFirst;<\/em><\/p>\n<p><em>\/\/ Green = 0RGB -&gt; 00RG -&gt; 000G -&gt; 0GGG -&gt; GG0G -&gt; 000G -&gt; 00G0 -&gt; 00GB<\/em><br \/>\n<em>temp = mult16(((pal[i] &gt;&gt; 4) &amp; kMaskFirst), count);<\/em><br \/>\n<em>temp = (xba(temp) &amp; kMaskFirst) &lt;&lt; 4;<\/em><br \/>\n<em>result = temp | result;<\/em><\/p>\n<p><em>\/\/ Red = 0RGB -&gt; GB0R -&gt; 000R -&gt; 0RRR -&gt; RR0R -&gt; 000R -&gt; 0R00 -&gt; 0RGB<\/em><br \/>\n<em>temp = xba(pal[i]) &amp; kMaskFirst;<\/em><br \/>\n<em>temp = xba(mult16(temp, count));<\/em><br \/>\n<em>temp = xba(temp &amp; kMaskFirst);<\/em><br \/>\n<em>result = temp | result;<\/em><\/p>\n<\/div>\n<p>And after examining the palette fade at the microscopic level, let&#8217;s watch it in action at the macroscopic level:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-75\" src=\"https:\/\/blogs.scummvm.org\/quote58\/wp-content\/uploads\/sites\/54\/2022\/07\/Jul-03-2022-19-21-27.gif\" alt=\"\" width=\"320\" height=\"206\" \/><\/p>\n<div>\nI don&#8217;t about you, but I think it&#8217;s pretty neat to see something like this and understand a process on the smallest scale that makes it work.<\/div>\n<div><\/div>\n<div><\/div>\n<div>\n<hr \/>\n<p>&nbsp;<\/p>\n<p>Next week, more on the structure of the engine and how the translation for different files and functions is going.<br \/>\nUntil then, I think I&#8217;ll take my puns and wax poetic for a bit (or maybe a byte):<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p><em>One bit, Two bit, Red bit, Blue bit,<\/em><br \/>\n<em>Green bit, Blue bit, Test if True bit,<\/em><br \/>\n<em>This word has a little endian.<\/em><br \/>\n<em>My post won&#8217;t seem to end-again.<\/em><br \/>\n<em>Say! What a lot of wiseBit puns there are. (might need to XBA that middle word!)<\/em><br \/>\n<em>Yes. Some bits are False, and some are True.<\/em><br \/>\n<em>Some I&#8217;m told, are complimentary too.<\/em><br \/>\n<em>Some are high and some are low,<\/em><br \/>\n<em>And some so high they&#8217;re in an or-bit (on second thought, it&#8217;s not exclusive)<\/em><br \/>\n<em>What if I roll, left shift then add?<\/em><br \/>\n<em>Nope! it doesn&#8217;t work because I&#8217;m bad.<\/em><\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Welcome back! Last week I mentioned that the next step would be to work on translating Kernal.gs and Driver.gs. These files contain many important functions for the entire game engine, including the main game loop and the initialization before it. These two files are distinct in the context of the apple IIGS, but for our&hellip; <a class=\"more-link\" href=\"https:\/\/blogs.scummvm.org\/quote58\/2022\/07\/04\/one-bit-two-bit-red-bit-blue-bit\/\">Continue reading <span class=\"screen-reader-text\">One bit, Two bit, Red bit, Blue bit<\/span><\/a><\/p>\n","protected":false},"author":14,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-59","post","type-post","status-publish","format-standard","hentry","category-uncategorized","entry"],"_links":{"self":[{"href":"https:\/\/blogs.scummvm.org\/quote58\/wp-json\/wp\/v2\/posts\/59","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.scummvm.org\/quote58\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.scummvm.org\/quote58\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/quote58\/wp-json\/wp\/v2\/users\/14"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/quote58\/wp-json\/wp\/v2\/comments?post=59"}],"version-history":[{"count":15,"href":"https:\/\/blogs.scummvm.org\/quote58\/wp-json\/wp\/v2\/posts\/59\/revisions"}],"predecessor-version":[{"id":81,"href":"https:\/\/blogs.scummvm.org\/quote58\/wp-json\/wp\/v2\/posts\/59\/revisions\/81"}],"wp:attachment":[{"href":"https:\/\/blogs.scummvm.org\/quote58\/wp-json\/wp\/v2\/media?parent=59"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/quote58\/wp-json\/wp\/v2\/categories?post=59"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/quote58\/wp-json\/wp\/v2\/tags?post=59"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}