Naja, die Haredware-Interrupts haben eine (einstellbare) Priorität.zatzen hat geschrieben:Danke, DOSferatu, es ist immer gut wenn man genau Bescheid weiss. Also ist das Interrupt Flag so zu verstehen, dass die CPU(!) auftretende Interrupts abarbeitet oder nicht, aber sie reihen sich aneinander wenn sie nicht abgearbeitet werden, aber nicht mehrfach die gleichen. So habe ich das jetzt verstanden.
Und sie haben ein Register (ab AT eigentlich 2), wo ein Bit auf 1 gesetzt wird, wenn eine betreffende "Anfrage" (also ein IRQ) aufgetreten ist. Weil es nur ein Bit ist, kann also nicht herausgefunden werden, ob "in der Zwischenzeit" 2x oder 3x DERSELBE IRQ aktiviert wurde, sondern nur, daß mind. 1x aktiviert wurde.
Naja, so ähnlich. Wichtig: Scancode hat nix mit ASCII zu tun. (ESC hat z.B. den Scancode 1.) Scancodes sind nur quasi "mechanisch" mit den Tasten verbunden - was der Grund ist, wieso bei uns Z den gleichen Scancode liefert, wie bei ner USA/UK-Tastatur das Y (weil die Taste an der gleichen Stelle steht). (Und was auch der Grund ist, wieso man bei rein USA-Spielen ne Abfrage wie "Quit DOOM [Y/N]" mit Z (statt Y) beantworten muß.)Thomas hat geschrieben:Das mit dem Scancodearray interessiert mich jetzt näher:
Wie machst Du denn die Abfrage der einzelnen Tasten? Kann ich mir das etwa so vorstellen:
Wenn INT 16 dann lese scancode. Wenn bsp ESC, dann KeyArray[27] := 1 ?
Oder ist es doch etwas komplexer?
Was aus den Scancodes die ASCII macht, ist der Tastaturtreiber - aber für ein interaktiveres Spiel will man ja nicht mit Tastaturpuffern arbeiten und diesem Taste gedrückt, reagiert 1x und nach ner Weile setzt die automatische Wiederholung ein... Das ist ja totaler Murks, wenn man damit ein Spiel steuern will - da gingen dann nur Tasten wie Shift/Ctrl/Alt usw., für die der Treiber zusätzlich Bits setzt, z.B. in $0040:$0017 (und z.B. $0040:$0096)...
Außerdem nehme ich für Keyboard-Abfrage IRQ9 (=INT 01).
Und dann wirklich genau so: Wenn INT kommt, dann bei PORT $60 gucken, was drinsteht (z.B. 42) und Scancode[42]:=1 setzen. Und wenn eine Taste LOSGELASSEN wird, kommt nämlich auch ein INT 01, und da steht dann der SCANCODE+128 (also gesetztes Bit7) drin und man kann Scancode[Taste and 127]:=0 setzen.
Für die "Sondertasten", die erst mit AT dazukamen (Cursortasten, rechte Alt+Ctrl, zweite Enter usw) gibt es einen "Präfix-Code" (224, also $E0), der sowohl beim Drücken als auch beim Loslassen vorher gesendet wird. Dann weiß man, daß danach eine "erweiterte" Taste kommt. (Anm.: Die "Multimedia"-Tasten, die manche Tastaturen haben, sind auch manche von denen...)
Und, weil man ja nun sieht, daß das Ganze nur für max. 127 Tasten (eher weniger) gebaut ist, 0 (null) z.B. nicht vergeben ist... weil ja das obere Bit für "Loslassen" benutzt wird, aber es eben "Erweiterte" Tasten gibt, mach ich der Einfachheit halber ein Feld von 256, und eine "erweiterte" trage ich ab 128 ein.
Und JA! Es würde auch ein BIT-Feld (von 256 BIT) statt 256-BYTE-Feld reichen - aber, es hat sich in der Praxis herausgestellt, daß die Abfrage (auch "indirekte" Abfrage usw.) eines 256-BYTE-Arrays einfacher ist. So "verschwende" ich 224 Bytes (also 256 statt 32), aber dafür spare ich an einigen Stellen komplizierteren CODE (der vielleicht insgesamt mehr als 224 Bytes bräuchte) UND bin bei Abfragen schneller.
Mit "indirekt" meine ich: Wenn ich ein Spiel baue, mache ich es immer mit freibelegbaren Tasten für die Spieler (außer ein paar, die man vielleicht für die Steuerung der Menüs oder so braucht), d.h. in der Spielsteuerung frage ich nur z.B. Taste 0,1,2,3 (für hoch/runter/links/rechts) oder Taste 4 (für springen) Taste 5 (für schießen), Taste 6 (für benutzen) usw. ab.... Und irgendwo extern lege ich fest, welcher Scancode z.B. für Taste 5 steht (und das kann man in einem Menü dann änderbar machen.
Zum Glück habe ich hier auch für alle Tasten die zugehören Scancodes da, auch als Liste und so.
Naja, und das mit dem Tastenarray mache ich u.a. auch deswegen, weil so auch mehrere Tasten gleichzeitig gedrückt abgefragt werden können - weil ja nicht irgendwas die ganze Zeit "AN" ist, wenn eine Taste gedrückt wird, sondern nur ein INT kommt, wenn eine Taste gedrückt wird (und danach zusätzliche INTs für die Tastenwiederholung, aber das spielt keine Rolle, ob man da NOCHMAL das Feld auf :=1 setzt, was es schon vorher war) und nochmal ein INT, wenn die Taste losgelassen wird. Und somit hat man ein Feld, das quasi alle Tasten enthält, die momentan gedrückt sind.
Wichtig noch anzumerken: Nicht alle Tastaturen erlauben es, unendlich viele ("alle") Tasten gleichzeitig gedrückt zu haben - da ist hardwaremäßig so gebaut, kann softwareseitig nicht umgangen werden (originale IBM-Keyboard haben das aber wohl mit "alle gleichzeitig" möglich).
Und dann wäre da noch die "Pause"-Taste. Die abzufragen ist ein bißchen "komisch", weil sie beim Drücken EINIGE Scancodes hintereinander sendet und beim Loslassen NIX. - Sie simuliert quasi das Drücken von Rollen und Num und Ctrl oder sowas gleichzeitig - weiß grad nicht auswendig. Früher (XT) gab es keine PAUSE-Taste, da wurde das durch 'ne Tastenkombi gemacht und bei AT hat man, damit es abwärtskompatibel ist, diesen Schlunz so eingebaut. Allerdings ist es erkennbar am Präfix-Code 225 ($E1). (Diese Präfix-Codes $E0 und $E1 würden XT-Rechner einfach ignorieren, deshalb hat man die genommgen. Es ist wie "Loslassen Taste 96 und 97 ($60 und $61)", die es nicht gibt.) Also kann man nur feststellen, ob Pause gedrückt wurde, aber nicht, ob sie festgehalten wird. Ist aber auch egal. Da kann man ein Flag setzen - die nimmt man sowieso nicht zum Steuern - aber zum Spiel anhalten reicht es.
So, das war wahrscheinlich wieder viel mehr Info als nötig.
Naja, ich sag's mal so: Prinzipiell mache ich seit Jahren (Jahrzehnten) das gleiche wie Du (Thomas) : Spiele unter MS-DOS in Pascal+Assembler programmieren, inklusivie eigener Subroutinen/Units usw. - (Kannst Dir ja mal "Xpyderz" angucken, wenn Du willst.) Und momentan bin ich gerade ein einer neuen zusammenfassenden "Engine" dran, die meine ganzen Sachen neu zusammenbaut: Sprite-/Levelanzeige, Erzeugung/Abspielen von Musik/SoundFX, Steuerung der Figuren (Spieler, "Feinde", Projektile, usw) durch einen in Assembler geschriebenen Bytecode-Interpreter... usw. Und dann eben auch so niedliche Kleinigkeiten wie den Keyboard-Interrupt mit diesen Scancodes oder den Timer-Interrupt für die Steuerung und die richtigen "Spielticks/Sekunde"... und so Zeug wie die ganzen verschiedenen (auch selbstge"tweak"-ten) Auflösungen, die man so mit Mode-X fahren kann... Naja, was eben alles so zusammenkommt, wenn man so einen Kram schon über 25 Jahre (auf PC) und fast 35 Jahre (insgesamt auf Computern) macht...