Line routines

All 680x0 related coding posts in this section please.

Moderators: simonsunnyboy, Mug UK, Zorro 2, Moderator Team

User avatar
atari_mark
Captain Atari
Captain Atari
Posts: 182
Joined: Thu Oct 10, 2002 12:30 pm
Location: Wigan, England
Contact:

Line routines

Postby atari_mark » Thu Aug 31, 2006 12:35 pm

Many years ago when I was very active on the Atari scene, the world of 3D was lost on me. I had no idea how to draw lines, rotate, depth sort, etc. One day I had a brain wave and wrote a line drawing routing which I later found out was code based on the Bresenham method. I wrote the line rout into the Poverty demo then forgot all about it.

Recently I have been wondering how other people wrote line drawing routines. The theory behind Bresenham is simple but it is a slow way of drawing lines. So what method do other people use, can you explain them simply and what is perceived as the fastest line routine?
Mac Sys Data/Persistence Of Vision

Instructions said to install Windows 2000 or better so I installed Fedora.

Maartau
Fuji Shaped Bastard
Fuji Shaped Bastard
Posts: 2630
Joined: Thu Dec 15, 2005 2:15 am
Location: France

Postby Maartau » Fri Sep 01, 2006 8:30 pm

Hiya,

3d's fast routs seems ones of the "nec plus ultra" & hard to find sources.

You probably checked Marcer's Ftp & find Fury's routs :?:

I can post Arkham's 3d's code also there. (I'm the person who send them to Marcer :wink: )

You can find some excerpts in ST Mag (french only :oops: But for comments so a code is a code :) )(One hint there : Oxbab used some of these in his demos :roll: => Run Easy Rider & you can find all symbols. :wink: ATM doesn't have names in memory.

3d isn't my "swimming pool"/"cup of tea", fullfilled ... less.

G.

User avatar
MiggyMog
Atari Super Hero
Atari Super Hero
Posts: 865
Joined: Sun Oct 30, 2005 4:43 pm
Location: Scotland

Postby MiggyMog » Sat Sep 02, 2006 4:16 pm

The English language have stollen the French word "Forte" Maartau so you could have used that without being misunderstood.

'Not my cup of Tea' is more of a preference thing rather than being what you are familiar with.

I have some scans of the STF 3D article somewhere but it only gives the basic theory IIRC.
Last edited by MiggyMog on Sun Sep 03, 2006 1:34 pm, edited 1 time in total.
('< o o o o |''| STM,2xSTFM,2xSTE+HD,C-Lab Falcon MK2+HD,Satandisk,Ultrasatandisk,Ethernat.

User avatar
leonard
Moderator
Moderator
Posts: 648
Joined: Thu May 23, 2002 10:48 pm
Contact:

Postby leonard » Sun Sep 03, 2006 8:48 am

Lines rout are great ! Remember me old years :-) At the end almost everyone had he same routine. Classic routines draw 15 lines per frame if I remember well (a line from 0,0 to 319,199).

You cna do better using a new method, with bitmap blocks, and carefully link blocks together. I think no demos were release with that method.
Leonard/OXYGENE.

User avatar
atari_mark
Captain Atari
Captain Atari
Posts: 182
Joined: Thu Oct 10, 2002 12:30 pm
Location: Wigan, England
Contact:

Postby atari_mark » Sun Sep 03, 2006 10:48 am

leonard wrote:You cna do better using a new method, with bitmap blocks, and carefully link blocks together. I think no demos were release with that method.


In 1992 I was discussing line drawing and I mentioned was it not possible to use bitmaps, we agreed it was possible but it would take a lot of work to put a demo together using this method.
Mac Sys Data/Persistence Of Vision



Instructions said to install Windows 2000 or better so I installed Fedora.

User avatar
earx
Captain Atari
Captain Atari
Posts: 353
Joined: Wed Aug 27, 2003 7:09 am

Postby earx » Tue Sep 05, 2006 7:37 am

i made a lot of line routs. some bresenham and some using div + add. the method with blocks sounds interesting. but it possibly looks slightly worse and would be only useful for long lines. still worth a shot i'd say..

on chunky screens (i started on falcon highcolor) it's best to use an approach where you walk through the line from two sides, making it alot faster! this leads to a little knot in the middle. but with some effort you can overcome this. in the best case you can reach speeds of 1.4 mln pix/sec on a plain falcon.

on ST i stick with the "straightforward" bresenham line routine. I (sadly) use conditional branching within the loop but in order to gain some speed i unroll the loop as much as possible. also, i use just one bitplane. the funny thing is that the DY > DX case is probably the fastest..

Code: Select all


; input:
; d0.w=x0
; d1.w=y0
; d2.w=x1
; d3.w=y1
; d4.w=$F
; a0: screen
; a1: offset table
; a2: putpixel table
Line.paint:
   cmp.w   d0,d2
   bgt.s   .x_order_ok
   exg   d0,d2
   exg   d1,d3
.x_order_ok:
   sub.w   d0,d2            ; d2.w=dx=abs(dx)
   sub.w   d1,d3            ; d3.w=dy
   add.w   d1,d1
   move.w   d0,d5
   and.w   d4,d0            ; d0.w=lx&$F
   sub.w   d0,d5            ; d5.w=lx&$FFF0
   lsr.w   d5            ; d5.w=chunk=(lx&$FFF0)>>2
   add.w   (a1,d1.w),d5         ; d5.w=offset=y*160+chunk
   lea   (a0,d5.w),a6
   move.w   #160,d6            ; d6.w=y increment
   move.w   d3,d7
   bpl.s   .y_abs
   neg.w   d7
   neg.w   d6            ; negative increment!
.y_abs:   cmp.w   d2,d7
   bgt.s   .dy_greater

.dx_greater:
; todo: special masking poo!   
;   add.w   d0,d0
;   cmp.w   d0,d5
;   bgt.s   .mask_optimised
; choose a mask-optimised thingy or straight-forward put-pixel stuffs.

; for now we use a totally 100% pessimised (but simple) loop!
   move.w   d2,d5            ; d5.w=abs(dx)
   move.w   d2,d3            ; d3.w=abx(dx)
   add.w   d0,d0
   move.w   (a2,d0.w),d0
   moveq   #0,d1

.hor_loop:
   or.w   d0,d1
   sub.w   d7,d5
   bgt.s   .next_hor
   add.w   d2,d5
   or.w   d1,(a6)
   moveq   #0,d1
   adda.w   d6,a6
.next_hor:
   ror.w   d0
   dbcs   d3,.hor_loop

   or.w   d1,(a6)
   moveq   #0,d1
   addq   #8,a6
; beware, d3 may already be -1! no dbf possible!
   subq.w   #1,d3
   bpl.s   .hor_loop

   rts

; todo: use table to get rout decision?
.dy_greater:
   move.w   d7,d5            ; d5.w=abs(dy)
   move.w   d7,d3
   add.w   d0,d0
   move.w   (a2,d0.w),d0
;   tst.w   d2
;   bmi.s   .rol_loop

   ifne   1

   lea   .jump_end(pc),a3      ;  8
   neg.w   d7            ;  4
   lsl.w   #4,d7            ; 14 / combines to
   jmp   (a3,d7.w)         ; 14 \ 28, not 32 :))
   
   rept   200
   or.w   d0,(a6)
   sub.w   d2,d5
   bgt.s   *+10   ;.next
   add.w   d3,d5
   ror.w   d0
   bcc.s   *+4   ;.next
   addq   #8,a6
