möglichkeiten zur grafikausgabe?



  • hi,
    kann mal jemand alle möglichkeiten zur bildschirmausgabe aulisten? aber ohne die unterstützung eines anderen OS...
    könnt ihr dann vielleicht auch noch zu jeder methode ein beispiel machen, oder mir ein gutes tut dazu sagen?
    MFG BlockBuster



  • Grafikausgabe ohne OS geht eigentlich alles ueber int 10h
    Die 2 gebraeuchlichsten Beispiele fuer VGA werde ich hier mal auflisten. (320x200 256Farben und 640x480 16Farben)
    Fuer VESA (hoehere Aufloesungen/Farbtiefe etc.) schau dir mal die VBE 3.0 Specifications auf www.vesa.org an. Irgendwo am Ende sind da wohl auch Beispielcodes in C und asm 🙄

    Grafik 320x200 256Farben:
    mov ax,0013h ;93h loescht dazu noch den Bildschirm (13h mit Bit7 gesetzt)
    int 10h ;Modus wechseln
    mov ax,0A000h ;VGA
    mov es,ax
    mov al,0Ah
    xor di,di
    stosb ;gruenen Punkt links oben setzen
    mov di,100*320
    stosb ;den gruenen Punkt ein bisschen weiter unten nochmal setzen...
    Wie man hieraus vielleicht ersehen kann, ist jeder Byte in der VGA einem Pixel zugeordnet (8Bit)...
    Der speicher ist Zeilenweise von links nach rechts und oben nach unten - also linear - angeordnet.

    Grafik 640x480 16Farben:
    erstmal, um in diesen GrafikModus zu gelangen -

    mov     ax, 0012h
            int     10h ;Grafikmodus einschalten
    

    Weiter ist die Sache hier schon etwas komplizierter, da die Datenmenge nicht mehr einfach in ein 64KByte-Segment passt.
    Dazu muss man nun erstmal wissen, dass die VGA-Grafikkarte intern 4BitMaps hat, in denen Daten abgelegt werden koennen.
    Jede von denen ist 64KByte gross, so dass es also insgesamt 256KByte Speicher gibt.
    Im Mode 12h ist nun Map0 fuer Blau zugeteilt, Map1 fuer gruen usw. kennt man ja von 16Farben-Modi. 🙂
    Die Maps selbst sind nun wie der Speicher im Mode 13h linear angeordnet, wobei ein Bit genau ein Pixel steuert. Dh. Bit0 den Pixel ganz oben links, Bit1 den rechts daneben ... Bit 8 ist dann x=8,y=0 usw.
    Ebenfalls wie beim Mode 13h oben, sind auch hier alle 4BitMaps aktiv, jedoch werden hier durch einen Schreib-/Lesezugriff normalerweise alle vier Maps gleichzeitig angesprochen - also bekommt man durch einfaches in den Speicher schreiben nur schwarz/weiss-Pixel hin.
    Um nun einzelne verschiedenfarbige Pixel zu setzen/auszulesen, gibt es verschiedene Moeglichkeiten, einzelne Maps zu maskieren - also unbeeinflusst zu lassen.
    Eine von denen werde ich mit diesem Beispielcode zum Pixelsetzen mal erklaeren:
    (Danke an wasiliy fuer dieses Schnippsel)

    Proc Pix NEAR
    
    	mov     ax,0A000h 
    	mov     es,ax ;VGA
    	mov     bx,[Xc] ;X-Koordinate
    	mov     ax,[Yc] ;Y-Koordinate
    	mov     cl,bl 
    	and     cl,07h  ;die unteren 3Bit der X-Koordinate (modulo 8) benutzen wir
    ;nachher fuer die BitMaskierung (fuer ein Byte - 8Bit) beim setzen der Maps.
    	shr     bx,3 ;Diese 3Bit brauchen wir ansonsten bei der Adressberechnung nicht mehr
    ;x/8, da ja hier jedes Byte 8Pixel setzt
    	shl     ax,6 ;<=y*64
    	add     bx,ax 
    	shr     ax,2 ;<=y*16 (<=y*64/4)
    	add     bx,ax ;=>y*80 (entspr. y*640 / 8)
    
    	mov     dx,3CEh ;Graphics Controller Registers
    ;ggf. noetig, wenn es Probleme gibt
    ;	mov     ax,0005h ;Index 05h: Graphics Mode Register
    ;	out     dx,ax ;Disable 256Color; Disable ShiftRegisters; disable Odd/Even-Adressing; ReadMode 0; WriteMode 0
    
    	mov     ax,8008h ;Index 08h: Bit Mask Register
    ;hier wird jetzt die BitMaske fuer unseren Zugriff auf die SpeicherMaps
    ;gesetzt. Alle Bits, die hier in ah 0 sind, werden spaeter maskiert.
    ;in ah wird nun das 1Bit an die richtige Stelle fuer den Zugriff auf das
    ;gewuenschte Pixel verschoben.
    	shr     ah,cl 
    	out     dx,ax ;Set Bit Mask
    
    ;Hier werden die Set/Reset-Register fuer alle Maps eingeschaltet (Bit0-3 in ah)
    ;So bekommen bei einem Byte-Schreibzugriff auf die VGA alle 8Bit in jeder Map
    ;den Wert, der im entsprechenden Set/Reset-Register eingestellt wurde.
    	mov     ax,0F01h ;Index 01h: Enable Set/Reset Register
    	out     dx,ax ;enable Set/Reset for all maps
    
    ;Hier werden nun die Set/Reset-Register gesetzt.
    ;Die Bits0-3 in ah sind hierbei genau den Maps 0-3 zugeordnet.
    ;Dh. wenn hier Bit0=1 ist, werden beim naechsten Byte-Schreibzugriff auf
    ;die VGA alle 8Bit 1 gesetzt.
    	xor     al,al ;Index 00h: Set/Reset Register
    	mov     ah,[COLOR] 
    	out     dx,ax
    
    ;damit die Bit-Maskierung funktioniert, muss von der Speicherstelle erstmal
    ;gelesen werden - so sichert sich der Graphics-Controller intern eine Kopie
    ;dieser Speicherstelle.
    	mov     cl, [byte ptr es:bx]
    ;nun einfach irgendwie einen Byte-Schreibzugriff produzieren
    ;dabei werden die Bits in allen Maps wie oben mit dem Mask-Register/den Set/
    ;Reset-Registern eingestellt gesetzt.
    	mov     [byte ptr es:bx],al
    
    ;was nun folgt ist wie das auskommentierte Codestueck am Anfang nicht
    ;unbedingt noetig... - nur ein wenig aufraeumen
    ;wieder alle Set/Reset-Register abschalten
    	inc     al ;Index 01h: Enable Set/Reset Register
    	xor     ah,ah 
    	out     dx,ax
    
    ;und die Bit-Maskierung ebenfalls (alle Bits zulassen)
    	mov     ax,0FF08h ;Index 08h: Bit Mask Register
    	out     dx,ax ;disable Bit Mask
    
    ;Ende
    	ret 
    endp pix
    

    hth



  • hi,

    danke für die antwort 🙂
    aber auf www.vesa.org find ich nix... kannst du mir mal den genauen link geben?

    MFG BLockBuster



  • http://www.vesa.org/vbe3.pdf
    Die VBE 3.0 Specifications 😉



  • hi,
    danke für den link...
    aber nochmal zu int 10h: wenn ich das hier versuche dann malt er das rechteck viel zu weit unten:

    asm{
    mov ax,0012h
    int 10h
    }

    for(x=0; x<100; x++)
    {
    for(y=0; y<100; y++)
    {
    asm{
    mov ah,0Ch
    mov dx,[x]
    mov cx,[y]
    mov al,0Ah
    int 10h
    }
    }
    }

    aber warum?

    MFG BlockBuster



  • In meiner Interrupt Liste steht das hier:
    *
    CX = column number (zero based)
    DX = row number (zero based)
    *
    Also ist cx x und dx y und nicht andersrum 😉
    Dann solltest du noch bh (Page Number) auf 0 setzen...
    Mehr faellt mir dazu jetzt auch nicht ein, ausser, dass Pixel-setzen mit int 10h nicht gerade fuer schnellere Grafikanwendungen geeingnet ist 😃



  • ok, danke jetzt funzt es... aber total lahm 🙂
    wie funzt das mit "stosb"-zeug... wie male ich da nen pixel an 100,100 ich check das irgendwie net 🙂 kannst du das vielleicht mal ganz genau erklären?

    MFG BlockBuster



  • ok. dann erstmal eine "PutPixel" routine fuer den 320x200 Modus:
    ;(DIE solltest du aber nicht benutzen, um bitmaps o.ao. zu zeichnen... nur als Demo gedacht, weil bei groesseren Gebilden auch noch ziemlich lahm 😉 )
    ;ax=Y
    ;cx=X
    ;bl=color
    mov dx,320 ;eine Reihe ist 320Pixel lang
    mul dx ;ax(y)320
    add ax,cx ;ax(y
    320)+x
    mov di,ax
    mov ax,0A000h
    mov es,ax ;es Zeigt im RM jetzt zur VGA bei A000
    mov [byte ptr es:di], bl ;Farbe in die VGA nach es:di / A000:((y*320)+x) schreiben
    ret

    ;um damit zB. ein ausgefuelltes Rechteck zu malen:
    ;ax=Y
    ;cx=X
    ;bl=color
    ;dl=x-Size
    ;dh=y-size
    push dx
    push bx
    mov bx,320
    mul bx
    add ax,cx ;s.o.
    mov di,ax
    mov ax,0A000h
    mov es,ax
    pop ax ;bis hierhin, wie oben
    pop cx ;x und y size des Rechtecks zurueckholen
    xor dx,dx
    xchg dl,ch ;ch=0 dl=y-size
    @@SetYLoop:
    push cx
    push di
    rep stosb
    pop di
    pop cx
    add di,320 ;eine Zeile nach unten
    dec dx
    jnz short @@SetYLoop ;noch eine Reihe zeichnen, bis y=0
    ret

    so. hoffe das war bis hier verstaendlich 😃
    Die ganze Sache fuer den 640*480-Modus spar ich mir jetzt erstmal. 😉

    [edit]
    aufpassen, dass die Farb- und Positionswerte in den Registern nicht zu gross sind (also immer die GANZEN 16Bit Register setzen), sonst kommt da nur Muell raus.
    [/edit]

    [ Dieser Beitrag wurde am 18.05.2002 um 20:37 Uhr von Nobuo T editiert. ]


Anmelden zum Antworten