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:
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:
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
* -----------------------—-----------------------—--