← ST-Computer 10 / 1987

1st Patch - zwei Dutzend Nadeln machen Druck

Listing

Kennen Sie das? Da hat man sich nun endlich das langersehnte, ultragrelle Programm angelandet, lĂ€dt die erstbeste Demo und ist fasziniert ob der fantastischen Möglichkeiten, die sich einem da auf dem Monitor prĂ€sentieren. Der erste Frust stellt sich allerdings meist sehr schnell ein, nĂ€mlich dann, wenn man den Drucker anwirft: Gemeinerweise ist unter den Myriaden mitgelieferter Druckertreiber wieder mal keiner vorhanden, der auf das eigene Lieblings-PeripheriegerĂ€t zugeschneidert ist. In diesen FĂ€llen gibt es zwei Möglichkeiten: Man kauft sich einen Treiber, so es ĂŒberhaupt einen gibt, oder aber man macht dem Betriebssystem Beine und schreibt „das Ding“ selbst. Kein Problem, wenn man 1st Patch zur Hand hat...

Wer schon einmal mit dem Gedanken eines Druckerkaufes gespielt hat und sich im Dschungel der 8-, 9-, 18-, 19- und 24-Nadler, der Laser-, Typenrad- und Non-Impact-Drucker umgetan hat, wird es messerscharf erkannt haben: Vielfalt ist angesagt. Deshalb kann man es den SoftwarehĂ€usern eigentlich nicht verĂŒbeln, wenn sie ihre ach so kostbare Entwicklungszeit lieber mit dem Schreiben der eigentlichen Programme denn mit der Erstellung von Hunderten von Druckertreibern verbringen. In aller Regel kann man ja auch mit gemĂ€ĂŸigtem Aufwand die mitgelieferten Druckertreiber anpassen, wobei man beispielsweise das Textverarbeitungsprogramm WORDPLUS in punkto Anpassungsfreundlichkeit lobend hervorheben muß. Auch die Möglichkeit, Grafiken in den Text einstreuen zu können, besticht durch ĂŒberlegene Eleganz. Dann aber schlafen einem doch glatt die FĂŒĂŸe bei der Vorstellung ein, daß eben jenes gerade noch so positiv erwĂ€hnte Produkt im Zeitalter der LQ-Drucker nur so acht bis neun Nadeln aus ihrem Magnetbett reißt. Da hilft denn auch die beste Druckeranpassung nicht mehr weiter, wenn das Programm selbst die Schönschreiber boykottiert. Man könnte ja nun der Idee verfallen, sich ein eigenes Ausgabeprogramm zu schreiben, oder in WORDPLUS selbst ein paar Bytes abzuĂ€ndern, jedoch sind die Aussichten auf Erfolg speziell in letzerem Fall Ă€ußerst gering. Selbst wenn die Operation wider Erwarten gelingen sollte, so funktioniert es doch nur bei diesem einen Programm. Viel aussichtsreicher und universeller ist folgende Überlegung: Wenn ein Programm auf die Centronics-Schnittstelle zugreift, so passiert dies in aller Regel ĂŒber eine Betriebssystemfunktion des GEMDOS, namentlich der Funktion Printer Output, GEMDOS 0x5. Dann mĂŒĂŸte es doch möglich sein, das auszugebende Byte auf seine Wirkung zu untersuchen und gegebenenfalls ein paar ganz andere Zeichen an den Drucker zu senden. Sie werden es vermuten: Es ist wirklich möglich - sofern besagtes Programm auch tatsĂ€chlich ĂŒber das Betriebssystem mit dem Drucker kommuniziert und nicht etwa eigene Routinen benutzt.

ESC-Sequenzen

