Beiträge von Mike im Thema „Kleiner Maustreiber“

    Du hast hier z.B. nicht beschrieben, was wie genau auf den Stack gepusht werden muss.

    Schau mal hier:

    [...] indem 'über' dem ursprünglichen IRQ-Stackframe (Y,X,A,P,PC) ein Dummy-Stackframe angelegt wird [...]

    in Beitrag Bitte melde dich an, um diesen Link zu sehen.. Daraus läßt sich dann schon ableiten, wie der Dummy-Stackframe auszusehen hat - im Aufbau nämlich genau wie der originale IRQ-Stackframe, nur anderer Inhalt.

    [...] Der KERNAL-IRQ macht die Tastaturabfrage und sonstiges Gedöns und hebt zum Schluß den Dummy-Stackframe ab - womit die CPU aber zunächst nicht beim Hauptprogramm weitermacht, sondern beim "Rest" des Maustreibers! [...]

    Daraus läßt sich wiederum ableiten, daß der ge-stack-te PC im Dummy-Stackframe auf den "Rest" des Maustreibers verweisen soll. Mit ein wenig knobeln kommt man dann noch darauf, daß das Statusregister mit PHP in den Dummy-Stackframe gepusht werden kann und automatisch auch das I Flag gesetzt hat. Mit noch etwas mehr knobeln kommt man dann auch noch darauf, daß es auf die Inhalte von A, X, Y nach dem Abheben des Dummy-Stackframes nicht ankommt, weil der "Rest" des Maustreibers diese nicht genau definiert braucht. Sieht man denn auch an der Implementierung von wizball6502.

    Das steht alles bereits in meinem Beitrag Bitte melde dich an, um diesen Link zu sehen..

    MacBacon hat die andere Herangehensweise gewählt. Im anderen Thread steht einfach der Code zum Erstellen des Dummy-Stackframes auf dem Silbertablett. Wie er darauf gekommen ist, steht da nicht!

    Ansonsten aber ...

    Damit weiß ich nun natürlich, wie ich es implementiere. Am Umsetzen scheitert es sicher nicht. Es geht mir ums Verständnis. Ich weiß nun, dass $ea31 am Ende drei Bytes vom Stack zieht und die in Y,X und A schreibt und dann per RTI zur Adresse springt, die danach im Stack steht. Das ist dann der zweite Teil unseres Maustreibers. Ziemlich clever! Am Ende des Treibers wird dann $ea81 aufgerufen, was den ursprünglichen Stack-Frame zieht, und alles läuft normal weiter. So richtig?

    ... so richtig. :)

    Jo, sicher.

    Ganz genau!

    Schon der erste jsr in $ea31 verweist auf vier weitere jsr's im Kernal. In der ganzen Routine ist natürlich auch viel dabei, was ich gar nicht wissen will. Mich interessiert z.B. nicht, wie die Tastaturabfrage funktioniert, nur wo sie passiert.

    Bei einem gut kommentierten ROM-Listing ist das auch ganz klar ersichtlich und Du kannst die Sachen überspringen, die für die Anwendung erstmal nicht relevant sind.

    Was ich gerne hätte wäre ein grober Ablauf, wo was passiert.

    Ganz knallhart gesagt, da mußt Du dich jetzt selbst durchbeißen! Ich habe deine Frage wie man den Dummy-IRQ-Stackframe aufbaut im anderen Thread nochmal ausführlich beantwortet. Wie weit aufdröseln soll ich das denn jetzt noch? Du siehst doch, daß wizball6502 aufgrund der Blaupause von MacBacon ohne weiteres in der Lage war, den Maustreiber umzubauen und das, obwohl die Blaupause wesentlich knapper beschrieben war als hier in dem Thread. Also kriegen andere sowas hin. Es gibt also noch was für dich zu studieren und das nimmt dir niemand ab.

    Was trage ich denn in den Dummy-Stackframe ein, damit mich $EA81 zum Rest des Maustreibers schickt, wo der Multiplexer eingestellt wird?

    Das, was MacBacon im Solitaire-Thread geschrieben hat. Er hatte die gleiche Idee in dem anderen Thread und war auch schneller. Dafür steht hier meine etwas ausführliche Erklärung, wie es funktioniert.

    WebFritzi, ich würde dir schon anraten, dir mal genau anzuschauen was die CPU und der KERNAL beim Interrupt machen und wie die Stackbefehle und RTI arbeiten. Dann ergibt sich die Erklärung, ausgehend bereits von meinem Beitrag Bitte melde dich an, um diesen Link zu sehen., schon von selbst. Mit meinen Beiträgen Bitte melde dich an, um diesen Link zu sehen. und Bitte melde dich an, um diesen Link zu sehen. kam nichts substantiell neues dazu - die Blaupause in Beitrag Bitte melde dich an, um diesen Link zu sehen. reicht völlig aus, wenn man sich mit der Sache auskennt und nur noch nicht auf diese Idee gekommen war.

    wizball6502, saubere Umsetzung! 8o

    oder nicht?

    Oder nicht.

    Häng' meine oben beschriebene Abfolge in Gedanken mal zweimal untereinander. Wer (ver)stellt den Multiplexer auf Port 1? Die Tastaturabfrage in Punkt 6. Wer stellt den Multiplexer (wieder) auf Port 2? Der "Rest" des Maustreibers in Punkt 8. Wo werden die POT-Register gelesen? In Punkt 3, beim nächsten Interrupt. tWieviel Zeit vergeht zwischen Punkt 8 und Punkt 3? Circa 16 Millisekunden, die Zeit zwischen zwei Tastatur-IRQs. Ausreichend Zeit in denen sich die Combo Multiplexer-A/D-Wandler "einpendeln" kann und das Hauptprogramm ohne 4-ms-Busy-Wait unbehindert läuft.

    Beanworte dir die Frage jetzt selbst, welche Instanz als letztes vor der POT-Abfrage den Multiplexer eingestellt hat.

    Ganz am Anfang, die allererste Abfrage liest bei dieser Darstellung noch von Port 1. Nur die. Macht das was? Wenn dir das nicht gefällt, stell' den Multiplexer in der Init-Routine auf Port 2, warte hier eiin einziges mal 4 Millisekunden und gebe dann den IRQ frei. Brauchen tut's das aber nicht.

    Wenn dir das zur Erklärung nicht ausreicht, kann ich dir leider nicht weiterhelfen.

    Und wie "legt man" einen Stackframe "an"?

    Von Hand, mit PHA und PHP.

    Der Stackframe muß dann genau den gleichen Aufbau haben wie sonst auch beim Eintritt in die IRQ-Routine ab ($0314): die CPU hat bereits den PC und das Statusregister abgelegt, der KERNAL-IRQ-Handler legt noch A, X und Y dazu.

    Bei der Rückkehr aus dem Interrupt holt die Routine ab $EA81 das A, X und Y-Register wieder ab, RTI dann das Status-Register und den PC.

    Den Dummy-Stackframe "fabriziert" man jetzt so, daß der im Zwischengang aufgerufene Tastaturinterrupt bei dessen "Verwendung" in $EA81 nicht direkt zum Hauptprogramm zurückkehrt, sondern zu einer anderen vorgegebenen Stelle - eben dem "Rest" des Maustreibers! Wenn der dann fertig ist und seinerseits $EA81 aufruft, wird der ursprüngliche Stackframe abgehoben und dann erst geht's im Hauptprogramm weiter.

    Der Ablauf ist also jetzt so:

    1. Hauptprogramm läuft,
    2. Interrupt passiert,
    3. Maustreiber liest POT-Register und aktualisiert Mauszeiger,
    4. Maustreiber legt Dummy-IRQ-Stackframe an,
    5. Maustreiber springt zu $EA31 (bzw. "zu vorherigem Besitzer des IRQ-Vektors"),
    6. $EA31 ff. macht sein Interrrupt-Processing (Tastatur, Uhr, ...),
    7. Ende der IRQ-Routine bei $EA81 hebt Dummy-IRQ-Stackframe ab (!!!),
    8. "Rest" des Maus-Treibers wird ausgeführt und stellt Portregister für Multiplexer richtig ein,
    9. Maustreiber springt $EA81 an,
    10. $EA81 hebt jetzt originalen IRQ-Stackframe ab,
    11. Hauptprogramm läuft weiter.

    wizball6502 hat in einem anderen Thread übrigens eine Lösung per Raster IRQ gefunden.

    Ich denke nicht, daß die Verwendung eines Raster-IRQs an dieser Stelle für die Lösung des Portproblems relevant ist. Man wird ohnehin sinnvollerweise den Raster-IRQ anstelle des Tastatur-(CIA)-Interrupts verwenden, damit die Sprite-Register des Mauszeigers sauber "im Frame" geändert werden.

    Die 4-Millisekunden-Warteschleife sollte sich eliminieren lassen, indem 'über' dem ursprünglichen IRQ-Stackframe (Y,X,A,P,PC) ein Dummy-Stackframe angelegt wird, der in eine Nachbehandlungs-Routine im Maustreiber verweist.

    Der Maustreiber macht zuerst sein Ding (mit bereits korrekt eingestelltem Port-Multiplexer!), legt dann den Dummy-Stackframe an und kehrt zum KERNAL-IRQ zurück. Der KERNAL-IRQ macht die Tastaturabfrage und sonstiges Gedöns und hebt zum Schluß den Dummy-Stackframe ab - womit die CPU aber zunächst nicht beim Hauptprogramm weitermacht, sondern beim "Rest" des Maustreibers! Dieser Rest stellt dann noch den Multiplexer wieder auf den gewünschten Port und hebt dann den echten IRQ-Stackframe ab. Bis zum nächsten IRQ sind es dann 16 Millisekunden - lange genug, daß auf jeden Fall wieder gültige Werte in den POT-Registern stehen.

    POKEd jemand böswilligerweise das Portregister um, kein Problem: das steht nach dem nächsten Interrupt wieder richtig.

    Das Statusregister im Dummy-Stackframe sollte übrigens das I-Bit gesetzt haben. Weiß wer, warum? :D