Hallo Besucher, der Thread wurde 2,3k mal aufgerufen und enthält 13 Antworten

letzter Beitrag von Bytebreaker am

Hat schon mal jemand Probleme mit GET# gehabt?

  • Ich habe zugegebenermaßen ein Extrembeispiel.
    Ich habe 3.600 Koordinaten mit der Open-Funktion exportiert und sie mit get# importiert.
    get# ist aus meiner Sicht kein besonders toller Befehl.
    Zeilenweises Einlesen geht nicht, ich muss eine eigene Verarbeitungslogik nutzen um Zeichen einzeln zu parsen, zusammenzusetzen und in rechenbare Werte umzuwandeln.
    Die Umwandlung von Petscii in Zahl ist nicht so schlimm, aber dass ich selber prüfen muss wieviele Ziffern jeweils in einer Zeile stehen um diese dann zu verketten finde ich schon schlecht.


    Noch blöder finde ich, dass die get#-Funktion evtl. Fehler beim Einlesen macht. Mein Export sieht sauber aus. Aber nach dem Import habe ich im Mittelteil der Daten eigentlich immer ein paar Mal Fehler drin. Wenn mein Einlese-Algorithmus gefühlt bei 3500 von 3600 Werten richtig arbeitet, kann da imho nicht der Fehler liegen. Wobei ich auch gerne blöde Fehler mache, so ist es nicht.


    Daher die Frage in die Runde: Ist get# dafür bekannt dass es bei großen Zahlenmengen fehlerhaft arbeitet?



    P.S.: die Leier mit Loco Basic fange ich gar nicht erst an. Dort tut alles nämlich wunderbar per zeilenweisem Einlesen ohne Einzelzeichen-Verarbeitung und manueller ziffernabhängiger Verkettung. Man hat dem CPC eben keine Sprites gegeben. Tja so ist es eben.

  • Der einzige Fehler von GET# ist, dass Nullbytes nicht als CHR$(0), sondern als Leerstring zurückgegeben werden. Wie sieht denn Dein Datenformat aus? Wenn Du die Exportfunktion eh beliebig abändern kannst, sollte da auch ein Format machbar sein, dass dann problemlos per INPUT# zurückgelesen werden kann (hauptsächlich aus Geschwindigkeitsgründen, aber auch weil dann Zahlen automatisch wieder konvertiert werden und man das nicht zu Fuß machen muss).

  • Mit OPEN exportiert man keine Daten, das öffnet nur eine Datei. Zahlen, die man mit PRINT# ausgeschrieben hat, sollte man mit INPUT# zurücklesen. Und eine Routine mit drei Prozent Fehlerrate ist definitiv fehlerhaft- oder sie triggert ganz gezielt ein Problem des Computers. Das könnte man besser beurteilen, wenn man den Programmcode kennen würde.

  • Hallo!


    Ich habe mich als Loco Basic Verliebter wohl etwas zu sehr ans V2 Basic Bashing gewöhnt - ich war ungerecht.


    input# macht genau das was ich will - zeilenweises Einlesen aus Datei und gefühlt sogar noch schneller als beim CPC. Dabei gilt das per Basic angesteuerte 1541 Laufwerk ohne Speedloader ja schon als kreuzlahm.


    Ich habe mit beiden Varianten, get# und print#, etwa in der Mitte der 3600 Werte, so zwischen dem 1500. und 1600. Wert, fehlerhaft eingelesene Werte ins Array. Die sind dann 0, oder 200 bei get#, bei print# liegen die Werte noch innerhalb von 319x199, daher stoppt mein Programm nicht (anders als bei der get# Version).


    Ich glaube mittlerweile aber nicht mehr, dass get# und print# hier Fehler machen. Ich glaube, der C64 kriegt einfach nur einen Daten-Koller weil ich mit wüsten Fließkomma-Arrays wahrscheinlich Betriebssystem-Teile beeinflusse/überschreibe. Das sehe ich an korrupten Bits in der Bitmap während des Einlesens. Da ist der Grafik-Modus nämlich schon an. Ich habe die normale Ausgangssituation mit $801 und keine platzoptimierte Positionierung von BasicRAM, Bitmap, etc.


    Ich hatte auch schon mit Integer-Typen experimientiert, aber da klappt es dann gar nicht. Dabei ist Integer mit 2 Byte doch viel kürzer als der C64 Standard Float mit 6 Bytes (es sind doch 6 beim C64?). Ich arbeite nämlich nur mit Ganzzahlen, da ist kein einziges Komma dabei.


    Sinn von alledem war, Koordinaten von Animationsphasen per Datei einzulesen und im HiRes Modus einlesebasiert zu zeichnen anstatt in Echtzeit zu berechnen.


    Anbei noch der Quellcode:


    get#, so vergewaltigt dass es dasselbe macht wie #input:


    8000 rem grid laden
    8010 open 1,8,2,"grid.bin"
    8020 for a=1 to 120
    8021 for w=0 to 14
    8022 get#1,a$
    8023 if asc(a$)=13 then goto 8030
    8024 b$=b$+a$:goto 8022
    8030 x=val(b$):co(0,w,a)=x
    8031 b$=""
    8040 get#1,a$
    8041 if asc(a$)=13 then goto 8043
    8042 b$=b$+a$:goto 8040
    8043 x=val(b$):co(1,w,a)=x
    8044 b$=""
    8050 next w:next a
    8051 close 1
    8052 return


    Und jetzt die viel schnellere input# Funktion:


    8000 rem grid laden
    8010 open 2,8,4,"grid.bin"
    8020 for a=1 to 120
    8021 for w=0 to 14
    8022 input#2,a$:x=val(a$):co(0,w,a)=x
    8043 input#2,a$:x=val(a$):co(1,w,a)=x
    8050 next w:next a
    8051 close 1
    8052 return


    Die Koordinatenliste zum Nachvollziehen ist angehängt. Die Koordinaten-Datei wurde aus einer Echtzeit-Animation heraus exportiert mit print#. Es sind 120 Animationsphasen von bewegter Liniengrafik.


    Ohne geschicktes Umpositionieren des BasicRAMs, des Zeichensatzes und der Bitmap werde ich diese Array-Fehler nicht wegkriegen. Das liegt imho nicht an den Befehlen selbst.


    Die komplette Animation etc. zeige ich alles irgendwann später wenn es eines Tages in ASM umgesetzt ist.


    Edit:
    Damit das Einlesen klappt muss man voranstellen:


    10 dim co(1,14,120)

  • Ich glaube, der C64 kriegt einfach nur einen Daten-Koller weil ich mit wüsten Fließkomma-Arrays wahrscheinlich Betriebssystem-Teile beeinflusse/überschreibe.

    So kaputt ist Basic dann doch nicht. Solange Du nicht per POKE an den Interpreter-Zeigern herumfummelst, werden Dir weder Fließkomma-Werte noch Arrays etwas kaputtmachen.

    Ich hatte auch schon mit Integer-Typen experimientiert, aber da klappt es dann gar nicht.

    Das muss gehen (tm). Beschreib mal den/die Fehler. Integer-Typen funktionieren nicht als Schleifenzähler, aber einfach co() durch co%() austauschen klappt. Gerade getestet:

    Änderungen:
    - Schreibfunktion hinzugefügt, um Ein- und Ausgabe vergleichen zu können.
    - Variablenzuweisung bei INPUT vereinfacht.
    - Auf Integer-Array geändert.
    Nach jedem der drei Schritte waren Ein- und Ausgabedatei identisch.

    Ohne geschicktes Umpositionieren des BasicRAMs, des Zeichensatzes und der Bitmap werde ich diese Array-Fehler nicht wegkriegen.

    ?!


    EDIT: Erste Arraydimension korrigiert.

  • @ MacBacon


    Danke!


    Ich glaube mein Problem liegt eher hier:


    Zitat von MacBacon

    Integer-Typen funktionieren nicht als Schleifenzähler, aber einfach co() durch co%() austauschen klappt.


    Wenn ich sage "abs(co% Wert 1 - co% Wert 2) = Schleifenzähler z" dann kriege ich wohl ein Problem, auch wenn z nicht als z% definiert wird. z ist aber ein Rechenergebnis aus der Differenz zweier co%-Werte.


    z ist bei mir der Zähler der schnellen Richtung zum Linenziehen durch Setzen einzelner Punkte.


    Was ist der Unterschied zwischen open 2,8,4, und open 1,8,2? Wann macht man da ein w,s,r usw. dahinter?


    C64 Wiki erklärt das nicht genau und ich wandle deren Beispiele meistens so lange ab bis sie klappen. Verstehen tu ich es dadurch aber nicht vollständig.

  • Wenn ich sage "abs(co% Wert 1 - co% Wert 2) = Schleifenzähler z" dann kriege ich wohl ein Problem, auch wenn z nicht als z% definiert wird. z ist aber ein Rechenergebnis aus der Differenz zweier co%-Werte.

    Woher der Wert für z kommt, ist egal, z ist und bleibt trotzdem ein Float.

    Was ist der Unterschied zwischen open 2,8,4, und open 1,8,2? Wann macht man da ein w,s,r usw. dahinter?

    Die erste Zahl ist Deine logische Dateinummer, damit referenzierst Du diesen Datenkanal bei allen späteren PRINT#, INPUT# und GET# (und am Ende CLOSE). Ob Du da 1 oder 2 oder 5 nimmst, ist egal. Bei mehreren gleichzeitig geöffneten Kanälen müssen die Zahlen natürlich eindeutig sein, genau zum Auseinanderhalten der Kanäle sind sie ja da.
    (Ist in der Zahl Bit7 gesetzt, macht Basic noch irgend nen Sonderscheiß, bitte selbst im Wiki nachlesen und sofort wieder vergessen)


    Die zweite Zahl ist die Geräteadresse (dies nur der Vollständigkeit halber).


    Die dritte Zahl ("Sekundäradresse") ist geräteabhängig: Bei CBM-Druckern kann man damit z.B. den Zeichensatz auswählen, bei Diskettenlaufwerken ist Sekundäradresse 15 der Befehlskanal. Weiterhin gilt dies hier. Für eigene Dateien kann man also 0 (nur zum Lesen), 1 (nur zum Schreiben) und 2 bis 14 (beliebig) nutzen. Bei gleichzeitig geöffneten Dateien auf dem selben Gerät müssen die Nummern aber wiederum eindeutig sein, denn das Laufwerk unterscheidet die Dateien anhand dieser Nummer - von Deiner logischen Dateinummer in Basic bekommt das Laufwerk nichts mit.

  • Für eigene Dateien kann man also 0 (nur zum Lesen), 1 (nur zum Schreiben) und 2 bis 14 (beliebig) nutzen.

    Ähm- nein. Es ändert sich nur die Vorgabe für Dateityp und Zugriff. Sek-Adr. 0 ist 'Proggramm lesen', 1 ist 'Programm schreiben', 2 bis 14 ist 'sequenziell lesen'. 'sequenziell' nennt CBM-DOS seine normalen Daten-Dateien. Es ist aber kein Problem, eine Datei mit OPEN 1,8,ß,"name,s,w" zu öffnen- dabei ist das angehängte ',s' die Angabe für eine sequenzielle Datei (es geht auch p für ein BASIC-Programm und noch ein paar andere) und ',w' die Angabe 'write', also eine neue Datei zum Beschreiben öffnen. Da geht auch noch ',r' zum Lesen, ',a' zum Anhängen von Daten an eine bestehende Datei, und noch eins für die Behandlung 'kaputter' Dateien.


    Ob man jetzt seine Daten in 'prg'-Dateien speichert und seine Programme als 'seq' ist den System egal, man muß es dann nur jedesmal explizit angeben.


    Und man kann eine einmal geschriebene Datei nur lesen oder etwas anfügen- wahlfrei darin herumändern ist nicht möglich.


    Aber...


    ...wo liegt denn die Hires-Grafik? Gibt es eine Initialisierung des BASIC-Endes? An der Integer-Float-Wandlung kann es jedenfalls kaum liegen, die ist normalerweise völlig transoparent, und Rundungsfehler hier nicht zu erwarten. Aufpassen muß man nur bei ABS und INT mit negativen Zahlen.

  • Ich hatte auch schon mit Integer-Typen experimientiert, aber da klappt es dann gar nicht. Dabei ist Integer mit 2 Byte doch viel kürzer als der C64 Standard Float mit 6 Bytes (es sind doch 6 beim C64?). Ich arbeite nämlich nur mit Ganzzahlen, da ist kein einziges Komma dabei.

    Commodore-Basic kennt keinen Integer-Typ. Da kannst soviele Prozentzeichen dahinter schreiben, wie du willst. Der Interpreter rechnet und speichert immer im Float-Format.
    Einzige Ausnahme waren glaube ich die Array-Indizes. Aber das ist schon so lange her.

  • Ähm- nein. Es ändert sich nur die Vorgabe für Dateityp und Zugriff.

    Na, dann versuch mal mit Sekundäradresse Null eine Datei zum Schreiben zu öffnen. Da kannst Du ein ",w" an den Namen hängen so oft Du willst, das Laufwerk wird "file not found" melden (weil es einen Lesezugriff versucht).
    Bei dem Rest stimme ich Dir zu, mehr oder weniger genau das schrob ich ja auch in dem oben verlinkten anderen Beitrag,

    Commodore-Basic kennt keinen Integer-Typ. Da kannst soviele Prozentzeichen dahinter schreiben, wie du willst. Der Interpreter rechnet und speichert immer im Float-Format.
    Einzige Ausnahme waren glaube ich die Array-Indizes. Aber das ist schon so lange her.

    Der Interpreter rechnet immer im Float-Format, korrekt. Ansonsten gilt aber:
    - Float-Variable: fünf Byte pro Wert
    - Float-Array: fünf Byte pro Wert
    - Integer-Variable: zwei Byte pro Wert, und weitere drei Byte ungenutzt (keine Ersparnis)
    - Integer-Array: zwei Byte pro Wert (hier wird wirklich gespart)

  • Ich glaube, der C64 kriegt einfach nur einen Daten-Koller weil ich mit wüsten Fließkomma-Arrays wahrscheinlich Betriebssystem-Teile beeinflusse/überschreibe. Das sehe ich an korrupten Bits in der Bitmap während des Einlesens. Da ist der Grafik-Modus nämlich schon an. Ich habe die normale Ausgangssituation mit $801 und keine platzoptimierte Positionierung von BasicRAM, Bitmap, etc.

    ...und plötzlich ergibt alles einen Sinn. :D
    Die "korrupten Bits in der Bitmap" sind schlicht und einfach der Inhalt des Arrays, denn die Bitmap wurde mitten in den Basic-Speicher gelegt (8192).