Collab: Entwicklung eines TSB-Puzznic-Klons

Es gibt 1.089 Antworten in diesem Thema, welches 110.226 mal aufgerufen wurde. Der letzte Beitrag (1. November 2024 um 23:56) ist von Omega.

  • Ich habe nochmal eine Verständnisfrage zum Verkleinern des Basic-Speichers:

    Wenn ich print d!peek(55) eingebe, dann bekomme ich als Ergebnis 32768.

    Normalerweise liegt das Ende des Basic-Speichers also bei dieser Adresse 32768.

    Wenn ich jetzt beispielsweise mit d!poke 55,30270 den Basic-Speicher einschränke.

    • Steht dann die Adresse 30270 auch schon für eigene Programme zur Verfügung? Oder gilt das erst ab Adresse 30271?
    • Und kann ich die Adresse 32768 für eigene Programme benutzen? Oder geht das nur bis Adresse 32767?

    Mir ist nicht ganz klar, wo genau (ich meine auf's Byte genau) ich den Speicher nutzen darf.

  • Normalerweise liegt das Ende des Basic-Speichers also bei dieser Adresse 32768.

    Wenn du mal print $$d!peek(55) eingibst, wird dir das vielleicht klarer. Dann steht da nämlich $8000, und - wie du weißt - ist das der Anfang von TSB. Die von 55 angegebene Adresse ist also der Anfang des BASIC-Bereichs. Das freie Basic-RAM endet dementsprechend ein Byte vorher, bei $7fff (bzw. 32767). Bis dahin kannst du das RAM nutzen. Wenn du also einen neuen Wert nach 55 POKEst, legst du damit den Anfang deines Privat-Speichers fest (und musst höllisch aufpassen, dass der alte Wert - bzw. die Bytes im vorher geltenden Bereich ab $8000 - nicht irgendwie von deinen Bytes beschädigt werden - aber das ist ja immer so).

    Arndt

    GoDot C64 Image Processing
    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. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • Die von 55 angegebene Adresse ist also der Anfang des BASIC-Bereichs.

    Jetzt bin ich total verwirrt. Im C64-Wiki findet sich die folgende Skizze. Nach meinem Verständnis der Skizze sind die Bytes 55/56 ein Zeiger auf das Ende des BASIC-RAMs. Und wenn ich das Ende nach vorne verlege, dann verschaffe ich mir dahinter Platz für meine eigenen Daten.

    Bitte melde dich an, um diesen Anhang zu sehen.

  • Ich frage nochmal anders:

    Wenn ich d!poke 55,30270 eingebe, dann habe ich mir einen Privatspeicher von 30270 ($763e) bis 32768 ($8000) eingerichtet.

    Kann ich die Adresse 30270 ($763e) jetzt einfach überschreiben (JA/NEIN).

    Kann ich die Adresse 32768 ($8000) jetzt einfach überschreiben (JA/NEIN).

  • Oh, oh, oh! Ich bin ganz aufgeregt. Mir ist da gerade noch eine tolle Idee gekommen. :D

    Könntest du es so einrichten, dass der Befehl x!step noch einen zweiten Wert in der Adresse 873 zurückgibt? Dabei soll es sich um die Anzahl der Steine handeln, die gefallen sind. Eigentlich interessiert mich dabei nur, ob überhaupt ein Stein gefallen ist (0=Nein, 1=Ja). Aber wenn du die Anzahl der gefallenen Steine zählst, dann ist das wahrscheinlich auch nicht komplizierter. Und wer weiß, wofür man es noch brauchen kann? Dann hätte man peek(873)=0 kein Stein gefallen oder peek(873)>0 mindestens einer ist gefallen.

    Mit dieser Erweiterung könnte ich den TSB-Code deutlich reduzieren und beschleunigen.

    Die Belegung des Kassettenpuffers würde dann so aussehen:

    Adresse dez.Adresse hex.Bedeutung
    828-872$033c-$0368unbenutzt
    873$0369Erster Rückgabewert von x!step.
    Anzahl der Steine, die gefallen sind.
    874$036aZweiter Rückgabewert von x!step.
    Anzahl der verbleibenden Spielsteine auf dem Spielfeld.
    875-1019$036b-$03fbRückgabeliste von x!clr.
    Liste der zu löschenden Spielsteine, Endekennung = 255.
    145 Bytes (bis zu 144 Bytes und 1 Byte für die Endekennung).
  • Jetzt bin ich total verwirrt. Im C64-Wiki findet sich die folgende Skizze. Nach meinem Verständnis der Skizze sind die Bytes 55/56 ein Zeiger auf das Ende des BASIC-RAMs.

    Nein, das ist im Wiki falsch ausgedrückt. Bei Basic V2 steht in MEMSIZE der Wert $a000, und das ist der Anfang des Basic-ROMs. Der ganze Begriff MEMSIZE ist falsch, denn das klingt ja so, als ob $a000 Bytes frei wären, was ja nun völliger Quark ist. Der String-Heap fängt bei MEMSIZE-1 (also $7fff bei TSB) an und wird im Betrieb immer kleiner. Das sagt dir auch, was beschrieben werden darf: Wenn du MEMSIZE nach unten verlegst (also den Bereich ab dort vom String-Heap abtrennst), hast du genau ab dort freie Hand, ab dem neuen MEMSIZE.


    Zu deiner neuen Idee: Lässt sich sicher machen. Die Tabelle hab ich jedenfalls schon fertig. Frage: Wie herum soll sie angelegt sein? Aufsteigend oder absteigend? Im Moment ist sie aufsteigend (fängt mit der obersten Zeile an). Eingetragen ist jeweils der Tile-Typ. Wozu brauchst du eigentlich den Ende-Marker, die Tabelle hat doch eine definierte Länge?

    Arndt

    GoDot C64 Image Processing
    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. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

    Einmal editiert, zuletzt von GoDot (26. Februar 2024 um 01:00)

  • GoDot:

    1.) Hmmm. Das beantwortet jetzt nicht so ganz meine Frage aus Post#384.

    2.) Die Tabelle soll aufsteigend angelegt sein. Linke obere Ecke = 0. Rechte untere Ecke = 143. So wie in meiner Zeicnung. Aber...

    3.) Ich habe es mir so vorgestellt, dass die Tabelle eine variable Länge hat. Je nachdem, wieviele Spielsteine gelöscht werden müssen. Wenn z.B. nur zwei Spielsteine gelöscht werden, dann wird nur die Adresse 875 und 876 benutzt. Und in 877 steht dann die 255 als Endekennzeichen. Damit man beim Durchlesen erkennen kann, wo das Ende ist. Das muss auch so sein. Sonst müsste das Basic-Programm die ganze lange Tabelle abgrasen, was zu lange dauert.

    Beispiel: Wenn nur der Stein in der linken oberen Ecke und der Stein in der rechten unteren Ecke gelöscht werden. Dann steht in 875 die Nummer 0 und in 876 die Nummer 143. Und in 877 die 255. Verstehen Sie?

  • Ich möchte es nochmal anders beschreiben:

    Jedesmal wenn du einen Spielstein findest, der gelöscht werden kann, dann verlängerst du die Tabelle um ein Element. D.h. wenn gar kein Spielstein zum Löschen gefunden wurde, dann steht direkt an erster Stelle in Adresse 875 der Wert 255. Und jedesmal wenn du die Tabelle um ein Element verlängerst, dann rutscht die 255 um ein Byte nach hinten

    So kann man schnell prüfen, ob überhaupt etwas gelöscht werden muss. Wenn peek(875)=255 ist, dann weiß das TSB-Programm, dass keine Steine zum Löschen gefunden wurden.

    In den meisten Fällen wird die Tabelle nur ca. 3 oder 4 Bytes lang sein. Aber da theoretisch jedes Feld den gleichen Spielstein enthalten könnte, braucht man bis zu 145 Bytes (Ich weiß, das ist ziemlich unrealistisch. Aber man muß ja auf alle Eventualitäten vorbereitet sein).

  • Sie haben für diese Aufgabe 2 Stunden Zeit. Hilfsmittel, wie Taschenrechner und das C64-Handbuch, sind erlaubt. ;)

  • Dann hab ich die Idee dahinter nicht ganz verstanden. Du hast ja keine Information, wo der Stein steht, den du löschen willst. Ich hatte deine Idee so verstanden, dass die Nummer des Steins in der Tabelle ja gleichzeitig auch dessen Adresse klärt. Wenn du nun aber die Steine einfach nach Vorkommen ablegst, geht dir diese Information verloren. Wie willst du dann den Ort finden, wo der Löschvorgang stattfinden soll?

    Arndt

    GoDot C64 Image Processing
    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. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • Nehmen wir mal an, wir haben folgende Konstellation:

    Bitte melde dich an, um diesen Anhang zu sehen.

    Da sind vier Herzen, die gelöscht werden sollen. Also speicherst du in der Tabelle

    51, 52, 53, 64, 255

    Anhand dieser fünf Werte kann ich nachher im TSB-Programm feststellen, dass es:

    • 4 Steine gibt, die gelöscht werden müssen
    • wo sich diese Steine befinden, ergibt sich aus der Feldnummer im Grid (0-143).

    Die gespeicherten Zahlenwerte kann ich leicht in echte Koordinaten (X: 0-11 und Y: 0-11) zurückrechnen:

    Rechenbeispiel:

    Erster gelesener Wert ist A=51. Dann haben wir:

    A=51

    Y=INT(A/12) ergibt 4

    X=A-Y*12 ergibt 3

    Anhand der Zahl 51 wissen wir nun, dass die X/YKoordinaten folgende sind: x=3, y=4.

  • Hab ich mir inzwischen auch überlegt. So machen wir das! :smile: Einen Stop-Wert haben wir aber schon: die Null! Wozu die 255 dahinter?

    Arndt

    GoDot C64 Image Processing
    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. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • So als Anregung:

    Für solche Spielfelder und Prüfungen auf Nachbarsfelder wird gerne ein Array genommen, das eine Extra-Spalte außerhalb besitzt, damit man nicht extra auf X < 0 oder X > 11 prüfen muss.
    Man liest einfach ein leeres Feld und es passt.

    C64Studio: Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. --- C64Studio WIP: 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.

  • Einen Stop-Wert haben wir aber schon: die Null! Wozu die 255 dahinter?

    Weil die Null das oberste linke Feld in der Ecke repräsentiert. Der Stopp-Wert muss im Bereich 144-255 liegen. Also warum nicht 255? Das springt einem gut ins Auge. :anonym

    Beispiel: Ich lese in einer Schleife solange die Werte, bis ich irgendwann die 255 lese. Dann ist Ende. Die 0 kann man dafür nicht nehmen.

  • Für solche Spielfelder und Prüfungen auf Nachbarsfelder wird gerne ein Array genommen, das eine Extra-Spalte außerhalb besitzt, damit man nicht extra auf X < 0 oder X > 11 prüfen muss. Man liest einfach ein leeres Feld und es passt.

    Wie man das macht, hat GoDot bereits erfolgreich herausgefunden. Wir beraten uns nur noch über die Übergabe der Daten vom Assembler zum Basic Programm.

  • Weil die Null das oberste linke Feld in der Ecke repräsentiert. Der Stopp-Wert muss im Bereich 144-255 liegen. Also warum nicht 255? Das springt einem gut ins Auge.

    Ach ja, nicht bedacht! Ok!

    Arndt

    GoDot C64 Image Processing
    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. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • Ich fände 666 als Endezeichen noch besser ins Auge springend. :bgdev

    Gute Idee. Dann brauchen wir zwar noch zwei extra Bits in jedem Byte. Aber ich bin sicher, dass GoDot das irgendwie hinkriegt. :D

    "Erweitern Sie Ihren C64 mit TSBneo zu einem 10-Bit-Computer!" :party2:

  • Ich fände 666 als Endezeichen noch besser ins Auge springend. :bgdev


    Bitte melde dich an, um dieses Medienelement zu sehen.

    Arndt

    GoDot C64 Image Processing
    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. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.