MOSpeed

Aus C64-Wiki
Zur Navigation springenZur Suche springen
MOSPeed
Konsolenausgabe
Entwickler EgonOlsen71
Release 2018
Lizenz Open Source / The Unlicense
Plattform(en) PC, C64
Genre BASIC-Cross-Compiler
Steuerung Icon tastatur.png
Sprache(n) Sprache:englisch

MOSPeed ist ein optimierender BASIC-Cross-Compiler von EgonOlsen71. Er ist Open Source bzw. Public Domain. Als Cross-Compiler läuft er auf dem PC, erzeugt aber 6502-Maschinencode für den Commodore 64, für den VC 20, für den X16 (den Commander (NICHT den Commodore) X16), Javascript, Python oder Powershell-Skripte.

Beschreibung[Bearbeiten | Quelltext bearbeiten]

MOSPeed ist ein optimierender BASIC-Cross-Compiler, der auf dem PC über die Eingabeaufforderung oder eine Shell gesteuert wird. Er erwartet als Eingabe ein BASIC-V2-Programm in Form einer Textdatei, wie sie auch z.B. vom C64 Studio oder CBM prg Studio verwendet wird. Der Compiler unterstützt die dort üblichen Platzhalter für Steuerzeichen wie z.B. {clear}. Zusätzlich dazu kann der Compiler auch direkt mit PRG-Dateien arbeiten. In diesen Fall wandelt er die PRG-Datei vor der Compilierung in ein Textformat um. Damit das funktioniert, muss die PRG-Datei auf .prg enden, ansonsten wird sie nicht als solche erkannt. MOSpeed ist in Java geschrieben und benötigt daher eine installierte Java-Runtime-Umgebung in Version 11 oder höher.

MOSpeed lässt sich über diverse Kommandozeilenparameter anpassen. Compilerdirektiven im Quelltext, wie einige andere Compiler für den C64 sie kennen, verwendet er nicht.

MOSpeed ist ein optimierender Compiler. Er kann Konstanten erkennen (auch wenn diese als Variablen deklariert sind) und entsprechend ersetzen. Nicht (mehr) verwendete Variablen oder die Berechnungen zu deren Zuweisung kann er erkennen und entfernen. In der Folge produziert der für andere Compiler gerne verwendete Benchmark-Test aus dem 64'er-Sonderheft 12 hier keine vollständig vergleichbaren Ergebnisse, da MOSpeed Teile der dort laufenden Berechnungen vollständig weg optimiert.

Die Geschwindigkeit des compilierten Programms liegt im Schnitt 10 bis 20 % über der eines mit Basic-Boss ohne spezielle Variablendeklarationen compilierten Programms, kann im Einzelfall aber auch auch wesentlich höher sein. Im Durchschnitt beschleunigt MOSpeed BASIC-V2-Programme etwa um den Faktor 3 bis 5.

Laden, Starten, Bedienung[Bearbeiten | Quelltext bearbeiten]

MOSPeed ist eine Konsolenanwendung für den PC. Da MOSPeed in Java geschrieben wurde, liegt der Compiler selber als JAR-Datei vor. In der Distribution sind zwei Skripte enthalten - einmal für Windows (mospeed.cmd), einmal für Linux (mospeed.sh) - über die der Compiler gestartet werden kann.

Er erwartet mindestens den Dateinamen/-pfad zur zu compilierenden Datei oder alternativ /?, um die integrierte Hilfe anzuzeigen. Nur mit dem Dateinamen gestartet, erzeugt der Compiler nach einem fehlerfreien Durchlauf eine .prg-Datei mit dem Namen der Quelldatei und zwei vorangestellten Pluszeichen, also z.B. example.bas wird zu ++example.prg

Der Compiliervorgang kann über zahlreiche Kommandozeilenparameter beeinflusst werden.

Der Quelltext kann mit Zeilennummern (wie üblich) arbeiten oder aber auch mit, vom Interpreter nicht ausführbaren, Labels. MOSpeed übersetzt die Labels beim Compilieren dann automatisch in Zeilennummern.

