КаталогИндекс раздела
НазадОглавлениеВперед


Лабораторная работа N7
УПРАВЛЕНИЕ ВИДЕОАДАПТЕРОМ

1. Цель работы

Изучение особенностей функционирования видеосистемы в текстовом режиме и получение практических навыков работы с видеомонитором в этом режиме.

2. Темы для предварительного изучения

3. Постановка задачи

Применяя прямую запись в видеопамять получить на экране оригинальный, желательно динамический видеоэффект. Возможны (но не обязательны) такие варианты видеоэффектов:

4. Порядок выполнения

Порядок выполнения работы и содержание отчета определены в общих указаниях.

5. Пример решения задачи

5.1. Индивидуальное задание.

5.4. Разработка алгоритм решения

5.4.1. Структура программы

Программа состоит из основной функции main() и семи вспомогательных функций.

5.4.2. Описание переменных

Переменные, глобальные для всей программы:

Координаты участка задаются в пределах: X - [0..7], Y - [0..4] .

5.4.3. Описание алгоритма программы

Основная функция main() проверяет, был ли в командной строке дополнительный параметр. Если нет, программа не очищает старый экран. Если какой-нибудь параметр был, то экран очищается и выводится инструкция по управлению программой. Далее в основной программе выполняется бесконечный цикл, в котором обрабатываются коды нажатых клавиш и, в зависимости от них, вызываются вспомогательные функции. Выход из цикла - по клавише Esc.

Функции GetSym(x1,y1), GetAtr(x1,y1) читают непосредственно из видеопамяти дисплея символ и атрибут соответственно.

Функции PutSym(x1,y1,sym), PutAtr(x1,y1,atr) выводят непосредственно в видеопамять дисплея символ и атрибут соответственно.

Во всех этих четырех функциях координаты задаются в квадрате 79х24 символов (нумерация начинается с нуля).

Функция Invert(x1,y1) использует функции GetAtr и PutAtr для инверсии прямоугольника экрана размером 10х5 по маске 0x7f, при этом независимо выполняется инверсия фона и цвета символа.

Функция Change(x,y) обменивает содержимое текущего участка с содержимым левого верхнего участка путем последовательного побайтного обмену атрибутов и символов. Она использует функции GetSym, GetAtr, PutSym, PutAtr.

Функция RandText(void) - псевдослучайным образом перетасовывает все участки на экране, при этом она в цикле увеличивает на единицу локальные в данной функции координаты текущего участка xk, yk и обращается к функции Change. Таким образом достигается эффект перемешивания. Функция работает, пока не будет нажата любая клавиша.

5.5. Текст программы

/*-----------------Лабораторная работа N7-----------------*/
/*---------------Управление видеоадаптером.---------------*/
#include <dos.h>


#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
/*-----------------------Константы----------------------- */
#define VSEG 0xb800       /* Сегментный адрес видеопамяти */
#define byte unsigned char


#define word unsigned int
#define Esc 27
#define Spase 32
#define Enter 13
#define Up 0x48
#define Down 0x50
#define Left 0x4b
#define Right 0x4d
#define Home 0x47
int xk,yk;
/*--------------Чтение символа из видеопамяти-------------*/
byte GetSym(x1,y1)
int x1,y1;
{
 return(peekb(VSEG,y1*160+x1*2));
}
/*-------------Чтение атрибута из видеопамяти-------------*/
byte GetAtr(x1,y1)
int x1,y1;
{
 return(peekb(VSEG,y1*160+x1*2+1));
}
/*-------------Запись символа в видеопамять--------------*/
void PutSym(x1,y1,sym)
int x1,y1;
byte sym;
{
 pokeb(VSEG,y1*160+x1*2,sym);
}
/*-------------Запись атрибута в видеопамять--------------*/
void PutAtr(x1,y1,atr)
int x1,y1;
byte atr;
{
 pokeb(VSEG,y1*160+x1*2+1,atr);
}
/*------------Инверсия квадрата на экране-----------------*/
void Invert(x1,y1)
int x1,y1;
{
 byte b;
 int i,j;
 for (j=0;j<5;j++)
  for (i=0;i<10;i++)
   {
    b=GetAtr(x1*10+i,y1*5+j);
    PutAtr(x1*10+i,y1*5+j,(b^0x7f));
   }
}
/*-------Замена текущего квадрата на левый верхний--------*/
void Change(x,y)
byte x,y;
{
 int i,j;
 byte ba,bs;
 if ((x!=0)||(y!=0))
  for (j=0;j<5;j++)
   for (i=0;i<10;i++)
    {
     bs=GetSym(x*10+i,y*5+j);
     ba=GetAtr(x*10+i,y*5+j);
     PutSym(x*10+i,y*5+j,GetSym(i,j));
     PutAtr(x*10+i,y*5+j,GetAtr(i,j));
     PutSym(i,j,bs);
     PutAtr(i,j,ba);
    }
}
/*------Перемешивание квадратов до нажатия клавиши------*/
void RandText(void)
{
 Invert(xk,yk);
 xk=5;
 yk=1;
 while(!kbhit())
 {
  Change(xk,yk);
  xk++;
  if (xk>7) xk=0;
  yk++;
  if (yk>4) yk=0;
 }
 Invert(xk,yk);
}
/*----------------Начало основной программы---------------*/
main(int argn,char *argc[])
{
int i;

xk=0;
yk=0;
if (argn>1){}
else            /* Если параметров нет, вывод инструкции */
{
textattr(10);
clrscr();
cprintf("---------------");
cprintf("              Лабораторная работа N7              ");
cprintf("---------------");
cprintf("---------------");
cprintf("            Управление видеоадаптером.            ");
cprintf("---------------");
textattr(15);
gotoxy(23,4);cprintf("Демонстрация работы с видеопамятью.");
textattr(12);
gotoxy(30,6);cprintf("<< М О З А И К А >>");
textattr(14);
gotoxy(30,8);cprintf("Клавиши управления:");
gotoxy(7,10);cprintf("< Left, Right, Up, Down> - ");

             cprintf("управление выделенним квадратом.");
gotoxy(7,11);cprintf("<Spase Bar> - Обмен содержимым ");
             cprintf("между выделенным квадратом");
gotoxy(7,12);cprintf("           и левым верхним");
             cprintf(" квадратом.");
gotoxy(7,13);cprintf("<Enter> - перемешивание квадратов");
             cprintf(" до нажатия любой клавиши.");
gotoxy(7,14);cprintf("<Esc> - вихiд.");
textattr(11);
gotoxy(28,16);cprintf("З А Д А Ч А   И Г Р И :");
gotoxy(14,17);cprintf("Собрать при помощи клавиш ");
              cprintf("управления начальный экран.");
textattr(12);
gotoxy(27,19);cprintf("Ж е л а е м  у с п е х а !");
textattr(7);
gotoxy(1,21);cprintf("Примечание: При запуске с ");
              cprintf("параметром <->");
gotoxy(13,22);cprintf("начальным экраном для игри ");
              cprintf("является текущий.");
}
Invert(xk,yk);
 for(i=0;i==0;)
  switch(getch())
  { /* Обработка нажатых клавиш */
   case Esc:  i++; break;
   case Enter:RandText();break;
   case Spase:Invert(xk,yk);
              Change(xk,yk);
              Invert(xk,yk);
              break;
   case 0:
      switch (getch()) {
         case  Left:Invert(xk,yk);
                    xk--;
                    if(xk<0) xk=7;
                    Invert(xk,yk);
                    break;
         case Right:Invert(xk,yk);
                    xk++;
                    if(xk>7) xk=0;
                    Invert(xk,yk);
                    break;
         case    Up:Invert(xk,yk);
                    yk--;
                    if(yk<0) yk=4;
                    Invert(xk,yk);
                    break;
         case  Down:Invert(xk,yk);
                    yk++;
                    if(yk>4) yk=0;
                    Invert(xk,yk);
                    break;
          }
  }
Invert(xk,yk);
}

5.6. Результаты работы программы

Результаты работы программы выводятся на экран терминала и меняются интерактивно.


КаталогИндекс раздела
НазадОглавлениеВперед