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

    {
    >I want to write a routine to scroll text smoothly i.e. pixel wise. This
    >might be ambitious as I know almost nothing about pogramming the display
    >card, but I have two theories. The one will work, but is very long
    >winded. Please advise me on a course of action.

    >BTW, can anyone recommend any good books on topics such as the above,
    >i.e. advanced graphics programming etc. When giving advice please
    >remember my coding ability is way behind the ability to figure
    >algorithms.

    One of the best books I've read is PC and PS/2 video systems by
    microsoft press (if I/'m correct). It deals with a lot of great topics
    like graphs in textmode and the differences between video cards.

    The best way to start it is to re-program the starting line of the
    display. This way you've got hardware scrolling in textmode. Only
    program is when & were to insert a new line.

    I know that PC-magazine once published a smooth scrolling routine in
    textmode. This one should contain all info you need.

    Btw here's a small demo of how to re-program the starting line of a
    E/VGA card. Once re-programmed you see the second text page of the E/VGA
    card.

    {---------------------------------------------------------}
    {  Project : Split screen for EGA & VGA                   }
    {  Auteur  : Wim van der Vegt                             }
    {---------------------------------------------------------}
    {  Datum .tijd  Revisie                                   }
    {  910505.1645  Creatie.                                  }
    {---------------------------------------------------------}

    Program split(INPUT,OUPUT);

    {----Source of information :

         Programmer's Guide to PC & PS/2 Video Systems, by Microsoft press

    }

    uses
      crt,
      dos,
      graph;

    VAR
      vgacard  : BOOLEAN;
      gvmax,
      tvmax    : INTEGER;
      r        : Registers;
      grmode,
      grdriver : INTEGER;

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

    var
      v,i,j    : integer;

    const
      CRTC_adr = $3D4;
      CRTC_dat = $3D5;

    {---------------------------------------------------------}
    {----Wait for vertical retrace                            }
    {---------------------------------------------------------}

    procedure V_retrace; inline($BA/$DA/$03/ { mov dx,$03DA   }
                                $EC/         { in al,dx   <-\ }
                                $A8/$08/     { test al,8    | }
                                $75/$FB/     { jnz >--------/ }
                                $EC/         { in al,dx   <-\ }
                                $A8/$08/     { test al,8    | }
                                $74/$FB);    { jz >---------/ }

    {---------------------------------------------------------}
    {----Sets re-start line for CRTC controller               }
    {---------------------------------------------------------}

    procedure CRTC_split(i : WORD);

    VAR
      b : BYTE;

    begin
      V_retrace;
      IF vgacard
        THEN
          BEGIN
            port[CRTC_adr]:=$09; b:=port[CRTC_dat];
            port[CRTC_adr]:=$09; port[CRTC_dat]:=BYTE(b AND $BF)+(BYTE(i DIV 512)) ;
            port[CRTC_adr]:=$18; port[CRTC_dat]:=BYTE(i MOD 256);
            port[CRTC_adr]:=$07; b:=port[CRTC_dat];
            port[CRTC_adr]:=$07; port[CRTC_dat]:=BYTE(b AND $ef)+BYTE((i DIV 256)) ;
          END
        ELSE
          BEGIN
            port[CRTC_adr]:=$18; port[CRTC_dat]:=i MOD 256;
            port[CRTC_adr]:=$07; port[CRTC_dat]:=$ef+((BYTE(i DIV 256) MOD 2) SHL 4)
           END;
    end; {of CRTC_split}

    {---------------------------------------------------------}
    {----Sets display start address for CRTC controller       }
    {---------------------------------------------------------}

    procedure CRTC_start(i : word);

    begin
      port[CRTC_adr]:=$0d; port[CRTC_dat]:=i mod 256;
      port[CRTC_adr]:=$0c; port[CRTC_dat]:=i div 256;
    end; {of CRTC_start}

    {---------------------------------------------------------}
    {----Resets the screen split                              }
    {---------------------------------------------------------}

    PROCEDURE Unsplit;

    BEGIN
      CRTC_start(0);
      CRTC_split($1ff);
    END;

    {---------------------------------------------------------}
    {----Graphic mode, mouse controlled screen split          }
    {---------------------------------------------------------}

    Procedure do_graph_split;

    begin
    {----get motion count from mouse}
      r.ax:=$000B;
      INTR($33,r);
      v:=v+INTEGER(r.dx);

      if v>gvmax THEN v:=gvmax;
      if v<0     THEN v:=0;
      IF v>0
        THEN
        {----By adjusting this value according to v,
             the two EGA/VGA graphic screens will be linked}
          begin
          {----Second Graph Screen 32K after start of First Screen}
            CRTC_start($8000);
            CRTC_split(v);
          end
        ELSE Unsplit;
    end;

    {---------------------------------------------------------}
    {----Text mode, mouse controlled screen split             }
    {---------------------------------------------------------}

    Procedure do_text_split;

    begin
    {----get motion count from mouse}
      r.ax:=$000B;
      INTR($33,r);
      v:=v+INTEGER(r.dx);

      if v>tvmax THEN v:=tvmax;
      if v<0     THEN v:=0;
      IF v>0
        THEN
          begin
          {----Second text Screen 4K after start of First Screen}
            CRTC_start($1000);
            CRTC_split(v);
          end
        ELSE Unsplit;
    end;

    {=========================================================}

    BEGIN
    {----Screen must be EGA or VGA}
      grdriver:=detect;
      Detectgraph(grdriver,grmode);
      vgacard:=(grdriver=vga);

    {----Graphics Mode, watch out,
         VGA hasn'got two pages in 640x480 graphics mode,
         switch to EGA 640x350 mode if you want two full pages,
         and change gvmax below from 479 to 349}

      IF vgacard
        THEN gvmax:=479
        ELSE gvmax:=349;

    {----Text Mode, VGA in text mode has 400 lines (So NOT 480 lines !!) }
      IF vgacard
        THEN tvmax:=399
        ELSE tvmax:=349;

      IF (grdriver<>vga) AND (grdriver<>ega)
        THEN
          BEGIN
            Writeln('Ega or Vga Card NOT Found');
            Halt;
          END;

    {----Text mode demo #1}
      FOR i:=0 TO 80*25 DO
        BEGIN
          MEMW[$B800:i*2]:=$0F30;
          MEMW[$B900:i*2]:=$3031;
        END;

    {----Oscillating Screen Split}
      CRTC_start($1000);
      for i:=8 to 192 do CRTC_split( round(175-175*cos(i/30*pi)*(8/i)) );
      Delay(1000);

    {----Accelerating screen split}
      for i:=3*175 downto 16 do CRTC_split( Trunc(175-(175/i)*16) );
      Delay(1000);
      Unsplit;

    {----Text mode demo #2 & Graphics demo #1 need a mouse}
      r.ax:=$0000;
      INTR($33,r);
      IF (r.ax=0)
        THEN
          BEGIN
            Writeln('Microsoft mouse NOT Found');
            Halt;
          END;

    {----Text mode demo #2}
      GotoXY(10,09);
      Write('                                                           ');
      GotoXY(10,10);
      Write('  Now Move your mouse up and down and see text page 0 & 1  ');
      GotoXY(10,11);
      Write('            Press SPACE key to exit this demo              ');
      GotoXY(10,12);
      Write('                                                           ');

      v:=50;
      WHILE NOT(keypressed AND (Readkey=#32)) DO Do_text_split;
      Unsplit;

    {----Graphic Mode Demo #1, works best on EGA and VGA in EGA mode}
      grdriver:=ega;
      grmode:=egahi;
      Initgraph(grdriver,grmode,'e:\bp\bgi');
      Setcolor(blue);
      FOR i:=0 TO gvmax DO
        FOR j:=0 TO 39 DO
          memw[$a000:WORD(i*80)+2*j]:=$1000;
      Setcolor(red);
      FOR i:=0 TO gvmax DO
        FOR j:=0 TO 39 DO
          memw[$a800:WORD(i*80)+2*j]:=$0010;
      Setcolor(white);
      Outtextxy(10,10,'  This is Graphic page 0, Move your mouse & press space to e');
      Rectangle(0,0,639,gvmax);
      Setactivepage(1);
      Outtextxy(10,10,'  This is Graphic page 1  ');
      Rectangle(0,0,639,gvmax);

      v:=50;

      WHILE NOT(keypressed AND (Readkey=#32)) DO Do_graph_split;
      Unsplit;

      Closegraph;
    END.

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