This screen-refresh challenge is proving to be a significant issue; I've been through four different models over the past few days, looking for the 'right' way to do it, and I'm still not quite there. I have refined the basic dirty-row mechanism though - the logic has collapsed into a much neater process and I've dispensed with the need for those four bytes in Zero Page which contained a bitmap for which rows were dirty. I now hold the dirty bit in the first Control Byte of each row in the Control Buffer, so setting a dirty bit is now just a matter of getting that first byte (via a fast indexed-lookup into a table) and setting bit 7. Conversely, finding dirty row bits no longer requires that clunky bit of code I didn't like to interrogate the bitmap - instead, we just scream down the first byte of each row looking to see if bit 7 is set. Much faster, much neater, and simpler to understand.
The problem I'm grappling with is simply one of speed. The 6502 runs at roughly 1MHz in the VIC-20, and getting a decent bitmap mode screen-refresh working at that clock speed without sucking most of the CPU horsepower away from the users' code is proving to be ... interesting. It all comes down to cycles-per-IRQ, and making sure I'm not burning more than are available in that window. But at the same time, I know I've got to be able to refresh individual lines quickly and responsively or the user experience is going to suck - and I'm also conscious of the fact that when we get beyond this point, there will be further demands on the CPU for refreshing the entire bitmap in one go for situations as simple and elementary as scrolling the screen viewport up and down (which will entail somehow moving large chunks of bitmap data around in a short space of time).
At the moment, the idea I'm working on - and which I feel, after much experimentation, is likely to be the one that works - will trigger the find-dirty-bits routine on each IRQ, and then process precisely one dirty row (if it finds any). This will take considerably less than the 22150 cycles available in the IRQ frame, and means that a complete refresh of the screen where all rows have had their dirty bits set would take half a second and not swamp the CPU. The routine stashes the line it just refreshed, so on the next IRQ it carries-on from there and we avoid the potential issue of some areas of the screen never getting refreshed due to higher lines 'jumping the queue'.
The code is still a little untidy, so I'm not posting it yet - but it's starting to hang together and I've got a good feeling about it. There's a little more to do, and then some optimisation, so I'm hoping the next post here will see it fit for publication. Stay tuned!
The code is still a little untidy, so I'm not posting it yet - but it's starting to hang together and I've got a good feeling about it. There's a little more to do, and then some optimisation, so I'm hoping the next post here will see it fit for publication. Stay tuned!
No comments:
Post a Comment