;.next:
   adda.w   d6,a6
   endr
.jump_end:

   else

.ror_loop:
   or.w   d0,(a6)
   sub.w   d2,d5
   bgt.s   .next_ror
   add.w   d3,d5
   ror.w   d0
   bcc.s   .next_ror
   addq   #8,a6
.next_ror:
   adda.w   d6,a6
   dbf   d7,.ror_loop

   endc
   rts

; never gets called with dx>=0
.rol_loop:
   or.w   d0,(a6)
   sub.w   d2,d5
   bgt.s   .next_rol
   add.w   d3,d5
   add.w   d0,d0
   bcc.s   .next_rol
   moveq   #1,d0
   subq   #8,a6
.next_rol:
   adda.w   d6,a6
   dbf   d7,.rol_loop
   rts


User avatar
leonard
Moderator
Moderator
Posts: 648
Joined: Thu May 23, 2002 10:48 pm
Contact:

Postby leonard » Wed Sep 06, 2006 4:45 pm

I love line routines !

There is another great trick for lines "almost" horizontal: put pixel into register instead of screen ! In the previous exemple, (only case dx>dy), there is one "or.w d0,(a6" per pixel. If the line is "alomost" horizontal (say dx > *3dy) tou can do:

or.w d0,d1
sub.w d2,d5
bgt.s .next_rol
or.w d1,(a6)
moveq #0,d1
add.w d3,d5
add.w d0,d0
bcc.s .next_rol
moveq #1,d0
subq #8,a6
.next_rol:

