Hardcopy Quer

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


Aus: ST-Computer 01 / 1987, Seite 58

Links

Copyright-Bestimmungen: siehe Über diese Seite