]> git.sur5r.net Git - cc65/blob - libsrc/common/cc65_sin.s
Added fixpoint sine and cosine functions.
[cc65] / libsrc / common / cc65_sin.s
1 ;
2 ; Fixed point sine function.
3 ;
4 ; Returns the cosine for the given argument as angular degree.
5 ; Valid argument range is 0..360
6 ;
7 ;
8 ; Ullrich von Bassewitz, 2009-10-29
9 ;
10
11         .export         _cc65_sin
12
13         .import         _cc65_sintab
14
15
16 ; ---------------------------------------------------------------------------
17 ;
18
19 .code
20
21 .proc   _cc65_sin
22
23 ; If the high byte is non zero, argument is > 255
24
25         cpx     #0
26         bne     L3
27         cmp     #180
28         bcs     L4
29
30 ; 0..179°
31
32         cmp     #90
33         bcc     L1
34
35 ; 90..179°. Value is identical to sin(180-val). Carry is set on entry.
36 ;
37 ;       180-val := -val + 180.
38 ; With
39 ;       -val := (val ^ $FF) + 1
40 ; we get
41 ;       180-val = (val ^ $FF) + 1 + 180
42 ; Since carry is set, we can drop the "+ 1".
43 ;
44
45         eor     #$FF
46         adc     #180            ; 180-val
47
48 ; 0..89°. Values for 87..90° are actually 1.0. Since this format doesn't fit
49 ; into the table, we have to check for it manually.
50
51 L1:     cmp     #87
52         bcc     L2
53
54 ; The value is 1.0
55
56         ldx     #>(1 << 8)
57         lda     #<(1 << 8)
58         rts
59
60 ; 0..86°. Read the value from the table.
61
62 L2:     tay
63         ldx     #0
64         lda     _cc65_sintab,y
65         rts
66
67 ; 180..360°. sin(x) = -sin(x-180). Since the argument is in range 0..180
68 ; after the subtraction, we don't need to handle the high byte.
69
70 L3:     sec
71 L4:     sbc     #180
72
73         cmp     #90
74         bcc     L5
75
76 ; 270..360°. Value is identical to -sin(180-val). Carry is set on entry.
77 ;
78 ;       180-val := -val + 180.
79 ; With
80 ;       -val := (val ^ $FF) + 1
81 ; we get
82 ;       180-val = (val ^ $FF) + 1 + 180
83 ; Since carry is set, we can drop the "+ 1".
84 ;
85
86         eor     #$FF
87         adc     #180            ; 180-val
88
89 ; 180..269°. Values for 267..269° are actually -1.0. Since this format doesn't
90 ; fit into the table, we have to check for it manually.
91
92 L5:     ldx     #$FF
93         cmp     #87
94         bcc     L6
95
96 ; The value is -1.0
97
98         lda     #<(-1 << 8)
99         rts
100
101 ; 180..266°. Read the value from the table. Carry is clear on entry.
102
103 L6:     tay
104         txa                     ; A = $FF
105         eor     _cc65_sintab,y
106         adc     #1
107         bcc     L7
108         inx
109 L7:     rts
110
111 .endproc
112
113