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.
Bedienung
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.
Assembler-Listing "HARDCOPY.Sâ:
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
Der Basic Lader "HARDCOPY. BASâ:
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 !"