20.1. Программный опрос режимов текстового дисплея
Начнем с рассмотрения видеопамяти. Известно, что она располагается в адресах памяти ПЭВМ от $А000:$0000 до $BFFF:$0000. Непосредственно интересующая нас память текстового изображения находится «где-то» в этом диапазоне.
Определение начала видеопамяти текстового изображения — весьма важная и нужная задача. Монохромные режимы используют ячейки памяти, начиная с $В000:0000, а цветные — с $В800:0000. Хорошая программа должна сама определять, с каким режимом она
- 472 -
работает. Рассматриваемая ниже функция опрашивает специальный адрес, в котором MS-DOS хранит информацию по текущей конфигурации системы. В зависимости от его содержимого функция возвращает адрес начала видеопамяти текстового режима (рис. 20.1). На эту функцию мы будем ссылаться в дальнейшем.
файл GET_PTR.INC
| { Функция возвращает адрес видеопамяти в режиме текста }
| FUNCTION GetScreenPtr : Pointer;
| BEGIN
| if ( Mem[0:$0410] and $30 ) = $30
| then GetScreenPtr := Ptr($B000,0) { режим MONO }
| else GetScreenPtr := Ptr($B800,0) { цветной режим }
| END;
Рис. 20.1
Рассмотренная функция работает практически со всеми стандартными видеоадаптерами в режимах с разрешениями 80 или 40 столбцов на 25, 43 или 50 строк.
Реальный размер используемой видеопамяти зависит от режима работы. Минимальное значение его (при режиме 40 столбцов на 25 строк) равно 40x15x2 = 2000 байт. Максимальный из стандартных режимов размер для адаптера VGA в режиме 80x50 равен 8000 байт.
Определение текущего режима есть, по сути, задача опроса фиксированных адресов памяти, где хранятся сведения по конфигурации. Тип адаптера определяет минимальное число столбцов (80 или 40) и максимальное число строк (25, 43 или 50) на текстовом экране. Варианты возможных режимов сведены в табл. 20.1.
Таблица 20.1
25
43
50
40
Все, кроме MDA
EGA, VGA
VGA
80
Все
EGA, VGA
VGA
При работе с адаптером VGA и программами русификации ПЭВМ режим 80x50 может быть включен только, если загружены
- 473 -
шрифты форматов 8x16 и 8x8. Если же в ПЭВМ загружен шрифт 8x14, то будет включаться режим 80 столбцов на 43 строки.
Некоторые адаптеры (VGA, UltraEGA, SuperEGA и т.п.) могут использовать и другие режимы, но они не являются стандартными и не рассматриваются в этой книге.
Можно легко получить номер текущего текстового режима. Он всегда содержится в переменной модуля CRT LastMode, имеющей тип Word. Младший байт LastMode содержит номер режима (см. табл. 15.6), а нулевой бит старшего байта содержит признак режима в 43 или 50 строк (десятичное число 256 — константа Font8x8). Используя эту переменную, легко построить две функции опроса видеорежимов (рис. 20.2).
файл GET_PAR.INC
| { Функция возвращает номер текущего режима }
| FUNCTION CurrentMode: Byte;
| BEGIN
| CurrentMode := Lo( LastMode )
| END;
| { Функция возвращает True, если включен режим Font8x8 }
| FUNCTION Font8x8YES : Boolean;
| BEGIN
| Font8x8YES := ( LastMode and Font8x8 ) = Font8x8
| END;
| {Функция возвращает длину видеопамяти в режиме текста }
| FUNCTION GetScreenSize : Word;
| VAR
| R : Byte absolute $0000:$0484;
| С : Byte absolute $0000:$044A;
| BEGIN
| if Hi( LastMode ) = 1
| then GetScreenSize := Succ( R )*С*2
| else GetScreenSize := 25*С*2;
| END;
| { Функция возвращает число столбцов - 40 или 80 }
| FUNCTION GetColNum : Byte;
| BEGIN GetColNum := Mem[0:$44A] END;
| { Функция возвращает число строк - 25,43 или 50 }
| FUNCTION GetRowNum : Byte;
| BEGIN
| GetRowNum := GetScreenSize div GetColNum div 2
| END;
Рис. 20.2
- 474 -
Сложнее получить информацию о текущем количестве столбцов и строк на экране и размер видеопамяти, поскольку эти числа зависят не только от режимов, но и от типа адаптера. На рис. 20.2 предлагается библиотека процедур и функций опроса видеорежимов. В большинстве примеров применяются опросы специальных адресов системной памяти IBM-совместимых ПЭВМ. Пример обращения к этим функциям приведен на рис. 20.3.
| USES CRT; { ДЕМОНСТРАЦИЯ АНАЛИЗА ВИДЕОРЕЖИМА (ТЕКСТ) }
| {$I get_ptr.inc} { функция GetScreenPtr (см. рис. 20.1) }
| {$I get_par.inc) { функции анализа режима с рис. 20.2 }
| VAR
| P : Pointer;
| BEGIN
| P := GetScreenPtr; { P^ - Начало видеопамяти }
| if Seg(P^)=$B000 then TextMode(Mono)
| else TextMode( C040);
| WriteLn('Старт видеопамяти: ', Seg(P^), ':', Ofs(P^) );
| WriteLn('Длина видеопамяти: ', GetScreenSize,' Байт' );
| WriteLn('Емкость экрана : ', GetColNum, 'x', GetRowNum);
| WriteLn; Write( 'Нажмите Enter...');
| ReadLn { пауза до нажатия ввода }
| END.
Рис. 20.3