Author Topic: Drawing a Line  (Read 8759 times)

0 Members and 1 Guest are viewing this topic.

Offline Phoenix

  • C= 64
  • **
  • Posts: 99
  • Karma: 4
    • View Profile
Drawing a Line
« 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

Offline Phoenix

  • C= 64
  • **
  • Posts: 99
  • Karma: 4
    • View Profile
Re: Drawing a Line
« Reply #1 on: August 13, 2006 »
Ohh, I think I got it. I'm just going to finish it...

Offline Phoenix

  • C= 64
  • **
  • Posts: 99
  • Karma: 4
    • View Profile
Re: Drawing a Line
« Reply #2 on: August 13, 2006 »
Hmm... I followed this 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:
Code: [Select]
; 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

Offline Rbz

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 2757
  • Karma: 493
    • View Profile
    • https://www.rbraz.com/
Re: Drawing a Line
« Reply #3 on: August 13, 2006 »
Can you provide the full source, with screen initializations etc ?
Challenge Trophies Won:

Offline Phoenix

  • C= 64
  • **
  • Posts: 99
  • Karma: 4
    • View Profile
Re: Drawing a Line
« Reply #4 on: August 13, 2006 »
Code: [Select]
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

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Drawing a Line
« Reply #5 on: August 13, 2006 »
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
Challenge Trophies Won:

Offline Phoenix

  • C= 64
  • **
  • Posts: 99
  • Karma: 4
    • View Profile
Re: Drawing a Line
« Reply #6 on: August 14, 2006 »
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?

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Drawing a Line
« Reply #7 on: August 14, 2006 »
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
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Drawing a Line
« Reply #8 on: August 14, 2006 »
I think I've found the original problem
Code: [Select]
        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
Code: [Select]
xor dx,dx
xor cx,cx
mov dl,[x]
mov cl,[y]

Does that make any difference?

Jim
Challenge Trophies Won:

Offline relsoft

  • DBF Aficionado
  • ******
  • Posts: 3303
  • Karma: 47
    • View Profile
Re: Drawing a Line
« Reply #9 on: August 15, 2006 »
Ints to plot pixels is bad

Try a direct memory access starting from 0a00h
Challenge Trophies Won:

Offline Agent Smith

  • ZX 81
  • *
  • Posts: 24
  • Karma: 3
    • View Profile
Re: Drawing a Line
« Reply #10 on: August 15, 2006 »
I think you mean 0a000h

Offline Phoenix

  • C= 64
  • **
  • Posts: 99
  • Karma: 4
    • View Profile
Re: Drawing a Line
« Reply #11 on: August 15, 2006 »
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?

Offline Agent Smith

  • ZX 81
  • *
  • Posts: 24
  • Karma: 3
    • View Profile
Re: Drawing a Line
« Reply #12 on: August 15, 2006 »
?
« Last Edit: August 15, 2006 by Agent Smith »

Offline Rbz

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 2757
  • Karma: 493
    • View Profile
    • https://www.rbraz.com/
Re: Drawing a Line
« Reply #13 on: August 15, 2006 »
@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.


Code: [Select]
;
;   --------------
;   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
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Drawing a Line
« Reply #14 on: August 16, 2006 »
Quote
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.
Code: [Select]
;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
Challenge Trophies Won:

Offline Phoenix

  • C= 64
  • **
  • Posts: 99
  • Karma: 4
    • View Profile
Re: Drawing a Line
« Reply #15 on: August 18, 2006 »
Thanks for your help, I'll try it later...