Zusätzlich zur Kommandozeilen-basierten Compiler, gibt es auch eine einfache GUI. Man kann dort Zielplattform und die zu compilierende Datei auswählen, compiliert wird aber immer mit den Default-Einstellungen. Die GUI lässt sich über die Skripte mospeed_gui.xxx im dist-Verzeichnis starten (.cmd für Windows, .sh für Linux).


Kommandozeilenparameter[Bearbeiten | Quelltext bearbeiten]

Die Kommandozeilenparameter werden direkt an den Aufruf des Compilers angehängt, die Reihenfolge ist dabei egal.
Alle Parameter beginnen mit /, es kann aber alternativ auch ein Minuszeichen verwendet werden.
true|false bedeutet im Folgenden, dass hier entweder true (für aktiv/eingeschaltet) oder false (für nicht-aktiv/ausgeschaltet) angegeben werden kann.

  • /target=<target file>: Setzt den Namen der Zieldatei explizit. Wenn nichts angegeben wird, wird das Name (wie oben kurz beschrieben) aus dem Quellnamen generiert. Hier kann auch ein kompletter gültiger Pfad angegeben werden.
  • /platform=xxxx: Gibt die Zielplattform an. Unterstützt werden aktuell c64 für C64-kompatible Maschinensprache, vc20 bzw. vic20 für VC20-kompatible Machinensprache, js für Javascript ps für Powershell. und py für Python. Default ist c64.
  • /generatesrc=true|false: Wenn true, werden zusätzlich zur Zieldatei noch die während des Compilierens generierten Quelltexte für 6502-Assembler und die verwendete Zwischensprache (assemblernah) rausgeschrieben. Default ist false.
  • /constfolding=true|false: Wenn true, werden Konstanten erkannt und im Compilat durch ihren expliziten Werte ersetzt. Beispiele sind hier die oftmals in einer Variablen abgelegten Adressen von VIC oder SID. Default ist true.
  • /constprop=true|false: Wenn true, wird Constant Propagation als Optimierung durchgeführt. D.h. Konstanten werden nicht nur direkt erkannt, sondern es werden auch solche Berechnungen als konstant erkannt, die nur auf letztendlich konstanten Werten basieren. Default ist true.
  • /ilangopt=true|false: Wenn true, wird der erzeugte Zwischencode in einem extra Durchlauf optimiert. Dies beschleunigt und verkleinert das Programm üblicherweise. Default ist true.
  • /nlangopt=true|false: Wenn true, wird der erzeugte 6502-Assemblercode im einem extra Durchlauf optimiert. Die beschleunigt und verkleinert das Programm üblicherweise, der Durchlauf ist allerdings je nach Programmgröße teilweise recht zeitaufwändig. Default ist true.
  • /smartlinker=true|false: Wenn true, werden nur die Teile der Runtime zum Compilat gelinkt, die auch wirklich von diesem verwendet werden. Bei false wird die gesamte Runtime mit dazugelinkt. Default ist true.
  • /deadstoreopt=true|false: Wenn true, werden tote, d.h. ungenutzte Variablenzuweisungen erkannt und entfernt. Dies ist meistens sinnvoll, kann aber in seltenen (z.B. bei zwar ausgeführten, aber nicht weiter genutzten Aufrufen von RND) das Ergebnis des Compilats von dem des Interpreters abweichen lassen. Dieser Parameter wirkt sich nur auf Gleitkomma- und Ganzzahlvariablen aus. Default ist true.
  • /deadstoreoptstr=true|false: Analog zu /deadstoreopt, aber für String-Variablen. Default ist true.
  • /deadcodeopt=true|false: Schaltet das Entfernen von nicht verwendetem Code an/aus. Default ist false.
  • /loopopt=true|false: Erkennt und entfernt leere Schleifen aus dem Compilat. Diese Schleifen müssen im Quelltext nicht zwangsläufig leer sein, aber wenn z.B. das in ihnen berechnete Ergebnis für nichts sonst benutzt wird, werden sie trotzdem wegoptimiert. Default ist true.
  • /addressheader=true|false: Schaltet das Schreiben der Adressbytes am Anfang der erzeugten PRG-Datei ein bzw. aus. Default ist true.
  • /floatopt=true|false: Wenn true, werden diverse Optimierungen für Gleitkommabrechnungen angewendet. Im Einzelfall kann dies, bedingt durch die Ungenauigkeiten bei Gleitkommabrechnungen, zu kleinen Abweichungen im Ergebnis führen, die aber in den meisten Fällen zu vernachlässigen sein sollten. Default ist aus Kompatibilitätsgründen false.
  • /xfloatopt=true|false: Wenn true, werden zusätzliche Optimierungen für Gleitkommabrechnungen durchgeführt. Diese können bestimmte Berechnungen um bis zu 25% beschleunigen, benötigen aber auch mehr Speicherplatz. Default ist true.
  • /intopt=true|false: Wenn true, werden bestimmte Integer-Operationen optimiert. Generell behandelt MOSpeed aus Kompatibilitätsgründen Integer-Variablen im Wesentlichen so wie der Interpreter. Mit diesem Parameter kann dieses Verhalten zu Gunsten der Geschwindigkeit etwas aufgeweicht werden. Default ist true.
  • /compactlevel=[0|3...]: Wenn >= 3, wird der generierte Code auf eine geringere Größe hin optimiert. Dies geht leicht zu Lasten der Geschwindigkeit, allerdings nicht im selben Verhältnis wie die erfolgte Größenreduktion. Je größer der Wert, desto weniger sinkt die erzielte Geschwindigkeit aber desto größer bleibt meistens der optimierte Code. 4 oder 5 sind ein guter Kompromiss, der in vielen Fällen eine 10 bis 15 % geringere Codegröße mit einer 0,5- bis 1-%igen Geschwindigkeitseinbuße verbindet. Default ist 0, was diese Optimierung ausschaltet.
  • /progstart=xxxxx|$yyyy: Legt die Startadresse des compilierten Programms fest. Die Angabe erfolgt entweder Dezimal oder Hexadezimal. Wenn diese Adresse nah an der Adresse des Starts des jeweiligen BASIC-Speichers ist, wird automatisch ein Basic-Header zum Starten mit eingebunden, ansonsten nicht. Default ist 2072.
  • /varstart=xxxxx|$yyyy: Legt die Startadresse des Variablen- bzw. Konstantenbereichs fest (siehe BASIC-Speicherbelegung). Die Angabe erfolgt entweder Dezimal oder Hexadezimal. Wird nichts angegeben, schließt sich dieser Bereich direkt an den des erzeugten Programms bzw der Runtime an. Dies ist auch der Default.
  • /varend=xxxxx|$yyyy: Legt das Ende des Variablenbereichs fest. Da sich der eigentliche Variablenbereich zur Laufzeit nicht verändert, beschreibt dies faktisch das Ende des String-Speichers. Zu achten ist darauf, dass der gewählte Bereich lesbar ist und nicht unter einem der ROMs liegt. Der Defaultwert wird durch den Inhalt der Speicherstellen 55/56 bestimmt.
  • /runtimestart=xxxxx|$yyyy: Legt die Startadresse der Runtime-Routinen fest. Die Angabe erfolgt entweder Dezimal oder Hexadezimal. Wird nichts angegeben, schließen sich diese direkt an das erzeugte Programm an. Dies ist auch der Default.
  • /sysbuffer=xxxxx|$yyyy: Legt die Startadresse des Puffers für die Ausführung von SYS mit Parametern fest. Default ist 820 für CBM-Rechner und 1024 für den X16.
  • /alloff=true|false: Wenn true, werden alle Optimierungen, die per Default aktiv sind, abgeschaltet. Default ist false.
  • /memconfig=0|3|8: Die Speicherkonfiguration, wenn der VC20 als Zielplattform genutzt wird. 0 steht für einen nicht erweiterten VC20, 3 für einen mit 3K-Erweiterung und 8 für einen mit 8K oder größerer Erweiterung. Default ist 8.
  • /vice=<path>: Hier kann ein Pfad zum VICE-Emulator (oder einem anderen mit gleichem Verhalten) angegeben werden. Nachdem der Compiliervorgang erfolgreich abgeschlossen wurde, wird das Compilat dann in diesem Emulator direkt gestartet. Per Default passiert das nicht.
  • /symboltable=<file>: Dies betrifft nur die X16-Zielplattform. Hiermit kann eine andere Symboltabelle als die im Compiler integrierte angegeben werden, um für andere ROM-Versionen zu kompilieren.
  • /nondecimals=true|false: Wenn true, können hexadezimale und binäre Werte durch $ und % im Quelltext kenntlich gemacht werden. Default ist false, außer für die X16-Zielplattform. Dort ist der Defaultwert true.
  • /tolower=true|false: Wenn true, werden alle Zeichenketten in Kleinbuchstaben konvertiert. Das kann nützlich sein, wenn ein Quelltext direkt auf einem Emulator kopiert worden ist. Default ist false.
  • /flipcase=true|false: Wenn true, wird die Groß-/Kleinschreibung aller Zeichenketten umgedreht. Das kann nützlich sein, wenn ein Quelltext direkt auf einem Emulator kopiert worden ist, wo alle Zeichenkette als Großbuchstaben erscheinen. Default ist false.
  • /multipart=true|false: Wenn false (Default), wird die Zieldatei als eine große Datei geschrieben, die alle Programmteile enthält. Bei true werden mehrere, kleinere Dateien geschrieben, sofern die Teile des Programms nicht an angrenzenden Adressen liegen.
  • /memhole=<start1-end1>,<start2-end2>,...: Legt Löcher/gesperrte Bereiche im Speicher fest. Das compilierte Programm wird diese Bereiche nicht für Code und Variablen benutzen. Wenn das Loch hinter dem compilierten Programm liegt, wird diese Angabe ignoriert. Default ist ohne Loch.
  • /boost=true|false: wenn true, nutzt ein compiliertes C64 Programm den 2 MHz-Modus des C128 zur Beschleunigung (bis zu 25%). Dies funktioniert nur auf einem C128 im C64-Modus. Es hat keinen Effekt auf einem echten C64. Möglicherweise funktioniert dies nicht mit allen Programmen. Default ist false.
  • /bigram=true|false: - wenn true werden der Speicher unter dem BASIC-ROM sowie die oberen 4K für das kompilierte Programm zusätzlich benutzt. Dies geht zu Lasten der Geschwindigkeit, besonders wenn der Speicher unter dem ROM angesprochen wird. Default ist false.
  • /compression=true|false - wenn true wird das kompilierte Programm zusätzlich gepackt. Die gepackte Datei wird zusätzlich zum normalen Kompilat abgespeichert. Packen bringt nicht immer positive Ergebnisse, in dem Fall wird keine gepackte Datei geschrieben.
  • /inlineasm=true|false - wenn true, kann Inline Assembler-Code verwendet werden, markiert mittels REM [...;...;...]. Default ist false.
  • /deploy=<ip/domain> - Wenn dies auf eine IP/Domain gesetzt wird, unter der ein Ultimate64 lauscht, wird das kompilierte Programm automatisch an dieses übertragen und gestartet. Default ist leer.
  • /printopt=true|false - *Experimentell* - wenn true, versucht der Compiler Text in PRINT-Befehlen so umzustellen, dass Speicher auf Kosten der Geschwindigkeit gespart wird. Default ist false.
  • /arrayopt=true|false - *Experimentell* - wenn true, versucht der Compiler Zugriffe auf mehrdimensionale Arrays auf Kosten des Speicherplatzes zu optimieren. Default ist false
  • /assignmentopt=true|false - *Experimentell* - wenn true, versucht der Compiler Zuweisungen zu optimieren. Default ist false.
  • /varopt=true|false - *Experimentell* - wenn true, versucht der Compiler, Integervariablen in der Zeropage abzulegen, sofern dies sinnvoll erscheint. Default ist false.

