Beiträge von WebFritzi im Thema „Kleiner Maustreiber“

    Mit ein wenig knobeln

    ... hätte ich auch alles ohne Hilfe hinkriegen können. :wink: Bitte bedenke, dass ich immer noch ein ziemlicher Anfänger bzgl ASM bin. Es ist wie beim Schach. Ich kenne die Regeln, aber das war's auch schon. Zudem bin ich Ü40 und habe nicht mehr die schnellste Auffassungsgabe.

    Allerdings bin ich auch zu ungeduldig und will am liebsten alles auf dem Silbertablett geliefert bekommen. Dein Ansatz über Learning By Doing ist aber schon richtig. Nur so lernt man wirklich. Aber bedenke auch, dass das bei einem Begriffsstutzigen wie mir dann auch seine Zeit braucht.

    ... so richtig. :smile:

    Danke! Zum Schluss habe ich dann auch kapiert, dass $ea81 genau im Anschluss an die $ea31-Routine läuft und die Register des 6510 wieder auf die Werte setzt, wie sie vor dem Feuern des IRQ waren. Welche Routine sorgt eigentlich dafür, dass die überhaupt auf den Stack kommen? Das muss irgendwo im Kernal sein, denn ich meine mich zu erinnern, dass man bei ausgeblendetem Kernal selbst dafür sorgen muss.

    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.

    Das stimmt so nicht ganz. Du hast hier z.B. nicht beschrieben, was wie genau auf den Stack gepusht werden muss. Das wird erst in dem anderen Thread klar. Das hatte ich zuerst nur nicht gesehen, weil ich dachte, dass es dort um die Umsetzung per Raster-IRQ ging.

    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?

    Um all das besser zu verstehen, wäre ein kommentiertes ROM-Listing in der Tat ideal. Ich habe jetzt ein solches gefunden: Bitte melde dich an, um diesen Link zu sehen.

    wo finde ich eine solche Erklärung des Ablaufs?

    Das Datenblatt der 65xx CPU und ein ROM-Listing sind deine Freunde.

    Jo, sicher. 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. Was ich gerne hätte wäre ein grober Ablauf, wo was passiert.

    EDIT: Ok, stimmt nicht mit den JSRs. Das sind JMPs. Egal, mein Hauptpunkt bleibt, dass ich mir nicht stundenlang den Kernal-Code anschauen möchte.

    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.

    Das denke ich auch. Nur: wo finde ich eine solche Erklärung des Ablaufs? Ich würde gerne wissen, was da intern passiert.

    EDIT: Ich nehme an, du spielst auf das RTI am Ende der Routine in $ea31 an. Dort wird dann der Dummy aus dem Stack gezogen. Tastatur-IRQ und alles andere passiert vorher?

    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.

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

    Doch, doch. Danke! Jetzt verstehe ich es. Naja, fast. Was mir noch unklar ist: Zur Beschreibung von $EA81 steht in der C64-Wiki:

    Holt Register A/X/Y aus dem Bitte melde dich an, um diesen Link zu sehen. zurück und beendet einen IRQ

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

    3. Maustreiber liest POT-Register und aktualisiert Mauszeiger,

    Dann sind das doch aber die Werte, die Port 1 sendet, oder nicht? Und das wird dann Käse sein, wenn die Maus an Port 2 hängt.

    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.

    Hmm. Alle Maustreiber, die ich bisher gesehen habe, benutzen den CIA-Interrupt für den Maustreiber.

    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.

    Kapiere ich nicht. Was heißt "über"? Und wie "legt man" einen Stackframe "an"? Einfach ein paar Bytes in den Speicher schreiben? Und dann?

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

    Wählt man beim VICE 3.5 r40486 die 1351 auf Port 2 steht danach in den Control Port Settings auch bei Port 1 die 1351.

    Interessant. Ich habe die Version r39984, und da ist das anders. Da kann ich die Maus auch nur über Input Devices -> Control Port auswählen. Ich kann dann einstellen, was ich in Port 1 und Port 2 haben will. Dort hatte ich Port 2: 1351 und Port 1: none ausgewählt, und das Programm auf der Testdisk lief.

    Beim aktuellen Vice 3.5 nightly läuft die Maus-Emulation an Port 2 bei mir schon mal gar nicht.

    Das ist interessant. Danke. Ich bin jetzt aber eh auf Port 1 umgestiegen, da mich eventuelle Tastatureingaben bei meinem Spiel nicht stören.

    Bei VICE 3.2 flitzt die Maus in der Tat viel zu schnell, aber in den Mouse Settings kann man die Sensivity von 40 auf 10 oder 5 senken, wobei 5 da einer echten 1351 am nächsten kommt.

    Auch danke dafür. VICE 3.2 habe ich nicht, aber in VICE 3.5 sehe ich keine Möglichkeit, die Maussensitivity einzustellen.

    Ich vermute, daß Vice die PotX/Y-Eingänge des SID nicht wirklich detailliert simuliert, sondern nur die Stellung des Multiplexers berücksichtigt.

    Das wird dann wahrscheinlich so sein, ja. Vielen Dank für deine Erklärungen.

    Mann, ich hoffe echt, meine Maus ist bald da. Warte darauf nun schon seit drei Tagen. Es ist nämlich auch so, dass die Maus in Vice sehr schnell und unruhig ist und man beim Klicken genau aufpassen muss. Hoffe, das ist auf echter Hardware anders.

    Mac Bacon Vielen Dank für die ausführliche Antwort auf meine Fragen.

    Wenn bei eingeschaltetem Kernal ein Interrupt auftritt, wird der Interrupthandler des Kernals angesprungen. Dieser erledigt ein paar Kleinigkeiten und springt dann über $314 die "normale" Interruptroutine des Kernals an, wo unter anderem die Tastatur abgefragt und TI erhöht wird.

    Verbiegt man $314 auf eine eigene Routine und springt am Ende zur "normalen" Routine -> dann wird die eigene Routine natürlich immer direkt vor der "normalen" Routine ausgeführt.

    Danke. Jetzt hab ich's kapiert. Erst wenn der Tastaturscanner durch den Kernal wieder "anspringt", wird Port 1 verbunden, was seine Zeit braucht. Hängen wir uns vorher ein, ist Port 1 bereits verbunden.

    Ansichtssache. Sie verhindern eine Mehrfachinstallation, die zu einer Endlosschleife führen würde.

    All diese Dinge kann man mMn auch weglassen, wenn man den Treiber nur für ein kleines BASIC-Programm braucht, wie es bei wizball6502 und bei mir der Fall ist. Und warum sollte das zu einer Endlosschleife führen? Ich trage ja nur noch einmal den Vektor in $314/15 ein.

    Will man die Werte von Port 2 haben, muss man Port 2 auswählen und eine gewisse Zeit abwarten, und während dieser Wartezeit darf auf keinen Fall der Tastaturscanner aktiv werden.

    Aha. Diese Abfrage hat also mit dem Tastaturscanner nichts zu tun, richtig? Der ist an Port 1 angeschlossen und soll da auch bleiben.

    Also muss ich die Maus an Port 1 auslesen, wenn ich das BASIC-Programm nicht ausbremsen will.

    Ich wäre sehr dankbar, wenn jemand mal mein Programm (Anhang) mit 1351-Maus in Port 2 an echter Hardware testen könnte.

    Wenn man nun allerdings am Anfang des umgebogenen IRQ-Handlers auf PortB umschaltet, indem man eine 0x80 nach 0xDC00 schreibt, dann muß man eine Zeit (>1.6ms) warten, bis der SID über seine Lade-/Entladefunktion die Widerstände an PotX/Y sicher ausmessen konnte. Keine Ahnung, wie exakt das Emulatoren nachbilden. Meine Vermutung wäre: gar nicht.

    Also ich kann nur sagen, wie PotX/Y-Eingänge nach meinem Verständnis funktionieren, weder wie genau sie in Emulatoren nachgebildet sind noch wie gut die Mausroutine in diesem Basicspiel funktioniert.

    Demnach dürfte es nicht laufen.

    Aha, alles klar. Die Bits stehen auch gleichzeitig für die Pins des Chips.

    Alle diese 16 Pins sind jeweils als OpenDrain-Ausgang mit integriertem Pullup oder als Eingang benutzbar. Diese Auswahl geschieht über das jeweilige DDR-Register (DDRA/DDRB).

    Alle diese Bezeichnungen sagen mir rein gar nichts. Ich mag ja Programmieren, aber bei Hardware und Elektrotechnik geht bei mir gar nichts.

    Aber wie gesagt: eigentlich reicht es nicht, direkt vor dem Auslesen umzuschalten. Wenn die PotX/Y-Leitungen des SID vorher durch den Tastaturscan o.ä. mit dem anderen Port verbunden waren, braucht es eine gewissen Zeit, damit das Lade-/Entladespielchen mit den Kondensatoren abgeschlossen werden kann.

    Und wie passt das dann mit der Aussage von Mac Bacon (Bitte melde dich an, um diesen Link zu sehen.) zusammen?

    Oder muss man nur warten, wenn man Port 2 nutzen möchte? Das Doofe ist echt, dass ich das hier nur auf einem Emulator ausprobieren kann.

    -> Habe mir Deine Funktion nicht angeschaut, aber ich würde erwarten, daß irgendwo 0x40 nach 0xDC00 geschrieben wird und das müßtest Du in 0x80 ändern. Oder so.

    Ganz ehrlich: den ganzen Hardware-Kram kapiere ich nicht. Der ein sagt, man muss warten, der andere (@Mac Baco) sagt nicht.

    In meiner Funktion wird gar nichts in $dc00 geschrieben. Aber ich habe jetzt $80 da reingeschrieben, und siehe da: es geht. Was ich wiederum nicht verstehe: auf der Lynx verlinken Paddle-Wiki-Seite steht

    Controlport 1 auswählenBit6=0 und Bit7=1
    Controlport 2 auswählenBit6=1 und Bit7=0

    Ist das nicht falsch rum?

    Ziel dieses Threads ist es, das Thema Maustreiber aus Bitte melde dich an, um diesen Link zu sehen. outzusourcen, weil es dort schließlich um das Solitaire von wizball6502 gehen soll und nicht um meine Anfängerfragen zu Assembler. Ich habe nämlich die folgenden Fragen zu dem (funktionierenden) Code unten:

    1. Wie stellt der Code sicher, dass der Mouse-IRQ vor der Tastaturabfrage ausgeführt wird?
    2. Wozu speichert man den Standard-IRQ nochmal extra in IIRQ2? Steht da nicht immer $ea31 drin?
    3. Gibt es einen großen Unterschied zwischen der Verwendung von SEI..CLI und PHP SEI.. PLP (welches hier verwendet wird)?
    4. Sind die ersten drei Zeilen in INSTALL nicht überflüssig?
    5. Kann man meine langwierigen Fallabfragen vor MOVCHK irgendwie kürzer gestalten? Sie dienen dem Zweck, den Mauszeiger im C64-Rahmen zu halten.

    Der Code in Kleinbuchstaben ist von mir eingefügt. Der Rest ist der Treiber aus dem 1351-Manual.