e-mail    Debatní kniha    Mapa stránek    Hlavní  
 perličky 
 

Joystick kurzorem

Michal Šaňák

Tento program slouží k simulování stisku kurzorových kláves při pohybu joystickem, přičemž tlačítka se chovájí jako klávesy Enter (1. tlačítko) a Escape (2. tlačítko). Může posloužit i jako návod, jak jednoduše obsluhovat joystick nebo vkládat klávesy do bufferu klávesnice. Princip programu je v podstatě velice jednoduchý. Program nahrazuje interrupt 1Ch vlastní obsluhou, která čeká na událost joysticku. To se provádí přes interrupt 15h, jehož služba 84h poskytuje informace o stavu joysticku:

* Interrupt 15h: AH .. 84h * DX .. 00h pro zjištění stavu tlačítek. V registru AL se octne stav tlačítek (bity 4-7) joysticku A a B. * DX .. 01h pro zjištění souřadnic joysticku. Výstup vypadá následovně: AX - osa x joysticku A BX - osa y joysticku B CX - osa x joysticku A DX - osa y joysticku B

Hned po spuštění program pomocí této funkce zjistí souřadnice joysticku a uloží je jako center.x a center.y. V dalších funkcích bere tyto souřadnice jako souřadnice vystředněného joysticku. V samotné obslužné rutině pak porovnává aktuální stav os x a y s vycentrovanými osami a jestliže zjistí, že osa x nebo y se od vystředněných liší alespoň o 40 stupňů, pošle do bufferu klávesnice příslušnou klávesu. (To samé provádí i za předpokladu, že bylo stisknuto některé z tlačítek joysticku). Zápis do bufferu přitom provede pomocí služby 05h interruptu 16h:

* Interrupt 16h : AH .. 05h * CH .. scan code klávesy * CL .. ASCII code klávesy Například pro zapsání šipky nahoru do bufferu vypadá procedura takto:
_AH=0x05; _CH=72; _CL=0; geninterrupt(0x16);

To je tedy základ programu. Dále se po každém odeslání klávesy kurzoru čeká tak dlouho, jako se 2x provede interrupt 1Ch. Tím se zajistí přijatelná rychlost opakování. Snížením či zvýšením hodnoty čísla u proměnné wait se dá repeat regulovat. Při odeslání kláves Enter a Escape se čeká dokonce 5x provedení interruptu, aby se Enter nemačkal při jednom stisknutím joysticku třeba 3x. Vliv joysticku na kurzorové klávesy se dá vypnout a opětovně uvést do chodu stiskem kombinace SHIFT+SHIFT+CTRL. Poněvadž při provedení interruptu probíhá rozsáhlá smyčka, ostatní činost se zpomalí, což se například projeví při pohybu myší, že se kurzor hýbe trhavě. Proto se při zapnutém vlivu joysticku na kurzorové klávesy zakáže zobrazení kurzoru myši pomocí interruptu 33h:

* Interrupt 33h: AX .. 0002h A při vypnutém vlivu opět zapne: * Interrupt 33h: AX .. 0001h

Nakonec snad už jen to, že program nevyužívá knihoven STDIO.H ani CONIO.H, tudíž nevypisuje při spuštění žádný text, což přispívá k co nejmenší délce kódu v paměti.

Program byl odladěn v borlandském Turbo C++ 2.0 na počítači 386 s joystickem QuickShot. Využívá inline assembler.

