Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Листинг 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 Уфф... Вот и все, ребята! Заключение В этой главе мы изучили некоторые нетривиальные приемы управления работой персонального компьютера. Мы узнали, как работает таймер, как можно использовать прерывания (включая и клавиатурные) и многое другое. Мы научились писать обработчики прерываний на языке Си и регистрировать их в таблице векторов прерываний. Кроме того, мы узнали много полезного о том, как при помощи автономных функций и функций ответа можно организовать на персональном компьютере синхронизацию программы и обработку наступления определенных событий. И, в конце концов, мы использовали полученные знания Для написания нескольких программ, которые брали на себя управление компьютером - одна из этих программ даже не пожелала вернуть управление обратно!
|