Im Zusammenhang mit WORDPLUS ist der Befehl: ESC 2A 04 n1 n2 DATA interessant, weil er die 8-Nadel-Emulation (CRT I, 640 Punkte/Zeile) einschaltet. Wie Bild 1 verdeutlicht, werden die Bits der nachfolgenden Grafikdaten nur jeder dritten Nadel zugeordnet, wodurch dann die ungeliebten LĂŒcken entstehen. Abhilfe kann hier durch Einschalten des 24er Modus mit dreifacher Dichte geschaffen werden (ESC 2A 27). Hier mĂŒssen dann allerdings pro Spalte gleich drei Bytes vorstellig werden, wozu man die von WORDPLUS abgeschickten Daten verdreifacht. Dies muß aber bitweise passieren, weil man sonst dieselbe Zeile druckt wie im CRT I-Modus (jetzt halt mit 24 Pins), auf ein Drittel der ursprĂŒnglichen Höhe gestaucht. DafĂŒr aber dreimal untereinander. Der verfremdende Effekt lĂ€ĂŸt sich auf Dauer ziemlich schwer verheimlichen...

Falsche VerhÀltnisse

Nicht nur vertikal nimmt die Informationsdichte bei 24 Nadeln zu, sondern auch in der Breite, denn um eine Zeile komplett einzuschwÀrzen, braucht man nun genau 1440 Punkte horizontal, also zweieinviertel mal soviel als im CRT I-Modus.

TrĂ€gt man dieser Tatsache keine Rechnung, erscheint der mitgelieferte Demo-Tiger zwar in hervorragender BriefqualitĂ€t; es drĂ€ngt sich jedoch der Eindruck auf, als hĂ€tte er seinen Kopf versehentlich auf einer Dampframme abgelegt... 1st Patch behebt diesen Mißstand dadurch, daß jede Pixelspalte doppelt und jede vierte dreifach ausgegeben wird. Ergebnis: Der Tiger packt’s wieder.

Bild 1: Links: So druckt WORDPLUS Grafiken... Rechts: Und das macht 1st Patch daraus

NEC-ereien

Zum neuen Star am LQ-Grafik-Himmel hat sich aufgrund seiner ĂŒberragenden Leistungen die NEC Px-Reihe gemausert. FĂŒr sie sind PixelabstĂ€nde von 1/360 Zoll horizontal und vertikal eine Leichtigkeit. Horizontal sind z.B. Epson-Drucker durchaus kompatibel; beim Zeilenvorschub sieht es da etwas anders aus: Bei NEC hat man, um die FĂ€higkeiten der eigenen Drucker auszukitzeln, das fĂŒr alle anderen unbekannte Steuersymbol FS (OxlC) eingefĂŒhrt. Gefolgt von: 33 n befiehlt es dem Drucker, das Papier um n/360” voranzutreiben. Da wohl jeder Drucker die ESC-Sequenz 1B 33 n versteht (Zeilenvorschub um n/180”), fĂ€ngt 1st Patch das NEC-Kommando ab und bedient sich des uralten mathematischen Prinzips der KĂŒrzung: Wenn x = n/360, dann auch x = (n/2)/180. Außerdem wird die Sequenz FS 46 von 1st Patch abgefangen und einfach ignoriert; sie soll wohl auch eine Art Zeilenvorschub erzeugen, ihr Fehlen stört aber nicht weiter. Alle anderen FS- und ESC-Sequenzen werden von 1st Patch unverĂ€ndert weitergegeben; notfalls muß man sie halt ebenfalls abfangen und Ă€ndern (s. ESC_Z1, ESC_Z2). Wer einen NEC Px besitzt, sollte natĂŒrlich die mit (*) markierten Zeilen im Programm weglassen bzw. in der angegebenen Form modifizieren!!!

Wo bitte geht’s zum GEMDOS?

