Scroll tekstu w trybie 13H

    -- Sebastian Pawlak, PCkurier 27/1996.


Każdy na pewno spotkał się z pojęciem, lub też widział w jakimś programie SCROLLING tekstu. Płynnie przesuwające się po ekranie napisy, często wzbogacone o dodatkowe efekty, jak np. falowanie. W tej pracy zajmę się opisem uzyskania przedstawionego powyżej efektu. Rzecz jasna będzie to najprostszy do wykonania przykład z wykorzystaniem fontów systemowych, gdyż oczywiste jest, że listing scrollingu na wysokim poziomie zajął by objętościowo kilkadziesiąt razy więcej miejsca. Nic nie stoi jednak na przeszkodzie żeby na własną rękę udoskonalić program przykładowy, ponieważ w przypadku bardziej skomplikowanych scrollingów idea działania nie zmienia się.



Pobierz plik scroll.zip

Oto działanie programu: 

REPEAT {Pętla}
1. Synchronizuje wyświetlanie obrazu z wygaszaniem ekranu.
2. W kolumnie o współrz. 319 wyświetla jedną kolumnę znaku.
3. Przesuwa obszar o rozmiarze [szerokość obrazu (320) * wysokość znaku (8)]
   jedną kolumnę w lewo.
4. Czyści obszar o współrz. poziomej 0 i wysokości 8 tak aby
   przesuwany tekst po osiągnięciu lewej strony ekranu nie
   wchodził na znak świeżo wyświetlany.
5. Żeby było bardziej atrakcyjnie po przesunięciu tekstu wyświetlamy rysunek.
UNTIL KeyPressed;

Cykl powtarza się ...

Bardzo ważna jest przeprowadzana w pierwszym punkcie synchronizacja wyświetlania obrazu z wygaszaniem ekranu (tzn. wyświetlamy i przesuwamy tekst dopiero wtedy gdy wiązka elektronów zakończy kreślenie linii i wraca na początek kolejnego wiersza ekranu), gdyż bez tego scrolling będzie działał bardzo nierównomiernie. Aby przeprowadzić eksperyment proszę usunąć wywołanie procedury SYNCHRONIZACJA; - udowodni to niezbędność stosowania synchronizacji. Korzystając z rozwiązań, które zawarłem w tym przykładzie udało mi się stworzyć przesuw tekstu z:

literami o wysokości 50 pixeli, 
każda litera miała inną szerokość, 
na litery nałożyłem bitmapę, 
scroll mógł działać z różnymi prędkościami, dzięki
  wyświetlaniu 2, 3 lub 4 kolumn znaku w jednym cyklu,
  a nie jednego jak to ma miejsce w przykładzie. 


W pliku " SCROLL.TXT" należy wpisać treść tekstu, która ma być wyświetlona przez program.

{Scroll tekstu w trybie 13H}
{autor: Sebastian Pawlak}
{1995 sierpień}
Program Scroll;
Uses Crt,Dos;
Var RozmiarTekstu     :Word;
    Pozycja_w_Tekscie :Word;
    Pozycja_w_Znaku   :Byte;
    Tekst             :Array [0..1000] of char;
    Wiersz            :String;
    PisakX,PisakY     :Integer;
    Rys               :Byte;
    Kolor             :Byte;
    i                 :Integer;

{Współrzędne punktów kreślonego rysunku.}
Const Pkt :Array [0..96] of Integer=
 ( -1,0, 01,5, 01,1, 03,1, 03,3, 01,3, -1,0,
   07,5, 05,5, 05,1, 07,1, -1,0,
   11,1, 11,5, -1,0, 13,1, 11,3, 13,5, -1,0,
   14,1, 14,5, 16,5, 16,1, -1,0,
   17,5, 17,1, 19,1, 19,3, 17,3, 19,5, -1,0,
   20,1, 20,5, -1,0,
   23,1, 21,1, 21,5, 23,5, -1,0, 23,3, 21,3, -1,0,
   24,5, 24,1, 26,1, 26,3, 24,3, 26,5, -2);

{Ustawia podany tryb graficzny.}
Procedure InitGraph (Tryb:Byte); Assembler;
asm
 mov ah,0
 mov al,Tryb
 int 10h
end;

{Procedura wczytująca tekst zawarty w pliku}
{SCROLL.TXT do pamięci.}
Procedure WczytajTekst;
Var Plik     :Text;
    PlikInfo :SearchRec;
