{"id":1058,"date":"2019-04-12T03:00:17","date_gmt":"2019-04-12T10:00:17","guid":{"rendered":"https:\/\/www.pagetable.com\/?p=1058"},"modified":"2019-04-12T03:00:17","modified_gmt":"2019-04-12T10:00:17","slug":"reconstructing-the-unreleased-c128-rom-update","status":"publish","type":"post","link":"https:\/\/www.pagetable.com\/?p=1058","title":{"rendered":"Reconstructing the Unreleased C128 ROM Update"},"content":{"rendered":"<p>The C128 source dump over at <a href=\"http:\/\/www.zimmers.net\/anonftp\/pub\/cbm\/src\/c128\/index.html\">zimmers.net<\/a> that appeared recently contains source for a version 2 kernel, which was never released. The known versions are 0 and 1. Let&rsquo;s see whether we can reconstruct the ROM image!<\/p>\n<h2 id=\"Release-Notes\">Release Notes<\/h2>\n<p>These are the release notes for the version 2 C128 KERNAL:<\/p>\n<pre><code>         C128 ROM RELEASE NOTES: 318020-06\n                                 318023-03\n\n\nTHE FOLLOWING MODIFICATIONS HAVE BEEN MADE TO THE 318020-05 KERNEL  CODE TO\nCREATE A NEW ROM SET RELEASED ON 05\/30\/88.  THIS  RELEASE IS FOR USE IN THE\nFOLLOWING SYSTEMS:  C128, C128D, C128CR, C128DCR.  ROMS WILL BE BUILT FOR\nONLY THE CURRENT 32K BYTE \"CR\" SYSTEMS, HOWEVER (318023-03).\n\n   1.  # 318023-03 --&gt; EDITOR, KERNEL, CP\/M ($C000-$FFFF, U32) cksum= E424\n   2.  # 318020-06 --&gt; EDITOR, KERNEL, CP\/M ($C000-$FFFF)      cksum= DFC4\n\n       1.  SECURE.  This kernel initialization routine has been modified\n           to accomodate technological advances in DRAMs.  The discharge\n           rates for data cells has lengthened considerably and it is no\n           longer possible to rely upon the  loss  of data as indicative\n           of a  power cycle as opposed to a  reset.  The SECURE routine\n           has been patched to also check the  contents of the  8568 VDC\n           registers.  These will  contain  $FF  if  power  cycled.  The\n           previous  testing of a \"CBM\" RAM key in  bank one remains for\n           compatability.  This patch required new code in patch area.\n\n       2.  DLABYE.  This kernel  serial  I\/O routine has been patched to\n           provide a longer delay.  This should prevent certain randomly\n           occurring DEVICE NOT READY errors, particularly at 2MHz. This\n           is a single byte patch totally inline.\n\n       3.  OPN232.  This kernel  routine  has  been patched to correctly\n           return error status.  When  implementing  an X-line interface\n           it was possible to receive an error when there was none. This\n           is a single byte patch totally inline.\n\n       4.  The ROM  signature at location $CFFC  and  $CFFD  (lo\/hi)  is\n           $8C3E.\n\n       5.  The ROM revision byte at location $CFFE, has incremented from\n           $01 to $02.\n\n       6.  The ROM checksum byte at  location  $CFFF,  has  changed from\n           $3C to $3B.\n\n       7.  The Kernel revision byte at location  $FF80  has  incremented\n           from $01 to $02.\n\n\n       Fred Bowen        05\/30\/88.\n<\/code><\/pre>\n<p>The &ldquo;31802x-0y&rdquo; numbers are Commodore Product IDs for the physical ROM chips:<\/p>\n<table>\n<thead>\n<tr>\n<th> Product ID <\/th>\n<th> System     <\/th>\n<th> Description                <\/th>\n<th> Size  <\/th>\n<th> Status     <\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td> 318020-05  <\/td>\n<td> C128\/C128D <\/td>\n<td> KERNAL version 2           <\/td>\n<td> 16 KB <\/td>\n<td> released   <\/td>\n<\/tr>\n<tr>\n<td> 318020-06  <\/td>\n<td> C128\/C128D <\/td>\n<td> KERNAL version 3           <\/td>\n<td> 16 KB <\/td>\n<td> <strong>unreleased<\/strong> <\/td>\n<\/tr>\n<tr>\n<td> 318023-02  <\/td>\n<td> C128DCR    <\/td>\n<td> C64 ROM + KERNAL version 2 <\/td>\n<td> 32 KB <\/td>\n<td> released   <\/td>\n<\/tr>\n<tr>\n<td> 318023-03  <\/td>\n<td> C128DCR    <\/td>\n<td> C64 ROM + KERNAL version 3 <\/td>\n<td> 32 KB <\/td>\n<td> <strong>unreleased<\/strong> <\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2 id=\"Parsing-the-.LST-Files\">Parsing the <code>.LST<\/code> Files<\/h2>\n<p>In addition to the source trees of the two versions, the archive also contains an <code>.LST<\/code> file for each version. An <code>.LST<\/code> file is generated during assembly and consists of every source line annotated with the current address and the generated object bytes.<\/p>\n<p>Here is an example line:<\/p>\n<pre><code>     E000   A2 FF        2367   start   ldx #$ff        ;normal \/reset entry\n<\/code><\/pre>\n<ul>\n<li><code>E000<\/code> is the address of the code<\/li>\n<li><code>A2 FF<\/code> is the object code produced by the line<\/li>\n<li><code>2367<\/code> is the global line number of the project (counts all source lines starting from 1)<\/li>\n<li>The remainder is the original source line.<\/li>\n<\/ul>\n<p>After cutting out just the addresses and the object code, we can easily compare the two files:<\/p>\n<pre><code>for i in 05 06; do\n  cat kernal\/318020_$i\/kernal.lst | grep \"^     [0-9A-F]...   [0-9A-F]\" | cut -c -25 &gt; $i.txt\ndone\ndiff 05.txt 06.txt\n<\/code><\/pre>\n<h2 id=\"The-Differences\">The Differences<\/h2>\n<p>This is the result:<\/p>\n<pre><code>14c14\n&lt;      E01B   20 E1F0\n---\n&gt;      E01B   20 CF9E\n1986c1986\n&lt;      F098   90 09\n---\n&gt;      F098   90 08\n1988c1988\n&lt;      F09D   30 04\n---\n&gt;      F09D   30 03\n3264a3265,3272\n&gt;      CF9E   A2 0F\n&gt;      CFA0   20 CDDA\n&gt;      CFA3   C9 FF\n&gt;      CFA5   D0 06\n&gt;      CFA7   CA\n&gt;      CFA8   10 F6\n&gt;      CFAA   4C E224\n&gt;      CFAD   4C E1F0\n3284c3292\n&lt;      FF80   01\n---\n&gt;      FF80   02\n<\/code><\/pre>\n<ul>\n<li><code>$E01B<\/code>: <code>jsr secure_patch<\/code> instead of <code>jsr secure<\/code> (bullet point 1)<\/li>\n<li><code>$F098<\/code>\/<code>$F09D<\/code>: two branches have different destinations (bullet point 3)<\/li>\n<li><code>$CF9E<\/code>: <code>secure_patch<\/code>, a new patch in the patch area (bullet point 1)<\/li>\n<li><code>$FF80<\/code>: the updated KERNAL revision byte (bullet point 7)<\/li>\n<\/ul>\n<p>So the changes are minor and can easily be manually patched into a copy of <a href=\"http:\/\/www.zimmers.net\/anonftp\/pub\/cbm\/firmware\/computers\/c128\/\">kernal.318020-05.bin<\/a>.<\/p>\n<p>What is weird though is that the release notes mention a difference in <code>DLABYE<\/code>, but there doesn&rsquo;t seem to be one. This is the code in both versions:<\/p>\n<pre><code>dlabye  jsr scatn       ;always release atn\ndladlh  txa             ;delay and then release clock &amp; data\n        ldx #10         ;delay approx 60 us\n10$     dex\n        bne 10$\n        tax\n        jsr clkhi\n        jmp datahi\n<\/code><\/pre>\n<p>The single-byte patch for the increased delay mentioned by the release notes would probably have to be a change in the number of iterations in the loop.<\/p>\n<p>The release notes also mention that some version and checksum bytes in the file have changed. We don&rsquo;t have to calculate them ourselves, they are provided for us (bullet points 4, 5 and 6 in the release notes):<\/p>\n<pre><code>CFFC   3E 8C\nCFFE   02\nCFFF   3B\n<\/code><\/pre>\n<h2 id=\"Checksum\">Checksum<\/h2>\n<p>Now how do we verify that the resulting binary is correct? The release notes states the checksum of the new ROM!<\/p>\n<pre><code>    2.  # 318020-06 --&gt; EDITOR, KERNEL, CP\/M ($C000-$FFFF)      cksum= DFC4\n<\/code><\/pre>\n<p>I couldn&rsquo;t find any documentation on what algorithm is used for the checksum, but there are also release notes for the 318020-05 ROM that states the checksum for the ROM we have:<\/p>\n<pre><code>    3.  # 318020-05 --&gt; EDITOR, KERNEL, CP\/M ($C000-$FFFF, U35) cksum= EEC4\n<\/code><\/pre>\n<p>As it turns out, it is just the lower 16 bits of all bytes added up. This Python code does it:<\/p>\n<pre><code>import sys\nc = 0\nfor i in bytearray(sys.stdin.read()):\n    c = (c + i) &amp; 0xffff\nprint hex(c)\n<\/code><\/pre>\n<p>I tested the algorithm with several existing ROMs and the checksum always matched the release notes.<\/p>\n<p>Now let&rsquo;s test it with our newly created 318020-06 ROM:<\/p>\n<pre><code>$ python cksum.py &lt; kernal.318020-06_canditate.bin\n0xe68b\n<\/code><\/pre>\n<p>The checksum should be 0xdfc4, but our file has a checksum of 0xe68b \u2013\u00a0a difference of 0x6c7. Because of the way the checksum works, this means we are not close. A difference in a single byte would mean the checksum could not be off by more than $ff.<\/p>\n<h2 id=\"Conclusion\">Conclusion<\/h2>\n<p>So no, it seems we can&rsquo;t reconstruct the exact 318020-06 ROM image, and it is unclear what the differences are.<\/p>\n<p>If anyone has any ideas, I&rsquo;d be very interested!<\/p>\n<p>In the meantime, here is the &ldquo;best-we-can-do&rdquo; image:<\/p>\n<p><a href=\"docs\/kernal.318020-06_canditate.bin\">kernal.318020-06_canditate.bin<\/a> (32768 bytes)<\/p>\n<p>It contains the initialization and RS232 patches and identifies as version 2.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The C128 source dump over at zimmers.net that appeared recently contains source for a version 2 kernel, which was never released. The known versions are 0 and 1. Let&rsquo;s see whether we can reconstruct the ROM image! Release Notes These are the release notes for the version 2 C128 KERNAL: C128 ROM RELEASE NOTES: 318020-06 &#8230; <a title=\"Reconstructing the Unreleased C128 ROM Update\" class=\"read-more\" href=\"https:\/\/www.pagetable.com\/?p=1058\" aria-label=\"Read more about Reconstructing the Unreleased C128 ROM Update\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[40,8,19],"tags":[],"class_list":["post-1058","post","type-post","status-publish","format-standard","hentry","category-c128","category-commodore","category-kernal"],"_links":{"self":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts\/1058","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1058"}],"version-history":[{"count":0,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts\/1058\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1058"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1058"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1058"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}