← ST-Computer 04 / 1994

Falcon-VT52: Auf die Sprünge geholfen

Grundlagen

Wer auf seinem Falcon des öfteren TOS-Programme benutzt, dem wird vielleicht aufgefallen sein, daß die Bildschirmausgabe nicht immer korrekt ist. Der folgende Artikel beschreibt die Probleme und bietet ein Listing, das eine Korrektur des VT52-EmuIators vornimmt.

Der wohl deutlichste Fehler tritt bei der normalen Textausgabe auf (auch im Raw-Modus): Befindet sich der Cursor in der unteren rechten Bildschirmecke, wird plötzlich nach jedem weiteren Zeichen gescrollt, so daß pro Zeile nur noch ein Buchstabe steht. Dies ist insbesondere bei solchen Programmen mehr als störend, die längere Listen ohne Zeilenumbruch ausgeben, da die Bildschirmausgabe schlicht unlesbar wird.

Des weiteren funktionieren einige der Escape-Sequenzen nicht mehr, was unter Umständen zu völlig zerstörten Bildschirmmasken führen kann. Im einzelnen sind dies ESC b (Setzen der Vordergrundfarbe), ESC c (Setzen der Hintergrundfarbe), ESC j (Cursor-Position speichern) und ESC k (gespeicherte Cursor-Position abrufen).

Anscheinend haben sich in der Eile der Falcon-TOS-Entwicklung unbemerkt ein paar Fehler eingeschlichen. Abhilfe schafft die Verwendung von NVDI 2.5 oder das im folgenden beschriebene Listing.

Fehlerbereinigung

Um die Unzulänglichkeiten der Falcon-Bildschirmausgabe zu beseitigen, muß man in das Betriebssystem eingreifen. Dazu sollte man zunächst wissen, daß nur die BIOS-Textausgabe (per Bconout) abgefangen werden muß, da sämtliche GEM-DOS-Ausgaberoutinen intern auf das BIOS zurückgreifen (das BIOS ist die unterste Betriebssystemebene). Man könnte sich also nun in den BIOS-Trap einhängen und den Bconout-Aufruf abfangen, doch es geht noch einfacher: Seit TOS 1.02 existiert eine Tabelle mit Zeigern auf Routinen, die das BIOS für die einzelnen Ausgabegeräte bei Bconstat, Bconin, Bcostat und Bconout benutzt. Somit müssen in dieser Tabelle nur die beiden Zeiger auf die Bconout-Routinen für CON: und RAWCON: umgebogen werden, was selbstverständlich per XBRA geschehen sollte.

In der eingeklinkten CON:-Routine wird nun geprüft, ob eine der fehlerhaften Escape-Sequenzen ausgeführt werden soll.

Wenn ja, wird diese durch eine eigene, korrigierte Funktion ersetzt. Um das erstgenannte Problem zu beseitigen, das auch im Raw-Modus auftritt, muß man wissen, was hier überhaupt schiefläuft: Nach dem Erreichen des unteren rechten Bildschirmrands wird die X-Cursor-Position auf einen viel zu großen Wert gesetzt, so daß das BIOS meint, der Cursor befände sich immer noch am Rand, obwohl er ja eigentlich wieder am Zeilenanfang steht. Also wird beim nächsten Zeichen gleich wieder gescrollt, was natürlich falsch ist. Beheben läßt sich dies, indem man vor jeder Zeichenausgabe prüft, ob die horizontale Cursor-Position größer als der Maximalwert ist. Wenn ja, muß sie auf Null gesetzt werden.

Das Listing benötigt die negativen Line-A-Variablen, da nur hier die aktuelle Cursor-Position ermittelt und die Vorder- bzw. Hintergrundfarbe gesetzt werden kann. Dabei werden auch Schreibzugriffe vorgenommen, was laut Dokumentation [2] nicht erlaubt, hier aber leider nicht zu vermeiden ist, da nur so eine Korrektur möglich ist.

Leider verlangsamt sich die Zeichenausgabe durch die eingehängten Routinen geringfügig, was man jedoch verschmerzen kann, da sie nun endlich wieder so funktioniert, wie sie sollte.

Literatur:

[1] Jankowski/Rabich/Reschke, ATARI Profibuch ST-STE-TT, SYBEX-Verlag GmbH, Düsseldorf, 1991 (besonders Teil I, Kapitel 1, Abschnitt 2: Zeichenorientierte Funktionen)