Begin
 {$I-}
 Assign (Plik,\'SCROLL.TXT\');
 Reset (Plik);
 If IoResult<>0 then
 Begin
  Writeln (\'Mam problemy z dost?pem do pliku !\');
  Halt (1);
 End;
 RozmiarTekstu:=0;
 Repeat
  ReadLn (Plik,Wiersz);
  For i:=RozmiarTekstu to RozmiarTekstu+Length (Wiersz) do
    Tekst [i]:=Wiersz [i-RozmiarTekstu+1];
  Inc (RozmiarTekstu,Length (Wiersz));
 Until Eof (Plik);
 Close (Plik);
 {$I+}
End;

{Funkcja zwracająca wartość określonej komórki}
{pamięci.}
Function Adres (_Seg,_Ofs:word):Byte;
Var Zwrot :Byte;
Begin
 Asm
  push es
  mov ax,_Seg
  mov es,ax
  mov di,_Ofs
  mov al,es:[di]
  mov Zwrot,al
  pop es
 End;
 Adres:=Zwrot;
End;

{Wyświetla punkt o współrzędnych X,Y i kolorze Kolor.}
Procedure PutPixel (X,Y:word;Kolor:byte); Assembler;
Asm
 push es
 mov ax,0A000h
 mov es,ax
 mov ax,X
 mov bx,Y
 mov cl,6
 shl bx,cl
 mov cx,bx
 shl bx,1
 shl bx,1
 add bx,cx
 add bx,ax
 mov dl,Kolor
 mov es:[bx],dl
 pop es
End;

{Zsynchronizowanie wyświetlania obrazu z}
{wygaszaniem ekranu.}
Procedure Synchronizacja; Assembler;
Asm
 mov dx,03dah
@Czekaj:
 in al,dx
 test al,8
 je @Czekaj
End;

{Prcedura wyświetla jedną kolumnę znaku i}
{przesuwa scroll o jeden pixel w lewo.}
Procedure PrzesunScroll;
Var Wiersz :Byte;
Begin
 For i:=0 to 7 do
 Begin
  Wiersz:=(Adres ($0F000,$0FA6E+Ord (
    Tekst [Pozycja_w_Tekscie])*8+i) shl Pozycja_w_Znaku);
  If Wiersz and 128<>0 then
    PutPixel (319,96+i,57+i);
 End;
 Inc (Pozycja_w_Znaku);
 If Pozycja_w_Znaku=8 then
 Begin
  Pozycja_w_Znaku:=0;
  Inc (Pozycja_w_Tekscie);
  If Pozycja_w_Tekscie=RozmiarTekstu then
    Pozycja_w_Tekscie:=0;
 End;

 {Przesunięcie scrollu.}
 Asm
  push ds
  push es
  mov ax,0A000h
  mov es,ax
  mov di,96*320
  mov ds,ax
  mov si,96*320+1
  mov cx,320*8
  rep movsb
  pop es
  pop ds
 End;
 For i:=0 to 7 do PutPixel (0,96+i,0);
End;

Begin
 WczytajTekst;
 InitGraph ($13);
 Pozycja_w_Tekscie:=0;
 Pozycja_w_Znaku:=0;
 Rys:=0;

 {Pętla główna.}
 Repeat
  {Synchronizacja, szybkie wyświetlenie i}
  {przesunięcie tekstu.}
  Synchronizacja;
  PrzesunScroll;
  {Dzięki zastosowaniu procedury przesuwającej}
  {scroll o jeden punkt i zwracającej sterowanie}
  {do głównej pętli programu, możemy równocześnie}
  {wykonywać inne czynności, np rysować.}
  If Pkt [Rys*2]=-1 then
  Begin
   Inc (Rys);
   PisakX:=Pkt [Rys*2]*10;
   PisakY:=Pkt [rys*2+1]*10;
  End;

  PutPixel (PisakX+30,PisakY+23,Kolor xor 0);
  PutPixel (PisakX+30,PisakY+127,Kolor xor 15);
  If Pkt [Rys*2]*10>PisakX then Inc (PisakX);
  If Pkt [Rys*2]*10<PisakX then Dec (PisakX);
  If Pkt [Rys*2+1]*10>PisakY then Inc (PisakY);
  If Pkt [Rys*2+1]*10<PisakY then Dec (PisakY);

  If ((Pkt [Rys*2]*10=PisakX)and(Pkt [Rys*2+1]*10=PisakY))
    then Inc (Rys);

  If Pkt [Rys*2]=-2 then
  Begin
   Rys:=0;
   If Kolor=0 then Kolor:=15 else Kolor:=0;
  End;
 Until KeyPressed;
 InitGraph ($3);
End.



Literatura: 
[1] "Programowanie kart graficznych"
      - Krzysztof Łabanowski
      (opisy: synchronizacji wyświetlania, generowania znaków) 

[2] "Programowanie w języku Assembler"
      - Stanisław Kruk
      (opis: kopiowania łańcuch bajtów z jednego miejsca w
       pamięci do drugiego) 

[3] "Procedury graficzne dla kart EGA, VGA i SVGA"
      - Jarosław Skolimowski
      (opisy: synchronizacji wyświetlania, generowania znaków). 
w3cw3c
automatyka przemysłowa