Obwohl beim ATARI ST die hardware-mäßigen Voraussetzungen für eine Druckausgabe parallel zu laufenden Programmen gegeben sind, wurde bei den Betriebssystemroutinen auf diese Möglichkeit verzichtet. Die Folgen sind Ihnen bekannt: Für die Dauer des Ausdruckens einer Hardcopy wird die Arbeit am Computer vollständig blockiert.
Mit der in Assembler geschriebenen Hardcopy-Routine HC-FIX für 24-Nadeldrucker sind diese Zeiten endgültig vorbei. Neben Ausnutzung der maximal möglichen Druckgeschwindigkeit - in Abhängigkeit vom angeschlossenen Drucker - ist die Routine multitaskingfähig, d.h. die Datenausgabe findet im Hintergrund statt.
Wegen der Unzulänglichkeiten der von ATARI vorgegebenen Betriebssystemroutine für die parallele Druckerschnittstelle entstanden die sogenannten Spooler. Unter einem Spooler versteht man ein Programm, das die Zeichenausgabe zum Drucker zunächst in einen eigenen Puffer (Speicherbereich) umlenkt. Danach zieht es sich in den Hintergrund zurück und füttert den Drucker, während ein anderes Programm gestartet werden bzw. weiterlaufen kann. Mit Hilfe dieses Verfahrens braucht der Anwender nicht zu warten, bis alle Daten an den Drucker übergeben worden sind. Er kann gleich nach der Umlenkung Weiterarbeiten, was bei mittellangen Texten eine beachtliche Zeitersparnis bedeutet. Allerdings ergeben sich bei der Anwendung dieser Methode auf Hardcopies zwei Probleme:
Einerseits fallen bei Grafiken große Datenmengen an. Um nämlich bei 24-Nadeldruckern auf eine Bildgröße von 18 * 11 cm zu kommen, muß man 128 kB Daten an den Drucker senden. Soll die Hardcopy eine DIN A4-Seite füllen, sind es sogar fast 300 kB (80% des Speicherplatzes eines 520 ST). Ein entsprechend großer Spooler-Puffer läßt schnell keinen Platz mehr für eine andere Applikation - es sei denn. Sie sind Besitzer eines Mega-ATARIs und haben genug Speicher.
Andererseits wird die Geschwindigkeit der Zeichenumlenkung in den Puffer von den BIOS-Routinen bestimmt; sie liegt bei ca. 4000 Baud. Selbst ein guter Spooler benötigt für 300 kB Daten mindestens 6 Minuten zur Übernahme.
Während dieser Zeit ist der Rechner blockiert, so daß kein Vorteil gegenüber der normalen Hardcopy entsteht.
Ein Lösungsansatz des Problems findet sich im Kommunikationsprinzip zwischen Rechner und Drucker.
Bei der Datenübermittlung werden außer den acht Datenleitungen ,die den Binärcode des Zeichens übertragen, noch zwei Steuerleitungen, Strobe und Busy, benutzt. Diese Leitungen regeln das Übertragungsprotokoll zwischen Rechner und Peripherie im sogenannten Handshake-Modus. Damit der Drucker nicht wahllos Zeichen einliest, generiert der Computer das Strobe-Signal, das die Gültigkeit der Daten auf den Leitungen anzeigt. Umgekehrt teilt das Ausgabegerät dem Rechner über die Busy-Leitung seine Empfangsbereitschaft mit.
Beim Senden eines Daten-Bytes legt der Computer die Strobe-Leitung kurzzeitig auf Low - das Signal zur Übernahme. Während der Drucker das Zeichen entgegennimmt, setzt er die Busy-Leitung auf High und zeigt damit dem Rechner, daß er beschäftigt ist. Erst mit einem Low-Pegel auf der Leitung kann die Ausgaberoutine das nächste Byte abschicken. Zur Überprüfung des Druckerzustandes gibt es zwei Möglichkeiten:
mittels Software, d.h. die regelmäßige Abfrage des Busy-Signals z.B. in einer Schleife. Diese auch vom Betriebssystem verwendete Methode verbraucht den größten Teil der Rechenzeit - verglichen mit der eigentlichen Übertragung -und sperrt damit den Computer für andere Tätigkeiten.
mittels Hardware durch die Verwendung des Busy-Interrupts. Er wird vom MFP (Multifunktionsbaustein, für Ports zuständig) generiert, der auch bei anderen Ereignissen, wie z.B. Bewegen der Maus oder Tastatureingaben, entsprechende Unterbrechungen des normalen Programmablaufs auslöst. Nun ist der Busy-Interrupt im Normalzustand des Rechners gesperrt, d.h. er wird vom MFP ignoriert. Glücklicherweise kann er softwaremäßig aktiviert werden. Ist das der Fall, überwacht der MFP die Busy-Leitung und erzeugt den Interrupt, sobald ein Pegelwechsel stattgefunden hat. Dieses Verfahren entlastet die CPU und wird auch von HC-FIX benutzt.
Die Grundidee für das neue Hardcopy-Programm war denn auch, es als Interrupt-Routine laufen zu lassen. Natürlich darf dabei nicht die komplette Hardcopy ausgegeben werden, da sonst die Applikation nicht mehr zum Zuge kommt. Also wird HC-FIX portionsweise ausgeführt -genauer: bei jedem Busy-Interrupt wird nur ein Byte an den Drucker ausgegeben und die Routine danach terminiert. Damit HC-FIX beim nächsten Aufruf die folgende Position im Hardcopy-Puffer bearbeiten kann, müssen die dafür notwendigen Informationen abgespeichert werden. Das ist der Hauptunterschied zu normalen Interrupt-Routinen, die in sich abgeschlossene Programmstücke bilden und bei jedem Aufruf unabhängig vom vorherigen Aufruf arbeiten. Für interessierte Leser folgt eine detaillierte Beschreibung des interruptgesteuerten Multitaskings der Hardcopy-Routine.
HC-FIX benutzt diverse Register zur Verwaltung von Programmschleifen (Zeilen-/Spaltenzähler, siehe dokumentierte Registerbelegung im Listing) - sie entsprechen den Schleifenvariablen höherer Programmiersprachen. Zu ihrer Speicherung wird ein programminterner Stack benutzt.
Nach der Installation von HC-FIX kann ein beliebiges Programm gestartet werden (im folgenden auch Hauptprogramm genannt), das im ‘Vordergrund’ läuft. Löst man jetzt die Hardcopy aus, wird das Hauptprogramm unterbrochen und die neue Hardcopy-Routine ausgeführt. Sie lenkt zunächst den Busy-Interrupt-Vektor auf die Routine um und speichert die Register ab, die während der Hardcopy verändert werden. Nachdem sie ein Zeichen an den Drucker gesendet hat, kommt die Routine an eine Unterbrechungsstelle. Da der Drucker mit der Datenübernahme beschäftigt ist, kann sinnvollerweise das Hauptprogramm weiterlaufen. Also werden alle relevanten Registerinhalte auf dem eigenen Stack abgelegt, damit die Routine bei einem späteren Aufruf an dieser Stelle fortgesetzt werden kann. Außerdem wird die Registerbelegung des Hauptprogramms wiederhergestellt.
Das Hauptprogramm wird nun solange ausgeführt, bis der Drucker zur Aufnahme des nächsten Zeichens bereit ist und den Busy-Interrupt auslöst. Dieser führt bei der CPU zu einer Exception (Ausnahmebehandlung): Das Hauptprogramm wird unterbrochen und die Interrupt-Routine von HC-FIX ausgeführt. Sie rettet zunächst die Register des Hauptprogramms, lädt dann die Registerbelegung für die Hardcopy und stellt so den alten Zustand her. Dann wird erneut ein Daten-Byte berechnet und abgeschickt, und der Kreislauf kann von neuem beginnen.
Im Unterschied zum normalen Multitasking ist die Zeitspanne, in der der Hardcopy-Vorgang bedient wird, durch die festgelegte Unterbrechungsstelle immer gleich lang. Das erweist sich als optimal, denn durch die Interrupt-Technik werden einerseits die Daten entsprechend der Aufnahmegeschwindigkeit des Druckers weitergegeben. Auf der anderen Seite läuft das Hauptprogramm weiter, während der Drucker beschäftigt ist.
Klar, daß das Programm im Vordergrund durch die Interrupts langsamer wird - und zwar proportional zur Druckgeschwindigkeit. Deshalb war es wichtig, die Interrupt-Routine zu minimieren. Also wurden möglichst wenige Register benutzt, da ein erheblicher Teil der Rechenzeit zum Retten und Restaurieren ihrer Inhalte verbraucht wird. Beim NEC P6 verlangsamt sich die Ausführung durchschnittlich um den Faktor 1,3. Die Daten für einige andere Drucker sind in Tabelle 1 festgehalten.
Probleme treten bei sehr schnellen Druckern mit großem Zeichenpuffer auf, wie beim NEC P6 plus. Solche Geräte bremsen Vordergrundprogramme bis auf 10% der Ursprungsgeschwindigkeit ab! Bei einer Anfertigungszeit von 20 Sekunden für eine Hardcopy lohnt sich der Einsatz von HC-FIX in diesen Fällen aber ohnehin nicht. In Verbindung mit dem NEC P6 liefert HC-FIX das kleine Format in durchschnittlich 1 Minute 45 Sekunden. Die DIN A4-Hardcopy ist nach ca. 4 Minuten 20 Sekunden fertig.
Im Gegensatz zum Spooler genügen 32000 Bytes für die Kopie des Bildschirmspeichers. Dieser Puffer ist notwendig, damit Änderungen des Bildschirminhalts während der Programmausführung keine Auswirkungen auf den Ausdruck haben. Insgesamt belegt HC-FIX nur ca. 34 kB des Systemspeichers, so daß für die Hauptanwendung ausreichend Raum übrig bleibt.
Die Aufbereitung der Druckerdaten aus den Informationen des Puffers geschieht innerhalb der Interrupt-Routine, d.h. das auszugebende Byte wird erst nach Auslösen des Interrupts berechnet. Würde man die Daten 1:1 an den Drucker weitergeben, entstünde bei einer Einstellung von 180 Punkt/Zoll (dreifache Dichte) eine Mini-Hardcopy von 9 * 5,5 cm. Deshalb verdoppelt bzw. verdreifacht die Routine jeden Punkt in vertikaler und horizontaler Richtung. So erreicht die Hardcopy die zwei möglichen Bildgrößen von 11,3 x 18 cm und 17 x 26,5 cm. Allerdings erhöht sich damit auch die Datenmenge auf das Vier- bzw. Neunfache, was beim Spooler-Betrieb zu den oben aufgeführten Problemen führt.
Drucker | mittlere | maximale |
---|---|---|
NEC P6 | 1,30 | 1,35 |
NEC P2200 | 1,27 | 1,43 |
Seikosha SL-80 IP | 1,13 | 1,20 |
Star LC 24-10 | 1,28 | 2,02 |
Tabelle: Verzögerung der Vordergrundprogramme
Hardcopies vom Desktop oder von Punktmustern sind oft dunkler als erwartet. Das liegt am Durchmesser der Nadeln, der etwas größer als der darzustellende Punkt ist. Folglich sind die (gedruckten) schwarzen Punkte etwas größer als die weißen. Betrachten wir zur Veranschaulichung ein Schachbrettmuster, bei dem der Effekt am gravierendsten auftritt (siehe Bild auf der nächsten Seite).
Links sehen Sie die Punktdarstellung auf dem Monitor und die übliche Umsetzung für den Drucker. Der weiße Punkt in der Mitte ist beim normalen Ausdruck zu klein geraten. HC-FIX verwendet deshalb einen speziellen Algorithmus, um die Qualität zu verbessern (Abbildung rechts):
Normalerweise wird ein schwarzer Bildschirmpunkt mit vier quadratisch angeordneten Druckernadeln aufs Papier gebracht. Folgt auf einen schwarzen Punkt ein weißer (in vertikaler Richtung), werden bei HC-FIX von den vier Nadeln nur die beiden oberen benutzt. Der gedruckte Punkt ist zwar nicht mehr quadratisch - das fällt bei der Größe aber kaum auf - dafür erhält man Hardcopies mit einem größeren Graustufenumfang.
Die Hardcopy wird wie gewohnt durch Alternate-Help ausgelöst bzw. gestoppt. Durch gleichzeitiges Drücken der linken Shift-Taste erhalten Sie das größere Ganzseitenformat. Zur optischen Bestätigung des Vorgangs wird der Bildschirm kurz invertiert.
Als residentes und vektorverbiegendes Programm ist HC-FIX selbstverständlich mit einer XBRA-Struktur ausgestattet. Sie befindet sich direkt vor der Stelle, auf die man den Vektor umgebogen hat - also der Einsprungadresse in das eigene Programm - und hat folgende Form:
xb_magic: DC.B 'XBRA'
xb_id: DC.B 'name'
;vier beliebige Zeichen zur individuellen Kennzeichnung des Programms
xb_oldvec: DC.L 0
;Platz für ursprünglichen Vektor
prg_start:
;Hier fängt das eigene Programm an
Damit kann ein Programm leicht überprüfen, ob es schon installiert ist, bzw. ist es möglich, das Programm wieder zu entfernen. Das setzt allerdings voraus, daß alle nachfolgenden Programme, die den entsprechenden Vektor ebenfalls verbiegen, auch die XBRA-Struktur besitzen. Aus diesem Grund kann ich nur allen Programmierern empfehlen, die XBRA-Methode zu verwenden, wo immer es möglich ist.
Wegen der herkömmlichen Auslösemethode arbeitet die Routine nur mit Programmen zusammen, die keine Interrupts sperren. Programme die den Hardcopy-Vektor ($502) verbiegen, müssen nach Installation von HC-FIX gestartet werden (z.B Tempelmon). Besonderes Augenmerk wurde auf die Verträglichkeit mit Spoolern gelegt, die meistens auch Interrupts benutzen. Dazu wird bei Auslösung einer Hardcopy der Busy-Interrupt auf die eigenen Routine umgelenkt. Ein eventuell vorhandener Vektor eines Spoolers wird gerettet und nach Beendigung der Hardcopy wieder hergestellt. So können beide Routinen auf den Interrupt zugreifen.
Man sieht aber auch sofort, daß während einer Hardcopy kein Text durch den Spooler ausgegeben werden kann. Dieser würde die Interrupt-Routine der Hardcopy benutzen - eine Datenkollision wäre die Folge. Ebenso geht es im umgekehrten Fall. Hält man sich strikt an die zeitliche Trennung von Hardcopy und Textausgabe, kann eigentlich nichts passieren.
***************************************************
* *
* HC-FIX *
* *
* multitaskingfähige Hardcopyroutine *
* für 24-Nadel-Drucker *
* *
* (c) MAXON Computer 1989 *
* *
* written by MARCUS KRAFT, *
* *
* Niederramstädterstr. 187 *
* 61 Darmstadt *
* *
* V 1.3 vom 18.08.89 *
***************************************************
;-------------- Systemparameter -----------------
; Hardwareadressen
psg: EQU $FFFF8800
mfp: EQU $FFFFFA00
mfp_aer: EQU mfp+$03
mfp_ierb: EQU mfp+$09
mfp_isrb: EQU mfp+$11
color_0: EQU $FFFF8240
;Betriebssystemaufrufe
gemdos: EQU 1
bios: EQU 13
xbios: EQU 14
physbase: EQU $02
super: EQU $20
supexec: EQU $26
ptermres: EQU $31
; Systemvariablen
busy_vec: EQU $0100
_prt_cnt: EQU $04EE
savptr: EQU $04A2
dump_vec: EQU $0502
;Programmlänge ermitteln (mit Speicherplatz für den Spooler)
hc_install:
movea.l 4(sp),a6 ;Basepage -> a6
move.l #$0100,d5 ;Länge der Basepage
add.l 12(a6),d5 ;+ Länge Textsegment
add.l 20(a6),d5 ;+ Länge Datensegment
add.l 28(a6),d5 ;+ Länge BSS-Segment
pea bieg(pc)
move.w #supexec,-(sp) ;führt Routine bieg im Super aus
trap #xbios
addq.l #6,sp
pea meldung(pc)
move.w #9,-(sp) ;Cconws: gibt Installations-meldung aus
trap #gemdos
addq.l #6,sp
moveq #30,d1 ;Warteschleife
wa2: moveq #-1,d0
wa1: dbra d0,wa1
dbra d1,wa2
move.l d5,-(sp) ;Programm resident machen
move.w #ptermres,-(sp)
trap #gemdos
;Programm ist jetzt resident und wird an dieser Stelle verlassen
bieg: move.l dump_vec,xb_old ;alten HC-Vektor nach XBRA-Konvention retten
move.l #hcstart,dump_vec ;Hardcopy Vektor auf neue Routine setzen
rts
;Kennzeichnung nach XBRA-Konvention:
xb_magic: DC.B 'XBRA' ;4 Bytes 'XBRA'
xb_id: DC.B 'MKHC' ;4 Bytes für Programmname
xb_old: DC.L 0 ;4 Bytes für alten Vektor
hcstart: cmpi.b #-1,status ;wird eine HC gedruckt ?
beq.s begin
break: move.b #2,status ;ja, also HC stoppen
rts
begin: move sr,-(sp) ;macht aus dem Unterprogramm eine Exception
ori #$0700,sr ;alle Interrupts sperren
move.b mfp_ierb,old_ierb ;altes IERB retten
move.l busy_vec,mfp_vec0 ;alten Interruptvektor retten
andi.b #%11111110,mfp_aer ;setze Active Edge auf fallende Flanke
move.l #busy_int,busy_vec ;neuer Busy-Interrupt-Vektor
subi.l #46,savptr ;damit Bios- und Xbios-Routinen vom
;Interrupt aus aufgerufen werden können
move.w #0,-(sp) ;aktiviere Busy-Interrupt:
move.w #27,-(sp) ;jenabint
trap #14
addq.l #4,sp
move.w #-1,_prt_cnt
movea.l #psg,a3 ;PSG-Adresse laden
movem.l d0-d6/a0-a3,-(sp) ;Register retten
move.l sp,old sp ;alten Stackpointer retten
lea mystack(pc),sp ;Stackpointer für HC-Routine
bsr getadr ;Bildschirmadresse->anfadr
shifttst:
move.b #0,mode
move.w #-1,-(sp)
move.w #11,-(sp) ;kbshift
trap #13
addq.l #4,sp
addi.l #46,savptr ;Stackpointer für BIOS wiederherstellen
btst #1,d0 ;wurde zusätzlich die Shifttaste gedrückt?
beq.s noshift
move.b #1,mode ;ja: große HC
noshift: bchg #0,color_0 ;reverse video
movea.l anfadr,a0
lea puffer,a1
move.w #31999,d1
save_scr: move.b (a0)+,(a1)+ ;kopiert normalen Bildschirm in Puffer
dbra d1,save_scr
bchg #0,color_0 ;norm video
btst #0,color_0
bne.s pr_init
lea puffer(pc),a1
move.w #7999,d0
invert: not.l (a1)+ ;invertiere ggf.Pufferinhalt
dbra d0,invert
pr_init: move.b #0,status ;HC beginnt
bsr sender ;Zeilenvorschub senden
bsr setlf ;Linefeed für Grafikausdruck einstellen
lea puffer(pc),a0
tst.b mode
bne vert_hc ;mode=1 =>große
;--------------------------------------------------
; Horizontale Hardcopy
;--------------------------------------------------
;--------------------------------------------------
;
; Registerbelegung der Routine bei horiz. Copy :
;
; d0- Zähler d.3 Druckerbytes f.1 Nadelreihe(24N)
; d1- Bitzähler für Puffer
; d2- Byte/Zeilenzähler für Puffer
; d3- 4malzähler f.1 Druckerbyte (jedes Bit 2mal)
; d4- zu druckendes Zeichen
; d5- Anzahl Zeichen (für chrout)
; d6- Speicher für Portkommunikation
; d7-
; a0- Pufferadresse
; a1- Kopie von a0, die aber verändert wird
; a2- Adresse Zeichenstring (für chrout)
; a3- Adresse PSG
;
;--------------------------------------------------
move.w #33,d2 ;34 Zeilen (34*12=408)
scr: swap d2
move.w #79,d2 ;eine Zeile drucken (80 B)
bsr grafon ;Grafikzeile senden
row: move.w #7,d1 ;ein Byte bearbeiten
byte: movea.l a0,a1
moveq #2,d0 ;das ganze 3x
col: moveq #3,d3
four: lsl.w #2,d4 ;d4 ist das Druckerbyte
btst d1,0(a1)
beq.s offset ;Punkt gesetzt?
addq.w #2,d4 ;ja, aber nur 1 Punkt für Drucker (statt 2)
btst d1,80(a1) ;teste den nachfolgenden Punkt
beq.s offset
addq.w #1,d4 ;und setze ggf. den fehlenden Druckerpunkt
offset: adda.l #80,a1
dbra d3,four
move.w d4,-(sp) ;Druckerbyte retten
bsr chrout ;und ausgeben
dbra d0,col ;das ganze 3x
move.w 4(sp),d4
bsr chrout ;und die 3 Byte wg der horiz.
move.w 2(sp),d4 ;Verdopplung nochmal raus
bsr chrout
move.w (sp),d4
bsr chrout
addq.l #6,sp ;Stack reinigen
dbra d1,byte ;ganzes Byte abarbeiten
addq.l #1,a0 ;nächstes Byte
dbra d2,row ;Zeile bearbeiten
bsr sender ;Zeilenvorschub senden
cmpi.b #2,status ;wurde alt-help gedrückt?
beq.s bye ;falls ja, Stop
adda.l #880,a0 ;Offset für die nächsten 12 Pixelzeilen
swap d2
dbra d2,scr ;ganzer Bildsch.
bsr sender
bye: bsr reslf
move.b #-1,status ;HC beendet
move.w #-1,_prt_cnt
move.b old_ierb(pc),mfp_ierb;IERB restaurieren
move.l mfp_vec0(pc),busy_vec;wieder alten Interruptvektor benutzen
bra jobend
;--------------------------------------------------
; Vertikale Hardcopy (groß)
;--------------------------------------------------
;--------------------------------------------------
;
; Registerbelegung bei vertikaler Hardcopy :
;
; d0 - Zähler f.d. 3fach-Ausgabe d.3 Druckerbytes
; d1 - Bitzähler für Puffer
; d2 - Bytezähler für Puffer
; d3 - Zeilenzähler für Puffer
; d4 - zu druckendes Zeichen
; d5 - Anzahl Zeichen (für chrout)
; d6 - Speicher für Portkommunikation
; d7 -
; a0 - Pufferadresse
; a1 - Kopie von a0, die aber verändert wird
; a2 - Adresse Zeichenstring (für chrout)
; a3 - Adresse PSG
;
;--------------------------------------------------
vert_hc: adda.l #32000-80,a0 ;letzte Bildschirmzeile
move.w #79,d3
v_screen: movea.l a0,a1
bsr v_grafon
move.w #399,d2
v_row: move.w #7,d1
v_byte: lsl.l #3,d4
btst d1,(a1)
beq.s noadd
addq.l #7,d4
noadd: dbra d1,v_byte
move.w d4,-(sp) ;Byte 3
lsr.l #8,d4
move.w d4,-(sp) ;Byte 2
lsr.w #8,d4
move.w d4,-(sp) ;Byte 1
move.w #2,d0
dr_col: move.w (sp),d4 ;3 mal 3 Bytes ausgeben
bsr.s chrout
move.w 2(sp),d4
bsr.s chrout
move.w 4(sp),d4
bsr.s chrout
dbra d0,dr_col
addq.l #6,sp
suba.l #80,a1
dbra d2,v_row
bsr sendcr
cmpi.b #2,status
beq bye
addq.l #1,a0
dbra d3,v_screen
bsr sendcr
bra bye
;-------------------------------------------
; Busy-Interrupt-Routine
;-------------------------------------------
busy_int: cmpi.b #-1,status ;Hardcopy in process?
bne.s load
bclr #0,mfp_isrb ;keine HC-Anforderung
rte
load: movem.l d0-d6/a0-a3,-(sp) ;Register und SP retten
move.l sp,old_sp
movea.l new_sp(pc),sp ;HC-SP u.-register laden
movem.l (sp)+,d0-d5/a0-a3
bra.s go_on ;weitermachen,wo aufgehört wurde
;--------------------------------------------------
; Unterprogramm zur Zeichenausgabe auf Drucker
;--------------------------------------------------
chrout:
move.b #7,(a3)
move.b (a3),d6
or.b #%10000000,d6 ;Port B als Ausgang
move.b d6,2(a3)
move.b #15,(a3) ;PSG Port B auswählen
move.b d4,2(a3) ;d4 in Port B
move.b #14,(a3) ;PSG Port A auswählen
move.b (a3),d6
and.b #%11011111,d6
move.b d6,2(a3) ;Strobe senden (active low)
move.b #14,(a3)
move.b (a3),d6
or.b #%100000,d6
move.b d6,2(a3) ;Strobesignal abstellen
jobend: ;Abbruch des Hintergrundjobs
movem.l d0-d5/a0-a3,-(sp)
move.l sp,new_sp ;Routinen-SP und-Register save
movea.l old_sp(pc),sp
movem.l (sp)+,d0-d6/a0-a3 ;alten SP und Register wiederherstellen
bclr #0,mfp_isrb
rte ;und zurück zum unterbrochenen Hauptprogramm
go_on: rts
;--------------------------------------------------
; Diverse Unterprogramme
;--------------------------------------------------
getadr: move.w #physbase,-(sp) ;Bildschirmadresse ermitteln
trap #xbios
addq.l #2,sp
move.l d0,anfadr
rts
grafon: lea grafdat(pc),a2 ;Grafikmodus f.horiz. HC einschalten
moveq #8,d5
bra.s strout
v_grafon: lea v_grdat(pc),a2 ;Grafikmodus für vert. HC ein
moveq #8,d5
bra.s strout
sendcr: lea feed(pc),a2 ;Zeilenvorschub
moveq #1,d5
bra.s strout
setlf: lea lfdat(pc),a2 ;Zeilenvorschub für Grafik ein
moveq #2,d5
bra.s strout
reslf: lea oldlf(pc),a2 ;Normalen Zeilenvorschub hersteilen
moveq #1,d5
strout: move.b (a2)+,d4 ;gibt durch a2 adr. String
bsr chrout ;mit Lg.d5+1 aus
dbra d5,strout
endrout: rts
DATA
lfdat: DC.B 27,'3',24
oldlf: DC.B 27,'2'
grafdat: DC.B 27,36,20,0,27,'*',39,0,5
v_grdat: DC.B 27,36,30,0,27,'*',39,176,4
feed: DC.B 13,10
status: DC.B $FF
meldung: DC.B 13,10,27,'K',13,10
DC.B 9,27,'p','HC-FIX',27,'q',' V 1.3 installiert, (c) MAXON Computer 1989',27,'K' ,13,10
DC.B 9,'von Marcus Kraft, Niederramstädterstr. 187, 61 Darmstadt'
DC.B 27,'K',13,10,27,'K',0
EVEN
BSS
old_ierb: DS.B 1
mode: DS.B 1
mfp_vec0: DS.L 1
old_sp: DS.L 1
new_sp: DS.L 1
anfadr: DS.L 1
endstack: DS.W 400
mystack: DS.W 1
puffer: DS.B 32640 ;Puffer für Bildschirmsp.
END