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


{
Here is some fade code.   It works in graphics mode as well as text mode. I
have tested it in 80x25 color text mode and 320 x 200 x 256 color graphics
mode (Standard VGA)   The Fade unit is followed by example test program that
shows fading in text mode.   If anyone wants a example for fading in graphics
mode, E-MAIL me.   The only thing I ask you for using this code is that you
E-MAIL me to tell me what you are using it in.   (Well, maybe you could give
me a little credit in the documentation of your program) I didn't write the
SetPalette and GetPalette routines so I don't know what the commented out
CLIs and STIs are for.
My E-MAIL address is ericbrodsky@pslc.psl.wisc.edu
{------------------------------------------------------------------------}
{$R-} {Range checking off (Helps the fade speed)}
{$G+} {286 instructions must be enabled}
unit Fade;

    interface

 type
     TColor =
  record
      R, G, B: byte;
  end;
     TPalette = array [0..255] of TColor;
     Proc = procedure; {Passed to fade procedures}

 procedure SetPalette(Pal: TPalette; First, Last: word);
 procedure GetPalette(var Pal: TPalette; First, Last: word);
 procedure BlackenPalette(First, Last: word);
   {Blackens all colors from First to Last.   Make sure you have the}
   {palette saved in a variable.}
 procedure FadeIn(Pal: TPalette; First, Last: Word; Speed: byte; AProc:
pointer);
   {AProc is called each palette step}
 procedure FadeOut(Pal: TPalette; First, Last: Word; Speed: byte; AProc:
pointer);
   {AProc is called each palette step}

    implementation

 procedure SetPalette(Pal: TPalette; First, Last: word); assembler;
     asm
  MOV   DX, 03DAh
       @Rt:
  IN    AL, DX       { wait for no retrace                 }
  TEST  AL, 8        { this bit is high during a retrace   }
  JZ    @Rt          { so loop until it goes high          }

  MOV   CX, [Last]   { CX = last colour to set             }
  MOV   AX, [First]  { AX = first colour to set            }
  SUB   CX, AX
  INC   CX           { CX = number of colours to set       }
  MOV   DX, 03C8h    { Palette Address register            }
  {CLI}
  OUT   DX, AL       { set starting register               }
  INC   DX           { Palette Data register               }
  PUSH  DS
  LDS   SI, [Pal]    { DS:SI -> palette                    }
  ADD   SI, AX
  ADD   SI, AX
  ADD   SI, AX       { DS:SI -> first entry to set         }
  MOV   AX, CX       { triple the value in CX              }
  ADD   CX, AX
  ADD   CX, AX       { CX = total number of bytes to write }
  REP   OUTSB        { write palette                       }
  {STI}
  POP   DS
     end;

 procedure GetPalette(var Pal: TPalette; First, Last: word); assembler;
     asm
    MOV   CX, [Last]     { CX = last colour                    }
    MOV   AX, [First]    { AX = starting colour                }
    SUB   CX, AX
    INC   CX             { CX = number of colours              }
    MOV   DX, 03C7h      { Palette Address register            }
    {CLI}
    OUT   DX, AL         { set starting register               }
    INC   DX
    INC   DX             { DX = Palette Data register          }
    LES   DI, [Pal]      { ES:DI -> palette                    }
    ADD   DI, AX
    ADD   DI, AX
    ADD   DI, AX         { ES:DI -> first entry to read        }
    MOV   AX, CX         { triple the value in CX              }
    ADD   CX, AX
    ADD   CX, AX         { CX = total number of bytes to read  }
    REP   INSB           { Read  palette                       }
    {STI}
     end;

 procedure BlackenPalette(First, Last: word);
     var
  Pal: TPalette;
  i: word;
     begin
  for i := First to Last do
      begin
   Pal[i].R := 0; Pal[i].G := 0; Pal[i].B := 0;
      end;
  SetPalette(Pal, First, Last);
     end;

 procedure FadeIn(Pal: TPalette; First, Last: Word; Speed: byte; AProc:
pointer);
     var
  i, j    : Byte;
  TempPal : TPalette;
     begin
  for i := 0 to Speed do
      begin
   for j := First to Last do
       begin
    TempPal[j].R := Pal[j].R * i div Speed;
    TempPal[j].G := Pal[j].G * i div Speed;
    TempPal[j].B := Pal[j].B * i div Speed;
       end;
   Setpalette(TempPal, First, Last);
   if (AProc <> nil) then Proc(AProc);
      end;
     end;

 procedure FadeOut(Pal: TPalette; First, Last: Word; Speed: byte; AProc:
pointer);
     var
  i, j    : Byte;
  TempPal : TPalette;
     begin
  TempPal := Pal;
  for i := Speed downto 0 do
      begin
   for j := First to Last do
       begin
    TempPal[j].R := Pal[j].R * i div Speed;
    TempPal[j].G := Pal[j].G * i div Speed;
    TempPal[j].B := Pal[j].B * i div Speed;
       end;
   Setpalette(TempPal, First, Last);
   if (AProc <> nil) then Proc(AProc);
      end;
     end;
    end.

{---------------------------------------------------------------------}

program FadeTest;
    uses
 CRT,
 Fade;
    const
 FadeSpeed1 = 64;

 FadeSpeed2 = 64;
    var
 Pal : TPalette;
 i : longint;
    procedure aProcedure; far;
      {This procedure will be called every fade step}
 begin
     Inc(i);
     writeln('Test 2 of Ethan Brodsky''s fade routines:   Fade Step #',
                    i);
 end;
    begin
 GetPalette(Pal, 0, 255);

 {Test part 1}
 BlackenPalette(0, 255);
 writeln('Test 1 of Ethan Brodsky''s fade routines');
 FadeIn(Pal, 0, 255, FadeSpeed1, nil);
 FadeOut(Pal, 0, 255, FadeSpeed1, nil);
 FadeIn(Pal, 0, 255, FadeSpeed1, nil);

 writeln('Press any key to continue . . .');
 repeat until KeyPressed;

 {Test part 2}
 i := 0;
 FadeOut(Pal, 0, 255, FadeSpeed2, @aProcedure);
 i := 0;
 FadeIn(Pal,  0, 255, FadeSpeed2, @aProcedure);
    end.


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