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

{
MARK DIXON

Um, have a look at this, and see what you can come up with. It's some code I
wrote a while back to use mode-x and do double buffering (or page-flipping).
}

Program Test_ModeX;

Uses
  crt;


{ This program will put the VGA card into a MODEX mode (still only 320x200)
  and demonstrate double buffering (page flipping)

  This program was written by Mark Dixon, and has been donated to the
  Public Domain with the exception that if you make use of these routines,
  the author of these routines would appreciate his name mentioned somewhere
  in the documentation.

  Use these routines at your own risk! Because they use the VGA's registers,
  cards that are not 100% register compatible may not function correctly, and
  may even be damaged. The author will bear no responsability for any actions
  occuring as a direct (or even indirect) result of the use of this program.

  Any donations (eg Money, Postcards, death threats.. ) can be sent to  :

  Mark Dixon
  12 Finchley St
  Lynwood,
  Western Australia
  6147

  If you have Netmail access, then I can also be contacted on 3:690/660.14

  }

Const
  Page : Byte = 0;

Var
  I, J : Word;


Procedure InitModeX;
{ Sets up video mode to Mode X (320x200x256 with NO CHAIN4) making available
  4 pages of 4x16k bitmaps }
Begin
  asm
    mov    ax, 0013h    { Use bios to enter standard Mode 13h }
    int    10h
    mov    dx, 03c4h    { Set up DX to one of the VGA registers }
    mov    al, 04h      { Register = Sequencer : Memory Modes }
    out    dx, al
    inc    dx           { Now get the status of the register }
    in     al, dx       { from the next port }
    and    al, 0c7h     { AND it with 11000111b ie, bits 3,4,5 wiped }
    or     al, 04h      { Turn on bit 2 (00000100b) }
    out    dx, al       { and send it out to the register }
    mov    dx, 03c4h    { Again, get ready to activate a register }
    mov    al, 02h      { Register = Map Mask }
    out    dx, al
    inc    dx
    mov    al, 0fh      { Send 00001111b to Map Mask register }
    out    dx, al       { Setting all planes active }
    mov    ax, 0a000h   { VGA memory segment is 0a000h }
    mov    es, ax       { load it into ES }
    sub    di, di       { clear DI }
    mov    ax, di       { clear AX }
    mov    cx, 8000h    { set entire 64k memory area (all 4 pages) }
    repnz  stosw        { to colour BLACK (ie, Clear screens) }
    mov    dx, 03d4h    { User another VGA register }
    mov    al, 14h      { Register = Underline Location }
    out    dx, al
    inc    dx           { Read status of register }
    in     al, dx       { into AL }
    and    al, 0bFh     { AND AL with 10111111b }
    out    dx, al       { and send it to the register }
                        { to deactivate Double Word mode addressing }
    dec    dx           { Okay, this time we want another register,}
    mov    al, 17h      { Register = CRTC : Mode Control }
    out    dx, al
    inc    dx
    in     al, dx       { Get status of this register }
    or     al, 40h      { and Turn the 6th bit ON }
    out    dx, al       { to turn WORD mode off }
                        { And thats all there is too it!}
  End;
End;


Procedure Flip;
{ This routine will flip to the next page, and change the value in
  PAGE such that we will allways be drawing to the invisible page. }
Var
  OfsAdr : Word;
Begin
  OfsAdr := Page * 16000;
  asm
    mov    dx, 03D4h
    mov    al, 0Dh      { Set the Start address LOW register }
    out    dx, al
    inc    dx

    mov    ax, OfsAdr
    out    dx, al       { by sending low byte of offset address }
    dec    dx
    mov    al, 0Ch      { now set the Start Address HIGH register }
    out    dx, al
    inc    dx
    mov    al, ah
    out    dx, al       { by sending high byte of offset address }
  End;

  Page := 1 - Page;     { Flip the page value.
                          Effectively does a :
                          If Page = 0 then Page = 1 else
                          If Page = 1 then Page = 0.       }
End;



Procedure PutPixel (X, Y : Integer; Colour : Byte );
{ Puts a pixel on the screen at the current page. }
Var
  OfsAdr : Word;
BEGIN
  OfsAdr := Page * 16000;
  ASM
    mov    bx, x
    mov    ax, Y
    mov    cx, 80     { Since there are now 4 pixels per byte, we
                        only multiply by 80 (320/4) }
    mul    cx
    mov    di, ax
    mov    ax, bx
    shr    ax, 1
    shr    ax, 1
    add    di, ax
    and    bx, 3
    mov    ah, 1
    mov    cl, bl
    shl    ah, cl

    mov    al, 2
    mov    dx, 03C4h

    mov    bx, $A000
    mov    es, bx
    add    di, OfsAdr

    out    dx, ax        { Set plane to address (where AH=Plane) }
    mov    al, Colour
    mov    es:[di], al
  end;
end;

Begin
  Randomize;
  InitModeX;
  Flip;

  For I := 0 to 319 do
    For J := 0 to 199 do
      PutPixel(I, J, Random(32) );
  Flip;

  For I := 0 to 319 do
    For J := 0 to 199 do
      PutPixel(I, J, Random(32) + 32);

  Repeat
    Flip;
    Delay(200);
  Until Keypressed;

End.

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