Posts by will

    Diddl: Gute Frage :-) ... Du hast Recht, man sollte konsequent sein. Ich schau mir diese Routine mal an. Aber für mich erklärt sich dann immer noch nicht, weil Du geschrieben hast der Farbwert wäre zufällig, warum es nach Druck auf Return funktioniert. Der Farbwert wird doch beim Einsprung (main) gesetzt.


    Danke Dir

    Am Beginn von Main setzt du den Farbwert in $286. Das beeinflusst (1) alle folgenden Zeichen die über CHROUT ausgegeben werden und (2) den Farbwert der beim Bildschirmlöschen in den Farbspeicher geschrieben wird.


    Da du CHROUT nicht verwendest hat der geschriebene Farbwert keinen Effekt bis du Return drückst, damit löst du die Bildschirmlöschroutine aus und diese setzt die Farbwerte.

    So, dank Eurer Tips habe ich jetzt ein Problem lösen können. Die Zeichen werden nun nacheinander ausgegeben. Bleibt noch die Textfarben Geschichte. Das funktioniert nur, wenn ich einmal Return gedrückt habe, das verstehe ich nicht. Hat da jemand auch noch einen Tip für mich ?? Weiss jemand zufällig welchen Code die CHRIN Routine für Run/Stop zurückgibt ??? Ich dachte gelesen zu haben, das es die 103 ist, deshalb ja auch der (falsche) Vergleich auf #$103 ... seitdem ich aber die (hoffentlich :-) ) dezimale 103 (#103) drinhabe funktioniert es nicht mehr.


    Danke Euch

    Stop key kannst du am besten über die ZP Adresse $91 überprüfen:


    Code
    1. bit $91 ; check STOP key
    2. bpl quit ; if pressed, quit program

    Mike: vielen Dank für den alles berücksichtigenden Beitrag. Ich habe mir jetzt einen Einfiler gebastelt der ein Programm unabhängig von der Lademethode und von der Speicherwerweiterung an Adresse $1000 kopiert und dann startet. Im Falle von ",8,1" muss sich das Programm selbst nochmal mir ",8" laden da ein Teil im Loch zwischen $400 und $fff verlorengeht, ist bei Programmen von maximal 3,5k Länge aber halb so schlimm.


    Der VC20 hat ja, je nachdem welche Speichererweiterung drinsteckt seinen BASIC-Beginn bei 4097, bei 1025 oder bei 4609. D.h., ein Maschinenprogramm mit SYS-Zeile, das für die kleinste Speicherversion geschrieben ist funktioniert nicht mehr wenn es auf einem VC-20 mit Speichererweiterung geladen wird.
    Abgesehen vom SYS-Befehl ist es auch sehr schwierig, ein Maschinenprogramm voll relokatibel zu schreiben.


    Gibt es da einen Trick wie man ohne großen Overhead ein Programm hinkriegt das in Assembler geschrieben ist, mit LOAD und RUN gestartet wird, und unabhängig von der Speichererweiterung läuft?

    So richtig korrigiert ist es ja nicht, es wird einmal anfangs der Fokus drauf gesetzt, und dann gibt es noch ein Script-Teil, dass aufpaßt, dass die Audio-Objekte nicht überlappen bzw. mehrfach angelegt werden. Ich hab das auch nur irgendwo geklaut :)

    Danke, darf ich es von dir klauen übernehmen? Hast du nur am Aufrufscript gebastelt oder auch an x64.js?

    Endurion, verstehe ich richtig dass du den x64s von Rijanek gefixt hast? Wie hast du das mit dem Sound hinbekommen?

    Ich bin, trotz der Verfügbarkeit anderer Webemulatoren sehr an Rijaneks Vice.js interessiert weil der auch den C128 unterstützt, das habe ich bis jetzt noch nirgendwo anders gefunden.

    Bei bisherigen Projekten war der CC65 in Verbindung mit seinem Assembler sehr nützlich für mich. Ich habe auch gelernt dass das Ding extrem viel kann und dementsprechend komplex ist.


    Allerdings bin ich noch nicht draufgekommen, wo sich User mit Fragen dazu austauschen, das scheint ziemlich verteilt zu sein. Es gibt ein paar Threads hier im Forum (die aufgrund der Sprache naturgemäß auf eine Gruppe aus 3 Ländern eingeschränkt ist), bisschen was in der csdb, in lemon64, in NES-Entwicklerforen, auf retrocomputing.stackexchange.com, ...

    Alles ziemlich versprengt...


    Früher gab es eine Mailingliste zu cc65, diese ist aber nicht mehr in Betrieb soweit ich das sehe. Das cc65-Projekt wird hingegen noch immer fleißig weiterentickelt, letztes Update war vor ein paar Tagen.


    Habe ich etwas übersehen oder gibt es wirklich kein zentrales Entwicklerforum für cc65?

    Ich würde gerne ein Assemblerprogramm in ca65 mit Makros in ein Assemblerprogramm mit aufgelösten Makros umwandeln, um beim daraus entstehenden Code ggf. noch händisch oder automatisch Optimierungen vorzunehmen. Danach soll das Assemblerprogramm in ausführbaren Code assembliert werden.


    Ist das möglich und welche Optionen muss ich angeben, um ein aufgelöstes Assemblerprogramm zu erzeugen?


    Im Moment assembliere ich mit folgender Kommandozeile:


    Code
    1. ca65 myprog.s
    2. cl65 myprog.o -C c64-asm.cfg -u __EXEHDR__ -o myprog.prg

    bzw. in einem Schritt mit


    Code
    1. cl65 myprog.s -C c64-asm.cfg -u __EXEHDR__ -o myprog.prg

    Grade getestet, hört sich hervorragend an! Schade dass ich keine SuperCPU in der Originalhardware habe.


    Meine Frage ist aber eigentlich wie man ein Audio am besten bearbeitet, wenn Player und Abspielrate vorgegeben sind.


    Welche Bearbeitungsschritte hast du durchgeführt um das Sample sauber hinzukriegen? Ich nehme an du hast einen Tiefpass vor dem Heruntersamplen verwendet. Wie steil hast du den Tiefpass eingestellt und auf welche Frequenz im Vergleich zur Abspielfrequenz?

    Quote from sidfan

    4-bit ;) Wieso abrunden? Wieso nicht nearest-neighbor, e.g. kaufmännisch runden? Sollte das nicht weniger quantization noise geben, weil quantisierte kurve näher an der soll-kurve?

    Danke für den Hinweis, der Fehler ist mit nearest-neighbor sicherlich geringer und noch dazu ist diese Feature ganz leicht implementierbar.

    Quote from sidfan

    Ich habe es nie bei 4bit probiert (ok, ich habe noch nie 4bit probiert) - aber könntest mal dithering testen, falls Audacity das auf beliebige bit auflösung kann. Ansonsten, für sowas fliegt code im netz herum...
    Ich frage mich nur, ob bei 4 bit so langsam die grenze erreicht ist, wo einfach zu wenig bits da sind, dass absichtliches hinzufügen von noise einen positiven effekt haben kann :D

    Gute Idee, werde ich probieren, danke! Du hast schon recht, supertolle Samples werden das bei 4 Bit sicherlich nicht werden, aber ich brauchte die 4 Bit weil dass für ein Release war wo der C128 Samples in BASIC (!) abspielt, und ich wollte das Ergebnis noch möglichst hörbar machen. Der Witz daran war nicht die Qualität sondern die Art des Players (siehe https://csdb.dk/release/?id=192738)

    Quote from sidfan

    Was nicht-lineares mapping betrifft - ich verstehe nicht, wie das hier helfen soll.
    Ich kenne das als verlustbehaftetes kompressionsverfahren zum sparsameren speichern oder transport über ein medium.
    Aber beim abspielen muss es ja wieder auf den größeren dynamikumfang rückkonvertiert werden - und wenn der SID nur 4 bits abspielen kann (noch dazu über einen schmutzigen hack ^^), dann helfen da mehr bits auch nicht.

    Da hatte ich mich unklar ausgedrückt, meine Frage war ob das korrekte Mapping auf die vier Lautstärken-Bits beim SID linear oder an eine Nichtlinierität anzupassen wäre. Antwort: es gibt eine nichtlinieare Komponente, ich habe meinen SID ausgemessen und eine entsprechende Kurve erstellt. Wobei wahrscheinlich jeder SID da ein bisschen anders ist...


    P.S.: Willkommen sidfan im forum64 und danke für deinen hilfreichen Beitrag!

    Der Stack, natürlich, warum ich da nicht drauf gekommen bin? :platsch:

    Das machen ja Compiler nicht anders wenn sie Funktionsaufrufe übersetzen.

    Die Stackvariante habe ich immer als recht umständlich empfunden. Wenn ich im aufrufenden Programm meine Argumente auf den Stack pushe und danach das Unterprogramm aufrufe, sind die obersten Bytes am Stack ja die Rücksprungadresse. Um an die Daten ranzukommen muss ich demnach den Stackpointer ins X-Register holen und über diesen den Stack auslesen. Nach dem Aufruf des Unterprogramms muss das Hauptprogramm den Stack aufräumen. Callee cleans wäre noch aufwendiger weil die Rücksprungadresse am Stack im Weg ist. Insgesamt ist das ist langsamer als ein Ablegen im normalen Speicher und erfordert relativ viel Code im aufrufenden Program .



    Das mit dem lda $103,x ist auch nicht gerade intuitiv, zumindest ich selbst vertue mich da oft beim richtigen Offset.


    Der Aufwand für Übergabe im Stacke lohnt sich meiner Meinung nach nur für Unterprogramme die rekursiv und reentrant sein müssen. Wobei der Hardware-Stack bei rekursiven Routinen mit Parametern sehr schnell zum Bottleneck wird.


    Um diese Limitierungen zu umgehen verwendet die C-Implementierung in cc65 daher zum Beispiel einen zweiten, in Software realisierten Stack für die Parameterübergabe.

    Gerne :-) Ich hoffe der Bezug zum C64 BASIC ist zumindest interessant gewesen, auch wenn der RORSW dort off ist.

    Aber zur eigentlichen Frage bzgl. Parameterübergabe: alles was noch Platz hat (3 Byte + Carrybit) in die Register, wenn es ein 16-Bit-Wert ist in AX. Bei einem String würde ich den Pointer übergeben. Wenn es mehr ist als in die Register passt und der Zugriff darauf zeitkritisch ist in die ZP. Wenn die Ausführungszeit nicht so kritisch ist, dann in eine Struktur im Hauptspeicher direkt bei der Routine, ggf. bau ich mir dann auch Makros zum Setzen einzelner Parameter, sodass ich bei einer Änderung der Struktur nur die Makros anpassen muss.

    Hat alles Vor-und Nachteile:


    Wenn man die Selbstmodifizierungsstrukuren in Makros packt (cc65 hat z.B. ein Macro Package dafür), kann man den Code trotzdem noch gut strukturieren.


    Auf selbstmodifizierenden Code zu verzichten benötigt dafür mehr Zero Page-Adressen. Das wird mit der Zeit auch teuflisch, wenn man dann mehrere Codeteile hat (ggf. Fremdcode) und nicht genau weiß welche ZP-Adressen verwendet werden. Insbesondere wenn BASIC und Kernal daneben noch laufen sollen, ist die ZP schon sehr belegt.


    Dafür verbau ich mir mit Selbstmodifizierungsstrukuren meine Chancen als ROM-Programmierer.


    Reentrant ist leider beides nicht...

    In den früher 6502-Chip-Versionen von 1975 gab es einen Bug beim ROR-Befehl (siehe https://www.pagetable.com/?p=406.) Die Microsoft-BASIC-Sourcen enthalten daher einen Switch (RORSW) um den Code so zu generieren dass ROR durch andere Befehle emuliert wird - natürlich auf Kosten von Geschwindigkeit und Codegröße (siehe https://www.pagetable.com/?p=774).


    Ab ca. 1976 gab es dann aber auch einen funktinierenden ROR-Befehl im 6502.


    Dieser Bug wird aber in keinem C64 zu finden sein, da dieser den 6510-Prozessor enthält, der auf der gefixten Version des 6502 mit ROR aufbaut. Das Commodore-Basic, welches ja stark auf Microsoft Basic basiert, ist deshalb auch mit ausgeschaltenem RORSW assembliert.


    Nein, mein Programm schreibt jedes Byte, auch $20. Der Grund ist dass die Zielumgebung bei mir vorher nicht mit Screen-Clear gelöscht wird, darum kann ich nicht davon ausgehen dass dort schon ein Leerzeichen ($20) steht. Der Vorteil ist, dass man mit dieser Methode auch einzelne Bytes in I/O-Registern (z.B. VIC oder SID) schreiben kann ohne den Speicher drumherum zu beeinträchtigen.

    Mein Programm funktiniert so, dass es für einen angegebenen Speicherbereich einen BASIC-Dump erstellt der genau diesen Speicherbereich befüllt. Anwendung ist also

    1. gewünschte Daten von Hand laden
    2. mein Programm laden und ausführen, die gewünschten BASIC-Zeilen stehen dann am Bildschirm
    3. eigenes Programm laden und die generierten BASIC-Zeilen mit Return dazu übernehmen
    4. Speichern nicht vergessen

    Das geht natürlich nur in Happen von ein paar hundert Byte, ansonsten muss man das mehrfach machen. Für ein paar Sprites o.ä. geht es sich aber leicht aus.