I made a CalcSine that does not use table:
- Code:
; ---------------------------------------------------------------------------
; Subroutine to calculate sine and cosine of an angle
; d0 = input byte = angle (360 degrees == 256)
; d0 = output word = 255 * sine(angle)
; d1 = output word = 255 * cosine(angle)
; ---------------------------------------------------------------------------
; New CalcSine without table, the max diference of original CalcSine
; is + or - 4 in sine or cosine value.
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
CalcSine: ; XREF: SS_BGAnimate; et al
movem.l d2-d5,-(sp) ; save the variables that will be changed in this calculation
andi.w #$FF,d0 ; adapt a angle (alpha > 255) to a angle (alpha < 256)
move.w d0,d5 ; copy the angle, because after loop we need again the angle (to sine)
moveq #1,d4 ; repeat the loop 1 time (to sine)
CalcSine_loop_start:
moveq #0,d3 ; reset the "negate the sine or cosine in end" flag
move.w d5,d0 ; get the angle value (to sine after loop)
cmpi.w #128,d0 ; is the angle in 1st or 2nd quadrant?
blt.s CalcSine_cos_to_sine ; if yes, don't rotate the angle to fix it in 1st or 2nd quadrant
subi.b #128,d0 ; rotate the angle 128º (180º in real world)
add.b #1,d3 ; set to negate the sine or cosine in end of calculation
CalcSine_cos_to_sine:
tst.b d4 ; sine or cosine is being calculated?
beq.s CalcSine_bhaskara ; if is the sine, branch
cmpi.w #64,d0 ; is the angle in 1st quadrant?
blt.s CalcSine_cos_to_sine2 ; if yes, rotate it 64º
subi.b #64,d0 ; if not, rotate it -64º (-90º in real world)
add.b #1,d3 ; add 1 in "negate the sine or cosine in end" flag (if the d3=2, don't negate the result in end)
bra.s CalcSine_bhaskara ; calculate the cosine
CalcSine_cos_to_sine2:
addi.b #64,d0 ; rotate the angle 64º (90º in real world)
CalcSine_bhaskara: ; Sine = 12*Beta/Delta
; Beta = (128-angle)*angle
; Delta = (28800-Beta)/128
move.l #128,d1 ; Beta /// 128
sub.w d0,d1 ; Beta /// 128-angle
muls.w d0,d1 ; Beta /// (128-angle)*angle
move.l #28800,d2 ; Delta /// 28800
sub.w d1,d2 ; Delta /// 28800-Beta
divs.w #128,d2 ; Delta /// (28800-Beta)/128
muls.w #12,d1 ; SINE /// 12*Beta
divs.w d2,d1 ; SINE /// 12*Beta/Delta
cmpi.b #1,d3 ; is d3=1? negate the result?
bne.s CalcSine_save ; if not, don't negate the result
neg d1 ; if d3=1, negate the result
CalcSine_save:
movem.l d1,-(sp) ; save the result in sp
dbf.w d4,CalcSine_loop_start ; if the sine don't was calculated, return and calculate it
movem.l (sp)+,d0-d5 ; load the results (sine to d0 and cosine to d1) and the variables that were modified
rts
; End of function CalcSine