Änderungen gegenüber BASIC 2.0[Bearbeiten | Quelltext bearbeiten]

MOSpeed versucht, weitgehend kompatibel zum BASIC-V2-Interpreter zu sein. Es gibt aber ein paar wenige Abweichungen.

  • LIST: Wird ignoriert.
  • RUN: Eine evtl. nach RUN vorhandene Zeilennummer wird ignoriert.
  • NEW, STOP: Funktionieren wie END.
  • DIM mit Variablen: Dies ist generell zwar nicht erlaubt, funktioniert aber teilweise trotzdem, wenn MOSpeed die Variablen als Konstanten erkennt.
  • Eingeschränkter Support von USR: Diese Funktion wird unterstützt, als Eingabeparameter wird aber nur eine einzelne Zahl akzeptiert. Strings oder mehrere Parameter sind nicht möglich.
  • SYS mit Parametern: Diese Option wird unterstützt. Da sie aber in erster Linie ohnehin eher ein Hack ist, kann die Ausführung des Aufrufs im Kompilat langsamer sein.
  • INPUT mit Anführungszeichen: MOSpeed ist bei der Eingabe von Anführungszeichen bei INPUT etwas toleranter als der Interpreter.
  • Vereinheitlichte Rundung: Der Interpreter wählt in verschiedenen Situationen verschiedene Rundungsansätze. So wird z.B. je nach Ursprung eines Wertes teilweise anders gerundet. Beispiel: A=145/3*3 setzt A auf 145, aber PEEK(145/3*3) liest aus 144, nicht aus 145.[1] MOSpeed vereinheitlicht dieses Verhalten, so dass in diesem Beispiel immer 145 gilt (wie dies z.B. auch im BASIC 7.0 des C128 der Fall ist).
  • Gleitkommagenauigkeit: Die Ergebnisse von Gleitkommaoperationen können sich, je nach gewählter Optimierung, zwischen MOSpeed und dem Interpreter leicht unterscheiden. Dies sollte in den allermeisten Fällen aber kein Problem sein bzw. gar nicht erst auffallen. MOSpeed versucht ferner, einen Fehler in den Gleitkommaroutinen des ROMs zu umgehen, so dass Ergebnisse unter Umständen in MOSpeed richtiger sein können.
  • IF mit Strings ohne Vergleichsoperator: BASIC V2 gibt für A$="":B$="YEAH":IFA$THEN?"OK" OK aus, obwohl A$ leer ist. Das liegt daran, dass hier nicht die Variable im IF (also A$) für den Test benutzt wird, sondern der tatsächlich im Fließkommaakkumulator verbliebene Wert.[2] MOSpeed führt den Test immer mit der Variable durch, die im IF-Teil steht.

