Hunting down the TI/TI$ bug in the C64 core

By Jens Schönfeld - just in case you want to know who the 'I' person is ;-)

The TI$ bug was a rom failure, address $ffe0 in the kernal rom was corrupted. Since the kernal rom is not a real rom on the C-One, a small bug in Jeri's core lead to corruption of this byte. Here's how we found it, and who-did-what:

Philip Zembrod from Germany read out the rom from the C64 core side, and discovered a difference in a few bytes, where only one byte could not be explained with PAL/NTSC differencies and Kernal rom release versions - this was address $ffe0 of the rom.

The value of that byte is supposed to be $f6 (246), but a PRINT PEEK(65504) gave a result of 251, which is $fb. Philip confirmed that the C64 core works fine with the rom copied to ram, and the byte corrected, so the processor part of Jeri's core is not at fault.

Tobias and I have then checked the pre-configuration phase (uploading of the roms) and the reset phase of the C64 core with my logic analyzer. It seemed like uploading the roms works as expcted, and all timings are far away from being critical, so our focus turned to the reconfig-phase of the 1k100. I closely watched the time when the 1k100 gets erased and re-configured after the roms are uploaded - I assumed the glitch that overwrites the byte around that time, but again, everything was far from being critical, and not a single glitch was visible. A re-config just puts all chip IO pins into tri-state, and the pullup resistor on the CPU/RAM card becomes effective, protecting the memory's contents until the next access.

At this point, I was at my wit's end.

Tobias saved the day: He found a pattern in the address, which lead us to the source of the problem:

Address $ffe0 of the Kernal is located in address $1ffe0 of the S-Ram chip. In that address, all bits are 1, except for the lower five address lines that are also connected to the 1k30 FPGA. This lead us to looking for the fault in the reset phase of the C64 core: The reset is being initiated by writing a value of $fb into the control register of the 7064 CPLD - the first sign of "we're on the right way", because $fb is the wrong value that Philip has found in the Kernal. Obviously, the write to this control register also ended up in the corresponding memory location with the lower five address lines determined by the 1k30.

Here's the workaround that we found together:
First, we looked for a byte between $ffe0 and $ffff that needs to be $fb. There is none in the C64 kernal. Then we checked if we can alter the value to something that makes the C64 core start, but has the same value as one of the upper 32 bytes of the kernal rom. Luckily, the 7064 control register only uses the lower four bits, so the upper four can be chosen freely without affecting proper function. Further, the 7064 ignores the lower five address lines, so these can also be chosen freely. The C64 kernal rom has $9b at address $ffeb, so we set the address lines on the 1k30 side to $0b, and the value for the 7064 register to $9b.

The result is a working C64 core, this workaround fixes the TI/TI$ bug.

Drawback: Only kernal roms that have a value of $9b at $ffeb will work with the old C64 core. This solution was only a temporary one, because Jeri fixed the bug pretty fast after we located it. The new system flash makes the old core work, and the new C64 core works with old system flashes!