I hope you see the trick (the previous rout is not good as you have to store the pixels if you change 16 pixels blocks too)

Another great trick when unrolling loops is to remove every "rol" stuff:

or.w #$8000,d1
or.w #$4000,d1
etc..

if you don't like the trick of writing in register before flusing in the screen , better use .B adressing so you can use registers to draw pixels:

or.b d0,(a1)
or.b d1,(a1)

etc.

you may say you need 8 data registers and it's goosed up ! No! just use mixed code with or.b or bset ! if D0 = 1 then

or.b d0,(a0) draw pixel at coord 7
bset d0,(a0) draw a pixel at coord 6

You draw two different pixels with only one data registers, that's the trick :-)
Leonard/OXYGENE.

User avatar
earx
Captain Atari
Captain Atari
Posts: 353
Joined: Wed Aug 27, 2003 7:09 am

Postby earx » Mon Sep 11, 2006 7:25 am

There is another great trick for lines "almost" horizontal: put pixel into register instead of screen ! In the previous exemple, (only case dx>dy), there is one "or.w d0,(a6" per pixel. If the line is "alomost" horizontal (say dx > *3dy) tou can do:


i do this already, check my code. :) it's almost a first requirement to speed things up.

getting rid of the ROR would be a cool thing, though.. never thought about this. . are there alot of unrolling and tables required to do this?

for the rest i know that when dx >> dy , or dx << dy , you can speed up by using start, end masks for the horizontal case (like a polygon filler) and unrolled "inner" loops for the vertical case:

vertical case example ( 3 <= dy/dx < 4 )

loop:
rept 3
or.w d0,(a6)
adda.w d6,a6
endr
sub.w d2,d5
bgt.s next
or.w d0,(a6)
adda.w d6,a6
next:

but for the case where dy/dx ~= 1 it stays slow. that's where this joining blocks idea may come in handy?

maartau: i'll check out Fury's routs :)

User avatar
earx
Captain Atari
Captain Atari
Posts: 353
Joined: Wed Aug 27, 2003 7:09 am

Postby earx » Tue Sep 12, 2006 7:26 am

i checked Fury's code, the line routine to be specific. it's also a bresenham.. but the implementation could be faster: a CMPI instruction is not the best way to do things. otherwise, it's a good all-round routine.

Maartau
Fuji Shaped Bastard
Fuji Shaped Bastard
Posts: 2630
Joined: Thu Dec 15, 2005 2:15 am
Location: France

Postby Maartau » Tue Sep 12, 2006 8:47 am

Ahem, one "Bresenham" representation found on the net...

*******************************************************************************
*LINE from d0,d1 (x1,y1) to d2,d3 (x2,y2) without blitter. (Raped Bresenham :-)
*Uses only 68000 instructions (almost no gain by using higher CPU intructions)
*Can be converted to work in chunky-mode because it 'walks' through adresses.
*I've included some psuedo-C comments to clearify the sourcecode.
*Made by Patrick van Logchem (v912152@si.hhs.nl) on 7 June 1993.
*******************************************************************************

cnop 0,8

CPUline:
lea screen,a1 ; offset='start adress of bitplane'

move.w #Width>>3,d4
muls d1,d4
add.w d4,a1 ; 'add Y offset to screen-pointer'

move.w d0,d4
lsr.w #3,d4
add.w d4,a1 ; 'add X offset to screen-pointer'

moveq #1,d4
move.w d2,d6
sub.w d0,d6 ; ax = abs(x2 - x1)
bge.s noABSx
neg.w d6
neg.w d4 ; sx = sign(x2 - x1) /* X-step */
noABSx:
move.w #Width>>3,d5
move.w d3,d7
sub.w d1,d7 ; ay = abs(y2 - y1)
bge.s noABSy
neg.w d7
neg.w d5 ; sy = (Width/8)*sign(y2 - y1) /* Y-step */
noABSy:
cmp.w d6,d7
bgt.w ydomi ; if(ax > ay)

;-----------------------------------------
; X dominant part:

xdomi:
move.w d6,d1 ; d1 = counter /* length of line = ax */
move.w d6,d2
asr.w #1,d2 ; D = ax>>1 /* 'D' is digital error */

not.b d0 ; X = bitnr(X)
and.w #7,d0 ; X &= 7
bchg.b d0,(a1) ; 'change bit on [offset]'
dbf d1,xloop
rts

