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’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
318023-03
THE FOLLOWING MODIFICATIONS HAVE BEEN MADE TO THE 318020-05 KERNEL CODE TO
CREATE A NEW ROM SET RELEASED ON 05/30/88. THIS RELEASE IS FOR USE IN THE
FOLLOWING SYSTEMS: C128, C128D, C128CR, C128DCR. ROMS WILL BE BUILT FOR
ONLY THE CURRENT 32K BYTE "CR" SYSTEMS, HOWEVER (318023-03).
1. # 318023-03 --> EDITOR, KERNEL, CP/M ($C000-$FFFF, U32) cksum= E424
2. # 318020-06 --> EDITOR, KERNEL, CP/M ($C000-$FFFF) cksum= DFC4
1. SECURE. This kernel initialization routine has been modified
to accomodate technological advances in DRAMs. The discharge
rates for data cells has lengthened considerably and it is no
longer possible to rely upon the loss of data as indicative
of a power cycle as opposed to a reset. The SECURE routine
has been patched to also check the contents of the 8568 VDC
registers. These will contain $FF if power cycled. The
previous testing of a "CBM" RAM key in bank one remains for
compatability. This patch required new code in patch area.
2. DLABYE. This kernel serial I/O routine has been patched to
provide a longer delay. This should prevent certain randomly
occurring DEVICE NOT READY errors, particularly at 2MHz. This
is a single byte patch totally inline.
3. OPN232. This kernel routine has been patched to correctly
return error status. When implementing an X-line interface
it was possible to receive an error when there was none. This
is a single byte patch totally inline.
4. The ROM signature at location $CFFC and $CFFD (lo/hi) is
$8C3E.
5. The ROM revision byte at location $CFFE, has incremented from
$01 to $02.
6. The ROM checksum byte at location $CFFF, has changed from
$3C to $3B.
7. The Kernel revision byte at location $FF80 has incremented
from $01 to $02.
Fred Bowen 05/30/88.
The “31802x-0y” numbers are Commodore Product IDs for the physical ROM chips:
Product ID | System | Description | Size | Status |
---|---|---|---|---|
318020-05 | C128/C128D | KERNAL version 2 | 16 KB | released |
318020-06 | C128/C128D | KERNAL version 3 | 16 KB | unreleased |
318023-02 | C128DCR | C64 ROM + KERNAL version 2 | 32 KB | released |
318023-03 | C128DCR | C64 ROM + KERNAL version 3 | 32 KB | unreleased |
Parsing the .LST
Files
In addition to the source trees of the two versions, the archive also contains an .LST
file for each version. An .LST
file is generated during assembly and consists of every source line annotated with the current address and the generated object bytes.
Here is an example line:
E000 A2 FF 2367 start ldx #$ff ;normal /reset entry
E000
is the address of the codeA2 FF
is the object code produced by the line2367
is the global line number of the project (counts all source lines starting from 1)- The remainder is the original source line.
After cutting out just the addresses and the object code, we can easily compare the two files:
for i in 05 06; do
cat kernal/318020_$i/kernal.lst | grep "^ [0-9A-F]... [0-9A-F]" | cut -c -25 > $i.txt
done
diff 05.txt 06.txt
The Differences
This is the result:
14c14
< E01B 20 E1F0
---
> E01B 20 CF9E
1986c1986
< F098 90 09
---
> F098 90 08
1988c1988
< F09D 30 04
---
> F09D 30 03
3264a3265,3272
> CF9E A2 0F
> CFA0 20 CDDA
> CFA3 C9 FF
> CFA5 D0 06
> CFA7 CA
> CFA8 10 F6
> CFAA 4C E224
> CFAD 4C E1F0
3284c3292
< FF80 01
---
> FF80 02
$E01B
:jsr secure_patch
instead ofjsr secure
(bullet point 1)$F098
/$F09D
: two branches have different destinations (bullet point 3)$CF9E
:secure_patch
, a new patch in the patch area (bullet point 1)$FF80
: the updated KERNAL revision byte (bullet point 7)
So the changes are minor and can easily be manually patched into a copy of kernal.318020-05.bin.
What is weird though is that the release notes mention a difference in DLABYE
, but there doesn’t seem to be one. This is the code in both versions:
dlabye jsr scatn ;always release atn
dladlh txa ;delay and then release clock & data
ldx #10 ;delay approx 60 us
10$ dex
bne 10$
tax
jsr clkhi
jmp datahi
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.
The release notes also mention that some version and checksum bytes in the file have changed. We don’t have to calculate them ourselves, they are provided for us (bullet points 4, 5 and 6 in the release notes):
CFFC 3E 8C
CFFE 02
CFFF 3B
Checksum
Now how do we verify that the resulting binary is correct? The release notes states the checksum of the new ROM!
2. # 318020-06 --> EDITOR, KERNEL, CP/M ($C000-$FFFF) cksum= DFC4
I couldn’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:
3. # 318020-05 --> EDITOR, KERNEL, CP/M ($C000-$FFFF, U35) cksum= EEC4
As it turns out, it is just the lower 16 bits of all bytes added up. This Python code does it:
import sys
c = 0
for i in bytearray(sys.stdin.read()):
c = (c + i) & 0xffff
print hex(c)
I tested the algorithm with several existing ROMs and the checksum always matched the release notes.
Now let’s test it with our newly created 318020-06 ROM:
$ python cksum.py < kernal.318020-06_canditate.bin
0xe68b
The checksum should be 0xdfc4, but our file has a checksum of 0xe68b – a 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.
Conclusion
So no, it seems we can’t reconstruct the exact 318020-06 ROM image, and it is unclear what the differences are.
If anyone has any ideas, I’d be very interested!
In the meantime, here is the “best-we-can-do” image:
kernal.318020-06_canditate.bin (32768 bytes)
It contains the initialization and RS232 patches and identifies as version 2.
Typo: “binray” should be “binary”.
Thanks, fixed!
Looking into the binary “complete.german.318077-03.bin” from zimmers.net:
(1) It contains all but one patches from above, only the f098 patch is missing. But it contains the DLABYE Patch:
dlabye jsr scatn ;always release atn
dladlh txa ;delay and then release clock & data
ldx #$24 ;delay approx … us
10$ dex
bne 10$
tax
jsr clkhi
jmp datahi
So I am quit sure that this is one of the missing pieces.
Is there some element of corrupted data here? My reasoning:
– Point 3 of Fred Bowen’s original summary describes the OPN232 patch as _a_ single-byte inline change.
– The unreleased ROM image being analyzed contains _two_ single-byte changes.
– The German ROM which MarkusC64 references only contains one of those single-byte changes .
– It’s stated that the unreleased ROM image does not in fact contain the four altered bytes described in points 4 through 6. Does some combination of including or not including various of those three individual changes help solve the checksum mystery?
– MarkusC64 reports that the German ROM includes all 7 of these patches, albeit with one variation in the object code, _and_ that ROM’s part number ends in -03… just like the unreleased North American ROM was to be. I’d like to interpret that as meaning “oh hey, it’s already out there” — but certainty would require analysis of the OPN232 routine, to figure out just what it’s _supposed_ to look like. One change, or two?
Any thoughts on my comment?