Hi,
AhmadTayseerDajani wrote:anyway i need some things to kill flicker in screen mode 0x12.
Before you blit the buffer to display memory, you could wait for vertical retrace to start. Note: "vertical retrace" is the time it takes the video card's signal to go from the bottom right corner of the screen to the top left corner of the screen; where the video isn't using video display memory (and where you can change video display memory without worrying about half a frame being displayed, or sheering effects, or flicker).
The code goes something like this:
Code: Select all
mov dx, 0x03DA ;dl = VGA misc register #1
.l1: in al, dl ;al = value from VGA misc register #1
test al, 8 ;Is the "retrace not in progress" bit set?
jnz .l1 ; yes, wait until the retrace isn't in progress
.l2: in al, dl ;al = value from VGA misc register #1
test al, 8 ;Is the "retrace not in progress" bit set?
jnz .l2 ; no, wait until the retrace is in progress
There's 2 problems here:
- It can waste a lot of CPU time. The retrace would happen 60 times per second for standard 640 * 480 VGA mode, so you could waste up to 16.66 ms of CPU time while you're waiting for the retrace to start, which adds up to millions of cycles for modern computers.
- The blit may be too slow to update all 4 planes before the retrace ends (especially on old/slow computers). In this case you'd get flicker even though you are waiting for retrace to start.
To avoid the first problem you could try using a vertical retrace IRQ, but that's non-standard (not supported most of the time). However, it is possible to use some other timer to emulate a vertical retrace IRQ. For example, you'd wait for the vertical retrace to start (like above), then program the PIT chip to generate an IRQ in about 10 ms time. When the PIT IRQ occurs you'd wait for retrace to start again (but it'd only take about 2 ms because you've been running other code for 10 ms), reprogram the PIT again, etc. You can also dynamically adjust the PIT timer's delay to reduce the time spent polling as much as possible (just be careful of "IRQ jitter").
To avoid the second problem (and to reduce the time spend in the vertical retrace IRQ handler, if used) it's possible to use page flipping. The idea is that you use two areas in video display memory - an "active" area that the video card is displaying and a "work" area that you can modify without worrying much about (because it isn't being displayed). When you're ready to display the next frame it's already in display memory, and all you do is reprogram the VGA's "Start Address High Register" and "Start Address Low Register" so that the "work" area becomes the "active" area and the "active" area becomes the "work" area. This method requires more video display memory, but all modern video cards will have enough video display memory anyway. Another option would be to use dirty rectangles or some other way to avoid updating parts of video display memory that didn't change since last time.
You could also combine all of the above. For example, you draw data into your buffer in RAM (while keeping track of which areas were modified), and when you're ready you blit areas that did change from your buffer in RAM to the "work" buffer in video display memory, and then your (real or emulated) vertical retrace IRQ does a "page flip" during the next vertical retrace to make the new frame visible.
Of course all of this may be overkill - the extra complexity may or may not be worth the hassle...
Cheers,
Brendan