Zeitmessung (fps) und Tastaturabfrage



  • Hallo zusammen,
    Ich bins schon wieder und habe schon wieder 2 Fragen, auf welche ich einfach trotz mehrstündiger Suche im Internet keine Antworten finde 😞

    1. Weiss jemand, ob es mit 16-Bit BIOS - Interrupts soetwas wie TimeGetTime() oder QueryPerformanceCounter() gibt? Ich benötige dies, um die Zeit zwischen verschiedenen Punkten im Programm zu messen!

    2. Ich möchte zu einem bestimmten Zeitpunkt, einmal pro mainloop den Status der Tastatur abfragen! Zwar kann ich dies mit Hilfe der Funktion 02 des Interrupts 16h tun, doch leider wird die Taste dabei nicht auf dem Eingabebuffer entfernt! Wie kann ich das tun?

    Mfg Ishildur



  • int 08 wird defaultmäßig 18.2 mal pro sekunde generiert und ist für andere taktraten reprogrammierbar.



  • @cpt. obvious
    Vielen Dank für deine Hilfe!

    Ich habe da noch etwas nettes entdeckt.
    An der Adresse 0040h:006ch scheint das BIOS die Timerticks seit Mitternacht zu hinterlegen! Ich glaube, das ist genau das, was ich benötige!



  • int 16h/AH=01h checkt, ob eine Taste gedrueckt wurde, idR. ohne die Eingabe vom Puffer zu entfernen.
    Wenn diese Funktion also meldet, dass eine Taste gedrueckt wurde, schiebst du ein int 16h/AH=00h nach.



  • Ja, aber das Problem dabei ist, dass die minimale Verzögerung IMHO 250ml beträgt, was ich bräuchte, wäre ein GetAsyncKeyState()!

    Noch eine Frage, gibt es eine möglicheit, den Int 10/ah 13 Text ausgeben zu veranlassen, auf einen anderen Speicherbereicht als 0a000h zu schreiben?

    Und ist es möglich, der Grafikkarte zu sagen, dass es die Daten von einem anderen Speicherbereich lesen soll?

    Aufgrund der Tatsache, dass es nicht möglich war, direkt in das Videomemory zu schreiben, ohne dass ständig irgendwas flackern musste, habe ich mir einen backbuffer angelegt, welcher genau oberhalb des Videobuffers im UMA liegt: (hoffentlich überschreibe ich da keine Systemdaten...)

    DrawScene PROC NEAR
       mov ax,0e000h  ; load baseaddress of backbuffer into ax
       mov es,ax      ; load ax into es  
       xor di,di      ; param: destindex = beginning of buffer (es implicitly used)
       mov ax,00h     ; param: value = black
       mov cx,7d00h   ; param: number of repeats = 64kb / 2 => wordstep
       cld            ; clear direction flag (incremental mode)
       rep stosw      ; block - transfer
    
       ; draw everything here
    
       mov ax,0e000h ; load baseaddress of backbuffer into ax
       mov ds,ax     ; load ax into ds
       xor si,si     ; param: sourceindex = beginning of buffer (ds implicitly used)
       mov ax,0a000h ; load baseaddress of videobuffer into ax
       mov es,ax     ; load ax into es
       xor di,di     ; param: destindex = beginning of buffer (es implicitly used)
       mov cx,7d00h  ; param: number of repeats = 64kb / 2 => wordstep
       cld           ; clear direction flag (incremental mode)
       rep movsw     ; block - transfer
     DrawScene ENDP
    

    Das Problem dabei ist aber nun natürlich, dass ich einmal pro Frame den Inhalt des Backbuffers in 16-Bit schritten in den Videospeicher kopieren muss.

    Viel schneller wäre es natürlich, wenn ich der Grafikkarte einfach sagen könnte, sie solle die Daten mit einem anderen Speicherbereich abgleichen. Auf diese Weise müssten lediglich pro Frame 2 16-Bit Zeigre umgebogen werden!

    PseudoCode
    var frm
    if(frm++ % 2){
    grafikkarte.zeiger = 0a000
    programm.zeiger = 0e000
    }
    else{
    grafikkarte.zeiger = 0e000
    programm.zeiger = 0a000
    }

    mov si,[programm.zeiger]
    mov es:[si],byte ptr 01h

    Au ja, noch eine Frage! (Mein Gott wie viele denn noch?! 😃 ) Gibt es eine Möglichkeit, Resourcen wie bspw. Bilddaten in Assembler einzubinden? Ich benutze einen uralten 16-Bit MASM Assembler, welcher bei mir in einer VMWare Umgebung unter MS-DOS 6.2.2 läuft!
    Lg Ishildur



  • Ishildur schrieb:

    Ja, aber das Problem dabei ist, dass die minimale Verzögerung IMHO 250ml beträgt, was ich bräuchte, wäre ein GetAsyncKeyState()!

    Wo hast du denn diesen Wert (ich denke mal, du meinst ms) her? Und was fuer ein Moerderprogramm schreibst du, das auf einem Museumsstueck mit solchen Verzoegerungen derart akkurate Timings bei der Tastaturabfrage braucht? 😕
    Naja, wenn dir die BIOS-Funktionen zu lahm sind, bleibt eigentlich nur noch die Moeglichkeit, das BIOS auszuhaken und direkt mit der Hardware zu kommunizieren.

    Docs dazu gibt es in der Assembler FAQ unter OS-Dev.

    Ishildur schrieb:

    Noch eine Frage, gibt es eine möglicheit, den Int 10/ah 13 Text ausgeben zu veranlassen, auf einen anderen Speicherbereicht als 0a000h zu schreiben?

    Deutsch? Scheint so, als waeren da 2 Fragen ungluecklich in einen Satz gerutscht.
    Also: Textausgabe im 13h VGA-Modus klappt entweder mit den int 10h Teletype-Funktionen, oder indem du selbst deine Schrift irgendwie in den Video-Speicher pixelst.
    Die Adresse A0000h des VGA Video-Speichers ist eigentlich fest. Vielleicht gibt es irgendeine abgefahrene Moeglichkeit, den VGA-Controller davon zu ueberzeugen, seine Grafik-Daten stattdessen von B0000h zu lesen, aber das waere ziemlich frickelig und koennte ungeahnte Nebenwirkungen haben. ...

    Ishildur schrieb:

    Und ist es möglich, der Grafikkarte zu sagen, dass es die Daten von einem anderen Speicherbereich lesen soll?

    Wenn du hardwareseitig double- oder triple-Buffer oder andere Grafik-Schmankerl bedienen willst, musst du zumindest auf VESA 2.0 und den Protected oder Voodoo-Mode umsteigen.

    Ishildur schrieb:

    Aufgrund der Tatsache, dass es nicht möglich war, direkt in das Videomemory zu schreiben, ohne dass ständig irgendwas flackern musste, habe ich mir einen backbuffer angelegt, welcher genau oberhalb des Videobuffers im UMA liegt: (hoffentlich überschreibe ich da keine Systemdaten...)

    DrawScene PROC NEAR
       mov ax,0e000h  ; load baseaddress of backbuffer into ax
       mov es,ax      ; load ax into es  
       xor di,di      ; param: destindex = beginning of buffer (es implicitly used)
       mov ax,00h     ; param: value = black
       mov cx,7d00h   ; param: number of repeats = 64kb / 2 => wordstep
       cld            ; clear direction flag (incremental mode)
       rep stosw      ; block - transfer
    		   
       ; draw everything here
    		
       mov ax,0e000h ; load baseaddress of backbuffer into ax
       mov ds,ax     ; load ax into ds
       xor si,si     ; param: sourceindex = beginning of buffer (ds implicitly used)
       mov ax,0a000h ; load baseaddress of videobuffer into ax
       mov es,ax     ; load ax into es
       xor di,di     ; param: destindex = beginning of buffer (es implicitly used)
       mov cx,7d00h  ; param: number of repeats = 64kb / 2 => wordstep
       cld           ; clear direction flag (incremental mode)
       rep movsw     ; block - transfer
     DrawScene ENDP
    

    E0000h ist idR. fuer das EMS Speicherfenster oder ein BIOS-Shadow belegt. In den Bereich zwischen 98000h und 100000h solltest du wirklich nur schreiben, wenn du genau weist, was du da tust.

    Ishildur schrieb:

    Das Problem dabei ist aber nun natürlich, dass ich einmal pro Frame den Inhalt des Backbuffers in 16-Bit schritten in den Videospeicher kopieren muss.

    Willst du dein Programm unbedingt <386-kompatibel halten, oder warum 16Bit?

    Ishildur schrieb:

    Viel schneller wäre es natürlich, wenn ich der Grafikkarte einfach sagen könnte, sie solle die Daten mit einem anderen Speicherbereich abgleichen. Auf diese Weise müssten lediglich pro Frame 2 16-Bit Zeigre umgebogen werden!

    PseudoCode
    var frm
    if(frm++ % 2){
    grafikkarte.zeiger = 0a000
    programm.zeiger = 0e000
    }
    else{
    grafikkarte.zeiger = 0e000
    programm.zeiger = 0a000
    }

    mov si,[programm.zeiger]
    mov es:[si],byte ptr 01h

    Wie gesagt: Nicht mit VGA. Auf jedem halbwegs brauchbaren Rechner ist das Kopieren des 2. Puffers ueber die CPU aber eigentlich kein wirklich ernst zu nehmendes Hemmnis.

    Ishildur schrieb:

    Au ja, noch eine Frage! (Mein Gott wie viele denn noch?! 😃 ) Gibt es eine Möglichkeit, Resourcen wie bspw. Bilddaten in Assembler einzubinden? Ich benutze einen uralten 16-Bit MASM Assembler, welcher bei mir in einer VMWare Umgebung unter MS-DOS 6.2.2 läuft!

    MASM kann AFAIK keine Binaerdateien in seine OBJs einbinden. Also entweder Assembler wechseln (NASM kann sowas zB.), oder selbst ein Programm schreiben/suchen, dass dir Binaer-Daten in einen Haufen MASM-"db"-Anweisungen presst.



  • @Nobuo T

    Und was fuer ein Moerderprogramm schreibst du,...

    Naja, eigentlich will ich nur ein simples Pong schreiben, aber da ist es eben ärgerlich, wenn sich das Pad nach dem laaaang,kurz,kurz,kurz Prinzip beschleunigt!

    E0000h ist idR. fuer das EMS Speicherfenster oder ein BIOS-Shadow belegt. In den Bereich zwischen 98000h und 100000h solltest du wirklich nur schreiben, wenn du genau weist, was du da tust.

    Ok, sowas habe ich bereits befürchtet! In welchen Speicherbereicht darf ich denn schreiben. Unterhalb von 0a000h fängt dann doch der Stack an, oder?

    Willst du dein Programm unbedingt <386-kompatibel halten, oder warum 16Bit?

    Ja, das Spiel muss auf jedem x86 kompatiblen Rechner (inkl. x86) lauffähig sein, ohne Betriebssystem auskommen (keine DOS - Interrupts)
    Das Ganze ist eine Übung im Fach "Grundlagen der Informatik" an der Fachhochschule

    MASM kann AFAIK keine Binaerdateien in seine OBJs einbinden. Also entweder Assembler wechseln (NASM kann sowas zB.)

    Kennst NASM auch die Intel - Syntax? (Ich hasse diesen AT&T Hack) Kann denn NASM 16-Bit Programme erstellen?

    Mfg Ishildur



  • Ishildur schrieb:

    @Nobuo T

    Und was fuer ein Moerderprogramm schreibst du,...

    Naja, eigentlich will ich nur ein simples Pong schreiben, aber da ist es eben ärgerlich, wenn sich das Pad nach dem laaaang,kurz,kurz,kurz Prinzip beschleunigt!

    Axo. 😃 Hm, IMHO waere dann die praktischste Loesung, eine kleine Funktion vor den BIOS IRQ-Handler an int 09h zu installieren. In dieser kannst du als erster den Keyboard Scan-Code von Port 60h auslesen und entsprechende Flags in deinem Programm setzen. Anschliessend springst du weiter zum BIOS IRQ-Handle und laesst ihn die restliche Drecksarbeit mit der Hardware erledigen.

    Ishildur schrieb:

    E0000h ist idR. fuer das EMS Speicherfenster oder ein BIOS-Shadow belegt. In den Bereich zwischen 98000h und 100000h solltest du wirklich nur schreiben, wenn du genau weist, was du da tust.

    Ok, sowas habe ich bereits befürchtet! In welchen Speicherbereicht darf ich denn schreiben. Unterhalb von 0a000h fängt dann doch der Stack an, oder?

    Der Speicherbereich zwischen 07C00 und 98000 steht dir zur freien Verfuegung. Wo du fuer dein Programm Code, Daten und Stack hinlegst, haengt allein von dir, bzw. (sofern vorhanden) auch dem DOS ab. Da du dein Programm scheinbar ohne irgendein DOS praktisch als eigenes OS konzipierst, solltest du schon grob wissen, wie sich dein Programm ueber den Speicher verteilt, und wo da noch Platz ist. Dein PONG wird doch wohl kaum die ganzen unteren 640kByte einnehmen.
    Also suchst du dir entweder auf diese Weise selbst einen freien Speicherbereich, oder laesst deinen Assembler das machen, indem du ein extra Datensegment definierst und da ein 64kByte grosses Array reinpackst.

    Ishildur schrieb:

    Willst du dein Programm unbedingt <386-kompatibel halten, oder warum 16Bit?

    Ja, das Spiel muss auf jedem x86 kompatiblen Rechner (inkl. x86) lauffähig sein, ohne Betriebssystem auskommen (keine DOS - Interrupts)
    Das Ganze ist eine Übung im Fach "Grundlagen der Informatik" an der Fachhochschule

    Oha - na herzliches Beileid. Keine Ahnung, wie grafisch aufwendig dein PONG ist, aber evtl. solltest du dir dann ueberlegen, ob du die Sache nicht dahingehend optimieren kannst, dass du entweder nicht immer den ganzen buffer kopieren musst, oder evtl. sogar ohne auskommst. Das Flimmern kommt ja eigentlich nur zustande, wenn du helle Pixel beim Neuzeichnen deines Bildes kurzzeitig mit dunklen uebermalst oder andersherum.

    Ishildur schrieb:

    MASM kann AFAIK keine Binaerdateien in seine OBJs einbinden. Also entweder Assembler wechseln (NASM kann sowas zB.)

    Kennst NASM auch die Intel - Syntax? (Ich hasse diesen AT&T Hack) Kann denn NASM 16-Bit Programme erstellen?

    Beides: ja. Ist sogar ein quick-guide fuer MASM-Umsteiger in der Hilfe. 🙂


Anmelden zum Antworten