Laufzeitfehler[Bearbeiten | Quelltext bearbeiten]

Laufzeitfehler im Programm (z.B. bei Division durch 0 oder ähnlichem) werden in den meisten Fällen von MOSpeed zwar erkannt und ausgegeben, als Zeilennummer wird allerdings immer 0 ausgegeben.


Zielplattformen[Bearbeiten | Quelltext bearbeiten]

C64 / 6502-Maschinensprache[Bearbeiten | Quelltext bearbeiten]

Bei dieser (Default-)Zielplattform wird vom Compiler eine .prg-Datei erzeugt, die direkt im Emulator ausgeführt werden kann. Sie kann auch über einen der üblichen Wege auf einen echten C64 übertragen werden und dort direkt ausgeführt werden.

VC/VIC20/ 6502-Maschinensprache[Bearbeiten | Quelltext bearbeiten]

Es wird vom Compiler eine .prg-Datei erzeugt, die direkt im Emulator ausgeführt werden kann. Sie kann auch über einen der üblichen Wege auf einen echten VC-20 übertragen werden und dort direkt ausgeführt werden.

X16 / 6502-Maschinensprache[Bearbeiten | Quelltext bearbeiten]

Es wird vom Compiler eine .prg-Datei erzeugt, die direkt im Emulator ausgeführt werden kann. Diese kann auf einen echten X16 übertragen werden, so er denn irgendwann verfügbar ist.

