http://sulfurzona.com/
News
Service
Magazine
Software (Battle City Game, Wallpaper manager, Superpad, VG-NOW, Puzzle Game, Netler Internet Browser, ..)
Dune Game (Dune III, Dune IV, Cheats, Forum, ..)
Games free
Turbo Pascal (Assembler, Docs, Sources, Debbugers, ..)
Books (Docs for developers)
Forum
Guest book
Компьютерная диагностика двигателя автомобиля (адаптер К-линии)Компьютерная диагностика двигателя автомобиля (адаптер К-линии)
 
 

Паскаль для новичков (часть 14)

 
 

Спрашивали? Отвечаю…

 
Паскаль для новичковСнова пришёл черёд отвечать на письма читателей. И я рад этому. В письмах, пришедших за последнее время на мой адрес, тот что чуть повыше ;O) , читатели просят подсказать альтернативу стандартному модулю CRT, так как на современных процессорах Am5x86, Pentium, Celeron, Pentium III и выше использование модуля CRT приводит к неработоспособности программы и возникает ошибка выполнения 200.
 

Работаем с текстовым режимом MS-DOS

 
Раз уж читатели интересуются модулем CRT, то вероятнее всего им необходимо, чтобы их программы могли работать с текстовым режимом. На этот случай я могу предложить написать некоторый модуль VESACRT.PAS, который позволил бы работать с шестью текстовыми режимами с экранным разрешением от 80x25 до 132x60 символов, и при этом загружать пользовательские масштабируемые растровые шрифты, осуществлять ввод с клавиатуры и работать с мышью.
Ну что же, если это Вас заинтересовало, то начнём.
 
Что такое VESA и с чем её едят? ;-)
Производители вычислительной техники объединились и создали ассоциацию стандартов на видеоэлектронику (Video Electronics Standards Association – VESA). Ей было дано право издавать стандарты. Было решено установить минимальный набор особых свойств, которыми должна обладать каждая карта Super VGA. Ассоциация подтолкнула программистов к написанию драйверов для самых распространённых программ, использующих преимущества плат Super VGA любого производителя. Стандарт поддерживается большинством современных SVGA плат и акселераторов на уровне BIOS платы.
 
Я бы с удовольствием рассказал обо всех версиях VBE (VESA BIOS Extension) и их возможностях, но всё это невозможно вместить даже в объём двух статей. Гораздо проще скачать необходимую документацию. На этом же ресурсе можно раздобыть Norton Guide.
 
Итак, при работе видеоадаптера в текстовом режиме память, отведённая под видеобуфер, имеет следующую структуру: каждый отображаемый на экране символ представляется парой байт, где чётный байт несёт информацию о ASCII коде отображаемого символа, а нечётный байт содержит его цветовую информацию (атрибут). В свою очередь, атрибут состоит из двух частей. Первая расположена в младших четырёх битах и содержит код цвета символа 0..15, а вторая расположена в старших четырёх битах и содержит код цвета фона 0..7, при этом самый старший бит отвечает за мерцание символа, т.е. значение бита равное 1 включает мерцание. Коды цветов соответствуют стандартным константам Black..White Turbo Pascal.
 
На мой взгляд, целесообразным является использование шести текстовых режимов, из которых первый режим является стандартным для базового видео BIOS’а, а пять остальных являются стандартными для VESA BIOS’а. Теперь можно начать составление модуля с описания типов, которые могут понадобиться в дальнейшем:
 
unit VesaCrt;
 
interface
 
type
TSymbRec = record
Symb : char;
Attr : byte;
end;
TScrLine = array [0..131] of TSymbRec;
PScrLine = ^TScrLine;
TVesaTextMode = record
Mode, Width, Height, CharWidth, CharHeight,
CharBytes : word;
end;
TScreenMetrix = record
Mode, Width, Height, MinX, MaxX, MinY, MaxY,
CharWidth, CharHeight, CharBytes : word;
end;
TWinRect = record
Left, Top, Right, Bottom, Width, Height : word;
end;
 
