Zeichnen im DOS-Mode



  • Hallo. Wie kann ich im DOS - Mode Punkte, Linien, Kreise und Quadrate zeichnen? Wenn ihr noch wißt, wie man die Farbe der Punkte... verändern kann, dann schreibt dies bitte auch dazu.
    Ich wäre froh, wenn es mit einem Beispiel-Programm erklärt würde, dass man dann genau so ausführen kann.
    Bitte helft mir.
    Danke im voraus.

    ------------------
    Squolly



  • Sorry, habe hier gelöscht weil ich den Beitrag ins Archiv schieben will.

    [Diese Nachricht wurde von class CMarcus am 20-01-2001 editiert.]



  • @Christian

    Wer redet denn hier von Zugriffsfehlern, was denkst Du denn wie die Daten von Deinem C-Programm in den Speicher der Grafikkarte gelangen.
    Das einfachtste was ich Dir anbieten kann wäre hier Mode13. Du hast dann eine Auflösung von 320x200 Punkten bei 256 Farben zur Verfügung. Die Startadresse für den Videospeicher im BIOS lautet 0xa000. Die Farben werden über eine Palette gesetzt, die dann 768 Bytes lang ist und sich in der Form RGBRGBRGBRG.. (drei Bytes bilden immer eine Farbe) zusammensetzt. Wenn Du keine neue Palette generieren willst, hast Du in den Farben 0 bis 15 die bekannten Farben aus der Standard-DOS-Palette zur Verfügung.

    Alles was Du tun musst, ist in diesen Modus umschalten (Aufruf von Interupt 0x10 mit AX=0x13) und Dir eine Setpixel-Routine bauen. Beachte das eine Zeile 320 Pixel hat, also ist die Transformation von Punkt(X,Y) zu Speicher wie folgt zu berechnen: 320*X+Y .

    Allerdings weis ich nicht was Dir lieber ist: willst Du es in Assembler oder in C schreiben ??? ich habe beides schon geschrieben, wenn Du willst dann Poste ich Dir zurück wie das geht.

    MfG



  • #pragma    inline
    asm    .386p
    
    #include <io.h>
    #include <dos.h>
    #include <stdio.h>
    #include <conio.h>
    #include <fcntl.h>
    #include <process.h>
    
    #define byte     unsigned char
    #define word    unsigned int
    #define    dword    unsigned long
    
    void     setpixel_in_c    ( word xpos, word ypos, byte color )
    {
        char     *screen=(char*)0xa0000000;
    
        *(screen+320*ypos+xpos)=color;
    }
    
    void     setpixel     ( word xpos, word ypos, byte color )
    {
        asm    push    [0xa000]
        asm    pop    es
        asm    mov    di,[xpos]
        asm    mov     bx,[ypos]
        asm    mov    al,[color]
        asm    mov    cx,bx
        asm    shl    bx,8
        asm    shl    cx,6
        asm    add    bx,cx
        asm    add    di,bx
        asm     stosb
    
    }
    
    void    copyscreen    ( word dest, word source )
    {
        asm    mov    ds, [source]
        asm    mov    es, [dest]
        asm    xor    si, si
        asm    mov    di, si
        asm    mov    cx, 16000
        asm    rep    movsd
    }
    
    void    clearscreen     ( word dest )
    {
        asm    push    [dest]
        asm    pop    es
        asm    xor    di, di
        asm    mov    cx, 16000
        asm    xor    eax,eax
        asm    rep    stosd
    }
    
    void    mode13exit     ( void )
    {
        asm    mov    ax, 0x03
        asm    int    0x10
    }
    
    void    mode13init     ( void )
    {
        asm    mov    ax, 0x13
        asm    int    0x10
    }
    
    void     setpal        ( char palette[] )
    {
        word    counter;
    
        outp(0x3c8,0);
        for(counter=0;counter<=768;counter++)
        outp(0x3c9,palette[counter]);
    
    }
    
    void    loadtga        ( char *name, char *pixels, char palette[] )
    {
        byte    file_handle,temp_col;
        word    counter;
    
        if ((file_handle =open(name, O_RDONLY | O_BINARY)) == -1)
        {
        printf("can't open %s\n",name);
        exit(1);
        }
        read(file_handle, pixels, 18);
        read(file_handle, palette, 768);
        for(counter=0;counter<=766;counter+=3)
        {
        temp_col=palette[counter]>>2;
        palette[counter+1]=palette[counter+1]>>2;
        palette[counter]=palette[counter+2]>>2;
        palette[counter+2]=temp_col;
        }
        for(counter=1;counter<=200;counter++)
        read(file_handle, (pixels+64000-counter*320), 320);
        close(file_handle);
    }
    
    void    loadpcx        ( char *name, char *pixels, char palette[] )
    {
    
        int    handle;
        word    i,j,k;
        byte    p,q;
    
        i=0;j=0;p=0;k=0;
    
        if ((handle =open(name, O_RDONLY | O_BINARY)) == -1)
        {
        printf("can't open %s\n",name);
        exit(1);
        }
        lseek(handle,128,SEEK_SET);
        do
        {
        read(handle,&p,1);
        if((p&0xc0)==0xc0)
        {q=(p&0x3f);read(handle,&p,1);for(k=0;k<q;k++){*(pixels+j)=p;j++;}}
        else
        {*(pixels+j)=p;j++;}
        }
        while(j<64000);
        lseek(handle,-768,SEEK_END);
        for(i=0;i<768;i++)
        {read(handle,&p,1);palette[i]=p>>2;}
        close(handle);
    
    }
    

    Eigentlich kann man alles in C programmieren, aber ich hatte immer das Problem, dass ich den Mode13 nicht initialisieren kann, ohne eine Assemblerbefehl zu nehmen. Es sei denn, jemand weiss, wie man den Interupt mit einem C-Befehl anspringen kann.
    Die beiden Bild-Loader nehmen nur Bilder, die 320X200 Pixel sind und 256 Farben haben.
    Die Setpixel-Routine in C sieht zwar kurz und bündig aus, aber wer weiss was der Compiler draus macht? Auf jeden Fall ist die in Assembler geschriebene schneller (ich glaube weniger als 20 Taktzyklen auf 'nem 486-er), da ich die Multiplikation (320*y) in zwei Bitverschiebungen umwandle.

    Wen es interessiert, das ganze habe ich unter Borland C-Compiler 3.x unter MS-Dos geschrieben (aber mit Watcom hab' ich es auch schon unter Win9x compiliert).

    MfG

    Edit by SideWinder: Code-Tags eingefügt.

    [ Dieser Beitrag wurde am 06.05.2002 um 19:28 Uhr von SideWinder editiert. ]


Anmelden zum Antworten