http://sulfurzona.com/
News
Service
Magazine
Dune Game (Dune III, Dune IV, Cheats, Forum, ..)
Games free
Turbo Pascal (Assembler, Docs, Sources, Debbugers, ..)
Books (Docs for developers)
Компьютерная диагностика двигателя автомобиля (адаптер К-линии)Компьютерная диагностика двигателя автомобиля (адаптер К-линии)
 
 
 
 
 

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

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

Работаем с графическим режимом 3 (продолжение)

 
Паскаль для новичковНас на некоторое время прервали, но я продолжу ;0)
А вот и краткий код подпрограмм PutPixel24BitsVesa, GetPixel24BitsVesa:
 
procedure PutPixel24BitsVesa( X, Y : word; Color : TColor ); assembler;
asm
 mov si,X; shl si,2 {24 bits/color}; mov bx,Y
 …
 int 10h
@a: mov ax,word ptr Color; mov es:[di],ax
 add di,2; mov ax,word ptr Color+2; mov es:[di],ax
end;
 
function GetPixel24BitsVesa( X, Y : word ): TColor; assembler;
asm
 mov si,X; shl si,2; mov bx,Y
 …
 int 10h
@a: mov ax,es:[di]; add di,2; mov dx,es:[di]
end;
 
Так как все дальние подпрограммы уже описаны, то можно закрыть блок директивой {$F-}. Теперь можно перейти к универсальным подпрограммам PutPixel и GetPixel. Они обеспечивают не только вывод и чтение точки, но и проверку выхода её координат за пределы текущего ограничивающего окна, что позволит избежать вычисления некорректного адреса точки и обращения по нему, стало быть, и аварии.
 
procedure PutPixel( X, Y : integer; Color : TColor );
begin
if (X<0) or (X>=WinRect.Width) then exit;
if (Y<0) or (Y>=WinRect.Height) then exit;
X := X + WinRect.Left;
Y := Y + WinRect.Top;
PutPixelProc(X,Y,Color);
end;
 
function GetPixel( X, Y : integer ): TColor;
begin
GetPixel := 0;
if (X<0) or (X>=WinRect.Width) then exit;
if (Y<0) or (Y>=WinRect.Height) then exit;
X := X + WinRect.Left;
Y := Y + WinRect.Top;
GetPixel := GetPixelProc(X,Y);
end;
 
А вот и те две пресловутые функции, позволяющие получить информацию о видеоадаптере и параметрах поддерживаемых видеорежимов в глобальные переменные VESAInfo и ModeInfo.
 
function GetVESAInfo: boolean; assembler;
asm
 mov ax,4f00h; lea di,VESAInfo; int 10h
 shr ax,8; sub ax,1
end;
 
Данный код вызывает функцию 4f00h видео BIOS’а, которая возвращает информацию об адаптере в переменную типа TVESAInfo, адрес которой должен быть в регистровой паре ES:DI. В регистр AH при успехе возвращает нуль, иначе единицу. Поэтому это значение приходится командами shr ax,8; sub ax,1 преобразовать в тип boolean, где значение true будет означать успех. Интерфейс вызова следующей функции BIOS’а аналогичен, но она в переменную типа TVESAModeInfo возвращает информацию о видеорежиме с номером Mode.
 
function GetVESAModeInfo( Mode : word ): boolean; assembler;
asm
 mov ax,4f01h; mov cx,mode; lea di,ModeInfo
 int 10h; shr ax,8; sub ax,1
end;
 
Процедура инициализации констант базовых цветов:
 
procedure PrepareColors;
begin
clBlack := RGBToColor(0,0,0);
clBlue := RGBToColor(0,0,255);
clGreen := RGBToColor(0,128,0);
clRed := RGBToColor(255,0,0);
clYellow := RGBToColor(255,255,0);
clWhite := RGBToColor(255,255,255);
end;
 
А вот и функция для определения значения параметра GranulShift, то есть длины битового сдвига, соответствующего гранулярности текущего видеорежима:
 
function GetGranulShift( WinGranul : word ): word;
var Count : word;
begin
Count := 0;
while WinGranul <> 64 do begin
          WinGranul := WinGranul shl 1;
          inc( Count );
          end;
GetGranulShift := Count;
end;
 
Тут всё просто, и сводится к подсчёту количества бит, на которое следует сдвинуть количество 64Кб-ых страниц, чтобы получить количество реальных страниц для текущего адаптера.
  