const
{-- Colors --}
clBlack = 0;
clBlue = 1;
clGreen = 2;
clCyan = 3;
clRed = 4;
clMagenta = 5;
clBrown = 6;
clLightGray = 7;
clDarkGray = 8;
clLightBlue = 9;
clLightGreen = 10;
clLightCyan = 11;
clLightRed = 12;
clLightMagenta = 13;
clYellow = 14;
clWhite = 15;
{-- Screen Modes --}
VesaDefault = 0;
Vesa80x25 = VESADefault;
Vesa80x60 = 1;
Vesa132x25 = 2;
Vesa132x43 = 3;
Vesa132x50 = 4;
Vesa132x60 = 5;
Metrix : Array[0..5] of TVesaTextMode =
((mode:$003;Width:80;Height:25;CharWidth:8;
CharHeight:8;CharBytes:17),
(mode:$108;Width:80;Height:60;CharWidth:8;
CharHeight:8;CharBytes:8),
(mode:$109;Width:132;Height:25;CharWidth:8;
CharHeight:8;CharBytes:17),
(mode:$10A;Width:132;Height:43;CharWidth:8;
CharHeight:16;CharBytes:10),
(mode:$10B;Width:132;Height:50;CharWidth:8;
CharHeight:16;CharBytes:9),
(mode:$10C;Width:132;Height:60;CharWidth:8;
CharHeight:16;CharBytes:9));
ScrAddr = $0b800;
 
var
Screen : TScreenMetrix;
WinRect : TWinRect;
 
function SetTextMode( num : word ) : boolean;
procedure SetCharTable( var CharTable; FirstChar,
CharCount : word; BytePerChar : byte);
function InstallFont( FileName : string; FirstChar,
CharCount, BytePerChar : word) : word;
procedure SetWindow( MinX, MinY, MaxX, MaxY : byte );
procedure DefaultWindow;
procedure SetCurSize( Start, Finish : byte );
procedure SetCurPos( x, y : byte);
procedure CursorHide;
procedure CursorShow;
procedure ClrScr;
procedure FillScr( Symbol : char; TextColor,
BackColor : byte );
procedure FillRect( Left, Top, Right, Bottom : byte;
Symbol : char; TextColor, BackColor : byte );
procedure TextOut( x, y : byte; s : string );
procedure SetTextColor( color : byte );
function GetTextColor : byte;
procedure SetBackColor( color : byte );
function GetBackColor : byte;
 
implementation
 
const TextAttr : byte = clLightGray;
 
Итак, тип TSymbRec отражает выше описанную структуру информации о символе на экране. Для удобства доступа к строке символов на экране описываем тип TScrLine. Тип TVesaTextMode описывает параметры видеорежима из таблицы режимов Metrix. Тип TScreenMetrix описывает параметры текущего режима, которые будут храниться в переменной Screen. Тип TWinRect описывает границы текущего окна, которые будут храниться в переменной WinRect. Помимо этого инициализируем атрибут символов TextAttr цветом clLightGray и адрес начала видеобуфера ScrAddr номером сегмента $0b800.
 
Как видно, кроме всего этого ещё описаны константы цветов clBlack..clWhite, которые применимы не только для кодирования цвета символа, но и для цвета фона.
Ну и индексы шести текстовых режимов VesaDefault..Vesa132x60, где VesaDefault и есть стандартный текстовый режим, который установлен по умолчанию, и в который необходимо переходить перед завершением программы.
Теперь, используя вызов документированной функции VESA BIOS по переключению видеорежимов, опишем функцию установки текстового режима по индексу:
 
function SetTextMode( num : word ) : boolean;
var Res : boolean;
begin
Screen.Mode := Metrix[num].Mode;
Res := false;
asm
mov bx,Screen.Mode; mov ax,4F02h;
int 10h; cmp ah,0; jnz @err; mov Res,true
@err:
 
 
 
 
end;
SetTextMode := Res;
if Res then begin
with Screen do begin
Width := Metrix[num].Width;
Height := Metrix[num].Height;
MaxX := Width-1;
MaxY := Height-1;
MinX := 0;
MinY := 0;
CharWidth := Metrix[num].CharWidth;
CharHeight := Metrix[num].CharHeight;
CharBytes := Metrix[num].CharBytes;
end;
DefaultWindow;
end;
end;
 
