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).