← ST-Computer 01 / 1987

Hardcopy Quer

Listing

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 !"