aaaaaa123456789 icon

StableRandom's original gbz80 code

aaaaaa123456789 | PRO | 08/07/18 01:34:20 PM UTC | 0 ⭐ | 439 👁️ | Never ⏰ | []
text |

3.28 KB

|

None

|

0 👍

/

0 👎

; This code was originally found in Prism. Originally written on 2016-12-18; updated on 2018-08-18 with a bug fix.
; Since I never bothered with a license header, I'm hereby placing it in the public domain as of 2019-01-04.
 StableRandom::
	; in: hl: pointer to 8-byte RNG state
	; out: a: random value; other registers preserved
	push bc
	push de
	push hl
	call .advance_left_register
	call .check_right_register_cycles
	call .advance_right_register
	inc hl
	inc hl
	inc hl
	call .advance_selector_register
	pop hl
	push hl
	rlca
	rlca
	ld c, a
	and 3
	ld e, a
	ld d, 0
	add hl, de
	ld b, [hl]
	pop hl
	push hl
	ld e, 5
	add hl, de
	ld a, c
	ld c, [hl]
	rlca
	rlca
	and 3
	call .combine_register_values
	pop hl
	pop de
	pop bc
	ret
 .advance_left_register
	; in: hl: pointer to left register
	; out: hl: pointer to RIGHT register
	ld a, [hli]
	ld e, a
	ld a, [hli]
	ld d, a
	ld a, [hli]
	ld c, a
	ld a, [hld]
	ld b, a
	or c
	or d
	or e
	call z, .reseed_left_register
	ld a, e
	xor d
	ld e, a
	ld a, d
	xor c
	ld d, a
	ld a, c
	xor b
	ld c, a
	ld a, c
	ld [hld], a
	ld a, d
	ld [hld], a
	ld [hl], e
	sla e
	rl d
	rl c
	inc hl
	ld a, [hl]
	xor e
	ld [hli], a
	ld a, [hl]
	xor d
	ld [hli], a
	ld a, [hl]
	xor c
	ld [hld], a
	ld b, a
	ld c, [hl]
	sla c
	rl b
	sbc a
	and 1
	dec hl
	xor [hl]
	ld [hld], a
	ld a, [hl]
	xor b
	ld [hli], a
	inc hl
	inc hl
	inc hl
	ret
 .reseed_left_register
	; in: hl: pointer to left register + 2
	; out: hl preserved; bcde new seed
	ld de, 5
	push hl
	add hl, de
	call .advance_selector_register
	ld b, a
	call .advance_selector_register
	ld c, a
	call .advance_selector_register
	ld d, a
	call .advance_selector_register
	ld e, a
	pop hl
	inc hl
	ld a, b
	ld [hld], a ;only b needs to be written back, since the rest will be handled by the main function
	ret
 .check_right_register_cycles
	; in: hl: pointer to right register
	; out: hl preserved
	inc hl
	inc hl
	ld a, [hld]
	ld c, a
	ld a, [hld]
	ld d, a
	or c
	ld e, [hl]
	push hl
	jr z, .check_long_cycles
	ld hl, .right_register_short_cycles - 1
	ld b, (.right_register_short_cycles_end - .right_register_short_cycles) / 3 + 1
.short_cycle_handle_loop
	inc hl
	dec b
	jr z, .pop_ret
.short_cycle_loop
	ld a, [hli]
	cp c
	ld a, [hli]
	jr nz, .short_cycle_handle_loop
	cp d
	jr nz, .short_cycle_handle_loop
	ld a, e
	cp [hl]
	jr nz, .short_cycle_handle_loop
	inc hl
.copy_right_register_state
	ld a, [hli]
	ld c, a
	ld a, [hli]
	ld b, [hl]
	pop hl
	inc hl
	ld [hli], a
	ld a, c
	ld [hld], a
	dec hl
	ld [hl], b
	ret
 .check_long_cycles
	ld hl, .right_register_long_cycles
.long_cycle_loop
	ld a, [hli]
	and a
	jr z, .pop_ret
	cp e
	jr nz, .long_cycle_loop
	ld a, [hl]
	and a
	jr z, .start_short_cycles
	pop hl
	ld [hl], a
	ret
 .start_short_cycles
	pop hl
	push hl
	inc hl
	inc hl
	inc hl
	call .advance_selector_register
	ld hl, .right_register_short_cycles
	jr .copy_right_register_state
 .pop_ret
	pop hl
	ret
 .right_register_short_cycles
	db $72, $4f, $9f
	db $7b, $1a, $7b
	db $84, $e5, $56
	db $8d, $b0, $32
.right_register_short_cycles_end
	db 0, 0
.right_register_long_cycles
	db 1, 2, 4, 8, 13, 17, 23, 26, 29, 58
	db 0
 .advance_right_register
	; in: hl: pointer to right register
	; out: hl preserved
	ld a, [hli]
	cp 210
	jr c, .right_carry_OK
	sub 210
.right_carry_OK
	ld d, a
	ld a, [hli]
	ld e, a
	ld c, [hl]
	or c
	or d
	jr z, .right_register_needs_reseed
	ld a, c
	and e
	inc a
	jr nz, .right_register_OK
	ld a, d
	cp 209
	jr nz, .right_register_OK
.right_register_needs_reseed
	call .reseed_right_register
.right_register_OK
	ld a, e
	ld [hld], a
	push hl
	ld b, 0
	ld h, b
	ld l, d
	ld a, 210
	rst AddNTimes
	ld a, l
	ld b, h
	pop hl
	ld [hld], a
	ld [hl], b
	ret
 .reseed_right_register
	; in: hl: pointer to right register + 2
	; out: hl preserved, cde new seed
	inc hl
	call .advance_selector_register
	ld c, a
	call .advance_selector_register
	ld d, a
	sub 210
	jr c, .carry_reseed_OK
	ld d, a
.carry_reseed_OK
	call .advance_selector_register
	ld e, a
	dec hl
	ret
 .advance_selector_register
	; in: hl: pointer to selector register
	; out: all registers but a preserved; a = new selector
	push bc
	ld a, [hl]
	ld b, 0
	rra
	rr b
	rra
	rr b
	ld a, [hl]
	swap a
	rrca
	and $f8
	add a, b
	add a, [hl]
	add a, 29
	ld [hl], a
	pop bc
	ret
 .combine_register_values
	and a
	jr z, .add_registers
	dec a
	jr z, .xor_registers
	dec a
	jr z, .subtract_registers
	ld a, c
	sub b
	ret
.subtract_registers
	ld a, b
	sub c
	ret
.add_registers
	ld a, b
	add a, c
	ret
.xor_registers
	ld a, b
	xor c
	ret

Comments