Quick-Tips

Abfrage des Joysticks in Turbo C

Als ich vor kurzem eine Joystick-Abfrage mit Hilfe der Kommandos des Tastatur-Chips programmieren wollte, stellte ich fest, daß das vom IKBD gesendete Statuspaket für Joystick-Ereignisse nicht das in der Fachliteratur (Profibuch, ST Intern) beschriebene Format besitzt. Denn statt aus zwei besteht das Paket aus drei Bytes, da im zweiten Byte immer der Zustand von Joystick 0 und im dritten Byte immer der Zustand von Joystick 1 gemeldet wird. Das erste Byte zeigt lediglich an, ob zuletzt von Joystick 0 ($FE) oder Joystick 1 ($FF) ein Ereignis gemeldet wurde. Somit kann das erste Byte getrost ignoriert werden, falls man diese Information nicht benötigt. Mein Listing zeigt, wie man ganz leicht eine eigene Auswertungsroutine für dieses Statuspaket in Turbo C installieren kann. Die Installation funktioniert nur in Turbo C so leicht, da Turbo C Parameter über Register übergibt (soweit möglich).

Achim Pauls

#include <tos.h> 

typedef struct 
    { 
        char header, /* 'letzte' Meldung: J0, J1 */ 
             val[2]; /* Bit 0: up, 1: dn 3: rt 4: lf, 
                        7: button */ 
    } JOYEVENT; 

void joystick_report(JOYEVENT *paket) 

{ 
/* Hier Auswertung des Steuerpakets. 8UNG! */ 
/* nicht zu lange, da Interrupt!           */ 
} 

