Angeregt von einer Veröffentlichung in der Programmierpraxis in GFA-BASIC (Michael Kraus, Hardcopy fĂŒr 9-Nadler, 12/88, S.88 f.) und in Erinnerung an ein Ă€lteres, etwas langsames, in Pascal erstelltes Programm aus der ST-PD-Sammlung (HACOMINI.TOS), wollte ich endlich einmal die Aufgabe, Hardcopies in besonderen Formaten auszugeben, a.) in âAssemblerâ lösen und b.) als jederzeit abrufbare residente Routine gestalten (Start des Programms aus dem AUTO-Ordner).
Zwar graute mir insgeheim vor Seiten voller endloser Move-Befehle, mit denen ich jede einzelne Nadel mit jedem einzelnen Pixel bestĂŒcken mĂŒĂte, doch faĂte ich mir schlieĂlich ein Herz und griff zum Druckerhandbuch samt Bleistift und Papier. Und siehe da, bald stellte sich heraus, daĂ bei einigermaĂen geschickter Organisation alles nicht einmal halb so schlimm war, wie befĂŒrchtet: Es fing sogar an, SpaĂ zu machen!
Da der Computer auf jeden Fall sehr viel schneller sein wĂŒrde als der Drucker, wurde die Kompaktheit des zu erzeugenden Codes höher bewertet als die reine Ablaufgeschwindigkeit. Der Registersatz des MC68K wurde wie ĂŒblich weitgehend ausgenutzt. FĂŒr Mini- und Midicopy entspricht das Vorgehen im Programm der Beschreibung in dem zitierten Artikel von M. Kraus.
Das Problem, die in den waagerechten Zeilen liegenden Pixel (oder Bits in den Bytes des Bildschirmspeichers) in eine fĂŒr die Beschickung der Druckernadeln notwendige âsenkrechte' Anordnung zu bekommen, wurde mit dem LSL-Befehl gelöst (in der Kernroutine der Minicopy steht add.w d0,d0 statt lsl.w #1,d0, es bewirkt das gleiche, ist nur kĂŒrzer und schneller!). So ergaben sich fĂŒr die Hauptroutine der Minicopy fĂŒnf ineinandergeschachtelte DBF-Schleifen. Das Programm lĂ€uft von oben gleich in die innerste Schleife, wobei die Werte fĂŒr die Auflösung und die Register (SchleifenzĂ€hler) vorbesetzt werden. Hier werden nun die Pixel, der Anzahl der druckenden Nadeln (D2) entsprechend, in D1 akkumuliert, beginnend in der Ă€uĂersten Ecke oben links, im 3-Zeilen-Versatz (âinnerer Bildschirmzeiger' A3), und an den Drucker geschickt. D3 ist der BitzĂ€hler (im Byte), und wenn er heruntergezĂ€hlt ist, muĂ das nĂ€chste Byte geholt werden, das Ganze 80mal (D4), dann ist die oberste Zeile abgegrast (und natĂŒrlich auch acht weitere im 3-Zeilen-Versatz). Jetzt wird ein Mikro-Papiervorschub gemacht, und das Ganze noch zweimal (D5) jeweils eine Zeile tiefer wiederholt. Nun kann nach einem gröĂeren Papiervorschub der âĂ€uĂere Bildschirmzeiger' (A4) entsprechend weiter positioniert werden: Es wird der nĂ€chste Block hereingeholt, Ablauf wie oben, das Ganze insgesamt 16,7mal (D6). Um eine Sonderroutine fĂŒr das letzte BruchstĂŒck zu sparen und dennoch nicht etwa auĂerhalb des Bildschirmspeichers befindliche Daten zu Papier kommen zu lassen, wird einfach in der innersten Schleife abgefragt, ob sich die entsprechende Adresse ĂŒberhaupt noch innerhalb des Bildschirms befindet (Bildschirmendadresse A6). Das geht in âAssembler' so kurz und schnell (4 Byte & 16/18 Taktzyklen), daĂ man es unbeschwert machen kann. Der Druckkopf bewegt sich sowieso nur, wenn es auch etwas zu drucken gibt. Dann noch ein Glocken- oder Piepston, und wir wĂ€ren fertig!
Die Hauptroutine der Midicopy ist ganz analog programmiert, nur daĂ hier das vorher noch freie Register D7 als Schalter benutzt wird, um zwischen den ungeraden und den geraden Nadeln umzuschalten und, falls notwendig, einen zusĂ€tzlichen Papiervorschub auszufĂŒhren. Die Einzelheiten sind hoffentlich recht klar dem im Motorola-Standard gehaltenen Quelltext zu entnehmen.
Das einzige noch nicht genutzte âsichereâ Register ist A5, und das könnte von AS68-Anwendern auf Null gesetzt und zur - fĂŒr diesen verbreiteten Assembler zwecks Optimierung notwendigen - relativen Adressierung der Systemvariablen genutzt werden, so wie es auch im TOS ĂŒblich ist.
Mini- und Midicopy sind, wie ĂŒbrigens auch die Desktop-Hardcopy, in der Höhe um etwa 11% gestreckt, das liegt an der unterschiedlichen horizontalen und vertikalen Schrittweite der 9-Nadler (1/ 240â oder 1/120â bzw. 1/216â oder 1/108 â). Kreise erscheinen also als senkrecht stehende Ellipsen etc.. Nun gibt es aber auch eine Dichte mit gleicher Schrittweite in beiden Richtungen: die (beim NL10) sogenannte Plotterdichte mit 72 dpi, das entspricht genau dem Abstand der Nadeln im Druckkopf! Da ich nun schon einmal dabei war, wurde die âPlotcopyâ auch noch gleich programmiert.
Die Plotcopy muĂ wegen ihrer Abmessungen (ca. 11% lineare VergröĂerung in Bezug auf den Bildschirm) lĂ€ngs aufs DIN A4- Blatt gedruckt werden. Wenn man dabei unten links anfĂ€ngt, braucht man beim Programmieren auch nicht die Bits in den Bytes (diesmal um 180°) zu drehen, sondern kann sich so bedienen, wie es da so schön im Speicher liegt: 80 Reihen zu je 400 Bytes, das geht sogar glatt auf, und so wurde es die kĂŒrzeste der drei Routinen.
Von diesen drei Hardcopy-Routinen wurden die gemeinsamen Teile nun zusammengefaĂt und optimiert, und das Ganze mit einem gemeinsamen Kopf versehen, der u.a. die folgenden Aufgaben zu erfĂŒllen hat:
- Identifikations-ASCII-String vor dem Einstieg bereitstellen
- wenn kein monochromer Grafikmodus, Programm verlassen. (Falls der Grafikmodus ohne Reset gewechselt wurde! Wie sinnvoll so etwas ist, kann ich nicht beurteilen, aber es gibt ja inzwischen diese Umschalter.)
- savptr retten und Platz fĂŒr BIOS-Stack zuweisen
- wenn Drucker nicht bereit, Programm verlassen
- Bildschirmadresse feststellen
- feststellen, welche der drei Routinen angewÀhlt ist
Um die Routinen nun auf Tastendruck jederzeit abrufbar zur VerfĂŒgung zu haben, sollte ein VBI (Vertical Blank Interrupt)-Slot belegt werden. Routinen, die so eingebunden sind, werden normalerweise (d.h. wenn sie nicht gerade gesperrt sind) bei jedem VertikalrĂŒcklauf einmal abgearbeitet. Der Prozessor befindet sich dabei im Supervisor-Status, und die Routine muĂ mit RTS beendet werden (fĂŒr Einzelheiten siehe Jankowski/Reschke/Rabich. ATARI ST Profibuch II, S. 177f.).
Um das Programm also dort zu verankern, muĂte folglich ein Lader erstellt werden, der die folgenden Voraussetzungen erfĂŒllen sollte:
- wenn keine 640*400 Auflösung im monochromen Modus, nicht laden
- wenn keine Slots vorhanden, nicht laden. Es wurde darauf verzichtet, welche einzurichten: Da defaultmĂ€Ăig 8 Slots vorhanden sein sollten, muĂ ein anderes Programm nvbls auf Null gesetzt haben
- Wenn keine freien Slots vorhanden, nicht laden. Es wurde darauf verzichtet, die Liste evtl. zu verschieben und neue Slots einzurichten oder sich (inkorrekt!) zusĂ€tzlich in ein Slot âeinzuklinken': Wenn der Zug schon so ĂŒberfĂŒllt ist, wollen wir mal lieber verzichten
- falls Programm schon geladen, nicht nochmals laden, aber Meldung und Bedienungsanleitung ausgeben, sowie auf Taste warten
- falls Programm geladen wird, gleich noch die Gelegenheit beim Schopfe packen und die ALT-HELP Standard-Hardcopy auf Epson-Drucker setzen. Meldung mit Anleitung ausgeben, dabei nicht auf Taste warten: Das Programm ist zum Start aus dem AUTO-Ordner vorgesehen!
- er Lader selbst soll nicht resident gehalten, sondern nach Gebrauch weggeworfen werden
- fĂŒr die FĂ€lle 1. bis 3. Fehlermeldung ausgeben und auf Taste warten, sowie negativen âretcode' an aufrufendes Programm ĂŒbergeben
Die hier geĂŒbte Art der Behandlung der VBI-Slots wurde ĂŒbrigens dem VBI-Handler des Betriebssystems nachempfunden.
Punkt 1. im Pflichtenheft des Laders und Punkt 2. im eigentlichen Programmkopf sind notwendig, weil das Programm nur eine einfache âBit-Ebene' von 640*400 Elementen zum Drucker schaufeln kann: Das wĂŒrde bei einer anderen (mittlerer oder niedriger) Auflösung zur Ausgabe von âDatenschrott' fĂŒhren.
Zur Ermittlung des Grafikmodus' kann man hier direkt die Variable sshiftmd ($44C, sollte 2 sein) auslesen, weil sich der Prozessor ohnehin im Supervisormodus befindet. Das geht schneller und ist kĂŒrzer als der Aufruf der XBIOS-Funktion #4 Getrez, die ĂŒbrigens auch nichts anderes tut. Doch da stellt sich nun folgendes Problem:
Was die hohe Auflösung betrifft, so gibt es ja neuerdings auch andere als die in der ATARI-Originaldokumentation erwĂ€hnten 640400 Pixel, z.B. 1280960 Pixel beim AnschluĂ eines Matscreen / M110 GroĂbild-Monitors. In GEM-Programmen ist dies kein Problem, da man die entsprechenden Parameter der Screen-Workstation ja leicht abfragen kann. In TOS-Programmen kann man sich mit der Abfrage dreier sog. Line-A- oder VDI-ESC-Variablen behelfen (Jankowski et al., op. cit., S.224 ff.). Also in âAssembler' etwa so:
Abfrage auf BildschirmgröĂe 640*400 Pixel, monochrom
dc.w $A000 ; Line-A Basisadresse holen
cmpi.w #1,(a0) ; Anz. der Bildschirmebenen = 1 ?
bne out ;nein ? -> raus
cmpi.w #640,-12(a0) ; horizontale Auflösung = 640 ?
bne out ;nein ? -> raus
cmpi.w #400,-4(a0) ; vertikale Auflösung = 400 ?
bne out ;nein ? -> raus
Diese Werte sind erfreulicherweise schon vor der Initialisierung des GEM-AES vorhanden! Also auch beim Start eines Programmes aus dem AUTO-Ordner, ebenfalls beim Start vom COMMAND.PRG aus, wenn dies durch Setzen von _cmdload ($482) aus dem Bootsektor oder aus dem AUTO-Ordner gestartet wurde. Bis ATARI hier selbst einen anderen Vorschlag macht oder eine Variable fĂŒr OEM-Auflösung deklariert, sollte man diese Möglichkeit nutzen, um die korrekte, systemkonforme Programmierung zu unterstĂŒtzen. Ob man auf die Benutzung der entsprechenden XBIOS-Funktion dann möglicherweise verzichten könnte, ist (auch) eine Frage der Interpretation ihrer Bedeutung: Bezieht sie sich auf die Auflösung in Pixeln (Bildschirmbreite mal -höhe) oder die Anzahl der Bitebenen (1, 2 oder 4 entsprechend monochrom, 4 oder 16 Farben), d.h. die Organisation des Bildschirmspeichers? Den mir bekannten Originaldokumenten ist das nicht explizit zu entnehmen: Damals dachte man wahrscheinlich weder an die Implementierung eines âoffenen Systemsâ (Mega-Bus) noch an die softwaremĂ€Ăige Nutzung anderer als der drei Standardauflösungen. HardwaremĂ€Ăige Ăberlegungen jedoch, sowie die Analyse der entsprechenden Routinen des Betriebssystems lassen den SchluĂ zu, daĂ man âGetrezâ besser in âGetshiftmdâ umbenennen und dann auch in diesem Sinne verwenden sollte [Hierzu siehe auch: Jankowski et al., op. cit., S.664 ff., Julian Reschke, Der weiche GroĂbildschirm, ST Magazin (M&T) 11188, S.76f und Arnd Beissner, Höhere Auflösung -mehr Farben, dgl. 12/88, S. 158f.]
Bliebe noch das Problem des nicht wiedereintrittsfĂ€higen BIOS/XBIOS- Traphandlers zu erklĂ€ren: Falls man aus dem Interrupt BIOS/XBIOS-Funktionen aufrufen möchte, muĂ man zuvor den âBIOS save areaâ-Vektor savptr ($4A2) umsetzen und einen neuen BIOS-Stackbereich einrichten: FĂŒr einfache Tiefe genĂŒgen 46 Bytes - 10 Register, PC & SR - bei erwarteter tieferer Rekursion entsprechend mehr (siehe dazu auch Kramer et al.. Das TOS-Listing, S.22 ff. & S.84 und Alex Esser, Die System-Variablen des TOS, Teil 2, ST Computer 12/88, S.126 ff.). Nach Ablauf der Routine wird dann alles wieder in den alten Zustand zurĂŒckversetzt.
Was die Shift-Tastenkombinationen betrifft, die ich hier gewĂ€hlt habe, um die verschiedenen Hardcopies auszulösen, so kann sich das ja ein jeder so zusammenstellen, daĂ es bei ihm nicht mit anderen Anwendungen kollidiert. Auch Kombinationen mit anderen ârichtigenâ Tasten sind natĂŒrlich denkbar, dann wird die Programmierung der Abfrage allerdings etwas aufwendiger. Man könnte die Routinen natĂŒrlich auch auf ganz andere Weise laden, sie z.B. in den scr_dump ($502) einklinken, dort eine Abfrage mit Verzweigung und evtl. eine Möglichkeit zum Abbruch vorsehen etc. p.p....
In der Praxis erweist es sich als angenehm, daĂ das Programm sofort zurĂŒckkehrt, wenn der Drucker nicht aufnahmebereit ist. Es wird erst dann die ĂŒbliche halbe Minute gewartet, wenn die Ausgabe bereits begonnen hat und man danach den Drucker âofflineâ schaltet.
Wem das nicht gefÀllt, der kann die Funktion bcostat ja herausnehmen.
Was die QualitĂ€t des Ausdrucks betrifft, so ist Minicopy (4-fache Dichte) gut fĂŒr Strichzeichnungen bzw. Text geeignet (ich habe z.B. zum SpaĂ den Quelltext des Programms damit ausgedruckt, das war recht scharf und gut lesbar!). Gerastertes Grau hingegen, wie z.B. der Desktop-Hintergrund, lĂ€uft ziemlich zu, es sei denn, man hielte ein gut âausgelutschtesâ Farbband bereit, was zu diesem Zweck sowieso vorzuziehen ist. Damit könnte man sich dann z.B. einen netten Bilderkatalog drucken. Midicopy (2fache Dichte) eignet sich auch oder gerade mit etwas frischerem Farbband fĂŒr gut abgestufte Rasterbilder und schöne StrichschwĂ€rze, wĂ€hrend man bei Plotcopy (Plotterdichte) auch schon die dichtgepackten Punkte einzeln erkennen kann und deshalb hier nur ein gutes Farbband zu empfehlen ist. Hier hat man gegenĂŒber der Standard-Hardcopy jedoch den Vorteil der Aspekttreue (d.h. gleiches VerhĂ€ltnis Breite/Höhe), und daĂ wieder jedem Pixel ein Punkt auf dem Papier entspricht.
Absichtlich habe ich darauf verzichtet, die Routinen mit Kinkerlitzchen wie z.B. Einstellen des linken Randes, diversen PapiervorschĂŒben, Formfeeds etc. auszustatten, das sollte sich jeder nach seinem Gusto einrichten. Es kam mir hier nur darauf an, die - bei Wahrung der Ăbersichtlichkeit - hochoptimierten Kernroutinen und beispielhaft die korrekte Einbindung einer VBI-Slot-Routine mit Betriebssystemaufrufen sowie die exakte Abfrage auf die aktuelle BildschirmgröĂe in TOS-Programmen zu demonstrieren, der Rest ist mehr oder weniger beliebig.
* --------------------------------------------------
* SCRNCOPY.S VBI-Slot residente 3-fach Hardcopy-Routine fĂŒr STAR-NL10
* & andere EPSON-FX80 kompatible Drucker © MAXON Computer GmbH br 15.2.89
* ----â---------------------------------------------
start: bra install ; -> Installation
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ----â---------------------------------------------
* residente Routine
* --------------------------------------------------
dc.l 'SCRN' ;Programmidentifikation
dc.l 'COPY' ;desgleichen
begin: cmpi.b #2,$44C ;sshiftmd=monochr?
bne.s out ;nein ? -> raus
move.l $4A2,savptr ;BIOS save area retten
move.l #savptr,$4A2;neuen BIOS-Stack besorgen
clr.w -(sp) ;PRT
move.w #8,-(sp) ;Bcostat
trap #13 ;BIOS
addq.l #4,sp ;SP restaurieren
tst.w d0 ;Drucker bereit?
beq.s getout ;nein ? -> raus
move.l $44E,a4 ;_v_bas_ad= Screenadresse
move.l a4,a6
lea 31999(a6),a6;letztes Byte des Bildschirms
status: move.w #-1,-(sp) ;mode: Status abfragen
move.w #$B,-(sp) ;Kbshift
trap #$D ;BIOS
addq.l #4,sp ;SP restaurieren
andi.b #$F,d0 ;obere 4 Bits ausmaskieren
cmpi.b #5,d0 ;SHIFT R - CTRL?
beq.s minicop ;-> Minicopy
cmpi.b #3,d0 ;SHIFT R-SHIFT L?
beq midicop ;-> Midicopy
cmpi.b #9,d0 ;SHIFT R - ALT?
beq plotcop ;-> Plotcopy
getout: move.l savptr(pc),$4A2 ;BIOS save area zurĂŒckschreiben
out: rts
* -----------------------â-----------------------â--
* gemeinsame Variablen & Unterroutinen
* -----------------------â-----------------------â--
resolve: dc.w 0 ;
n1bytes: dc.w 0 ;in grafmod ben.
n2bytes: dc.w 0 ;
* -----------------------â-----------------------â--
grafmod: moveq #27,d0 ;ESC
bsr.s bconout ;zum Drucker
moveq #42,d0 ;'*' = Grafikmodus
bsr.s bconout ;zum Drucker
move.w resolve(pc),d0 ;n0 = Grafik-Auflösung
bsr.s bconout ;zum Drucker
move.w n1bytes(pc),d0 ;n1: siehe n2
bsr.s bconout ;zum Drucker
move.w n2bytes(pc),d0 ;n2: n1+256*n2 = Anzahl Bytes
bra.s bconout ;zum Drucker
papfeed: moveq #27,d0 ;ESC
bsr.s bconout ;zum Drucker
moveq #74,d0 ;'J'=n/216" feed
bsr.s bconout ;zum Drucker
move.w d3,d0 ;n
bsr.s bconout ;zum Drucker
moveq #13,d0 ;CR
bconout: move.w d0,-(sp) ;char
clr.w -(sp) ;dev = PRT
move.w #3,-(sp) ;Bconout
trap #13 ;BIOS
addq.l #6,sp ;SP restaurieren
rts
* -----------------------â-----------------------â--
* + + + + + + + + + + + + Hauptroutine Minicopy
* -----------------------â-----------------------â--
minicop: move.w #3,resolve ;n0 = Auflösung = 240 dpi
move.w #128,n1bytes;n1 = 128
move.w #2,n2bytes ;n1+n2*256=640 Bytes senden
moveq #16,d6 ;Anzahl Blöcke (17)
nex1bloc: moveq #2,d5 ;Anzahl Microfeed-Zeilen = 3
nex1row: moveq #79,d4 ;Anzahl Bytes in Zeile = 80
bsr grafmod ;Grafikmodus einschalten
nex1byte: moveq #7,d3 ;Anzahl Bits im Byte = 8
get1col: moveq #7,d2 ;Anzahl druckender Nadeln = 8
moveq #0,d0 ;fĂŒr das zu druckende Byte lösch,
move.l a4,a3 ;Bildschirmzeiger setzen
get1pix: add.w d0,d0 ;1 Bit nach links schieben
move.b (a3),d1 ;Byte holen
btst d3,d1 ;Bitnummer im Byte
beq.s no1set ;0 ? -> weiter
cmpa.l a6,a3 ;Ende des Bildsch.
bgt.s no1set ;nicht im Bereich? -> weiter
addq.w #1,d0 ;letztes Bit setzen &
no1set: lea 240(a3),a3 ;3 Zeilen vorrĂŒcken
dbf d2,get1pix ;8 mal fĂŒr 8 Nadeln
bsr bconout ;fertiges Byte in D0 zum Drucker
dbf d3,get1col ;8 mal fĂŒr 8 Bits pro Byte
addq.l #1,a4 ;nÀchstes Byte in Bildschirmzeile
dbf d4,nexlbyte ;80 mal fĂŒr 80 Bytes pro Zeile
moveq #1,d3 ;1/216" Micro-
bsr papfeed ;Papiervorschub
dbf d5,nex1row ;nÀchste Zeile von 80 Bytes
lea 1680(a4),a4 ;zum nÀchsten Block
moveq #21,d3 ;21/216"
bsr papfeed ;groĂer Vorschub
dbf d6,nex1bloc ;17 mal das Ganze fĂŒr Bildschirm
moveq #7,d0 ;BEL
bsr bconout ;zum Drucker
bra getout ;fertig
* -----------------------â-----------------------â--
* + + + + + + + + + + + + Hauptroutine Midicopy
* -----------------------â-----------------------â--
midicop: move.w #1,resolve ;n0 = Auflösung = 120 dpi
move.w #128,n1bytes;n1 = 128
move.w #2,n2bytes ;+2*256=640 Bytes senden
moveq #0,d7 ;D7 als Schalter
moveq #33,d6 ;Anzahl Blöcke(34)
nex2bloc: not.w d7 ;D7 umschalten
moveq #2,d5 ;Anzahl Microfeed-Zeilen = 3
nex2row: moveq #79,d4 ;Anzahl Bytes in Zeile = 80
bsr grafmod ;Grafikmodus einschalten
nex2byte: moveq #7,d3 ;Anzahl Bits im Byte = 8
get2col: moveq #3,d2 ;Anzahl druckender Nadeln = 4
moveq #0,d0 ;fĂŒr das zu druckende Byte lösch.
move.l a4,a3 ;Bildschirmzeiger initialisieren
get2pix: lsl.w #2,d0 ;2 bit schieben Nadeln 6,4,2,0
move.b (a3),d1 ;Byte holen
btst d3,d1 ;Bitnummer im Byte
beq.s no2set ;0 ? -> nÀchstes Pixel
cmpa.l a6,a3 ;Ende des Bildschirms - 1 ?
bgt.s no2set ;nicht im Bereich? -> weiter
addq.w #1,d0 ;letztes Bit setzen &
no2set: lea 240(a3),a3 ;3 Zeilen vor
dbf d2,get2pix ;4 mal fĂŒr 4 Nadeln
tst.w d7 ;gesetzt ?
beq.s output ;nein ? -> Nadeln 6,4,2,0
add.w d0,d0 ;1 bit schieben Nadeln 7,5,3,1
output: bsr bconout ;fertiges Byte zum Drucker (D0)
dbf d3,get2col ;8 mal fĂŒr 8 Bits im Byte
addq.l #1,a4 ;1 Byte vor
dbf d4,nex2byte ;80 mal fĂŒr die Zeile
moveq #2,d3 ;2/216" Micro-
bsr papfeed ;Papiervorschub
dbf d5,nex2row ;nÀchste Zeile von 80 bytes
lea 720(a4),a4 ;zum nÀchsten Blk.
tst.w d7 ;gesetzt ?
bne.s short ;ja ? -> benutzte Nadeln 7,5,3,1
moveq #6,d3 ;6/216"
bsr papfeed ;Zusatzvorschub beim Nadelwechsel
short: moveq #15,d3 ;15/216" | gerade -> ungerade
bsr papfeed ;groĂer Papiervorschub
dbf d6,nex2bloc ;34 mal die ganze Geschichte
moveq #7,d0 ;BEL
bsr bconout ;zum Drucker
bra getout ;na endlich
* -----------------------â-----------------------â--
* + + + + + + + + + + + + Hauptroutine Plotcopy
* -----------------------â-----------------------â--
plotcop: move.w #5,resolve ;n0 = Auflösung 72 dots per inch
move.w #144,n1bytes ;n1 = 144
move.w #1,n2bytes ;n1+n2*256=400 Bytes senden
movea.l a6,a3 ;letztes Byte des Bildschirms
addq.l #1,a3 ;+1:gerade drauĂen
moveq #79,d5 ;Anzahl (senkr.) Bytereihen
getrow: move.w #399,d4 ;Anzahl Bytes in einer Reihe
bsr grafmod ;Grafikmodus einschalten
getbyte: lea -80(a3),a3 ;nÀchstes Byte
move.b (a3),d0 ;Beginn in linker unterer Ecke
bsr bconout ;zum Drucker
dbf d4,getbyte ;400 mal=1(senkr.) Reihe waagerecht
;aufs Papier drucken
lea 32001(a3),a3;nÀchste Reihe ansteuern
moveq #24,d3 ;24/216" = 8/72"
bsr papfeed ;Papiervorschub
dbf d5,getrow ;80 Reihen a 400 Bytes = Bildsch.
moveq #7,d0 ;BEL
bsr bconout ;zum Drucker
bra getout ;das war's
* -----------------------â-----------------------â--
filler: dc.l 0,0,0,0,0,0,0,0,0,0,0,0 ;neuer BIOS-Stack Bereich (12 .L)
savptr: dc.l 0 ;alte BIOS save area Adresse
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* -----------------------â-----------------------â--
* Installlationsroutine
* -----------------------â-----------------------â--
install: clr.l -(sp) ;stack->superstack
move.w #$20,-(sp) ;Super
trap #1 ;GEMDOS
addq.l #6,sp ;SP restaurieren
move.l d0,-(sp) ;alten SSP auf den Stack retten
dc.w $A000 ;Line-A Basisadresse holen
cmpi.w #1,(a0) ;Anzahl der Bildschirmebenen=1?
bne out ;nein ? -> raus
cmpi.w #640,-12(a0);horizontale Auflösung=640?
bne out ;nein ? -> raus
cmpi.w #400,-4(a0) ;vertikale Auflösung=400?
bne out ;nein ? -> raus
move.w $454,d6 ;nvbls
beq noslot ;kein Slot da? -> raus
subq.l #2,d6 ;ZĂ€hler fĂŒr dbf Schleife
movea.l $456,a0 ;_vblqueue
addq.l #4,a0 ;erstes Slot auslassen (VDI)
getslot: movea.l (a0)+,a1 ;Eintrag holen
cmpa.l #0,a1 ;steht was drin?
beq.s action ;nichts da? -> installieren!
cmpi.l #$5343524E,-8(a1) ; 'SCRN' schon da ?
bne.s again ;nein -> weiter
cmpi.l #$434F5059,-4(a1) ;'COPY' ?
beq.s donot ;schon da? -> laĂ es!
again: dbf d6,getslot ;nÀchstes Slot
bra.s noslot ;kein freies Slot mehr da !
* -----------------------â-----------------------â--
action: lea begin(pc),a1;Startadresse des residenten Teils
move.l a1,-4(a0) ;ins VBI-Slot eintragen
move.w #$20,-(sp) ;Super->User (SSP auf dem Stack!)
trap #1 ;GEMDOS
addq.l #6,sp ;SP restaurieren
move.w #4,-(sp) ;Epson-Drucker
move.w #$21,-(sp) ;Setprt
trap #14 ;XBIOS
addq.l #4,sp ;SP restaurieren
pea string1(pc) ;Meldung und Anleitung zeigen
move #9,-(sp) ;Cconws
trap #1 ;GEMDOS
addq.l #6,sp ;SP restaurieren
lea start(pc),a0;halte Code von hier
lea install(pc),a1 ;bis zu dieser Marke
suba.l a0,a1 ;Rest wegwerfen
lea $100(a1),a1 ;fĂŒr die Basepage
clr.w -(sp) ;retcode=0
move.l a1,-(sp) ;keep: Anzahl von Bytes v. p_lowtpa
move.w #$31,-(sp) ;Ptermres
trap #1 ;GEMDOS
* -----------------------â-----------------------â--
donot: move.w #$20,-(sp) ;Super->User (SSP auf dem Stack!)
trap #1 ;GEMDOS
addq.l #6,sp ;SP restaurieren
pea string1(pc) ;Meldung und Anleitung zeigen
move #9,-(sp) ;Cconws
trap #1 ;GEMDOS
addq.l #6,sp ;SP restaurieren
move.w #7,-(sp) ;Crawcin: auf Taste warten
trap #1 ;GEMDOS
clr.w -(sp) ;Pterm0
trap #1 ;GEMDOS
* -----------------------â-----------------------â--
noslot: move.w #$20,-(sp) ;Super->User (SSP auf dem Stack!)
trap #1 ;GEMDOS
addq.l #6,sp ;SP restaurieren
pea string2(pc) ;Fehlermeldung
move #9,-(sp) ;Cconws
trap #1 ;GEMDOS
addq.l #6,sp ;SP restaurieren
move.w #7,-(sp) ;Crawcin: auf Taste warten
trap #1 ;GEMDOS
addq.l #2,sp ;SP restaurieren
move.w #-1,-(sp) ;retcode-1:Fehler!
move.w #$4C,-(sp) ;Pterm()
trap #1 ;GEMDOS
* -----------------------â-----------------------â--
string1: dc.b 27,'v',13,10
dc.b '3-fach Hardcopy (9N) pd by br 0 2/89 |'
dc.b ' RSHFT-CTRL -> Minicopy ~ 6,8 * 4,7 cm2',13
dc.b 'RSHFT-ALT-> Plotcopy ~ 22,6 * 14, 1 cm2|'
dc.b ' RSHFT-LSHFT -> Midicopy ~ 13,6 * 9,4 cm2',13,10,7,0
string2: dc.b 13,10,'SCRNCOPY nicht installiert! [Taste] ',13,10,7,0
* -----------------------â-----------------------â--