Читайте также: |
|
// ВКЛЮЧАЕМЫЕ ФАЙЛЫ///////////////////////////////////////
#include <dos.h>
#include <bios.h>
#include <stdio.h>
#include <math.h>
#include <conio.h>
#include <graph.h>
// ОПРЕДЕЛЕНИЯ //////////////////////////////////////////
#define KEYBOARD_INT 0х09
#define KEY_BUFFER 0х60
#define KEY_CONTROL 0х61
#define INT_CONTROL 0х20
// коды нажатия и отпускания для клавиш со стрелками
#define MAKE_RIGHT 77
#define MAKE_LEFT 75
#define MAKE_UP 72
#define MAKE_DOWN 80
#define BREAK__RIGHT 205
#define BREAK_LEFT 203
#define BREAK_UP 200
#define BREAK_DOWN 208
// индексы в таблице состояния клавиш со стрелками
#define INDEX_UP 0
#define INDEX_DOWN 1
#define INDEX_RIGHT 2
#define INDEX_LEFT 3
// ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ////////////////////////////////
void (_interrupt _far *01d_Isr)(void);
// хранит старый обработчик прерывания
unsigned char far *video_buffer = (char far *)0xA0000000L;
// указатель на видеобуфер
int raw_key; // необработанные данные от клавиатуры
int key_table[4] = {0,0,0,0};
// таблица состояний клавиш со стрелками
// ФУНКЦИИ //////////////////////////////////////////////
void Plot_Pixel_Fast(int x,int y,unsigned char color)
{
// эта функция рисует точку заданного цвета несколько быстрее,
// чем обычно за счет применения операции сдвига вместо операции
// умножения
// используем известный факт, что 320*у = 256*у + 64*у = у<<8 + у<<6
video_buffer[((y<<8) + (у<<6)) + х] = color;
} // конец Plot_Pixel_Fast
/////////////////////////////////////////////
void Fun_Back(void)
{
int index;
// несомненно запоминающийся рисунок фона
_setcolor(1);
_rectangle(_GFILLINTERIOR, 0,0,320,200);
_setcolor{15);
for (index=0; index<10; index++)
{
_moveto(16+index*32,0);
_lineto(16+index*32,199);
} // конец цикла
for (index=0; index<10; index++)
{
_moveto(0,10+index*20);
_lineto(319,10+index*20);
} // конец цикла
} // конец Fun Back ///////////////////////////////////////
void _interrupt _far New_Key_Int(void)
{
// я в настроении немного попрограммировать на ассемблере!
_asm{
sti; разрешаем прерывания
in al,KEY BUFFER; получаем нажатую клавишу
xor ah,ah; обнуляем старшие 8 бит регистра АХ
mov raw_key, ax; сохраняем код клавиши
in al,KEY_CONTROL; читаем управляющий регистр
or al,82h; устанавливаем необходимые биты для сброса FF
out KEY_CONTROL,al; посылаем новые данные в управляющий регистр
and al,7fh
out KEY_CONTROL,al; завершаем сброс
mov al,20h
out INT CONTROL,al; завершаем прерывание
} // конец ассемблерной вставки
// теперь вернемся К Си, чтобы изменить данные
// в таблице состояния клавиш со стрелками
// обработка нажатой клавиши и изменение таблицы
switch(raw_key)
{
case MAKE_UP: // нажатие стрелки вверх
{
key_table[INDEX_UP] = 1;
} break;
case MAKE_DOWN: // нажатие стрелки вниз
{
key_table[INDEX_DOWN] = 1;
) break;
case MAKE_RIGHT: // нажатие' стрелки вправо
{
key_table[INDEX_RIGHT] = 1;
} break;
case MAKE_LEFT: // нажатие стрелки влево
{
key__table[INDEX_LEFT] = 1;
} break;
case BREAK_UP: // отпускание стрелки вверх
{
key_table[INDEX_UP] = 0;
} break;
case BREAK DOWN: // отпускание стрелки вниз
{
key_table[INDEX_DOWN] = 0;
} break;
case BREAK_RIGHT; // отпускание стрелки вправо
{
key_table[INDEX_RIGHT] = 0;
} break;
case BREAK_LEFT: // отпускание стрелки влево
{
key_table[INDEX_LEFT] = 0;
} break;
default: break;
} // конец оператора switch
} // конец New_Key_Int
// ОСНОВНАЯ ПРОГРАММА ////////////////////////////////
void main(void)
{
int dопе=0, x=160, y=100;// флаг выхода и координаты точки
//установка видеорежима 320x200x256
_setvideomode(_MRES256COLOR);
Fun_Back(); // оригинальная картинка, не так ли?
printf("\nPress ESC to Exit.");
// установка нового обработчика прерывания
Old_Isr = _dos_getvect(KEYBOARD_INT);
_dos_setvect(KEYBOARD_INT, New_Key_Int);
// основной цикл
while(!done)
{
_settextposition(24,2);
printf("raw key=%d ",raw_key);
// смотрим в таблицу и перемещаем маленькую точку
if (key_table[INDEX_RIGHT]) х++;
if (key_table[INDEX_LEFT]) х--;
if (key_table[INDEX_UP]) y--;
if (key_table[INDEX_DOWN]) y++;
// рисуем киберточку
Plot_Pixel_Fast(x,y,10);
// Наша клавиша завершения. Значение кода нажатия ESC равно 1
if (raw_key==1) done=l;
} // конец while
// восстановление старого обработчика прерывания
_dos_setvect(KEYBOARD_INT, Old_Isr);
_setvideomode (_DEFAULTMODE);
} // конец функции main
Уфф... Вот и все, ребята!
Заключение
В этой главе мы изучили некоторые нетривиальные приемы управления работой персонального компьютера. Мы узнали, как работает таймер, как можно использовать прерывания (включая и клавиатурные) и многое другое.
Мы научились писать обработчики прерываний на языке Си и регистрировать их в таблице векторов прерываний. Кроме того, мы узнали много полезного о том, как при помощи автономных функций и функций ответа можно организовать на персональном компьютере синхронизацию программы и обработку наступления определенных событий.
И, в конце концов, мы использовали полученные знания Для написания нескольких программ, которые брали на себя управление компьютером - одна из этих программ даже не пожелала вернуть управление обратно!
Дата добавления: 2015-07-12; просмотров: 149 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Листинг 12.6. Трехмерное звездное небо (STARS.C). | | | ИСКУССТВЕННЫЙ ИНТЕЛЛЕКТ |