Wrapmouse, der ultimative Treiber für Mäuse aller Art, Teil 2

Nachdem der letzte Teil praktisch frei von Grundlagen war, rücken wir Wrap-Mouse anhand des Quelltextes näher zu Leibe und sezieren die Ausgaben der MS-DOS-Mouse.

Eines der Hauptprobleme bei der Realisierung von Wrap-Mouse waren die zum Anschluß an IBM und kompatible Rechner vorgesehenen Mäuse. Sie unterscheiden sich in der Arbeitsweise grundlegend von unseren gewohnten Atari-Mäusen, da bei den ersten MS-DOS-Computern kein eigener Maus-Anschluß vorgesehen war. Aufgrund dieses Mangels nutzt die Masse der Maus-Produzenten die serielle Schnittstelle (RS232) als Eingang für die Mausdaten. Damit die Mäuse diesen Port bedienen können, sind sie mit einem Mikrokontroller bestückt. Er wertet die Bewegungsdaten aus und sendet sie Byte-weise an die serielle Schnittstelle. Um Übersicht zu vermeiden, kochen die verschiedenen Hersteller ein eigenes »Übertragungssüppchen«. Zu unserem Glück kristallisierten sich aus diesem Chaos die Übertragungsformate von Microsoft und Mouse-Systems als Pseudo-Standards heraus. Der Standard der jeweiligen MSDOS-Maus entnehmen Sie der Bedienungsanleitung.

Microsoft

Die serielle Microsoft-Mouse und ihre Nachbauten haben zwei Maustasten und übertragen die Bewegungsdaten in drei Byte großen Päckchen mit einer Rate von 1200 Baud. Im ersten Byte steckt die Anfangskennung, der Status der Maustasten und die Vorzeichen für die Mausbewegungen. Die folgenden zwei Byte enthalten die relative Bewegung der Maus seit der letzten Abfrage. Allerdings ist diese Information in den unteren 6 Bit kodiert. Um die Verwirrung noch zu steigern, geschieht dies in Abhängigkeit von den Vorzeichen aus dem ersten Byte. Sind sie gesetzt, war die betreffende Bewegung negativ und der Wert ist ein Zweierkomplement. Bei gelöschtem Vorzeichen handelt es sich um eine einfache 6 Bit Zahl. Um aus den unteren 6 Bits des zweiten und dritten Bytes die tatsächlichen Werte zu errechnen, müssen die Vorzeichen aus dem ersten Byte berücksichtigt werden. In Pseudo-Code sieht das dann so aus:

wenn Byte_1 and 3
	X_Bewegung = -(192-Byte_2)
sonst X_Bewegung = Byte_2-128
wenn Byte_1 and 12
	Y_Bewegung = -(192-Byte_3)
sonst Y_Bewegung = Byte_3-128

Mouse-Systems

macht natürlich alles ganz anders. Diese Mäuse haben drei Maustasten und übertragen die Bewegungsdaten in 5 Byte großen Päckchen, wiederum mit 1200 Baud. Im ersten Byte steckt die Anfangskennung und der Status der Maustasten. Im zweiten, dritten, vierten und fünften Byte sind die relativen Bewegungsdaten seit der letzten Abfrage enthalten (Tabelle 2). Wichtig: Pro Päckchen sendet die Maus zwei Abfragen der Mausposition. In Byte zwei und drei bzw. vier und fünf, jeweils als XY-Paar. Zwar sind diese Werte »normale« 8-Bit-Werte, dafür ist die Bewegungsrichtung der Y-Achse umgekehrt zum Microsoft- und Atari-Standard und muß durch Vorzeichenwechsel angepaßt werden. Da beide Maustypen ihre Werte unaufgefordert bei einer Mausbewegung oder einem Druck auf eine Maustaste an den Rechner senden, sind die RS232-Routinen des Atari-Betriebssystems unbrauchbar. Wir müssen also eine eigene Interrupt-Routine für die gewünschte Schnittstelle installieren. Auf einem »normalen« ST, Stacy oder Book fällt die Wahl nicht schwer, da nur eine serielle Schnittstelle vorhanden ist. Auf dem TT und Mega STE kann die Wahl schon eher zur Qual werden. Das Modul »RS232A.S« auf der TOS-Diskette bietet Treiber für alle Schnittstellen.

Damit die Übersichtlichkeit gewahrt bleibt, ist nur die Empfangsroutine in Assembler geschrieben. Die jeweilige Auswertung erfolgt im Modul »RS232.C« durch die Funktion »chk_rs()«. Sie sammelt die Daten bis zum Erhalt eines ganzen Päckchens und übergibt die umgerechneten Daten an das Betriebssystem. Erste Versuche ergaben, daß sich MS-DOS-Mäuse bei der Übergabe der Daten im Verhältnis zur Atari-Maus viel Zeit lassen. Das Ergebnis: Der Mauszeiger holpert etwas schwerfällig auf dem Bildschirm. Um dieses Ruckeln zu vermindern, installiert Wrapmouse auf Wunsch eine VBL-Interrupt-Routine, die die empfangenen Daten in zwei Portionen an das Betriebssystem weitergibt, wobei sich das Ruckeln annähernd halbiert.

Joystick-Maus

Wie im letzten Teil bereits erwähnt, erlag der Autor bei den Basteleien an Wrap-Mouse dem Programmierer-Wahn und baute bei dieser Gelegenheit auch noch eine Maus-Simulation via Joystick (Port 2) ein. Die Frage nach der Verwendung von Betriebssystem-Routinen stellt sich bei dieser Arbeit nicht, da das BIOS den Joystick erst gar nicht unterstützt. In den Modulen »WMJOYSI.S« und »WMJOY.C« finden sich daher die entsprechenden Routinen. Ein kleines Problem haben wir aber noch zu bewältigen! Der Feuerknopf des Joysticks in Port 2 ist von Atari hardwaremäßig auf die rechte Maustaste gelegt. Um also den Joystick-Feuerknopf als linke Maustaste einsetzen zu können, müssen wir die Maustasten via Software vertauschen. Dazu später mehr.

Im Gegensatz zur Maus, liefert der Joystick nur absolute Schalterstellungen für die vier Richtungen. Damit der Maustreiber des Betriebssystems damit etwas anfangen kann, müssen wir diese kontinuierlichen High- bzw. Low-Werte in Mausdaten verwandeln. Am einfachsten wäre es, für jeden Pegelwechsel am Joystickport die Maus um ein Pixel zu bewegen, was aber in einer Fülle von Joystickbewegungen ausartet. Um der Entwicklung von Popeye-ähnlichen Unterarmen vorzubeugen, überwacht Wrap-Mouse den Joystick im VBL. Damit wird, je nach Bildschirmauflösung, 50 bis 70 mal pro Sekunde die Richtung am Joystick abgefragt und in eine Mausbewegung verwandelt, indem wir dem Maustreiber ein »gefälschtes« Datenpaket unterschieben. Leider ist auch diese Vorgehensweise nicht ganz optimal. Der Versuch den Mauszeiger um genau ein Pixel zu bewegen artet damit in ein Geduldsspiel aus. Für den endgültigen »Durchbruch« muß also auch noch ein Wartezeit am Anfang der Bewegung berücksichtigt werden. Um den Komfort noch ein wenig zu steigern und die Geduld des Anwenders nicht über Gebühr zu strapazieren, verwaltet Wrap-Mouse den Joystick dynamisch: je länger er in eine Richtung gedrückt wird, desto schneller bewegt sich der Mauszeiger.

Speedy Gonzales

Womit wir beim universellen Mausbeschleuniger angelangt sind. Im Grunde sind in Wrapmouse drei Beschleuniger eingebaut: für die Atari-Maus, die serielle Maus und den Joystick. Vom Prinzip her funktionieren sie allerdings ähnlich und sind in ihrer Dynamik frei definierbar. Ein dynamischer Maustreiber kennt prinzipiell zwei Wege: Er überwacht die Dauer einer Bewegung und verstärkt das Signal um so mehr, je länger diese Bewegung anhält. Oder er überwacht die Schrittweite der Bewegung, und verstärkt in Abhängigkeit der Bewegungsgeschwindigkeit die Beschleunigung. Zu welchem der Ansätze man sich entschließt, ist reine Geschmackssache, beide haben Vor- und Nachteile. Wir haben uns in Wrapmouse für die Überwachung der Schrittweite entschlossen. In den Modulen »WMMOUSE.C« und »WMASS.S« finden Sie die entsprechenden Routinen. Da für die Verwirklichung eines Beschleunigers schon eigene Maus-Routinen notwenig waren, beseitigt Wrapmouse bei dieser Gelegenheit ein weiteres Übel: Wer einen Großbildschirm oder einen gewissen Hang zur Bequemlichkeit besitzt, hat sich wahrscheinlich über die langen Bildschirmwege geärgert. Warum also keine Abkürzung über den Bildschirmrand hinaus einbauen, frei nach dem Motto: »Links hinaus und rechts herein - kann ja nicht so schwierig sein.« Leider wirft uns das Betriebssystem bei diesem Vorhaben einige Steine in den Weg, da es eigentlich keinen sauberen Weg gibt, aus einem Interrupt heraus die Maus abzufragen oder gar neu zu setzen. Ein brauchbarer Kompromiß der auch auf dem TT dem Falcon und mit Grafikkarten funktioniert, ist das wiederholte Aufrufen der original Mausroutine mit den entsprechenden Werten. Wenn die Maus zum Beispiel in der ST-Hoch-Auflösung vom linken an den rechten Bildschirmrand soll, muß die Mausroutine fünf mal mit dem Wert »128 Pixel nach rechts« aufgerufen werden. Zur Abfrage der aktuellen Mausposition verwenden wir die VDI-Variablen, für die Atari mittlerweile das Leserecht eingeführt hat.

Damit die Maus nun nicht bei jeder Gelegenheit sofort den Bildschirm »umkreist«, kann die Anzahl der Stöße an den Bildschirmrand, die zu einem »Durchbruch« führen, individuell und für jeden Rand einzeln eingestellt werden. Bei jeder Mausbewegung testet Wrap-Mouse, ob die Maus den Bildschirmrand verlassen würde. Wenn ja, erhöht sich der Zähler um Eins, bis die »Durchbruchsmarke« erreicht ist, wenn nicht, geht der Zähler wieder auf Null.

Maustasten-Komfort

Um den Joystick vernünftig als Mausersatz einsetzen zu können, mußten wir ja schon eine Möglichkeit zum Vertauschen der Maustasten einbauen. Was liegt nun näher, als aus dieser Pflicht eine Kür zu machen. Im Modul »WMMOUSE.C« ist die Funktion »do_changes()« hierfür zuständig. Aus Links wird Rechts und umgekehrt. Damit die rechte Maustaste in Zukunft nicht mehr verkümmert, kann sie für die Kür mit Wrapmouse auch als Shift, Control, Alternate oder Doppelklick fungieren. Das Vertauschen der Tasten ist die einfachste Übung. In den Werten, die der original Maustreiber untergeschoben bekommt, müssen wir lediglich die Bits für die Maustasten umdrehen. Auch der Doppelklick ist nicht schwer zu realisieren: Anstelle eines Druckes auf die rechte Maustaste melden wir dem Betriebssystem: Einen Links-Klick, das Loslassen desselben, erneuter Links-Klick und wieder loslassen. Etwas schwieriger ist die Simulation der Sondertasten, speziell in der Kombination mit dem Doppelklick. Zuerst müssen wir unterscheiden, ob eine Sondertaste oder der Doppelklick erzeugt werden soll. Klickt der Anwender nur mit der rechten Maustaste, geht Wrapmouse von einem Doppelklick aus. Kommt vor dem Loslassen der rechten Maustaste nun auch noch ein Druck auf die linke Maustaste hinzu, setzt WrapMouse die Bits für die Sondertasten in der Systemvariablen »kbshift« und sendet keinen Doppelklick. Damit kann man auf dem Desktop ohne Zuhilfenahme von <SHIFT> mehrere Dateien mit den beiden Maustasten selektieren, oder mit einem Druck auf die rechte Maustaste ein Programm starten.

