Читайте также: |
|
// ВКЛЮЧАЕМЫЕ ФАЙЛЫ,///////////////////////////////////
#include <dos.h>
#include <bios.h>
#include <stdio.h>
#include <math.h>
#include <conio.h>
#include <graph.h>
// ОПРЕДЕЛЕНИЯ ////////////////////////////////////////
#define JOYPORT 0х201 // порт джойстика - 201h
#define BUTTON_1_A 0х10 // джойстик А, кнопка 1
#define BUTTON_1 В 0х20 // джойстик А, кнопка 2
#define BUTTON_2_A 0х40 // джойстик В, кнопка 1
#define BUTTON_2_B 0х80 // джойстик В, кнопка 2
#define JOYSTICK_1_X 0х01 // джойстик А, ось Х
#define JOYSTICK_1_Y 0х02 // джойстик А, ось Y
#define JOYSTICK_2_X 0х04 // джойстик В, ось Х
#define JOYSTICK_2_Y 0х08 // джойстик В, ось Y
#define JOY_1_CAL 1 // команда калибровки джойстика А
#define JOY_2_CAL 2 // команда калибровки джойстика В
// ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ///////////////////////////////////
unsigned int
joy_1_max_x, // глобальные переменные для сохранения
joy_1_max_y, // калибровочных значений
joy_1_min_x,
joy_l_min_y,
joy_1_cx, joy_1_cy,
joy_2_max_x, joy_2_max_y,
joy_2_min_x, joy_2_min_y,
joy_2_cx, joy_2_cy;
// ФУНКЦИИ //////////////////////////////////////////////
unsigned char Buttons(unsigned char button)
{
// функция читает статус кнопок джойстика
outp(JOYPORT,0); // получаем запрос на получение статуса кнопок
// инвертируем полученное значение и комбинируем его с маской
return (~inp(JOYPORT) & button);
} //конец функции ///////////////////////////////////////////////////////
unsigned int Joystick(unsigned char stick)
{
// Функция читает положение счетчика на основании количества
// циклов, прошедших между сбросом и установкой бита в порту
// джойстика. Встроенный ассемблер - прекрасная вещь!
_asm{
cli; запрещаем прерывания
mov ah, byte ptr stick; в регистр АН заносим маску
; для выбора джойстика
хоr аl,аl; обнуляем AL
хоr сх,сх; обнуляем СХ
mov dx,JOYPORT; в DX помещаем номер порта джойстика
out dx,al; обнуляем содержимое порта
discharge:
in al,dx; читаем данные из порта
test al,ah; установился ли бит?
loopne discharge; если нет - повторяем чтение
sti; разрешаем прерывания
хог ах,ах; обнуляем АХ
sub ах,сх; теперь АХ содержит искомое значение
} // конец ассемблерного блока
} // конец функции
//////////////////////////////////////////////////////
unsigned int Joystick_Bios(unsigned char stick)
(
// версия функции чтения состояния джойстика
// работающая через BIOS
union _REGS inregs, outregs;
inregs.h.ah = 0х84; // нам нужна функция 84h
inregs.x.dx = 0х01;
// подфункция 01h - чтение состояния джойстика
_int86(0х15,&inregs, &outregs); // вызываем BIOS
// возвращаем требуемое значение
switch(stick)
{
case JOYSTICK_1_X:
{
return(outregs.x.ax);
} break;
case JOYSTICK1_Y:
{
return(outregs. x. bx};
} break;
case JOYSTICK_2_X:
{
return(outregs.x.ex);
} break;
case JOYSTICK_2_Y:
{
return(outregs.x.dx);
} break;
default:break;
} // конец оператора switch
} // конец функции
///////////////////////////////////////////////////////
unsigned char Buttons_Bios(unsigned char button)
{
// версия функции для чтения статуса кнопок джойстика,
// работающая через BIOS
union _REGS inregs, outregs;
inregs.h.ah = 0х84; // обращение к джойстику - функция 84h
inregs.x.dx = 0х00; // подфункция 0 - чтение статуса кнопок
_int86 (0х15, &inregs, &outregs);
// инвертируем результат и комбинируем с переданной маской
return((~outregs.h.al) & button);
} // конец функции //////////////////////////////////////////////////////
void Joystick_Calibrate(int stick)
{
// функция выполняет калибровку джойстика путем нахождения
// минимального и максимального значений по осям Х и У. Затем
// полученные значения сохраняются в глобальных переменных.
unsigned int x_new,у_new; // позиция джойстика
if (stick==JOY_1_CAL) {
printf("\nCalibrating Joystick #1: Swirl stick, then release it and press FIRE");
// придаем переменным заведомо невозможные значения
joy_1_max_x=0;
joy_1_max_y=0;
joy_1_min_x=10000;
joy_1_min_y=10000;
// пользователь должен покрутить джойстик, поставить его в среднее
// положение и затем нажать любую кнопку
while(!Buttons(BUTTON_1_A | BUTTON_1_B))
{
// читаем новые значения потенциометра и пытаемся улучшить
// калибровку
x_new = Joystick_Bios(JOYSTICK_1_X);
y_new = Joystick_Bios(JOYSTICK_1_Y};
// обрабатываем ось X
if (x_new >= joy_1_max x) joy_1_max x = x_new;
if (x_new <= joy_1_min_x) joy_1_min_x = x_new;
// обрабатываем ось Y
if (y_new >= joy_1_max_y) joy_1_max_y = y_new;
if (y_new <= joy_1_ min y) joy_1_min у = у_new;
} // конец цикла while
// получаем значения потенциометра, соответствующие нейтральному
// положению
joy_1_cx = x_new;
joy_l_cy = y_new;
} // конец калибровки джойстика А
else
if (stick==JOY_2_CAL)
{
printf("\nCalibrating Joystick #2: Swirl stick, then release it and pres's FIRE");
// придаем переменным заведомо невозможные значения
joy_2_max x=0;
joy_2_max_y=0;
joy_2_min_x=10000;
joy_2_min_y=10000;
// пользователь должен покрутить джойстик, поставить его в
// нейтральное положение и нажать любую кнопку
while(!Buttons(BUTTON_2_A | BUTTON_2_B))
{
// читаем значение потенциометра и пытаемся улучшить калибровку
x_new = Joystick (JOYSTICK_2_X);
y_new = Joystick(JOYSTICK_2_Y);
// обрабатываем ось Х
if (x_new >= joy_2_max_x)
joy_2_max x = x_new;
else if (x_new <= joy_2_min_x)
joy_2_min_x = x_new;
// обрабатываем ось Y
if (y_new >=joy_2_max_y)
joy_2_max_y = y_new;
else if (y_new <= joy_2_min_y)
joy_2_min_y = y_new;
} // конец цикла while
// читаем значения, соответствующие нейтральному положению
joy_2_cx = x_new;
joy_2_су = y_new;
} // конец калибровки джойстика В
printf ("\nCalibration Complete... hit any key to continue.");
getch();
} // конец функции калибровки джойстика
// ОСНОВНАЯ ПРОГРАММА ////////////////////////////////////////
void main(void) (
// калибруем джойстик
Joystick_Calibrate(JOY_1_CAL);
_clearscreen(_GCLEARSCREEN);
// даем пользователю поиграть с джойстиком
while(!kbhit())
{
_settextposition(2,0);
printf("Joystick 1 = [%u,%u] ", Joystick__Bios(JOYSTICK_1_X), Joystick_Bios(JOYSTICK_1_Y));
if (Buttons_Bios(BUTTON_1_A))
printf("\nButton 1 pressed ");
else if (Buttons_Bios(BUTTON_1_B))
printf("\nButton 2 pressed ");
else
printf("\nNo Button Pressed ");
} // конец цикла while
// даем пользователю посмотреть, на калибровочные данные
printf("\nmax x=%u/ max y=%u,min x=%u,min y=%u, cx=%u, cy=%u", joy_1_max_x, joy_1_max_y, joy_1_min_x, joy_1_min_y, joy_1_cx, joy_1_cy);
// кое-что будем добавлять позже
} // конец функции main
Если вы введете программу с Листинга 3.3, то увидите, как джойстик А изменяет свои значения в процессе работы с ним.
Клавиатура
Клавиатура - это наиболее сложное устройство ввода, которое есть в ПК. Она даже имеет свою собственную микросхему - контроллер ввода. Я провел много бессонных ночей, вчитываясь в листинги BIOS и пытаясь понять тайны, скрытые в работе с клавиатурой.
В этой жизни есть множество непонятных вещей - курс доллара, термический - коэффициент расширения рубидия и т. д. Несомненно одно - любовь людей к клавиатуре абсолютно необъяснима.
Для наших целей (для написания видеоигр) мы должны научиться хорошо работать с клавиатурой. Для этого вовсе не стоит разбираться с прерываниями, регистрами и портами. Мы будем использовать функции языка Си и BIOS для работы с очередью клавиатуры. Говоря о Си, я не имею в виду функции типа getch () и scanf (). Речь пойдет, скорее, о функциях типа _bios_keyboard ().
Примечание
Давайте приостановимся и немного подумаем, Общее правило для авторов игр - никогда не использовать BIOS. Верно? Хорошо, на самом деле BIOS вполне можно использовать для файловых операций и для выделения памяти. В общем, обращения к BIOS вполне допустимы в функциях, некритичных по времени. Попытка использовать его для работы с джойстиком или клавиатурой не будет для нас смертельна (в отличие от попыток организовать через BIOS вывод графики). Как я уже говорил, современные компьютеры достаточно быстры, чтобы нам не приходилось оптимизировать каждую запятую в тексте программы или писать ее целиком на ассемблере.
BIOS поддерживает несколько функций, которые мы будем использовать и которые приведены в таблице 3-1.
Таблица 3.1. Клавиатурные функции BIOS.
Дата добавления: 2015-07-12; просмотров: 79 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Листинг 3.2. Чтение позиции джойстика. | | | Bios INT 16h |