Neues Solitaire (Kartenspiel) für den Commodore 64 in BASIC V2 - Gratis Abtipp-Listing zum Herunterladen (PDF)

Es gibt 140 Antworten in diesem Thema, welches 24.572 mal aufgerufen wurde. Der letzte Beitrag (22. Dezember 2021 um 16:39) ist von WebFritzi.

  • Mac Bacon Wenn der einzige Nachteil meines Port 2 Maustreibers die Warteschleife ist, dann sollte sich die Schleife doch einfach mit einem zweiten Raster IRQ ersetzen lassen. Das ist zumindest der Ansatz, den ich Freitag ausprobieren möchte.

  • Wenn der einzige Nachteil meines Port 2 Maustreibers die Warteschleife ist, dann sollte sich die Schleife doch einfach mit einem zweiten Raster IRQ ersetzen lassen.

    Wenn Du den Timer-IRQ abgeschaltet hast und den Tastaturscanner nur aus Deinem ersten Raster-IRQ aufrufst, sollte das gehen, ja.

    Alternativ kann man den Kernal-Interrupt nachbilden und dafür sorgen, dass am Ende des Tastaturscans nicht Port 1, sondern Port 2 ausgewählt wird. Das braucht aber etliche Bytes.

    Eine andere Möglichkeit wäre diese: Statt aus der eigenen Interruptroutine wieder direkt mit JMP zur Kernal-Interruptroutine zu springen, fälscht man mit PHA:PHA:PHA:PHP:LDA#>fixer:PHA:LDA#<fixer:PHA einen IRQ-Kontext auf dem Stack. Wenn man dann mit JMP zur Kernal-Interruptroutine springt, erledigt diese den üblichen Kram (und damit auch den Tastaturscan) und springt am Ende aber nicht zurück ins unterbrochene Programm, sondern zu der Adresse "fixer", die man gerade auf den Stack gelegt hat. Dort wird dann Port 2 ausgewählt und mit JMP zum normalen IRQ-Ende ($ea81) gesprungen.

    Yes, I'm the guy responsible for the Bitte melde dich an, um diesen Link zu sehen. cross assembler. And some Bitte melde dich an, um diesen Link zu sehen..

  • Mac Bacon Wenn der einzige Nachteil meines Port 2 Maustreibers die Warteschleife ist, dann sollte sich die Schleife doch einfach mit einem zweiten Raster IRQ ersetzen lassen. Das ist zumindest der Ansatz, den ich Freitag ausprobieren möchte.

    D.h.: Im Timer-IRQ Port 2 setzen, aktuelle Rasterline ermitteln, ca. ein Viertel des Screens draufaddieren, dementsprechend Raster-IRQ installieren, raus aus Timer-IRQ und dann im Raster-IRQ, der ca. 4ms später gestartet wird, die Werte auslesen?

    Bitte melde dich an, um diesen Link zu sehen. (Bitte melde dich an, um diesen Link zu sehen.)Bitte melde dich an, um diesen Link zu sehen.Bitte melde dich an, um diesen Link zu sehen.
  • Wenn der einzige Nachteil meines Port 2 Maustreibers die Warteschleife ist, dann sollte sich die Schleife doch einfach mit einem zweiten Raster IRQ ersetzen lassen.

    Eine andere Möglichkeit wäre diese: Statt aus der eigenen Interruptroutine wieder direkt mit JMP zur Kernal-Interruptroutine zu springen, fälscht man mit PHA:PHA:PHA:PHP:LDA#>fixer:PHA:LDA#<fixer:PHA einen IRQ-Kontext auf dem Stack. Wenn man dann mit JMP zur Kernal-Interruptroutine springt, erledigt diese den üblichen Kram (und damit auch den Tastaturscan) und springt am Ende aber nicht zurück ins unterbrochene Programm, sondern zu der Adresse "fixer", die man gerade auf den Stack gelegt hat. Dort wird dann Port 2 ausgewählt und mit JMP zum normalen IRQ-Ende ($ea81) gesprungen.

    Den Ansatz mit dem Ändern des IRQ-Kontexts auf dem Stack fände ich noch interessant, aber funktioniert bei mir nicht. Und du meinst, das sollte gehen?

  • Statt aus der eigenen Interruptroutine wieder direkt mit JMP zur Kernal-Interruptroutine zu springen, fälscht man mit PHA:PHA:PHA:PHP:LDA#>fixer:PHA:LDA#<fixer:PHA einen IRQ-Kontext auf dem Stack.

    :platsch:

    Den Ansatz mit dem Ändern des IRQ-Kontexts auf dem Stack fände ich noch interessant, aber funktioniert bei mir nicht. Und du meinst, das sollte gehen?

    Es ist natürlich genau umgekehrt... :anonym

    Code
    lda #>fixer ; ein IRQ legt erst das Highbyte des Folgebefehls auf den Stack,
    pha
    lda #<fixer ; dann das Lowbyte
    pha
    php    ; dann den Status
    ; und dann wird die Handlerfunktion aufgerufen und speichert die drei Register:
    pha
    pha
    pha
    jmp $ea31 ; fertig, nach IRQ wird zu "fixer" gesprungen.

    EDIT: Jetz isses auch getestet.

    Yes, I'm the guy responsible for the Bitte melde dich an, um diesen Link zu sehen. cross assembler. And some Bitte melde dich an, um diesen Link zu sehen..

  • D.h.: Im Timer-IRQ Port 2 setzen, aktuelle Rasterline ermitteln, ca. ein Viertel des Screens draufaddieren, dementsprechend Raster-IRQ installieren, raus aus Timer-IRQ und dann im Raster-IRQ, der ca. 4ms später gestartet wird, die Werte auslesen?

    Wohl nicht.

    Bitte melde dich an, um diesen Link zu sehen. (Bitte melde dich an, um diesen Link zu sehen.)Bitte melde dich an, um diesen Link zu sehen.Bitte melde dich an, um diesen Link zu sehen.
  • D.h.: Im Timer-IRQ Port 2 setzen, aktuelle Rasterline ermitteln, ca. ein Viertel des Screens draufaddieren, dementsprechend Raster-IRQ installieren, raus aus Timer-IRQ und dann im Raster-IRQ, der ca. 4ms später gestartet wird, die Werte auslesen?

    Wohl nicht.

    WebFritzi Ja, ich denke auch so etwas wäre möglich. Auf diese Art wäre zumindest weiterhin die Geschwindigkeit des Cursor Blinkens sichergestellt, was beim Ausschalten des Timer IRQ und ausschliesslichen Abwicklung über den Raster IRQ nicht mehr der Fall wäre. Ich persönlich bin weiterhin auf der Suche nach dem Treiber-Minimum, was insgesamt am wenigsten Taktzyklen und Bytes verbraucht. Eigentlich am liebsten über Port 1, aber das mit dem Abfangen der Garbagezeichen-Einflüsse beim Drücken der linken oder rechten Maustaste, habe ich bisher noch nicht hingekriegt (z.B. hatte ein Poke 198,0 bei erkanntem Mausklick leider keinen Einfluss). Bin weiterhin am Forschen.

  • POKE 649,0 schaltet zumindest die Tastatur stumm. Aber sollte der geneigte C64 Anwender nicht wissen, dass er nicht wild auf der Maus rumhämmern sollte, wenn er eine Texteingabe tätigen muss. Aber es ist natürlich eine nette Challenge, jeden DAU abzufangen. :emojiSmiley-12:

  • Es ist natürlich genau umgekehrt... :anonym

    Supi. Funzt. Vielen Dank! Muss aber noch auf realer Hardware testen. Schaue ich mir dann morgen an.

    Habe das heute auf meinem echten C64 getestet. Was soll ich sagen... es funktioniert! :ChPeace

    Hier mein Maustreiber (für Joystick Port2) - ohne Warteschleife - als BASIC-Listing (inkl. Solitaire Mousepointer Sprite).

    Wenn man diese Zeilen in meinem Solitaire Listing ersetzt, dann läuft Solitaire damit um rund 30%(!) schneller und spielt sich damit um einiges flüssiger <3:).

    Der "Stack-Hack"-Teil sieht bei mir nun folgendermassen aus. Achtung: Ich setze hier in diesem Fall $dc00 nicht auf "$80" (%10000000), sondern auf %10111111, damit die unteren Bits gesetzt sind (statt gelöscht). Die $DC00 Leitungen sind im Normal/Default-Zustand ja AKTIV, wenn NICHTS gedrückt wird.

    Edit: Das auf itch.io herunterladbare Solitaire-Listing werde ich dementsprechend heute noch anpassen und eine neue Version mit diesen aktualisierten Zeilen hochladen.

    Edit2: Habe das "return" nun noch hinzugefügt. Danke Lynx. Hinweis: Das angehängte ".prg" hat das "return" nicht drin und lässt sich somit direkt starten.

  • Code
    2110 pokev,90:pokev+1,190:pokev+16,0:poke2040,13:pokev+21,1:sysad:return

    Für die Eiligen unter uns: in Zeile 2110 das RETURN noch hinzufügen, falls man mit copy&paste die Zeile komplett überschrieben hat.

  • dann läuft Solitaire damit um rund 30%(!) schneller und spielt sich damit um einiges flüssiger <3:) .

    Gern geschehen. :P;) Jetzt kann Lynx auf 2 MHz runterstellen.

    Bitte melde dich an, um diesen Link zu sehen. (Bitte melde dich an, um diesen Link zu sehen.)Bitte melde dich an, um diesen Link zu sehen.Bitte melde dich an, um diesen Link zu sehen.
  • dann läuft Solitaire damit um rund 30%(!) schneller und spielt sich damit um einiges flüssiger <3:) .

    Gern geschehen. :P;) Jetzt kann Lynx auf 2 MHz runterstellen.

    :emojiSmiley-23:genau das habe ich gemacht. Aber es läuft ja auch auf einem handelsüblichen Brotkasten performant genug.

    Das Solitaire wäre damals auf jeden Fall Listing der Jahres geworden und hätten den Mausverkauf um mindestens 200% gesteigert.

  • Dieses

    Code
    pha
    pha
    pha

    Wozu dient das? Ist es egal, was ich da in den Stack pushe? Könnte ich z.B. auch dreimal php machen?

    Bitte melde dich an, um diesen Link zu sehen. (Bitte melde dich an, um diesen Link zu sehen.)Bitte melde dich an, um diesen Link zu sehen.Bitte melde dich an, um diesen Link zu sehen.
  • Wozu dient das?

    Damit RTI beim ersten Aufruf von $EA81 richtig an das Statusregister und PC des Dummy-IRQ-Stackframes "herankommt".

    Ist es egal, was ich da in den Stack pushe?

    In diesem Fall, ja.

    Könnte ich z.B. auch dreimal php machen?

    Könntest Du, aber es werden nominell Registerinhalte gepusht, nicht der Status.

    Ansonsten gilt das, was ich bereits im anderen Thread geschrieben hab: schau dir das Verhalten der CPU, die Stackbefehle, den Interrupthandler im KERNAL bitte mal genauer an. Für wizball6502 war es kein größerer Akt, die Sache zu implementieren nachdem die Grundidee klar war.

  • Gern geschehen.

    WebFritzi Ja, danke nochmals für den Hinweis, dass das BASIC Programm mit Maustreiber langsamer lief. Das hatte ich irgendwie gar nicht gechecked, dass ein IRQ gesteuertes Maschinenprogramm Einfluss auf die Geschwindigkeit eines BASIC-Programms haben könnte. Aber hängt ja logischerweise alles zusammen. Und die Warteschleife verbrätzelte als Folge wertvolle CPU-Cycles. Ironischerweise habe damals ich im BASIC nichts unversucht gelassen, um die Geschwindigkeit zu steigern (z.B. Verwendung von Variablennamen statt Konstanten), dabei war die Mess-Wartschleife für Port2 der wesentliche Einfluss auf die BASIC-Performance. Hach Göttle! Wieder was gelernt. :saint:

    Und Mac Bacon auch nochmals danke für den Tipp mit dem "Stack-Hack". Mit diesem kleinen "Dreh" wurde mein Maustreiber nur ein paar Bytes grösser, so dass alles noch in dieselben Anzahl Zeilen bzw. auf 3 A4 Seiten passt.

  • WebFritzi Ironischerweise habe damals ich im BASIC nichts unversucht gelassen, um die Geschwindigkeit zu steigern (z.B. Verwendung von Variablennamen statt Konstanten), dabei war die Mess-Wartschleife für Port2 der wesentliche Einfluss auf die BASIC-Performance.

    Du könntest z.B. noch alle Nullen durch einen Punkt ersetzen. Das bringt auch etwas Speed.

    Was mir noch aufgefallen ist: wenn der Stapel zu lang wird, werden die unteren Karten nicht mehr angezeigt. Ich habe das bei mir so gelöst, dass ich die letzte Karte ganz unten anzeige und die Character-Line darüber suggeriert, dass sich dazwischen noch andere Karten befinden.

    Bitte melde dich an, um diesen Link zu sehen. (Bitte melde dich an, um diesen Link zu sehen.)Bitte melde dich an, um diesen Link zu sehen.Bitte melde dich an, um diesen Link zu sehen.

    Einmal editiert, zuletzt von WebFritzi (13. August 2021 um 14:35)

  • Das Solitaire wäre damals auf jeden Fall Listing der Jahres geworden und hätten den Mausverkauf um mindestens 200% gesteigert.

    Danke für die Blumen. Nur daaamalstm hätte ich ohne Internet und Forum64 wohl kaum was gescheites auf die Beine stellen können. Umso schöner ist es, dass nun fast 40(!) Jahre später nachzuholen.

    Ein Hoch auf all diejenigen, welche in den 80er Jahren ohne äussere Hilfe die Innereien des C64 verstanden hatten. Das war schon eine echte Leistung und hart erarbeiteter Sachverstand.

  • Was mir noch aufgefallen ist: wenn der Stapel zu lang wird, werden die unteren Karten nicht mehr angezeigt. Ich habe das bei mir so gelöst, dass ich die letzte Karte ganz unten anzeige und die Character-Line darüber suggeriert, dass sich dazwischen noch andere Karten befinden.

    Ja, ich habe das bei mir so gelöst, dass man im Falle eines zu langen Stapels auf das unterste Kartenelement, dessen Oberteil grad noch so herausschaut, klicken kann und es wird dann der komplette untere Teil der Kartenreihe aufgebaut bzw. angezeigt. Damit hat man etwas mehr Spielraum für's Umschichten. Danach kann man wieder auf das oberste Kartenelement in der Reihe klicken und sieht dann wieder den oberen Teil der Kartenreihe. Ich finde deine Lösung für das Problem des zu langen Stapels aber auch gut.

  • Du könntest z.B. noch alle Nullen durch einen Punkt ersetzen. Das bringt auch etwas Speed.

    Ja, das wende ich bei meinen BASIC-10-Linern in der Regel an, um ein kleines bisschen mehr Performance herauszuholen. Viel ist es aber nicht. Bei meinen BASIC-Listings zum Abtippen habe ich darauf verzichtet, weil sich da vielleicht Leute wundern bzw. sogar das als Tippfehler ansehen könnten und dann verunsichert sind. Den Hintergrund mit dem Dezimalpunkt statt Null (der Wert muss damit vom Interpreter nicht mehr in eine Fliesskommazahl-Null konvertiert werden) kennen vermutlich nur BASIC-Insider bzw. aufmerksame Forum64 Leser :).