math.inc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. {$ifdef NDS_INTERFACE}
  2. // Math coprocessor register definitions
  3. const
  4. REG_DIVCNT : pcuint16 = pointer($04000280);
  5. REG_DIV_NUMER : pcint64 = pointer($04000290);
  6. REG_DIV_NUMER_L : pcint32 = pointer($04000290);
  7. REG_DIV_NUMER_H : pcint32 = pointer($04000294);
  8. REG_DIV_DENOM : pcint64 = pointer($04000298);
  9. REG_DIV_DENOM_L : pcint32 = pointer($04000298);
  10. REG_DIV_DENOM_H : pcint32 = pointer($0400029C);
  11. REG_DIV_RESULT : pcint64 = pointer($040002A0);
  12. REG_DIV_RESULT_L : pcint32 = pointer($040002A0);
  13. REG_DIV_RESULT_H : pcint32 = pointer($040002A4);
  14. REG_DIVREM_RESULT : pcint64 = pointer($040002A8);
  15. REG_DIVREM_RESULT_L : pcint32 = pointer($040002A8);
  16. REG_DIVREM_RESULT_H : pcint32 = pointer($040002AC);
  17. REG_SQRTCNT : pcuint16 = pointer($040002B0);
  18. REG_SQRT_PARAM : pcint64 = pointer($040002B8);
  19. REG_SQRT_PARAM_L : pcint32 = pointer($040002B8);
  20. REG_SQRT_PARAM_H : pcint32 = pointer($040002BC);
  21. REG_SQRT_RESULT : pcuint32 = pointer($040002B4);
  22. // Math coprocessor modes
  23. DIV_64_64 = 2;
  24. DIV_64_32 = 1;
  25. DIV_32_32 = 0;
  26. DIV_BUSY = (1 shl 15);
  27. SQRT_64 = 1;
  28. SQRT_32 = 0;
  29. SQRT_BUSY = (1 shl 15);
  30. function inttof32(n: cint): cint32; inline;
  31. function f32toint(n: cint32): cint; inline;
  32. function floattof32(n: cfloat): cint32; inline; //inlining it makes impossible to pass it to another function :/
  33. function f32tofloat(n: cint32): cfloat; inline;
  34. function divf32(num: cint32; den: cint32): cint32; inline;
  35. function mulf32(a, b: cint32): cint32; inline;
  36. function sqrtf32(a: cint32): cint32; inline;
  37. function div32(num, den: cint32): cint32; inline;
  38. function mod32(num, den: cint32): cint32; inline;
  39. function div64(num: cint64; den: cint32): cint32; inline;
  40. function mod64(num: cint64; den: cint32): cint32; inline;
  41. function sqrt32(a: cint32): cuint32; inline;
  42. function sqrt64(a: cint64): cuint32; inline;
  43. procedure crossf32(a: pcint32; b: pcint32; res: pcint32); inline;
  44. function dotf32(a, b: pcint32): cint32; inline;
  45. procedure normalizef32(a: pcint32); inline;
  46. {$endif NDS_INTERFACE}
  47. {$ifdef NDS_IMPLEMENTATION}
  48. function inttof32(n: cint): cint32; inline;
  49. begin
  50. inttof32 := ((n) shl 12);
  51. end;
  52. function f32toint(n: cint32): cint; inline;
  53. begin
  54. f32toint := ((n) shr 12);
  55. end;
  56. function floattof32(n: cfloat): cint32; inline;
  57. begin
  58. floattof32 := trunc((n) * (1 shl 12));
  59. end;
  60. // check it!
  61. function f32tofloat(n: cint32): cfloat; inline;
  62. begin
  63. f32tofloat := cfloat(n * 1.0) / cfloat((1 shl 12) * 1.0);
  64. end;
  65. function divf32(num: cint32; den: cint32): cint32; inline;
  66. begin
  67. REG_DIVCNT^ := DIV_64_32;
  68. while (REG_DIVCNT^ and DIV_BUSY) <> 0 do;
  69. REG_DIV_NUMER^ := cint64(num) shl 12;
  70. REG_DIV_DENOM_L^ := den;
  71. while (REG_DIVCNT^ and DIV_BUSY) <> 0 do;
  72. divf32 := REG_DIV_RESULT_L^;
  73. end;
  74. function mulf32(a, b: cint32): cint32; inline;
  75. var
  76. rslt: clonglong;
  77. begin
  78. rslt := clonglong(a) * clonglong(b);
  79. mulf32 := cint32(rslt shr 12);
  80. end;
  81. // Fixed point square root
  82. // Takes 1.19.12 fixed point value and
  83. // returns the fixed point result
  84. function sqrtf32(a: cint32): cint32; inline;
  85. begin
  86. REG_SQRTCNT^ := SQRT_64;
  87. while (REG_SQRTCNT^ and SQRT_BUSY) <> 0 do;
  88. REG_SQRT_PARAM^ := cint64(a) shl 12;
  89. while (REG_SQRTCNT^ and SQRT_BUSY) <> 0 do;
  90. sqrtf32 := REG_SQRT_RESULT^;
  91. end;
  92. // Integer versions
  93. // Integer divide
  94. // Takes a 32 bit numerator and 32 bit
  95. // denominator and returns 32 bit result
  96. function div32(num, den: cint32): cint32; inline;
  97. begin
  98. REG_DIVCNT^ := DIV_32_32;
  99. while (REG_DIVCNT^ and DIV_BUSY) <> 0 do;
  100. REG_DIV_NUMER_L^ := num;
  101. REG_DIV_DENOM_L^ := den;
  102. while (REG_DIVCNT^ and DIV_BUSY) <> 0 do;
  103. div32 := REG_DIV_RESULT_L^;
  104. end;
  105. // Integer divide
  106. // Takes a 32 bit numerator and 32 bit
  107. // denominator and returns 32 bit result
  108. function mod32(num, den: cint32): cint32; inline;
  109. begin
  110. REG_DIVCNT^ := DIV_32_32;
  111. while (REG_DIVCNT^ and DIV_BUSY) <> 0 do;
  112. REG_DIV_NUMER_L^ := num;
  113. REG_DIV_DENOM_L^ := den;
  114. while (REG_DIVCNT^ and DIV_BUSY) <> 0 do;
  115. mod32 := REG_DIVREM_RESULT_L^;
  116. end;
  117. // Integer divide
  118. // Takes a 64 bit numerator and 32 bit
  119. // denominator are returns 32 bit result
  120. function div64(num: cint64; den: cint32): cint32; inline;
  121. begin
  122. REG_DIVCNT^ := DIV_64_32;
  123. while (REG_DIVCNT^ and DIV_BUSY) <> 0 do;
  124. REG_DIV_NUMER^ := num;
  125. REG_DIV_DENOM_L^ := den;
  126. while (REG_DIVCNT^ and DIV_BUSY) <> 0 do;
  127. div64 := REG_DIV_RESULT_L^;
  128. end;
  129. // Integer divide
  130. // Takes a 64 bit numerator and 32 bit
  131. // denominator are returns 32 bit result
  132. function mod64(num: cint64; den: cint32): cint32; inline;
  133. begin
  134. REG_DIVCNT^ := DIV_64_32;
  135. while (REG_DIVCNT^ and DIV_BUSY) <> 0 do;
  136. REG_DIV_NUMER^ := num;
  137. REG_DIV_DENOM_L^ := den;
  138. while (REG_DIVCNT^ and DIV_BUSY) <> 0 do;
  139. mod64 := REG_DIVREM_RESULT_L^;
  140. end;
  141. // Integer square root
  142. // takes a 32 bit integer and returns
  143. // 32 bit result
  144. function sqrt32(a: cint32): cuint32; inline;
  145. begin
  146. REG_SQRTCNT^ := SQRT_32;
  147. while(REG_SQRTCNT^ and SQRT_BUSY) <> 0 do;
  148. REG_SQRT_PARAM_L^ := a;
  149. while(REG_SQRTCNT^ and SQRT_BUSY) <> 0 do;
  150. sqrt32 := REG_SQRT_RESULT^;
  151. end;
  152. function sqrt64(a: cint64): cuint32; inline;
  153. begin
  154. REG_SQRTCNT^ := SQRT_64;
  155. while(REG_SQRTCNT^ and SQRT_BUSY) <> 0 do;
  156. REG_SQRT_PARAM^ := a;
  157. while(REG_SQRTCNT^ and SQRT_BUSY) <> 0 do;
  158. sqrt64 := REG_SQRT_RESULT^;
  159. end;
  160. procedure crossf32(a: pcint32; b: pcint32; res: pcint32); inline;
  161. begin
  162. res[0] := mulf32(a[1], b[2]) - mulf32(b[1], a[2]);
  163. res[1] := mulf32(a[2], b[0]) - mulf32(b[2], a[0]);
  164. res[2] := mulf32(a[0], b[1]) - mulf32(b[0], a[1]);
  165. end;
  166. function dotf32(a, b: pcint32): cint32; inline;
  167. begin
  168. dotf32 := mulf32(a[0], b[0]) + mulf32(a[1], b[1]) + mulf32(a[2], b[2]);
  169. end;
  170. procedure normalizef32(a: pcint32); inline;
  171. var
  172. magnitude: cint32;
  173. begin
  174. magnitude := sqrtf32( mulf32(a[0], a[0]) + mulf32(a[1], a[1]) + mulf32(a[2], a[2]) );
  175. a[0] := divf32(a[0], magnitude);
  176. a[1] := divf32(a[1], magnitude);
  177. a[2] := divf32(a[2], magnitude);
  178. end;
  179. {$endif NDS_IMPLEMENTATION}