chickendude wrote:

lirtosiast: I believe your routine should work for unsigned numbers as is as well.

You mean signed numbers?
As I mentionned before, I'm adapting my own rectangle routine (written for Sprite project v3.2) because I'd like to propose it to the C libraries.

Here's the source:


Code:
_FillRectangle_NoClip:
 Draws an unclipped rectangle with the global color index
 Arguments:
  arg0 : X Coord
  arg1 : Y Coord
  arg2 : Width
  arg3 : Height
 Returns:
  None
       
        ld      iy,0
        add     iy,sp
        ld      a,(iy+12)               ; height
        or      a
        ret     z
        ld      bc,(iy+9)               ; width
        sbc     hl,hl
        adc     hl,bc
        ret     z 
        ld      hl,(iy+3)                       ; hl = x coordinate
        ld      e,(iy+6)                        ; e = y coordinate
_FillRectangle_NoClip_ASM:
        ld      d,lcdWidth/2
        mlt     de
        add     hl,de
        add     hl,de
        ld      de,(currDrawBuffer)
        add     hl,de
        ex      de,hl
        push    de
        ld      (_RectangleWidth1_SMC),bc \.r
        ld      (_RectangleWidth2_SMC),bc \.r
        ld      hl,color1
        ldi                                     ; check if we only need to draw 1 pixel
        pop     hl
        jp      po,_Rectangle_NoClip_Skip \.r
        ldir
_Rectangle_NoClip_Skip:       
        dec     a
        ret     z
        inc     b
        ld      c,$40                  ; = fast "ld bc,lcdWidth"
_Rectangle_Loop_NoClip:
        add     hl,bc
        dec     de
        ex      de,hl
_RectangleWidth1_SMC =$+1       
        ld      bc,0
        lddr
        dec     a
        ret     z
        ld      bc,2*lcdWidth+1
        add     hl,bc
        inc     de
        ex      de,hl
_RectangleWidth2_SMC =$+1       
        ld      bc,0
        ldir
        ld      bc,2*lcdWidth-1
        dec     a
        jr      nz,_Rectangle_Loop_NoClip
        ret

;-------------------------------------------------------------------------------
;_FillRectangle_NoClip:
; Draws an unclipped rectangle with the global color index
; Arguments:
;  arg0 : X Coord
;  arg1 : Y Coord
;  arg2 : Width
;  arg3 : Height
; Returns:
;  None
;       
;        ld      iy,0
;        add     iy,sp
;        ld      bc,(iy+9)                       ; bc = width
;        sbc     hl,hl
;        adc     hl,bc
;        ret     z                               ; make sure width is not 0
;        ld      a,(iy+12)                       ; a = height
;        or      a,a
;        ret     z                               ; make sure height is not 0
;        ld      hl,(iy+3)                       ; hl = x coordinate
;        ld      e,(iy+6)                        ; e = y coordinate
;_FillRectangle_NoClip_ASM:
;        ld      d,lcdWidth/2
;        mlt     de
;        add     hl,de
;        add     hl,de
;        ld      iy,(currDrawBuffer)
;        ex      de,hl                           ; de -> place to begin drawing
;        ld      (_RectangleWidth_SMC),bc \.r
;_Rectangle_Loop_NoClip:
;        add     iy,de
;        lea     de,iy
;_RectangleWidth_SMC =$+1
;        ld      bc,0
;        ld      hl,color1 \.r
;        ldi                                     ; check if we only need to draw 1 pixel
;        jp      po,_Rectangle_NoClip_Skip \.r
;        scf
;        sbc     hl,hl
;        add     hl,de
;        ldir                                    ; draw the current line
;_Rectangle_NoClip_Skip:
;        ld      de,lcdWidth                     ; move to next line
;        dec     a
;        jr      nz,_Rectangle_Loop_NoClip
;        ret
;----------------------------------------------------------------------       


EDIT: here's my final version
I might as well copy/paste Runer's comments from #ez80-dev if he didn't notice the post:
Quote:
[7:46pm] Runer112: I'm confused
[7:46pm] Runer112: why would you include constants in magic number form
[7:47pm] Runer112: but then comment them anyways with their semantic value


But anyway, you should make a PR to replace the existing graphx routine Smile
(and also time it to compare, for instance, how long it takes for 1000 rectangles with graphx and yours)
Before my Pull Request, I have to manage this jump inside the routine
_FillRectangle_NoClip_ASM:
my version needs to allow that...

And concerning comparisons, I'll ask you , Adriweb Wink
Well, I can try comparing things, but give me some 8xp Razz
(or some C code to call the function)
The test of 1000 whole-screen-rectangles takes now 13 seconds !.. (instead of 13.5 seconds)
Here is a fast and accurate arctan routine. It only works on the range [0,1), but it is easy enough to extend the range to any input. It's only good to approximately 8 bits, though.

Input is in E, output is H=256*atan(E/256). For example, E=177 returns H=154. In reality, 256*atan(177/256)=154.8633...

Code:

atan8:
;returns H=256*arctan(E/256)
;48cc if ADL mode
;takes 164cc to call this on the TI-84+CE
  ld c,201
  ld b,e
  mlt bc    ;x*201
  xor a
  sub e
  ld d,a
  mlt de    ;x(256-x)
  ld l,e
  ld h,70
  ld e,h
  mlt de  ;upper bytes
  mlt hl  ;lower bytes
  ld a,e
  add a,h
  ld l,a
  ld h,d
  jr nc,$+3
  inc h
  add hl,bc
  ret
I have something that might be of interest.
It's a fast approximation of the square root of a 24 bit number (either from the stack or from DE) (~300-600 clock cycles, including wait states)

Code:

section .text
; Approximates the square root of a number
; floor(2^(floor((floor(log2(x))+1)/2)-1) + (x)/(2^(floor((floor(log2(x))+1)/2)+1)))
; Generally within +6.07% -2% of the real answer
; Inputs:
; sp + [3,5] : Number to take the square root of
; Outputs:
; HL: Square root
; Destroys:
; A, B, DE, F
public _approx_sqrt_a
_approx_sqrt_a:
    ; Set hl to 3
    ld hl, 3
    add hl, sp
    ld de, (hl)
    sbc hl, sp
    sbc hl, de
    ex de, hl
    ; If the number is greater than 3, move on
    jr c, threeCont
    ; Else, if the number is 1 or 0, return HL
    bit 1, l
    ret z
    ; Else, return HL - 1
    dec hl
    ret
; Inputs:
; DE : Number to take the square root of
; Outputs:
; HL: Square root
; Destroys:
; A, B, DE, F
public approx_sqrt_a
approx_sqrt_a:
    ld hl, 3
    or a, a
    sbc hl, de
    ex de, hl
    ; If the number is greater than 3, move on
    jr c, threeCont
    ; Else, if the number is 1 or 0, return HL
    bit 1, l
    ret z
    ; Else, return HL - 1
    dec hl
    ret
threeCont:
    ; Just to be safe
    di
    ; Save the original number for later
    push hl
    ; Count the number of bits
    ; ((x+1)/2)
    ld b, 12
    add hl, hl
    jr c, count_bits_cont
    dec b
    add hl, hl
    jr c, count_bits_cont
    add hl, hl
    jr c, count_bits_cont
    dec b
    add hl, hl
    jr c, count_bits_cont
    add hl, hl
    jr c, count_bits_cont
    dec b
    add hl, hl
    jr c, count_bits_cont
    add hl, hl
    jr c, count_bits_cont
    dec b
    add hl, hl
    jr c, count_bits_cont
    add hl, hl
    jr c, count_bits_cont
    dec b
    add hl, hl
    jr c, count_bits_cont
    add hl, hl
    jr c, count_bits_cont
    dec b
    add hl, hl
    jr c, count_bits_cont
    add hl, hl
    jr c, count_bits_cont
    dec b
    add hl, hl
    jr c, count_bits_cont
    add hl, hl
    jr c, count_bits_cont
    dec b
    add hl, hl
    jr c, count_bits_cont
    add hl, hl
    jr c, count_bits_cont
    dec b
    add hl, hl
    jr c, count_bits_cont
    add hl, hl
    jr c, count_bits_cont
    dec b
    add hl, hl
    jr c, count_bits_cont
    add hl, hl
    jr c, count_bits_cont
    dec b
    count_bits_cont:
    ; generate our guess
    ld a, b
    sub a, 9
    ; If the log is less than 9 (true log is less than 18), continue
    jr c, log_less_than_8
        ; Else, shift the number right by 8 and the guess left by 8
        ld b, a
        inc sp
        pop de
        dec sp
        ld a, e
        ld hl, 256
        jr nz, shift_guess
        srl d
        rra
        srl d
        rra
        ld e, a
       
        ; add the guess and the shifted original number together
        add.s hl, de
        ei
        ret
    log_less_than_8:
    pop de
    ; Because the carry flag is always set by the time we get here, this gives -1
    sbc hl, hl
    add hl, sp
    ; Shift the guess left by 1 to start
    ld a, e
    srl (hl)
    rr d
    rra
    ; Start our guess at 2
    ld hl, 2
    dec b
    ; If the log is 1, return
    ret z
    dec b
    jr z, guess_cont
    ; 1 << b
    ; (2^b)
    shift_guess:
    ; Shift our guess left and the original number right
    add hl, hl
    srl d
    rra
    dec b
    jr z, guess_cont
    add hl, hl
    srl d
    rra
    dec b
    jr z, guess_cont
    add hl, hl
    srl d
    rra
    dec b
    jr z, guess_cont
    add hl, hl
    srl d
    rra
    dec b
    jr z, guess_cont
    add hl, hl
    srl d
    rra
    dec b
    jr z, guess_cont
    add hl, hl
    srl d
    rra
    guess_cont:
    ; Shift the original number right 2 final times
    srl d
    rra
    srl d
    rra
    ld e, a
    ; add the guess and the shifted original number together
    add.s hl, de
    ei
    ret

By the way, the add.s hl,de instructions are completely unnecessary, they can just be add hl, de instructions. I only used add.s to make sure HLU gets cleared, but if you don't need HLU to be cleared then you can just use add hl, de.
May I make a suggestion? Maybe a line routine that is more crude but faster than the built in gxf_Line()? I could probably do something myself in C, but just that would probably cancel out any performance benefits. Thanks! Very Happy
  
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 2 of 2
» 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