Nachdem nun die Problematik des Patches klar zutage getreten ist, stellt sich die Frage, wie man denn ein im ROM befindliches TOS abĂ€ndern kann. Dies birgt de facto keine Schwierigkeiten: Die Adresse nĂ€mlich, wo denn das Betriebssystem seine Traps versteckt hat, liegen im RAM und können bequemerweise sogar mit einer BIOS-Funktion auf die eigenen Routinen umgebogen werden. In D0 erhĂ€lt man die ursprĂŒngliche Adresse (die man sich merken muß!) zurĂŒck. Ab jetzt landen also alle GEMDOS-Aufrufe in unserer Routine. Hier mĂŒssen wir nun prĂŒfen, ob der Aufruf aus dem User- oder Supervisormodus erfolgte, weil die Daten ja auf dem jeweiligen Stack zu finden sind. Erfolgte der Aufruf aus dem S-Mode heraus, muß man darauf achten, erst einen Offset von sechs Bytes auf den Stack zu addieren, weil die CPU beim Antreffen eines Trap-Befehles automatisch die RĂŒcksprungadresse (.L) und das Statusregister (.W) auf den Stack legt. Als nĂ€chstes ĂŒberprĂŒfen wir, ob es sich um die Printer-Funktion 0x5 handelt. Wenn nicht, springen wir an die (hoffentlich gerettete) Originaladresse des GEMDOS. Ansonsten kann unser Patch in Aktion treten. Beachten muß man nur, daß die ĂŒblichen Register (D1-D6/ A2-A6) gerettet werden. Abschließend werden die Registerinhalte restauriert und unsere Routine mit RTE abgeschlossen. Als Lohn fĂŒr unsere Arbeit erhalten wir von nun an nur noch wunderschöne 24-Nadel-Grafiken; die Nicht-Besitzer eines NEC-Druckers zusĂ€tzlich noch die faire Chance, in Zukunft wenigstens deren Treiber benutzen zu können. Da es weder zeitliche noch speicherplatzmĂ€ĂŸige Restriktionen fĂŒr die Patch-Routine gibt, darf man nach Belieben zusĂ€tzliche Steuercodes abfangen und verĂ€ndern.

SelbstverstĂ€ndlich kann man nach dieser Methode auch zusĂ€tzliche Funktionen ins Betriebssystem einschleusen, sich z.B. eine neue File-Selector-Box bauen, oder die Umlaute mittels 1st Patch in ESC-Sequenzen umwandeln (Einschalten des deutschen Zeichensatzes), auf daß das gewohnte Frusterlebnis bei der Desktop-Option „Drucken“ zukĂŒnftig ausbleiben möge.

M. Schumacher