nop
nop
nop ; use nop's to make sure xloop is on a 8 byte boundary (for speed)
xloop:
sub.w d7,d2 ; D -= ay
bgt.s x_no_e ; if(D <0>>1 /* 'D' is digital error */

not.b d0 ; X = bitnr(X)
and.w #7,d0 ; X &= 7
bchg.b d0,(a1) ; 'change bit on [offset]'
dbf d1,yloop
rts

nop
nop
nop
yloop:
sub.w d6,d2 ; D -= ax
bgt.s y_no_e ; if(D < 0) {
add.w d7,d2 ; D += ay
sub.w d4,d0 ; X -= sx /* next bitnr */
btst #3,d0 ; /* bit 3 clear = X between 0 and 7 ? */
beq.s y_no_e ; if(X & 8) {
and.w #7,d0 ; X &= 7
add.w d4,a1 ; offset += sx }
; }
y_no_e:
bchg.b d0,(a1) ; 'change bit on [offset]'
dbf d1,yloop
rts

Maartau
Fuji Shaped Bastard
Fuji Shaped Bastard
Posts: 2630
Joined: Thu Dec 15, 2005 2:15 am
Location: France

Postby Maartau » Tue Sep 12, 2006 8:49 am

Is it "THE" Earx there :?: :wink: :lol:

:EARchaeopteryx says:

ÿÿf1!cluck BRESENHAM!ÿÿf0

After that powerful title that could start world war III, you probably expect
something mindboggling... something cunning.... something like:

A replacement for the bresenham algorithm?!?!

For those of you that don't know what the hell that is, I should say: "And
you call yourself a coder!" ;-)
The bresenham algo relies on first calculating a few simple discriminants. In
the main loop these discriminants added to/subtracted from eachother. This is
quite effecient, because the loop only consists of some simple and fast
instructions.

Let's cut the crap and get to it. I found out a quite simple algorithm that
beats the old bresenham to it. It is based on the following incredibly simple
math >>>> steepness = dX/dY >>>> Where dX is the difference between the
x-coordinate of point 1 and point 2 of the line and dY is the same for the
y-coordinate.

OK, let's get to the code then, shall we? Here is it in dumb Pascal. And all
you speedfreaks: don't worry, I know this isn't neccessarily faster than
Bresenham, but the assembler version is!!

------------------------------ òsourcecode 1 ð---------------------------------

Procedure DrawLine(integer: X1, X2, Y1, Y2)
var
X, Y, dX, dY: integer;
steepness, d: real;
begin
dX:=X2-X1;
dY:=Y2-Y1;
if dX > dY then
{The loop for the situation where dX > dY}
begin
steepness:=dY/dX
d:=Y1;
for X:=X1 to X2 do
begin
PutPixel(X, Trunc(d), 1); {plot the pixel by using the integer part}
d:=d+steepness; {add steepness to get the new Y}
end;
end;
else
{The same loop for the situation where dX =< DY}
begin
steepness:=dX/dY;
d:=X1;
for Y:=Y1 to Y2 do
begin
PutPixel(Trunc(d), Y, 1) {plot the pixel by using the integer part}
d:=d+steepness; {add steepness to get the new X}
end;
end;
end;

--------------------------- òend of sourcecode 1 ð-----------------------------

There it was in Pascal. Ofcourse this still is slow. And I'm not talking
about the normal Pascal compilers that are crap, but about the instructions
used. There is a floating-point division at the initilializing part of the
procedure, so this is quite slow when the line we want to draw is short (i.e.
the main loop is done only a few times).

The good thing however, is that only very simple instructions are used in the
main loop (for..do statement). And ofcourse the main loop is executed
everytime a pixel is drawn so that mostly outweights the executing time of
the initializing part.

The big difference with bresenham algo is that this uses floating-point
numbers whereas bresenham only uses integers....

...What's that??......I hear a voice screaming from far away....

Y0u S0d!! th@t'5 th3 wh0le p0inT: N0t us1nG 3xpeNs1vE floating-point
op3raTi0n5!

Now that might be true, but in the assembler version for the beautiful 680x0
series of processors, we don't need that poo!! We can do it with fairly
cheap fixed point numbers! HARHAR!

The ñ<Trunc>ð statement from the Pascal-source can easily be translated
into: ñ<swap>ð on the 68000 :-) Comprendez? Non? Well.. Let's say you have
a 68000 register like d0. This contains 32 bits. Now you can divide this up
into two spaces: the upper 16 bits for the integer part and the lower 16 bits
for the fractational part. What the ñ<swap>ð instruction does is only swap
the upper part with lower part so you can use the integer part of the number!

