← ST-Computer 09 / 1989

Residente 3fach-Hardcopy fĂŒr 9-Nadeldrucker

Programmierpraxis

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:

  1. Identifikations-ASCII-String vor dem Einstieg bereitstellen
  2. 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.)
  3. savptr retten und Platz fĂŒr BIOS-Stack zuweisen
  4. wenn Drucker nicht bereit, Programm verlassen
  5. Bildschirmadresse feststellen
  6. 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:

  1. wenn keine 640*400 Auflösung im monochromen Modus, nicht laden
  2. 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
  3. 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
  4. falls Programm schon geladen, nicht nochmals laden, aber Meldung und Bedienungsanleitung ausgeben, sowie auf Taste warten
  5. 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!
  6. er Lader selbst soll nicht resident gehalten, sondern nach Gebrauch weggeworfen werden
  7. 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 * -----------------------—-----------------------—--
Bernd Rosenlecher