; ######################################## ; # 1st Patch fĂŒr TRAP 1 # 25.06.87 ; ######################################## ; Dieser Druckertreiber klinkt sich ins GEMDOS ein und verĂ€ndert ; die folgenden Steuercodes (Escape-Sequenzen): ; * ESC 2A 04 (Einschalten der CRT I-Grafik) wird umgewandelt ; in ESC 2A 39..., wodurch die 24-Nadelgrafik mit ; dreifacher Dichte eingeschaltet wird. Alle nach ; diesem Kommando folgenden Grafikbytes werden ; bitweise verdreifacht (24 Nadeln!), doppelt ge- ; sendet und jedes 4. Byte sogar dreifach, um die ; gleiche Breite wie bei CRT I zu erhalten. ; * FS 33 n ist fĂŒr den NEC P6 das Steuerzeichen zum n/360" ; Zeilenvorschub. 1st Patch wandelt IC (= FS) in ; 1B (= ESC) um und halbiert n, wodurch der glei- ; che Zeilenvorschub (=(n/2)/180") erreicht wird. ; * FS 46 (Papiervorschub) wird völlig ignoriert, da kei- ; ne vergleichbare Funktion existiert. text pea PATCH ; Adresse der neuen TRAP #1-Routine move.w #33,-(a7) ; Vektor #33... move.w #5,-(a7) ; ...mittels Setexec... trap #13 ; ...umbiegen addq.l #8,a7 ; Stack aufrĂ€umen move.l d0,AD_GDOS ; alten Vektor merken clr.w -(a7) ; kein Fehler aufgetreten move.l #2000,-(a7) ; 2000 Bytes reservieren move.w #$31,-(a7) ; KEEP PROCESS trap #1 ; ...und weggetreten! PATCH: ;======================================================= move.l #-1,D0_ZWS ; Default auf ok movea.l a7,a0 ; SSP -> A0 btst #5,(a0) ; Aufruf aus S-Mode beq.s FROM_USER ; nein addq.l #6,a0 ; ja: Offset addieren bra.s IS_IT_PRT FROM_USER: move.l USP,a0 ; USP benutzen IS_IT_PRT: cmpi.w #5,(a0) ; Printer Output? beq.s LOS move.l ADGDOS,-(a7) ; sonst Originaladresse rts ; benutzen LOS: movem.l d1-d7/a0-a6,-(a7) ; Register retten tst.b ESC_ON ; ESC-Sequenz eingeschaltet? bne.s MORE_ESC ; ja tst.b GRF_ON ; Grafik eingeschaltet? beq TEST_IF_ESC ; nein, testen auf ESC move.w 2(a0),d0 ; auszugebendes Zeichen -> d0 bsr TRIPLE ; dessen Bits verdreifachen tst.b GRF_CNT ; ZĂ€hler fĂŒr FĂŒllbytes schon 0? bne.s \los_end ; nein, normal weiter bsr OUT_3 ; sonst Byte einmal ausgeben move.b #4,GRF_CNT ; ZĂ€hler wieder rĂŒcksetzen \los_end: bsr OUT_3 ; Zeichen doppelt ausgeben subq.b #1,GRF_CNT ; ZĂ€hler fĂŒr FĂŒllbytes dekrementieren subq.w #1,GRF_BYT ; Anzahl zu sendender Bytes dekrement. bne PATCH_END ; noch nicht fertig clr.b GRF ON ; sonst Grafik-Flag löschen bra PATCH_END ; und zurĂŒck MORE_ESC: cmpi.b #1,BYT_NR ; 1. Zeichen nach ESC bzw. FS? bne.s ESCZ2 ; nein, vielleicht 2.? move.b 3(a0),ESC_I ; Zeichen retten ESC_Z1: tst.b FS_ON ; FS eingeschaltet? beq \esc_z1_esc ; nö cmpi.b #'3',ESC1 ; FS 3? (=n/360" Zeilenvorschub) beq \esc_z1_end ; ja, 3.Byte (=n) abwarten cmpi.b #'F',ESC_1 ; FS F? (=Papiervorschub) bne \esc_z1_send_fs ; nein sf ESC_ON ; sonst einfach so tun, sf FS_ON ; als wĂ€re gar nichts sf BYT_NR ; gesendet worden bra PATCH_END \esc_z1_send_fs: move.b #$1C,d0 ; FS-Code senden (ob's gut ist?) bsr OUT bra NOT_ESC ; und akt. Zeichen ebenso \esc_z1_esc: cmpi.b #$2a,ESC_1 ; ESC 2A? bne NOT_ESC ; nein, abbrechen \esc_z1_end: addq.b #1,BYT_NR ; # Zeichen erhöhen bra PATCH_END ; und fertig ESCZ2: cmpi.b #2,BYT_NR ; 2. Zeichen? bne ESC_Z3 ; nein, vielleicht 3.? move.b 3(a0),ESC_2 ; Zeichen retten tst.b FS_ON ; FS eingeschaltet? beq \esc_z2_esc ; nein move.b 3(a0),d0 ; n -> d0 asr.b #1,d0 ; div 2 (wg. n/360=(n/2)/180) move.b d0,ESC_2 ; und abspeichern move.b #$1B,d0 ; ESC statt FS bsr OUT ; ausgeben bra NOTESC ; und den Rest auch \esc_z2_esc: cmpi.b #4,ESC 2 ; ESC 2A 04 (CRT I ein)? bne NOT_ESC ; nein, abbrechen move.b #39,ESC_2 ; sonst 24er-Grafik-Code speichern addq.b #1,BYT_NR ; # Zeichen erhöhen bra PATCH_END ; und fertig ESC Z3: cmpi.b #3,BYT_NR ; 3. Zeichen? bne.s ESC_Z4 ; nein, dann 4. Zeichen move.b 3(a0),GRF_LO ; n1 speichern addq.b #1,BYT_NR ; Index erhöhen bra PATCH_END ; und fertig ESCZ4: st GRF_ON ; Grafik einschalten sf ESC_ON ; ESC-Modus aus move.b #3,GRF_CNT ; ZĂ€hler fĂŒr FĂŒllbytes initialisieren move.b 3(a0),GRF_HI ; n2 speichern move.b ESC_1,d0 ; 1. Zeichen ausgeben bsr OUT move.b ESC_2,d0 ; 2. Zeichen ebenso bsr OUT move.w GRFBYT.d0 ; Anzahl Grafik-Bytes speichern move.w d0,d1 ; in d1 retten (-> FĂŒllbytes berechnen) add.w d0,d0 ; n*2 (wegen Doppeldruck) asr.w #2,d1 ; n durch 4 dividieren add.w d1,d0 ; und zu 2n addieren bsr OUT ; n1 ausgeben ror.w #8,d0 ; Bytes tauschen bsr OUT ; n2 ausgeben tst.w d0 ; keine Grafikdaten? bne.s ESC_END ; dann Schluss clr.b GRF_ON ; und Grafik löschen ESC_END: bra PATCH_END ; und fertig NOT_ESC: sf ESC_ON ; war nix von wegen CRT I ein sf FS_ON ; und auch nix mit n/360” move.b ESC_1,d0 ; 1. Byte nach ESC cmpi.b #1,BYT_NR ; erst beim 2. Byte als ungĂŒltig erkannt? beq \not_esc_end ; nein: fertig bsr OUT ; sonst 1. und move.b ESC_2,d0 ; 2. Byte nach ESC ausgeben \not_esc_end: sf BYT_NR ; Anzahl Zeichen nach ESC/FS rĂŒcksetzen bra CHAR_0UT ; Zeichen in d0 ausgeben und beenden TEST_IF_ESC: move.w 2(a0),d0 ; auszugebendes Zeichen -> d0 cmpi.b #$1B,d0 ; = ESC? bne TEST IF_FS ; nein st ESC_ON ; sonst ESC einschalten bsr OUT ; und ausgeben move.b #1,BYT_NR ; ZĂ€hler fĂŒr # Zeichen nach ESC erhöhen bra PATCH_END ; und beenden TEST_IF_FS: cmpi.b #$1C,d0 ; = FS? bne CHAR_OUT ; nein st FS_ON ; sonst FS st ESC_ON ; und ESC einschalten move.b #1,BYT_NR ; ZĂ€hler fĂŒr # Zeichen nach ESC erhöhen bra PATCH_END ; und beenden CHAR_OUT: bsr OUT ; Zeichen ausgeben bra PATCH_END ; Routine beenden TRIPLE: ; Bits von d0.b verdreifachen clr.l d1 ; hier kommt das Ergebnis hin moveq.l #7,d2 ; unser Bit-Nr.-ZĂ€hler fĂŒr d0 moveq.l #23,d3 ; unser Bit-Nr.-ZĂ€hler fĂŒr d1 \triple_lp: btst d2,d0 ; Bit gesetzt? bne.s \triple_mal3 ; dann verdreifachen subq.l #3,d3 ; sonst ĂŒbergehen bra.s \triple_end \triple_mal3: bset d3,d1 subq.l #1,d3 bset d3,d1 subq.l #1,d3 bset d3,d1 subq.l #1,d3 \triple_end: dbra d2,\triple_lp move.l d1,d0 rts OUT_3: ; 3 Bytes in d0 ausgeben (d0 = xl 23) movem.l d0/d4,-(a7) ; d0/d4 retten moveq.l #1,d4 ; Default-Offset « 2 (doppelt ausgeben) tst.b GRF_CNT ; nur einmal ausgeben? bne.s \out_3_lp ; nein clr.l d4 ; sonst Offset = 0 \out_3_lp: movem.l d0/d4,-(a7) ; d0 und d4 retten (lokal) swap d0 bsr.s OUT ; 1. Byte swap d0 ror.w #8,d0 bsr.s OUT ; 2. Byte ror.w #8,d0 bsr.s OUT ; 3. Byte movem.l (a7)+,d0/d4 ; Register zurĂŒck dbra d4,\out_3_lp ; 1 oder 2mal ausgeben movem.l (a7)+,d0/d4 ; Register zurĂŒck rts OUT: ; Ausgabe von d0.b movem.l d0-d1/a0,-(a7) ; benötigte Register sichern move.b d0,d1 ; Byte nach d1 ext.w d1 ; auf WortlĂ€nge bringen move.w d1,-(a7) ; Byte ausgeben clr.w -(a7) ; auf Drucker move.w #3,-(a7) ; Bconout trap #13 ; BIOS addq.l #6,a7 ; Stack aufrĂ€umen move.l d0,DO_ZWS ; Return-Wert sichern movem.l (a7)+,d0-d1/a0 ; Register zurĂŒck rts PATCHJND: movem.l (a7)+,d1-d7/a0-a6 ; Register zurĂŒck move.l DO_ZWS,d0 ; Return-Wert rte ; ...und fertig data ESCON: dc.b 0 ; Flag, ob ESC-Sequenz gesendet wurde FS_ON: dc.b 0 ; Flag, ob FS-Sequenz gesendet wurde GRF_ON: dc.b 0 ; Flag, ob Grafik eingeschaltet ist align GRF_BYT: ; dient nur als Offset GRF_HI: dc.b 0 ; Anzahl Grafikbytes, MSB GRF_LO: dc.b 0 ; Anzahl Grafikbytes, LSB BYT_NR: dc.b 0 ; ZĂ€hler fĂŒr ESC-Codes ESC_1: dc.b 0 ; 1. Zeichen hinter ESC ESC_2: dc.b 0 ; 2. Zeichen hinter ESC GRF_CNT: dc.b 0 ; ZĂ€hler fĂŒr FĂŒllbytes align DO_ZWS: dc.l 0 ; Zwischenspeicher fĂŒr d0 AD_GDOS: dc.l 0 ; Originaladresse GEMDOS end

