;Randomizes a TI-list in Ans

_RclAns= 4AD7h
seed1  = $80F8
seed2  = $80FC

seed1_0=seed1
seed1_1=seed1+2
seed2_0=seed2
seed2_1=seed2+2
#define bcall(x) rst 28h \ .dw x


.db $BB,$6D
.org $9D95

; Put it into 15MHz mode if possible!
  in a,(2)
  add a,a
  sbc a,a
  out (20h),a


; Initialize the random seed
  ld hl,seed1
  ld b,7
  ld a,r
_:
  xor (hl)
  ld (hl),a
  inc hl
  djnz -_
  or 99
  or (hl)
  ld (hl),a
  

; Locate Ans, verify that it is a list or complex list
  bcall(_RclAns)
  ex de,hl
  ld c,(hl)
  inc hl
  ld b,(hl)
  inc hl
  ld (list_base),hl
  dec a
  jr z,+_
  sub 12
  ret nz
  dec a
_:

;A is 0 if a real list, -1 if complex
;HL points to the first element
;BC is the number of elements
  and $29     ;make it either NOP or ADD HL,HL
  ld (get_complex_element),a
  sub 29h
  sbc a,a
;FF if real, 00 if complex
  cpl
  and 9
  add a,9
  ld (element_size),a


shuffle_loop:
  push bc

  push bc
  call rand
  pop bc
  ex de,hl
  call mul16
  dec bc
  ;swap elements DE and BC
  
  call get_element
  push hl
  ld d,b
  ld e,c
  call get_element
  pop de

  call swap_elements
  
  pop bc
  dec bc
  ld a,c
  dec a
  jr nz,shuffle_loop
  inc b
  dec b
  jr nz,shuffle_loop
  ret


swap_elements:
;HL and DE point to the elements
element_size = $+2
  ld bc,255
_:
  ld a,(de)
  ldi
  dec hl
  ld (hl),a
  inc hl
  djnz -_
  ret


get_element:
;Input:
;   DE is the element to locate
;Output:
;   HL points to the element
  ld l,e
  ld h,d
  add hl,hl
  add hl,hl
  add hl,hl
  add hl,de
get_complex_element:
  nop
list_base = $+1
  ld de,0
  add hl,de
  ret


rand:
;Tested and passes all CAcert tests
;Uses a very simple 32-bit LCG and 32-bit LFSR
;it has a period of 18,446,744,069,414,584,320
;roughly 18.4 quintillion.
;LFSR taps: 0,2,6,7  = 11000101
;291cc
;Thanks to Runer112 for his help on optimizing the LCG and suggesting to try the much simpler LCG. On their own, the two are terrible, but together they are great.
    ld hl,(seed1)
    ld de,(seed1+2)
    ld b,h
    ld c,l
    add hl,hl \ rl e \ rl d
    add hl,hl \ rl e \ rl d
    inc l
    add hl,bc
    ld (seed1_0),hl
    ld hl,(seed1_1)
    adc hl,de
    ld (seed1_1),hl
    ex de,hl
;;lfsr
    ld hl,(seed2)
    ld bc,(seed2+2)
    add hl,hl \ rl c \ rl b
    ld (seed2_1),bc
    sbc a,a
    and %11000101
    xor l
    ld l,a
    ld (seed2_0),hl
    ex de,hl
    add hl,bc
    ret


mul16:
;BC*DE
  ld hl,0
  ld a,16
mul16_loop:
  add hl,hl
  rl e
  rl d
  jr nc,+_
  add hl,bc
  jr nc,+_
  inc de
_:
  dec a
  jr nz,mul16_loop
  ret