HC-FIX: Multitasking-Hardcopy-Routine

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.

Wie alles begann

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.

Datenübertragung

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:

Das Konzept

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.

Im Detail

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.

Datenaufbereitung

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

Druckqualität

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.

Auslösemechanismus

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.

XBRA-Verfahren

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.

Verträglichkeit mit anderen Programmen

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

Marcus Kraft
Links

Copyright-Bestimmungen: siehe Über diese Seite
Classic Computer Magazines
[ Join Now | Ring Hub | Random | << Prev | Next >> ]