Listing 1: Das steckt hinter 1st Patch

Übrigens: FĂŒr die seltenen FĂ€lle, in denen ĂŒber das'BIOS (Trap #13, Bccnout) ausgedruckt wird, muß man 1st Patch folgendermaßen modifizieren:

  1. Das BIOS hat die Vektornurmer 45 (Änderung in der zweiten Progranmzeile)

  2. Der Befehl Bconout hat eine andere Struktur als Printer CXitput. Deshalb muß man IS_IT_PRT Ă€ndern:

cmpi.w #3,(a0) ; Bconout? bne.s NIX_DRUCK ; nö, fertig tst.w 2(a0) ; geht Ausgabe auf PRT: (dev=^)? bne.s NIX_DRUCK ; sieht nicht so aus addq.l 12,a0 ; sonst Offset fĂŒr Stack addieren bra.s LOS ; und anfangen NIX_DRUCK: move.l AD_GDOS,-(a7) ; Originalroutine des BIOS rts ; benutzen
  1. Da es nicht möglich ist, innerhalb einer Trap-Routine nochmal dieselbe Trap zu aktivieren, muß das Unterprogramm 'OUT' ab der Stelle: trap #13 (incl. derselben) folgendermaßen geĂ€ndert werden:
pea \out_ret ; RĂŒcksprungadresse auf Stack move.w SR,-()a7) ; Status auf Stack (TRAP-Simulation) move.l AD_GDOS,-(a7) ; Adresse Originalroutine rts ; anspringen \out_ret: addq.l #6,a7 ; Stack wieder aufrĂ€umen move.l d0,DO_ZWS ; Ergebnis der Ausgabe merken movem.l (a7)+,d0-d1/a0 ; Register restaurieren rts ; und zurĂŒck

