Hello, Guest the thread was called205 times and contains 10 replays

last post from wizball6502 at the

Joystick Port 2 ($dc00) in Raster-IRQ gibt an, obwohl nichts gedrückt?

Heute 13.11.2019 ca. 11:30 Uhr Serverreboot wegen Systemupdates. Danke für Euer Verständnis. Team Forum64.de

  • Ich hoffe, das kann mir ein Assembler-Spezialist erklären.


    Der folgende Assembler-Code legt einen Raster-IRQ fest und fragt den Joystick-Port 2 bei $DC00 (56320) ab. Alle paar Sekunden kriege ich aber einen Wert "0" zurück, was bei mir ein "Feuer gedrückt"-Entscheid auslöst. Normalerweise sollte doch immer ein Wert von 127 (%01111111) stehen, wenn der Joytick nicht gedrückt wird. Was funkt mir da rein? Ich habe den Code auch als Beispielprogramm angehängt (siehe attachment unten. Start mit "sys 49152")


    warum.prg

  • Ah vielen Dank. Ich glaube ich habe sogar die Stelle gefunden wo das passiert (SCNKEY):



    Hmmm... dann müsste ich noch einen zusätzlichen Timer-Interrupt machen, damit ich dort zuverlässig den Joystick-Button abfragen kann? Und den Wert dann in einer separaten Adresse speichern, die ich dann aus dem Raster-IRQ abfrage? Der Raster-IRQ soll parallel zu einem BASIC-Programm laufen, deshalb muss SCNKEY auch noch aktiv bleiben.

  • Habe das Programm etwas angepasst. So scheint das Problem elegant gelöst:

  • Bei dem Codebeispiel verstehe ich überhaupt nicht, wieso zwei verschiedene IRQ-Quellen behandelt werden. Wenn man nicht mit dem VIC in sync sein muss kann man sich einfach in den system-IRQ "reinhängen" (eigenen Code vorher ausführen, dann nach ea31 springen), ganz ohne VIC.


    Wenn man tatsächlich mit dem VIC in sync sein muss stört der Timer-IRQ nur und zerschießt regelmäßig das Timing (der "Sinn" des CLI in deinem originalen Code ist, diesen Effekt wenigstens zu minimieren -- direkt nach dem CLI kann ein Timer-IRQ vom VIC-IRQ unterbrochen werden. Besonders exakt wird das aber immer noch nicht).


    Entweder man schaltet den System-IRQ einfach komplett ab wenn man ihn eh nicht braucht, oder man arbeitet ihn einmal per Frame aus dem VIC-IRQ ab (was das Timing nur leicht verändert und in der Regel einfach egal ist) ... kann man ungefähr so machen:

    Da braucht's dann übrigens auch kein SEI/CLI zum einrichten -- man schaltet einfach zuerst die unerwünschte IRQ-Quelle ab (muss man ja sowieso tun), konfiguriert dann den VIC und den Vektor und schaltet erst danach den VIC-IRQ ein.


    Kleiner Hinweis noch am Rande: Das Verlassen einer ISR ohne zum System-IRQ zu springen geht (bei aktivem Kernal) auch etwas kompakter mit jmp $ea81 -- gibt keinen Grund für eigenen Code zur Register-Wiederherstellung, außer vielleicht die paar Cycles für jmp zu sparen :)

  • Bei dem Codebeispiel verstehe ich überhaupt nicht, wieso zwei verschiedene IRQ-Quellen behandelt werden

    Das originale Code-Beispiel war nur ein isolierter Test, welches das seltsame Verhalten reproduzieren sollte.


    Insgeim :whistling: arbeite ich an einem Spiel, welches die Kontrolle der Sprites (und handling der Joystick-Aktion) über den Raster-IRQ (Assembler-Code) abwickelt. Parallel dazu soll aber ein BASIC-Programm, welches den Bildaufbau steuert, weiterlaufen können - inklusive Timer-Handling, etc. Macht das Sinn?


    Das Entfernen des CLI hat mein Problem jedenfalls gelöst :thumbsup:. Das meinem Code zugrunde liegende Raster-IRQ-Beispiel (inklusive diesem CLI) hatte ich wohl von hier (letzter Abschnitt mit Code-Ergänzungen):
    https://www.retro-programming.…er-rasterzeileninterrupt/


    Dort wurde dieses CLI für Cycle-exaktes Timing eingesetzt und hat mir aber damit diesen fiesen Nebeneffekt im Raster-IRQ bei Joystick-Abfrage via $DC00 eingebrockt. :wand


    Bei der Gelegenheit vielen, vielen Dank an den Jörn (Nachname leider nicht gefunden) für dessen exzellente Assembler-Einführung - und dies sogar in deutsch! :applaus:: https://www.retro-programming.de

    Ich möchte sogar behaupten, dass mich diese Site erst wieder auf den C64 gebracht hatte.

    :DJ

  • Insgeim :whistling: arbeite ich an einem Spiel, welches die Kontrolle der Sprites (und handling der Joystick-Aktion) über den Raster-IRQ (Assembler-Code) abwickelt. Parallel dazu soll aber ein BASIC-Programm, welches den Bildaufbau steuert, weiterlaufen können - inklusive Timer-Handling, etc. Macht das Sinn?

    Kann man machen. Persönlich sehe ich wenig Vorteile darin, Teile in BASIC zu bauen, aber wenn dann würde ich den CIA-IRQ trotzdem komplett abschalten und den System-IRQ einmal pro Frame aufrufen. Ja, TI$ läuft dann ein bisschen anders, auch abhängig von PAL/NTSC, aber damit kann man in der Regel leben. Die Alternative ist schlimmer:

    Dort wurde dieses CLI für Cycle-exaktes Timing eingesetzt

    "Cycle-exakt" ist daran nämlich gar nichts. Im Kernal passiert das hier:

    also Register sichern, auf dem Stack nachsehen ob es vielleicht ein BRK war, dann erst indirekt zur tatsächlichen ISR springen -- macht bereits 3+2+3+2+3+2+4+2+3+5 = 29 cycles bis überhaupt dein eigener Code angesprungen wird. Da hast du dann:

    Code
    1. irq: lda $d019
    2. bmi raster:
    3. lda $dc0d
    4. cli

    4+2+4+2 = 12 cycles bis das I flag wieder gelöscht ist und ein eventuell wartender Raster-IRQ endlich starten kann. Insgesamt also bis zu 41 Cycles Verzögerung.


    Cycle-exakt wäre es, wenn man den "normalen" Jitter von 7 cycles eliminiert -- das hier erhöht den Jitter auf 48 cycles.