[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]