void init_joystick(void) 
{ 
    Ikbdws(1,"\x13"); /* Daten vom IKBD: Stop */ 
    
    Kbdvbase()->kb_joyvec = joystick_report; 
    /* Neuen Vektor setzen, alten evtl. merken */ 
    Ikbdws(1,"\x12"); /* Maus aus, nur JSticks */ 
    Ikbdws(1,”\x14"); /* Joystick-Modus aus */ 
} 
 
void exit_joystick(void) 
{ 
    Ikbdws(1,"\x80\x01"); /* IKBD-Reset */ 
} 

int main(void) 
{ 
    init_joystick(); 
    /* Hier Hauptprogramm einfügen! */ 
    exit_joystick(); 
}

Listing 1: Einfache Abfrage des Joysticks in Turbo C

Genauer Timer in CCD-Pascal

In GFA-BASIC und Omikron.BASIC gibt es die nützlichen Befehle TIMER und WATT (letzteren nur in Omikron.-BASIC). Diese Funktionen benutzen die dokumentierte Systemvariable _hz_200 an der Adresse $4BA. Es handelt sich um eine Long-Variable (32 Bits), und sie wird vom MFP 200mal pro Sekunde inkrementiert. Damit eignet sie sich hervorragend zur Zeitmessung, wie sie die obigen BASIC-Dialekte auch zur Verfügung stellen. Leider kennt das CCD Pascal (1.4) nur die Funktion CLOCK mit einer Auflösung von mickrigen 2 Sekunden. Das direkte Lesen der 200 Hz-Systemvariablen bleibt dem (sauberen) PASCAL-Programmierer wegen fehlender PEEKs versperrt, zumal ein Zugriff nur im Supervisormodus erlaubt ist. Abhilfe schafft entweder die Einbindung der PASTRIX-Routinen (siehe Q-Tips in Ausgabe 6/90) oder die hier vorgestellte Lösung, die nur mit der im CCD-Pascal fest implementierten XBIOS-Funktion Supexec [XBIOS(38)] auskommt. Supexec führt ein Maschinenprogramm im Supervisormodus aus, wozu es als einzigen Übergabeparameter die Startadresse der Routine benötigt. Wird Supexec als function deklariert, muß das Maschinenprogramm in dem Prozessonregister D0 den entsprechenden Wert zurückgeben. Die Opcodes werden in Pascal am einfachsten als RECORD abgelegt, der Supexec als Var-Parameter übergeben wird. Nur so setzt der Compiler die Adresse des RECORDs und damit der Routine ein. Diese Art der Implementierung von Maschinencode eignet sich hervorragend für klein(st)e Aufgaben wie den Zugriff auf Systemvariablen oder Peripherieadressen. Zurück zur Timer-Routine, die im wesentlichen aus zwei Maschinenbefehlen besteht: Der erste lädt den 200 Hz-Zähler nach D0, der zweite ist schon der Rücksprung. Mit der function timer ist dann die Realisierung einer wait-procedure nur noch eine leichte Fingerübung.

Bernd Blank

program timertest(input,output); 

function timer: long__integer; 
{liefert den Wert der Systemvariablen _hz_200 
zurück, der 200mal pro Sek. inkrement. wird) 

    type prog_rec = packed record {für opcodes} 
            op1: long_integer; 
            op2: integer 
         end; 
    var prog: prg_rec; 

    function Supexec(var prg: prg_rec): long_integer; 
        XBIOS(38); 

begin {timer} 
    prog.op1 := $203804BA; {move.l $04BA.w,D0} 
    prog.op2 := $4E75;     {rts              } 
    timer := Supexec(prog) 
end; {timer} 

procedure wait(secs: real); 
    var time: long_integer; 
begin 
    time := timer + long_round(secs*200); 
    while time>timer do; 
end; {wait} 

begin {timertest} 
    repeat 
        writeln(timer); 
        wait(0.5) 
    until keypress 
end.

Listing 2: Ein 200 Hz-Timer in CCD-Pascal mittels Supexec

Proportionalschrift in 20 cpi

Ich habe mir vor einiger Zeit einen NEC P6plus zugelegt, und da man nach so einer Anschaltung die ersten Blätter zum „Ausprobieren“ in den Papier korb produziert, habe ich mächtig ‘rumgetestet! Als ich nun in GFA-BASIC versucht habe, ein bißchen softwaremäßig zwischen den Fonts hin- und herzuschalten, ist mir folgendes aufgefallen: Wenn man (per ESC-Sequenz)einen nicht-proportionalen Font auswählt, den auf z.B. 20cpi einstellt und dann auf einen Proportional-Font umschaltet, passiert Sagenhaftes! Der verwirrte P6plus druckt tatsächlich einen Proportional-Font in 20 cpi (z.B. Times)! Damit lassen sich viele interessante Schriftbilder „zusammenbasteln“. Aber wie oben erwähnt - nicht auf der Tastatur des Druckers z.B. Courier auswählen, 4mal Pitch drücken (um eine 20 im LED Display erscheinen zu lassen) und dann auf Times umschalten -das klappt nicht! Viel Spaß mit den neuen Fonts!

Oliver Mohr

Neue „imagesize“-Funktion in Turbo C

Die Funktion imugesize in der BGI Bibliothek der neuen Version von Turbo C arbeitet nicht korrekt. Die Funktion soll den Speicherbedarf für einen Bildausschnitt errechnen, der dann per malloc reserviert werden soll. Der Bildausschnitt wird dann mit getimage in diesen Speicherbereich kopiert (siehe: Referenzhandbuch zu Turbo C 2.0 Seite 119). Die Funktion imugesize berechnet allerdings falsche (zu kleine) Werte. Mit malloc wird dadurch zu wenig Speicher reserviert. Der nachfolgende getimage-Aufruf überschreibt dann unkontrolliert den Speicher. In einem meiner Programme hat dies zu ständigen Systemabstürzen geführt, de ren Ursache wohl hierin zu suchen ist. Zur Demonstration des Fehlers beachten Sie bitte Listing 3. Das Programm errechnet für den gesamten Bildschirm (0,0 bis 639. 399) einen Platzbedarf von gerade einmal 7428 Bytes! Um diesen Fehler zu umgehen, habe ich die Funktion imagesz2 geschrieben. Sie liefert in obigem Beispiel einen Wert von 32804 Bytes zurück. Nachdem ich in meinem programm imagesize durch imagesz2 ersetzt hatte, waren keine Abstürze mehr vorhanden!

Michael Benz


 #include <stdlib.h> 
 #include <stdio.h> 
 #include <graphics.h> 
 
 int graphdriver=DETECT, graphmode; 
 
 unsigned imagesz2(int left,int top,int right, int bottom) 
 {  int groesse 
    groesse=((right-left+1)/8*(bottom-top+1) + (bottom+top+1)*2 + 4) ; 
    return(groesse); 
}

main() 
{   initgraph(&graphdriver,&graphmode,"   TC"); 

    printf("Original: %u Bytes n",imagesize (0,0,639,399)); 
    printf("Neu:      %u Bytes n",imagesz2 (0,0,639,399)); 
    closegraph(); 
    return(0); 
} 

Listing 3: Die verbesserte Version von imagesize



Aus: ST-Computer 11 / 1990, Seite 164

Links

Copyright-Bestimmungen: siehe Über diese Seite