Hello, Guest the thread was called2.4k times and contains 50 replays

last post from JeeK at the

Variablenwert aus Basic durch Poke verändern

  • Bildschirmadresse wieder irgendwo hinsetzen, z.B. mit POKE 648,160 nach $A000, dann PRINT"{steuerzeichen für farbe}{clr}", und wieder POKE 648,4.

    :thumbsup:


    Für die Anzeige ab $4000 muss man den anderen Steuerkram in CIA2 und VIC auch noch setzen. Dafür böte sich dann eine Unterroutine an.

    Ist den Aufwand wohl nicht Wert.


    Ich schreibe jetzt den Dateiinhalt in Variablen, gebe die bei Bedarf aus und füge dann an manchen Stellen etwas Farbe und anderen Inhalt ein.

    So ist das relativ komfortabel.

  • Mit ROM-RAM kannst du den Bildschirm ins obere RAM verlegen und dort umschalten. Und mehrere Bildschirme verwalten.

    Das Farbram kann man mit Block-Kopy sichern und wiederherstellen.


    Falls es nur um das Umfärben geht, braucht man nur den Bildschirm umzuschalten und unsichtbar zu printen.
    Damit kann man dann alle Farbcodes mit dem Print-Befehl umfärben.


    Grundsätzlich kann man auch kleine Basic-Programme(3kB,12 Blocks) nach 49152 laden und dort ausführen.


    Schönen Gruß.

  • Die kanonische Lösung wäre wohl, die benötigten Bildschirmmasken - incl. derer Farbinformation - mit einer geeigneten Methode in geschützten Speicher zu laden und von da aus mit einer kleinen Maschinenroutine in den Standard-Bildschirmspeicher/Farb-RAM zu kopieren:

    In $FC und $FE stehen Quell- und Zielpage - die legt man per POKE 252,... und POKE 254,... vor dem SYS fest - und die Routine kopiert immer 4 Pages.


    All die zuvor genannten Verrenkungen in BASIC wollen letztenendes nur das gleiche erreichen, aber hier ist wenigstens klar was läuft.

  • Schöner Trick

    Jo, sogar ohne unnötige Doppelpunkte. Nur, was hat man damit erreicht, was man nicht auch durch herkömmliche Variablenmanipulation tun könnte?


    dim a$:a$="abcdefg":print left$(a$,1)

    vs.

    dim a$,a:a$="abcdefg":a=len(a$)*0+peek(71)+peek(72)*256:poke a,1:print a$

    ...

    Am Ende muss man den String so oder so noch in den passenden Bildschirmspeicher an der richtigen Stelle PRINTen, auch dann, wenn nur die Farbe geändert werden soll. Einzelne POKEs direkt in den Farbspeicher gehen, aber ganze Passagen mit POKE färben, das wäre langsam und sperrig. Besser mit PRINT oder einer kleinen Asm-Routine.


    Viele Wege führen nach Rom, und welcher der beste ist, lässt sich immer nur sagen, wenn man haargenau weiß, wo was wie in dem Programm passieren soll, ob Geschwindigkeit oder Speicherverbrauch wichtiger ist, ob bestimmte Aufgaben durch Assembler-Routinen ersetzt werden dürfen, bspw. eine zum Färben bestimmter Bildbereiche, oder eine zum Swappen von Bildschirminhalten, etc.

  • Die Tricks sind schon ulkig, aber sorgen auch häufiger dafür, dass das Ergebnis nicht mehr durch einen BASIC-Compiler geht. Nur falls sowas irgendwann auf dem Plan steht...


    Im Zusammenhang mit Gold Quest ist https://github.com/c1570/CrankThePRINT entstanden. Sowas wie eine Menümaske kann einfach als viele PRINTs geschrieben werden; die einzufärbenden Teile separate PRINTs mit CHR$ zum Farbe setzen; das funktioniert dann "einfach so" ohne weiteres und ist nach Crank the PRINT und Compiler ggf. rasend schnell, ganz ohne Tricks im reinen BASIC.

  • Die Bedeutung des Trick ist, das ich jeden Speicherbreich als String lesen kann.

    Eine Anwendung, die ich unter GBC-Vermeidung gepostet habe ist auch z.B. die Umwandlung von Num nach String bei Tasteneingaben.

    mit Sys Getin habe ich dabei die Tastatur gelesen und die Stringadresse auf den Akku 780 gesetzt. Damit hat man dann eine automatische Wandlung in einen String ohne Stringanlegen und GBC im Stringbreich.


    Schönen Gruß.

  • dim a$,a:a$="abcdefg":a=len(a$)*0+peek(71)+peek(72)*256:pokea,1:printa$

    Hmm... als Mathematiker hänge ich bei len(a$)*0 - ist das nicht immer null?!


    Nur, was hat man damit erreicht, was man nicht auch durch herkömmliche Variablenmanipulation tun könnte

    left$.. erstellt einen neuen String. Bei dem anderen... ??!


    Die kanonische Lösung wäre wohl, die benötigten Bildschirmmasken - incl. derer Farbinformation - mit einer geeigneten Methode in geschützten Speicher zu laden und von da aus mit einer kleinen Maschinenroutine in den Standard-Bildschirmspeicher/Farb-RAM zu kopieren:

    Ja, kann man machen - und irgendwo ist dann wohl auch der Punkt erreicht, wo man auch Basic ein bißchen pimpen sollte. Wollte mich da ja später mal dran versuchen.


    das funktioniert dann "einfach so" ohne weiteres und ist nach Crank the PRINT und Compiler ggf. rasend schnell, ganz ohne Tricks im reinen BASIC.

    Ohne mich da jetzt allzu sehr reinzulesen... wird hier nicht auch nur ein kleines Assembler Programm gepoket und aufgerufen?

    Falls es nur um das Umfärben geht, braucht man nur den Bildschirm umzuschalten und unsichtbar zu printen.

    Das wäre dann die selbe Technik, wie der "schnelle einfarbige Bildschirm" weiter oben im Thread.

    Aber um darauf nochmal zurückzukommen. Wenn ich einen Bereich für das umschalten des Bildschirms verwende: Wie vermeide ich, dass der Bereich mit Variablen überschrieben wird oder ich Variablen überschreibe?

  • dim a$,a:a$="abcdefg":a=len(a$)*0+peek(71)+peek(72)*256:pokea,1:printa$

    Hmm... als Mathematiker hänge ich bei len(a$)*0 - ist das nicht immer null?!

    Ja, aber der Befehl hat einen Seiteneffekt, nämlich die Adresse des Strings bei Adressen 71/72 zu hinterlegen. Da Basic das nicht wegoptimiert, wird brav die Länge des Strings ermittelt, dabei diese Adressen geschrieben und das Ergebnis dann mit 0 multipliziert, also verworfen. Danach wird die Adresse berechnet, so dass poke a, ... an der richtigen Stelle herumsauen kann.

  • Ja, aber der Befehl hat einen Seiteneffekt, nämlich die Adresse des Strings bei Adressen 71/72 zu hinterlegen.

    Aah, danke für die Erklärung. Das hätte die Sache von Anfang an "interessanter" und weniger kryptisch gemacht. Danke, danke!

  • Mit der Verwendung des ROM-RAM-Kopier-Codes wird das Überschreiben des Bildschirms vermieden.

    Weil man mit ROM-RAM die oberen 16kB für die Grafikdaten und Bildschirme benutzt.


    80 :rem-rom-ram,schirm:52224,satz:53248

    81 :poke56334,.:poke1,51:forj=88to91:pokej,.:next:poke781,97:poke782,.:sys41971

    82 :poke1,53:poke648,204:sys65374:sys58692:poke56576,4:poke53272,54:return


    Die erstmals gepostete Variante:

    150 :rem--rom/ram,bild:52224,satz:53248

    151 poke56334,0:poke1,51:fori=88to91:pokei,0:next:poke781,97:poke782,.:sys41971

    152 :poke53248+32*8+6,16:rem--zeichen demo

    153 poke1,53:poke56334,1:poke648,204:sys58692:poke53272,52:poke56576,196:return


    Schönen Gruß.

  • left$.. erstellt einen neuen String

    Nur temporär am unteren Ende des Stringspeichers. Die benutzten Bytes gelten weiterhin als frei und werden nirgends registriert.

    Bei dem anderen... ??!

    Zusätzlich a, registriert und dauerhaft.


    Zudem hat man mit dem Beispiel mal erst nur die Länge. Um den String selbst zu manipulieren, muss man wieder andere Speicherzellen auslesen, die Startadresse zusammenfummeln und den Offset addieren, und nicht zu vergessen, die String-Variable vorher immer zu benutzen, am besten mit der Fließkomma-Multiplikation, weil die ja so schnell ist. Das benötigt am Ende mehr Speicher und Rechenzeit als LEFT$() und co. mit temporär entstehenden Strings. Ich kann dazu einen Testlauf mit Zeitmessung machen. Es ging ja hier um die effiziente Umschaltung von unterschiedlich farblichen Bildschirminhalten und nicht um das Auslesen des Eingabepuffers o.ä., wenn ich es richtig verstanden habe.

  • Nur temporär am unteren Ende des Stringspeichers. Die benutzten Bytes gelten weiterhin als frei und werden nirgends registriert.

    Ah, gut zu wissen, danke.


    Ursprünglich war der Gedanke den Bildschirminhalt weitestgehend feststehend in Variablen (als Print-Text) zu haben und nur die Farbe an manchen Stellen zu ändern, indem man dort dann entsprechend einen anderen Farbwert poked. Dazu wäre BIFs Variante, so wie ich das sehe, durchaus geeignet.


    Zudem hat man mit dem Beispiel mal erst nur die Länge. Um den String selbst zu manipulieren, muss man wieder andere Speicherzellen auslesen,

    Doch eben nicht, wenn ich das richtig verstanden habe. Len ist ja nur Mittel zum Zweck, damit in 71,72 die Adresse des Strings abgelegt wird. Die Länge und die genaue Position (vom Start aus) weiß ich ja.

    Weil man mit ROM-RAM die oberen 16kB für die Grafikdaten und Bildschirme benutzt.

    Ähm... um Dein Beispiel nachzuvollziehen muss ich noch ein paar Bier mehr trinken...:/

  • Len ist ja nur Mittel zum Zweck, damit in 71,72 die Adresse des Strings abgelegt wird.

    Wird sie nicht, sondern nur die Adresse der Variable a$ (Name inkl. Typ, Länge, Textzeiger), nicht ihres Inhalts. Ich bezog mich nicht auf das LEN(), sondern auf poke a,1:print a$. Die erste (Nutz-)Stelle der String-Variable a$, die hinter dem BASIC-Programm liegt, ist also die Länge, die er hier von 7 auf 1 verkürzt, sodass beim PRINTen nur noch das A erscheint. Danach kommt der Text-Zeiger, der auf den Text zeigt, der am Ende des BASIC-Speichers liegt. Diesen Zeiger, den man nach Gebrauch der Variablen auch in der Zeropage findet, muss man wiederum für die Manipulation des Strings selbst benutzen.


    Ursprünglich war der Gedanke den Bildschirminhalt weitestgehend feststehend in Variablen (als Print-Text) zu haben und nur die Farbe an manchen Stellen zu ändern

    So würde ich es auch machen.

    indem man dort dann entsprechend einen anderen Farbwert poked.

    Das muss natürlich jeder für sich entscheiden, aber das würde ich eben nicht machen, weil es m.E. sperriger und langsamer ist. Wie gesagt, man muss ja die Strings sowieso noch PRINTen, denn vom Ändern desselben allein passiert ja noch nichts. Und dann täte es ein einziger POKE in 646 oder ein Farb-Steuercode. Auch das Invertieren ist so kein Problem, zuletzt so gemacht in der 2-Player-Menüvorlage "doubletask.prg", Dez. 2019. Ich glaube, PIRATES! und "Die Fugger" PRINTen ihren Text auch hin, ohne fertige Screens zu speichern.

  • Die Farbcodes in den String zu poken ist zwar nicht unmöglich,
    aber eigentlich unüblich.

    Das macht man normalerweise eigentlich so:

    z.B.

    a$="test test test":
    print"[weiß]"a$"[rot]"a$
    print"[gelb]"a$
    print"[grün,revers]"a$


    Für die direkte Berechnung der String-Adresse und der Basic-Zeilenadresse hab ich übrigens auch schon eine Formel gepostet.

    Ansonsten kann man das natürlich auch mit SYS-Aufrufen ermitteln.



    Schönen Gruß.