{"id":396,"date":"2019-11-12T23:00:16","date_gmt":"2019-11-13T05:00:16","guid":{"rendered":"https:\/\/greg-kennedy.com\/wordpress\/?p=396"},"modified":"2019-11-18T10:06:55","modified_gmt":"2019-11-18T16:06:55","slug":"back-to-the-future-part-iii-color-fix-patch","status":"publish","type":"post","link":"https:\/\/greg-kennedy.com\/wordpress\/2019\/11\/12\/back-to-the-future-part-iii-color-fix-patch\/","title":{"rendered":"Back to the Future: Part III &#8211; Color Fix Patch"},"content":{"rendered":"\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"694\" height=\"243\" src=\"https:\/\/greg-kennedy.com\/wordpress\/wp-content\/uploads\/2019\/11\/BttF3-TitleCompare.png\" alt=\"\" class=\"wp-image-399\" srcset=\"https:\/\/greg-kennedy.com\/wordpress\/wp-content\/uploads\/2019\/11\/BttF3-TitleCompare.png 694w, https:\/\/greg-kennedy.com\/wordpress\/wp-content\/uploads\/2019\/11\/BttF3-TitleCompare-300x105.png 300w, https:\/\/greg-kennedy.com\/wordpress\/wp-content\/uploads\/2019\/11\/BttF3-TitleCompare-624x218.png 624w\" sizes=\"auto, (max-width: 694px) 100vw, 694px\" \/><figcaption>Title Screen &#8211; Before and After<\/figcaption><\/figure>\n\n\n\n<p>An exchange on Twitter led me into a trap that consumed a week of my time &#8211; the Sega Genesis \/ Mega Drive version of Back to the Future: Part III shipped with a bug that caused <strong>completely wrong colors to display<\/strong>.  Evidently the programmer(s) were confused about the proper format of color data on the Genesis.  While color values <em>should<\/em> be stored in two bytes as <code>0000bbb0 ggg0rrr0<\/code>, this game instead uses the incorrect format <code>00000bbb 0ggg0rrr<\/code> &#8211; all values shifted right by one bit.  The end result is that the game displays at half brightness, and lower contrast.<\/p>\n\n\n\n<p>I naively assumed this would be a simple fix: in fact, <a href=\"http:\/\/www.sega-16.com\/forum\/showthread.php?16125-Has-anyone-ever-fixed-the-palette-bug-in-Back-to-the-Future-Part-III\">some prior discussion<\/a> pointed out that color tables are stored plainly in the file, and even provided addresses to fix some of them.  Of course, things are never as easy as they seem.  Using a hex editor I changed some color palettes, then used the <a href=\"https:\/\/www.retrodev.com\/blastem\/\">BlastEm emulator<\/a> (its debugger is okay) to test, and made two discoveries:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>the list in the forum post is incomplete, and I needed to do further digging to uncover the rest of the palettes, and<\/li><li>even with the palettes fixed, colors still didn&#8217;t display correctly.  Any code that sets the palette (e.g. when fading to\/from black) still used the old, wrong format.  So while the data was correct, it still displayed wrong.<\/li><\/ul>\n\n\n\n<p>At this point I decided to see how <a href=\"https:\/\/ghidra-sre.org\/\">Ghidra<\/a> would fare on 68000 code.  With the help from <a href=\"https:\/\/zznop.github.io\/romhacking\/2019\/03\/14\/sega-genesis-rom-hacking-with-ghidra.html\">some scripts from zznop<\/a> (to parse Genesis ROM headers, and to generate a new checksum after modification), I spent a couple days working at a disassembly of the ROM.  Ghidra works well for this, but it has some quirks: it does not properly handle 24-bit addresses, it sometimes needs a kick with the &#8220;disassemble&#8221; key to force it to parse a block of obvious code, and the &#8220;address table&#8221; checkbox on Auto-Analysis causes far more pain than benefit &#8211; don&#8217;t use that!<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"694\" height=\"243\" src=\"https:\/\/greg-kennedy.com\/wordpress\/wp-content\/uploads\/2019\/11\/BttF3-Stage1Compare.png\" alt=\"\" class=\"wp-image-400\" srcset=\"https:\/\/greg-kennedy.com\/wordpress\/wp-content\/uploads\/2019\/11\/BttF3-Stage1Compare.png 694w, https:\/\/greg-kennedy.com\/wordpress\/wp-content\/uploads\/2019\/11\/BttF3-Stage1Compare-300x105.png 300w, https:\/\/greg-kennedy.com\/wordpress\/wp-content\/uploads\/2019\/11\/BttF3-Stage1Compare-624x218.png 624w\" sizes=\"auto, (max-width: 694px) 100vw, 694px\" \/><figcaption>Despite the nice color improvements, this stage is still way too hard!<\/figcaption><\/figure>\n\n\n\n<p>In the end I produced a disassembly that was quite revealing.  The game doesn&#8217;t have a lot of code re-use, it was apparently written in isolated stages and then combined together at the end.  Functions for palette fades and &#8220;cutscene&#8221; display are duplicated in each segment.  Finding palette setting code wasn&#8217;t too difficult once a palette were found, and usually looked something like this (taken from a &#8220;Fade To Palette&#8221; routine):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>...\n                         LAB_0000a264\n    0000a264 3c 11           move.w     (A1),D6w\n    0000a266 02 46 0f 00     andi.w     #0x700,D6w\n    0000a26a 36 12           move.w     (A2)=>targetPalette64,D3w\n    0000a26c 02 43 0f 00     andi.w     #0x700,D3w\n    0000a270 b6 46           cmp.w      D6w,D3w\n    0000a272 64 00 00 06     bcc.w      LAB_0000a27a\n    0000a276 06 43 01 00     addi.w     #0x100,D3w\n                         LAB_0000a27a\n    0000a27a 3c 11           move.w     (A1),D6w\n    0000a27c 02 46 00 f0     andi.w     #0x70,D6w\n    0000a280 38 12           move.w     (A2)=>targetPalette64,D4w\n    0000a282 02 44 00 f0     andi.w     #0x70,D4w\n    0000a286 b8 46           cmp.w      D6w,D4w\n    0000a288 64 00 00 06     bcc.w      LAB_0000a290\n    0000a28c 06 44 00 10     addi.w     #0x10,D4w\n                         LAB_0000a290\n    0000a290 3c 11           move.w     (A1),D6w\n    0000a292 02 46 00 0f     andi.w     #0x7,D6w\n    0000a296 3a 12           move.w     (A2)=>targetPalette64,D5w\n    0000a298 02 45 00 0f     andi.w     #0x7,D5w\n    0000a29c ba 46           cmp.w      D6w,D5w\n    0000a29e 64 00 00 04     bcc.w      LAB_0000a2a4\n    0000a2a2 52 45           addq.w     #0x1,D5w\n                         LAB_0000a2a4\n    0000a2a4 86 44           or.w       D4w,D3w\n    0000a2a6 86 45           or.w       D5w,D3w\n    0000a2a8 3c 19           move.w     (A1)+,D6w\n    0000a2aa 02 46 0f ff     andi.w     #0x777,D6w\n    0000a2ae bc 43           cmp.w      D3w,D6w\n    0000a2b0 66 00 00 04     bne.w      LAB_0000a2b6\n    0000a2b4 52 41           addq.w     #0x1,D1w\n                         LAB_0000a2b6\n    0000a2b6 33 c3 00        move.w     D3w,(VDP_DATA).l\n             c0 00 00\n...<\/code><\/pre>\n\n\n\n<p>A bit hard to see maybe, but the important parts are that it&#8217;s processing the values in B, G, R order, by using &#8220;(component) <code>and 0111<\/code>&#8220;, and incrementing if less than the desired value.  This is the wrong bitmask.  Changing to 1111 (i.e. <code>0x7<\/code> to <code>0xf<\/code>) allows fading through the full gamut, and everything now displays as intended.  I was also able to reference the SEGA logo (at game boot), which DOES have proper colors, to double-check that I had this implemented correctly.<\/p>\n\n\n\n<p>Finding the other places in the code where this happens is pretty trivial.  A search for <code>0x0777<\/code> or <code>andi.w 0x07<\/code> reveals the rest.  With that fixed, I regenerated the checksum and wrote a new ROM, then used <a href=\"https:\/\/fusoya.eludevisibility.org\/lips\/\">LunarIPS<\/a> to make an IPS patch for distributing the fix.<\/p>\n\n\n\n<p>The last step was to port the changes to the EU version of the game.  Fortunately, the data is the same, and a Perl script with find-replace made locating the offsets easy.  A new IPS patch, a README file, and we&#8217;re ready to ship.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Download the patch:<\/h2>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/greg-kennedy.com\/wordpress\/wp-content\/uploads\/2019\/11\/BttF3-ColorFix.zip\">BttF 3 &#8211; Color Fix (ZIP file containing US \/ EU IPS patches)<\/a><a href=\"https:\/\/greg-kennedy.com\/wordpress\/wp-content\/uploads\/2019\/11\/BttF3-ColorFix.zip\" class=\"wp-block-file__button\" download=\"\">Download<\/a> (4kb)<\/div>\n\n\n\n<p>All told, this was actually a fun rabbit hole to get lost in, and I did pick up a lot about Ghidra and 68000 assembly that I had been wanting to learn anyway.  If only it didn&#8217;t come right in the middle of <a href=\"https:\/\/nanogenmo.github.io\/\">NaNoGenMo<\/a>&#8230; \ud83d\ude42<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"694\" height=\"243\" src=\"https:\/\/greg-kennedy.com\/wordpress\/wp-content\/uploads\/2019\/11\/BttF3-Stage4Compare.png\" alt=\"\" class=\"wp-image-401\" srcset=\"https:\/\/greg-kennedy.com\/wordpress\/wp-content\/uploads\/2019\/11\/BttF3-Stage4Compare.png 694w, https:\/\/greg-kennedy.com\/wordpress\/wp-content\/uploads\/2019\/11\/BttF3-Stage4Compare-300x105.png 300w, https:\/\/greg-kennedy.com\/wordpress\/wp-content\/uploads\/2019\/11\/BttF3-Stage4Compare-624x218.png 624w\" sizes=\"auto, (max-width: 694px) 100vw, 694px\" \/><figcaption>Doc!  &#8230;Your hat!<\/figcaption><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>An exchange on Twitter led me into a trap that consumed a week of my time &#8211; the Sega Genesis \/ Mega Drive version of Back to the Future: Part III shipped with a bug that caused completely wrong colors to display. Evidently the programmer(s) were confused about the proper format of color data on [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,8],"tags":[],"class_list":["post-396","post","type-post","status-publish","format-standard","hentry","category-games","category-software"],"_links":{"self":[{"href":"https:\/\/greg-kennedy.com\/wordpress\/wp-json\/wp\/v2\/posts\/396","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/greg-kennedy.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/greg-kennedy.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/greg-kennedy.com\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/greg-kennedy.com\/wordpress\/wp-json\/wp\/v2\/comments?post=396"}],"version-history":[{"count":6,"href":"https:\/\/greg-kennedy.com\/wordpress\/wp-json\/wp\/v2\/posts\/396\/revisions"}],"predecessor-version":[{"id":406,"href":"https:\/\/greg-kennedy.com\/wordpress\/wp-json\/wp\/v2\/posts\/396\/revisions\/406"}],"wp:attachment":[{"href":"https:\/\/greg-kennedy.com\/wordpress\/wp-json\/wp\/v2\/media?parent=396"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/greg-kennedy.com\/wordpress\/wp-json\/wp\/v2\/categories?post=396"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/greg-kennedy.com\/wordpress\/wp-json\/wp\/v2\/tags?post=396"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}