So, without looking at the code what method does VDC101 actually use to "divide the screen into two or more areas with independently controllable base addresses and x-y smooth scrolling" as the text in the demo says? I would like to understand and try this method maybe on interlace-mode and see what can be done there...
Well, more than a year after the demo is released,
somebody finally asks how it works!?! (yes Wil I know you know.. )
Below is a (3rd) draft of an explanation of the technique. Feel free to ask about anything that isn't clear so I can improve it.
Background to VDC-SPLIT
There are fundamental limitations with the VDC when it comes to dividing up the screen, in particular the vertical smooth scroll (reg #24) and the base addresses of the screen (reg #12-13) & attributes (reg #20-21):
1. They latch only once per frame. i.e changing them mid screen has no effect.
2. They latch at illogical and inconvenient locations
The VDC-SPLIT method demonstrated in VDC101
gets around the first limitation but
compounds the second.
To understand this you will need to have a basic understanding of video signals, particularly timing pulses.
Essentially VDC-SPLIT tricks the VDC into drawing 2 (or more) frames in a way that
your monitor interprets and displays them as a single frame. By drawing 2+ “sub-frames” we now have
not one but
two or more locations for those special values to latch!
VDC101 demonstrates this with a smooth XY logo swinger moved entirely by altering the screen/attribute base addresses and X/Y smooth scrolling, while the DYCP scroller underneath remains unaffected –
because it is in a different frame with completely separate values for those registers.This is only possible due to a quirk in the VDC which can be demonstrated from BASIC. (This is exactly what I did to have a little Eureka moment that this might actually work...)
On a real 128 (or Vice 3.4 or later or recent version of Z64k), try the following:
SYS52684,255,7
To restore normal operation do:
SYS52684,29,7
(for a PAL 128 use 32 instead of 29)If you try the above you will notice 2 things:
a) The screen starts rolling uncontrollably. This is because
we have effectively disabled the vertical sync pulse. Your monitor/TV now has no idea where a frame starts or ends.
b) The 2nd and more important thing that happens is what does NOT change –
the VDC keeps drawing the screen. You can still see that SYS line and whatever else was on the screen, it’s still drawing it just like it was before.
Or in other words –
the VDC does not NEED the vertical sync pulse to be enabled to function!So now we know how to disable and re-enable the vertical sync pulse:
1. To disable the pulse put any value in reg #7 higher than reg # 4
2. To enable the pulse again, put a value in reg #7 less than or equal to reg #4.
Knowing this we can now logically divide our screen into 2 or more sub-frames.
NOTE the sub-frames do not have to be the same height! You can (and probably should) alter register # 4 on the fly to change the height of each sub-frame and reg # 6 to vary the number of displayed rows.
BUT.. to achieve a valid video signal, we have to make sure that
the TOTAL HEIGHT of all the sub-frames is the same as our video standard AND
there is only ONE vertical sync pulse across all the sub-frames.
In practise achieving this looks like:
1. Draw sub-frame #1 with no vertical sync pulse. In this frame we setup the base addresses and vertical smooth scroll for sub-frame #2. The simplest way to do this is write the values for the next frame in the active area of the current frame. It is also useful to set the total and displayed height of this sub-frame with Reg #4 & 6 respectively at this point:
- Wait for vblank=0 (so in active area of sub-frame #1)
Set the total height of this sub-frame with reg #4
Set the displayed height of this sub-frame with reg #6
Disable vsync for this sub-frame setting reg #7 > reg #4
Set the screen address of the next sub-frame with reg #12/13
Set the attribute address of the next sub-frame with reg #20/21
NOTE: you don’t have to set registers 12/13 and 20/21 immediately out of vblank but you must set them before we hit the last line of the active area, that is before vblank=1 again.
- Wait for vblank=1 (so in lower border area of sub-frame #1)
Set the vertical smooth scroll of the next sub-frame with reg #24
Set the horizontal smooth scroll of the next sub-frame with reg #25
NOTE: you don’t have to set registers 24/25 immediately in vblank but you must set them before we hit internal row 0 of the VDC in the next sub-frame, that is one character row above vblank=0. Typically 8 raster lines above the top border of the next sub-frame.
2. Repeat above for any intermediate sub-frames if needed. 3. Draw the last sub-frame (e.g. #2) with the vertical sync pulse re-enabled (reg #7 <= reg #4). In this frame we setup the base addresses and vertical smooth scroll for sub-frame #1
The steps below are almost identical to those from step 1 except for the reg # 7 write:- Wait for vblank=0 (so in active area of last sub-frame)
Set the total height of this sub-frame with reg # 4
Set the displayed height of this sub-frame with reg # 6
Enable vsync for this sub-frame setting reg #7 <= reg #4
Set the screen address of sub-frame #1 with reg #12/13
Set the attribute address of sub-frame #1 with reg #20/21
NOTE: you don’t have to set registers 12/13 and 20/21 immediately out of vblank but you must set them before we hit the last line of the active area, that is before vblank=1 again.
- Wait for vblank=1 (so in lower border area of the last sub-frame)
Set the vertical smooth scroll for sub-frame #1 with reg #24
Set the horizontal smooth scroll for sub-frame #1 with reg #25
NOTE: you don’t have to set registers 24/25 immediately into vblank but you must set them before we hit internal row 0 of the VDC in the first sub-frame, that is one character row above vblank=0. Typically 8 raster lines above the top border of sub-frame #1.
4. Loop back to 1.
The above can be done with simple busy-wait loops on VBLANK bit 5 in $d600. This is what VDC101 does.
Now you know how VDC-SPLIT works!
Tokra I doubt it will help you in interlace mode, because you'll wind up with one field in one sub frame and the other field in the other sub frame. Then again maybe you can use that to your advantage? But you may not even know which field is where...
Cheers, Strobe