Billentyűzet kezelés assemblyvel pascalban

Billentyűzet kezelés assemblyvel pascalban
2007-04-03T14:00:22+02:00
2007-04-10T12:48:55+02:00
2022-11-04T03:41:52+01:00
neuromancer
jelenleg egy kisebb pascal játékszerűségen dolgozom pascalban (Turbo 7-es) es használok inline assembly-t is.
arra ugye minden értelmesebb ember rá tud jönni hogy iskolai feladatok elvégzésén túl a READKEY szinte semmi komolyra nem használható.
na ezért nekiálltam hogy utánanézzek hogy hogyan lehet mindezt megoldani assemblyben es azt találtam, hogy a 16h interruptot kell használjam (ir még valamit a 9h-ról is, de asszem az a puffer-be való íráshoz kell).
ezeket talán (csak talán) lehet ha megtudnám oldani, de azon is elgondolkodtam, hogy nem lehetne azt, hogy direkt magából a pufferből olvassam ki az adott billentyű kódjait, interrupt használata nélkül?
konkrétan sima előre-hátra mozgást akarok elérni + a foldulást kurzorokkal vagy akár WASD-al.
előre is köszi, és bocs ha már egyszer feltették ezt a kérdést.
Mutasd a teljes hozzászólást!
Ajánlom figyelmedbe
Varga Márton: Játékprogramok készítése Pascal és Assembly nyelven
című könyvét. Ebben benne van a megoldás. Le is lehet tölteni a netről, csak fejből nemtudom a linket, de itt a tudástárban is leírták már, sőt énis ajánlottam már itt billentyűzet kezelést, csak nemtudom mi a téma címe, de itt van valahol a Pascal témák között.

Amúgy ezt próbáld meg:
bill=port[$60];

