After doing some disassembling, I found the differences between the NES/FDS versions. It turns out that the FDS version of Metroid doesn't have it's own RNG, and that it uses the FDS BIOS RNG subroutine. I can only guess that Tohru Narihiro (the person who did the conversion from FDS to MMC1) didn't have access to the FDS RNG? There had to be some reason he didn't use it...

So I figured I'd port it over...

Here's the NES Metroid RNG: (Credit to SnowBro and Dirty McDingus for Metroid disassembly)

Code: Select all

```
;--------------------------------------------------------
; NES Metroid RNG
;--------------------------------------------------------
RandomNumber1 = $2E
RandomNumber2 = $2F
.org $C000
NESMetroidRNG:
TXA ; transfer X to A
PHA ; push A to stack
LDX #$05 ; load 5 into X register
_C004:
LDA RandomNumber1 ; load RandomNumber1 into A
CLC ; clear carry flag
ADC #$05 ; add 5 to A
STA RandomNumber1 ; RandomNumber1 is increased by #$19 every frame
LDA RandomNumber2 ; RandomNumber2 is increased by #$5F every frame
CLC ; clear carry flag
ADC #$13 ; add 13 to A
STA RandomNumber2 ; store A in RandomNumber2
DEX ; decrement X by one
BNE _C004 ; branch to _C004 if result not zero
PLA ; pull A from stack
TAX ; transfer A to X
LDA RandomNumber1 ; load RandomNumber1 into A
RTS
;Hex code: (26 bytes)
;8A 48 A2 05 A5 2E 18 69 05 85 2E A5 2F 18 69 13 85 2F CA D0 EF 68 AA A5 2E 60
```

I read the MMC1 page and it says something about no bus conflicts, but maybe this was not referring to MMC1 register writes at a ROM address? Someone please correct me if I'm wrong.

Anyway, the code about defintely doesn't produce enough "randomness" in it's results, and you can see patterns in the enemy behavior.

So here's the FDS RNG:

Code: Select all

```
RandomNumber1 = $2E
RandomNumber2 = $2F
.org $C000
;---------------------------------------------------------
; Start Metroid pass in parameters to FDS RNG subroutine
;---------------------------------------------------------
BeginRNGForMetroid:
LDX #$2E ; X is the memory location where random numbers start
LDY #$02 ; Y is the count of how many random numbers there are from the start index
;---------------------------------------------------------
; FDS Random number generator
;---------------------------------------------------------
FDSRNG:
LDA $00,X ; load previous random number 1 into A
AND #$02 ; AND A with 00000011
STA $00 ; store A in $00 (working memory)
LDA $01,X ; load previous random number 2 into A
AND #$02 ; AND A with 00000011
EOR $00 ; XOR A with random number 1
CLC ; clear carry flag
BEQ _E9C1 ; branch if equal (zero set)
SEC ; set carry flag
_E9C1:
ROR $00,X ; rotate right one bit random number 1, the carry is shifted into bit 7
; and bit 0 is shifted into carry
INX ; increment X
DEY ; decrement Y is the count of bytes for RNG
BNE _E9C1 ; branch if not equal (zero clear)
RTS
;Resulting hex code, 27 bytes
;A2 2E A0 02 B5 00 29 02 85 00 B5 01 29 02 45 00 18 F0 01 38 76 00 E8 88 D0 FA 60
```

So I had to make a couple changes, but it still outputs the same values:

Code: Select all

```
; vars
tmp = $00
RandomNumber1 = $2E
RandomNumber2 = $2F
.org $C000
;---------------------------------------------------------
; FDS Random number generator fit
;---------------------------------------------------------
Init:
TXA
TAX
FDSRNG:
LDA RandomNumber1 ; load previous random number 1 into A
AND #$02 ; AND A with 00000011
STA tmp ; store A in tmp (working memory)
LDA RandomNumber2 ; load previous random number 2 into A
AND #$02 ; AND A with 00000011
EOR tmp ; XOR A with tmp
CLC ; clear carry flag
BEQ _E9C1 ; branch if equal (zero set)
SEC ; set carry flag
_E9C1:
ROR RandomNumber1 ; rotate right one bit random number 1, the carry is shifted into bit 7
ROR RandomNumber2 ; and bit 0 is shifted into carry
NOP
LDA RandomNumber1
RTS
; modified FDS RNG to fit in Metroid NES at $C000
; 8A AA A5 2E 29 02 85 00 A5 2F 29 02 45 00 18 F0 01 38 66 2E 66 2F EA A5 2E 60
```