Posts by JeeK

    Naja, man kann schlecht beurteilen, was er vorher schon probiert hat. Er hat ja angeblich vorher schon probiert.

    Ja eh, da ist natürlich viel Mutmaßung meinerseits dabei. Ich stelle es einfach nur in den Raum, weil ja nicht genau bekannt ist, was hinter den Kulissen so probiert wurde. Nur überzeugend wurde es im Beitrag selbst halt nicht dargestellt.

    Auch wenn er ein Fan aus der damaligen Zeit war und so einige dazu wusste, die TV-Bedienung muss einem ja nach all den Jahren nicht unbedingt geläufig sein. Ob auch ein TV mit automatischen Suchlauf probiert wurde, ist natürlich auch nicht gesichert. Aber im Zweifel natürlich immer für den Angeklagten. ;)

    Genau das meine ich. Im ersten Moment dachte ich auch, dass der Kanal nicht stimmt. Man konnte ihn ja auch verstellen. Aber er war wohl schon auf dem richtigen Kanal.

    Vielleicht, den UHF-Selektor unten hätte ich geschätzt jetzt nicht so ganz bei Kanal 36 gesehen (bei 23:35), eher näher bei 30 als bei 40, aber das war bei solchen TV-Geräten ja nicht so exakt. Außerdem bin ich mir nicht sicher, ob der TV überhaupt auf UHF eingestellt ist. Der VHF-Selektor ist auf 10 gestellt und hätte vermutlich auf eine gesonderte UHF-Stellung gedreht gehört (vor VHF-Kanal 12 vermutlich), damit man dann die UHF-Frequenzen wählen kann. Nur, dass dann überhaupt kein Bild kommt und dann live gar nicht sucht, bzw. nur ein Zucken am TV zu sehen ist, scheint lediglich ein Indiz zu sein, dass am Antennenkabel "etwas" kommt. Das Ganze, zumindest so wie es gebracht wurde, spricht nicht sehr für die Fehlersuchfähigkeiten des Kollegen ...

    Das heißt für mich, dass man die Fehlerbehandlung so oder so in das BASIC-Programm auslagern muss, denn die Routine soll ja wirklich nur INPUT# ersetzen. Ich habe das jetzt mal so umgesetzt:

    INPUT# ist in dem Fall kein Maßstab. Wenn man schon eine eigene Routine macht, dann sollte es dort richtig sein, egal wie es andere machen. ;)
    Wie gesagt, die Fehlerbehandlung (ich meine die Kontrolle von ST bzw. $90) soll nur verhindern, dass das Ergebnis nicht unnötige Zeichen enthält und überhaupt zu Ende kommt, auch wenn kein CR vorkommt.
    Wenn das Ergebnis des Einlesens CHR$(255) ist, zeigt das einen leeren Record an. Wenn sonst ein Datensatz gelesen wurde, sollte dennoch ST überprüft werden. Wenn dort ein Wert <> 64 aufweist, dann gab es einen Fehler.

    Anbei das angepasste Demo-Programm (mit BASIC-Loader) auf d64 und der Sourcecode.

    Feedback und sachdienliche Hinweise wie immer willkommen.

    Super, danke für die Mühe!


    Anmerkung: Ein bisschen geht mir die Fehlerbehandlung ab. Wenn ein Record nicht mit einem CR abgeschlossen wird, liefert das letzte Zeichen einen Status ($90) $40 (EOF), alle weiteren Leseversuche liefern $FF und Status $40.

    Ein unbelegter Record liefert beim ersten Zeichen 255 und Status $40.

    (aus meinen Experimenten für die Aufarbeitung fürs Wiki - noch nicht dort erwähnt - ob es eine andere Quelle gibt weiß ich nicht, aber ich kann gerne entsprechende nähere Informationen dazu zur Verfügung stellen auf Anfrage).


    Vielleicht sollte man nur einlesen und das Zeichen übernehmen, solange der Status 0 ist, bis der Status Bit $40 gesetzt hat (dann das Zeichen auch übernehmen).

    Das ergibt bei einem unbelegten Record dann einen String mit Länge 1 dem $FF-Byte. Das ist nicht schlecht, es zeigt einen unbelegten Record.

    Also, wenn ich es richtig sehe, werden einfach bis zur nächsten Blockgrenze leere Datensätze (mit führenden $ff) angelegt? :gruebel

    Kein Grübeln notwendig. Schon probiert. Es wird immer der Datenblock mit Records bis zum Ende gefüllt. Leicht auszuprobieren, nach dem Anlegen mit Schreiben des letzten Wunschdatensatzes, kann man dann die folgenden positionieren und bekommt, je noch Layout weitere Records, ohne dass der Status Error 50 liefert.


    Nur so paar Minianmerkungen, die auch das 1541-Handbuch noch angebrachter sind und dort sogar genau genommen fehlerhafte Programme führen können.

    880 print#15,"p"chr$(2)chr$(lb)chr$(hb)chr$(1)

    Hier sollte man korrekterweise mit ";" abschließen (es wird ein überflüssige - in diesem Fall ohne Schaden anzurichten - Return-Zeichen gesendet).

    hb=int(nr/256):lb=nrand255

    Das int() kann man sich sparen, da hb, wenn ausschließlich in chr$() verwendet, automatisch eine Konvertierung in einen Integer vornimmt. ;)

    Nein, da ist der Fehler korrigiert (steht alles in dem verlinkten Artikel).

    Also ich kenn an sich den Transactor-Artikel, ab das hat ja nichts mit dem RECORD-Befehl zu tun. Der Artikel ist von 1986 und bezieht sich primär auf die 1541. Der läuft je nach angehängtem Laufwerk natürlich auch in den Bug hinein, da ja hier der Workaround nie implementiert wurde. Bestenfalls funktioniert RECORD mit neueren Laufwerken, wo der Bug behoben ist.

    JeeK https://archive.org/details/tr…-v7-i04/page/n76/mode/1up (auch im C64-Wiki verlinkt übrigens...)


    Der Fehler dürfte wenn ich das richtig sehe nicht auftreten, falls die Datensatzlänge 254 ohne Rest teilt (also, naja, Datensatzlänge 2, 127 oder 254 :) ); man nur einzelne Datensätze schreibt und die Datei dann wieder schließt; man das doppelte Positionieren inkl. Warten macht; oder den Workaround aus dem Artikel oben benutzt (Listing Zeilen 1360-1470).

    Lustig, den Fehler und die Referenz hab ich ja selbst dort eingefügt ... tja, wieder komplett verdrängt. Das Alter macht sich echt ungut bemerkbar ... X/

    Das zeichnet ja die REL-Datei aus, dass die Datensätze gleich lang sind. Wenn man als DS-Länge 2 Byte hat, bekommt man die 65535 Datensätze sozusagen voll, mehr geht ja nicht. Dazu hatte ich irgendwo mal eine Berechnung gelesen (auch im Vergleich mit der 1581), wie lange die DS sein dürfen bei 65535 DS.

    Damit gehen sich natürlich auch mit Recordsize 1 65535 Datensätze aus.


    Die Datenblöcke und und Sidesector-Blöcke (bei DOS 2.6) berechnen man mit (pro Datenblock kann 254 Bytes für Recorddaten aufnehmen, jeder Site-Sector-Block kann 120 Block-Referenzen aufnehmen)

    Code
    1. RS=2
    2. N=65535
    3. DB=INT((RS*N-1)/254)+1
    4. SB=INT((DB-1)/120)+1

    Ab Recordsize 3 überschreiten DB+SB die Kapazität von 664 Blöcken und/oder SB die maximale Side-Sector-Anzahl von 6.

    Und dann ist die Datei wieder kaputt - der Bug ist ziemlich zuverlässig reproduzierbar wenn man ungünstige Bedingungen erwischt hat. Den Positionierbefehl zweimal senden umgeht den Bug zuverlässig und kostet kaum Zeit.

    Wie ist dieser reproduzierbar? Gibt es eine Quelle? Bezieht sich das nur auf die in 1570/71-Laufwerken aktiver CBM-DOS-Version?

    Im Handbuch zur Floppy 1571 steht, dass der Positionierungsbefehl vorsichtshalber doppelt abgeschickt werden sollte. Außerdem sollte auf die Kanalnummer (die direkt nach dem P folgt) mit 96 aufaddiert werden (das DOS macht das intern selber auch so). Und die verunstaltete Meldung „mismatch“ deutet darauf hin, dass irgendwo in der Floppy eine falsche Zuordnung eingetreten sein muss.


    Ach ja, wenn du die REL-Datei anlegst, müssen als erstes alle Records auch angelegt werden (also irgendwas in jeden Record reinschreiben, z.B. CHR$(255), dabei die Positionierung nicht vergessen).


    Arndt

    Besser wäre es, denn wenn nämlich ein Record, der noch nicht angelegt ist, erzeugt einen Fehler "50, RECORD NOT PRESENT". Ich glaub da würde das DOS die LED auch blinken lassen. Aber das Schreiben des Blocks müsste dennoch funktionieren.


    Der Hinweis im Handbuch mit dem Doppel-schicken klingt wild. Hat das DOS der 1571 tatsächlich einen Bug? Also die Implementierung von RECORD in BASIC 7.0 wird das jedenfalls nicht doppelt gesendet, soweit ich mich erinnere. Ich glaub fast, Commodore unterstellt dem Programmierer irgendwie das DOS derartig im Fehlerkanal zu verwirren, dass man das doppelte Senden empfiehlt.


    Bezüglich Positionierung, könnte man effizienter machen, unter der Annahme, dass es nicht mehr als 32767 Records gibt. Funktion CHR$() macht implizit bereits ein INT().
    Weiters sollte man nicht ein CHR$(13) nachsenden und das PRINT mit einem Semikolon beenden. In dem Fall passiert nicht viel, weil das Positionierungsbyte im Record (CHR$(1)) mitgeschickt wird - sollte es ab fehlen, was Position 1 entspricht - würde das implizite CHR$(13) die Position 13 setzen wollen und man wundert sich, warum man mitten im Record ist ...)



    410 : print#2,"p"+chr$(2)+chr$(nrand255)+chr$(nr/256)+chr$(1);


    Wenn man Record-Nummer > 32767 berücksichtigt haben möchte, geht auch


    print#15,"p"chr$(2)chr$(255andr+65536*(r>32767))chr$(r/256);


    Da die Floppy-Übertragung relativ gemächlich ist, kann man hier auf eine Optimierung durch das Verlagern der Konstanten in Variablen verzichten. Wenn man's aber hat, schadet's der Laufzeit jedenfalls nicht.

    hmm beim Compilen mit Blitz oder reblitz64 (Danke an dieser Stelle an 1570 für das genialen reblitz64) war die Dateigröße immer etwas kleiner als das Original Basic Programm. Oder ändert sich dabei auch der Stringspeicher obwohl der Code kleiner ist?

    Das hab ich ja nicht ausgeschlossen. Ich schrieb, ja mit den damals mir zur Verfügung stehenden Compilern. Und die Größe war nur ein Aspekt.

    Ähnein. Speziell in BASIC V2 kann man eigentlich gar nicht effizient programmieren, weil die ganzen Datenstrukturen dafür fehlen und die Workarounds prinzipbedingt langsam sind. Z.B. bräuchte man eigentlich verkettete Listen, damit man eben schnell Zeugs in eine Liste stecken und wieder draus löschen kann. Gibt's in BASIC V2 nicht, wird also meistens mit Arrays nachgebildet, in denen dann zum Löschen von Elementen alle anderen verschoben werden (brrr), und dynamisch ist da schonmal gar nichts, also macht man das Array von Anfang an auf maximale Größe => Speicherverschwendung.

    Oder Sets, gibt's auch nicht. Werden in BASIC V2 typischerweise nachgebildet wieder mit Arrays und linearer Suche drin. Brrrr.

    Effizient im Rahmen der Möglichkeiten kann man immer programmieren. Die Dinge, die sich strukturell nicht schnell genug machen lassen, kann man dann mit entsprechenden fertigen oder eigenen BASIC-Erweiterungen bzw. MC-Call-Outs abdecken.
    Bei meinen größeren Projekten, war dann etwa das Sortieren von String-Arrrays, Einlesen des Directorys, stabile Input-Routine, schnelle Garbage-Collection, Listen-Eiditor/Scroller "ausgelagert". Für mich war der Schritt über einen BASIC-Compiler immer ein viel zu langer Zyklus während der Entwicklung und eigentlich nie eine Option. Vor Auslieferung einer Release hat dann ein Renumber und Kompaktieren des Codes (das ging "in-place") dann auch noch ein bisschen Einsparung hinsichtlich Codesize und Laufzeit oben drauf gegeben.
    Die Verwendung eines Compilers habe ich zu dem auch gescheut, da der Code (meiner Erinnerung nach bzw. bei den mir zur Verfügung stehenden Compilern) des Compilats umfangreicher wurde und mir dadurch wertvoller String-Speicher verloren gegangen wäre (den ich jedenfalls für ein bisschen schnellere Abarbeitung nicht eintauschen wollte).

    Oft hab ich in 64er Ausgaben gelesen "Und hier wird der BASIC-Anfang raufgesetzt und ein paar Seiten weiter wurde bei einem anderen Programm das BASIC-Ende runtergesetzt"

    Und in manchen Büchern kommt das auch oft vor, z.B. wenn mit selbstdefinierten Zeichen gearbeitet wird.

    Ich schätze, das hängt damit zusammen, dass der VIC-Chip nur ein 16 KByte-Bank adressiert und wenn man in Bank 0 (0 bis $3FFF) bleiben möchte, dann gerne den BASIC-Anfang nach oben schiebt, um das BASIC-Programm aus dem Weg zu haben. Dann kann man HiRes-Grafik oder Zeichensatz in da platzieren. Gut, nur für HiRes ist mir Bank 3 ohnehin lieber (auch wenn man da mit ROM-Wegblenden arbeiten muss, was unter Plain-BASIC halt nicht so prickelnd ist).

    JeeK ja, das trifft es ziemlich genau.
    vielen dank!

    Ich hab halt leider - was sonst nicht meine Art ist - diesmal nicht überprüft, ob das so tatsächlich funktioniert und durchgetestet. Man möge mir bitte verzeihen. Den Rest überlass ich sozusagen dem geneigten Leser als "Übung". Gegebenenfalls kann man ja dann ein etwaiges Problem oder die Weiterentwicklung hier aufgreifen und gemeinschaftlich lösen. ;)

    Ok, das sind die 38911 Bytes, die man bei der Einschaltmeldung angezeigt bekommt.

    Angenommen, ich will jetzt den BASIC-Anfang um 5000 Bytes nach oben, also auf die Adresse 7049, setzen.

    Ja, dass schaut soweit gut aus. Beim BASIC-Anfang muss man auch noch darauf achten, dass dann die Speicherstelle 7048 (1 vor dem BASIC-Anfang) Null enthält (POKE7048,0), sonst scheitert ein RUN mit SYNTAX ERROR.

    Die Superkraft des 6502-Stacks ist, dass man in gerade 3 Zyklen Werte raufschieben kann (günstig wie Zeropage-Zugriff) und dank Auto-Dekrement die Indexregister frei bleiben.

    Aber dafür 4 Takte für runterziehen braucht, was ein Takt mehr ist als ein ZP-Restore. Das PLA setzt aber nebenbei auch gleich die Flags N, Z, was viele andere CPUs (vorwiegend aus dem Zilog- und Intel-Lager) bei Stack-Operationen nicht machen und eventuell einen gesonderte Test-Instruktion notwendig macht (sofern halt dann notwendig).

    Es wäre das Auswerten eines Basic-Parameters.

    Ok, hab ich mir ja so gedacht.


    Aber wie weiter oben schon angemerkt, ist der Wertebereich von Signed Byte ohnehin zu klein.

    Hab ja in Posting #8 die 16-Bit Signed-Variante angedeutet.

    Müsste dann für eine Parameterauswertung in etwa so aussehen. Werte von -160 bis 160 sind gültig, andere liefern einen Illegal Quantity Error.

    Wenn der Wert negativ ist, wird er negiert und in einen positiven Wert Wert umgewandelt. Man hat dann den Absolutwert. Dann braucht man nur mit 161 vergleichen (< ist dann ok).

    Ist nicht das, was eigentlich gesucht war?