Advertisement
NovaYoshi

math.s

Nov 23rd, 2014
310
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ;
  2. ; math.s
  3. ; Arithmetic and trigonometry routines for Thwaite
  4. ;
  5. ; Copyright (c) 2011 Damian Yerrick
  6. ;
  7. ; Copying and distribution of this file, with or without
  8. ; modification, are permitted in any medium without royalty provided
  9. ; the copyright notice and this notice are preserved in all source
  10. ; code copies.  This file is offered as-is, without any warranty.
  11. ;
  12.  
  13. ;
  14. ; The NES CPU has no FPU, nor does it have a multiplier or divider
  15. ; for integer math.  So we have to implement these in software.
  16. ; Here are subroutines to compute 8x8=16-bit product, a fractional
  17. ; quotient in 0.8 fixed point, 2-argument arctangent, and rectangular
  18. ; to polar coordinate conversion.  Also included are lookup tables of
  19. ; sine and cosine for angles expressed in units of 1/32 of a turn
  20. ; from due right, where cos(0) = cos(32) = sin(8) = 1.0.
  21. ;
  22. ; Further information:
  23. ; http://en.wikipedia.org/wiki/Fixed-point_arithmetic
  24. ; http://en.wikipedia.org/wiki/Binary_multiplier
  25. ; http://en.wikipedia.org/wiki/Boxing_the_compass
  26. ; http://en.wikipedia.org/wiki/Binary_scaling#Binary_angles
  27. ;
  28.  
  29. .segment "CODE"
  30.  
  31. ;;
  32. ; Multiplies two 8-bit factors to produce a 16-bit product
  33. ; in about 153 cycles.
  34. ; @param A one factor
  35. ; @param Y another factor
  36. ; @return high 8 bits in A; low 8 bits in $0000
  37. ;         Y and $0001 are trashed; X is untouched
  38. .proc mul8
  39. factor2 = TempVal+1
  40. prodlo = TempVal
  41.  
  42.   ; Factor 1 is stored in the lower bits of prodlo; the low byte of
  43.   ; the product is stored in the upper bits.
  44.   lsr a  ; prime the carry bit for the loop
  45.   sta prodlo
  46.   sty factor2
  47.   lda #0
  48.   ldy #8
  49. loop:
  50.   ; At the start of the loop, one bit of prodlo has already been
  51.   ; shifted out into the carry.
  52.   bcc noadd
  53.   clc
  54.   adc factor2
  55. noadd:
  56.   ror a
  57.   ror prodlo  ; pull another bit out for the next iteration
  58.   dey         ; inc/dec don't modify carry; only shifts and adds do
  59.   bne loop
  60.   ldy TempVal
  61.   rts
  62. .endproc
  63.  
  64. ;;
  65. ; Computes 256*a/y.  Useful for finding slopes.
  66. ; 0 and 1 are trashed.
  67. .proc getSlope1
  68. quotient = 0
  69. divisor = 1
  70.  
  71.   sty divisor
  72.   ldy #1  ; when this gets ROL'd eight times, the loop ends
  73.   sty quotient
  74. loop:
  75.   asl a
  76.   bcs alreadyGreater
  77.   cmp divisor
  78.   bcc nosub
  79. alreadyGreater:
  80.   sbc divisor
  81.   sec  ; without this, results using alreadyGreater are wrong
  82.        ; thx to http://6502org.wikidot.com/software-math-intdiv
  83.        ; for helping solve this
  84. nosub:
  85.   rol quotient
  86.   bcc loop
  87.   lda quotient
  88.   rts
  89. .endproc
  90.  
  91. ;;
  92. ; Find the angle of a vector pointing from (x1, y1) to (x2, y2),
  93. ; all coordinates unsigned.
  94. ; This is also called arctan2 or (on TI calculators) "R>Ptheta".
  95. ; @param 0 x1
  96. ; @param 1 y1
  97. ; @param 2 x2
  98. ; @param 3 y2
  99. ; @return A: angle (0-31);
  100. ;         0: slope reflected into first octant;
  101. ;         1: angle reflected into first octant;
  102. ;         2, 3: point reflected into first octant
  103. ;         Trashes Y and nothing else.
  104. .proc getAngle
  105. x1 = 0
  106. y1 = 1
  107. x2 = 2
  108. y2 = 3
  109. flags = 4
  110.  
  111.   lda y2
  112.   cmp y1
  113.   bne notHorizontal
  114.   lda x2
  115.   cmp x1
  116.   lda #0
  117.   sta 1
  118.   bcs :+
  119.   lda #16
  120. : rts
  121.  
  122. notHorizontal:
  123.   ; make sure x2 > x1
  124.   lda x2
  125.   cmp x1
  126.   bne notVertical
  127.   lda y2
  128.   cmp y1
  129.   lda #$FF
  130.   sta 3
  131.   lda #0  ; store first-octant angle
  132.   sta 1
  133.   lda #24
  134.   bcc :+
  135.   lda #8
  136. : rts
  137. notVertical:
  138.  
  139.   ; At this point, we have already eliminated the special cases of a
  140.   ; perfectly horizontal or vertical ray.
  141.   ; So now compute the sign and abs of (y2 - y1)
  142.   sec
  143.   lda y2
  144.   sbc y1
  145.   bcs noVerticalFlip
  146.   eor #$FF
  147.   adc #1
  148. noVerticalFlip:
  149.   sta y1
  150.  
  151.   lda #0
  152.   rol a
  153.   sta flags  ; flag 2: SKIP y flip (angle = 16 - angle)
  154.  
  155.   ; Compute the sign and abs of (x2 - x1)
  156.   sec
  157.   lda x2
  158.   sbc x1
  159.   bcs noHorizontalFlip
  160.   eor #$FF
  161.   adc #1
  162. noHorizontalFlip:
  163.   sta x1
  164.   rol flags  ; flag 1: SKIP x flip (angle = 8 - angle)
  165.  
  166.   ; if x1 > y1 then swap x1 and y1
  167.   lda y1
  168.   cmp x1
  169.   bcc noDiagonalFlip
  170.   ldy x1
  171.   sty y1
  172.   sta x1
  173. noDiagonalFlip:
  174.   rol flags  ; flag 0: PERFORM diagonal flip (angle = 4 - angle)
  175.  
  176.   lda y1
  177.   sta y2
  178.   ldy x1
  179.   sty x2
  180.   jsr getSlope1
  181.   sta x1
  182.  
  183.   ldy #4
  184. tansearch:
  185.   cmp tantable-1,y
  186.   bcs foundTan
  187.   dey
  188.   bne tansearch
  189. foundTan:
  190.   tya
  191.   sta y1
  192.  
  193.   lsr flags
  194.   bcc noUndoDiagonal
  195.   eor #$FF  ; reverse-subtract 8
  196.   adc #8
  197. noUndoDiagonal:
  198.  
  199.   lsr flags
  200.   bcs noUndoHorizontal
  201.   eor #$FF  ; reverse-subtract 16
  202.   adc #17   ; plus one because we came in with clc
  203. noUndoHorizontal:
  204.  
  205.   lsr flags
  206.   bcs noUndoVertical
  207.   eor #$FF  ; reverse-subtract 32
  208.   adc #33   ; plus one because we came in with clc
  209. noUndoVertical:
  210.  
  211.   cmp #32   ; fixes a bug where it tries to get a value past the end of the table
  212.   bcc :+
  213.   lda #0
  214. : rts
  215. .endproc
  216.  
  217. ; Tangents of angles between the ordinary angles, used by getAngle.
  218. ; you can make trig tables even in windows calculator
  219. ; (90/16*1)t*256= 25
  220. tantable:
  221.   .byt 25, 78, 137, 210
  222.  
  223. ; Accurate sin/cos table used by measureFromSilo.
  224. ; These are indexed by angle in quadrant 1, and scaled by 256.
  225. ; (90*7/8)s*256=
  226. sine256Q1:
  227.   .byt 0, 50, 98, 142, 181, 213, 237, 251
  228. cosine256Q1:
  229.   .byt  0, 251, 237, 213, 181, 142, 98, 50
  230.  
  231. ; Less precise sin/cos table used by e.g. missile smoke generation.
  232. ; These are indexed by angle through the whole circle
  233. ; and scaled by 64.
  234. ; (90*7/8)s*64=
  235. SineTable:
  236.   .byt   0, 12, 24, 36, 45, 53, 59, 63
  237. CosineTable:
  238.   .byt  64, 63, 59, 53, 45, 36, 24, 12
  239.   .byt   0,-12,-24,-36,-45,-53,-59,-63
  240.   .byt -64,-63,-59,-53,-45,-36,-24,-12
  241.   .byt   0, 12, 24, 36, 45, 53, 59, 63
  242.  
  243. .macro neg16 val
  244.   sec             ;Ensure carry is set
  245.   lda #0          ;Load constant zero
  246.   sbc val+0       ;... subtract the least significant byte
  247.   sta val+0       ;... and store the result
  248.   lda #0          ;Load constant zero again
  249.   sbc val+1       ;... subtract the most significant byte
  250.   sta val+1       ;... and store the result
  251. .endmacro
  252.  
  253. ; added stuff
  254. .proc SpeedAngle2Offset ; A = speed, Y = angle -> 0,1(X) 2,3(Y)
  255. Angle = 4
  256. Speed = 5
  257.   sty Angle
  258.   sta Speed
  259.  
  260.   lda CosineTable,y
  261.   php
  262.   bpl :+
  263.   eor #255
  264.   add #1
  265. : ldy Speed
  266.   jsr mul8
  267.   sty 0
  268.   sta 1
  269.  
  270.   plp
  271.   bpl :+
  272.   neg16 0
  273. :
  274.  
  275.   ldy Angle
  276.   lda SineTable,y
  277.   php
  278.   bpl :+
  279.   eor #255
  280.   add #1
  281. : ldy Speed
  282.   jsr mul8
  283.   sty 2
  284.   sta 3
  285.   plp
  286.   bpl :+
  287.   neg16 2
  288. :
  289.   rts
  290. .endproc
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement