Been a bit quiet the last couple of weeks, with not a lot of time to work on the project mainly due to Real Life making me do other stuff. But a lack of posts here - or indeed tangible progress on the code - does not equate to zero progress on the project; in fact, I have been devoting considerable grey matter runtime to ... the renderer.
Yes, once again I've returned to this element of the OS. It strikes even myself as odd that such a small component of the system should demand so much attention, and to be frank I had thought that after the last pass (where I streamlined and improved the logic immensely) I was finally done with it. But then a fellow-forum-member at Denial posted a comment on this post, and suddenly I knew I had to return to it. Here's what Tokra wrote:
Reading through your post I noticed that you use 8x16 characters which will result in your 4-bit-wide characters only being able to be color-changed not in pairs but in chunks of four since the character a line directly below will use the same color-RAM position. This could be avoided by setting up the screen in 8x8 mode. However to make this fit, you would need to place the 25th line in the middle of the screen instead of at the bottom. The layout would then look like this:
- Primary Screen Matrix @ $0200-$02ef - char 0-239 charram pointing to $1000
- Secondary Screen Matrix @ $02f0-$0303 - char 112-131 charram pointing to $1400
This way the whole bitmap of 4000 byte would reside from $1000-$1f9f and could be addressed in a straight way. However you would need TWO raster-splits right before and after the 13th line to make this work. You keep the zeropage free however and have doubled the color-resolution vertically.
- Tertiary Screen Matrix @ $0304-$03f3 - char 4-243 charram pointing to $1800
Well, there was challenge-and-a-half: basically, just rework the entire display-logic, IRQ synchronisation code, and memory layout! I wrote a reply enthusing about the idea, but wasn't sure I really wanted to go all the way back to almost the very beginning of the system design. But the more I thought about it, the more I knew that I could do it, and that when I did it would be awesome - eliminate the 160-byte ZP usage, make the bitmap contiguous, improve colour resolution, and make the renderer code even simpler and faster. Yep, it had to be done.
So I fairly rapidly adjusted the memory map to accommodate this new model, and tweaked the screen-setup and clearing logic to reflect the fact that the bitmap is now a single block of memory from $0200 - $03F3. That's been tested and proven to work (and SO much quicker) and I'm now working on the IRQ multiplexer which has to split the screen into three sections - on that point Tokra was slightly mistaken, since I actually need THREE raster splits; one at the end of row 12, one at the end of row 13, and one somewhere after the end of row 25 but before the start of row 1 on the next frame. This does actually only equate to two IRQ interrupts per frame, since the second split is 8 raster lines after the first and I can squeeze most of the system housekeeping in there and then execute a wait-loop for the next split.
But we don't want to just have the CPU executing a series of wait-state loops until the VIC raster line counter gets to the right place so we can adjust things to correctly draw row 1 and row 13 - that would consume a huge percentage of the processor time, and leave little or nothing for anything else. Instead, we need a bit of code that keeps track of what section of the screen is being drawn by the VIC and set the IRQ timer in VIA#2 to an appropriate interval that will trigger the next IRQ at the right place, and allow us to reset the VIC for the next section of screen 'just in time' for it to be drawn.
In the previous version of the code, we synchronised the IRQ with the raster at the end of row 24 - this allowed us to do the VIC-twiddle to display row 25, do the IRQ housekeeping whilst row 25 was being drawn, and then wait a couple of raster lines before switching the VIC back for the next frame. The VIA#2 timer value was a constant, as we wanted the IRQ to occur once per frame at exactly the same place - but now we want two IRQ interrupts per frame, and that means the multiplexer code has to know which bit of the screen is being drawn in order to reset the VIA#2 timer to the right value.
So that's what I'm working on right now - getting the IRQ initialisation working and ensuring that it'll trigger twice per frame in just the right spots, taking account of NTSC/PAL timing differences too, of course. I'll post an updated memory map and some code next time.
So that's what I'm working on right now - getting the IRQ initialisation working and ensuring that it'll trigger twice per frame in just the right spots, taking account of NTSC/PAL timing differences too, of course. I'll post an updated memory map and some code next time.
No comments:
Post a Comment