Очередная функция выполняет подготовку к установке затребованного видеорежима VESA по индексу массива режимов. Для этого вызывается функция GetVESAModeInfo для получения информации о режиме. Если информация получена, то режим поддерживается. Тогда инициализируется параметр GranulShift, затем выполняется установка видеорежима при помощи ассемблерной вставки с вызовом функции $4F02 BIOS’а, а в переменную Res возвращается значение типа boolean, где true – это успех. Завершает функцию код инициализации структур Screen и WinRect. Функция возвращает true в случае успеха.
 
function PrepareVesaMode( Index : word ): boolean;
var Res : boolean;
begin
PrepareVesaMode := false;
if not GetVESAModeInfo(Metrics[Index].mode) then exit;
GranulShift:=GetGranulShift(ModeInfo.WinGranul);
asm
 mov LastPage,$FFFF; mov bx,Screen.Mode
 mov ax,4F02h; int 10h; shr ax,8; sub ax,1
 mov Res,al
end;
PrepareVesaMode := Res;
if Res then begin
   with Screen do begin
     Width := Metrics[Index].Width;
     Height := Metrics[Index].Height;
     BytesPerScanline:=ModeInfo.BytesPerScanline;
     BitsPerPixel := ModeInfo.BitsPerPixel;
     end;
   DefaultWindow;
   end;
end;
 
Функция SetMode обеспечивает установку текстового режима и графических режимов VGA, VESA. При этом, в ней выполняется инициализация процедурных переменных PutPixelProc, GetPixelProc, RGBToColor, а также константы базовых цветов. Функция возвращает true в случае успеха.
 
function SetMode( Index : word ): boolean;
begin
SetMode := false;
Move( Metrics[Index], Screen,
            Sizeof( TVESAGraphMode ) );
case Index of
 0: begin
     asm
      mov ax,Screen.Mode; int 10h
     end;
    PutPixelProc := NilProc;
    GetPixelProc := NilFunc;
    end;
 1: begin
     asm
      mov ax,Screen.Mode; int 10h
     end;
    PutPixelProc := PutPixel8BitsVga;
    GetPixelProc := GetPixel8BitsVga;
    with Screen do begin
            Width := Metrics[Index].Width;
            Height := Metrics[Index].Height;
            BytesPerScanline := Width;
            BitsPerPixel := 8;
            end;
 
 
 
 
    clGray := 15;
    DefaultWindow;
    end;
2..6: if PrepareVesaMode( Index ) then begin
         PutPixelProc := PutPixel8BitsVesa;
         GetPixelProc := GetPixel8BitsVesa;
         end
         else exit;
7..11: if PrepareVesaMode( Index ) then begin
          PutPixelProc := PutPixel16BitsVesa;
          GetPixelProc := GetPixel16BitsVesa;
          RGBToColor := RGBTo16Bits;
          PrepareColors;
          end
          else exit;
 else if PrepareVesaMode( Index ) then begin
         PutPixelProc := PutPixel24BitsVesa;
         GetPixelProc := GetPixel24BitsVesa;
         RGBToColor := RGBTo24Bits;
         PrepareColors;
         end
         else exit;
end; {case}
SetMode := true;
end;
 
Следующие две подпрограммы реализуют привычный интерфейс включения/выключения видеорежима.
 
function InitGraph( ModeIndex : word ): boolean;
begin
InitGraph := SetMode( ModeIndex );
end;
 
procedure ExitGraph;
begin
if SetMode( VESAText ) then;
end;
 
При установке видеорежима позиция и границы текущего окна совпадают с границами экрана дисплея. Для задания новых параметров окна достаточно создать следующую процедуру:
 
procedure SetWindow( MinX, MinY, MaxX, MaxY : word );
begin
with WinRect do begin
 if MinX>Screen.Width-1 then MinX:=Screen.Width-1;
 Left:=MinX;
 if MinY>Screen.Height-1 then MinY:=Screen.Height-1;
 Top:=MinY;
 if MaxX>Screen.Width-1 then MaxX:=Screen.Width-1;
 Right:=MaxX;
 if MaxY>Screen.Height-1 then MaxY:=Screen.Height-1;
 Bottom := MaxY;
 Width := (Right-Left)+1;
 Height := (Bottom-Top)+1;
 end;
end;
 
При вызове данной процедуры параметры текущего окна задаются в глобальных координатах всего экрана (в пикселях), после чего вывод графики в окне производится в локальных координатах относительно верхнего левого угла окна (0,0). Если возникнет необходимость вернуться к исходному окну, то это легко осуществить с помощью следующей процедуры:
 
procedure DefaultWindow;
begin
with WinRect do begin
         Left := 0;
         Top := 0;
         Right := Screen.Width-1;
         Bottom := Screen.Height-1;
         Width := Screen.Width;
         Height := Screen.Height;
         end;
end;
 
Следующие две процедуры предназначены для чтения/установки текущей палитры для 256-цветных режимов отображения. Для этого используются функции $1017 и $1012 BIOS’а соответственно.
 
procedure GetPalette( var Palette ); assembler;
asm
 mov ax,1017h; mov bx,0; mov cx,256
 les dx,Palette; int 10h
end;
 
procedure SetPalette( var Palette ); assembler;
asm
 mov ax,1012h; mov bx,0; mov cx,256
 les dx,Palette; int 10h
end;
 
На всякий случай оформим процедуру установки текущей страницы видеопамяти для отображения в видеобуфере.
 
procedure SetPage( Index : word ); assembler;
asm
 mov dx,Index; mov LastPage,dx; mov ax,4f05h
 xor bx,bx; int 10h
end;
 
Следующая функция позволяет определить, является ли видеоадаптер VGA-совместимым. Для этого вызывается подфункция 0 функции $1A BIOS’а для получения кода сочетания дисплея. Если функция возвращает значение $1A в регистре AL, то эта функция поддерживается, и тогда можно по значению в регистре BL определить тип дисплея: $00 – нет дисплея; $07 – монохромный VGA; $08 – цветной VGA; $FF – неизвестный тип дисплея. При успехе функция возвращает true.
 
function IsVGA : boolean; assembler;
asm
 mov ah,1ah; mov al,00h; int 10h; cmp al,1ah
 jne @NoVGA
 cmp bl,07h; je @VgaPresent
 cmp bl,08h; je @VgaPresent
@NoVGA: xor ax,ax; jmp @end
@VgaPresent: mov al,1
@end:
end;
 
Ещё одна процедура, о которой уже слагают легенды ;0) позволяет дождаться момента, когда луч ЭЛТ-монитора начнёт свой обратный ход из нижней строки в верхнюю. Обычно в момент обратного хода луча экран выключен и бит 3 (считать от нуля) регистра состояния дисплея, который доступен для чтения через порт $3DA, установлен в единицу. При этом, если в этот момент рисовать точки на экране, то это позволит избежать побочного эффекта "хлопьев" или мерцания изображения.
 
procedure WaitRetrace; assembler;
asm
 mov dx, 3DAh
@L1: in al,dx; and al,08h; jnz @L1
@L2: in al,dx; and al,08h; jz @L2
end;
 
Наконец, модуль можно завершить блоком инициализации.
 
begin
PutPixelProc := NilProc;
GetPixelProc := NilFunc;
RGBToColor := NilRGBFunc;
end.
 
Подпрограммы данного модуля обеспечивают лишь самые примитивные манипуляции с графикой. Чтобы иметь возможность рисовать на экране линии, окружности, эллипсы, прямоугольники, закрашивать сложные фигуры, рисовать текст и выводить и масштабировать изображения в формате BMP могут пригодиться модули SBRUSH.PAS, FONTS.PAS и BITMAPS.PAS вашего покорного слуги. ;O)
  
Эти модули базируются на возможностях модуля, описанного в данной статье. Освещение этих модулей могло бы занять ещё много страниц МК, поэтому я не стану испытывать терпение редакции, и не буду ущемлять других авторов, отбирая у них свободные страницы МК, чем обрекаю себя на голодную смерть ;о) , а просто предложу вам самим скачать с выше указанного сайта все эти модули вместе с примерами и самостоятельно разобраться в них.
 
Данный титанический труд вынудил меня составить материал объёмом, равным трём статьям. Спасибо вам за терпение, с которым вы смогли прочесть данный толмут. ;0)
 
Продолжение следует…
 
© Владислав Демьянишин
 

Литература

1. Диалоговая справочная система Norton Guide.
2. VESA BIOS EXTENSION (VBE) Core Functions Version: 2.0
3. Interrupt list by Ralf Brawn v.3.3.
 
Вы находитесь на официальном сайте Владислава Демьянишина - разработчика игры Dune IV (Dune 4). На нашем сайте Вы можете бесплатно скачать игры Dune IV (Dune 4), Battle City (Танчики с Dendy/Nintendo), читы к играм и многое другое. Также Вы можете скачать бесплатно программы и полезные утилиты. Все программы чистые, т.е. не содержат вирусов и иного вредоносного ПО. Предлагаю также посетить Марья искусница - сайт о рукоделии (http://mariya-iskusnica.ru).
 
 
 

Журнал > Программирование > Паскаль для новичков (Turbo Pascal, Assembler) > Паскаль для новичков (часть 40): Работаем с графическим режимом 3 (продолжение)
 
 
 
351
 
ВКонтакте
Facebook
 
 
 
На главную страницу На предыдущую страницу На начало страницы
 
 
Рейтинг@Mail.ru Рейтинг Сайтов YandeG