Liniensubroutine zeichnet krumme Linien



  • Mein Linienprogramm zeichnet krumme Linien.
    Das Demonstrationsprogramm zeichnet Linien vom linken oberen Punkt angefangen an durchgehend bis zum rechten oberen Punkt lauter Linien, die alle am Mittelpunkt des Bildschirmes enden. Es muesste also nach dem Zeichnen ein Dreieck zu sehen sein, das von der Mitte des Bildschirmes bis zum oberen Rand verlaeuft.
    Aber in der Mitte bei X-Koordinate 160 werden die Linien krum und schwanken von links nach rechts, so dass lauter Luecken entstehen.
    Wer findet den Fehler, der die Linien krumm macht?

    COMMENT ~ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

    Datei: Punkt.ASM

    setzt Punkte einer Linie in der Farbe Gelb auf den VGA Videoschirm
    mit der Restmethode - schwankungen bei linien mit negativer steigung

    Copyright: (c) 2005 Eric N. Falbe

    ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-~

    Code SEGMENT BYTE PUBLIC 'CODE'
    .386

    ; Meldungen:

    Msg1 DB 'Textausgabe ist OK! Supeeeeeer!! Duper!!! Schwankungen',13,10,'$'
    Oben DB 0,1,2,3
    x DW 012h,0a0h,070h,0
    y DW 030h,064h,0a0h,0
    x1 DW 0
    y1 DW 0
    deltax DW 0,0,0,0
    deltay DW 0,0,0,0
    m DW 0,1
    Rest DW 0

    ASSUME CS:CODE, DS:CODE

    Start:
    mov ax,CODE ; Segmentadresse in
    mov ds,ax ; ds laden, da assume kein Programmcode ist ??
    Msg_1: mov ah,009h ; Funktion 9 = Textausgabe
    mov dx,OFFSET Msg1 ; Text an Offset Msg2
    int 021h ; DOS-Funktion aufrufen
    mov ah,009h ; Funktion 9 = Textausgabe
    mov dx,OFFSET Msg1 ; Text an Offset Msg2
    int 021h ; DOS-Funktion aufrufen

    xor ah,ah ; Wait for a keypress
    int 16h

    mov ax,13h ; 320x200x256
    int 10h

    Call Linie

    xor ah,ah ; Wait for a keypress
    int 16h

    mov x,48
    mov y,38
    Call Linie

    xor ah,ah ; Wait for a keypress
    int 16h

    mov x,308
    mov y,6
    Call Linie

    xor ah,ah ; Wait for a keypress
    int 16h

    Linien: Call Linie
    xor ah,ah ; Wait for a keypress
    int 16h
    add x1,1
    mov ax,x1
    mov x,ax
    mov bx,y1
    mov y,bx
    cmp x,320
    jle Linien

    xor ah,ah ; Wait for a keypress
    int 16h

    mov bx,0070h ; 110h x Position
    mov ax,080h ; 050h y Position
    mov cx,ax
    shl ax,8 ; mal 256
    shl cx,6 ; mal 64 (= mal 320)
    add ax,bx
    add ax,cx
    mov di,ax
    mov al,0eh ;
    mov es:di,al

    xor ah,ah ; Wait for a keypress
    int 16h

    mov bx,00a0h ; 110h x Position
    mov ax,064h ; 050h y Position
    mov cx,ax
    shl ax,8 ; mal 256
    shl cx,6 ; mal 64 (= mal 320)
    add ax,bx
    add ax,cx
    mov di,ax
    mov al,0eh ;
    mov es:di,al

    xor ah,ah ; Wait for a keypress
    int 16h

    xor ah,ah ; Wait for a keypress
    int 16h

    mov ax,3 ; 80x25x16 text mode
    int 10h

    mov ax,4c00h ; Terminate and back to DOS
    int 21h

    Linie proc near
    mov bx,y+2
    sub bx,y
    jnz Nully
    mov m,0
    mov m+2,1
    Nully: mov deltay,bx
    mov eax,0
    mov ax,x+2
    sub ax,x
    cwd
    mov deltax,ax
    idiv deltay
    mov m,ax
    mov Rest,dx

    mov x+6,0
    mov ax,0a000h ; Set ES to VGA segment (0a000h)
    mov es,ax
    Punkte: mov bx,x ; 110h x Position
    mov ax,y ; 050h y Position
    mov cx,ax
    shl ax,8 ; mal 256
    shl cx,6 ; mal 64 (= mal 320)
    add ax,bx
    add ax,cx
    mov di,ax
    mov al,0eh ;
    mov es:di,al
    mov ax,m+2
    add y,ax
    mov ax,m
    add x,ax
    mov ax,Rest
    add x+6,ax
    mov ax,x+6
    cmp ax,0
    jge positiv
    cmp ax,deltay
    jg noX
    moreX1: sub ax,deltay
    sub x,1
    cmp ax,deltay
    jle moreX1
    mov x+6,ax
    jmp noX
    positiv: cmp ax,deltay
    jl noX
    moreX: sub ax,deltay
    add x,1
    cmp ax,deltay
    jge moreX
    mov x+6,ax
    noX: mov ax,y
    cmp ax,y+2
    jle Punkte
    ret
    endp
    Code ENDS

    END Start



  • Habe zwar lange nichts mehr mit Grafig gemacht, aber du schreibst die
    Pixel ja direkt in den Grafigspeicher ab Segment A000. Bei einer Auflösung
    von 320*200 komme ich auf 64000 Bytes. Nun kommt es auf die sogenannte
    Granularität deiner Grafigkarte an, hat eine Bank 65535 Bytes dann kannst
    du sämtliche Pixel ohne umschalten der Bank schreiben, hat die Karte eine
    Granularität von 32768 Bytes, musst du ab der zweiten Bildschirmhälfte
    die Bank umschalten.

    mov     ax,4f05h
                    mov     dx,bank
                    xor     bx,bx
                    int     10h
    


  • Was genau ist das Granularität?
    Womit misst man die?
    Und wo kann ich sowas nachschauen?



  • Hi.

    @Eric Falbe:
    Sry, aber dein komisches unkommentiertes Gewurstel da zu debuggen ist mir einfach zu viel Aufwand. => Machs selber :p , oder noch besser: Benutz' doch einfach den Bresenham-Algo fuer Linien (=>google, gibt's viele Dokus zu). 😉

    BTW:
    Speicherzugriffe sind in eckige Klammern einzuschliessen - auch wenn MASM das vielleicht auch ohne schluckt (siehe Zeilen 95, 105, 155). 🙄

    @hermes:
    Standard-VGA kennt kein Bank-Switching in diesem Sinne und der FrameBuffer fuer den 320*200*8-VGA-Modus ist immer 64KByte gross.
    Dein Beispielcode enthaelt einen Funktionsaufruf fuer VESA - das ist aber was anderes.



  • Sorry, aber lange ist es her das ich mich damit beschäftigt habe.
    Es gibt aber Karten mit 32K Granularität gilt das dann nicht auch für den
    VGA Modus.

    Was genau ist das Granularität?

    Grafigkarten haben ihren Speicher in Bänke aufgeteilt.
    Die Bankgröße ist dabei die Granularität 64K oder 32K.
    Bei einer Auflösung von 320200 und einer Granularität von 32K würde man
    in Bank 0 bis zur Zeile 102 kommen und in dieser Zeile noch 128 Pixel
    darstellen können.
    In der Zeile 102 (32768/320) ab dem 129 Pixel (32768-(102
    320) müsste man dann in Bank 1 schalten um die restlichen Pixel erreichen zu können.

    Sry, aber dein komisches unkommentiertes Gewurstel da zu debuggen ist mir einfach zu viel Aufwand

    Da hat er recht, du solltes das ganze vieleicht etwas Kommentieren.
    Ausserdem scheint mir das ganze etwas Umständlich programmiert.
    Ich würde zunächst eine Funktion schreiben die ein Pixel an die Position
    X,Y schreibt.
    Als Übergabeparameter würde ich die Register BX->XPos DX->YPos sowie für
    die Pixelfarbe AL benutzen.

    push ax
    mov ax,A000h
    mov es,ax
    pop ax;
    

    nun anhand der X Y Positionen einen Wert für die Speicherposition inerhalb des Segments errechnen und nach Register DI schreiben und mit

    stosb      ;Schreibt den Inhalt des Registers AL in den durch ES:DI anggebenen
               ;Speicher
    

    Das Pixel schreiben.



  • hermes schrieb:

    Es gibt aber Karten mit 32K Granularität gilt das dann nicht auch für den
    VGA Modus.

    Diese Form von "Granularitaet", die du meinst, gibt es nur beim Zugriff auf den FrameBuffer im RealMode bei Benutzung des VESA-Interface.
    Es gibt im VGA-Standard zwar die Moeglichkeit, zwischen 4verschiedenen planes mit je 64KByte zu waehlen, bzw. verschiedene Speicherfenster ein-/auszuschalten und noch viele Spielerchen mehr, aber das laesst sich nicht ueber BIOS-Interrupts regeln.

    Eine 32K-Granularitaet (o.Ae.) wie von dir weiter beschrieben, kommt im VGA-Standard jedenfalls nicht vor.


Anmelden zum Antworten