This is more or less the principle my new routine relies on. It uses the same
technique as the Pascal algorithm, but only now with a bit of fixed point
techniques and further optimisations. Ofcourse we can't get rid of the
division instruction, but we can make a ñ<divu>ð out of this with some
effort.

The routine I'm about to show here has NO CLIPPING so don't do anything weird
with it and uses Falcon truecolor mode. (320 pixels wide!) It is a subroutine
that is called by putting some values in the data-/address-registers.

------------------------------- òSourcecode 2ð --------------------------------

* INPUT: d0.w: X1
* d1.w: Y1
* d2.w: X2
* d3.w: Y2
* d6.w: highcolor word (color of line)
* a0: start of screenaddress
DRAW_TRUELINE
move.l d2,d4
move.l d3,d5
sub.w d0,d2 ; / calculate the absolute
bpl.s .ok ; | value of the difference
neg.w d2 ; \ between X1 and X2
.ok sub.w d1,d3 ; / calculate the absolute
bpl.s .ok2 ; | value of the difference
neg.w d3 ; \ between Y1 and Y2
.ok2 cmp.w d2,d3
bhi.s .ver
* Part for dX > dY
cmp.w d0,d4 ; / Get the
bhs.s .do2 ; | heighest
exg d0,d4 ; | X and Y
exg d1,d5 ; \ in d4.w and d5.w
.do2 moveq #10,d2 ; \put #640
lsl.l #6,d2 ; /in d2.l (bytes in scanline)
sub.w d0,d4
sub.w d1,d5
add.l d0,d0
adda.l d0,a0
mulu.w d2,d1
adda.l d1,a0
tst.w d5
bpl.s .poo
neg.w d5 ; / make the
neg.l d2 ; | dX absolute
.poo swap d5 ; | and negate the scanline-
addq.w #1,d4 ; \ offset if needed
divu.w d4,d5 ; d5.w: steepness
moveq #0,d0
subq.w #1,d4 ; d4.w: number of times to loop

.lp2 add.w d5,d0 ; / check if you need to jump to
bcc.s .mov ; \ the next scanline
adda.l d2,a0 ; jump to the next scanline
.mov move.w d6,(a0)+ ; plot and go to next pixel
dbra d4,.lp2
rts

* Part for dX =< dY
.ver cmp.w d0,d4
bhs.s .do
exg d0,d4
exg d1,d5
.do moveq #10,d2 ; \put #640
lsl.l #6,d2 ; /in d2.l (bytes in scanline)
sub.w d0,d4
sub.w d1,d5
add.l d0,d0
adda.l d0,a0
mulu.w d2,d1
adda.l d1,a0 ; a0: address of first pixel
tst.w d5 ; / make the
bpl.s .shitt ; | dY absolute
neg.w d5 ; | and negate the scanline-
neg.l d2 ; \ offset if needed
.shitt swap d4
addq.w #1,d5
divu.w d5,d4 ; d4.w: steepness
moveq #0,d0
subq.w #1,d5 ; d5.w: number of times to loop

.lp add.w d4,d0 ; / check if you need to jump to
bcc.s .movie ; \ the next pixel in the scanline
addq.l #2,a0 ; go to next pixel in scanline
.movie move.w d6,(a0) ; plot the pixel
adda.l d2,a0 ; go to next scanline
dbra d5,.lp
rts

---------------------------- òend of sourcecode 2 ð----------------------------

Well.. There you have it then. I tried this and put it up against some of the
best versions of bresenham linerouts I had and it still came out victorious!

The future: This routine is almost as fast as it gets. There is only two
things you could do to make it even faster:
ó1) ðCode specific main loops for special steepnesses. ( steepness<1/8 ,
steepness<1/4, etc..) I really want to do this. This could boost the speed
by 20-30% (!)
ó2) ðDraw the line from both ends, so you decrease the number of loops by 50%!
But this looks a bit awkward if you ask me: you get a little knot in the
middle of the line. So this is fast, but not always pretty.

-------------------------------------==================== EarX/fUn =========

User avatar
earx
Captain Atari
Captain Atari
Posts: 353
Joined: Wed Aug 27, 2003 7:09 am

Postby earx » Wed Sep 13, 2006 8:57 am

hehehe =) the first one (bresenham) i didn't know yet. is it an atari or amiga source?

the second one. hehehe, looking at it now i can say it could get alot faster by unrolling and using an addx instruction..

