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.
Neues Solitaire (Kartenspiel) für den Commodore 64 in BASIC V2 - Gratis Abtipp-Listing zum Herunterladen (PDF)
-
wizball6502 -
15. Februar 2021 um 12:36 -
Erledigt
Es gibt 140 Antworten in diesem Thema, welches 24.506 mal aufgerufen wurde. Der letzte Beitrag (
-
-
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.
-
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?
-
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:PHAeinen IRQ-Kontext auf dem Stack.
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...
Codelda #>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.
-
Es ist natürlich genau umgekehrt...

Supi. Funzt. Vielen Dank! Muss aber noch auf realer Hardware testen. Schaue ich mir dann morgen an.
-
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.
-
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...

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!

Hier mein Maustreiber (für Joystick Port2) - ohne Warteschleife - als BASIC-Listing (inkl. Solitaire Mousepointer Sprite).
Code
Alles anzeigen2050 rem *************************** 2060 rem *** mouse pointer setup *** 2070 rem *************************** 2080 ad=49152:h=int(ad/256):rem install driver at $c000 (49152) 2090 fori=0to217:reada:pokead+i,a:next:fori=1to8:reada:pokead+a,h:next 2100 fori=0to62:reada:poke832+i,a:next:v=53248:pokev+36,14:pokev+39,0 2110 pokev,90:pokev+1,190:pokev+16,0:poke2040,13:pokev+21,1:sysad:return 2120 rem *** 1351 mouse driver (port 2) 2130 rem 251=xpos / 252=ypos / 253=xpos high bit / 254=mouse click values 2140 rem process mouse click(s) - then poke254,0 to wait for next click 2150 data 120,169,13,141,20,3,169,192,141,21,3,88,96,165,254,208,21,173,0,220 2160 data 73,255,41,17,240,12,133,254,173,0,208,133,251,173,1,208,133,252,173 2170 data 25,212,160,0,32,184,192,140,42,192,164,253,208,11,172,0,208,192,19 2180 data 208,4,224,0,208,42,24,109,0,208,141,0,208,168,138,105,0,41,1,77,16 2190 data 208,141,16,208,41,1,133,253,208,8,192,19,176,13,169,19,208,6,192,81 2200 data 144,5,169,81,141,0,208,173,26,212,160,0,32,184,192,140,110,192,172,1 2210 data 208,192,50,208,4,224,0,240,35,192,247,208,4,224,0,208,27,56,73,255 2220 data 109,1,208,201,50,176,8,201,30,144,8,169,50,208,6,201,247,144,2,169 2230 data 247,141,1,208,169,192,72,169,176,72,8,72,72,72,76,49,234,169,191,141 2240 data 0,220,76,129,234,140,194,192,141,216,192,162,0,56,233,0,41,127,201,64 2250 data 176,5,74,208,11,138,96,9,192,201,255,240,248,56,106,202,160,0,96 2260 rem *** driver hi byte patch table so it can be installed other than $c000 2270 data 7,45,48,113,116,164,186,189 2280 rem *** mouse pointer sprite data 2290 data 6,0,0,9,0,0,9,0,0,9,0,0,9,0,0,9,192,0,9,56,0,9,38,0,9,37,0 2300 data 233,36,128,152,4,128,136,0,128,72,0,128,40,0,128,32,0,128 2310 data 16,0,128,16,1,0,8,1,0,8,1,0,4,2,0,3,252,0Wenn 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

.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.
Code
Alles anzeigenlda #>resetPaddlePort: pha lda #<resetPaddlePort: pha php pha pha pha jmp $ea31 resetPaddlePort: lda #%10111111 sta $dc00 jmp $ea81Edit: 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.
-
-
dann läuft Solitaire damit um rund 30%(!) schneller und spielt sich damit um einiges flüssiger

.Gern geschehen.

Jetzt kann Lynx auf 2 MHz runterstellen. -
dann läuft Solitaire damit um rund 30%(!) schneller und spielt sich damit um einiges flüssiger

.Gern geschehen.

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.
-
-
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.

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.
-
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
. -