← ST-Computer 01 / 1992

BigSTE: Pump up the Resolution

Grundlagen

Ein Großbildschirm ist sicherlich der Traum vieler ST-Besitzer - und wegen der hohen Kosten bleibt er für die meisten bestimmt auch weiterhin ein Traum. Trotzdem sind Großbildschirme und die damit verbundene Auflösungserhöhung nicht mehr aus dem Computeralltag wegzudenken, da sie in vielen Anwendungsgebieten enorme Vorteile bringen (z.B. DTP, CAD).

Ist man nun aber doch glücklicher Besitzer eines Großbildschirmes, hat man das Problem, daß sich ein nicht unbeträchtlicher Teil der gängigen Software außerstande sieht, diese Pixel-Darstellungswunder ordnungsgemäß zu betreiben. Also ist Software gefragt, die durch andere als die Standardauflösungen des ST nicht gleich außer Rand und Band gerät.

Angenommen, Sie wollten nun als (Hobby-) Programmierer mit naturgemäß immer zu kleinem Geldbeutel (und ohne Großbildschirm) solche Programme schreiben, würde bei Ihnen ein mittelgroßes Problem auftauchen, weil Sie die einwandfreie Funktion der Programme mangels Großbildschirm leider nicht austesten können.

„BigSTE“ kann Ihren SM 124 oder Fernseher zwar leider auch nicht in einen 10mal so teuren Großbildschirm verwandeln, aber das Programm kann Ihrem STE zumindest vorgaukeln, daß Sie neuerdings ein paar Pixel mehr darstellen können.

Insider werden jetzt zu Recht einwenden, daß ein Programm mit der eben beschriebenen Fähigkeit bereits existiert („Bigscreen“ von Julian Reschke [ 1 ]), das Ganze also kalter Kaffee ist. Ich habe mich daher ausschließlich der STEs mit ihren neuen Grafikfähigkeiten angenommen und ein Programm ähnlich „Bigscreen“ entwickelt, das die erweiterten Hardware-Fähigkeiten nutzt. Ging bei einem „normalen“ ST und „Bigscreen“ noch sehr viel wertvolle Prozessorzeit dabei verloren, die geänderte Auflösung auf dem Bildschirm darzustellen, macht das ein STE quasi mit Links, man muß nur wissen wie. Deswegen erst einmal ein kleiner Exkurs in die Videohardware der STEs.

Beim STE sind unter anderem die folgenden drei Videoregister ins Leben gerufen worden [2], die es dem Programmierer ermöglichen, dem Videochip flexiblere Darstellungen des Grafikspeichers mitzuteilen. Alle drei Register können sowohl gelesen, als auch beschrieben werden (s. Tab.l).

Diese drei Register machen es möglich, daß wir erhöhte Auflösungen ohne nennenswerten Arbeitsaufwand darstellen können. Natürlich stellt der Monitor jetzt nicht plötzlich 1280 * 800 Pixel dar, wir sehen immer nur einen bestimmten, verschiebbaren Ausschnitt daraus.

Aber, um es noch einmal zu betonen, der Rechenaufwand ist beim STE fast Null, während sich ein ST (ohne E) fast zu Tode arbeiten muß, um ein ähnliches Ergebnis zu liefern.

Das VBASELO-Register macht es möglich, pixelweise vertikal und in 16-Pixel-Schritten (Wortlänge!) horizontal zu scrollen. Pixel weise horizontal scrollen kann man erst mit Hilfe des HSCROLL-Registers, indem dort eine weitere Verschiebung um 0 bis 15 Pixel eingetragen wird.

Zum Verständnis der Wirkungsweise des LINEWID-Registers ein kleines Beispiel: Im Monochrommodus (1 Bitplane) hat eine Bildzeile bei 960 Pixeln horizontaler Auflösung eine Länge von 960 / 16 = 60 Wörtern.

40 Wörter (640 Pixel) werden in hoher Auflösung standardmäßig zur Anzeige gebracht, 20 Wörter müssen im virtuellen Bildschirm also übersprungen werden, um zu den Daten der nächsten Zeile zu gelangen (siehe Bild 1).

Diesen Offset kann man nun in das LINEWID-Register eintragen, und aus wirren Pixel-Mustern wird plötzlich ein ansehnliches Bild, wobei man beachten muß, daß man den Offset auch in Wörtern und nicht in Bytes angibt.

Sobald man jetzt aber in das HSCROLL-Register einen Wert ungleich 0 einträgt, hat man wieder Pixel-Müll auf dem Bildschirm, den man nur durch Verkleinern des Wertes im LINEWID-Register um 1 beseitigen kann. Angezeigt wird in diesem Moment ein Teil des 1. Wortes, dann 39 Wörter komplett und ein Teil des 4L Wortes, also 41 Wörter insgesamt. Daher beträgt die Distanz zur nächsten Zeile jetzt nur noch 19 anstatt 20 Wörter, was entsprechend im LINEWID-Register berücksichtigt werden muß.

Vorrangige Aufgabe des Programmes ist es natürlich, erst einmal dem GEM eine höhere Auflösung mitzuteilen. Dies geschieht durch eine Routine, die sich in den GEM-Vektor einschleift, auf den ersten OPEN WORKSTATION-Aufruf (v_opnwk) wartet und dessen Rückgabewerte sowie einige negative Line-A-Variablen [3] entsprechend abändert. Vorher muß natürlich noch der Bildschirmspeicher so vergrößert werden, daß er die Daten der erhöhten Auflösung aufnehmen kann.