;*********************************************** ;* Modulname : VT52FIX.S * ;* (C)1994 by MAXON-Computer * ;* Autor : Thomas Binder * ;* Zweck : TSR-Programm, das einige * ;* Fehler in der VT52-Emula- * ;* tion des Falcon030 behebt * ;* Compiler : Pure Assembler 03.02.1992 * ;* Erstellt am : 02.01.1994 * ;* Letzte Änderung: 10.01.1994 * ;*********************************************** super mc68030 equ _longframe,$59e equ xconout,$57e text ; Ist VT52FIX bereits installiert? pea is_installed(pc) move.w #38,-(sp) ; Supexec trap #14 addq.l #6,sp tst.w d0 bne already_installed ; Ist der Rechner wirklich ein F030? pea check_f030(pc) move.w #38,-(sp) ; Supexec trap #14 addq.l #6,sp tst.w d0 beq no_falcon ; Routinen einklinken pea install(pc) move.w #38,-(sp) ; Supexec trap #14 addq.l #6,sp ; Anfangsadresse der Line-A-Variablen merken aline #0 move.l d0,lineavar ; Erfolgsmeldung ausgeben pea patch_text (pc) move.w #9,-(sp) ; Cconws trap #1 addq.l #6,sp ; Größe des resident zu haltenden Speicherbereichs ; berechnen und Programm mit Ptermres beenden move.l #$100,d0 move.l 4(sp),a0 add.l $c(a0),d0 add.l $14(a0),d0 add.l $1c(a0),d0 clr.w -(sp) move.l d0,-(sp) move.w #49,-(sp) ; Ptermres trap #1 ; Meldung ausgeben, daß die Routine bereits in- ; stalliert ist already_installed: pea already_installed_text(pc) bra.s out ; Meldung ausgeben, daß der Rechner kein Falcon ; ist no_falcon: pea no_falcon_text(pc) out: move.w #9,-(sp) ; Cconws trap #1 ; Programm verlassen clr.w -(sp) ; Pterm0 trap #1 ; Die neue conout-Routine dc.b "XBRAVTFX" old_conout: dc.l 0 new_conout: move.l sp,a0 ; wenn wir noch nicht in einer Escape-Sequenz ; sind, das Zeichen "normal" behandeln tst.w in_escape(pc) beq normal_char ; ansonsten prüfen, ob mit diesem Zeichen die ; Sequenz festgelegt wird addq.w #1,escape_count cmpi.w #1,escape_count(pc) bne continue_escape ; Escape-Sequenz beginnt, ist es eine, die korri- ; giert werden muß? cmpi.b #'j',7(a0) ; save cursor position bne.s 11 ; Bei ESC j die aktuelle Cursorposition aus den ; negativen Line-A-Variablen auslesen move.l lineavar(pc),a1 move.l -$1c(a1),saved_curpos ; Jeweils 32 addieren, da ESC k spater durch ESC Y emuliert wird addi.l #$200020,saved_curpos clr.w 6(a0) clr.w in_escape bra back 11: cmpi.b #'k',7(a0) ; restore cursor position bne.s l2 ; Die gespeicherte Cursorposition wird per ESC Y ; angesprungen move.w #'Y',-(sp) move.w #2,-(sp) bsr old_out addq.l #4,sp move.w saved_curpos+2(pc),-(sp) move.w #2,-(sp) bsr old_out addq.l #4,sp move.w saved_curpos(pc),-(sp) move.w #2,-(sp) bsr.s old_out addq.l #4,sp ; Gespeicherte Position löschen, da nach VT52- ; Konvention die gesicherte Position durch ESC k ; verloren geht move.l #$200020,saved_curpos clr.w in_escape rts 12: cmpi.b #'b',7(a0) ; set foreground color bne.s 13 ; Hier nur das Flag setzen, daß ESC b angefangen ; wurde und dafür sorgen, daß die begonnene Escape- ; Sequenz abgebrochen wird (einfach noch ein NUL ; senden, da ESC NUL wirkungslos ist) move.w #2,in_escape clr.w 6(a0) bra.s back 13: cmpi.b #'c',7(a0) ; set background color bne.s 14 ; Wie oben, nur für ESC c move.w #3,in_escape clr.w 6(a0) bra.s back 14: cmpi.b #'Y',7(a0) ; position cursor beq.s back ; Wenn es nicht ESC Y war, das Escape-Sequenz-Flag ; löschen (nur ESC Y benötigt zusätzliche Para- ; meter, ESC b und ESC c werden ja separat behan- ; delt clr.w in_escape bra.s back ; Normales Zeichen ausgeben, dabei vorher testen, ; ob die x-Cursorposition noch fehlerfrei ist ; (also kleiner oder gleich dem Maximalwert) ; Ist das Zeichen ein Escape, das entsprechende ; Flag setzen normal_char: cmpi.b #27,7(a0) bne.s no_escape move.w #1,in_escape clr.w escape_count no_escape: ; Ist x-Position außerhalb des zulässigen ; Bereichs? move.l lineavar(pc),a1 move.w -$1c(a1),d0 ccmp.w -$2c(a1),d0 bls.s back ; wenn ja, X-Position auf 0 setzen (höchst ; unsauber, da Schreibzugriff auf negative ; Line-A-Variable, aber leider notwendig) clr.w -$1c(a1) ; Die alte conout-Routine aufrufen back: old_out: move.l old_conout(pc),a0 jmp (a0) ; Mit Escape-Sequenzen fortfahren, die mehr als ; einen Parameter erhalten (ESC b, ESC c und ; ESC Y, wobei letztere nicht korrigiert werden ; muß) continue_escape: ; Ist es ESC Y? cmpi.w #1,in_escape(pc) bne.s correction ; Wenn ja, ist dies das letzte Parameterzeichen? cmpi.w #3,escape_count(pc) bne.s back ; Ja, also Escape-Flag löschen clr.w in_escape bra.s back correction: ; ESC b bzw. ESC c ausführen, leider mit Schreib- ; Zugriff aus die negativen Line-A-Variablen :( move.l lineavar(pc),a1 cmpi.w #2,in_escape(pc) bne.s background_color clr.w in_escape move.w 6(a0),-$24(a1) rts background_color: clr.w in_escape move.w 6(a0),-$26(a1) rts ; Neue Routine für RAWCON:; hier muß nur geprüft ; werden, ob die x-Cursorposition im zulässigen ; Bereich liegt, da es ja hier keine Escape- ; Sequenzen gibt dc.b "XBRAVTFX" old_rawconout: dc.l 0 new_rawconout: ; siehe oben move.l lineavar(pc),a0 move.w -$1c(a0),d0 cmp.w -$2c(a0),d0 bls.s rawcon_back clr.w -$1c(a0) ; Die alte conout-Routine aufrufen rawcon_back: move.l old_rawconout(pc),a0 jmp (a0) ; Diese Routine prüft anhand des _MCH-Cookies, ob ; der Rechner ein Falcon ist check_f030: clr.w d0 move.l $5a0,d1 beq.s back2 move.l d1,a0 loop2: tst.l (a0) beq.s back2 cmpi.l #'_MCH',(a0)+ bne.s goon2 cmpi.l #$30000,(a0) bne.s back2 moveq #1,d0 back2: rts goon2: addq.l #4,a0 bra.s loop2 ; Diese Routine prüft, ob in der XBRA-Kette des ; xconout-Vektors die Limit-Routine bereits einge- ; klinkt ist is_installed: move.l xconout+8,a0 ; Xconout-Vektor loop: cmpi.l #'XBRA',-12(a0) bne.s not_installed cmpi.l #'VTFX',-8(a0) beq.s installed move.l -4(a0),a0 bra.s loop installed: moveq #1,d0 rts not_installed: clr.w d0 rts ; Neue conout/rawconout-Routinen einklinken install: move.l xconout+2*4,old_conout move.l #new_conout,xconout+2*4 move.l xconout+5*4,old_rawconout move.l #new_rawconout,xconout+5*4 ; Position für ESC k initialisieren move.l #$200020,saved_curpos rts data no_falcon_text: dc.b 13,10,"Machine is not a Falcon030!" dc.b 13,10,0 even patch_text: dc.b 13,10,"VT52FIX installed!" dc.b 13,10,0 even already_installed_text: dc.b 13,10,"VT52FIX is already " dc.b "installed!",13,10,0 bss lineavar: ds.l 1 saved_curpos: ds.l 1 in_escape: ds.w 1 escape_count: ds.w 1 ; Projektdatei zu VT52FIX.PRG ; Autor: Thomas Binder ; (c)1993 by MAXON-Computer ; Compiler: Pure C 1.0 ; Erstellt: 02.01.1994 ; Letzte Änderung: 02.01.1994 VT52FIX.PRG .L [ -S=0 ] .S [] = VT52FIX.S ; der Sourcecode ; Ende der Projektdatei zu VT52FIX.PRG
Thomas Binder