In a program I'm making [name must not be mentioned], I need to be able to draw lines fast. I could make my own routine to do this, but this program is for Mirage so I figure I will just use either the Mirage line routine or the Ion line routine. After searching for a while through routines called fastlinex, fastlinew etc, I came across what appears to me to be the correct one for my purposes: fastline. The only problem is that am having trouble determining what the inputs are. I have searched high and low for a program that uses fastline, and I did finally find one, but it must use some inputs that I don't understand how to use becuase simply putting X1,Y1 in hl and X2,Y2 in de produced nothing when I tried. Here's the code for the program that I found:


Code:
.nolist
 #include "ti83plus.inc"
 #include "mirage.inc"
.list
  .org $9d93        ;Origin
  .db $BB,$6D             ;Compiled AsmPrgm token
  ret                     ;Header Byte 1 -- So TIOS wont run
  .db 1                  ;Header Byte 2 -- Identifies as MirageOS prog
button:                       ;Button - should be a 15x15 graphic
.db %00000000,%00000000
.db %00000001,%00000000
.db %00000001,%00000000
.db %01010000,%10000000
.db %01001000,%10000000
.db %01000100,%01000000
.db %01000010,%01000000
.db %01000001,%00000000
.db %00100000,%10000000
.db %00100000,%01000000
.db %00100000,%00100000
.db %00100000,%00010000
.db %00101111,%10000000
.db %00000000,%00000000
.db %00000000,%00000000
.db %00000000,%00000000
.db %00000000,%00000000
progstart:
   ld b,95
   call   irandom      ;X1
   ld h,a
   ld b,63
   call   irandom      ;Y1
   ld l,a
   ld b,95
   call   irandom      ;X2
   ld d,a
   ld b,63
   call   irandom      ;Y2
   ld e,a
   ld b,255
   call   irandom      ;Pattern if 3 chosen below
   ld (mlinebitmap),a
   ld a,(userpattern)
   ld b,0
   cp 0
   jr z,dozero
   cp 1
   jr z,doone
   cp 2
   jr z,dotwo
   cp 3
   jr z,dothree
   ld b,4
   call   irandom      ;Pattern
merge:
   call   fastline
   call   ifastcopy
   ld b,100
lbl:
   ei
   halt
   bcall(_getCSC)
   cp $F
   ld c,0
   jr z,scnclr
   cp $38
   ret z
   cp $21
   jr z,userzero
   cp $22
   jr z,userone
   cp $1A
   jr z,usertwo
   cp $12
   jr z,userthree
   cp $23
   jr z,userfour
   djnz lbl
   jr progstart
scnclr:
   bcall(_GrBufClr)
   jr progstart
userfour:
   inc c
userthree:
   inc c
usertwo:
   inc c
userone:
   inc c
userzero:
   ld a,c
   ld (userpattern),a
   jr progstart
dothree:
   inc b
dotwo:
   inc b
doone:
   inc b
dozero:
   ld a,b
   jr merge
userpattern:
   .db $04
.end


It appears that a and b have some sort of input as well in the routine, but I don't understand exactly what it wants. All I want is a solid line from a given (x,y) to a second (x,y). I searched through both the mirage documentation (which is very very scarce) and the ion documentation (all that I could find of it), but I found nothing.


Does anyone know the inputs for a fastline routine in either Mirage or Ion? Kerm, I know you must; you did after all, re-write the ion libs. Wink
Just a note to anyone, this question has already been answered on the Detached Solutions forum. See here
Yea, thanks. It turned out to be a case of me not reading the manual thoroughly enough. I'm still not quite sure how I missed it before. Well, it's all good now. Smile
That's one of the routines I'll be remaking for DCS. Very Happy
Chipmaster wrote:
Yea, thanks. It turned out to be a case of me not reading the manual thoroughly enough. I'm still not quite sure how I missed it before. Well, it's all good now. Smile


What manual? I didn't know there was a MOS guru. I only have ionGuru Very Happy
There's a text file for the MOS routine reference on DetachedS.
Right you are Kerm. So you will be adding in MOS support? Smile
Here's a clipped line routine for you, courtesy of Timendus.