Bezeichnung Adresse Bedeutung
VBASELO $FF820D Low-Byte der Bildschirmbasisadresse. Ermöglicht es, die Adresse auf eine Wortgrenze (bisher 256-Byte-Grenze) zu legen (niederwertigstes Bit wird nicht genutzt, deswegen nur gerade Adressen).
LINEWID $FF820E Offset zur nächsten Zeile. Enthält die Anzahl der Wörter, die am Ende einer Zeile addiert werden, um zur nächsten Zeile zu gelangen. Das High-Byte wird nicht genutzt, daher sind nur Werte von 0 bis 255 möglich.
HSCROLL $FF8264 Anzahl der Bits, um die der Bildschirm nach rechtsverschoben werden soll (ermöglicht horizontales, pixelweises Scrollen).
Die Bits 4 bis 15 werden nicht genutzt, daher sind nur Werte im Bereich von 0..15 möglich. Bei einer Verschiebung um höhere Beträge muß das VBASELO-Register mitbenutzt werden.

Tabelle 1: Die drei Videoregister des STE

Ist das getan, muß das LINEWID-Register entsprechend gesetzt werden (s.o.), um die geänderte Auflösung sichtbar zu machen. Ab jetzt ist nur noch ein Ausschnitt des gesamten Bildes zu sehen.

Um mit dem Programm sinnvoll arbeiten zu können, ist es wünschenswert, den angezeigten Bildausschnitt verschieben zu können. Dabei bietet es sich an, die Bewegung bzw. die Position des Mauszeigers bei der Wahl des Ausschnittes einzubeziehen, so daß der angezeigte Bereich immer mit dem Mauszeiger mitwandert.

Zwei Routinen erledigen diese Aufgabe:

  • eine VBL-Interrupt-Routine, die die Position des Mauszeigers abfragt (negative Line-A-Variablen), die anzuzeigende Bildadresse daraufhin berechnet und den TIMER-B startet.
  • eine TIMER-B-Interrupt-Routine, die die zuvor berechnete Bildadresse in die jeweiligen Videoregister einträgt. Der Timer-B wird so programmiert, daß der Interrupt in der letzten Zeile des Bildaufbaus auftritt, so daß keine sichtbaren Störungen mehr auftreten können, wenn die Registerwerte geändert werden. (Das sonst übliche Setzen der Videoregister innerhalb einer VBL-Routine führt hier eigenartigerweise zu stark ruckelnden und äußerst unbefriedigenden Ergebnissen ?!)
Bild 1: Wirkungsweise des LINEWD-Registers

Das waren soweit die wichtigsten Aktionen, die das Programm erledigen muß, um grundsätzlich zu funktionieren. Nun aber noch ein paar Worte zu den Nebensachen, die auch getan werden müssen, und die dem Programmierer das Leben meist am schwersten machen:

„BigSTE“ muß aus dem Auto-Ordner heraus gestartet werden!

(falls Sie einen GDOS-Treiber besitzen, unbedingt nach dessen Installation!!!)

Da „BigSTE“ vor der Initialisierung des AES installiert werden muß, ist es nötig zu testen, ob das Programm in der Boot-Phase aus dem AUTO-Ordner heraus gestartet wurde. Das können wir überprüfen, indem wir einen appl_init -Aufruf durchführen und den ersten Eintrag im global-Feld auf 0 testen [4]. Bekommt man dort bereits die Versionsnummer des AES und nicht den Wert 0 zurückgeliefert, wurde das Programm erst nach der Initialisierung des AES gestartet, also zu spät.

„BigSTE“ läuft nur auf den STEs!

Deswegen muß überprüft werden, ob der Rechner, auf dem das Programm gestartet wurde, auch ein STE ist. Um das zu testen, fallen mir mehrere Möglichkeiten ein:

  • Test auf Vorhandensein einer STE-TOS-Version
  • Test auf Vorhandensein der STE-Hardware-Register
  • Test auf einen entsprechenden Eintrag im Cookie-Jar

Letzteres Verfahren ist wohl das „sauberste“ und funktioniert folgendermaßen: Die Systemvariable_p cookie {Adresse $5AO) enthält ein Langwort, das ab TOS 1.6 einen Zeiger auf einen Cookie-Jar darstellt [5]. Hat dieser Zeiger den Wert NULL (bei älteren TOS-Versionen), gibt es keinen Cookie-Jar, und der Test wird mit dem Ergebnis, daß es sich bei dem verwendeten Rechner wohl um keinen STE handelt, abgebrochen. Existiert aber ein Cookie-Jar, findet man an der Adresse, auf die _p_cookie zeigt, eine Tabelle mit Wertepaaren vor. In dieser Tabelle sollte sich ein Eintrag mit der Kennung _VDO befinden, wobei der zugehörige Wert die Version der Video-Hardware beschreibt. Hierbei steht ein Wert von $00000000 für die Video-Hardware eines normalen STs, $00010000 steht für die eines STEs und $00020000 für die eines TTs.

Das Programm soll nicht mehrfach installiert werden können!

Da die vom Programm benutzten Vektoren mit Hilfe des XBRA-Verfahrens umgelegt werden, kann man das relativ einfach abtesten, indem man die jeweiligen Vektorketten nach der eigenen XBRA-Kennung absucht. Dieses Verfahren funktioniert aber leider nur, wenn sich Programme, die sich vorher schon in dieselben Vektoren eingeklinkt haben, auch der XBRA-Kennung bedienen.

Wenn in niedriger und mittlerer Auflösungsstufe die Info-Box des Desktops angezeigt wird, wird vom Betriebssystem der TIMER-B benutzt, um die durchlaufenden Farben im Atari-Logo zeichnen zu können. Erstens benötigt „BigSTE“ diesen Timer zum Scrollen, und zweitens wird nach Verlassen der Info-Box der alte Vektor vom Betriebssystem nicht restauriert, daher wird der eigene Vektor vom Programm in jeder VBL-Routine aufs neue eingetragen, um eine einwandfreie Funktion des Programms zu gewährleisten. Auf eine bunte Info-Box muß man jetzt leider verzichten, aber das dürfte wohl eines der kleineren Übel sein.

