GRA-EXT ======= Autor: Johann Klasek, johann AT klasek at Versionen: 2022-04-24 v 1.34 Befehl &F (Fill) Code-Bereinigung, kleinere Optimierungen. 2022-03-27 v 1.33 Befehl &F (Fill) Korrektur Fehler Startpunkt. 2020-05-03 v 1.32 Befehl &F (Fill) in platzoptimierter Variante (als Standard), wo der Positionsstack nur noch 3 statt 4 Bytes braucht mit Korrektur der Startpositionsparameter. 2019-10-31 v 1.31 Befehl &B (Box) ergänzt. 2019-10-25 v 1.30 &T, &R mit beliebig weiteren Koordinatenpaaren mit TO als Separator. &S Modus 3-5 korrigiert. 2019-10-11 v 1.29 Optimierung &L (Bresenham, X-Dekrementierung). Grafik-Speichereinblendung mit Interruptsperre minimiert. Source-Doku. korr. und erweitert. 2016-09-10 v 1.28 Befehl &F (Fill) ergänzt. 2016-07-13 v 1.27 &V geschwindigkeitsoptimiert. 2016-07-09 v 1.26 Funktionen &X,&Y,&Z(x,y) ergänzt. save-Variablen umgeordnet, erweitert. Single-Expression-Hook ($030A) verwendet. 2016-06-19 v 1.25 &C korrigiert umstrukturiert. &s5 ist noch nicht implementiert. Produktiv mit Mängel: Fehlerbehandlung korr. (für &s3-5) Neu: &H x,y,xl[,yl] (breite horiz. Linie) LTC-Variante berücksichtigt spezielle Speicherkonfiguration! Versionsnummer im Dateikopf. 2016-06-16 v 1.24 Bugfix: &C korrigiert umstrukturiert. Startmeldung nur im Direktmodus ausgeben. Buggy: &s3-5 funktioniert nicht. Fehlerbehandlung unvollständig (für &s3-5) 2016-05-30 v 1.23 &U neu (UNNEW) Buggy: &s3-5 funktioniert nicht. Fehlerbehandlung unvollständig (für &s3-5) 2016-05-20 v 1.22 &G Modi 3 (nur löschen) und 4 (nur aus) &S neue Werte 3-5 für Fehlerbehandlung, Fehlerbehandlung dynamisch (unvollständig) ROM-fähig (gmask, gchange Routinen ins RAM, $033C-Bereich) Buggy: &s3-5 funktioniert nicht. Fehlerbehandlung unvollständig (für &s3-5) 2016-02-23 v 1.21 graext-core.asm als Basis für graext (ge) und ge-run (als RUN-Programm, verschiebt Basic-Start!) 2016-02-23 v 1.20 Optimierte Jump-Table, Bugfix Line command_rts_style=1 ... Kommandoverteiler via RTS statt JMP. Bugfix Command-Hook: z.B. ":" am Zeilenanfang lösten einen Syntax-Error aus. 2016-01-18 v 1.19 Bug in Line flat/up no_error=1 ... kein Illegal Quantity Error 2016-01-14 v 1.18 in ACME-Source übertragen Binär dem Original 1992 entsprechend, inklusive aller Bugs. 1992-12-28 v 1.18 Kommandosyntax ohne "," Verteilt (z.B. an Michael Rautner) 1986-03-24 v 1.17 Finale Version zur damaligen Zeit üblicherweise in Verwendung (Maturazeitungsdiagramme) 1985 v 0.00 - 1.16 ToDO: * &C Prozport nicht mit festen Wert überschreiben ($21), nur maskieren! Wunschliste: * Char mit Pixel-Positionierung * Grafik löschen separat und besonders schnell! * Circle * Clipping: trotzdem Zeichnen, aber am Rand aufhören. Echtes Clipping oder nur Koordinaten abschneiden? (Fehlerbehandlung Mode 5!) * Multicolor? erledigt: * Box &b -> ab 1.31 * &t (To), &r (RelTo) mit beliebig vielen Koordinatenpaaren. -> ab 1.30 * Optimierungen: Line: zu niedrigen Koordinaten mit Dekremetieren und Zero-Bedingung statt Inkremtieren mit explizitem Vergleich. -> ab 1.29 * Fill -> ab 1.28 * Grafikcursor auslesen -> ab 1.26 * GETXY-Funktion -> ab 1.26 * Fehlerbehandlung auswählbar -> ab 1.25 * Block gefüllt (&H anpassen?) -> ab 1.25 * Unnew -> ab 1.23 * Grafik einschalten ohne löschen. -> ab 1.22 Geschichte: Die Wurzel der Erweiterung liegt in der Grafikerweiterung für die Forth- Umgebung Performance Micro Prod. von Greg Harris, programmiert im (eigenen) Forth-Assembler mit entsprechenden Forth-Worten (GRON, GROFF, GRCL, GRCOL, MODE, LINE, PLOT, TEST, HLIN, VLIN). Die codierten Tabellen und Routinen (Screen 59 bis Screen 64 von Disk 059 "FORTH V5.0 MD") sind als JSR-Subroutinen ausgebildet und es sind nur jene Bestandteile entnommen worden, die keine Forth-High-Level-Worte darstellen. Diese Routinen und Tabellen wurden aus dem Forth-Dictionary per Monitor in den Bereich $C000 bis $CFFF übertragen, wobei diese reloziert wurden und auch die verwendeten Zero-Page-Speicherstellen umgesetzt werden mussten. Die BASIC-Kommandos und die Interpreter-Anbindung ist per Monitor dazu assembliert worden. Die Grafikroutinen sind dahingehend optimiert, dass die auf dem Bresenham-Algorithmus basierende Umsetzung ohne ständige Punktpositionsberechung arbeitet, sondern der Grafikcursor als Adresse und Bitposition geführt wird. Eine ähnliche Implementierung findet man auch im Spiel Elite, wo aber der Linienalgorithmus auf DDA basiert, wobei die Steigung auf 256 per Division vorher skaliert wird, was den Vorteil hat, dass in der Linienschleife nur eine Addition nötig ist und bei einem 0-Durchgang den Versatz eines Linienpunktes anzeigt. Dazu kommt noch, dass dort zum einen der Grafikbereich so eingeschränkt ist, dass die X- Koordinate mit einem Byte auskommt (0-255) und zum anderen ein Loop- Unrolling bei entsprechenden Platzverbrauch verwendet wurde, was eine noch schnellere Implementierung ergab. Zugunsten der Kompaktheit wurde für die BASIC-Erweiterung auf ein Loop-Unrolling verzichtet. Ergänzend kamen auch noch das Zeichnen speziell optimierter Linienvarianten, nämlich für eine horizontale und vertikale Linie, die auch als Sonderfälle im gewöhnlichen Linienbefehl integriert sind. Die horizontale Linie ist später zu einem Blockbefehl ausgeweitet worden, wo man die "Linienstärke" angeben kann (entspricht der Blockhöhe). Als eigenständiger Befehl wurde der Schriftbefehl, um Text in die Grafik zu schreiben. Es war aber nur die bekannte Text-Block-Auflösung für die Positionierung möglich (nicht auf Pixel-Basis). In der Initialversion ist der Code für den Punkttest (unter Forth "TEST") zwar enthalten, wird aber vom Glue-Code nicht in den Interpreter eingebunden. Verwendung ---------- ### RUN-Variante LOAD"GE-RUN",8 RUN # Einschaltmeldung sollte erscheinen. LOAD"....",8 ### SYS-Variante # die Erweiterung vorher laden: LOAD"GE",8,1 NEW SYS49152 LOAD"....",8 # Oder im Programm die Erweiterung automatisch laden und initialisieren: 1 IFPEEK(49153)+PEEK(49154)<>21THENLOAD"GE",8,1 2 IFPEEK(49153)+PEEK(49154)=21THENSYS49152 ### Originalvariante LOAD"G-EXT18",8,1 NEW LOAD"....",8 1 SYS49152 Source Repo ----------- Makefile Erstellen von make erstellt Gra-Ext PRGs make i erstellt D64-Image x.d64 butterfly-test.prg Hires-Bitmap mit einem Schmetterling für fill-butterfly debug.bas Grafik-Demo: Block-/Linien-Demo zum Experimentieren (Textformat) debug.prg Grafik-Demo: Block-/Linien-Demo zum Experimentieren (CBM-Format) demo1.bas Grafik-Demo: Schirm mit Linien füllen (Textformat) demo1.prg Grafik-Demo: Schirm mit Linien füllen (CBM-Format) demo2.bas Grafik-Demo: Schirm mit mittigem Linienstrahlen füllen (Textformat) demo2.prg Grafik-Demo: Schirm mit mittigem Linienstrahlen füllen (CBM-Format) demo-h-v.bas Grafik-Demo: Vergleich Schirmfüllen mit H-Linien, V-Linien und H-Block (Textformat) demo-h-v.prg Grafik-Demo: Vergleich Schirmfüllen mit H-Linien, V-Linien und H-Block (CBM-Format) demo-star.bas Grafik-Demo: Stern (Textformat) demo-star.prg Grafik-Demo: Stern (CBM-Format) Laufzeit: 2,5 s Aus https://www.c64-wiki.de/wiki/Special_Basic#Test_der_Grafik-Geschwindigkeit demo-v.bas Grafik-Demo: Zeitmessung Schirmfüllen mit V-Linien (Textformat) demo-v.prg Grafik-Demo: Zeitmessung Schirmfüllen mit V-Linien (CBM-Format) fill-butterfly.bas Grafik-Demo: Lädt butterfly-test Hires-Bild und füllt und löscht es mit Zeitmessung (Textformat) fill-butterfly.prg Grafik-Demo: Lädt butterfly-test Hires-Bild und füllt und löscht es mit Zeitmessung (CBM-Format) fill-demo.bas Grafik-Demo: Füllen des Zwischenraumes bei einem zufällig gesetzten Blockhaufen und wieder füllend löschen (Textformat) fill-demo.prg Grafik-Demo: Füllen des Zwischenraumes bei einem zufällig gesetzten Blockhaufen und wieder füllend löschen (CBM-Format) fill-demo2.bas Grafik-Demo: Füllen des Zwischenraumes bei einem zufällig gezeichneten Linienhaufen und wieder füllend löschen, wobei durch schräge Übergänge nicht alles zusammenhängend ist und damit nicht alles "verschwindet". (Textformat) fill-demo2.prg Grafik-Demo: Füllen des Zwischenraumes bei einem zufällig gezeichneten Linienhaufen und wieder füllend löschen, wobei durch schräge Übergänge nicht alles zusammenhängend ist und damit nicht alles "verschwindet". (CBM-Format) fill-demo3.bas Grafik-Demo: Füllen des Zwischenraumes bei einem zufällig gesetzten Rechteckhaufen und wieder füllend löschen (Textformat) Ab Gra-Ext 1.31 fill-demo3.prg Grafik-Demo: Füllen des Zwischenraumes bei einem zufällig gesetzten Rechteckhaufen und wieder füllend löschen (CBM-Format) Ab Gra-Ext 1.31 fill-all.bas Grafik-Demo: Leeren Screen bei 0,0 füllen und mit Zeitmessung. (Textformat) fill-all.prg Grafik-Demo: Leeren Screen bei 0,0 füllen und mit Zeitmessung. (CBM-Format) g-ext18.hex Gra-Ext 1.8 im od-Hex-Format g-ext18.prg Gra-Ext 1.8 im CBM-Format als Referenz, von der Distributionsdisk gliding-lines.bas Grafik-Demo: Bewegendes Linienbündel (Textformat) gliding-lines.prg Grafik-Demo: Bewegendes Linienbündel (CBM-Format) ge-run.asm Gra-Ext RUN-Variante, verwendet graext-core.asm ge-run.l ACME Listing-Ausgabe der RUN-Variante ge-run.prg ACME Objekt-Datei (CBM-Format) der RUN-Variante ge-run.r ACME Report-Ausgabe der RUN-Variante ge-run+.l ACME Listing-Ausgabe der RUN-Variante, Stack geschwindigkeitsoptimiert. ge-run+.prg ACME Objekt-Datei (CBM-Format) der RUN-Variante, Stack geschwindigkeitsoptimiert. ge-run+.r ACME Report-Ausgabe der RUN-Variante, Stack geschwindigkeitsoptimiert. graext-c000-ltc Gra-Ext LTC-Variante (Lost Turbo Card 64) graext-c000-ltc.l ACME Listing-Ausgabe der LTC-Variante graext-c000-ltc.r ACME Report-Ausgabe der LTC-Variante graext-core.asm Gra-Ext Core für RUN-Variante, SYS-Variante graext.asm Gra-Ext SYS-Variante, verwendet graext-core.asm graext.hex Binary im Hex-Format für den diff-Vergleich mit der Referenz g-ext18.hex War nur für die Source-Wiederherstellung auf Basis des 1.8-Codes verwendet worden. ge.prg Nur eine Kopie von graext.o, für das D64-Image ge+.prg Nur eine Kopie von graext+.o, für das D64-Image graext.l ACME Listing-Ausgabe der SYS-Variante graext.o ACME Objekt-Datei (CBM-Format) der SYS-Variante graext.r ACME Report-Ausgabe der SYS-Variante graext+.l ACME Listing-Ausgabe der SYS-Variante, Stack geschwindigkeitsoptimiert. graext+.o ACME Objekt-Datei (CBM-Format) der SYS-Variante, Stack geschwindigkeitsoptimiert. graext+.r ACME Report-Ausgabe der SYS-Variante, Stack geschwindigkeitsoptimiert. info.txt diese Datei kreise.bas Grafik-Demo: Kreise-Grafik (Textformat) kreise.prg Grafik-Demo: Kreise-Grafik (CBM-Format) kreise.png Grafik-Demo: Kreise-Grafik Screenshot Endbild. spirale.bas Grafik-Demo: Spiral-Grafik (Textformat) spirale.prg Grafik-Demo: Spiral-Grafik (CBM-Format) Lange Berechnung! Ergebnisbild laut PNG. Laufzeit: 5931.76667 s Jiffies, RTC: 1:39:06.5 (1:38:51 gemäß Jiffies) spirale.png Grafik-Demo: Spirale-Grafik Screenshot Endbild. x.d64 D64-Image, erstell mittels make x.d64 oder make i Source ------ 1.*/ Versionen-Snapshots ("tagged"), erstellt mittels make tag TAG="x.y" Makefile Erstellen von make erstellt Gra-Ext PRGs make i erstellt D64-Image x.d64 REV/ Datenrevisionen butterfly-test.prg Hires-Bitmap mit einem Schmetterling debug identisch mit debug.prg, von Diskimage kommend debug.bas Text-Version von debug.prg debug.prg Block-Demo demo1.bas Text-Version von demo1.prg demo1.prg Moiree-Demo asymmetrisch demo2.bas demo2.prg Moiree-Demo im Rechteck, mittig Laufzeit: 14,7 s demo-h-v.bas demo-h-v.prg Schirm mit vertikalen und horizontalen Linien füllen/löschen demo-star.bas demo-star.prg Stern Laufzeit: 2,5 s Aus https://www.c64-wiki.de/wiki/Special_Basic#Test_der_Grafik-Geschwindigkeit demo-test-1.bas demo-test-1.prg 1-Pixel-Blöcke füllen (Fill-Test). demo-v.bas demo-v.prg Schirm laufend mit vertikalen Linien füllen/löschen fill-butterfly.bas fill-butterfly.prg Lädt butterfly-test Hires-Bild und füllt es. fill-demo.bas fill-demo.prg Überdeckende Rechteck-Wolke umfüllen und wieder löschen fill-demo2.bas fill-demo2.prg Zick-Zack-Linien umfüllen und wieder löschen fill-demo3.bas fill-demo3.prg Durchscheinende Rechteck-Wolke umfüllen und wieder löschen g-ext18 identisch mit g-ext18.prg, von Diskimage kommend g-ext18.hex g-ext18.prg Gra-Ext 1.8 als Referenz ge-run.asm ge-run.l ge-run.prg ge-run.r Gra-Ext RUN-Variante gliding-lines.prg Grafik-Demo graext-core.asm graext.init.asm graext.asm graext.hex Binary im Hex-Format für den diff-Vergleich mit der Referenz g-ext18.hex War nur für die Source-Wiederherstellung auf Basis des 1.8-Codes verwendet worden. ge identisch mit ge.prg, von Diskimage kommend. ge.prg identisch mit graext.o^ graext.l graext.o graext.r Gra-Exe SYS-Variante graext.vice.src.txt index.txt info.demo.txt Hinweise für den Demo-Start info.txt kreise.bas kreise.prg kreise.png Kreise-Grafik-Demo. Lange Berechnung! Ergebnisbild laut PNG. spirale.bas spirale.prg spirale.png Spiral-Grafik-Demo. Lange Berechnung! Ergebnisbild laut PNG. Laufzeit: 5931.76667 s Jiffies, RTC: 1:39:06.5 (1:38:51 gemäß Jiffies) todo.txt Ideen und TODOs x.d64 D64-Image, erstellen mittels make x.d64 oder make i Lost Turbo Card 64 (LTC) ------------------------ Seit V 1.25 ist mit "graext-c000-ltc" die Unterstützung für die 65816-CPU-Erweiterungsplatine auf Basis eines Artikels im c't-Magazin gegeben: Michael Flamm, Rene Schneider: Aufgemotzt C64 mit 4-MHz-Takt und 16-Bit -CPU Projekt, Commodore C64 c't 6/87, Seite 94ff Im Boot-ROM der Erweiterung wird GraExt eingebunden und kann mit SYS 49152 aktiviert werden. Dies ist dank der seit Version 1.22 eingeführten ROM-Fähigkeit bei GraExt nun möglich. Dabei wird die vollständige ROM-Simulation aktiviert, die gewährleistet, dass GraExt mit der vollen Taktfrequenz (nicht auf 1 MHz gebremst) ausgeführt wird. Auf die Zeropage-Register wird ohnehin immer ungebremst zugegriffen. Lediglich beim Zugriff auf das Grafik-RAM (das C64-interne) zwecks Manipulation der Grafikdaten, erfolgt der Zugriff nur mit 1 MHz, was aber anteilig eher geringfügig ist. Allerdings hat der Modus "vollständige ROM-Simulation" den Nachteil, dass ab $8000 das externe RAM eingeblendet ist und als Pseudo-ROM wie ein ROM nicht veränderlich ist. Hier funktioniert leider auch nicht die gewohnte Steuerung der Memory-Map mittels Prozessorport $01. Daher muss beim Zugriff auf das Grafik-RAM ab $E000 immer dieser Modus ausgeschaltet und auf die normale ROM-Simulation umgeschaltet werden (wo dann das KERNAL-ROM ausgeblendet ist). Diese Umschaltung ist nur in der speziellen graext-c000-ltc-Variante inkludiert. Da hierbei umständlich ein Konfigurationsregister der HW-Erweiterung beschrieben werden muss, kommen hier zur Sicherung des Registers und zum Erreichen des Konfigurationsregisters auch 65816er-Befehle vor, die aber auch im Emulationsmodus ausgeführt werden können (XBA, STA absolut-long). Dieser zusätzliche Code hat als Nebenwirkung ein leichte Verlangsamung im 1-MHz-Modus im Vergleich zum "normalen" C64 ohne HW-Erweiterung, aber im Turbo-Modus wird das Maximum der möglichen Geschwindigkeit heraus geholt. Bugs ---- Version 1.28 bis 1.32 - - - - - - - - - - - * &F Kommando: Startpunkt wird nicht zuverlässig als füllbar erkannte und kann zu einem unmittelbaren Abbruch führen, ohne dass gefüllt wird. Version bis 1.29 - - - - - - - - * &S Kommando: Modus 3 bis 5 wurden nicht richtig verarbeitet (Fehlerbehandlungsmodus). Version 1.18 - - - - - - * Parser hat das Problem, ein ":" am Zeilenanfang führt zu einem "Syntax Error". Ursache: Der CHRGET-Status nach der Prüfung von "&" wird nicht der Status korrekt erhalten, wenn es kein "&"-Zeichen ist und das Parsing ans ROM weitergegeben wird. Fill-Demo --------- Speicherverbrauch - - - - - - - - - fill-demo.bas Stackverbrauch Elemente -------------------------------------------------------------------------------------- V1.34 2022-04-14 - 1400 V1.28 2016-09-10 094F - 0F80 396 Nachbaren auf Stack korr. V1.28 2016-09-05 0900 - 0F00 384 Stackelement entfernen, wenn Lücke vollständig leer. 0909 - 0F71 410 V1.28 2016-08-29 0900 - 1A00 1088 +Lückenstart bei 8-Pixelzeile V1.28 2016-08-26 0900 - 1A00 1088 durchgehende Lücke oben/unten nur ein Stackelement! V1.27 2016-08-15 0900 - 4000 3520 jeder nichtgefüllte Nachbar ein Stackelement! -------------------------------------------------------------------------------------- Benchmarking ------------- ++++++++ GraExt 1.17 ### Dreieck 10 &g,1,5,0 20 &s,2 100 fori=0to319 110 &l,0,0,i,199 120 next 130 goto100 1000 &g,0 # 6510 1 MHz 10 Durchläufe 1:33 -> 9,3s +++++++ GraExt 1.25, 1.31 ### Unterschied &H im Blockmodus und &V # Vertikale Linie von links nach rechts den Bildschirm füllend. # Siehe demo-h-v.bas # Variante 1 &H 0,0,319,199 # Variante 2 (1 Pixel lange vertikale Linie vertikal über volle Höhe) FOR X=0TO319 &H X,0,0,199 NEXT # Variante 3 FOR X=0TO319 &V X,0,199 NEXT # Variante 4 (vertikale Linie, ist Sonderfall der auf &V-Routine geht) FOR X=0TO319 &L X,0,X,199 NEXT # Variante 5 (vergleich, mit horiz. Linien füllen) FOR X=0TO199 &L 0,X,319,X NEXT Variante Zeit 1.25 1.31 TI RTC ----------------------------- 1: &H full 0,03 0,5 2: &H 6,52 6,5 3: &V 5,45 5,3 4: &L vert. 5,83 5,8 5: &L hor. 2,50 2,6 ++++++++++ GraExt 1.26 10x &VX,0,199 54.25 s (TI) Nach &V Optimierung in 1.27 10x &VX,0,199 52.85 s (TI) 10x &LX,199,X,0 57.00 s (TI) Parsing 4. Parameter 10x &LX,0,X,199 57.05 s (TI) Parsing 4. Parameter und Tausch der Y-Werte +++++++++++ Demos GraExt-Version 1.18 1.29 1.31/1.33 1.34a 1.34 1.34 size size size speed TI/RTC TI/RTC TI/RTC TI/RTC TI/RTC TI/RTC STACK STACK STACK STACK ------------------------------------------------------------------------------------------- DEMO1 21,0/25,2 20,5/22,7 20,5/22.6 DEMO2 15,0/19,0 15,2/16,8 15,1/16,7 DEMO-V 55,3/55,5 53,4/53,5 53,3/53,2 DEMO-H-V - 6,6/6,6 6,6/6,5 5,6/5,5 5,4/5,3 5,4/5.3 - 0,07/0,4 0,08/0,3 DEMO-STAR * * 2,45/2,5 FILL-BUTTERFLY - * 4/1,8 2,0/2,2 4/1,7 4/1,6 4/1,9 4/1,8 4/1,7 $1098 $1610 $1098 $12cc $1158 $1158 $13cc FILL-ALL - * -/1,77 -/1,9 -/1,8 -/1,8 $0a00 $0ba0 $094e(1) $094f(1) ------------------------------------------------------------------------------------------- Legende: * nicht erfasst - nicht implementiert