Hey everybody, I need a bit of help please. I need to create an 8086 application that will draw a line between two points on the screen that you click on. It's using Bresenham's line algorithm to do the calculations between the two points. I'm using Tasm and Tlink to compile and create the application. My problem is that when first point click's Y position on the screen is > the second Y position then the line doesn't draw. Also, I can't draw the line all around the screen. If the angle(slope) is greater or less then a certain number then it won't draw or it will be weird (I can't seem to figure it out). Below is the code that I've created and I'm using in making this. If anyone could help I'd greatly appreciate it.
; DRAWLINE.ASM - program is to be run from the 'command prompt' window.
;
; This program allows the user to enter the coordinates of a line using two successive left mouse
; clicks to indicate the start and end coordinates respectively. The program will then use an unsophisticated
; implementation of Bresenham’s line drawing algorithm to draw a line, pixel by pixel, between the two points.
; Note that the origin is at the top left corner of the screen, with x and y increasing positively as we
; migrate into the general screen area.
;
;
; The program will ascertain (and save) the current video mode, then switch to video mode 4 (this was available
; for CGA, EGA and VGA adaptors), palette 0 (one of the original video graphics modes for the IBM PC).
;
; It initialises the mouse driver and polls the mouse for left click events, storing the mouse's coordinates as
; it identifies these. Once it has the two points it tries to draw the line between them using Bresenham’s
; algorithm.
;
; The program will hold the screen until the user inputs any character (prompted). Once done, the program will
; restore the original video mode, then termnate. Note that the screen will be in full screen mode on
; completion - input ALT+ENTER to toggle between full screen mode and the original command prompt window size.
;
.model small
.stack 1000h
.data
vidmode db 0 ;stores initial video mode - for restoration on program completion
buttons dw 0 ;stores the left mouse button status (clicked or not clicked)
startx dw 0 ;x coordinate of the start of the line (from mouse interrogation)
starty dw 0 ;y coordinate of the start of the line (from mouse interrogation)
endx dw 0 ;x coordinate of the end of the line (from mouse interrogation)
endy dw 0 ;y coordinate of the end of the line (from mouse interrogation)
X dw 0 ;current working x coordinate on line
Y dw 0 ;current working y coordinate on line
deltax dw 0 ;number of pixels/iteration we advance x using Bresenham’s line drawing algorithm
deltay dw 0 ;number of pixels/iteration we advance y using Bresenham’s line drawing algorithm
error dw 0 ;used to determine which side of the true line we place each pixel
Xgrad dw 0 ;x gradient
finish db 24 DUP (10), 13, 'Finished! Press any key to exit please$'
.code
;set ds to point to the data segment
mov ax,@data
mov ds,ax
;ascertain original video mode
mov ah,0fh ;interrupt function 0Fh: "Get Video Mode"
int 10h ;invoke interrupt 10h function 0Fh
mov vidmode,al ;save Video Mode
;set video mode to mode 4
mov ah,00h ;interrupt function 00h: "Set Video Mode"
mov al,04h ;"Set Video Mode" to mode 4 (EGA/VGA graphics - 320 x 200 pixels)
int 10h ;invoke interrupt 10h function 00Fh
;set colour palette to mode 0
mov ah,0bh ;interrupt function 0bh:
mov bh,01h ;interrupt subfunction 01h: "Set Palette"
mov bl,00h ;new palette value:
;0=>background, green, red & brown/yellow
;1=>background, cyan, magenta & white
int 10h ;invoke interrupt 10h function 0bh subfunction 01h
;reset mouse driver
mov ax,0
int 33h
;display mouse cursor
mov ax,1
int 33h
;get start point of line by constantly polling mouse for its position and left button status
strtpt: mov ax,3 ;interrupt 33h, function 3:
int 33h ; - get mouse position and button status
and bx,01h ;get button status in bx - must do now as we want bx in a moment
mov buttons,bx ;save button status to memory - bx now reusable again
mov starty,dx ;store mouse's y coordinate (dx will change computing x coord.)
mov ax,cx ;compute (divide by 2) mouse x coordinate - again not start point
mov bx,2 ;load divisor into bx - unless left mouse
mov dx,0 ;set high bits of numerator to 0 ; - button is clicked
div bx ;divide bx into dx:ax - quotient stored in ax, remainder in dx
mov startx,ax ;store mouse's x coordinate - now check mouse left click status
cmp buttons,1 ;was left button clicked? (=> (startx,starty) is start point)
jne strtpt ;-if not, go back and poll mouse again, else seek end point next
;poll mouse until left button is released (otherwise end point will be same as start point)
cliked: mov ax,3 ;interrupt 33h, function 3:
int 33h ; - get mouse position and button status
and bx,01h ;get button status in bx
mov buttons,bx ;save button status to memory
cmp buttons,0 ;is left button clicked?
jne cliked ;-if is, go back and poll mouse again until it's released
;-if it isn't, then proceed to finding end point
;get end point of line by constantly polling mouse for its position and left button status
endpt: mov ax,3 ;interrupt 33h, function 3:
int 33h ; - get mouse position and button status
and bx,01h ;get button status in bx - must do now as we want bx in a moment
mov buttons,bx ;save button status to memory - bx now reusable again
mov endy,dx ;store mouse's y coordinate (dx will change computing x coord.)
mov ax,cx ;compute (divide by 2) mouse x coordinate - again not end point
mov bx,2 ;load divisor into bx - unless left mouse
mov dx,0 ;set high bits of numerator to 0 ; - button is clicked
div bx ;divide bx into dx:ax - quotient stored in ax, remainder in dx
mov endx,ax ;store mouse's x coordinate - now check mouse left click status
cmp buttons,1 ;was left button clicked? (=> (endx,endy) is end point)
jne endpt ;-if not, go back and poll mouse again, else output line next
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;
;draw the line from the start point to the end point using Bresenham’s classic line drawing algorithm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;
;initialise deltax with the absolute difference between its start and end x coordinates
mov ax,startx
mov bx,endx
cmp ax,bx
ja otherx
sub bx,ax
mov deltax,bx
jmp dodlty ;go to process deltay now
otherx: sub ax,bx
mov deltax,ax
;initialise deltay with the absolute difference between its start and end y coordinates
dodlty: mov ax,starty
mov bx,endy
cmp ax,bx ;if staryY is > endY
ja othery ; jump to otherY
sub bx,ax
mov deltay,bx
jmp inits
othery: sub ax,bx
mov deltay,ax
;do other initialisations for the algorithm (error, Xgrad, X and Y)
inits: mov error,0 ;initialise error
mov ax,deltay ;initialise Xgrad
mov Xgrad,ax
mov ax,startx ;initialise working coordinates X and Y
mov X,ax
mov ax,starty
mov Y,ax
;display pixel at (X,Y) in green
nxtpix: mov ah,0ch ;interrupt function 0Ch: "Write Graphics Pixel"
mov al,01h ;pixel colour 0:background, 1:green, 2:red, 3:brown/yellow
mov bh,00h ;page number
mov dx,Y ;pixel row
mov cx,X ;pixel column
int 10h ;invoke interrupt 10h function 0ch
;compute initial error value for next iteration
mov ax,error
add ax,Xgrad
mov error,ax
;correct this error value if necessary
add ax,ax ;double it
cmp ax,deltax
jl errOK ;no corection required if ax (=>error*2) >= deltax - so jump down (use jl for signed)
inc Y
mov ax,error ;error = error - deltax;
sub ax,deltax
mov error,ax
;next iteration : increment loopcounter and draw next pixel, if line not already finished
errOK: inc X
mov ax,X
cmp ax,endx
jb nxtpix
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;
;output the program termination message (string 'finish' defined above)
mov ah,9 ;interrupt function 9, "string output"
mov dx,offset finish;make dx point to string pgfin
int 21H ;display string
;input any character (without echo) to hold screen before program termination
mov ah,8 ;DOS function call 1, ;character input
int 21H ;Software interrupt 21H, ;Input/output
;hide mouse cursor
mov ax,2
int 33h
;restore original video mode
mov ah,00h ;interrupt function 00h: "Set Video Mode"
mov al,vidmode ;"Set Video Mode" to original mode
int 10h ;invoke interrupt 10h function 00Fh
;terminate program correctly
mov ah,4ch
int 21H
end