Отправляет email-рассылки с помощью сервиса Sendsay

Все обо всем

  Все выпуски  

Все обо всем Выпуск от 27.04.2003


Информационный Канал Subscribe.Ru


Все обо всем
╧3 27.04.2003


{см. начало в предыдущем номере}

В прошлом номере в качестве языка программирования был указан ассемблер, но пример программы был дан на си. Это связано с тем, что я не сразу нашел в своем архиве готовый пример, демонстрирующий описываемые возможности. Но в последствии я нашел необходимую программу и вставил ее в рассылку, забыв исправить язык программирования. В сущности, это ни на что не повлияло (я надеюсь...)

Как я и обещал, в данном номере я расскажу как рисовать пиксели в выше описанных видеорежимах.

Многие современные видеоадаптеры применяют давно известный прием, ранее использовавшийся для подключения к компьютеру дополнительной памяти. Центральный процессор получает доступ к видеопамяти через небольшое окно. Это окно может иметь небольшой размер - до 64 Кбайт - и располагаться в адресном пространстве процессора. Обычно окно занимает адресное пространство AООО:0ОООh - AOOO:FFFFh, то есть расположено так же, как и для стандартных цветных режимов видеоадаптеров EGA, VGA и SVGA. Процессор компьютера может перемещать это окно по всей видеопамяти адаптера, получая доступ к разным ее участкам. Таким образом, процессор может одновременно получить доступ только к части видеопамяти. Чтобы обратиться к другому участку видеопамяти, необходимо переместить окно доступа. Обычно для этого достаточно записать в определенный регистр видеоадаптера SVGA положение окна относительно начала видеопамяти. Доступ к видеопамяти через небольшое окно создает определенные трудности для программного обеспечения. Теперь, чтобы отобразить на экране монитора пиксел, вы должны не только вычислить положение соответствующей ячейки видеопамяти, но также определить смещение для окна доступа. Одновременно усложняются процедуры, отображающие на экране линии и другие геометрические фигуры. Возможно, что выводимое на экран изображение не помещается в одно окно. Процедура должна будет соответственно перемещать окно по видеопамяти.

Центральный процессор получает доступ к видеопамяти адаптера через окно небольшого размера. Функция 4F05h позволяет позиционировать окно по видеопамяти и определять его текущее положение. Окно может позиционироваться с определенным шагом.

Функция 4F05h выполняет две операции, выбираемые регистром ВН. Первая операция ВН = О позволяет переместить окно в определенную позицию.

На входе:
   АН 4Fh
   AL 05h
   ВН OOh Выбор окна видеопамяти
   BL Номер окна: 0 - окно А, 1 - окно В
   DX Адрес окна видеопамяти (в единицах шага)
На выходе:
   AL 4Fh
   АН Результат: О-в случае успешного завершения, 1 - в случае ошибки

Вторая операция ВН = 1 определяет текущее положение окна:

На входе:
   АН 4Fh
   AL 05h
   ВН Olh Определить адрес окна видеопамяти
   BL Номер окна: 0 - окно А, 1 - окно В
На выходе:
   AL 4Fh
   АН Результат: О-в случае успешного завершения, 1 - в случае ошибки
   DX Адрес окна видеопамяти (в единицах шага)

Пример программы, демонстрирующей непосредственный доступ центрального процессора к видеопамяти адаптера, работающего в режиме VESA. В качестве параметра вы должны указать программе режим VESA. Заметим, что программа предназначена для графических режимов, имеющих один цветовой слой, плоскую последовательную модель памяти (номер 4) в которых для каждого пиксела отводится 8 бит (256 цветов). Дчя упрощения исходного текста программы мы предполагаем, что окно доступа А можно использовать для записи данных в видеопамять. В качестве примера такого режима можно привести режим 103h, который имеет разрешение 800x600 пикселов и может одновременно отображать 256 различных цветов.

#include  
#include  
#include  
#include  
#include   "vesa.h"
#include   "sysp.h"
//   Описание  функций
int main(int  argc,   char*   argv[]);
int GetVESAModelnfо(unsigned, VESAINFO*, VESAMODEINFO*);
int AnalyseResult(union  REGS);
int SetSVGAMode(unsigned);
void WritePixel(VESAMODEINFO*, unsigned, unsigned, unsigned  char);

//  Главная функция
int main(int argc, char* argv[])
{
//   Структуры для получения  информации о VBE
VESAINFO vesalnfo;
VESAMODEINFO modelnfo;
unsigned modeVESA;
int  iResult,x,y;

// Проверка командной строки программы
if( argc != 2 )
  {
  printf ( "\nФормат вызова: VESATEST <режим>\n<режим>: режим видеоадаптера");
  return -1;
  }
sscanf(argv[ 1] , "%х", SmodeVESA);

// Записываем в структуры vesaInfo и modeInfo
// информацию о VBE и видеоадаптере
iResult = GetVESAModelnfo(modeVESA, &vesalnfo, &modelnfo);
if(iResult != 0)
  {
  printf ( "\nВыбранный вами режим не поддерживается");
  return -1;
  }

if(
  // Атрибуты окна А - доступно для записи
  ((modeInfo.ucWinAAttr & 5) != 5) ||
  // Количество слоев видеопамяти - один
  (modeInfo.ucNumPlanes != 1) ||
  // Количество бит на пиксел - восемь (256 цветов)
  (modeInfо.ucNumPixelBits != 8) ||
  // Тип модели памяти (плоская, последовательная)
  (modeInfо.ucTypeMemModel != 4))
  {
  printf("\nПрограмма не рассчитана на этот режим");
  return -1;
  }
iResult = SetSVGAMode(modeVESA);

if(iResult != 0)
  {
  printf("\nОшибка при установке режима видеоадаптера");
  return -1;
  }

// Отображаем линию, выходящую из левого верхнего угла
// монитора под углом 45 градусов
for(х = 0; х<6ОО; х++)
  WritePixel(&modeInfo, x, х, х%256);

// Ожидаем, когда пользователь нажмет на клавиатуру
getch();

// Возвращаемся в стандартный текстовый режим
_asm mov  ax,3
_asm int  10h
return 0;
}

// Функция GetVESAModelnfо
// Заполняет структуры типа VESAINFO и VESAMODEINFO
// сведениями о VBE и режиме modeVESA
int GetVESAModelnfo(unsigned modeVESA, VESAINFO *ptrVesaInfо, VESAMODEINFO  *ptrModeInfо)
{
union REGS regs;
struct SREGS segregs;
int iResult, i;

// Подготавливаем буфер для VBE версии 2.0
strcpy(ptrVesaInfo->cSignature, "VBE2" );

// Получаем данные о реализации VBE и видеоадаптере
regs.h.ah = Ox4f;
regs.h.al = 0x00;
segregs.es = FP_SEG((void far *) ptrVesalnfo);
regs.x.di = FP_OFF((void far *) ptrVesalnfo);
int86x(0x10, ®s, ®s, &segregs);

// Проверяем результат вызова функции VBE
if((regs.h.al != Ox4f) || (regs.h.ah != 0))
  return -1;

// Теперь получаем информацию для выбранного режима VESA
for( i=0; i<50; i++ )
  {
  // Выполняем поиск режима modeVESA
  if(ptrVesa!nfo->fpModeTable[i] == OxFFFF)
    break;
  if(ptrVesalnfo->fpHodeTable[i] != modeVESA)
    continue;
  // Получаем информацию о режиме vesalnfo.fpModeTable[i]
  regs.h.ah = Ox4f;
  regs.h.al = 0x01;
  regs.x.ex = ptrVesalnfo->fpModeTable[i];
  segregs.es = FP_SEG((void far *) ptrModelnfo);
  regs.x.di = FP_OFF((void far *) ptrModelnfo);
  int86x(0x!0, ®g, ®s, &segregs);

  // Проверяем результат вызова функции VBE
  if((regs.h.al != Ox4f) || (regs.h.ah != 0))
    return -1;
  else
    return 0;
  }
return iResult;
}

// Функция SetSVGAMode
// Устанавливает режим vmode

int  SetSVGAMode(unsigned vmode)
{
union REGS regs;
int  iResult;
regs.h.ah = Ox4f;
regs.h.al = 0x02;
regs.x.bx = vmode;
int86(0x10, ®s, ®s);
if((regs.h.al == 0x4f) && (regs.h.ah == 0))
  return 0;
else
return -1;
}

// Функция SetSVGAMode
// Отображает на экране пиксел (х,у) цветом color
// Переменная ptrModelnfo должна содержать указатель
// на заполненную структуру VESAMODEINFO

void WritePixel(VESAMODEINFO  *ptrMode!nfо, unsigned x, unsigned y, unsigned char color)
{
unsigned char _far *ptr_vbuf;
unsigned long  ulWinPos, uloffset, ulWinOffset;
unsigned uWinPos;

// Вычисляем смещение пиксела от начала видеопамяти
ulOffset = (unsigned long) y * (unsigned long) ptrMode!nfo->usBytesPerScanLine + (unsigned long) x;

// Вычисляем положение окна доступа для отображения
// пиксела (х,у)
uWinPos = ((unsigned long) uloffset /
(unsigned long) (ptrMode!nfo->usWinGranularity) ) / 1024;

// Перемещаем окно А в положение uWinPos
_asm {
mov  ax,4F05h
mov  bh , 0
mov  bl , 0
mov  dx,uWinPos
int  10h
}

// Определяем адрес окна доступа А
ptr_vbuf = (unsigned char _far *) FP_MAKE(ptrModeInfo->usBegSegA,0) ;

// Определяем смещение пиксела (х,у) относительно окна
// доступа
ulWinOffset = uloffset % ((unsigned long) (ptrHode!nfo->usWinGranularity) *1024 ) ;
// Устанавливаем новый цвет пиксела *(ptr_vbuf + ulWinOffset) = color;

Из "Программирование видеоадаптеров" А.В.Фролов, Г.В.Фролов

В программе используются вызовы функций из библиотек, приводимых в программе, но разобраться можно и так.. Но ежели все-таки возникнут вопросы - пишите!


E-mail: k_rusin@tut.by


http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное