Студопедия

Главная страница Случайная страница

КАТЕГОРИИ:

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Листинг 12.7. Киберточка (CYBER.C)._____






// ВКЛЮЧАЕМЫЕ ФАЙЛЫ///////////////////////////////////////

#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

Уфф... Вот и все, ребята!

Заключение

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

Мы научились писать обработчики прерываний на языке Си и регистрировать их в таблице векторов прерываний. Кроме того, мы узнали много полезного о том, как при помощи автономных функций и функций ответа можно организовать на персональном компьютере синхронизацию программы и обработку наступления определенных событий.

И, в конце концов, мы использовали полученные знания Для написания нескольких программ, которые брали на себя управление компьютером - одна из этих программ даже не пожелала вернуть управление обратно!


 


Поделиться с друзьями:

mylektsii.su - Мои Лекции - 2015-2024 год. (0.01 сек.)Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав Пожаловаться на материал