ассемблерный оператор asm..end заносит в регистр BX номер устанавливаемого режима из массива Metrix по указанному индексу num, заносит в регистр AX номер функции $4F сервиса VESA и номер подфункции $02 (установка видеорежима) и вызовом программного прерывания int 10h активизирует подфункцию установки видеорежима. При успешном вызове в регистре AL будет значение $4F, что значит, что функция поддерживается, а в регистре AH значение 0, что значит, что функция выполнена успешно, т.е. требуемый режим включён. И естественно, раз уж режим включён, то необходимо проинициализировать переменные Screen и WinRect. Последняя инициализируется процедурой DefaultWindow, о которой я расскажу позднее. Сразу, после установки видеорежима, координаты и размеры текущего окна совпадают с соответствующими параметрами всего текстового экрана. Пример использования функции SetTextMode:
 
Uses VesaCRT;
begin
if not SetTextMode(Vesa80x60) then begin
writeln('Error: Bad screen mode');
halt;
end;
if SetTextMode(VesaDefault) then;
end.
 
Как переводить видеоадаптер в нужный видеорежим теперь понятно. Следующее, что нужно научиться делать, это очищать экран с помощью процедуры ClrScr. Но перед этим опишем универсальную процедуру, которая заполняет область с координатами в пределах текущего окна указанным символом и цветом:
 
procedure FillRect( Left, Top, Right, Bottom : byte; Symbol : char; TextColor, BackColor : byte );
var x, y : word;
TextScreen : PScrLine;
Attribute: byte;
begin
Left := Left+WinRect.Left;
Right := Right+WinRect.Left;
Top := Top+WinRect.Top;
Bottom := Bottom+WinRect.Top;
if (Left > WinRect.Right) or (Top > WinRect.Bottom) then exit;
if Right > WinRect.Right then Right := WinRect.Right;
if Bottom > WinRect.Bottom then Bottom := WinRect.Bottom;
Attribute := (BackColor shl 4) or (TextColor and $0f);
for y := Top to Bottom do begin
TextScreen := ptr(ScrAddr, y*Screen.Width*2);
for x := Left to Right do
with TextScreen^[x] do begin
Symb := Symbol;
Attr := Attribute;
end;
end;
end;
 
В переменной TextScreen формируется указатель на начало области памяти видеобуфера, совпадающей с очередной строкой экрана с номером в переменной Y. Выражение y*Screen.Width*2 говорит о том, что мы вынуждены вычислять смещение для нужной строки, умножая номер строки на ширину строки в байтах. Так, как в переменной Screen.Width хранится ширина строки экрана в символах, а мы знаем, что каждый символ занимает в видеопамяти 2 байта, то ещё умножаем на 2. Ну а дальше, как говорится, дело техники. Т.е. в каждую позицию строки заносим символ Symbol и устанавливаем его цвет в TextColor, а цвет фона в BackColor.
Не могу умолчать о том, что ассемблерный вариант данной процедуры выполняется в два раза быстрее.
 
procedure ClrScr;
Begin
FillRect(0, 0, WinRect.Width, WinRect.Height, ' ', clLightGray, clBlack);
end;
 
Данная процедура очищает текущее окно исходя из его параметров, хранящихся в переменной WinRect. Т.е. в каждую позицию строки заносим символ “пробел” и устанавливаем его цвет в clLightGray, а цвет фона будет чёрный.
Теперь рассмотрим долгожданный вывод текста на экран.
 
