I already had much of the machinery in place for raster IRQs, I just hadn't finished tying it all together.
So a few lines of VHDL later, I set the FPGA building. Unfortunately, just adding a few ties for the IRQ pushed the timing out by about 2ns from the 5.6ns required for the 192MHz pixel clock to around 7ns. As a result it didn't work.
I scratched my head for a while wondering how about 7 logic gates could ruin the timing so badly, and eventually realised that I needed to pipeline the IRQ line by adding a drive stage, so that the IRQ had time to propagate across the FPGA. Without it, ISE was rearranging everything else (badly) to make the IRQ line get to the CPU in one cycle. Net result, the IRQ triggers one pixel clock cycle late on the CPU, which isn't really an issue, since the CPU runs at half that clock speed, so it should still trigger the CPU interrupt on the correct cycle.
So then I set about writing a little raster interrupt routine to test it. This was an important step, not only to make sure that the raster interrupt line worked, but also that clearing VIC-IV interrupts worked in a C64 compatible way, unlike the C65 where the usual ASL $D019 or INC $D019 doesn't clear VIC interrupts. This is a big source of incompatibility on the C65.
Interestingly, this incompatibility on the C65 is not the VIC-III's fault, but rather the 4510 CPU's. This is because the 4510 uses the CMOS 65CE02 core that changed the behaviour of ASL, INC and other read-modify-write instructions. On the 6510, the instructions read the original value, write the original value and then write the modified value. This is why ASL $D019 or INC $D019 works to clear interrupts on the C64, because writing the value read from $D019 will clear all triggered interrupts.
But on the 4510, the original value is read, and the modified value is written, saving a cycle, and in the process really breaking compatibility. The SuperCPU has a similar problem because it uses the 65816 that includes the same "optimisation". Aware of this problem, I resolved that this problem would not exist in the C65GS, and today it was time to test it.
The interrupt routine I wrote is:
sei ; CIA IRQ disable lda #$7f sta $DC0D ; clear bit 8 of raster compare and $D011 sta $D011 ; set raster for split lda #$80 sta $D012 ; enable raster IRQ lda #$01 sta $D01A ; set IRQ vector lda #
irq sta $0315 RTS irq: ; border yellow lda #$07 sta $D020 ; wait for a bit ldx #$ff l1: dex bne l1 ; border back to light blue lda #$0e sta $D020 ; acknowledge IRQ inc $D019 ; return from interrupt, via keyboard scan etc. jmp $EA31
As can be seen, I am using my usual INC $D019 to clear the raster IRQ.
Now to see if it worked. Bingo! A nice little raster bar. There is a few cycles jitter as you would expect, but of course with a 96MHz CPU the jitter is only about one character wide. Since each character is 20 cycles wide, that means a jitter of less than 10 cycles. That's more than on a real C64 because I still have some wait states in the C65GS CPU memory access that I have yet to work around, and so some instructions can take a dozen or so cycles, in particular things like INC that include six memory accesses can take 12 or 13 cycles.
For comparison, here is the same routing running on VICE.
The keen observer will notice that not only is the raster bar much narrow on the C65GS, but it is also not in quite the same position. This is because the 1920x1200 frame has 1248 physical rasters (including flyback), which is 4x PAL's 312 lines. However, to keep the vertical borders small, in C64 mode the C65GS makes each logical raster equal to five physical rasters.
I'll have to do something about this so that raster splits occur on the correct logical line. This will most likely consist of having logical rasters spaced 3-lines apart before the display, 5-lines apart during the display, and 3-lines after. It all gets a bit fun, because 1920x1200@60Hz has only one invisible raster at the beginning of frame, while PAL has more, so the logical raster counter will have to start during flyback in the previous frame. Entirely possible, just a bit fiddly.