1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
INCLUDE "constants.asm"
SECTION "engine/battle/core.asm", ROMX
_BattleRandom:
; If the normal RNG is used in a link battle it'll desync.
; To circumvent this a shared PRNG is used instead.
; But if we're in a non-link battle we're safe to use it
ld a, [wLinkMode]
and a
jp z, Random
; The PRNG operates in streams of 10 values.
; Which value are we trying to pull?
push hl
push bc
ld a, [wLinkBattleRNCount]
ld c, a
ld b, $0
ld hl, wLinkBattleRNs
add hl, bc
inc a
ld [wLinkBattleRNCount], a
; If we haven't hit the end yet, we're good
cp 9 ; number of seeds, including the last one. see comment in pokecrystal
ld a, [hl]
pop bc
pop hl
ret c
; If we have, we have to generate new pseudorandom data
; Instead of having multiple PRNGs, ten seeds are used
push hl
push bc
push af
; Reset count to 0
xor a
ld [wLinkBattleRNCount], a
ld hl, wLinkBattleRNs
ld b, 9 ; number of seeds; in release, this was increased to 10
; Generate next number in the sequence for each seed
; a[n+1] = (a[n] * 5 + 1) % 256
.loop
; get last #
ld a, [hl]
; a * 5 + 1
ld c, a
add a
add a
add c
inc a
; update #
ld [hli], a
dec b
jr nz, .loop
; This has the side effect of pulling the last value first,
; then wrapping around. As a result
pop af
pop bc
pop hl
ret
|