Code:
; ***
; [routine]draw.clippedLine(%posa,%posb)[/routine]
;
; Draws a line between two points to plotsscreen. This is a clipping routine, which means that coordinates can be off the screen. <i>posa</i> and <i>posb</i> are double bytes with the first byte (MSB) being the x-coord and the second byte (LSB) being the y-coord.
;
; ! Hasn't been tested yet !
;
; Example:
;  Write example
;
; Size:
;  ?? bytes routine + ?? bytes invocation
;
; Depends on:
;  draw.line
;
; Written by:
;  Badja
;

#IFDEF api_defines
#IFNDEF api_routines

   #DEFINE   draw.clippedLine(posa,posb) load(hl,posa)
   #DEFCONT  \ load(de,posb)
   #DEFCONT  \ call api_draw_clippedLine
   #DEFCONT  \ #DEFINE api_use_draw_clippedLine

#ENDIF
#ENDIF

#IFDEF api_routines
#IFDEF api_use_draw_clippedLine

   #DEFINE api_use_draw_line

api_draw_clippedLine:

   ; hl = posa
   ; de = posb

lineClipAndDrawLong:
      ld    a,d               ; compare signs of x0 and x1
      xor   h
      and   $80
      jr    z,lcd_notTooWide  ; if same, line is not too wide
      bit   7,d
      jr    z,lcd_dPositive
      ld    a,d
      neg
      add   a,h
      jr    lcd_checkWidth
lcd_dPositive:
      ld    a,h
      neg
      add   a,d
lcd_checkWidth:               ; A = |x1 - x0|
      and   $80
      jr    nz,lcd_longLine   ; check if width exceeds 128
lcd_notTooWide:
      ld    a,e               ; compare signs of y0 and y1
      xor   l
      and   $80
      jr    z,lineClipAndDraw ; if same, line is not too high
      bit   7,e
      jr    z,lcd_ePositive
      ld    a,e
      neg
      add   a,l
      jr    lcd_checkHeight
lcd_ePositive:
      ld    a,l
      neg
      add   a,e
lcd_checkHeight:              ; A = |y1 - y0|
      and   $80
      jr    z,lineClipAndDraw ; check if height exceeds 128
lcd_longLine:
      push  de                ; line is too long
      push  hl
      call  lcd_bisect        ; bisect line so rest of routine can handle it
      call  lineClipAndDraw   ; draw first half of line
      pop   de
      pop   hl
      call  lcd_bisect        ; bisect again with endpoints swapped, then draw second half
                              ; (second bisection can return a different midpoint - this
                              ; is required in case of lines being 256 pixels wide or high)

lineClipAndDraw:
      call  lcd_compOutCode
      ex    de,hl
      ld    c,b               ; C = ????, outcode0
lcd_subdivide:
      call  lcd_compOutCode   ; B = outcode0, outcode1
      ld    a,b
      or    a                 ; are both outcodes zero?
      jp    z,lineDraw        ; if so, trivial accept and draw line
      ld    a,b
      and   c                 ; is logical AND of outcodes non-zero?
      and   $0f               ; (mask off irrelevant bits)
      ret   nz                ; if so, trivial reject and return
      ld    a,b               ; failed both tests, so clip the line segment...
      and   $0f               ; at least one endpoint is off-screen, is point 1 off-screen?
      jr    nz,lcd_clip       ; if so, pick this one
      ex    de,hl             ; otherwise, the other endpoint must be off-screen, so exchange them
      ld    b,c
      ld    c,a
lcd_clip:
      push  hl
      bit   0,b
      jr    z,lcd_notBottom
      ld    b,63              ; divide line at bottom of screen (y = 63)
      jr    lcd_divideHoriz
lcd_notBottom:
      bit   1,b
      jr    z,lcd_notTop
      ld    b,0               ; divide line at top of screen (y = 0)
lcd_divideHoriz:
      push  bc
      ld    a,h
      sub   d
      ld    h,a               ; H = x1 - x0
      ld    a,d
      jr    z,lcd_vertical    ; if x1 - x0 == 0, then intersection point is x0 == A
      ld    a,l
      sub   e
      ld    c,a               ; C = y1 - y0
      ld    a,b
      sub   e
      ld    l,a               ; L = y - y0
      ld    b,c               ; B = y1 - y0
      ld    c,d               ; C = x0
      call  lcd_divideLine    ; A = x
