FE1 RNG Fix

So after playing the new Switch release, something felt off about the RNG. So I had a dive into the code and found this https://youtu.be/h32hV3Ewpy8

Basically it has a couple of flaws

  • Rng is x10 / 25 and thus is scaled over 250 not 256 giving >100 and more 100s. Which thanks to the inverted nature of the check means more 0s.
  • Only 0 is not 0 because you can get a 100 returned and its compared <= so there are no 0s
  • the RNG is not RNG at all and is always 22% less, which wraps. This gives very set patterns.

Since this is easy to fix I’ve made 2 patches ( I couldn’t find any others already made )
Fe1RNgFix.zip
The first patch ( Fire Emblem - Ankoku Ryuu to Hikari No Tsurugi_RNG_Fix.ips ) just fixes the x10/25 and makes it x100/256 as per FE2 and 3
the second patch ( Fire Emblem - Ankoku Ryuu to Hikari No Tsurugi_RNG_Improvement.ips ) fixes the scale and replaces the RNG generator with a LFSR based solution which gives a more random distribution. It will still loop every 256 so not amazing, but has a distribution rather than -22%.

Lightly tested, let me know if there are any issues.

15 Likes

yo dude cool stuff!

Would you mind sharing the sources for these? I assume there’s not much to them but just for the sake of it I think it would be nice. (and if you have any other fe1 reverse-engineering notes or whatever I’d like to have a look at those as well)

1 Like

So the RNG fix is

* = $C04E
LDA $31
BEQ DoEOR
LDY #$F0
ASL A
BCC NoEOR
DoEOR
EOR #$63
NoEOR
STA $31
RTS

For details on how and why this works see https://codebase64.org/doku.php?id=base:small_fast_8-bit_prng

To fix the Scale patch
This code

* = $CE7E
JSR GetRandomNumber      ; $C04E
STA $00                  
LDA #$0A                 
STA $01                  
JSR Mul8_8_r16Bit        ; $C6C9
LDA $01                  
STA $49                  
LDA $00                  
STA $48                  
LDA #$19                 
STA $4A                  
JSR Div16_16_8           ; $C6EB
LDA $48                  
CMP #$64                 
BCC $CEA1                
LDA #$64                 
RTS                      

becomes

*=$CE7E
JSR GetRandomNumber ; $C04E
STA $00
LDA #$64            ; x100
STA $01
JSR Mul8_8_r16Bit   ; $C6C9
LDA $01             ; take the high byte
RTS
2 Likes

The only other odd thing I came across was the Mecrulius sword. It does damage like a physical sword, but the avoid for it is calculated as if it is a magic sword.

Wait, so this also applies to the original NES version? Because I remember playing that and missing an awful lot even for a 1RN game.

1 Like

Seconded

Also Applies? This is the original NES version.

Oop
I was under the impression it was specifically for the Switch port
At any rate, thanks for confirming my suspicions