move.w d2,(a0,d0.w*2)
addx.l d1,d0
adda.l a6,a0

since this is 8 bytes, it's easy to put into a jump tree..

thedocbwarren
Retro freak
Retro freak
Posts: 15
Joined: Tue May 04, 2010 7:42 pm

Re: Line routines

Postby thedocbwarren » Wed May 19, 2010 2:42 am

I've been trying to play with this and make this work with bitplanes (oh the pain!!) has anyone been able to use the fast algorithm for the ST? I attempted to pair with a pixmapping sub to use the routine but no luck drawing a line.

User avatar
Zorro 2
Administrator
Administrator
Posts: 2209
Joined: Tue May 21, 2002 12:44 pm
Location: Saint Cloud (France)
Contact:

Another routine for mister Unkof

Postby Zorro 2 » Thu Nov 18, 2010 1:28 pm

Code: Select all

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ROUTINE DE LIGNE BY TCHOOM/ARKHAM (NON CLIPPE) ;
; INTEGRABLE DANS PROGRAMME UTILISANT LES LIGNES ;
; ENTREE:   A0=ADRESSE ECRAN       ;
;       A3=ADR. D'UN BUFFER D'EFFACEMENT ;
;      D0=X1      D1=Y1       ;
;      D2=X2      D3=Y3       ;
; SORTIE   A3=FIN DU BUFFER D'EFFACEMENT    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

line
 cmp.w d0,d2      Sens gauche_droite
 bhi.s no_change1
 exg d0,d2
 exg d1,d3
no_change1

 sub.w d0,d2      Dx
 sub.w d1,d3      Dy

 move.w d1,d4
 lea.l table_y,a1   Calcul de l'adresse ecran
 lsl.w d4
 add.w d4,a1
 add.w (a1)+,a0
 move.w d0,d4
 lea.l table_x,a1   
 lsl.w #2,d4
 add.w d4,a1
 add.w (a1)+,a0
 move.w (a1)+,d4

 move.w #$a0,a2      Sens de la pente
 tst.w d3
 bpl.s no_change2
 neg.w d3
 move.w #-$a0,a2
no_change2

 cmp.w d2,d3      Diagonale
 bne.s no_equ
 addq.w #1,d3
no_equ

 cmp.w d2,d3
 blo.s line_x

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; routine de ligne verticale ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

line_y
 move.l #$00070001,d1
 cmpi.w #8,d4
 blo.s no_change4
 addq.w #1,a0
 subq.w #8,d4
 swap d1
no_change4
 moveq.w #7,d0
 sub.w d4,d0
 swap d2
 tst.w d3
 bne.s no_nul_d3
 moveq.w #1,d3
no_nul_d3
 divu.w d3,d2
 lea.l offset_y,a1
 add.w d3,d3
 add.w d3,d3
 adda.w d3,a1
 move.l (a1),a1

 move.l a1,r_rts2+4
 move.w (a1),r_rts2+2
 move.w #$4e75,(a1)
 move.w d2,a1
 moveq.w #0,d6
 jsr code_y
r_rts2 move.w #0,code_y
 rts

;;;;;;;;;;;;;;;;;;;;;;;
; routine horizontale ;
;;;;;;;;;;;;;;;;;;;;;;;

line_x
 cmpi.w #8,d4
 blo.s no_change3
 addq.w #1,a0
no_change3
 swap d3
 tst.w d2
 bne.s no_d2_0
 moveq.w #1,d2      Evite division par zero !
no_d2_0
 divu.w d2,d3

 lea.l offset_x,a1
 add.w d0,d0
 add.w d0,d0
 add.w d0,a1
 move.l (a1),saut1+2
 add.w d2,d2
 add.w d2,d2
 add.w d2,a1
 move.l (a1),a1

 move.l a1,r_rts+4
 move.w (a1),r_rts+2
 move.w #$4e75,(a1)

 move.w d3,a1      Transfere pente
 moveq.w #0,d6      Compteur de pente
 moveq.w #-128,d5
 moveq.w #64,d4
 moveq.w #32,d3
 moveq.w #8,d2
 moveq.w #4,d1      Sert pour le 4 et 16
 moveq.w #1,d0      Sert pour le 1 et 2
saut1 jsr code_x
 move.l a0,(a3)+
r_rts move.w #0,code_x
 rts 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; routine pour code horizontale ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

code_x
 or.b d5,(a0)      ; 128
 add.w a1,d6
 bcc.s code_x1
 move.l a0,(a3)+
 add.w a2,a0