Javascript[Bearbeiten | Quelltext bearbeiten]

Bei dieser Zielplattform erzeugt der Compiler zwei Dateien, eine .js, die das compilierte Javascript und die Javascript-Laufzeitumgebung dafür enthält, und eine .html-Datei, die zum Einbinden der nötigen Ressourcen und zum Starten des compilierten Programms dient. Dabei gibt es mehrere Möglichkeiten des Startens. Der Default ist, dass das Programm seine Ausgaben auf die Javascript-Konsole schreibt und Eingaben (INPUT wie auch GET) über Javascript-Prompts entgegennimmt. Dabei läuft das Programm im Thread des Starters, also im Normalfall im normalen Browserthread, welcher dadurch bis zum Programmende blockiert ist.

Alternativ dazu lässt es sich auch so starten, dass es in einem WebWorker läuft. Damit ist der Starter-Thread frei für andere Aufgaben.

Eine dritte Option erlaubt es, die Ausgabe in eine an den C64-BASIC-Editor angelehnte Konsole im Browser zu schreiben. GET-Eingaben werden ebenfalls von dort eingelesen, INPUT-Eingaben erfolgen aber aus technischen Gründen weiter über Javascript-Prompts.

Die Auswahl dieser Optionen muss direkt durch Änderungen im Quelltext der .html-Datei erfolgen. Die entsprechenden Bereiche sind durch Kommentare markiert. Für die Nutzung der Browserkonsole müssen noch die Dateien console.js und CommodoreServer.ttf auf den resources-Verzeichnis des Projektes in das Verzeichnis mit der .html-Datei kopiert werden.