lcd_vertical:
      pop   bc                ; B = y
      ld    d,a
      ld    e,b               ; DE = intersection point
      jr    lcd_nextPass
lcd_notTop:
      bit   2,b
      ld    b,95              ; divide line at right edge of screen (x = 95)
      jr    nz,lcd_divideVert
      ld    b,0               ; divide line at left edge of screen (x = 0)
lcd_divideVert:
      push  bc
      ld    a,l
      sub   e
      ld    l,a               ; L = y1 - y0
      ld    a,d
      jr    z,lcd_horizontal  ; if y1 - y0 == 0, then intersection point is y0 == A
      ld    a,h
      sub   d
      ld    c,a               ; C = x1 - x0
      ld    a,b
      sub   d
      ld    h,a               ; H = x - x0
      ld    b,c               ; B = x1 - x0
      ld    c,e               ; C = y0
      call  lcd_divideLine    ; A = y
lcd_horizontal:
      pop   bc                ; B = x
      ld    d,b
      ld    e,a               ; DE = intersection point
lcd_nextPass:
      ld    b,c
      pop   hl
      jr    lcd_subdivide     ; repeat process for new line segment

lcd_divideLine:               ; return A = C + H * L / B
      ld    a,h
      xor   l
      xor   b                 ; bit 7 of A = sign of H * L / B
      push  af
      bit   7,h
      jr    z,lcd_positive1
      ld    a,h
      neg
      ld    h,a
lcd_positive1:                ; H = |H|
      bit   7,l
      jr    z,lcd_positive2
      ld    a,l
      neg
      ld    l,a
lcd_positive2:                ; L = |L|
      ld    a,b
      bit   7,a
      jr    z,lcd_positive3
      neg
lcd_positive3:                ; A = |B|
      bcall(_htimesl)         ; HL = H * L
      bcall(_divhlbya)        ; HL = HL / A
      pop   af                ; bit 7 of A = sign of H * L / B
      and   $80               ; mask off irrelevent bits
      ld    a,l               ; A = result of |H| * |L| / |B|
      jr    z,lcd_positive4
      neg                     ; make result negative if necessary
lcd_positive4:
      add   a,c               ; A = C + result
      ret

lcd_compOutCode:              ; left-rotate 4-bit outcode for point DE into B
      ld    a,d
      rla
      jr    c,lcd_negative1   ; if D < 0, then D must be < 96
      rl    b
      ld    a,95
      sub   d
      rla
      jr    lcd_notNegative1
lcd_negative1:
      rl    b
      and   a
lcd_notNegative1:
      rl    b

      ld    a,e
      rla
      jr    c,lcd_negative2   ; if E < 0, then E must be < 64
      rl    b
      ld    a,63
      sub   e
      rla
      jr    lcd_notNegative2
lcd_negative2:
      rl    b
      and   a
lcd_notNegative2:
      rl    b
      ret

lcd_bisect:                   ; set (H, L) to midpoint of (D, E) and (H, L)
      ld    a,d
      sra   a
      jr    nc,lcd_even1
      inc   a                 ; over-compensate for truncation on D only (valid)
lcd_even1:
      sra   h
      add   a,h
      ld    h,a               ; H = D/2 + H/2
      ld    a,e
      sra   a
      jr    nc,lcd_even2
      inc   a                 ; over-compensate for truncation on E only (valid)
lcd_even2:
      sra   l
      add   a,l
      ld    l,a               ; L = E/2 + L/2
      ret

#ENDIF
#ENDIF
Thanks, but I don't need a clipped line routine. I just needed a line routine. I found out how to use it, so I'm all set Smile
I figured as much. Awesomeness.
Wouldn't it be easier to check if the points are on the screen first? Or is the clipped line routine designed to be faster, and allows you to draw lines that are bigger than the actual screen?
Clipped routines at best should be the same speed as its non-clipped version when lines dont need to be clipped, but only a bit slower when it has to clip.
Liazon wrote:
Wouldn't it be easier to check if the points are on the screen first? Or is the clipped line routine designed to be faster, and allows you to draw lines that are bigger than the actual screen?
Clipped routines allow offscreen drawing; thy're useful for things like raycasters (although those use a completely different kind of clipping)
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement