Dark Bit Factory & Gravity
PROGRAMMING => Other languages => ASM => Topic started by: Phoenix on August 13, 2006
-
Hi!
I'm trying to write an ASM macro which draws a line, but it seems like I'm just drowning myself in useless lines - it's harder than I thought. You must calculate the angle of the line, distance, and where to put the pixels. If you have a little code snippet then feel free to share ;), because I could use some help here.
Thanks,
Martin
-
Ohh, I think I got it. I'm just going to finish it...
-
Hmm... I followed this (http://www.gamedev.net/reference/articles/article767.asp) tutorial, and made it to ASM, but it doesn't work. It only draws a dot at the end point, and not a line from source->destination. Here's my code:
; Draws a line bewtween the source x/y and destination x/y parameters
macro DrawLine sx, sy, dx, dy
{
local deltax ; Width
local deltay ; Height
local x ; Current drawing point's x coordinate
local y ; Current drawing point's y coordinate
local f ; Frequency decides when to change the y coordinate
; Set up the frequency
mov al, 2 ; Set up the al register for multiplication
mov ah, [deltay] ; Change the ah register to the value of deltay
mul ah ; Multiply by 2
sub ah, [deltax] ; Subtract the value of deltax
jmp draw
; Define locals
deltax db dx - sx
deltay db dy - sy
x db sx
y db sy
f db 0
draw:
mov [f], ah ; Set the frequency
mov ah, 0Ch ; Put pixels
; Repeat through the line pixel by pixel
repeat deltax
; Put pixel
mov dh, [x] ; X-axis
mov ch, [y] ; Y-axis
mov al, 255 ; Color (White)
int 10h ; Perform
; Update coords
if f < 0
mov bl, [deltay] ; Stick deltay into bl
mov al, 2 ; Change the multiplication factor
mul bl ; Multiply bl (deltay) with 2
add f, bl ; Add it to the frequncy
else
mov bl, [deltay] ; Stick deltay into bl
sub bl, [deltax] ; Subtract deltax from bl (deltay)
mov al, 2 ; Change the multiplication factor
mul bl ; Multiply es (deltay) with 2
add [f], bl ; Add it to the frequency
inc [y] ; Increase the y variable
end if
inc [x] ; Increase the x variable
end repeat
}
edit: Shockwave, can you change the codeboxes so that they use a font like courier new, the current font messes up my indentation
-
Can you provide the full source, with screen initializations etc ?
-
org 100h
mov ax, 13h
int 10h
; * * * * * * * * * * * * * * * * * * * ;
; Macros ;
; * * * * * * * * * * * * * * * * * * * ;
; Draws a line bewtween the source x/y and destination x/y parameters
macro DrawLine sx, sy, dx, dy
{
local deltax ; Width
local deltay ; Height
local x ; Current drawing point's x coordinate
local y ; Current drawing point's y coordinate
local f ; Frequency decides when to change the y coordinate
; Set up the frequency
mov al, 2 ; Set up the al register for multiplication
mov ah, [deltay] ; Change the ah register to the value of deltay
mul ah ; Multiply by 2
sub ah, [deltax] ; Subtract the value of deltax
jmp draw
; Define locals
deltax db dx - sx
deltay db dy - sy
x db sx
y db sy
f db 0
draw:
mov [f], ah ; Set the frequency
mov ah, 0Ch ; Put pixels
; Repeat through the line pixel by pixel
repeat deltax
; Put pixel
mov dh, [x] ; X-axis
mov ch, [y] ; Y-axis
mov al, 255 ; Color (White)
int 10h ; Perform
; Update coords
if f < 0
mov bl, [deltay] ; Stick deltay into bl
mov al, 2 ; Change the multiplication factor
mul bl ; Multiply bl (deltay) with 2
add f, bl ; Add it to the frequncy
else
mov bl, [deltay] ; Stick deltay into bl
sub bl, [deltax] ; Subtract deltax from bl (deltay)
mov al, 2 ; Change the multiplication factor
mul bl ; Multiply es (deltay) with 2
add [f], bl ; Add it to the frequency
inc [y] ; Increase the y variable
end if
inc [x] ; Increase the x variable
end repeat
}
; * * * * * * * * * * * * * * * * * * * ;
; Main ;
; * * * * * * * * * * * * * * * * * * * ;
DrawLine 100,100,200,200
mov ah, 01
int 21h
int 20h
-
This is crazy :o code for drawing a line! It looks like Bresenham's line algorithm, but it's done badly. One problem is, every time you write 'drawline' in your code it's going to splat in this whole routine into your file, and it can only ever draw that one line form those two endpoints! :o
I found this article http://www.gamedev.net/reference/articles/article767.asp which goes through Bresenham's line drawing algorithm with some explanation, and plenty of code to look at. I supect there are better links. Google 'Bresenham' for line drawing code.
Jim
-
Hehe, that's the article I followed. But I've never done any line algorithms before, so it's not a surprise that it's done badly. But do you mean that I should shrink it? Maybe I could remove all those local variables & definitions and place them at the bottom of the code instead?
-
I got a bit ahead of myself, you want it to work before doing anything I've posted below.
But the problem is, I don't know which assembler you're using that will actually assemble that code. :-\
To fix that, make it a function, so it doesn't duplicate the code for each line you want to draw. So you pass it the end points in
ax,bx,cx,dx. Get rid of all the macro stuff, end, repeat, if, local. Make it look more like the very last routine in the tutorial link I posted.
Try moving x,y,deltax,deltay and f into registers.
Also notice that
shl bx,1
is the same as
mov al,2
mul bl
That should clarify things a bit. This works in the same way that adding a 0 to a decimal number multiplies by 10, adding a 0 to a binary number multiplies by 2.
Jim
-
I think I've found the original problem
mov ah, 0Ch ; Put pixels
; Repeat through the line pixel by pixel
repeat deltax
; Put pixel
mov dh, [x] ; X-axis
mov ch, [y] ; Y-axis
mov al, 255 ; Color (White)
int 10h ; Perform
int 10h function 0Ch is described here http://www.ctyme.com/intr/rb-0104.htm
It's expecting cx and dx for the pixel positions. You're filling in ch and dh, so everything is 256x too big.
Try making it
xor dx,dx
xor cx,cx
mov dl,[x]
mov cl,[y]
Does that make any difference?
Jim
-
Ints to plot pixels is bad
Try a direct memory access starting from 0a00h
-
I think you mean 0a000h
-
I'm using FASM, and I'm only an ASM novice, so I don't know what you mean by using direct memory access starting from 0a000h. Anyway, I'm rewriting it now, but what's wrong with macros, ifs, and repeats?
-
?
-
@Phonix, try something like that to draw a pixel on screen (compile with fasm), and use function to create your line draw as Jim suggested.
;
; --------------
; Kryton Advetro
; --------------
;
; by Rbraz ^ Gravity
; April 2006
;
org 100h
;-------------VGA mode X - 320x200x256k
mov al,13h
int 10h
push 0a000h ; Vga memory
pop es ;
;-------------Load Palette
mov cl,63
mov bl,126
.pal:
mov dx,3c8h
mov al,bl ;[ col ]
dec bl
out dx,al
inc dx
mov al,0 ;[ r ]
out dx,al
mov al,0 ;[ g ]
out dx,al
mov al,cl ;[ b ]
out dx,al
loop .pal
;-------------Write our text
mov ah,02h
mov bh,00h
mov dx,0308h
int 10h
mov ah,9
mov dx,text
int 21h
Main:
;-------------Wait for vertical retrace
mov dx,03DAh
.wait_for_retrace:
in al,dx
test al,8
jz .wait_for_retrace
;-------------Blur Screen
mov di,16000
mov cx,8000
.blur:
mov eax,[es:di]
cmp eax,40404040h
jle .noblur
sub eax,01010101h
.noblur:
stosd
loop .blur
;-------------Sine wave function
fld [angle]
fadd [one]
fst [angle]
fdiv [twopi]
fsin
fmul [mult]
fadd [ center ]
fistp [y]
.draw:
mov ax,word [y] ; ax = y
mov bx,[x] ; bx = x
;-------------WritePixelFast :)
; vgamemory[x + (y*320)] = color ; bx=x, ax=y, cl=color
imul ax,320
add ax,bx
mov di,ax
mov byte [es:di],126 ; color
;-------------Increments x pos
inc [x]
cmp [x],320
je .lp1
jmp .draw
.lp1:
mov [x],0
; mov [angle],0
;-------------Loop (While not key hit)
mov ah,01
int 16h
jz Main
;-------------Return to text mode
mov al,03h
int 10h
;-------------Exit to DOS
mov ax,4c00h
int 21h
;-------------Some variables
angle dd 0.0
one dd 0.25
mult dd 20.0
center dd 100.0
y dd 0.0
x dw 0
twopi dd 6.2830
text db 'Kryton >> Coming up soon!',24h
-
I'm using FASM, and I'm only an ASM novice, so I don't know what you mean by using direct memory access starting from 0a000h.
Segment a000h is where the screen memory starts. In the mode you're using, there is 64Kb there, 320bytes wide, 200bytes high.
To write a pixel, you can poke into that memory.
;com file
org 100h
;screen mode 13h
mov ax,013h
int 10h
;point ds segment register at screen
mov ax,0a000h
mov ds,ax
;colour 255
mov al,255
;pixel address (320*y+x)
mov si,320*100+160
;write pixel
mov [si],al
;wait for a key
wait:
mov ah,01
int 016h
jz wait
;text mode
mov ax,03h
int 10h
;exit to dos (actually, ret is fine for .com programs)
mov ax,4c00h
int 21h
Fiddle around with the value in si (0-63999) to move the pixel and the colour in al (0-255)
Jim
-
Thanks for your help, I'll try it later...