Inspired by the palette switching
thread and tricky's attempts to do something special for MODE 1
, the discussion about the ULA's limitations in this thread got me thinking about a possible way to turn what appears to be a massive disadvantage into a peculiar Electron advantage. I ran the idea past paulb and it seemed like some experiments were in order. My thinking about the subject follows - corrections to any misunderstandings of CPU/ULA operation are welcome!
In Electron User, Roland Waddilove showed that, using interrupts and cycle counting
, you could palette switch for each line of characters in MODE 6 and use the gaps to hide timing irregularities. In principle, you could do the same for any mode and even change the palette for each scanline, but you would need to be really good at timing. What you really need is some way of synchronizing palette changes with scanlines, like an interrupt handler, but the CPU/ULA contention provides something else we can use.
The service manual mentions that, in modes 0-3, the CPU is denied RAM access during the part of a scanline when the ULA is active. In fact, is is made to wait for RAM access. If we were cycle counting our way down the screen, we would have to take this into account, and without exact counting there's no way we can know which scanline we are on. However, there is a scenario where we can use this blocking behaviour to our advantage: when we run our code from ROM.
In ROM, the code is only blocked when we access RAM during the display period, when the ULA is active, so we can use this to ensure that we execute a particular piece of code when the display period is over. Starting from the top of the screen, we delay until we are sure that we are in the display period, then we access the RAM. The CPU stalls until the display period is over, but this guarantees that we will execute the next instruction at the first opportunity between scanlines. At this point, we change the palette then wait until the display period has begun, then we access RAM again. We are basically using RAM access as a way to synchronize display and execution.
So, that's the theory. Having made something work in Elkulator, the next step was to see if it worked on a real Electron. There's a minor difference, but the implementation seems basically sound. It's a testament to how good Elkulator is that you can use it to prototype code like this and see it working on a real Electron.
I'll start a thread in the Retro Software 8-bit Acorn Programming forum
and put the code up later today or tomorrow. It may be useful for testing the limits of the FPGA Electron's ULA implementation.