Advertisement
Marrin

pi

Mar 21st, 2014
318
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ;--------------------------------------
  2. ; Approximation of pi by checking points
  3. ; in a grid if they are lying within
  4. ; a quarter of a circle with the radius
  5. ; of the grid's length and calculating
  6. ; the ratio of points in the circle and
  7. ; all points of the grid, known as pi.
  8. ;--------------------------------------
  9.         !to "test.prg", cbm
  10.         !convtab pet
  11.         !sl "test.labels"
  12.  
  13.         ; Radius and length of the grid.
  14.         RADIUS = 3000
  15.         ; 32 bit fixed point value with two bit fraction.
  16.         HIT_ZONE = (RADIUS * RADIUS) << 2
  17.  
  18.         ptr1 = $9e
  19.         ptr2 = $a5
  20.         x = $a7         ; 32 bit fixed point with two bit fractional part.
  21.         hit_count = $b0 ; 24 or 32 bit counter.
  22.         i = $f7         ; 16 bit fixed point with one bit fractional part.
  23.         r16a = $f9
  24.  
  25.         fac1_print = $aabc
  26.  
  27.         * = $0801
  28.  
  29. basic_header
  30.         !word .next_line
  31.         !word 2014      ; BASIC line number.
  32.         !pet "ti$", $b2, 34, "000000", 34, ":" ; Set clock to 00:00:00.
  33.         !byte $9e       ; SYS token.
  34.         !byte "0" + (start / 1000), "0" + ((start / 100) % 10)
  35.         !byte "0" + ((start / 10) % 10), "0" + (start % 10)
  36.         !pet ":", $99, "ti$" ; PRINT clock value.
  37.         !byte 0         ; BASIC line end marker.
  38. .next_line
  39.         !word 0
  40.  
  41. !zone
  42. start:
  43.         jsr calculate_squares
  44.        
  45.         jsr count_hits_on_one_side_of_the_diagonal
  46.  
  47.         asl hit_count   ; hit_count *= 2
  48.         rol hit_count+1
  49.         rol hit_count+2
  50.        
  51.         jsr count_hits_on_the_diagonal
  52.  
  53.         ;
  54.         ; fac1 = 4 * hit_count / int(HIT_ZONE)
  55.         ;
  56.         asl hit_count   ; hit_count *= 4
  57.         rol hit_count+1
  58.         rol hit_count+2
  59.         rol hit_count+3
  60.         asl hit_count
  61.         rol hit_count+1
  62.         rol hit_count+2
  63.         rol hit_count+3
  64.  
  65.         lda hit_count+3 ; fac1 = hit_count
  66.         sta $62
  67.         lda hit_count+2
  68.         sta $63
  69.         lda hit_count+1
  70.         sta $64
  71.         lda hit_count
  72.         sta $65
  73.         sec
  74.         lda #0
  75.         ldx #$a0
  76.         jsr $bc4f
  77.  
  78.         ldx #<.temp_flpt ; .temp_flpt = fac1
  79.         ldy #>.temp_flpt
  80.         jsr $bbd4
  81.  
  82.                         ; fac1 = int(HIT_ZONE)
  83.         lda #(HIT_ZONE >> 2) AND $ff
  84.         ldx #((HIT_ZONE >> 2) >> 8) AND $ff
  85.         ldy #((HIT_ZONE >> 2) >> 16) AND $ff
  86.         jsr $af87
  87.         sec
  88.         lda #0
  89.         ldx #$a0
  90.         jsr $bc4f
  91.  
  92.         lda #<.temp_flpt ; fac1 = .temp_flpt / fac1
  93.         ldy #>.temp_flpt
  94.         jsr $bb0f
  95.  
  96.         jmp fac1_print
  97.  
  98. .temp_flpt
  99.         !fill 5
  100.  
  101. ;--------------------------------------
  102. !align 255, 0, 0
  103. !zone
  104. calculate_squares
  105.         lda #<values    ; ptr1 = &values
  106.         sta ptr1
  107.         lda #>values
  108.         sta ptr1+1
  109.         ldy #1          ; i = 0.5
  110.         sty i
  111.         dey
  112.         sty i+1
  113.  
  114. .loop
  115.         lda i           ; r16a = i
  116.         sta r16a
  117.         lda i+1
  118.         sta r16a+1
  119.  
  120.         lda #0          ; x = i * r16a
  121.         sta x+2
  122.         sta x+3
  123.         ldx #16
  124. -       lsr r16a+1
  125.         ror r16a
  126.         bcc +
  127.         lda x+2
  128.         clc
  129.         adc i
  130.         sta x+2
  131.         lda x+3
  132.         adc i+1
  133. +       ror
  134.         sta x+3
  135.         ror x+2
  136.         ror x+1
  137.         ror x
  138.         dex
  139.         bne -
  140.  
  141.         ldy #0          ; *ptr1 = x
  142.         lda x
  143.         sta (ptr1),y
  144.         iny
  145.         lda x+1
  146.         sta (ptr1),y
  147.         iny
  148.         lda x+2
  149.         sta (ptr1),y
  150.         iny
  151.         lda x+3
  152.         sta (ptr1),y
  153.  
  154.         clc             ; i += 1.0
  155.         lda i
  156.         adc #2
  157.         sta i
  158.         bcc +
  159.         inc i+1
  160. +
  161.         clc             ; ptr1 += 4
  162.         lda ptr1
  163.         adc #4
  164.         sta ptr1
  165.         bcc +
  166.         inc ptr1+1
  167. +
  168.         lda ptr1
  169.         cmp #<(RADIUS * 4 + values)
  170.         bne .loop
  171.         lda ptr1+1
  172.         cmp #>(RADIUS * 4 + values)
  173.         bne .loop
  174.  
  175.         rts
  176.  
  177. ;--------------------------------------
  178. !align 255, 0, 0
  179. !zone
  180. count_hits_on_one_side_of_the_diagonal
  181.         lda #0          ; hit_count = 0
  182.         sta hit_count
  183.         sta hit_count+1
  184.         sta hit_count+2
  185.         sta hit_count+3
  186.        
  187.         lda #<values    ; ptr1 = &values
  188.         sta ptr1
  189.         lda #>values
  190.         sta ptr1+1
  191.  
  192. .outer_loop
  193.         inc $d020
  194.  
  195.         lda ptr1
  196.         sta ptr2
  197.         lda ptr1+1
  198.         sta ptr2+1
  199.         jmp .inner_continue
  200.  
  201. ; Make sure the inner loop is within one page.
  202. !align 255, 0, 0
  203.  
  204. .inner_loop
  205.         clc             ; x = *ptr1 + *ptr2
  206.         ldy #0
  207.         lda (ptr1),y
  208.         adc (ptr2),y
  209.         sta x
  210.         iny
  211.         lda (ptr1),y
  212.         adc (ptr2),y
  213.         sta x+1
  214.         iny
  215.         lda (ptr1),y
  216.         adc (ptr2),y
  217.         sta x+2
  218.         iny
  219.         lda (ptr1),y
  220.         adc (ptr2),y
  221.         ; sta x+3
  222.  
  223.         ; lda x+3
  224.         cmp #(HIT_ZONE >> 24) AND $ff
  225.         bcc +
  226.         bne .skip
  227.         lda x+2
  228.         cmp #(HIT_ZONE >> 16) AND $ff
  229.         bcc +
  230.         bne .skip
  231.         lda x+1
  232.         cmp #(HIT_ZONE >> 8) AND $ff
  233.         bcc +
  234.         bne .skip
  235.         lda x
  236.         cmp #HIT_ZONE AND $ff
  237.         bcs .skip
  238. +
  239.         inc hit_count   ; ... ++hit_count
  240.         bne +
  241.         inc hit_count+1
  242.         bne +
  243.         inc hit_count+2
  244. +
  245. .skip
  246.  
  247. .inner_continue
  248.         clc             ; ptr2 += 4
  249.         lda ptr2
  250.         adc #4
  251.         sta ptr2
  252.         bcc +
  253.         inc ptr2+1
  254. +
  255.         lda ptr2
  256.         cmp #<(RADIUS * 4 + values)
  257.         bne .inner_loop
  258.         lda ptr2+1
  259.         cmp #>(RADIUS * 4 + values)
  260.         bne .inner_loop
  261.  
  262. .outer_continue
  263.         clc             ; ptr1 += 4
  264.         lda ptr1
  265.         adc #4
  266.         sta ptr1
  267.         bcc +
  268.         inc ptr1+1
  269. +
  270.         lda ptr1
  271.         cmp #<(RADIUS * 4 + values)
  272.         bne .to_outer_loop
  273.         lda ptr1+1
  274.         cmp #>(RADIUS * 4 + values)
  275.         beq +
  276. .to_outer_loop
  277.         jmp .outer_loop
  278. +
  279.         rts
  280.  
  281. ;--------------------------------------
  282. !align 255, 0, 0
  283. !zone
  284. count_hits_on_the_diagonal
  285.         lda #<values    ; ptr1 = &values
  286.         sta ptr1
  287.         lda #>values
  288.         sta ptr1+1
  289.  
  290. .loop
  291.         ldy #0          ; x = *ptr1 * 2
  292.         lda (ptr1),y
  293.         asl
  294.         sta x
  295.         iny
  296.         lda (ptr1),y
  297.         rol
  298.         sta x+1
  299.         iny
  300.         lda (ptr1),y
  301.         rol
  302.         sta x+2
  303.         iny
  304.         lda (ptr1),y
  305.         rol
  306.         ; sta x+3
  307.  
  308.         ; lda x+3
  309.         cmp #(HIT_ZONE >> 24) AND $ff
  310.         bcc +
  311.         bne .skip
  312.         lda x+2
  313.         cmp #(HIT_ZONE >> 16) AND $ff
  314.         bcc +
  315.         bne .skip
  316.         lda x+1
  317.         cmp #(HIT_ZONE >> 8) AND $ff
  318.         bcc +
  319.         bne .skip
  320.         lda x
  321.         cmp #HIT_ZONE AND $ff
  322.         bcs .skip
  323. +
  324.         inc hit_count   ; ... ++hit_count
  325.         bne +
  326.         inc hit_count+1
  327.         bne +
  328.         inc hit_count+2
  329. +
  330. .skip
  331.         clc             ; ptr1 += 4
  332.         lda ptr1
  333.         adc #4
  334.         sta ptr1
  335.         bcc +
  336.         inc ptr1+1
  337. +
  338.         lda ptr1+1
  339.         cmp #>(RADIUS * 4 + values)
  340.         bcc .loop
  341.         lda ptr1
  342.         cmp #<(RADIUS * 4 + values)
  343.         bcc .loop
  344.  
  345.         rts
  346.  
  347. ;--------------------------------------
  348. ; Variables:
  349.  
  350. ; Make sure no indexed access to a 32 bit value crosses page boundaries.
  351. !align 4, 0, 0  
  352. ; 32 bit fixed point values with 2 bits fractional part.
  353. values
  354.  
  355. ; Mind the BASIC ROM.
  356. !if values + RADIUS * 4 > $9fff {
  357.         !error "`values` array does not fit into memory"
  358. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement