From: vitus@agropc.msk.su
Subject: Nonstandard BGI drivers HOW-TO (или "как это делается")
Date: 12 Jul 1996 20:41:54 +0400
Увидел в конфе в очередной раз вопрос на эту тему и решил сразу
написать все ответы. Возможно, это дело стоило бы отполировать, ну да ладно.
-----
1.Как определить, можно ли использовать данный BGI драйвер
со своей программой?
1). Не используйте драйверов от Quattro Pro или Paradox - они несовместимы
с Borland Pascal/Borland С.
2). Если Ваша программа написана на Turbo Pascal 6.0 и ниже,
то вам нужны драйверы версии 2.х
Программа на Borland Pascal версии 7.0 в реальном режиме
может использовать как драйверы версии 2.х, так и 3.0
Программа в Protected Mode нуждается в драйвере версии 3.0
Отличить драйвер версии 2.х от 3.0 очень просто -
если первые два байта в файле с расширением bgi
это 'pk' маленькими буквами, то это 2.х (а может 1.х -
с последними ни разу не сталкивался).
Если же файл начинается с символов 'FBGD', то это - 3.0
и он будет работать в Protected, но не будет работать с
6-м паскалем.
2. Как получить номер драйвера, который следует передавать
в процедуру InitGraph?
RTFM: InstallUserDriver
Function InstallUserDriver(DrvName:String;AutoDetectPtr:pointer):integer;
Эта функция получает имя драйвера БЕЗ ПУТИ И РАСШИРЕНИЯ. Второй параметр
указатель на функцию автодетектирования (см вопрос 4)
При первых экспериментах вместо него можно смело передавать nil.
Например:
Gd:=InstallUserDriver('SVGA256',nil);
Gm:=3;
InitGraph(GD,GM,'C:\BP\BGI');
3. Как заставить модуль GRAPH использовать нужный мне драйвер вместо
заданного по умолчанию?.
Явным образом присвоить значение переменной, которая будет передана
в процедуру InitGraph в качестве первого параметра (см. пример к
вопросу 2)
При этом надо не забыть присвоить значение и параметру GraphMode
(графический режим), поскольку если GraphDriver<>Detect, автоматического
определения режима не происходит.
4. Как заставить программу автоматически определять режим
нестандартного драйвера?
Написать процедуру автодетектирования и передать ее вторым
параметром в InstallUserDriver.
Процедура должна быть описана как far и представлять собой
функцию без параметров, возвращающую номер режима или
-1, если ни один из режимов данного драйвера не поддерживается.
Хороший пример процедуры автодетектирования приведен в программе
BGIDEMO.PAS, входящей в комплект поставки Borland Pascal.
Если вы не боитесь ассемблера и вам не лень разбираться
в функциях VESA BIOS вы легко адаптируете ее к 256-цветному драйверу
(если она у вас будет работать и в Real и в Protected - киньте мне,
а то мне лень :-)
Простейшая процедура детектирования для драйвера VGA256
(режим 13H, 320x200x256,VGA) выглядит так:
Function DetectVGA:integer;far;assembler;
asm
MOV AX,1A00H
INT 10H
CMP AL,1AH
JZ @@1
mov ax,-1 ;{Не вышло}
jmp @@2
@@1:MOV AX,0;{вышло - ставим нулевой режим}
@@2:
end;
Модуль GRAPH выполняет детектирование следующим образом:
вызывает процедуру детектирования для всех установленных
драйверов, начиная с конца (с последнего)
и устанавливает первый драйвер, процедура детектирования
которого вернула режим, больший или равный 0.
(это, естественно, происходит только если параметр
GraphDriver в процедуре InitGraph был равен Detect)
5. Как прилинковать нестандартный BGI-драйвер?
1). преобразовать его в объектный файл с помощью
утилиты binobj
2). Прилинковать
Для этого надо написать следующие две строки:
Procedure SVGADriver;External;
{$L SVGA.OBJ}
где имя процедуры - это то, что Вы указали третьим параметром
утилиты BINOBJ, а имя объектного файла - то что Вы указали вторым
параметром.
3). Вызвать InstallUserDriver точно так же, как вы вызывали
его при отдельно лежащем драйвере.
4). Вызвать RegisterBgiDriver, передав в него адрес процедуры,
в качестве которой вы прилинковали драйвер
RegisterBgiDriver(@SVGADriver);
5). Вызвать InitGraph, указав в качестве BGIPath тот каталог,
откуда вы будете грузить CHR шрифты (или пустую строку,
если шрифты не нужны или тоже прилинкованы)
Номер драйвера в данном случае будут возвращать и
InstallUserDriver и RegisterBgiDriver.
6. Как отловить все ошибки, связанные с загрузкой и
инициализацией драйвера?
Во-первых, можно проверять GraphResult после каждой
операции.
Напишите для этого такую процедурку
Procedure CheckError;
var Result:Integer;
begin
Result:=GraphResult;
if Result<>grOk then
begin
Writeln(GraphErrorMsg(Result));
Halt(1);
end;
end;
GraphErrorMsg, конечно, ругается по-английски, но она дает больше
информации, чем просто анализ кода GraphResult - она выдает
имя неправильного драйвера или шрифта.
Кроме того функции InstallUserDriver, InstallUserFont, RegisterBGIDriver,
и RegisterBGIFont возвращают, а InitGraph присваивает параметру
GraphMode в случае ошибки отрицательное значение, соответсвующее
коду GraphResult.
7. Как добиться русских шрифтов в BGI-графике?
а) шрифт 0 (DefaultFont) Для того, чтобы этот шрифт был русским,
вектор прерывания 1F должен быть установлен корректно.
Добудьте откуда-нибудь русский шрифт 8x8 (например, выдерите
из EGA.CPI от русской DOS или из какого-нибудь руссификатора),
возьмите от него вторую половину (1024 байта)
и прилинкуйте к своей программе (см вопрос 5).
После это сделайте SetIntVec($1F,@RussianFont);
Не забудьте обеспечить корректное восстановление этого вектора
при завешении программы.
На уровне команд DOS того же эффекта можно добиться загрузив
резидентную программу GRAFTABL, входившую в комплект DOS версий
до 6.
Запускать ее надо командой GRAFTABL 866, а сама программа
должна быть взята из русской DOS.
б) векторные (CHR) шрифты
Возьмите файлы шрифтов из комплекта русского Paradox или
Quattro Pro. В отличие от BGI драйверов они совместимы.
8. Куда делся мой курсор мыши?
К сожалению, большинство драйверов мыши не поддерживают
режимов SVGA. Поэтому вы можете попробовать найти драйвер BGI,
который содержит встроенную эмуляцию курсора или написать свою
эмуляцию (процедур GetImage и PutImage для этого вполне достаточно)
Кроме того, в 256 цветных режимах 255 и 0 цвета по умолчанию
оба черные, так что курсор мыши будет напоминать черную кошку в
темной комнате.
Сделайте SetRGBPalette(255,63,63,63);
9. Как добиться того, чтобы программе была доступна работа
со всей палитрой VGA (256 К цветов) а не только 63 цвета,
котроые предлагает EGA-совместимая процедура SetPalette?
Используйте SetRGBPalette.
В 256-цветных режимах вы не встретите никаких проблем,
а в 16 цветных все несколько сложнее. Дел в том, что в этих
режимах первым параметром в SetRGBPalette передается не
номер цвета, а индекс в палитре EGA.
Я с этим борюсь простейшим способом:
For i:=0 to 15 do
SetPalette(i,i);
После чего устанавливаю нужную мне палитру уже средствами
SetRGBPalette.
Moжно еще делать так
Var Pal:PaletteType;
......
GetPalette(Pal)
SetRBPalette(Pal.Colors[Color],R,G,B);
Если вы хотите переназначить все 256 цветов, то
конструкция вида
For i:=0 to 255
SetRGBPalette(i,R[i],G[i],B[i]);
вас, вероятно, не устроит, так как выполняется несколько
секунд.
Вот несколько полезных процедур для любителей работать с
палитрой:
Procedure SetRGBArray(Index,Count:Integer;var RGB);assembler;
asm
LES DX,RGB
MOV BX,Index
MOV CX,Count
MOV AX,1012H
INT 10H
end;
Устанавливает сразу много цветов(идущих подряд)
Index - номер первого из них,
Count - их количество
переменная RGB должна быть описана как
Array[1..Max] of Record
R,G,B:Byte;
end;
Впрочем
Type TcolorComponent=(R,G,B);
var PaLETTE256:ARRAY[0..255,R..B] of Byte;
тоже годится.
Procedure GetRGBPalette(Index:Integer;var R,G,B:Byte);assembler;
asm
MOV AX,1015H;
MOV BX,INDEX
INT 10H
LES DI,R
MOV ES:[DI],DH
LES DI,G
MOV ES:[DI],CH
LES DI,B
MOV ES:[DI],CL
end;
Возвращает три компоненты одного цвета, указанного в переменной
Index
Procedure GetRgbArray(Index,Count:Integer;var RGB);assembler;
asm
MOV BX,Index
MOV CX,Count
LES DX,RGB
MOV AX,1016H
INT 10H
end;
Копирует в переменную RGB описание Count цветов, начиная с Index
10. Почему PCX-файл, выведенный на экран в соответствии с
рекомендациями п.9 выглядит совершенно непохоже на оригинал?
Потому что регистры палитры VGA шестибитные, то есть каждая
из компонент R G B принимает значения от 0 до 63, а в стандарте
PCX на каждую компоненту отводится 8 бит - от 0 до 255.
Поделите содержимое палитры PCX-файла на 4 прежде чем
передавать в SetRGBPalette или SetRGBArray.
---------------------------------------------------------------------------
Phone: 7(095)230-80-61 Victor B. Wagner
Fax: 7(095)230-80-42 Dokuchaev Soil Institute
EMail: vitus@agropc.msk.su Moscow, Russia
|