code_x1
 or.b d4,(a0)      ; 64
 add.w a1,d6
 bcc.s code_x2
 move.l a0,(a3)+
 add.w a2,a0
code_x2
 or.b d3,(a0)      ; 32
 add.w a1,d6
 bcc.s code_x3
 move.l a0,(a3)+
 add.w a2,a0
code_x3
 bset.b d1,(a0)      ; 16
 add.w a1,d6
 bcc.s code_x4
 move.l a0,(a3)+
 add.w a2,a0
code_x4
 or.b d2,(a0)      ; 8
 add.w a1,d6
 bcc.s code_x5
 move.l a0,(a3)+
 add.w a2,a0
code_x5
 or.b d1,(a0)      ; 4
 add.w a1,d6
 bcc.s code_x6
 move.l a0,(a3)+
 add.w a2,a0
code_x6
 bset.b d0,(a0)      ; 2
 add.w a1,d6
 bcc.s code_x7
 move.l a0,(a3)+
 add.w a2,a0
code_x7
 move.l a0,(a3)+
 or.b d0,(a0)+      ; 1
 add.w a1,d6
 bcc.s code_x8
 move.l a0,(a3)+
 add.w a2,a0
code_x8
 or.b d5,(a0)      ; 128
 add.w a1,d6
 bcc.s code_x9
 move.l a0,(a3)+
 add.w a2,a0
code_x9
 or.b d4,(a0)      ; 64
 add.w a1,d6
 bcc.s code_x10
 move.l a0,(a3)+
 add.w a2,a0
code_x10
 or.b d3,(a0)      ; 32
 add.w a1,d6
 bcc.s code_x11
 move.l a0,(a3)+
 add.w a2,a0
code_x11
 bset.b d1,(a0)      ; 16
 add.w a1,d6
 bcc.s code_x12
 move.l a0,(a3)+
 add.w a2,a0
code_x12
 or.b d2,(a0)      ; 8
 add.w a1,d6
 bcc.s code_x13
 move.l a0,(a3)+
 add.w a2,a0
code_x13
 or.b d1,(a0)      ; 4
 add.w a1,d6
 bcc.s code_x14
 move.l a0,(a3)+
 add.w a2,a0
code_x14
 bset.b d0,(a0)      ; 2
 add.w a1,d6
 bcc.s code_x15
 move.l a0,(a3)+
 add.w a2,a0
code_x15
 or.b d0,(a0)      ; 1
 add.w a1,d6
 bcc.s code_x16
 move.l a0,(a3)+
 add.w a2,a0
code_x16
 move.l a0,(a3)+
 addq.l #7,a0
code_x17
 ds.b 19*(code_x17-code_x)
x_rts rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; code pour routine verticale ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

code_y
 bset.b d0,(a0)
 move.l a0,(a3)+
 add.w a2,a0
 add.w a1,d6
 bcc.s code_y2
 dbf d0,code_y2
 add.w d1,a0
 swap d1
 moveq.w #7,d0
code_y2
 ds.b 199*(code_y2-code_y)
y_rts rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; routine d'init de la ligne ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

init_line
 lea.l table_x,a0      Rempli Table_x
 move.w #319,d0
 moveq.w #0,d1
 move.w #0,d2
rempli_table_x
 move.w d1,(a0)+
 move.w d2,(a0)+
 addq.w #1,d2
 cmpi.w #16,d2
 bne.s rempli_table_x2
 moveq.w #0,d2
 addq.w #8,d1
rempli_table_x2
 dbf d0,rempli_table_x
 lea.l table_y,a0      Rempli Table_y
 move.w #199,d0
 moveq.w #0,d1
rempli_table_y
 move.w d1,(a0)+
 addi.w #160,d1
 dbf d0,rempli_table_y

 lea.l offset_x,a0      Rempli offset_x

n set 0
 rept 20
 move.l #code_x+n,(a0)+
 move.l #code_x1+n,(a0)+
 move.l #code_x2+n,(a0)+
 move.l #code_x3+n,(a0)+
 move.l #code_x4+n,(a0)+
 move.l #code_x5+n,(a0)+
 move.l #code_x6+n,(a0)+
 move.l #code_x7+n,(a0)+
 move.l #code_x8+n,(a0)+
 move.l #code_x9+n,(a0)+
 move.l #code_x10+n,(a0)+
 move.l #code_x11+n,(a0)+
 move.l #code_x12+n,(a0)+
 move.l #code_x13+n,(a0)+
 move.l #code_x14+n,(a0)+
 move.l #code_x15+n,(a0)+