Mit „BigSTE“ hat man die Möglichkeit, Auflösungen in gewissen Grenzen einzustellen. Die Programmierung der Auflösungseingabe wäre aber relativ aufwendig geworden und hätte das Programm unnötig aufgebläht, da das Programm in Assembler geschrieben ist. Daher habe ich noch ein kurzes Programm in GFA-BASIC geschrieben, das die Konfiguration von „BigSTE“ übernimmt. Es sollte, wie „BigSTE“, im AUTO-Ordner liegen, sinnvollerweise davor, damit sich die Konfiguration direkt auswirken kann. Das Programm wird bei einem Start aus dem AUTO-Ordner nur bei vorher aktiviertem CapsLock durchlaufen, ansonsten gleich wieder beendet! Man hat hier die Möglichkeit, folgende Einstellungen vorzunehmen:

  • „BigSTE“ installieren (ja/nein)
  • Auflösungsstufe in Farbe (niedrig/mittel)
    (Stimmt die Auflösungsstufe nicht mit der in der „DESKTOP.INF“-Datei angegebenen überein, wird sie dort auch noch entsprechend abgeändert.)
  • Auflösungen in Pixeln für alle drei Auflösungsstufen
  • Schieberänder für alle drei Auflösungsstufen
    (Mit Schieberand ist der Randbereich gemeint, bei dem „BigSTE“ anfängt zu scrollen, wenn sich der Mauszeiger hineinbewegt.)

Die Hardcopy-Routine des Betriebssystems kommt mit einer geänderten Bildschirmauflösung leider nicht zurecht, deswegen ist der Vektor dump vec (Adresse $502) auf eine eigene kleine (um nicht zu sagen winzige) Routine verbogen worden. Diese Routine macht schlicht und einfach nichts, außer sofort wieder zurückzuspringen. Auf eine Hardcopy-Funktion muß also leider verzichtet werden.

Zum Schluß noch ein paar Einschränkungen beim Umgang mit „BigSTE“:

Ein Auflösungswechsel über das Desk-top sollte vermieden werden, da „BigSTE“ auf diesen Wechsel nicht reagieren kann. (Es ist aber problemlos möglich, über einen Reset und eine entsprechende Konfiguration von „BigSTE“ die Auflösungsstufen zu wechseln.)

Werden Programme gestartet, die bezüglich der Bildschirmdarstellung „unsauber“ programmiert sind, kann es bei manchen dieser Programme passieren, daß auch nach deren Beendigung die Bildschirmdarstellung nicht mehr korrekt ist. Hier hilft dann meistens nur ein Reset.

Ich habe es trotz unzähliger Versuche leider nicht geschafft, in mittlerer und hoher Auflösung mit Hilfe der STE-Register pixelweise horizontal zu scrollen, ohne daß ein unschöner Seiteneffekt auftritt.

Und zwar klappt ständig ein Teil des rechten Bildes auf die linke Seite um, wenn der Inhalt des HSCROLL-Registers auf 0 wechselt. Hier scheint die Bildsynchronisation gehörig aus dem Tritt zu geraten. Alle Versuche, dieses Register zu verschiedenen Zeitpunkten während des Bildaufbaues zu ändern, haben keine befriedigenden Ergebnisse gebracht. Was bleibt, ist die Vermutung, daß pixelweises, horizontales Scrolling hardwaremäßig nur für die niedrige Auflösungsstufe gedacht ist. Auf eine diesbezügliche Anfrage bei Atari habe ich leider keine Antwort erhalten. Wer hier eine Lösung kennen sollte, möge sie mir bitte mitteilen. In mittlerer und hoher Auflösungsstufe kann deswegen leider auch nur in 16-Pixel-Schritten horizontal gescrollt werden.

Quellennachweis:

[1] Julian F. Reschke: Der weiche Großbildschirm, ST-Magazin 11/1988

[2] Martin Backschat: STarkes noch STErker, ST-Magazin 12/1989

[3] Julian F. Reschke: Saubere Fenster, ST-Magazin 10/1988

[4] Laurenz Prüßner: Reine Existenzfrage, ST-Magazin 2/1990

[5] Julian F. Reschke: Vorhang auf für die Keksdose, ST-Magazin 3/1990