Damit ist auch die Druckausgabe ĂŒber BIOS nicht mehr vor 1st Patch sicher.

1st Patch wird sinnvollerweise in den AUTO-Ordner der Boot-Diskette gelegt und bleibt dann fĂŒr die Einschaltdauer resident.

Open "O",#1,"1STPATCH.PRG" Cls Fertig$="Ende" Do Read Dat$ Inc Cnt% Exit If Instr(Dat$,Fertig$,1)>0 Dat$=Right$(Dat$,Len(Dat$)-1) If (Cnt% Mod 12)=1 Lin%=Val(Dat$) Chk%=0 Print At(38,25);Lin%; Else Dat$="A"+Dat$ If (Cnt% Mod 12) =0 If Chk%OVal(Dat$) Print " => Fehler!" Chk%=0 Endif Else Add Chk%,Val(Dat$) Out #1,Val(Dat$) Endif Endif Loop Read Dat$ If Chk%<>Val("&"+Right$(Dat$,Len(Dat$)-1)) Print " => Fehler!" Endif ' ' ################################### Dat_lines: Data 00001, 60, 1A, 00, 00, 02, C8, 00, 00, 00, 12, 156 Data 00002, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 000 Data 00003, 00, 00, 00, 00, 00, 00, 00, 00, 48, 79, 0C1 Data 00004, 00, 00, 00, 26, 3F, 3C, 00, 21, 3F, 3C, 13D Data 00005, 00, 05, 4E, 4D, 50, 8F, 23, C0, 00, 00, 262 Data 00006, 02, D6, 42, 67, 2F, 3C, 00, 00, 07, D0, 2C3 Data 00007, 3F, 3C, 00, 31, 4E, 41, 23, FC, FF, FF, 458 Data 00008, FF, FF, 00, 00, 02, D2, 20, 4F, 08, 10, 359 Data 00009, 00, 05, 67, 04, 5C, 88, 60, 02, 4E, 68, 26C Data 00010, 0C, 50, 00, 05, 67, 08, 2F, 39, 00, 00, 138 Data 00011, 02, D6, 4E, 75, 48, ZI, 7F, FE, 4A, 39, 4CA Data 00012, 00, 00, 02, C8, 66, 44, 4A, 39, 00, 00, 1F7 Data 00013, 02, CA, 67, 00, 01, A0, 30, 28, 00, 02, 22E Data 00014, 61, 00, 01, E2, 4A, 39, 00, 00, 02, D1, 29A Data 00015, 66, 0C, 61, 00, 01, F8, 13, FC, 00, 04, 2DF Data 00016, 00, 00, 02, D1, 61, 00, 01, BC, 53, 39, 2AD Data 00017, 00, 00, 02, D1, 53, 79, 00, 00, 02, CC, 26D Data 00018, 66, 00, 02, 2C, 42, 39, 00, 00, 02, CA, 1DB Data 00019, 60, 00, 02, 22, 0C, 39, 00, 01, 00, 00, 0CA Data 00020, 02, CE, 66, 62, 13, E8, 00, 03, 00, 00, 296 Data 00021, 02, CF, 4A, 39, 00, 00, 02, C9, 67, 00, 286 Data 00022, 00, 3C, 0C, 39, 00, 33, 00, 00, 02, CF, 185 Data 00023, 67, 00, 00, 3C, 0C, 39, 00, 46, 00, 00, 12E Data 00024, 02, CF, 66, 00, 00, 18, 51, F9, 00, 00, 299 Data 00025, 02, C8, 51, F9, 00, 00, 02, C9, 51, F9, 429 Data 00026, 00, 00, 02, CE, 60, 00, 01, D8, 10, 3C, 255 Data 00027, 00, 1C, 61, 00, 01, B0, 60, 00, 00, DE, 26C Data 00028, 0C, 39, 00, 2A, 00, 00, 02, CF, 66, 00, 1A6 Data 00029, 00, D2, 52, 39, 00, 00, 02, CE, 60, 00, 28D Data 00030, 01, B6, 0C, 39, 00, 02, 00, 00, 02, CE, 1CE Data 00031, 66, 00, 00, 4A, 13, E8, 00, 03, 00, 00, 1AE Data 00032, 02, D0, 4A, 39, 00, 00, 02, C9, 67, 00, 287 Data 00033, 00, 1A, 10, 28, 00, 03, E2, 00, 13, C0, 20A Data 00034, 00, 00, 02, D0, 10, 3C, 00, 1B, 61, 00, 19A Data 00035, 01, 64, 60, 00, 00, 92, 0C, 39, 00, 04, 1A0 Data 00036, 00, 00, 02, D0, 66, 00, 00, 86, 13, FC, 2CD Data 00037, 00, 27, 00, 00, 02, D0, 52, 39, 00, 00, 184 Data 00038, 02, CE, 60, 00, 01, 62, 0C, 39, 00, 03, 1DB Data 00039, 00, 00, 02, CE, 66, 12, 13, E8, 00, 03, 246 Data 00040, 00, 00, 02, CD, 52, 39, 00, 00, 02, CE, 22A Data 00041, 60, 00, 01, 46, 50, F9, 00, 00, 02, CA, 2BC Data 00042, 51, F9, 00, 00, 02, C8, 13, FC, 00, 03, 326 Data 00043, 00, 00, 02, Dl, 13, E8, 00, 03, 00, 00, 1D1 Data 00044, 02, CC, 10, 39, 00, 00, 02, CF, 61, 00, 249 Data 00045, 01, 00, 10, 39, 00, 00, 02, D0, 61, 00, 17D Data 00046, 00, F6, 30, 39, 00, 00, 02, CC, 32, 00, 25F Data 00047, D0, 40, E4, 41, D0, 41, 61, 00, 00, E4, 48B Data 00048, E0, 58, 61, 00, 00, DE, 4A, 40, 66, 06, 36D Data 00049, 42, 39, 00, 00, 02, CA, 60, 00, 00, F0, 297 Data 00050, 51, F9, 00, 00, 02, C8, 51, F9, 00, 00, 35E Data 00051, 02, C9, 10, 39, 00, 00, 02, CF, 0C, 39, 22k Data 00052, 00, 01, 00, 00, 02, CE, 67, 00, 00, 0C, 144 Data 00053, 61, 00, 00, AE, 10, 39, 00, 00, 02, D0, 22A Data 00054, 51, F9, 00, 00, 02, CE, 60, 00, 00, 44, 2BE Data 00055, 30, 28, 00, 02, 0C, 00, 00, 1B, 66, 00, 0E7 Data 00056, 00, 18, 50, F9, 00, 00, 02, C8, 61, 00, 28C Data 00057, 00, 88, 13, FC, 00, 01, 00, 00, 02, CE, 268 Data 00058, 60, 00, 00, 9C, 0C, 00, 00, 1C, 66, 00, 18A Data 00059, 00, 1A, 50, F9, 00, 00, 02, C9, 50, F9, 377 Data 00060, 00, 00, 02, C8, 13, FC, 00, 01, 00, 00, 1DA Data 00061, 02, CE, 60, 00, 00, 7C, 61, 00, 00, 58, 265 Data 00062, 60, 00, 00, 74, 42, 81, 74, 07, 76, 17, 29F Data 00063, 05, 00, 66, 04, 57, 83, 60, 0C, 07, C1, 27D Data 00064, 53, 83, 07, C1, 53, 83, 07, C1, 53, 83, 412 Data 00065, 51, CA, FF, EA, 20, 01, 4E, 75, 48, F7, 517 Data 00066, 88, 00, 78, 01, 4A, 39, 00, 00, 02, Dl, 257 Data 00067, 66, 02, 42, 84, 48, Z1, 88, 00, 48, 40, 36D Data 00068, 61, 18, 48, 40, E0, 58, 61, 12, E0, 58, 3E4 Data 00069, 61, 0E, 4C, DF, 00, 11, 51, CC, FF, E8, 4AF Data 00070, 4C, DF, 00, 11, 4E, 75, 48, E7, C0, 80, 46E Data 00071, 12, 00, 48, 81, 3F, 01, 42, 67, 3F, 3C, 23F Data 00072, 00, 03, 4E, 4D, 5C, 8F, 23, C0, 00, 00, 26C Data 00073, 02, D2, 4C, DF, 01, 03, 4E, 75, 4C, DF, 3F1 Data 00074, 7F, FE, 20, 39, 00, 00, 02, D2, 4E, 73, 36B Data 00075, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 000 Data 00076, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 000 Data 00077, 00, 02, 12, 18, 1A, 0C, 08, 12, 0E, 0A, 084 Data 00078, 06, 0A, 0C, 0A, 06, 0C, 0C, 0A, 06, 06, 05A Data 00079, 18, 0A, 0C, 0C, 06, 10, 14, 0C, 06, 0C, 082 Data 00080, 0A, 06, 0A, 06, 08, 08, 06, 0A, 0A, 1C, 066 Data 00081, 0A, 06, 06, 08, 0E, 06, 16, 0C, 12, 06, 06C Data 00082, 08, 3A, 3E, 10, 00, 00, Ende, 090

Listing 2: Wenn’s nicht anders geht: Der Basiclader