Hallo Besucher, der Thread wurde 78k mal aufgerufen und enthält 397 Antworten

letzter Beitrag von Boulderdash64 am

BASIC 4.5 für den C64 (BASIC 3.5 + EIGENE BEFEHLE)

  • RECORD ist nicht wirklich aufwendig.

    Wenn, dann sollte aber der BASIC-4.0-Level komplett abdecken und auch das fehlende APPEND, CONCAT, DCLOSE. Da ja schon andere Diskbefehle wie COPY, DOPEN usw. vorhanden sind, sollte ja der recht aufwendige Parameterparser für diese Kommandos vorhanden sein (der zumindest in BASIC 4, 3.5 und 7.0 generisch ist und für alle Disk-Kommandos verwendet wird), was die Umsetzung verhältnismäßig billig machen sollte.

  • Guten Morgen zusammen. Ich werde den Vorschlag mal aufgreifen und sehen wie ich diesen einarbeiten kann.

    Ich selber habe schon mit dem Gedanken gespielt zumindest rudimentäre Datenbank ähnliche Befehle zu

    implementieren.

    Allerdings bitte ich um viiiieeeel Geduld. Ich bin zur Zeit trotz COVID-19 Einschränkungen und Adventszeit
    beruflich sehr eingespannt. Seit einigen Monaten bleibt mir nicht viel Freizeit um mich weiter so intensiv dem

    BASIC 4.5 zu widmen. Es ist vielleicht auch an die zeitlichen Äbstände meiner Postings zu erkennen. ABER:

    die Erweiterung für den C64 wird von mir weiter gepflegt. Wie bereits vor Monaten mal erwähnt wird dieses

    BASIC wohl nie wirklich fertig. Solange die Retroszene wie in diesen erstklassigem Forum weiter

    so aktiv lebt, werde ich am Ball bleiben. Vielen Dank an alle die mich dabei unterstützen.

  • [..] ABER:

    die Erweiterung für den C64 wird von mir weiter gepflegt. Wie bereits vor Monaten mal erwähnt wird dieses

    BASIC wohl nie wirklich fertig. Solange die Retroszene wie in diesen erstklassigem Forum weiter

    so aktiv lebt, werde ich am Ball bleiben. Vielen Dank an alle die mich dabei unterstützen.

    Den jetzigen Modus finde ich prima, du hältst alles zusammen, machst den "Build" und die Core-Entwicklung und wir anderen liefern Vorschläge oder sogar auch Implementierungshinweise bzw. Code-Schnippsel. Wir richten uns da natürlich nach Dir und die Geduld wird sicherlich jeder aufbringen. :)

  • Hi dg5kr


    Wollte mal was mit deinen Basicerweiterung testen für eine Basic Game. Bin aber jetzt schon am verzweifeln, weil das kurze Programm nicht das macht was es soll.

    Hier mal der Code

    Statt das er A$ immer neben dran setzt, geht er in y-Richtung nach oben und der X-Wert wirt auch nicht richtig addiert. Woran kann das liegen.

    Ach ja was mir noch aufgefallen ist. Mit dem Befehl Char kann ich folgenden Anweisung nicht ausführen Char 1,10,10,"test";y ich muss es sondern so schreiben - Char 1,10,10,"test":print y. Aber das nur neben bei.

    Also ich weis nicht warum er das falsch zusammenzählt. Fällt dir dazu was ein.


    Gruß Drachen

  • Statt das er A$ immer neben dran setzt, geht er in y-Richtung nach oben und der X-Wert wirt auch nicht richtig addiert. Woran kann das liegen.

    Das liegt daran, dass du y bis Zeile 24 zulässt. Wenn dann in Zeile 24 ein PRINT gemacht wird, dann schließt das mit einem Return-Code ab, der veranlasst, dass der Bildschirm eine Zeile nach oben geschoben wird, da er nicht in Zeile 25 positionieren kann.


    Wenn du in Zeile 60 "y < 23" schreibst, geht es wie geplant:



  • Alles klar Danke Snoopy. Aber ich habe noch mehr Fehler in mein Listing entdeckt. Der größe war das A$. Durch den Getkey A$-Behlehl habe ich immer meinen String geleert :schande:.

    Wenn ich folgende Zeilen so ändere klappt alles wie geplant

    Code
    1. 15 B$="AAAA"
    2. .
    3. 60 IF Y<24 THEN Y=Y+1 :ELSE GOTO 100
    4. .
    5. 80 AT x,y:PRINT B$;
    6. .
    7. 110 X=X+LEN(B$)
    8. .
    9. .

    Jetzt kann ich weider planen. Aber das mit dem Befehl CHAR bleibt trotzdem. Vielleicht kann man das noch verbessern.

    Gruß Drachen

  • Das mit dem Befehl Char hat sich erledig. Habe mir den Befehl jetzt genau angeschaut bei Plus 4 dort wurde der Befehl genau erklärt. Also hat sich das von selbst erledigt.

    Gruß Drachen

  • Das mit dem Befehl Char hat sich erledig. Habe mir den Befehl jetzt genau angeschaut bei Plus 4 dort wurde der Befehl genau erklärt. Also hat sich das von selbst erledigt.

    Gruß Drachen

    Übrigends, der Grund für den AT Befehl war, das der CHAR Befehl mit dem Fenster Modus nicht zurecht kommt. Basic 3.5 kennt zwar keinen WINDOW Befehl, kann aber trotzdem ein "Fenster" erzeugen. Der CHAR Befehl ignoriert aber solche Fenster. AT tut das nicht.

  • Auf Anfrage von Drachen möchte ich hier eine Liste der Token, die als Erweiterung zu BASIC 3.5 hinzugekommen sind.

    Hinweis: (Fast) alle Befehle aus BASIC 2.0 und BASIC 3.5 haben auch dessen Token. Mit folgenden Ausnahmen:

    STOP (Wurde erweitert zu STOP [ON|OFF]

    RESTORE (Wurde erweitert zu RESTORE [ON|OFF]


  • Guten Abend zusammen.

    In Kommunikation mit dem User Drachen ist mit beim BASIC 4.5 noch ein Bug aufgefallen: Der Befehl CATALOG zeigt zwar bei der Floppy Nummer 10 und 11 den richtigen Catalog an, aber die Unitnummer (U8,U9 etc) wird mit einem U:: angezeigt. Den Fehler habe ich gefunden. Weiter gehe ich noch einem Hinweis von Drachen nach bei dem das alternative Kommentarzeichen ' ein Syntax Error ausgibt.

    Die Anregung Datenbank ähnliche Befehle zu integrieren steht noch aus. Es ist allerding zu überlegen in wie weit das verbleibende RAM zu Nutzen Verhältnis Sinn macht. Mal schauen was da raus kommt. Eine Idee mit nach ladbaren Modulen schwebt mir da auch im Kopf. Bei Floppy Laufwerken mit Speedern könnte man zum Beispiel einige Befehle erst laden, ausführen. Der nächste Ladebefehl überschreibt dann den vorherigen. Das sind aber nur Gedanken.

    Da ich den Sourcecode wieder anpacke sind gleich zwei Erweiterungen dazu gekommen:

    BEEP -> Wie der Name noch sagt, macht einen kurzen BEEP (In Gedenken an den Apple II)

    DELAY N -> Eine Verzögerung von 1/50*N Sekunden bei PAL oder 1/60*N bei NTSC.

    Auf meiner unmittelbaren Todo Liste steht eine weitere versteckte Funktion:

    Ein RTC. Ich möchte mit dem RTC DS12C887 die interne Variable TI$ ausfüllen. Dazu werde ich aber eine eigenen Thread in diesem Thema aufmachen, sonst wird es zu lang hier.

    Die neue Version wird wohl in den nächsten Tagen hier von mir hochgeladen.

    Drachen: Die aktualisierte Token List wird dann bei liegen.

  • RTC soll TI$ syncronisieren


    Hallo zusammen,

    mein BASIC 4.5 soll die RTC DS12887C unterstützen.

    Warum ausgerechnet dieser Baustein? Weil er in VICE "verbaut" ist.


    Die notwendigen Infos zu diesem Baustein sind hier zu finden:

    https://github.com/ytmytm/c64-ds12c887


    Den Baustein abzufragen und die Uhrzeit im BCD Format zu speichern

    ist reine Fingerübung. Aber dann fehlen mir doch ein paar Infos.

    In dieversen ROM Listings (meine Hauptquelle ist https://www.pagetable.com/c64ref/c64disasm/)

    habe ich gefunden, das die Uhrzeit in der Zeropage $A0 (Hour), $A1 (Minutes), $A2 (Seconds)

    gespeichert wird und permanent aktualisiert wird.

    Wo ich unsicher bin: Die Interrupt Service Routine geht via IRQ. Richtig?

    $FFDB setzt die Zeit und $FFDE holt die Zeit.


    $FFDB (Zeit setzen) ist ein JMP auf $F6E4.

    (C:$cacc) d f6e4

    .C:f6e4 78 SEI

    .C:f6e5 85 A2 STA $A2

    .C:f6e7 86 A1 STX $A1

    .C:f6e9 84 A0 STY $A0

    .C:f6eb 58 CLI

    .C:f6ec 60 RTS


    Dort werden dann die Speicher Zellen $A0-$A2 aus den Register Werten A,X,Y gefüllt.

    Aber wo zum Teufel werden die Register mit Werten befüllt und wie kann ich das stoppe

    um meine eigene Werte dort zu schreiben?


    Der IRQ Einsprung ist bei $FF48:

    (C:$f70f) d ff48

    .C:ff48 48 PHA

    .C:ff49 8A TXA

    .C:ff4a 48 PHA

    .C:ff4b 98 TYA

    .C:ff4c 48 PHA

    .C:ff4d BA TSX

    .C:ff4e BD 04 01 LDA $0104,X

    .C:ff51 29 10 AND #$10

    .C:ff53 F0 03 BEQ $FF58

    .C:ff55 6C 16 03 JMP ($0316)

    .C:ff58 6C 14 03 JMP ($0314) --> Das könnte mein Hook sein....

    .C:ff5b 20 18 E5 JSR $E518

    .C:ff5e AD 12 D0 LDA $D012


    Der Sprungvektor $0314 mit der Standard Adresse $EA31 könnte zu dem Bereich führen, wo die TI$ immer ne gesetzt wird.

    Aber auch das könnte hilfreich sein:

    ;$A9E0 Assign value to TI$, set Time of Day; read value from string pointed by memory addresses $0064-$0065.

    ;$AF48 Compute value of TI$.


    Aber wo? Ich komme nicht weiter.

    Ich benötige Antworten auf:

    - Wo wird TI$ durch den Interrupt aktualisiert?

    - Wo werden jeweils die Register mit den BCD Werten gefüllt um Sie per interrupt nach $A0-$A2 zu schreiben?

    - Kann ich diese Aktualisierung stoppen, bzw auf meine Aktualisierung verbiegen?

    - Habe ich einen vollkommene Denkfehler?


    Danke für jeden Hinweis.

  • Hi dg5kr


    Super, dann freue ich mich schon im Voraus darauf.

    Machst einen guten Job mit deiner Erweiterung :thumbsup:

    Oh, vielen Dank.

    Ich sitze gerade an dem TI$ Problem. Und ich denke ich habe tatsächlich einen Denkfehler. Ich muss die Uhrzeit ja gar nicht ständig über den IRQ setzen. Es reicht einmal im Startprozess. Den Rest kann ich weiter den Kernel Routinen überlassen.

    So ermutigt weiter zu grübelen bin ich auf das Ergebnis gespannt.

    Zur REM Alternative ' (Apostrophe):

    Hmm, funktioniert.

    Könntest du mir ein Beispiel oder einen Screenshot zukommen lassen damit ich das reproduzieren kann?

    Im Übrigen ist der REM Ersatz noch ein klein wenig Buggy: Wenn du ein ? rein bringt macht der einen PRINT daraus. Wo bei der original REM Befehl auch nicht ohne Bugs ist.....:D

  • Und ich denke ich habe tatsächlich einen Denkfehler. Ich muss die Uhrzeit ja gar nicht ständig über den IRQ setzen. Es reicht einmal im Startprozess. Den Rest kann ich weiter den Kernel Routinen überlassen.

    :ilikeit::dafuer:So brickst Du schon mal keine Programme, die TI$ setzen. Um was auch immer damit zu machen.

  • Könntest du mir ein Beispiel oder einen Screenshot zukommen lassen damit ich das reproduzieren kann?

    Im Übrigen ist der REM Ersatz noch ein klein wenig Buggy: Wenn du ein ? rein bringt macht der einen PRINT daraus. Wo bei der original REM Befehl auch nicht ohne Bugs ist.....

    Das ist ja nicht das Problem des Befehls an sich, sondern des Tokenizers und De-Tokenizers. Der hört ja nicht auf, bloß weil er ein REM oder ein "'" sieht.

    Gibt man ein REM {shift}+{e} -> ist das das Token für VAL, was bei einem LIST dann auch angezeigt wird.

    REM selbst funktioniert aber (ignoriert dann alles bis zum Zeilenende).

  • Ich benötige Antworten auf:

    - Wo wird TI$ durch den Interrupt aktualisiert?

    - Wo werden jeweils die Register mit den BCD Werten gefüllt um Sie per interrupt nach $A0-$A2 zu schreiben?

    - Kann ich diese Aktualisierung stoppen, bzw auf meine Aktualisierung verbiegen?

    - Habe ich einen vollkommene Denkfehler?

    TI$ wird nicht aktualisiert, sondern der String wird bei Abfrage aus den Speicherstellen $A0 bis $A2 "errechnet", also in die entsprechende Darstellung umgewandelt. In der Routine für die Ausdrucksauswertung, werden die Systemvariablen abgefragt und dann zu der Routine verzweigt, die das macht.


    Welche Register mit BCD-Werten? Die gibt es so nicht. $A0-$A2 ist ein einfacher 3-Byte-Zähler, der 1/60-Sekundenintervalle zählt.

    D.h. IRQ -> wenn von Timer -> Inkrement. (JSR $FFEA bei $EA31).

    Das war's schon.

    TI liest den Wert direkt aus, TI$ macht daraus einen String (bei TI$ ist auch noch eine Zuweisung möglich, wo dann aus dem String der Wert für $A0-$A2 zurück gerechnet wird).


    Die Aktualisierung stoppen geht nur, wenn du die IRQ-Routing komplett ersetzt, wo dann das Inkrement nicht mehr vorkommt (oder zumindest bis zu der stelle). Das ginge aber leicht, da das ja faktisch der erste JSR-Aufruf beim Eintritt bei $EA31 ist. Dann stellt man den Vektor auf $EA34. Dann gibt's kein Inkrement mehr.

    Man muss dann nur noch die Zugriffe auf TI und TI$ "abfangen", die dann den Wert vom RTC-Baustein nehmen.

    Wichtig ist, dass dann TI auf jeden Fall immer 1/60 Sekunden zurückliefern muss (um die Kompatibilität zu wahren). Wenn der RTC keine solche feine Auflösung hat. D.h. angenommen der RTC liefert Sekundenauflösung, dann muss man die Sekunden aus Stunden, Minuten und Sekunden zusammenmultiplizieren und dann den Wert mit 60 Multiplizieren, damit man einen Pseudo 1/60-Sekunden Wert erhält. Mal 60 ist halt mal 15 und dann noch 2x Shiften. Für mal 15 kann man dahingehend optimieren, dass man mal 16 rechnet (das sind 4x shiften) und dann den Ursprungswert davon subtrahiert.

  • Könntest du mir ein Beispiel oder einen Screenshot zukommen lassen damit ich das reproduzieren kann?

    Im Übrigen ist der REM Ersatz noch ein klein wenig Buggy: Wenn du ein ? rein bringt macht der einen PRINT daraus. Wo bei der original REM Befehl auch nicht ohne Bugs ist.....

    Das ist ja nicht das Problem des Befehls an sich, sondern des Tokenizers und De-Tokenizers. Der hört ja nicht auf, bloß weil er ein REM oder ein "'" sieht.

    Es wird aber definitiv anders gehandhabt. REM und ' (als Alternative) zeigen nach einem LIST verschiedene Kommentare. Beim REM bleibt das ? stehen, beim ' wird es in PRINT als Klartext umgewandelt.


  • So hier mein Listing



    Komisch das es bei dir funktionniert und bei mir nicht. Habe das selbe Zeichen verwqendet wie du. Habe extra dafür die Zeile 950 eingebracht um zu sehen ob es das selbe Zeichen ist. :huh:


    Nicht wunderen über den Zeichensatz, der ist von Retrofan.

    Der mir persönlich sehr gut gefällt:)


    Gruß Drachen