; ----------------------------------------------------------- ; ; BigSTE für Atari-STE ; ; Beschreibung: Simulation erhöhter Auflösungen auf dem Atari STE ; (STE-Hardware erforderlich) ; ; Autor: Matthias Andrä ; Sprache: Assembler ; Progammname: 'BIG_STE,PRG1 (unbedingt so benennen !!!) ; ; Version: 1.2 (c) 1991 MAXON Computer ; ; ----------------------------------------------------------- GEMDOS equ 1 GEM equ 2 XBIOS equ 14 LINE_A equ $A000 ; Line-A-Initialisierung v_lin_wr equ $02 ; Line-A-Variable (Zeilenbreite) BYTES_LIN equ -$02 ; negative Line-A-Variablen V_REZ_VT equ -$04 V_REZ_HZ equ -$0C V_REZ_WR equ -$28 V_CEL_MY equ -$2A V CEL MX equ -$2C V_CEL_HT equ -$2E MOUSE_Y equ -$0258 MOUSE_X equ -$025A DEV_TAB equ -$02B4 VBLVEKTOR equ $70 ; benutzte Vektoren GEMVEKTOR equ $88 TIMERBVEK equ $0120 dump_vec equ $0502 ; Zeiger auf Hardcopy-Routine _p_cookies equ $05A0 ; Zeiger auf Cookie-Jar VBASEHI equ $FF8201 ; diverse (STE-)Video-Register VBASEMID equ $FF8203 VBASELO equ $FF320D LINEWID equ $FF820E ; Offset zur nächsten Zeile HSCROLL equ $FF8264 ; Register für pixelweises Scrollen IERA equ $FFFA07 ; Interrupt EnableRegister ISRA equ $FFFA0F ; Interrupt In-Service Register IMRA equ $FFFA13 ; Interrupt Mask Register TBCR equ $FFFA1B ; Timer B Control Register TBDR equ $FFFA21 ; Timer B Data Register ; ---------------------------------------------- text bra.s start ; zu Programmstart springen dc.b 'BSTE' ; Programmkennung ; Nachfolgende Variablen werden von 'K_BIGSTE.PR6' ; gepatcht und dienen zur Konfiguration von ’BigSTE' aufloesung: dc.w 1 ; Farbauflosung (Mid/Low) ; BigSTE wird nicht installiert, wenn 'aufloesung' >1 !!! rez_plus: dc.w 320,200,0,200,640,560 ; Tabelle: zusätzliche Auflösungen ; wird zu Standardauflösung addiert rand: dc.w 16,16,32,16,32,32 ; Tabelle: hör./vert. Schieberänder start: movea.l 4(SP),A6 ; Basepageadresse movea.w #$0500,A5 ; Größe der Basepage + Stackgröße adda.l 12(A6),A5 ; + Größe TEXT-Segments adda.1 20(A6),A5 ; + Größe DATA-Segments adda.l 28(A6),A5 ; + Größe BSS-Segments move.l A5,D1 ; = Gesamtlänge and.b #$FE,D1 ; Länge gerade add.l A6,D1 ; + Basepageadresse movea.l D1,SP ; Stackende move.l A5,-(SP) ; Programmlänge move.l A6,-(SP) ; Basepageadresse move.l #$4A0000,-(SP) trap #GEMDOS ; Mshrink lea 12(SP),SP lea test_ste(PC),A0 ; auf STE testen bsr supexec ; im Supervisormodus ausführen tst.b ste ; STE-Hardware vorhanden? beq no_ste ; nein, Abbruch bsr appl_init ; 'appl_init' durchführen tst.w global ; geglückt ? bne auto ; dann Abbruch, da BigSTE nicht ; aus Auto-Ordner gestartet wurde cmpi.w #2,aufloesung ; 'aufloesung' > 1 ? bge not_installed ; dann BigSTE nicht installieren dc.w LINEA ; Line-A-Init move.l A0,linea_var ; Variabien-Startadresse merken move.w #3,-(SP) ; Logbase trap #XBIOS ; logische Bildschirmadresse addq.l #2,SP move.l D0,videobase ; merken move.w #4,-(SP) ; Getrez trap #XBIOS ; Auflösungsstufe holen addq.l #2,SP ; Stack korrigieren cmp.w #2,D0 ; hohe Auflösung ? beq.s res_ok ; dann weiter cmp.w aufloesung(PC),D0 ; tats. Farbauflösung = gewünschter ? beq.s resok ; ja, dann weiter move.w aufloesung(PC),-(SP) ; Auflösung setzen (Voreinstellung) move.l #-1,-(SP) move.l #-1,-(SP) move.w #5,-(SP) trap #XBIOS lea 12(SP),SP move.w aufloesung(PC),D0 res_ok: move.w D0,resolution ; merken add.w D0,D0 ; *2 lea planes(PC),A0 move.w 0(AO,D0.w),planeanz add.w D0,D0 ; *2 *2 = *4 lea rand(PC),A0 ; Zeiger auf Randtabellen move.w 0(A0,D0.w),h_rand ; horizontaler Rand move.w 2(A0,D0.w),v_rand ; vertikaler Rand lea rez(PC),A0 ; Zeiger auf Auflösungstabelle move.w 0(A0,D0.w),D6 ; Standardauflösung holen move.w 2(A0,D0.w),D7 move.w D6,h_mon move.w D7,v_mon addi.w #1,h_mon ; +1 = Breite addi.w #1,v_mon ; +1 = Höhe move.w v_mon(PC),D3 lsr.w #1,D3 move.b D3,count ; halbe vertikale Auflösung lea rez_plus(PC),A0 ; Tabelle Auflösungserhöhung move.w 0(A0,D0.w),D4 add.w 2(A0,D0.w),D4 ; keine Auflösungserhöhung? beq not_installed ; dann Ende add.w 0(A0,D0.w),D6 ; X-Wert addieren add.w 2(A0,D0.w),D7 ; Y-Wert addieren move.w D6,h_rez ; und merken move.w D7,v_rez addq.w #1,D6 ; Breite addq.w #1,D7 ; Höhe lsr.w #3,D6 ; Breite / 8 mulu planeanz(PC),D6 ; * Anzahl Planes mulu D6,D7 ; * Hohe = Bildschirmbedarf add.l #255,D7 ; +255 and.1 #$FFFF00,D7 ; auf 256 Byte Grenze bringen move.l D7,D6 sub.l #$8000,D6 ; -32k vorhandenen Bildschirmspeicher move.l #-1,D0 ; Größten freien Speicherblock bsr malloc ; erfragen move.l D0,D5 ; Länge in D5 bsr malloc ; Speicher reservieren movea.l D0,A0 ; Startadresse in A0 move.l D0,D4 ; und D4 merken bsr mfree ; und gleich wieder freigeben add.l D5,D4 ; Länge Speicherblock dazuaddieren cmp.l videobase(PC),D4 ; Block direkt am Video-Ram? bne.s new_v_ram ; nein, weiter cmp.l D6,D5 ; genug Speicher frei? blt memfull ; nein, Meldung ausgeben sub.l D6,D5 ; Freier Speicher minus benötigter move.l D5,D0 ; nach D0 bsr malloc ; 1. Block reservieren movea.l D0,A6 ; Startadresse in A6 merken move.l D6,D0 ; benötigter Speicherplatz bsr malloc ; Block unter Video-Ram reservieren tst.l D0 ; geklappt ? bmi memfull ; nein, Meldung ausgeben move.l D0,videobase ; Startadresse merken movea.l A6,A0 ; Startadresse 1. Block bsr mfree ; Block wieder freigeben bra.s install1 new_v_ram: cmp.l D7,D5 ; genug Speicher frei ? blt memfull ; nein, Meldung ausgeben move.l D7,D0 ; Speicher für Bildschirm bsr malloc ; reservieren tst.l D0 ; geklappt ? bmi memfull ; nein, Meldung ausgeben move.l D0,videobase ; Startadresse merken ; Das alte Videoram (32k) liegt jetzt brach, ; da kein Speicherblock direkt darunter ; reserviert werden konnte ! install1: andi.l #$FFFF00,videobase ; auf 256-Byte-Grenze bringen lea install2(PC),A0 ; ’install2' im bsr supexec ; Supervisormodus tst.b installiert ; BigSTE bereits installiert ? bne installed ; dann Meldung und Abbruch lea TEXT8(PC),A0 ; Bildschirm löschen bsr printline move.w #-1,- (SP) move.l videobase(PC),-(SP) ; Physikalische move.l videobase(PC),-(SP) ; und logische move.w #5,-(SP) trap #XBIOS ; Bildschirmadresse setzen lea 12(SP),SP lea TEXT0(PC),A0 ; Headertext bsr printline lea TEXT3(PC),A0 ; "BigSTE installiert" bsr printline clr.w -(SP) move.l A5,-(SP) move.w #$31,-(SP) ; Ftermres trap #GEMDOS ; Programm resident halten und Ende install2: lea GEMVEKTOR, A0 bsr.s inst_test ; BigSTE schon im GEM-Vektor bne.s install2end ; ja, Abbruch move.l (A0),oldgenrvec ; alten GEM-Vektor sichern und move.l #new_gem,(A0) ; eigene Routine eintragen lea VBLVEKTOR,A0 bsr.s inst_test ; BigSTE schon im VBL-Vektor bne.s install2end ; ja, Abbruch move.l (A0),oldvblvec ; alten VBL-Vektor sichern und move.l #new_vbl,(A0) ; eigene Routine eintragen move.l dump_vec,olddumpvec ; alten Hardcopy-Vektor sichern move.l #hardcopy,dump_vec ; Dummy-Routine eintragen move.l TIMERBVEK,oldtimerb ; alten Timer-B-Vektor sichern move.l #timer_b,TIMERBVEK ; Timer-B-Routine eintragen ori.b #1,IERA ; Timer-B erlauben ori.b #1,IMRA install2end: rts ; -- Testen ob ’BSTE'-Kennung bereits in ; Vektorkette vorhanden ist -------------- inst_test: sf installiert movea.l (A0),A1 testloop: cmpa.l #$08,A1 blt.s testend cmpi.l #'XBRA',-12(A1) ; XBRA-Kennung gefunden ? bne.s testend ; nein, Ende cmpi.l #'BSTE',-8(A1) ; Eigene Programmkennung gefunden ? seq installiert ; Ja, BigSTE bereits installiert beq.s testend ; und Ende movea.l -4(A1),A1 ; Nein, XBRA-Kette weiterverfolgen beq.s testend bra.s testloop testend: tst.b installiert rts ; -- Verschiedene (Fehler)-Meldungen ausgeben — installed: movea.l videobase(PC),A0 bsr mfree lea TEXT1,A0 ; Headertext bsr printline lea TEXT7(PC),A0 ; "BigSTE bereits installiert" bsr printline bra.s waitkey no_ste: lea TEXT1(PC),A0 ; Headertext bsr printline lea TEXT6(PC),A0 ; "Benötigte Hardware fehlt" bsr printline bra.s waitkey memfull: lea TEXT1(PC),A0 ; Headertext bsr printline lea TEXT2(PC),A0 ; "Nicht genug Speicher" bsr printline waitkey: move.w #7,-(SP) trap #GEMDOS ; auf Tastendruck warten addq.l #2,SP bra.s ende ; und Ende not_installed: lea TEXT1(PC),A0 ; Headertext bsr printline lea TEXT4(PC),A0 ; "BigSTE nicht installiert" bsr printline bra.s ende auto: move.w #1,intin move.l #TEXT5,addrin ; BigSTE aus Auto-Ordner starten ! bsr form_alert ; Meldung ausgeben ... bsr appl_exit ; Applikation abmelden ende: clr.w -(SP) trap #GEMDOS ; Ende ; — Rechner auf Vorhandensein der ; STE-Hardware testen ----------- test_ste: movea.l _p_cookies,A0 ; Cookie-Jar vorhanden ? beq.s tst_end ; Nein, dann kein STE cookie_tst: cmpi.l #'_VDO',(A0)+ ; gesuchte Cookie-ID gefunden? beq.s cookie_val ; ja, dann Wert abtesten lea 4(A0),A0 ; nächster Cookie tst.l (A0) ; Ende der Liste ? bne.s cookie_tst ; Nein, weiter tst_end: rts cookie_val: cmpi.l #$010000,(A0) ; Cookie-Wert mind. STE-Videohardware? sge ste ; Flag entsprechend setzen rts ; und zurück ; -- Hardcopy-Dummyroutine ---------------------- dc.b 'XBRA' dc-b 'BSTE' olddumpvec: ds.l 1 hardcopy: rts ; Bloß schnell wieder raus... ; ------------------------------------------------ ; Timer-B-Interrupt starten und Mausaktionen überwachen ... ; -- VBL-Interrupt ----------------------------- dc.b 'XBRA' dc.b 'BSTE' oldvblvec: ds.l 1 new_vbl: sf half ; 1. Hälfte Bildschirm zählen clr.b TBCR ; Timer anhalten move.l #timer_b,TIMERBVEK ; Eigene Timer-B-Routine auf jeden ori.b #1,IERA ; Fall einsetzen und ori.b #1,IMRA ; Timer-B erlauben move.b count(PC),TBDR ; 1/2 Bildschirm zählen move.b #8,TBCR ; Event-Count-Mode starten mouse: movem.l D0-A0,-(SP) ; benutzte Register retten movea.l linea_var(PC),A0 ; Adresse Line-A-Variablen move.w MOUSE_X(A0),D0 ; Maus X-Position move.w MOUSE_Y(A0),D1 ; Maus Y-Position cmp w mousex(PC),D0 ; Mauaposition geändert ? bne.s setnew ; ja, weiter cmp.w mousey(PC),D1 beq mouseend ; nein, Abbruch setnew: move.w D0,mousex ; geänderte Mausposition verarbeiten move.w D1,mousey move.w x_pos(PC),D2 ; linke Ecke Bildschirmanzeige move.w y_pos(PC),D3 ; obere Ecke move.w D2,D4 move.w D3,D5 add.w h_mon(PC),D4 ; rechte Ecke add.w v_mon(PC),D5 ; untere Ecke add.w h_rand(PC),D2 ; Verschieberänder zu sub.w h_rand(PC),D4 ; Bildschirmgrenzen add.w v_rand(PC),D3 ; addieren (links und oben) und sub.w v_rand(PC),D5 ; subtrahieren (rechts und unten) cmp.w D2,D0 ; linker Rand erreicht ? bgt.s pos1 move.w D2,D6 sub.w D0,D6 ; Verachiebewert (positiv) sub.w D6,x_pos ; von Anzeigeposition subtrahieren bge.s pos2 clr.w x_pos ; auf Null setzen bra.s pos2 pos1: cmp.w D4,D0 ; rechter Rand erreicht ? blt.s pos2 move.w D4,D6 sub.w D0,D6 ; Verschiebewert (negativ) sub.w D6,x_pos move.w x_pos(PC),D6 add.w h_mon(PC),D6 cmp.w h_rez(PC),D6 ; schon ganz rechts? blt.s pos2 move.w h_rez(PC),D6 sub.w h_mon(PC),D6 addq.w #1,D6 move.w D6,x_pos ; neue X-Position pos2: cmp.w D3,D1 ; oberer Rand erreicht? bgt.s pos3 ; nein, weiter move.w D3,D7 sub.w D1,D7 ; Verschiebewert sub.w D7,y_pos bge.s adresse clr.w y_pos bra.s adresse pos3: cmp.w D5,D1 ; unterer Rand erreicht ? blt.s adresse ; nein, weiter move.w D5,D7 sub.w D1,D7 ; Verschiebewert sub.w D7,y_pos move.w y_pos(PC),D7 add.w v_mon(PC),D7 cmp.w v_rez(PC),D7 ; schon ganz unten? blt.s adresse ; nein, weiter move.w v_rez(PC),D7 sub.w v_mon(PC),D7 addq.w #1,D7 move.w D7,y_pos ; max. untere Position adresse: moveq #0,D0 move.l D0,D1 move.w x_pos(PC),D0 move.w y_pos(PC),D1 movea.l videobase(PC),A0 ; Bildschirmbasisadresse holen move.w D0,D2 and.w #$0F,D2 move.w D2,shift lsr.w #4,D0 ; X-Position auf Wortgrenze mulu planeanz(PC),D0 ; * Anzahl Planes add.w D0,D0 ; in Bytes adda.l D0,A0 ; zu Bildschirmbasis addieren move.w h_rez(PC),D0 ; hor. Auflösung addq.w #1,D0 ; +1 lsr.w #3,D0 ; /8 mulu planeanz(PC),D0 ; * Anzahl Planes = Bytes pro Zeile mulu D1,D0 ; * Höhe adda.l D0,A0 ; zu Bildschirmbasis addieren move.l A0,videoadr ; neue Videoadresse merken mouseend: movem.l (SP)+,D0-A0 ; benutzte Register restaurieren move.l oldvblvec(PC),-(SP) ; alte VBL-Routine rts ; anspringen ; --------------------------------------------- ; Am Ende des Bildaufbaues Videoadressen setzen ; -- Timer-B-Interrupt ------------------------ dc.b 'XBRA' dc.b 'BSTE' oldtimerb: ds.l 1 timer_b: move.l D0,-(SP) clr.b TBCR ; Timer Stop move.b count (PC),TBDR ; Bildschirmzeilen zahlen move.b #8,TBCR ; Event-Count-Mode starten not.b half bne.s hbl2end ; erst halber Bildschirm gezählt ? setvideo: tst.l videoadr ; aktuelle Videoadresse beq.s hbl2end ; schon gesetzt ? move.b videoadr+1(PC),VBASEHI ; Videoadresse Highbyte move.b videoadr+2(PC),VBASEMID ; Videoadresse Midbyte move.b videoadr+3(PC),VBASELO ; Videoadresse Lowbyte clr.l videoadr ; gesetzt move.w line_wid(PC),D0 ; Video-Offset tst.w resolution ; Auflösung > Low-Resolution bne.s hbl1end ; dann Ende tst.w shift ; Wortgrenze (Pixelverschiebung=0) beq.s set_shift ; ja, weiter sub.w planeanz(PC),D0 ; nein, Offset - (1 *Anzahl Planes) set_shift: move.w shift(PC),HSCROLL ; Verschiebung in Pixeln hbl1end: move.w D0,LINEWID ; Video-Offset zur nächsten ; Zeile in Wortlänge hbl2end: move.l (SP)+,D0 bclr #0,ISRA ; In-Service-Bit löschen rte ; --------------------------------------------------- ; Auf v_opnwk-Aufruf warten und Variablen patchen ... ; -- Trap #2 ---------------------------------------- dc.b 'XBRA' dc.b 'BSTE' oldgemvec: ds.l 1 new_gem: cmp.l #$73,D0 ; VDI-Aufruf ? bne.s oldgem ; nein, zum normalen Aufruf movea.l D1,A0 move.l $0C(A0),intoutadr ; intout-Adresse merken movea.l (A0),A0 ; contrl-Adresse cmpi.w #1,(A0) ; v_opnwk-Aufruf ? bne.s oldgem ; nein, zum normalen Aufruf move.l 2(SP),oldgemret ; Return-Adresse merken move.l #set_vdi,2(SP) ; und neue setzen, oldgem: move.l oldgemvec(PC),-(SP) ; Normalen VDI-Aufruf rts ; ausführen set_vdi: movea.l intoutadr(PC),A0 ; intout-Adresse move.w h_rez(PC),(A0) ; horizontale Auflösung setzen move.w v_rez(PC),2(A0) ; vertikale Auflösung setzen set_linea: movea.l linea_var(PC),A0 move.w h_rez(PC),V_REZ_HZ(A0) ; horizontale Auflösung setzen addq.w #1,V_REZ_HZ(A0) move.w h_rez(PC),DEV_TAB(A0) move.w v_rez(PC),V_REZ_VT(A0) ; vertikale Auflösung setzen addq.w #1,V_REZ_VT(A0) move.w v_rez(PC),DEV_TAB+2(A0) move.w V_REZ_HZ(A0),D0 ; horizontale Auflösung lsr.w #3,D0 ; /8 = Bytes pro Zeile move.w D0,V_CEL_MX(A0) subq.w #1,V_CEL_MX(A0) ; maximale Cursorspalte mulu planeanz(PC),D0 ; * Anzahl Planes move.w D0,v_lin_wr(A0) ; Bytes pro Zeile move.w D0,BYTES_LIN(A0) mulu V_CEL_HT(A0),D0 ; * Zeichensatzhöhe move.w D0,V_REZ_WR(A0) ; = Bytes pro Charakterzeile moveq #0,D0 move.w V_REZ_VT(A0),D0 ; vertikale Auflösung divu V_CEL_HT(A0),D0 ; / Zeichensatzhöhe subq.w #1,D0 ; - 1 move.w D0,V_CEL_MY(A0) ; = maximale Cursorzeile lea set_video(PC),A0 ; ’set_video' im bsr.s supexec ; Supervisormodus ausführen movea.l oldgemret(PC),A0 jmp (A0) ; in aufrufendes Programm zurück set_video: movea.l linea_var(PC),A0 ; Zeiger auf Line-A-Variablen lea line_w(PC),A2 ; Zeiger auf Tabelle (Bytes/Zeile) move.w resolution(PC),D1 ; Auflösungsstufe holen add.b D1,D1 ; *2 move.w V_REZ_HZ(A0),D0 ; horizontale Auflösung lsr.w #4,D0 ; /16 mulu planeanz(PC),D0 ; * Planesanzahl = Worte pro Zeile sub.w 0(A2,D1.w),D0 ; - Worte pro Zeile (Standard) move.w D0,LINEWID ; = Video-Offset zur nächsten Zeile move.w D0,line_wid ; Offset merken move.l oldgemvec(PC),GEMVEKTOR ; alten GEM-Vektor restaurieren rts ; -- Betriebssystemaufrufe ---------------------- printline: pea (A0) ; Startadresse in AO move.w #$09,-(SP) ; Text auf Bildschirm ausgeben bra.s trapgemdos malloc: move.l D0,-(SP) ; Länge in D0 move.w #$48,-(SP) ; Speicher reservieren bra.s trapgemdos mfree: pea (A0) ; Adresse in A0 move.w #$49,-(SP) ; Speicher freigeben trapgemdos: trap #GEMDOS bra.s stackkor supexec: pea (A0) ; Startadresse der Routine in a0 move.w #38,-(SP) ; im Supervisormodus trap #XBIOS ; ausführen stackkor: addq.l #6,SP rts ; -- GEM-Aufrufe -------------------------------- form_alert: move.l #$340001,control move.l #$010001,control+4 bra.s call2gem appl_init: move.l #$0A0000,control bra.s call1gem appl_exit: move.l #$130000,control call1gem: move.l #$010000,control+4 call2gem: clr.w control+8 move.l #aespb,D1 move.w #$C8,D0 trap #GEM rts ; ----------------------------------------------- .data rez: dc.w 319,199,639,199,639,399 ; Tabellen:Standardauflösungen line_w: dc.w 80,80,40 planes: dc.w 4,2,1 mousex: dc.w 0 ; alte Maus-X-Position mousey: dc.w 0 ; alte Maus-Y-Position half: dc.b 0 count: dc.b 0 ste: dc.b 0 installiert: dc.b 0 TEXT0: dc.b 27,'E' TEXT1: dc.b 13,10,27,'p',' BigSTE ',27,’q Version 1.2',13,10 dc.b '5/91, Matthias Andrä',13,10,0 TEXT2: dc.b 'Nicht genug freier Speicher!!!',13,10,0 TEXT3: dc.b 'Installation durchgeführt ...',13,10,0 TEXT4: dc.b 'Nicht installiert ...',13,10,0 TEXT5: dc.b '[1][ |BigSTE muß unbedingt bei|Systemstart aus dem Auto-Ordner|herausgestartet werden!][ Ok ]',0 TEXT6: dc.b 'Hardwarevoraussetzungen nicht gegeben !',13,10,0 TEXT7: dc.b 'BigSTE bereits installiert!!!',13,10,0 TEXT8: dc.b 27,'E',0 aespb: dc.1 control,globa1,intin,intout,addrin,addrout bss linea_var: ds.l 1 intoutadr: ds.l 1 videobase: ds.l 1 videoadr: ds.l 1 oldgemret: ds.l 1 x_pos: ds.w 1 ; Darstellung ab X-Position y_pos: ds.w 1 ; Darstellung ab Y-Position h_mon: ds.w 1 ; hor. Monitorauflösung v_mon: ds.w 1 ; vert. Monitorauflösung hrez: ds.w 1 ; eingestellte hör. Auflösung v_rez: ds.w 1 ; eingestellte vert. Auflösung h_rand: ds.w 1 ; eingestellter hor. Schieberand v_rand: ds.w 1 ; eingestellter vert. Schieberand line_wid: ds.w 1 resolution: ds.w 1 planeanz: ds.w 1 shift: ds.w 1 control: ds.w 5 global: ds.w 15 intin: ds.w 16 intout: ds.w 7 addrin: ds.l 3 addrout: ds.l 1 end ' ****************************************** ' * BigSTE-Konfigurationsprogramm 12/90 * ' * Version 1.02 Matthias Andra * ' * (c) 1991 MAXON Computer * ' ****************************************** ' Bootdev%=Dpeek(&H446)+65 ! Bootlaufwerk Bste$=Chr$(Bootdev%)+":\AUTO\BIG_STE.PRG" ! Pfad BigSTE Desktopinf$=Chr$(Bootdev%)+":\DESKTOP.INF" ! Pfad DESKTOP.INF ' If Dpeek(Lpeek(Gb+4))<>0 Or (Bios(11,-1) And &H10) ' Programm normal gestartet, ' oder bei Systemstart aus Auto-Ordner mit Caps-Lock aktiv? Void Bios(11,0) ! Caps-Lock desaktivieren Print If Exist(Bste$) Then ! 'BIG_STE.PRG' suchen Open "U",#1,Bste$ Seek #1,&H1C+2 If InputS(4,#1)="BSTE" Then ! Programmkennung korrekt? @Konfiguration ! Dann konfigurieren Else Print "'BIG_STE.PRG' ist nicht BigSTE ..." Fehler!=True ! Programm unbekannt Endif Close #1 Else Print "'BIG_STE.PRG' nicht gefunden ..." Fehler!=True ! BigSTE nicht im Auto-Ordner. Endif Print If Fehler! Then Print "Konfiguration nicht möglich !!!" Else Print "BigSTE konfiguriert ..." @Patch_desktop_inf ! Auflösung in "DESKTOP.INF" anpassen Endif Print Endif ' Pause 20 Edit ' Procedure Konfiguration ' Einlesen der alten BigSTE-Parameter, ' Verändern der Werte durch Benutzer und ' neues Setzen der BigSTE-Parameter Local A$,B$,A% Repeat Cls Print '''''''Chr$(27);"p BigSTE -Konfiguration ";Chr$(27);"q" Print " Version 1.02" Print " von Matthias Andrä" ' Seek #1,&H1C+6 ' A$="j" Print At(1,5);"BigSTE Installation (j,n)?: "; Form Input 1 As A$ A$=Upper$(A$) A%=Cvi(Input$(2,#1)) Relseek #1,-2 If A$="J" Then Print #1,Mki$(A% And 1); Relseek #1,-2 @Werteingabe(7,"Farb-Auflösungsmodus [0,1] ?: ",0,1,1,1) ' Print At(1,9);"Niedrige Auflösung (in Pixel)" @Werteingabe(10,"Horizontal [320..1280]?: ",320,1280,16,4) @Werteingabe(11," Vertikal [200..800]?: ",200,800,8,3) Print At(1,9);"Mittlere Auflösung (in Pixel)" @Werteingabe(10,"Horizontal [640..2560]?: ",640,2560,16,4) @Werteingabe(11," Vertikal [200..800]? : ",200,800,8,3) Print At(1,9);"Hohe Auflösung (in Pixel)" @Werteingabe(10,"Horizontal [640..2560]?: ",640,2560,16,4) @Werteingabe(11," Vertikal [400..1600]? : ",400,1600,16,4) ' Print At(1,13);"Schieberand (niedrige Auflösung)" @Werteingabe(14,"Horizontal [0..120] ?: ", 0,120,1,3) @Werteingabe(15," Vertikal [0.75] ?: ", 0, 75,1,2) Print At(1,13);"Schieberand (mittlere Auflösung)" @Werteingabe(14,"Horizontal [0..240] ?: ",0,240,1,3) @Werteingabe(15," Vertikal [0..75] ?: ", 0,75,1,2) Print At(1,13);"Schieberand (hohe Auflösung) " @Werteingabe(14,"Horizontal [0. 240] ?: ", 0,240,1,3) @werteingabe(15," Vertikal [0.150] ?: ", 0,150,1,3) ' B$="j" Print At (1,17);"Eingaben in Ordnung (j, n): "; Form Input 1 As B$ B$=Upper$(B$) Else Print #1,Mki$(A% Or 2); Endif Until A$<>"J" Or B$="J" Return ' Procedure Werteingabe(Y%,Text$,Min%,Max%,Schritt%,Stellen%) ' Automatisierte Werteingaberoutine Local Wert$ Wert$=Str$(Cvi(Input$(2,#1))+Min%) Repeat Print At(1,Y%);Chr$(27);"K";Text$; Form Input Stellen% As Wert$ Wert$=Str$((Val(Wert$) Div Schritt%)* Schritt%) Until Val(Wert$)>=Min% And Val(Wert$)<=Max% Print At(1,Y%);Chr$(27);"K";Text$;Wert$ Relseek #1,-2 Print #1,Mki$(Val(Wert$)-Min%); Return ' Procedure Patch_desktop_inf Local A$,A%,B%,P% Print If Exist(Desktopinf$) If Exist(Bste$) Then Open "U",#1,Desktopinf$ Open "I",#2,Bste$ Seek #2,&H1C+2 If Input$(4,#2)=”BSTE" Then ! BigSTE Programmkennung korrekt? A%=Cvi(Input$(2,#2)) ! BigSTE Auflösungsstufe lesen. If A%<2 Then ! Soll BigSTE installiert werden? A%=2-A% ! Auflösung in 'DESKTOP.INF'-Format A$=Input$(Lof(#1),#1) P%=Instr(A$,"#E ") ! Auflösungsinformation im "DESKTOP.INF" If P%>0 Then ! gefunden? B%=Val("&"+Mid$(A$,P%+7,1)) ! Lesen If B%<>A% ! Auflösungen unterschiedlich? Seek #1,p%+6 Out #1,Asc(Hex$(A%)) ! Auflösung in "DESKTOP.INF" schreiben. Print "BigSTE-Auflösung in 'DESKTOP.INF' angepafit ..." Endif Endif Endif Else Print "'BIGSTE.PRG' ist nicht BigSTE ..." ! Programm unbekannt. Endif Close Else Print "'BIG_STE.PRG' nicht gefunden ..." Endif Else Print "'DESKTOP.INF' nicht gefunden ..." Endif Print Return
Matthias Andrä