Ahoj programátoři.
Zajímala by mě jedna věc. Pracuju v TP 7. Když si napíšu vlastní obsluhu klávesnice, která visí na int 9 a čte scankódy z port[$60], vrací se mi z numerické klávesnice stejné kódy jako z obyčejných šipek, home, end atd.. Na stavu numlocku vůbec nezáleží. Nikde jsem nenašel způsob, jak na úrovni scankódů numerickou klávesnici odlišit. Jsem si jist, že nějaký způsob určitě existuje, protože jsem viděl pár DOSových her, které to uměly. A taky třeba BIOS (Readkey) to dělá běžně - stačí zapnout numlock a numpad vrací čísla. A BIOS to taky musí na nejnižší úrovni číst ze scankódů, takže to jít musí... jenže jak?
Vím, že jde nějak, tuším, že to byla nějaká služba int $16, nastavit jiné rozložení klávesnice (101 kláves nebo něco jiného, celkem asi tři varianty), ale ta nic neřeší (zkoušel jsem všechny).
Na co to má být: šipky mají dejme tomu hýbat celou obrazovkou, zatímco numerické klávesy něčím na obrazovce (v osmi směrech). Samozřejmě nebufferovaně.
Úkol do školy ani nic životně důležitého to není, takže nijak nepospíchám.
Díky
Fórum › Pascal
Jak odlišit numpad podle scankódů?
Odlišit normální šipky a šipky na numerický klávesnici není úplně sranda. Jde o to, že některé klávesy jsou tzv. rozšířené klávesy. Mezi ně patří třeba normální šipky. Když ji zmáčkneš, tak z portu 60h příjde hodnota 224 (0E0h). Normální rutiny to považují za uvolnění klávesy č. 96 (96+128).
AŽ PŘI DALŠÍM PŘERUŠENÍ potom příjde z portu kód šipky. Proto nezafunguje prostě napsat:
KOD:=Port[$60];
if kod = $E0 then kod:=Port[$60]+PRIZNAK_ROZSIRENE_KLAVESY;
Musíš nechat přerušení skončit (okamžitě se automaticky vyvolá nové) a z něho načíst opravdový kód.
Paráda, funguje to.
Pro zájemce:
globální proměnné:
var rozsirena:byte; {informace o tom, jestli posledni precteny scankod byl kod pro
rozsirenou klavesu (pak rozsirena=128) nebo ne (rozsirena=0)}
_klavesy:^array[0..255] of boolean;
Stačí připravit buffer _klavesy, ulozit vektor preruseni int 9 (Getintvec) a povesit tam tohle (pres Setintvec):
procedure SpecialInt9; interrupt; assembler;
Asm
cli
in AL,$60
cmp AL,$E0 {je rozsirena?}
jne @normalni {neni => zpracujeme scankod}
mov rozsirena,128 {zapamatovat pro priste...}
jmp @konec {...a zatim konec}
@normalni:
mov BL,AL
and BL,$7F {v BL je ted samotny scankod}
add BL,rozsirena {ted mame v BL skutecny index pro pole _klavesy}
xor BH,BH
and AL,$80 {v AL je ted pouze nejvyssi bit hodnoty z portu (stisknuto/pusteno)}
xor AL,$80
rol AL,1 {prevedeno na boolean}
les DI,_klavesy
mov ES:[DI+BX],AL {do pole na index BX (cislo klavesy) vloz hodnotu AL (stav te klavesy)}
mov rozsirena,0 {nutne pro priste}
@konec:
mov AL,$20
out $20,AL {konec preruseni}
sti
End;
Doufám, že Assembler není v sekci pro Pascal zakázaný :-).
Off topic: Zvláštní je, že nejde stisknout neomezené množství kláves najednou. Obvykle když držím cca tři a zmáčknu čtvrtou, už se mi nenačte. To ale není vždy stejné: čím jsou nižší hodnoty scankódů těch stisknutých kláves, tím víc jich můžu stisknout (v oblasti vlevo nahoře na klávesnici třeba i pět a všechny se načtou). Zvláštní. No nic, to už mi nevadí.
Kolik kláves najednou ti to zdetekuje záleží na typu klávesnice. Jó, dřív, to byly klávesnice. Ty nový jsou v tomhle směru dost jakože na hovno. Třeba takový Mortal Kombat ve dvou na nových klávesnicích celkem často zlobí - postavičky občas neudělají nějaký pohyb jen proto, že je přeplněná "kapacita klávesnice"
Přidej příspěvek
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku
×Vložení zdrojáku
×Vložení obrázku
×Vložení videa
Uživatelé prohlížející si toto vlákno
Podobná vlákna
Notes NumPad — založil domitea
Jak na umístění podle velikosti — založil Zuben
Jak otočit rectangle podle osy X,Y a Z — založil Tom
G++ aneb jak psat podle normy norma — založil Koudis
Jak nastavit checkbox z datasetu podle existence zaznamu — založil VladislavK
Moderátoři diskuze