Aber wie immer - kein Licht ohne Schatten. Einige Programme mögen es überhaupt nicht, wenn plötzlich die rechte Maustaste zweckentfremdet wird, da sie diese für eigene Zwecke einsetzen (z.B. Calamus). Um ein einwandfreies Arbeiten auch mit solchen Programmen zu gewährleisten, erlaubt es Wrap-Mouse, jedem Programm eine eigene Belegung der Maustasten zu erstellen. Für das Umschalten der Belegungen zapfen wir die GEMDOS-Funktion »Pexec()« an. Interessierte Leser finden diesen Programmteil in »WMMOUSE.C« unter »do_switch()«.

Ein Appell zum Schluß

Gerüchteweise habe ich von MS-DOS-Mäusen mit erweitertem Funktionsumfang (mehr Tasten, Macro-Fähigkeit, höherer Baudrate) gehört. Sollten Sie ein derartiges Wundertier besitzen und den Anschluß an seinen Atari wünschen, stehe ich zur gerne Verfügung. Schreiben Sie an:
Richard Kurz
Vogelherdbogen 62
7992 Tettnang (ah)

Hinter den Kulissen

   
WMMAIN.C Der Start mit diversen Initialisierungsarbeiten
WMMOUSE.C Die Routinen für die originale Atari-Maus, der Speeder und die Wrap-Funktion.
WMASS.S Die zugehörigen Assembler-Routinen
WMJOY.C Der Joystick simuliert die Maus.
WMJOYSI.S Die zugehörigen Assembler-Routinen.
WMRS232.C Die Behandlung der seriellen Mäuse
WMRS232A.S Die zugehörigen Assembler-Routinen.
COOKIE.C Cookie-Verwaltungsroutinen.
COOKIASS.S Die zugehörigen Assembler-Routinen.

Alle Quelltexte sind auf der TOS-Diskette dieser Ausgabe.

Microsoft-Datenformat

Header und Status (Byte 1)

Bit Bedeutung
0+1 Vorzeichen für X-Bewegung (negativ, wenn gesetzt)
2+3 Vorzeichen für Y-Bewegung (negativ, wenn gesetzt)
4 Status der rechten Maustaste (1 = gedrückt)
5 Status der linken Maustaste (1 = gedrückt)
6+7 Anfangskennung (immer gesetzt)

Bewegung in der X-Achse (Byte 2)

Bit Bedeutung
0-5 Wert der X-Bewegung
6 stets 0
7 stets 1

Bewegung in der Y-Achse (Byte 3)

Bit Bedeutung
0-5 Wert der Y-Bewegung
6 immer 0
7 immer 1

Tabelle 1: Microsoft kodiert die Mausbewegungen in drei Byte.

Mouse-Systems-Datenformat

Header und Status (Byte 1)

Bit Bedeutung
0 Status der rechten Maustaste
1 Status der linken Maustaste
3-6 immer 0
7 immer 1
Bit Bedeutung
2 Bewegung in der X-Achse
3 Bewegung in der Y-Achse
4 Bewegung in der X-Achse
5 Bewegung in der Y-Achse

Richard Kurz
Aus: TOS 03 / 1993, Seite 61

Links

Copyright-Bestimmungen: siehe Über diese Seite