random.asm 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. ; RANDOM functions
  2. ;
  3. #include once <mul32.asm>
  4. ;
  5. RANDOMIZE:
  6. ; Randomize with 32 bit seed in DE HL
  7. ; if SEED = 0, calls ROM to take frames as seed
  8. ;- PROC
  9. ;- LOCAL TAKE_FRAMES
  10. ;- LOCAL FRAMES
  11. ;- ld a, h
  12. ora z80_l ;- or l
  13. ora z80_d ;- or d
  14. ora z80_e ;- or e
  15. ;- jr z, TAKE_FRAMES
  16. ;- ld (RANDOM_SEED_LOW), hl
  17. ;- ld (RANDOM_SEED_HIGH), de
  18. rts ;- ret
  19. TAKE_FRAMES:
  20. ; Takes the seed from frames
  21. ;- ld hl, (FRAMES)
  22. ;- ld (RANDOM_SEED_LOW), hl
  23. ;- ld hl, (FRAMES + 2)
  24. ;- ld (RANDOM_SEED_HIGH), hl
  25. rts ;- ret
  26. FRAMES EQU 23672
  27. ;- ENDP
  28. RANDOM_SEED_HIGH EQU RAND+6 ; RANDOM seed, 16 higher bits
  29. RANDOM_SEED_LOW EQU 23670 ; RANDOM seed, 16 lower bits
  30. RAND:
  31. ;- PROC
  32. ;- LOCAL RAND_LOOP
  33. ;- ld b, 4
  34. RAND_LOOP:
  35. ;- ld hl,(RANDOM_SEED_LOW) ; xz -> yw
  36. ;- ld de,0C0DEh ; yw -> zt
  37. ;- ld (RANDOM_SEED_LOW),de ; x = y, z = w
  38. ;- ld a,e ; w = w ^ ( w << 3 )
  39. ;- add a,a
  40. ;- add a,a
  41. ;- add a,a
  42. eor z80_e ;- xor e
  43. ;- ld e,a
  44. ;- ld a,h ; t = x ^ (x << 1)
  45. ;- add a,a
  46. eor z80_h ;- xor h
  47. ;- ld d,a
  48. ;- rra ; t = t ^ (t >> 1) ^ w
  49. eor z80_d ;- xor d
  50. eor z80_e ;- xor e
  51. ;- ld h,l ; y = z
  52. ;- ld l,a ; w = t
  53. ;- ld (RANDOM_SEED_HIGH),hl
  54. pha ;- push af
  55. php
  56. ;- djnz RAND_LOOP
  57. plp ;- pop af
  58. pha
  59. plp ;- pop af
  60. pha
  61. lda z80_a ;- ld d,a
  62. sta z80_d
  63. plp ;- pop af
  64. pha
  65. lda z80_a ;- ld e,a
  66. sta z80_e
  67. plp ;- pop af
  68. pha
  69. lda z80_a ;- ld h,a
  70. sta z80_h
  71. rts ;- ret
  72. ;- ENDP
  73. RND:
  74. ; Returns a FLOATING point integer
  75. ; using RAND as a mantissa
  76. ;- PROC
  77. ;- LOCAL RND_LOOP
  78. jsr RAND ;- call RAND
  79. ; BC = HL since ZX BASIC uses ED CB A registers for FP
  80. lda z80_h ;- ld b,h
  81. sta z80_b
  82. lda z80_l ;- ld c,l
  83. sta z80_c
  84. lda z80_e ;- ld a,e
  85. sta z80_a
  86. ora z80_d ;- or d
  87. ora z80_c ;- or c
  88. ora z80_b ;- or b
  89. bne *+3 ;- ret z ; Returns 0 if BC=DE=0
  90. rts
  91. ; We already have a random 32 bit mantissa in ED CB
  92. ; From 0001h to FFFFh
  93. ;- ld l,81h ; Exponent
  94. ; At this point we have [0 .. 1) FP number;
  95. ; Now we must shift mantissa left until highest bit goes into carry
  96. ;- ld a, e ; Use A register for rotating E faster (using RLA instead of RL E)
  97. RND_LOOP:
  98. ;- dec l
  99. ;- sla b
  100. rol z80_c ;- rl c
  101. rol z80_d ;- rl d
  102. ;- rla
  103. jcs RND_LOOP ;- jp nc, RND_LOOP
  104. ; Now undo last mantissa left-shift once
  105. ;- ccf ; Clears carry to insert a 0 bit back into mantissa -> positive FP number
  106. ;- rra
  107. ror z80_d ;- rr d
  108. ror z80_c ;- rr c
  109. ror z80_b ;- rr b
  110. lda z80_a ;- ld e,a ; E must have the highest byte
  111. sta z80_e
  112. lda z80_l ;- ld a,l ; exponent in A
  113. sta z80_a
  114. rts ;- ret
  115. ;- ENDP