procedure TextOut( x, y : byte; s : string);
var j, Count : integer;
TextScreen : PScrLine;
begin
x := x + WinRect.Left;
y := y + WinRect.Top;
if (x>WinRect.Right) or (y>WinRect.Bottom) then exit;
TextScreen := ptr(ScrAddr, y*Screen.Width*2);
Count := length(s) - 1;
if x + Count>WinRect.Right then Count := WinRect.Right - x;
for j := 0 to Count do
with TextScreen^[x + j] do begin
Symb := s[j+1];
Attr := TextAttr;
end;
end;
 
Процедура TextOut выводит строку S, начиная с позиции X, Y текущего окна. При этом координаты верхнего левого угла (0,0), а координаты нижнего правого угла (WinRect.Width-1,WinRect.Height-1). Строка выводится с атрибутом TextAttr, который следует устанавливать предварительно. Если строка окажется на столько длинной, что может выйти за правый край окна, то она будет урезана до правой границы окна. Это позволит избежать неуместного переноса выводимой строки на следующую строку экрана.
 
Теперь осталось научиться управлять цветом и дело в шляпе ;O)
Процедура SetTextColor устанавливает цвет символа (см. константы clBlack..clWhite) в переменную TextAttr, которая будет использоваться при очередном выводе текста на экран. При этом информация о цвете фона изменена не будет.
 
procedure SetTextColor( color : byte );
begin
TextAttr := (TextAttr and $f0) or (color and $0f);
end;
 
Следующая функция позволяет узнать, какой цвет символа установлен.
 
function GetTextColor : byte;
begin
GetTextColor := TextAttr and $0f;
end;
 
Процедура SetBackColor устанавливает цвет фона символа (можно использовать константы cl???) в переменную TextAttr. При этом информация о цвете символа изменена не будет. Следует, однако, помнить, что для установки фона без мерцания надо указывать константы clBlack..clLightGray, а для включения мерцания соответственно clDarkGray..clWhite.
 
procedure SetBackColor( color : byte );
begin
TextAttr := (TextAttr and $0f) or (color shl 4);
end;
 
Следующая функция позволяет узнать, какой цвет фона установлен.
 
function GetBackColor : byte;
begin
GetBackColor := TextAttr shr 4;
end;
 
Рассмотрим использование этих подпрограмм на примере.
 
ClrScr;
SetTextColor(clWhite);
{ строка будет белым цветом }
TextOut(0, 1, 'Hello All My Friends!');
SetTextColor(clGreen);
{ строка будет зелёным цветом }
TextOut(0, 2, 'Hello All My Friends!');
SetBackColor(clLightGray);
{ строка будет зелёным цветом на сером фоне }
TextOut(0, 3, 'Hello All My Friends!');
 
Это пока всё на сегодня. В следующий раз будем учиться управлять окнами, позицией курсора и его формой, а также рассмотрим способы установки различных шрифтов для текстовых режимов.
 

Литература

1. Р. Джордейн. Справочник программиста персональных компьютеров типа IBM PC, XT и AT. – М.: Финансы и статистика, 1992. – 543 с.
2. Диалоговая справочная система Norton Guide.
3. VESA BIOS EXTENSION (VBE) Core Functions Version: 2.0
 
Продолжение следует…
 
© Владислав Демьянишин
 
 
На нашем сайте можно не только бесплатно скачать игры, но и документацию и книги по программированию на MIDLetPascal, Turbo Pascal 6, Turbo Pascal 7, Borland Pascal, по программированию устройств Sound Blaster, Adlib, VESA BIOS, справочник Norton Guide и много другой полезной информации для программистов, включая примеры решения реальных задач по созданию резидентных программ. Предлагаю также посетить Марья искусница - сайт о рукоделии (http://mariya-iskusnica.ru).
 

Журнал > Программирование > Паскаль для новичков (Turbo Pascal, Assembler) > Паскаль для новичков (часть 14): Спрашивали? Отвечаю…
 
 
 
973
 
ВКонтакте
Facebook
 
 
 
На главную страницу На предыдущую страницу На начало страницы
 
 
Украинский портАл Украина онлайн Рейтинг@Mail.ru Рейтинг Сайтов YandeG Rambler's Top100