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

{
> I've seen few times an effect which fades the DOS screen before demo or
> something, how's it done?
> And how can I freeze DOS screen to memory so that I can write it again
> after demo or game has ended?
> And I want to know other that kind of 'effects' (or what ever they are
> called..)..

Here's some bits & pieces from a VGA library I'm writing... note that the fades
only work on VGA....
}

{$G+} {Yes, it does unfortunately use 286 opcodes to eliminate snow. Sorry.}
Program VGA_Stuff;
Uses Crt;
Type
 CharAttr=Record  {How a character looks in screen memory}
  Ch:Char;        {The character to display}
  Attr:Byte;      {The foreground+(background*16). bright backgrounds=flashing}
 End;

 TextScreen=Array[1..25,1..80] Of CharAttr;
                  {This represents 1 screen. Note the Y,X order}

 DAC_Trio=Record
  Red,Green,Blue:Byte;
 End;             {One pallette register. Note that it's always in that order}

Var
 Physical_TScreen:TextScreen Absolute $B800:0; {The real screen}
 Starting_TScreen:TextScreen;                  {Another screen, in memory}

Procedure WaitForRetrace;
 {Waits for vertical retrace. This is to assure the same speed across all PCs,
  and to eliminate interference. Waits at most 1/70th of a second.}
Begin
 Asm
  MOV  DX,$3DA;
@Wait1:
  IN   AL,DX
  TEST AL,8         {retrace hapening?}
  JNZ   @Wait1      {Yep, wait for it to end}
@Wait2:
  IN   AL,DX
  TEST AL,8         {Retrace happening?}
  JZ  @Wait2        {nope, wait to finish}
 End
End;

Procedure SetPal(Var P; Start:Byte; Count:Word);
{P is an array of DAC_Trio's, set up with the colours we want.
 The start is the first colour to set, the count is how many. Note that there's
only 256 registers, so count should be no more than 256. Also, they will wrap
round; starting at 128 & count=256 will set the register 128 to the first trio,
and so forth, till the last trio at 127.}
Begin
 WaitForRetrace; {To eliminate snow.}
 Asm
  MOV  DX,$3C8
  MOV  AL,Start
  OUT  DX,AL
  INC  DX
  MOV  BX,DS
  LDS  SI,P
  MOV  CX,Count
  ADD  CX,Count
  ADD  CX,Count
  REP  OUTSB
  MOV  DS,BX
 End;
End;

Procedure GetPal(Var P; Start:Byte; Count:Word);
{Gets a number of pallette registers. P should be an array of DAC_Trio's, start
 should be the first one to get, and count should be the number of registers to
get.}Begin
 Asm
  MOV  DX,$3C7
  MOV  AL,Start
  OUT  DX,AL
  INC  DX
  INC  DX
  MOV  BX,ES
  LES  DI,P
  MOV  CX,Count
  ADD  CX,Count
  ADD  CX,Count
  REP  INSB
  MOV  ES,BX
 End;
End;

Procedure Fade_Out;
{Gets the current pallette & fades it out.}
Var
 Pal:Array[0..255] Of Dac_Trio;
 Loop1,Loop2:Byte;
Begin
 GetPal(Pal,0,255);
 For Loop1:=1 To 64 Do
  Begin
   For Loop2:=0 To 255 Do
    Begin
     If Pal[Loop2].Red>0 Then
      Dec(Pal[Loop2].Red);
     If Pal[Loop2].Green>0 Then
      Dec(Pal[Loop2].Green);
     If Pal[Loop2].Blue>0 Then
      Dec(Pal[Loop2].Blue);
    End;
   WaitForRetrace;
   {Put WaitForRetrace; here to slow it down to suit. Each one slows it down
    one screenframe}
   SetPal(Pal,0,255);
  End;
End;

Procedure Fade_In(Var P);
{Fades the screen in from black to whatever colours are set in P. P should be
an array of DAC_Trio's}Var
 NewPal:Array[0..255] Of Dac_Trio Absolute P;
 Pal:Array[0..255] Of Dac_Trio;
 Loop1,Loop2:Byte;
Begin
 FillChar(Pal,SizeOf(Pal),0); {Set to black}
 SetPal(Pal,0,256);
 For Loop1:=63 DownTo 0 Do
  Begin
   For Loop2:=0 To 255 Do
    Begin
     If NewPal[Loop2].Red>Loop1 Then
      Inc(Pal[Loop2].Red);
     If NewPal[Loop2].Green>Loop1 Then
      Inc(Pal[Loop2].Green);
     If NewPal[Loop2].Blue>Loop1 Then
      Inc(Pal[Loop2].Blue);
    End;
   {Put WaitForRetrace; here to slow it down to suit. Each one slows it down
    one screenframe}
   WaitForRetrace;
   SetPal(Pal,0,255);
  End;
End;

Var Loop:Word;
    Orig_Pal:Array[0..255] Of Dac_Trio;

Begin
 Starting_TScreen:=Physical_TScreen;  {Make a copy of the origonal screen}
 GetPal(Orig_Pal,0,256);              {Make a copy of origonal pallette}

 For Loop:=1 To 4000 Do
  Mem[$B800:Loop]:=Random(127); {Fill screen with garbage!}

 Fade_Out;
 Physical_TScreen:=Starting_TScreen;  {Restore origonal screen}

 Fade_In(Orig_Pal);                   {Fade in to origonal colours}
End.

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