(Pozn. red. - autorovi je 14 let.) /********************************************************/ /* Joystick as Cursor */ /* Autor: Michal Šaňák, 14 let */ /* Pro BAJT upraveno dne 24.07.1993 */ /********************************************************/ #include <dos.h> extern unsigned _heaplen = 1024; /* Pro TSR */ extern unsigned _stklen = 512; /* | */ extern unsigned _psp; /* <-- */ int buttons=0; /* Tlačítka */ int waiting=0; /* Čekací interval */ int enabled=1; /* Povoleno */ int keybflags=0; /* Flagy keyboardu */ struct center { int x,y; /* X,Y vycentrovaného */ }; struct current { int x,y; /* X,Y aktuální */ }; struct center center; struct current current; void interrupt new0x1c(...) { asm { /* Pro jistotu pushneme všechny */ push bp /* registry */ push di push si push ds push es push dx push cx push bx push ax pushf /* i flagový registr */ } if(waiting!=0) waiting--; /* Když čekání, tak */ /* zmenši čekání o jeden */ keybflags = peekb(0x0040, 0x0017); /* Do keybflags */ /* dej flagy klávesnice */ if(keybflags & 1) if(keybflags & 2) if(keybflags & 4) if(waiting==0) { /* Jestliže stisk SHIFT-SHIFT-CTRL a nečeká se */ if(enabled==1) { /* Když je zapnutý joystick, */ enabled=0; /* tak ho vypni */ _AX=0x0001; /* a povol zobrazení kurzoru */ geninterrupt(0x33); /* myši */ } else { /* Jinak */ enabled=1; /* povol joystick */ _AX=0x0002; /* a zhasni kurzor myši */ geninterrupt(0x33); } waiting=10; /* Po této kombinaci interval, */ /* aby nedošlo omylem ke stisku */ /* akt. kláv. dvakrát */ } if(enabled==1) { /* Jestliže je joystick povolený */ _AH=0x84; /* Zjisti aktuální souřadnice */ _DX=0x01; geninterrupt(0x15); current.x=_AX; current.y=_BX; _AH=0x84; /* a stav tlačítek (buttonů). */ _DX=0x00; geninterrupt(0x15); buttons=_AL; if((buttons==224) & (waiting==0)) { /* Při stisku */ _CL=13; /* 1. buttonu do bufferu */ _AH=0x05; /* pošli klávesu enter */ geninterrupt(0x16); waiting=5; /* Pak počkáme */ } if((buttons==208) & (waiting==0)) { /* Při stisku */ _CH=1; /* 2 buttonu pošli do bufferu */ _CL=27; /* klávesu Escape */ _AH=0x05; geninterrupt(0x16); waiting=5; /* A čekáme */ } if((current.x<center.x-40) & (waiting==0)) { /* Když */ _CH=75; /* se joystick hnul doleva, pošli do */ _CL=0; /* bufferu šipku doleva */ _AH=0x05; geninterrupt(0x16); waiting=2; /* A čekej */ } if((current.x>center.x+40) & (waiting==0)) { /* Když */ _CH=77; /* joystick doprava, buffer <- šipka doprava */ _CL=0; _AH=0x05; geninterrupt(0x16); waiting=2; /* Čekej */ } if((current.y>center.y+40) & (waiting==0)) { /* Když */ _CH=80; /* Joystick dolů, buffer <- šipka dolů */ _CL=0; _AH=0x05; geninterrupt(0x16); waiting=2; /* Čekej */ } if((current.y<center.y-40) & (waiting==0)) { /* Když */ _CH=72; /* Joystick nahoru, buffer <- šipka nahoru */ _CL=0; _AH=0x05; geninterrupt(0x16); waiting=2; /* Čekej */ } } asm { /* Na konec popni všechny registry */ pop bp pop di pop si pop ds pop es pop dx pop cx pop bx pop ax popf /* i flagy */ } } void main(void) { _AX=0x0002; /* Vypni kurzor myši */ geninterrupt(0x33); _AH=0x84; /* Načti souřadnice */ _DX=0x01; geninterrupt(0x15); center.x=_AX; /* V registru AX je osa X */ center.y=_BX; /* V registru BX je osa Y */ setvect(0x1C, new0x1c); /* Nový vektor přerušení */ keep(0, (_SS + (_SP/16) - _psp)); /* Stay resident */ }


Pascal - hlavní
Překladače
Vlastní články
Převzaté články
Věci na stáhnutí
Odkazy k tématu
BP7 buglist
Chyba Run-time 200

BASIC