n set n+(code_x17-code_x)
 endr

 lea.l code_x,a0      Complete code_x
 lea.l code_x17,a1
 move.w #18,d0
rempli_code_x
 rept (code_x17-code_x)
 move.b (a0)+,(a1)+
 endr
 dbf d0,rempli_code_x

 lea.l code_y,a0      Complete code_y
 lea.l code_y2,a1
 move.w #198,d0
complete_x
 rept (code_y2-code_y)
 move.b (a0)+,(a1)+
 endr
 dbf d0,complete_x

 lea.l offset_y,a0
 lea.l code_y,a1
 move.w #199,d0
rempli_offset_y
 move.l a1,(a0)+
 add.l #code_y2-code_y,a1
 dbf d0,rempli_offset_y
 rts

table_x  ds.l 320
table_y  ds.w 200
offset_x ds.l 320
offset_y ds.l 200
Member of NoExtra Team

User avatar
simonsunnyboy
Moderator
Moderator
Posts: 5121
Joined: Wed Oct 23, 2002 4:36 pm
Location: Friedrichshafen, Germany
Contact:

Re: Line routines

Postby simonsunnyboy » Thu Nov 18, 2010 4:44 pm

What is "ADR. D'UN BUFFER D'EFFACEMENT " please?
Simon Sunnyboy/Paradize - http://paradize.atari.org/

Stay cool, stay Atari!

1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee

tfdi
Atariator
Atariator
Posts: 19
Joined: Mon Oct 25, 2010 6:31 pm

Re: Line routines

Postby tfdi » Thu Nov 18, 2010 5:06 pm

Thanks a lot Zorro2 ..... :mrgreen:

Simonsunnyboy:it's a Clear buffer

User avatar
simonsunnyboy
Moderator
Moderator
Posts: 5121
Joined: Wed Oct 23, 2002 4:36 pm
Location: Friedrichshafen, Germany
Contact:

Re: Line routines

Postby simonsunnyboy » Thu Nov 18, 2010 6:23 pm

Clear buffer for clearing what? Providing a chunk of workspace for the routine?
Simon Sunnyboy/Paradize - http://paradize.atari.org/

Stay cool, stay Atari!

1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee

User avatar
Zorro 2
Administrator
Administrator
Posts: 2209
Joined: Tue May 21, 2002 12:44 pm
Location: Saint Cloud (France)
Contact:

Re: Line routines

Postby Zorro 2 » Thu Nov 18, 2010 8:58 pm

In fact, this is the buffer who contains the adress of the coordonate of the points(x1,y1,x2,y2) on the physic screen.

But the technic used "two buffers" in one : one for old coordonate to clear (INPUT=A3 ADRESS) and an another to display new coordonate (OUTPUT=A3 ADRESS).

This technic allows you to delete only the points display on the screen. And you don't need to clear all the part of the screen :mrgreen:

Voila !
Member of NoExtra Team

User avatar
simonsunnyboy
Moderator
Moderator
Posts: 5121
Joined: Wed Oct 23, 2002 4:36 pm
Location: Friedrichshafen, Germany
Contact:

Re: Line routines

Postby simonsunnyboy » Fri Nov 19, 2010 4:53 pm

I still don't get it :( I think it shall draw a line not delete pixels?
Simon Sunnyboy/Paradize - http://paradize.atari.org/

Stay cool, stay Atari!

1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee

User avatar
earx
Captain Atari
Captain Atari
Posts: 353
Joined: Wed Aug 27, 2003 7:09 am

Re: Line routines

Postby earx » Thu Jan 20, 2011 4:56 pm

ssb: it's useful to clear the line you painted on the screen previously (i.e. "background restoral"). if there aren't too many line pixels being painted it's actually faster than clearing the entire screen. i do this in the dotlines screen in the "Meikever" (June bug) demo.

User avatar
simonsunnyboy
Moderator
Moderator
Posts: 5121
Joined: Wed Oct 23, 2002 4:36 pm
Location: Friedrichshafen, Germany
Contact:

Re: Line routines

Postby simonsunnyboy » Thu Jan 20, 2011 5:31 pm

I think someone already said that it was for clearing later. Thanks for repeating this information as this information got lost in the recent downtime!
Simon Sunnyboy/Paradize - http://paradize.atari.org/

Stay cool, stay Atari!

1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee


Social Media

     

Return to “680x0”

Who is online

Users browsing this forum: No registered users and 2 guests