Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Link battle LCG is effectively only nine bytes #1155

Open
SnowyMouse opened this issue Dec 15, 2024 · 2 comments
Open

Bug: Link battle LCG is effectively only nine bytes #1155

SnowyMouse opened this issue Dec 15, 2024 · 2 comments
Labels

Comments

@SnowyMouse
Copy link

SnowyMouse commented Dec 15, 2024

LCG is ten bytes, but only nine are actually ever used. The tenth byte is never read! As such, it is functionally identical to Gen 1's LCG.

I think it might be a holdover from Gen 1. In fact, the check to see if we've run out of bytes in the seed is actually the same code as pokered.

cp 10 - 1 ; Exclude last value. See the closing comment
ld a, [hl]
pop bc
pop hl
ret c

One could assume that this tenth byte is used for cycling PRNG, but this is also not so. If you scroll down below, you'll see this code:

; Reset count to 0
xor a
ld [wLinkBattleRNCount], a
ld hl, wLinkBattleRNs
ld b, 10 ; number of seeds
; 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

We do not use the value from the previous iteration, and hl is incremented at the end of the loop (hli increments hl after write, not before). As such, it works exactly the same as Gen 1's PRNG. In fact Gen 1's code is exactly the same, besides b being set to 10 instead of 9.

Therefore, the game generates a tenth byte but never uses it. I'm guessing the fix is probably to just change cp 10 - 1 to just cp 10 (or even better, cp SERIAL_RNS_LENGTH).

@SnowyMouse SnowyMouse changed the title Link battle LCG is effectively only nine bytes Bug: Link battle LCG is effectively only nine bytes Dec 15, 2024
@Rangi42
Copy link
Member

Rangi42 commented Dec 22, 2024

Gen 1 also has a 10-byte PRNG buffer (SERIAL_RNS_LENGTH is 10 there too). So one "fix" here could be to change the cp 10 - 1 to cp 10, but another could be to change the ld b, 10 to ld b, 9 like Gen 1 had. Also -- what would the consequence of either "fix" be? Does this cause an observable bug, e.g. repeated or inconsistent RNG values?

@SnowyMouse
Copy link
Author

SnowyMouse commented Dec 22, 2024

I think the better fix would be changing ld b, 10 to ld b, 9.

I only suggested using cp 10 because it looked like it might've been intentional by the developers to use a tenth byte for some bizarre reason. Gen 1-2's LCG is technically nine independent LCGs, and since it just uses random numbers as the seed, repeats are bound to happen, and not only that, but happen very predictably. Adding more bytes raises this probability.

Changing ld b, 10 to ld b, 9 will also not break cartridge compatibility (again, that 10th byte wasn't getting used!), so there is also points for that, too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants