Dieses Programm bringt Hardcopies im Querformat (wie DEGAS) zu Papier und nutzt die gesamte Papierbreite. Es wird durch ’AI-ternate +Help’ gestartet und ist jederzeit aufrufbar.
Die Fähigkeit der Hardcopy ist eine äußerst wichtige Eigenschaft des ST. Leider ist sie nicht bei allen Druckern anwendbar, da nicht alle Drucker auf dieselben Steuercodes reagieren.
Oft fällt der große Begriff ’EPSON-Kompatibel’ auf, der verdeutlichen soll, daß ein solcher Drucker problemlos arbeitet. Allzuoft zeigt sich aber, daß gerade bei der Hardcopy trotzdem irgendetwas nicht geht - meist der Zeilenvorschub, der etwas zu groß oder viel zu klein ist. Sogar bei Epson-Druckern (LQ 800) stimmt er nicht. Hier hilft meist nur ein eigenes Treiberprogramm. ’Hardcopy Quer’ ist zwar auf einen Druckertyp zugeschnitten, kann aber durch Änderung der Steuercodes an jeden Drucker angepaßt werden. Diese Steuercodes sind sowohl beim Assemblerprogramm als auch beim zugehörigen Basiclader leicht sichtbar und nach einem Blick in das Druckerhandbuch für die eigenen Bedürfnisse abänderbar. Eine äußerst wichtige Eigenschaft dieses Treibers ist, daß er, wie die normale Hardcopy auch, durch Drücken von ALTERNATE + HELP ausgelöst wird und somit ständig zur Verfügung steht.
Das Programm wird vom Desktop aus gestartet und kehrt sofort zu ihm zurück. Von jetzt an wird die neue Hardcopyroutine benutzt, die folgendermaßen bedient wird:
ALTERNATE/HELP, beliebige Taste außer ”2” und ”3”: Hardcopy im Querformat (576 Punkte Grafik)
ALTERNATE/HELP, ”2”: Hardcopy im Querformat mit doppeltem (vertikal leicht verschobenem) Anschlag
ALTERNATE/HELP, ”3”: Hardcopy im Querformat mit vierfachem (vertikal und horizontal leicht verschobenem) Anschlag
Der Druckvorgang kann durch nochmaliges Drücken von ALTERNATE/ HELP abgebrochen werden. Außerdem wird das Programm nach 30 Sekunden abgebrochen, falls kein Drucker im ”ON LINE”-Betrieb angeschlossen ist. Eventuelle Änderungen der Druckercodes können im Basic- und Assembler-Listing leicht vorgenommen werden.
Der Quelltext kann direkt mit dem Entwicklungssystem Assembler von DIGITAL RESEARCH assembliert werden. Das Umschreiben auf andere Assembler dürfte keine Probleme bereiten. Ich will hier näher auf das Listing eingehen:
Zuerst gehe ich mit der GEMDOS-Funktion 32 in den Supervisor Modus und rette anschließend den alten Supervisor Stackpointer nach d6. Danach hole ich mir mit der XBIOS Funktion 2 die physikalische Bildschirmadresse und bringe sie in a0. Wenn ich nun $7d00 addiere, zeigt a0 genau hinter das Video Ram. Diesen Wert rette ich nach a2. Danach kopiere ich das eigentliche Hardcopy Programm (das bei ”start” beginnt und bei ”ende” aufhört) hinter das Video-Ram. Dort befinden sich 768 unbenutzte Bytes, die auch erhalten bleiben. Steht unser Programm dort, können wir zu jeder Zeit und von jedem Programm aus (das natürlich nicht die 768 Bytes benutzt oder unseren Interrupt sperrt Hardcopys machen. Weiter zum Programm: Speicherstelle $456 zeigt auf eine Liste von Vektoren, die nach einem VBL-Interrupt (Bildrücklauf) angesprungen werden. Ich lade ihren Inhalt nach a0 (das geht nur im Supervisor Modus), zähle 28 dazu (also zeigt a0 jetzt auf den achten Vektor, der auf die alte Hardcopy-Routine zeigt) und ersetze den alten Vektor durch meinen neuen. Nun packe ich den geretteten Stackpointer auf den Stack und gehe wieder in den User Modus. Bei ”start” beginnt das eigentliche Hardcopyprogramm. Zuerst teste ich die Speicherstelle $4ee, die bei gleichzeitigem Drücken von ALTERNATE und HELP um eins erhöht wird. Bei einem Wert gleich Null soll eine Hardcopy gemacht werden, sonst mit RTS zum Aufruferprogramm zurückgesprungen werden. Weiter geht’s mit ”copy”. Mit der XBIOS Funktion 14 hole ich mir die physikalische Bildschirmadresse und rette sie nach ”screen”. Die GEMDOS Funktion 7 wartet auf einen Tastendruck und liefert den ASCII-Wert im untersten Byte von d0. Jetzt werden noch ”doppelx” und ”doppely” auf Null gesetzt. Nun wird d0 auf ”2” oder ”3” getestet und die entsprechenden Werte in ”doppelx” und ”doppely” gebracht.
Bei ”_in” geht’s nun richtig los. d6 ist der Spaltenzähler. Da ein Bildschirm aus 80 Spalten à 400 Bytes besteht, wird d6 mit Spalten -1 = 79 geladen. An dieser Stelle möchte ich kurz die kleinen Unterprogramme erklären, da eine weitere Programmbeschreibung vielleicht verwirrend sein könnte.
out:
Ein Zeichen in d3 wird mit der GEMDOS Funktion 5 an den Drucker ausgegeben. Wenn alles glatt lief (d0 = -1), rts, sonst Rücksprung zum Aufruferprogramm. (Da sich ”out” in der zweiten Unterprogrammverschachtelung befindet, einfach 2^4 = 8 zum Stack addieren). Das geschieht z. B., wenn kein Drucker im ”ON LINE”-Modus angeschlossen ist, da die Funktion dann nach 30 Sekunden den Wert 0 in d0 liefert.
gr_inl:
Der Code, auf den a2 zeigt, wird byteweise ausgegeben, bis (a2) = 255 ($FF) ist.
gra_in,pix_vor,klein,gross:
Übergeben graf_on,gpix_vor,kl_linef,gr_linef (die den Blöcken 1 - 4 im Basic-Listing entsprechen) an gr_inl.
spalte:
Eine Spalte (= 400 Bytes) wird von "unten” nach "oben” ausgegeben. d4 ist der Bytezähler. Da sich a5 am Ende "ganz oben” in einer Spalte befindet, muß 32 001 addiert werden, um auf das "unterste” Byte der nächsten Spalte zu kommen. Da ja eine Bildschirmzeile bekanntlich aus 80 Bytes besteht, wird von a5 bei jedem Durchlauf 80 abgezogen.
exit:
In die Speicherstelle $4ee wird -1 gepackt, damit beim nächsten Drücken von ALT/HELP wieder eine Hardcopy ausgelöst wird. Danach wird noch ”exit” (entspricht Block 5 im Basic-Listing) an gr_inl übergeben und mit dem letzten RTS ins Aufruferprogramm gesprungen.
So, jetzt geht’s endlich weiter im Hauptprogramm und zwar bei ”10”. Nachdem die erste Spalte gedruckt wurde, wird "doppely” auf Null geprüft. Bei ungleich Null wird einfach eine Spalte zurückgegangen, indem 1 von a5 abgezogen wird, und die Ausgangsspalte leicht verschoben (wegen ”pix_vor”) noch einmal gedruckt.
Bei ”101” wiederholt sich das ganze mit "doppelx”. (Mit "klein” wird ein 1/216 Inch Zeilenvorschub ausgeführt). Weiter geht’s mit ”103”. Da jetzt die Spalte auf jeden Fall fertig ist, wird mit "gross” ein 24/216 Inch-Zeilenvorschub ausgeführt. Nun wird noch getestet, ob ALT/HELP zum zweiten Mal gedrückt wurde. In diesem Fall wird die Hardcopy vorzeitig beendet ("exit”), andernfalls wird die Schleife solange durchlaufen, bis die Hardcopy ausgegeben wurde.
********************
* HARDCOPY *
* Kai Toedter 1986 *
********************
begin: clr.l -(sp)
move #32,-(sp) * Supervisor mode
trap #1
addq.l #6,sp
move.l d0,d6 * alter stack
move #2,-(sp) * phys_base
trap #14
addq.l #2,sp
movea.l d0,a0 * Programm hinters Video Ram
adda #$7d00,a0 * kopieren
lea (a0),a2
lea start,a1
move.l #ende-start-1,d0
loop: move.b (a1)+,(a0)+
dbra d0,loop
movea.l $456,a0 * _vblqueue
adda #28,a0
move.l a2,(a0) * neuer Vector
move.l d6,-(sp) * alter stack
move #32,-(sp) * user mode
trap #1
addq.l #6,sp
clr.l -(sp)
trap #1
start: tst $4ee * pflag
beq copy
rts
copy: move #2,-(sp) * phys_base
trap #14
addq.l #2,sp
move.l d0,screen
char_in: move #7,-(sp) * direct con without echo
trap #1
addq.l #2,sp
move #0,doppelx
move #0,doppely
cmpi.b #"2",d0
bne tstl
move #1,doppelx
bra _in
tst1: cmpi.b #"3",d0
bne _in move #1,doppely
move #1,doppelx
_in: move.1 #79,d6
movea.l screen,a5
suba.l #81,a5
lo: jsr spalte
cmpi #0,doppely
beq lo1
sub.l #1,a5
jsr pix_vor
jsr spalte
lo1: cmpi #0,doppelx
beq lo3
jsr klein
sub.l #1,a5
jsr spalte
cmpi #0,doppely
beq lo3
sub.l #1,a5
jsr pix_vor
jsr spalte
lo3: jsr gross
tst $4ee
bne exit
dbra d6,lo
exit: move #-1,$4ee * Hardcopy fertig
move.l #4,d1
lea _exit(pc),a2
bra gr_inl
spalte: adda.l #32001,a5 * eine der 80 Spalten drucken
move.l #399,d4 * 400 horizontale Bytes
jsr gra_in
spa_l: clr d3
move.b (a5),d3
suba.l #80,a5
jsr out
dbra d4,spa_l
rts
out: move d3,-(sp) * Zeichen in d3 an Drucker ausgeben
move #5,-(sp)
trap #1
addq.l #4,sp
tst d0
bne out_ok
addq.l #8,sp
out_ok: rts
gra_in: lea graf_on(pc),a2
gr_inl: move.b (a2)+,d3 * Den jeweiligen Code an Drucker
cmpi.b #255,d3 * ausgeben
beq gr_ex
jsr out
bra gr_dn1
gr_ex: rts
pix_vor: lea gpix_vor(pc),a2
bra gr_inl
klein: lea kl_linef(pc) ,a2
bra gr_inl
gross: lea gr_linef(pc) ,a2
bra gr_inl
*****************************************************************************
* Druckercodes und Daten. Die Druckercode* werden mit "255" auf 9 Byte Laenge *
* aufgefuellt, damit sie im Basic-Listing leichter geaendert werden koennen. *
*******************************************************************************
doppelx: .dc.w 0 * X-Verdopplung
doppely: .dc.w 0 * Y-Verdopplung
screen: .dc.l 1 * phys. Bildschirmadr.
graf_on: .dc.b 13,27,42,5,144,1,255,255,255 * CR+ 576 Grafik
gpix_vor: .dc.b 13,27,42,1,1,0,0,255,255 * CR+ 960 Grafik
kl_linef: .dc.b 27,51,1,10,255,255,255,255,255 * LINE FEED 1/216 Inch
gr_linef: .dc.b 27,51,24,10,255,255,255,255,255 * LINE FEED 24/216 Inch
_exit: .dc.b 13,10,27,65,12,255,255,255 * CR+LF+LF=l/6 Inch
ende: .dc.b 255
.end
Wird das Programm nach dem Eintippen mit "RUN” gestartet und es erscheint "Alles klar” im OUTPUT-Fenster, so wurde das Programm "HARDCOPY” auf Diskette erzeugt, das ganz normal mit Doppelklick gestartet werden kann. Erscheint "Data Fehler !”, so befindet sich ein Tippfehler in einer der Data-Zeilen.
Nach dem Programmcode kommen 5 Blöcke Druckercodes. Jeder dieser Blöcke muß immer aus genau neun Bytes bestehen. Wenn der jeweilige Druckercode aus weniger als neun Bytes besteht, muß der Block mit ”FF”s auf neun Byte aufgefüllt werden. Dabei ist zu beachten, daß das neunte Byte immer ein ”FF” ,sein muß. Der eigentliche Druckercode kann also aus maximal acht Bytes bestehen.
Block 1
besteht aus einem CR (CARRIAGE RETURN = Wagenrücklauf) und einer Sequenz, die den Drucker darauf vorbereitet, 400 Bytes in 576 Punkte Grafik auszugeben, bei der bei den meisten Druckern ein horizontales/ vertikales Verhältnis von 1/1 besteht. Wenn die Hardcopy vertikal gestaucht werden soll, kann die Sequenz z. B. in 640 Punkte Grafik umgeändert werden.
Block 2
wird nur bei vertikaler Verdoppelung (Modus 2 und 3) benutzt. In diesem Fall wird ein ”0” Byte in 960 Punkte Grafik gedruckt, so daß eine leichte vertikale Verschiebung bei der fertigen Hardcopy auftritt.
Block 3
wird nur bei horizontaler Verdoppelung (Modus 3) benutzt. Er besteht aus der Sequenz für die Umstellung des Zeilenvorschubs (LF = LINE FEED) auf 1/216 Inch.
Block 4
besteht aus einem CR und der Umstellung des Zeilenvorschubs auf 24/216 Inch. Dies ist im Programm der Abstand zwischen zwei Druckzeilen. Beim SEIKOSHA SP-800 stimmt dieser Wert, bei anderen Druckertypen muß er eventuell geändert werden.
Block 5
wird bei Beendigung oder beim Abbruch der Hardcopy benutzt. Er besteht aus einem CR, einem LF sowie der Umstellung auf den üblichen Zeilenvorschub von 1/6 Inch.
Kai Tödter
10 ' *********************
20 ' * HARDCOPY 3 *
30 ' * Kai Toedter 1986 *
40 ' *********************
50 '
60 open "R",1,"HARDCOPY.PRG",16
70 field#1,16 as b$
80 a$=""
90 for n=1 to 16: read d$: if d$="x" then 590
100 z=val("&H"+d$): a$=a$+chr$(z): sum=sum+z: next n
110 lset b$=a$: c=c+1: put 1,c: goto 80
120 '
130 data 60,1A,00,00,01,90,00,00,00,00,00,00,00,00,00,00
140 data 00,00,00,00,00,00,00,00,00,00,00,00,42,A7,3F,3C
150 data 00,20,4E,41,5C,8F,2C,00,3F,3C,00,02,4E,4E,54,8F
160 data 20,40,D0,FC,7D,00,45,D0,43,F9,00,00,00,48,20,3C
170 data 00,00,01,45,10,D9,51,C8,FF,FC,20,79,00,00,04,56
180 data D0,FC,00,1C,20,8A,2F,06,3F,3C,00,20,4E,41,5C,8F
190 data 42,A7,4E,41,4A,79,00,00,04,EE,67,02,4E,75,3F,3C
200 data 00,02,4E,4E,54,8F,23,C0,00,00,01,5E,3F,3C,00,07
210 data 4E,41,54,8F,33,FC,00,00,00,00,01,5A,33,FC,00,00
220 data 00,00,01,5C,0C,00,00,32,66,0A,33,FC,00,01,00,00
230 data 01,5A,60,16,0C,00,00,33,66,10,33,FC,00,01,00,00
240 data 01,5C,33,FC,00,01,00,00,01,5A,7C,4F,2A,79,00,00
250 data 01,5E,9B,FC,00,00,00,51,61,56,0C,79,00,00,00,00
260 data 01,5C,67,08,53,8D,61,00,00,8C,61,44,0C,79,00,00
270 data 00,00,01,5A,67,1A,61,00,00,82,53,8D,61,32,0C,79
280 data 00,00,00,00,01,5C,67,08,53,8D,61,00,00,68,61,20
290 data 61,00,00,6E,4A,79,00,00,04,EE,66,04,51,CE,FF,BA
300 data 33,FC,FF,FF,00,00,04,EE,72,04,45,FA,00,86,60,36
310 data DB,FC,00,00,7D,01,28,3C,00,00,01,8F,61,24,42,43
320 data 16,15,9B,FC,00,00,00,50,61,06,51,CC,FF,F2,4E,75
330 data 3F,03,3F,3C,00,05,4E,41,58,8F,4A,40,66,02,50,8F
340 data 4E,75,45,FA,00,2A,16,1A,0C,03,00,FF,67,04,61,E0
350 data 60,F4,4E,75,45,FA,00,21,60,EC,45,FA,00,24,60,E6
360 data 45,FA,00,27,60,E0,00,00,00,00,00,00,00,01
370 '
380 ' Die Druckercodes muessen mit "FF" auf eine Laenge
390 ' von 9 Bytes aufgefuellt werden !
400 ' ( CR= CARRIAGE RETURN, LF= LINE FEED )
410 '
420 ' Block 1 : 400 Bytes in 576 Punkte Grafik
430 data 0D,1B,2A,05,90,01,FF,FF,FF
440 '
450 ' Block 2 : 1 "0” Byte in 960 Punkte Grafik
460 data 0D,1B,2A,01,01,00,00,FF,FF
470 '
480 ' Block 3 : LF = 1/216 Inch
490 data 1B,33,01,0A,FF,FF,FF,FF,FF
500 '
510 ' Block 4 : LF = 24/216 Inch
520 data 1B,33,18,0A,FF,FF,FF,FF,FF
530 '
540 ' Block 5 : CR,LF,LF = 1/6 Inch
550 data 0D,0A,1B,41,0C,FF,FF,FF,FF
560 '
570 data 00,00,00,00,1E,3E,10,08,0E,10,08,08,10,12,12,00
580 data 00,00,00,00,00,x
590 close 1
600 if sum <> 31019 then print "Data Fehler !": end
610 print "Alles klar !"