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 steigungCopyright: (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 0ASSUME 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 aufrufenxor ah,ah ; Wait for a keypress
int 16hmov ax,13h ; 320x200x256
int 10hCall Linie
xor ah,ah ; Wait for a keypress
int 16hmov x,48
mov y,38
Call Liniexor ah,ah ; Wait for a keypress
int 16hmov x,308
mov y,6
Call Liniexor ah,ah ; Wait for a keypress
int 16hLinien: 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 Linienxor ah,ah ; Wait for a keypress
int 16hmov 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,alxor ah,ah ; Wait for a keypress
int 16hmov 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,alxor ah,ah ; Wait for a keypress
int 16hxor ah,ah ; Wait for a keypress
int 16hmov ax,3 ; 80x25x16 text mode
int 10hmov ax,4c00h ; Terminate and back to DOS
int 21hLinie 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,dxmov 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 ENDSEND 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-(102320) 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.