Monday, June 16, 2014

DMAgic colour RAM bug fixed

We have a work experience student called Max in the lab this week, and he is interested in low-level hardware type stuff.  So I asked if he would like to explore writing some tests for the C65GS.

In a previous post I had commented on a bug where scrolling the display in C65 mode results in the colour RAM going all weird.  We set about starting to write some tests for the DMA controller to try to find and fix that bug.

While Max is only 15, he has a good attitude and interest, and for someone who has never written anything in any assembly language or really used an 8-bit computer before, he is doing pretty well.

After a bit of poking about and talking about the bug with Jeremy as well, I came to the realisation that the bug was not in DMAgic, but in the colour RAM.  A little more explanation is required.

On the C64 the colour RAM is a separate 1KB x 4 bit memory.  The C65, however, which can require almost 2KB of colour RAM for 80 column mode.  Also, the upper four bits of the colour RAM represent extended attributes.  As a result the C65 needs 2KB of 8-bit RAM for colour RAM.  Rather than require a separate part, the designers of the C65 would have its colour RAM as the top 2KB ($1F800-$1FFFF) of the 128KB main memory.

This means that a stock C65 actually has a little bit less RAM available than a C128.  Actually, a stock C65 has quite a bit less available RAM, because the DOS eats another 8KB of RAM.  The overall memory map in C65 looks something like:

           RAM LO          RAM HI
$FEFF -   BASIC  10        COLOUR RAM
           PROGRAM           (2KB)
$F800 -     TEXT
          ($2000 -         BASIC  10
           $FEFF)          VARIABLES 
$2000 -
          SCREENS &       INTERNAL 3.5"
         SYSTEM DATA       DRIVE DOS
$0000 -

So all up, only 128KB - 8KB - 8KB - 2KB - 0.25KB = 128KB - 18.25KB = 109.75KB is available for BASIC 10 in C65 mode.

But when I began designing the C65GS, I had in mind that it would support much larger text modes than the C64 or C65.  With a native resolution of 1920x1200, it is possible to run a 240x150 character text mode.  This means we need up to 36,000 (35.2KB) bytes of colour RAM.  It seemed bad enough to lose 2KB of precious chip RAM, let alone losing more than 1/4 of all RAM, just for colour data for text mode.  Factoring in the actual screen RAM, this would mean that 240x150 text mode would consume more than 1/2 of the total memory.  That just wasn't going to fly.

My preferred solution was to have 256KB or 512KB of chipram, but the FPGA I am using can't combine that much BRAM at a high enough clock speed.  However, I was pleasantly surprised to find that I could make a 64KB x 8-bit memory as well as the 128KB chipram (in its 16KB x 64-bit form factor).  So I implemented colour RAM that way, mapping it to $D800-$DBFF (or $DFFF when the right bit is set in the VIC-III), as well as at the C65GS extended address $FF80000-$FF8FFFF.

All was happy until I remembered that the C65 direct maps the colour RAM at $1F800-$1FFFF, as described above.

My solution to this was to tweak the C65GS memory map, so that it also mapped at $1F800-$1FFFF, masking the 2KB of chipram there, a bit like how memory locations $0000 and $0001 are masked on the C64.  In fact, like those locations on the C64, there is no way for the CPU (or DMAgic, since DMAgic on the C65GS is just the CPU in drag) to access the last 2KB of chipram on the C65GS.  You would have to use some sort of reflective process to even read them, like the sprite trick that can be used to read $0000/$0001 on the C64.

This is a bit of a hack architecturally, since it means that you can't actually use those two kilobytes of chipram as real chipram now.  However, that is more or less the case on a real C65, as the colour RAM cannot be relocated elsewhere.  It is possible to point bitplanes there, which would produce different results on the C65GS.  Maybe one day I will have to revisit this, and make some magic that copies writes to $1F800 - $1FFFF through to the colour RAM, so that it has perfect compatibility.

Coming back to the point, it turns out that the logic to write to the colour RAM image at $1F800-$1FFFF was buggy, and would return the CPU to the wrong micro-code state.  I had noticed something odd in this regard previously, in that the serial monitor interface would get upset if you tried to write to colour RAM at $1F800 - $1FFFF.

Some more poking around revealed that accessing colour RAM at $FF8xxxx worked perfectly, so I adjusted the memory read/write parts of the 45GS10 CPU to translate the addresses with a cleaner abstraction layer than previously.  After FPGA rebuild, the result was happiness, with all the weirdness going away.  Scrolling now works correctly, and without DMA going bananas when writing to colour RAM, the DOS context switch state information doesn't get destroyed, so a directory listing can scroll off the bottom with the DIR command in C65 mode.  See video below:

No comments:

Post a Comment