Screen Saver Turbo Pascal
Tạo Screen Saver bằng Turbo PascalĐinh Mạnh ĐạtCác bạn hẳn đã biết tới các chương trình bảo vệ màn hình (Screen Saver) của Windows, Norton Commander(NC). Đó là các chương trình tự động kích hoạt sau một khoảng thời gian quy định nào đó, thông thường đó là các chương trình bảo vệ màn hình bằng cách giảm độ sáng của màn hình hoặc/và tạo cảm giác thoải mái cho người dùng bằng những hình ảnh vui nhộn. Trên môi trường Windows các chương trình Screen Saver hoạt động hơi đặc biệt một chút vì đó là môi trường đa nhiệm, còn trên MSDOS các Screen Saver chỉ đơn giản là các chương trình thường trú chúng ta có thể viết được bằng Assembler,C hay Pascal. Bạn hoàn toàn có thể viết được các Screen Saver như NC, tuy nhiên hãng Symantec đã viết cả bộ NC bằng Assembler (Giám đốc Peter Norton đã tiết lộ trong các sách của ông), vậy nên tôi không có ý định viết một Screen Saver mà chỉ muốn cho bạn thấy cách làm chúng như thế nào thông qua 'người bạn quen thuộc' Turbo Pascal.Các Screen Saver trong thực tế thường bắt đầu kích hoạt chương trình bảo vệ màn hình sau một khoảng thời gian bàn phím hay chuột không hoạt động và trả lại trạng thái cũ sau khi bàn phím hay chuột hoạt động. Nói chung là xử lý chuột và bàn phím thì gần như nhau trong Screen Saver, vì vậy mà tôi sẽ chỉ trình bày với bạn về một Screen Saver được kích hoạt nhờ bàn phím.Khi viết một Screen Saver chúng ta nhất thiết phải có các thủ tục sau đây:1. Bảo vệ màn hìnhĐối với các Lập trình viên siêu hạng họ có thể giảm độ sáng màn hình bằng cách tác động tới tận phần cứng - các ống phóng electron của màn hình hay card màn hình. Còn trong bài viết này, tôi xin đưa một giải pháp đơn giản để bảo vệ là làm tối đen mà hình hoặc hiển thị những hình ảnh tối màụ Tất nhiên bạn có thể không cần bảo vệ màn hình mà chỉ hiển thị những hình ảnh vui mắt hay bất kỳ hành động nào khác, lúc này chương trình của bạn coi như là chương trình giải trí thôi, thậm chí để trêu đùa và mang tính virus đơn giản!Bạn cần lưu lại màn hình trước khi 'bảo vệ'. Trong mode văn bản thông thường của DOS là 80*25, vùng nhớ màn hình có địa chỉ từ $B800, thật may Turbo Pascal có sẵn mảng MEM để truy nhập đến các vùng nhớ. Chúng ta khai báo 1 mảng screen: array[1 80*25*2] of byte, trước khi 'bảo vệ màn hình' ta lưu vùng nhớ màn hình vào mảng này bằng lệnh: move(MEM[$B800:0], screen[1],80*25*2), và sau này khôi phục bằng lệnh: move(screen[1], MEM[$B800:0],80*25*2). Sở dĩ mảng screen có kích thước 80*25*2 là vì mỗi vị trí trong 80*25 vị trí của màn hình cần 2 byte 1 cho ký tự ở đó và 1 cho thuộc tính (màu sắc) của ký tự đó.Bạn tham khảo 2 cách 'bảo vệ màn hình' trong chương trình ở dướị2. Xây dựng các ngắt mớiChương trình thường trú phải biết được bàn phím đã không được chạm đến trong một khoảng thời gian nhất định vì vậy mà ngắt thời gian và ngắt bàn phím cũ của BIOS cần phải được thay thế bằng ngắt mới của chúng ta, tuy nhiên ngắt mới phải có đoạn gọi ngắt cũ vì chúng ta không thể nào làm lại hoàn toàn một ngắt(!). Cũng vì lý do đó, khi một chương trình đang thường trú chúng ta không nên chạy nó nữa vì ngắt cũ đang không phải là ngắt gốc của BIOS! Ngắt thời gian mới có nhiệm vụ tăng biến Bộ đếm thời gian và kiểm tra nếu nó vượt qua giới hạn thì 'bảo vệ màn hình'. Ngắt thời gian mới có dạng:Procedure NewTimer; Interrupt;BeginCallOldInterrupt(OldTimer); { Gọi ngắt cũ } if TimeCounter <= TimeLimit then inc(TimeCounter) else GuardScreen;End;Khi có phím ấn thì ngắt bàn phím được gọi, ngắt(Interrupt) cũng là một loại chương trình con nên những điều chúng ta muốn thực hiện khi có phím ấn - chúng ta cho vào ngắt bàn phím. Ngắt bàn phím mới sẽ kiểm tra xem nếu màn hình đang trong tình trạng 'bảo vệ' thì nó sẽ khôi phục màn hình. Khi ngắt bàn phím mới này được gọi thì ta luôn cho biến Bộ đếm thời gian về 0 vì đó là thời điểm gần nhất bàn phím được ấn. Ngắt bàn phím mới có dạng:Procedure NewKeyboard; Interrupt;BeginCallOldInterrupt(OldKeyboard); { Gọi ngắt cũ } { Nhận xét: Màn hình đang bảo vệ thì TimeCounter >= Timelimit }if TimeCounter >= TimeLimit then RestoreScreen; TimeCounter:=0;End; 3. Thường trú:Để thường trú chương trình với các ngắt mới này trong Assembler là một chuỗi công việc dài còn trong Turbo Pascal (và cả C) thì rất đơn giản. Chỉ cần gọi thủ tục Keep(0) của unit DOS là mọi công việc 'trong hậu trường' được thực hiện. Bạn cũng cần lưu ý về kích thước các vùng nhớ cho chương trình. Turbo Pascal 'rất tốt bụng' cho ta định hướng biên dịch $M để đặt kích thước Stack và Heap, cú pháp của $M là: {$M StackSize, HeapMin, HeapMax}.4. Nối kết các thủ tục với nhau:Sau khi xây dựng các thủ tục này và nắm được tổng thể chương trình, bạn có viết chương trình và chỉnh sửa, thêm thắt đôi chỗ để được chương trình hoàn hảo nhất. Chương trình screensv dưới đây minh hoạ cho những điều nói trên:(* screensv.pas - Dinh Manh Dat *)(* Compiling to EXE to run *){$A+,B-,D+,E+,F+,G-,I-,L+,N-,O-,P-,Q-,R-,S-,T-,V-,X+}{$M 1024,0,0}Program ScreenSaver;Uses CRT, DOS;Const TimeLimit=91;(* 5s *) str: string= 'YOU ARE NEVER TOO OLD TO LEARN';Var TimeCounter: longint;OldTimer, OldKeyboard: pointer;screen: array[1 80*25*2] of byte;cx,cy,i: byte;Procedure GuardScreen;Beginclrscr;gotoxy(25,10);for i:=1 to length(str) dobegin textcolor(random(16)); write(str[i]); end;End;Procedure GuardScreen2;{Brick Out Characters like NC}Begininc(i); if i>3 then i:=0;if i mod 3<>0 then exit;textcolor(black);gotoxy(random(80)+1,random(25)+1); write(#219);gotoxy(random(80)+1,random(25)+1); write(#219);gotoxy(random(80)+1,random(25)+1); write(#219);End;Procedure GetScreen;Beginmove(mem[$B800:0],screen[1],80*25*2);cx:=wherex; cy:=wherey;asm mov ch,$01; mov cl,$00;mov ah,$01; int $10end;{Hide cursor}End;Procedure PutScreen;Beginmove(screen[1],mem[$B800:0],80*25*2);gotoxy(cx,cy);asm mov ch,$06; mov cl,$07;mov ah,$01; int $10end;{Show cursor}End;Procedure CallOldInterrupt(p: pointer);Begininline($9C);{Push flags}inline($FF/$5E/$06);{Call p} End;Procedure NewTimer; Interrupt;BeginCallOldInterrupt(OldTimer);if TimeCounter <= TimeLimit then inc(TimeCounter) elsebeginif TimeCounter = TimeLimit+1 thenbeginGetScreen;TimeCounter:=TimeLimit+2;end;GuardScreen;end;inline($FB);{STI Bat ngat cung} End;Procedure NewKeyboard; Interrupt;BeginCallOldInterrupt(OldKeyboard);if TimeCounter >= TimeLimit then PutScreen;TimeCounter:=0;inline($FB);{STI Bat ngat cung}End;Procedure Init;BeginTimeCounter:=0;(* Saving old interrupts: *)GetIntVec($08,OldTimer);{Timer Interrupt}GetIntVec($09,OldKeyboard);{Keyboard Interrupt}(* Set new interrupts: *)SetIntVec($08,@NewTimer);SetIntVec($09,@NewKeyboard);(* Note: @ - ađress of procedurẹ*)End;BEGINInit;Keep(0);END.Đọc kỹ chương trình trên bạn sẽ thấy những điều rất tinh tế của một Screen Saver (ví dụ thủ tục 'bảo vệ màn hình' thì được thực hiện lặp đi lặp lại nhờ bộ đếm thời gian, vậy nên mới có thể tạo hình chuyển động, bạn có thể dễ dàng cho nó thực hiện chỉ một lần giống như virus 'Mi là con dế hay 'Happy New Year' làm). Ngoài ra, với một Screen Saver bạn cũng cần quan tâm tới các vấn đề phức tạp khác như: chương trình đã thường trú chưa, bỏ thường trú như thế nào, Những nhiệm vụ 'tuyệt hảó này bạn tìm ở các hàm 35hex và 25hex trong ngắt 21 hex của DOS.Về các Screen Saver nhân tiện tôi xin kể mấy câu chuyện thú vị trong thực tế. Đã có không ít những lập trình viên nghịch ngợm - vui tính tạo những Screen Saver trên Windows với 'cảnh tượng' y như là đang Format, UnInstall hay Connect to Internet làm cho người dùng phải hốt hoảng sau vài phút vắng mặt, hầu hết sau đó họ lại thở phào nhẹ nhõm và vui vẻ nữa nhưng có trường hợp như bạn tôi vội vàng tắt bụp máy để Format không có tác dụng! Còn có những lập trình viên quái gở cho hiện một bản thông báo 'doạ dẫm' như 'Press any key to format' hay bắt người dùng chọn một trong một loạt toàn các 'yêu sách' như là Reset Computer, Turn off the monitor (!) còn có những Screen Saver hiện Linux Red Hat trên Windows, hiện thanh Tasbar trong DOS. Tôi và các bạn tôi cũng đã từng làm nhiều Screen Saver thú vị, đó không phải là những chương trình to tát gì nhưng là sự giải trí và rèn luyện rất bổ ích. Hy vọng bạn cũng sẽ tìm thấy những điều thú vị với các Screen Saver. Chúc bạn thành công!Đinh Mạnh Đạt . Tạo Screen Saver bằng Turbo Pascal inh Mạnh ĐạtCác bạn hẳn đã biết tới các chương trình bảo vệ màn hình (Screen Saver) của Windows, Norton. viết một Screen Saver mà chỉ muốn cho bạn thấy cách làm chúng như thế nào thông qua 'người bạn quen thuộc' Turbo Pascal. Các Screen Saver trong