Ha esetleg rosszul írtam, akkor port[#60] vagy csak port[60].
Ezt rakd be egy végtelen ciklusba és bill értékét írasd ki a képernyőre folyamatosan. Kezd el nyomogatni a billentyűzetet. bill értéke mindíg azt mutatja majd meg, hogy melyik billentyűt nyomtad le, vagy éppen engedted fel.
Nem muszáj ezt használni (bár ez is működik), de ez az alapja az assembly verziónak is. Annyi különbséggel, hogy az csinál egy boolean tömböt (key[0..255]) és a tömb egy-egy eleme azt mondja majd meg, hogy az aktuális billentyű le van e nyomva, vagy sem.
Programból már gyerekjáték kezelni:

if key[1] then writeln('ESCAPE-et nyomtunk');

Vagy mondjuk várunk az ENTER lenyomására:

repeat {valami} until key[$1c];
Mutasd a teljes hozzászólást!

  • Tudástár - Prog.Hu
    A témaindításban egy TP alatt működő forráskódot találsz, egszerre több billentyű kezelésére is.
    Mutasd a teljes hozzászólást!
  • Ajánlom figyelmedbe
    Varga Márton: Játékprogramok készítése Pascal és Assembly nyelven
    című könyvét. Ebben benne van a megoldás. Le is lehet tölteni a netről, csak fejből nemtudom a linket, de itt a tudástárban is leírták már, sőt énis ajánlottam már itt billentyűzet kezelést, csak nemtudom mi a téma címe, de itt van valahol a Pascal témák között.

    Amúgy ezt próbáld meg:
    bill=port[$60];

    Ha esetleg rosszul írtam, akkor port[#60] vagy csak port[60].
    Ezt rakd be egy végtelen ciklusba és bill értékét írasd ki a képernyőre folyamatosan. Kezd el nyomogatni a billentyűzetet. bill értéke mindíg azt mutatja majd meg, hogy melyik billentyűt nyomtad le, vagy éppen engedted fel.
    Nem muszáj ezt használni (bár ez is működik), de ez az alapja az assembly verziónak is. Annyi különbséggel, hogy az csinál egy boolean tömböt (key[0..255]) és a tömb egy-egy eleme azt mondja majd meg, hogy az aktuális billentyű le van e nyomva, vagy sem.
    Programból már gyerekjáték kezelni:

    if key[1] then writeln('ESCAPE-et nyomtunk');

    Vagy mondjuk várunk az ENTER lenyomására:

    repeat {valami} until key[$1c];
    Mutasd a teljes hozzászólást!
  • na az konyv pdf-ben pont megvan
    utananéztem egy kicsit a dolognak es úgy tűnik, hogy a port60-as megoldás elég egyszerűnek tűnik, már csak az az egy kérdés merült fel bennem, hogy kell-e utána handshakinget (61h port 7-es bitjét 1-re majd 0-ra állítani) csinaltatni, vagy ez pusztán csak figyeli a portot?
    Mutasd a teljes hozzászólást!
  • Ha megvan a könyv, akkor ottvan benne a billentyűzetkezelő. De ha a könyvhöz adott példaprogramokat is megszerzed akkor mégjobb vagy.

    Azthiszem nem elég "csak figyelni" a 60-as portot. Sőt, a könyvben lévő kezelő sem tökéletes, mert kilépéskor úgyérzi a gép, hogy a CTRL le van nyomva. De itt a tudástárban már erre is adtak megoldást.
    Mutasd a teljes hozzászólást!
  • én ezt használom, igaz hogy interruptos és nem assemblys
    használat előtt
    initnewkeyint;
    használat után
    setoldkeyint;
    a keydown arrayban kapod meg hogy mi van éppen leütve:
    keydown[billentyűkód] : boolean

    Mutasd a teljes hozzászólást!
  • megnéztem a könyvet, meg zoley programjat is amit mutatott.
    há eléggé meg van variálva mindekettő, de lényegében érthető.
    valami olyasmivel probalkozom majd meg, ami a könyvben van leírva (interrupt kicserélése) csak egyszerűbben
    egyelőre köszi, meglátom mi sül ki belőle
    Mutasd a teljes hozzászólást!
  • Ha találsz egy működő eljárást (például a könyvben), akkor nem muszáj azt megérteni, elemezni, elég ha bemásolod a saját programodba és használod. Amúgy ha a megszakítást áttírod akkor írhatod nyugodtan Pascal nyelven is, nemkell assemblyvel szenvedni.
    Mutasd a teljes hozzászólást!
  • nekem a lényeg az hogy meg is értsem mert az egyik kedvencem az assembly
    egyébként a könyben így szerepelt:
    procedure NewIRQ; assembler; asm push ds { Azokat a regisztereket, amelyek a meg- } push ax { szakítás végrehajtása közben módosulnak,} push bx { a veremben tároljuk } push cx xor cl,cl { Néhány regiszter kezdeti értéke } mov bh,cl mov ax,seg key { DS a KEY tömb szegmense } mov ds,ax in al,60h { AL-be beolvassuk a billentyv SCAN-kódot } mov bl,al { BL-be is bevisszük a kódot } shl al,1 { C jelzïbit (FLAG) = 7. bit } cmc { Ezt negáljuk, így ha 0, felengedtük az } { adott billentyvt, ha 1, akkor lenyomtuk } adc cl,00 { CL most 0 vagy 1 lehet (FALSE, TRUE) } and bl,127 { Az alsó 7 bit adja a valódi SCAN-kódot } mov [offset key+bx],cl { A megszaktást kiváltó billentyvhöz } { tartozó logikai változó beálltása } in al,61H { A megszakítás csatorna visszaállítása } mov ah,al or al,80H out 61H,al { Jelzés a billentyvzetnek } mov al,ah nop { Kevés várakozás } nop { (soros adatkiküldés sebessége miatt) } nop out 61H,al cli mov al,20H { "Megszakítás vége" jelzés } out 20H,al sti pop cx { Regiszterek visszaolvasása a verembïl } pop bx pop ax pop ds iret { Vége a megszaktásnak } end;

    na én ezt így kellet megoldjam:

    procedure int09h;assembler; asm push ds push ax push bx push cx xor cl, cl mov bl, cl in al, 60h mov bl, al mov cl, al shr al, 1 shr al, 1 shr al, 1 shr al, 1 shr al, 1 shr al, 1 shr al, 1 xor al, 1 mov cl, al and bl, 127 cmp bl, sc_up je @up cmp bl, sc_down je @down cmp bl, sc_left je @left cmp bl, sc_right je @right cmp bl, sc_esc je @esc cmp bl, sc_z je @Z cmp bl, sc_c je @C jmp @end @up: mov ax, seg k_u mov ds, ax mov k_u, cl jmp @end @down: mov ax, seg k_d mov ds, ax mov k_d, cl jmp @end @left: mov ax, seg k_l mov ds, ax mov k_l, cl jmp @end @right: mov ax, seg k_r mov ds, ax mov k_r, cl jmp @end @esc: mov ax, seg k_esc mov ds, ax mov k_esc, cl jmp @end @Z: mov ax, seg k_z mov ds, ax mov k_z, cl jmp @end @C: mov ax, seg k_c mov ds, ax mov k_c, cl jmp @end @end: in al, 61h mov ah, al or al, 80h out 61h, al mov al, ah nop nop nop out 61h, al cli mov al, 20h out 20h, al sti pop cx pop bx pop ax pop ds iret end;

    tudom egy kicsit gamat az a 7 db shift egymás után, de sohasem tudhatjuk mikor kell XT kompatibilis progit irni :D
    egyébként ezt a részt nem fogadta el a pascal:
    shl al,1
    cmc
    adc cl,00

    ezért kellet azt helyettesítsem.
    a lényeg az hogy sikerült a crt ne használjam többé, már csak a dos-t kell kiüssem.
    Mutasd a teljes hozzászólást!
  • Miért nem volt jó neked az eredeti kód? A 128 bájtos Key tömb scan kóddal történő indexelésével (pl. Key[sc_up]) bármelyik kívánt billentyű lenyomott/felengedett állapota lekérdezhető. Nekem praktikusabbnak és szebbnek tűnik az a megoldás. :)
    A kódodban feleslegesek az alábbi sorok:
    xor cl,cl ;nem kell mov bl,cl ;nem kell in al,60h mov bl,al mov cl,al ;nem kell

    A 7 db shr al,1 helyett pl.:
    xor ax,ax in al,60h shl ax,1 xor ah,1 shr al,1
    Ahol al-ben a billentyű scan kódja, ah-ban az állapota.
    Mutasd a teljes hozzászólást!
  • azért nem volt jo mert nekem nem kell egy külön tömb, mert csak egy wolf3d szerű játék az egész, csak mozgéshoz kell, fölösleges lett volna
    könnyebb volt nekem megérteni ha a saját elképzelésemet valósítom meg, a másikat mintául véve.
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd