[Back to GRAPHICS SWAG index]  [Back to Main SWAG index]  [Original]

{
>> You are using THREE different screens (no problem in x-mode).
>> One (A) is displayed, second (B) is waiting, third (C) is
>> being drawn. After third C is ready B is being displayed
>> and A is being drawn. No flickering, no waiting, no
>> problem...

> That makes sense.  Is there anyway to hook an interrupt
> to the vertical retrace to keep it automatic?

Yes, and no - it depends on VGA card. In theory it should be able to generate
IRQ 2 on retrace, but in fact one nevr now what's going on in a particular
computer. Sometimes it can be changed by a jumper on a VGA card, sometimes
not...

> (By the way, it still would be limited to the Vert retrace because you
> can't change from a to b until there is a Retrace, so you would just
> allow more variety in speed of drawing screens with triple buffering
> (ie. you can draw one fast and one really slow (alternating) if the total
> of both is less than two vertical retraces)).

One program is worth a thousand words ;-)
}

program buffexm;

{ Example of a double and tripple buffering in video memory.
  (c) by Borek (Marcin Borkowski), 2:480/25. Program is
  slow because of primitive drawbox procedure, but precisely
  shows how to use dbl and trpl buffering to achieve perfect,
  non-flickering screen displays. }

uses crt;

const
  speed = 40; { Speed of a program - lover values, faster action.
                As effect depends on your computer speed, try to
                experiment with this value. }

var
  scrofs,time : word;

procedure Enter4PlaneMode; { so called x-mode }
begin
  Port[$3CE]:=5;   Port[$3CF]:=Port[$3CF] and $FB;
  Port[$3CE]:=6;   Port[$3CF]:=Port[$3CF] and $FD;
  Port[$3C4]:=4;   Port[$3C5]:=(Port[$3C5] and $F7) or 4;
  Port[$3D4]:=$14; Port[$3D5]:=Port[$3D5] and $BF;
  Port[$3D4]:=$17; Port[$3D5]:=Port[$3D5] or $40;
end;

procedure SetStartAddress(w : word);
begin
{ Sets start address of displayed video memory. }
  Port[$3D4]:=$0C; Port[$3D5]:=Hi(w);
  Port[$3D4]:=$0D; Port[$3D5]:=Lo(w);
end;

procedure WaitForRetrace;
begin
  repeat until (port[$03DA] and 8)=8;
  repeat until (port[$03DA] and 8)=0
end;

procedure clrscreen(a : word);
begin
{ Fills all bitplanes at once with zeros, but only in
  a part of video memory. }
  Port[$3C4]:=2;  Port[$3C5]:=$0F;
  fillchar(mem[$A000:a],16384,#0);
end;

procedure drawbox(x,y : word;c : byte);
var
  i,j,a : word;
begin
{ Port writes are used to define which bitplane is used. }
  Port[$3C4]:=2;
  for i:=x to x+10 do
  begin
    Port[$3C5]:=1 shl (i and 3);
    a:=scrofs+i div 4+80*y;
    for j:=y to y+10 do
    begin
      mem[$A000:a]:=c;
      inc(a,80)
    end;
  end;
end;

procedure animate1;
{ No buffering example. }
var
  x,y : integer;
begin
  repeat
    clrscreen(0);
    drawbox(round(150+60*cos(time/speed)),
            round(90+60*sin(time/speed)),7);
{   WaitForRetrace;  Try with and without. Effect depends }
    inc(time)       { on your computer speed. }
  until keypressed;
end;

procedure animate2;
{ Double buffering example. There are two virtual screens -
  one at $A000:0, second at $A000:$4000 }
var
  x,y  : integer;
begin
  repeat
    clrscreen(scrofs);
    drawbox(round(150+60*cos(time/speed)),
            round(90+60*sin(time/speed)),15);
    inc(time);
    setstartaddress(scrofs);
    WaitForRetrace; { Screen is flickering without this. }
    scrofs:=$4000-scrofs;
  until keypressed;
end;

procedure animate3;
{ Triple buffering example. In fact there are four virtual screens,
  at $A000:0, $A000:$4000, $A000:$8000 and at $A000:$C000, but if you
  use three screens the effect will remain the same.
  No waiting for retrace, no flickering. Speed of rectangle moves
  depends _only_ on a computer speed. You may add WaitForRetrace to
  allow synchronization. }
var
  x,y  : integer;
begin
  repeat
    clrscreen(scrofs);
    drawbox(round(150+60*cos(time/speed)),
            round(90+60*sin(time/speed)),13);
    inc(time);
    setstartaddress(scrofs);
    inc(scrofs,$4000);
  until keypressed;
end;

begin
  asm mov ax,13h; int 10h end;
  enter4planemode;
  time:=0;
  animate1; readkey; { Fast, but always flickers }
  animate2; readkey; { No flickering but slow - must wait for retrace }
  animate3; readkey; { Same speed as in animate1, no flickering }
  asm mov ax,03h; int 10h end;
end.


[Back to GRAPHICS SWAG index]  [Back to Main SWAG index]  [Original]