Powershell[Bearbeiten | Quelltext bearbeiten]

Der Compiler erzeugt eine .ps1-Datei, die in einer Powershell-Konsole ausgeführt werden kann.

Python[Bearbeiten | Quelltext bearbeiten]

Der Compiler erzeugt eine .py-Datei, die auf der Kommandozeile ausgeführt werden kann.


Inline Asembler-Unterstützung[Bearbeiten | Quelltext bearbeiten]

MOSpeed unterstützt Inline-Assembler-Code, das ist aber aus Kompatibilitätsgründen standardmäßig deaktiviert. Man kann es aktivieren, indem man /inlineasm=true setzt. Wenn aktiviert, wird alles hinter einem REM in eckigen Klammern vom eingebauten Assembler verarbeitet. Mehrere Befehle/Labels//Zuweisungen können mittels Semikolon getrennt in eine Zeile geschrieben werden. Zum Beispiel:

10 print "hello asm"
20 rem [ ldx #$ff ]
30 rem [ loopy; inc 53280 ]
40 rem [ dex; bne loopy ]
50 goto 10

Dies gibt "hello asm" in einer Endlosschleife aus, lässt aber auch den Rand mittels Maschinensprache-Code blinken. Es können sowohl Labels als auch Konstanten im Assemblercode definiert werden. Also so etwas wird auch funktionieren:

10 print "hello asm"
20 rem [ numby=$ff; ldx #numby ]
30 rem [ loopy; inc 53280 ]
40 rem [ dex; bne loopy ]
50 goto 10

Es kann auf BASIC-Variablen und -Zeilen zugegriffen werden, indem ! als Postfix verwendet wird, also etwa so:

10 print "hello asm": i%=255
20 rem [ ldx i%! ]
30 rem [ inc 53280 ]
40 rem [ dex; bne 30! ]
50 goto 10

ldx i%! lädt das Low-Byte von i% in das X-Register; das High-Byte würde per ldx i%!+1 geladen.

Sowas geht auch:

10 print "hello asm": i%=255
20 rem [ ldx numby ]
30 rem [ inc 53280 ]
40 rem [ dex; bne 30!; jmp 50! ]
45 rem [ numby; .byte 255 ]
50 goto 10

Im Grunde geht also alles, was auch in dem eigentlichen Assembler geht, der mit diesem Projekt mitgeliefert wird. Dazu gehört auch, das kompilierte Programm und/oder die Laufzeit mit dieser Option zu vermasseln, wenn man nicht aufpasst. Sogar böse Hacks wie diese sind möglich:

10 print "hello asm"
20 rem [ldx #$ff]
30 rem [jmp 40!; *=$2000;]
40 rem [inc 53280]
50 rem [dex; bne 40!]
60 goto 10

Damit wird der kompilierte Code in zwei Teile geteilt, Teil 1 beginnt bei $0801 (standard) und alles nach Zeile 30 geht bei $2000 weiter. Obwohl das funktioniert, es ist besser, sowas nicht zu machen. In diesem Fall wäre die /memhole-Option eine bessere Lösung...

Einbindung in CBM prg Studio[Bearbeiten | Quelltext bearbeiten]

MOSpeed lässt sich in CBM prg Studio einbinden, so dass der Compiler bei jedem Build gestartet und das Compilat dann im Emulator ausgeführt wird. Diese Einbindung ist nicht perfekt, aber durchaus hilfreich. Zur Verdeutlichung hier ein kleines Beispiel.

Im Beispiel verwende ich ein Projekt namen "compilertest" mit einer Quelldatei namens "fractal.bas"

Sourcode



Jetzt den Menüpunkt "Build" -> "Build Events..." auswählen:

Menü "Build Events"



Hier den Haken bei "Post-Build Commands" und folgendes in der dann aktiven Textbox eintragen:

[DOSCMD]cd <Pfad zu MOSpeed> && <Laufwerk, auf dem MOSspeed liegt>: && mospeed.cmd [ProjectDir]<Name der Quelldatei> -vice=<Pfad zu VICE>\x64.exe

in meinem Beispiel sieht das dann konkret so aus:

[DOSCMD]cd e:\src\myprojects\workspace\BasicV2\dist && e: && mospeed.cmd [ProjectDir]fractal.bas -vice=e:\Programme\WinVICE-2.2-x64\x64.exe

"Post-Build Commands"


Der gesamte Aufruf wird hier also als verkettete Liste von DOS-Befehlen übergeben. Das müsste laut Dokumentation eigentlich auch anders gehen, aber das hat bei mir nicht funktioniert. Dieser Befehl wird nun nach jedem Build (also z.B. beim Drücken von F6  im CBM prg Studio) ausgeführt. Zu beachten ist, dass er nicht auf der von CBM prg Studio beim Build erzeugten .prg-Datei aufsetzt, sondern auf der eigentlichen Quelldatei. Leider bietet CBM prg Studio bisher keine Möglichkeit, den generierten Quelltext vor der Erzeugung eines PRG abzugreifen. Von daher ist die Lösung so nicht ideal.
Der Name der Quelldatei muss leider direkt im Befehl angegeben werden (in diesem Beispiel fractal.bas). CBM prg Studio bietet zwar einen [prg]-Platzhalter an, aber der verweist auf die erzeugte PRG-Datei, mit der MOSpeed nichts anfangen kann.
Ein weiteres Problem ist, dass CBM prg Studio die Ausgaben des Compilers nur im Fehlerfall anzeigt. Man sieht also nicht, was passiert und kann, gerade bei längeren Programmen, nur abwarten, bis der Compiler seine Arbeit erledigt hat.

Ein Fehler in CBM prg Studio sorgt aktuell dafür, dass nach einem Neustart die &&-Zeichen im Befehl in &amp;&amp; umgewandelt sind. Man muss diese also bei jedem Start der IDE korrigieren.


Weblinks[Bearbeiten | Quelltext bearbeiten]

Programm
Medien


Anmerkungen[Bearbeiten | Quelltext bearbeiten]

  1. Unterschiedliche Ergebnisse bei direkter Ausgabe einer Ausdrucksauswertung und einer Variable ergeben sich daraus, dass die Genauigkeit des Fließkommaakkumulators höher ist und für das implizite INT() beim PEEK-Argument keine Rundung durchgeführt wird, wo hingegen beim Transfer in eine Variablen eine Rundungslogik aktiv ist, um die Umwandlung auf die niedrigere Genauigkeit der Variable abzufedern. Dieses Verhalten zeigt sich nicht mehr bei BASIC 7.0.
  2. Der zuletzt im Fließkommaakkumulator befindliche Wert ist bei IF ausschlaggebend und wird z.B. durch eine String-Manipulation, die einen temporären String erzeugt, verändert, da hier die String-Länge in Zeropage-Speicherstelle $61 gelangt, welche auch gleichzeitig der Exponent des Fließkommaakkumulators ist.
    Siehe auch BASIC-ROM $B4A9 und $B4D5