The PokéCommunity Forums  

Go Back   The PokéCommunity Forums > ROM Hacking > Research & Development
Sign Up Rules/FAQ Live Battle Blogs Mark Forums Read

Notices

Research & Development Got a well-founded knack with ROM hacking? Love reverse-engineering the Pokémon games? Or perhaps you love your assembly language. This is the spot for polling and gathering your ideas, and then implementing them! Share your hypothesis, get ideas from others, and collaborate to create!
Research & Development programs in this forum are subject to moderator approval before they are displayed.


Advertise here

Reply
 
Thread Tools
  #1    
Old May 1st, 2010, 06:35 AM
HackMew's Avatar
HackMew
Mewtwo Strikes Back
 
Join Date: Jun 2006

Advertise here

Brief Intro


As probably most of you are aware of already, Emerald has a faulty PRNG implementation. The game does not take care of reseeding during the startup, leading to the fact it can be easily abused to get perfect IVs and similar.

Description


While it can be useful, it's indeed a major glitch. Since the whole game randomness is affected, it definitely needs to be fixed. Taking a look at Ruby's code, I found out that the initial reseeding happens as soon as the game starts (i.e. when the boot screen shows up). R/S use their internal clook to generate a 16-bit seed. In Emerald, of course, this part is totally missing. So I decided to emulate the R/S approach by porting their reseeding routine to Emerald. Here's the outcome:

Code:
.text .align 2 .thumb .thumb_func .global EmeraldPrngFix main: push {lr} ldr r1, .GET_CLOCK bl bx_r1 lsr r1, r0, #0x10 lsl r0, r0, #0x10 lsr r0, r0, #0x10 eor r0, r1 ldr r1, .UPDATE_SEED bl bx_r1 ldr r0, .UNK_RAM1 mov r4, #0x0 strb r4, [r0, #0x0] pop {pc} bx_r1: bx r1 .align 2 .UNK_RAM1: .word 0x03002700 .GET_CLOCK: .word 0x0802F664|1 .UPDATE_SEED: .word 0x0806F5F8|1
In order to apply the fix, assemble the routine and insert it somewhere where there's enough free space (if you never done it before, you better check my ASM tutorials). Take note of the address you used, and then replace 02 24 04 70 with FE 46 00 47, and 00 27 00 03 with XX XX XX XX, where XX XX XX XX represents the pointer to the routine's address + 1. For the respective offsets, see below.

The Offsets


  • Emerald US v1.0

    Code:
    0x402 0x478

This research document is Copyright © 2010 by HackMew.
You are not allowed to copy, modify or distribute it without permission.
__________________
Reply With Quote
  #2    
Old December 19th, 2011, 11:35 PM
ArmoredGuns
 
Join Date: Jan 2010
Can someone please make an IPS patch of this fix? It seems pretty important, and it seems it requires more than just hex editing... I would love to have this fix but I'm no programmer
Reply With Quote
  #3    
Old December 21st, 2011, 07:38 PM
itari's Avatar
itari
Community Supporter
 
Join Date: Mar 2010
Location: 渦潮隠れの里
Age: 17
Gender: Female
Nature: Relaxed
Quote:
Originally Posted by ArmoredGuns View Post
Can someone please make an IPS patch of this fix? It seems pretty important, and it seems it requires more than just hex editing... I would love to have this fix but I'm no programmer
Okay, here you go... However, I really recommend you learn to apply simple hacks like this.
Download.
*Note: Routine inserted at 0x9C0D00*
__________________
Touhou Puppet Play: Sapphire

SubscriptAdvanced SongType Effectiveness EditorTilemap CreatorPython IPS Patcher
Reply With Quote
  #4    
Old December 23rd, 2011, 12:19 AM
Bond697
 
Join Date: Oct 2008
Gender:
just FYI, the code to seed emerald's prng actually does exist in the game. all you would need to do is branch to this(and maybe turn on timer1 if it's not already, but that's easy) at some point and you're set. it was going to work exactly like fire red and leaf green.

it's just never used:


Code:
ROM:08000560             @ =============== S U B R O U T I N E =======================================
ROM:08000560
ROM:08000560
ROM:08000560             @ void __fastcall seedRNG__()
ROM:08000560             seedRNG__:
ROM:08000560 10 B5                       PUSH    {R4,LR}         @ this function never runs
ROM:08000562 06 48                       LDR     R0, =0x4000104  @ Timer1Data
ROM:08000564 04 88                       LDRH    R4, [R0]
ROM:08000566 20 1C                       MOVS    R0, R4          @ Timer1Data to r0
ROM:08000568 6F F0 46 F8                 BL      setRNG__        @ set rng state (0x3005D80) to result of timer1
ROM:0800056C 04 49                       LDR     R1, =0x4000106  @ T1CNT
ROM:0800056E 00 20                       MOVS    R0, #0
ROM:08000570 08 80                       STRH    R0, [R1]        @ turn off timer1
ROM:08000572 04 48                       LDR     R0, =0x2020000
ROM:08000574 04 80                       STRH    R4, [R0]        @ store the result of timer1 to 0x2020000
ROM:08000576 10 BC                       POP     {R4}
ROM:08000578 01 BC                       POP     {R0}
ROM:0800057A 00 47                       BX      R0
ROM:0800057A             @ End of function seedRNG__
ROM:0800057A
ROM:0800057A             @ ---------------------------------------------------------------------------
ROM:0800057C 04 01 00 04 dword_800057C:  .long 0x4000104         @ DATA XREF: seedRNG__+2r
ROM:08000580 06 01 00 04 dword_8000580:  .long 0x4000106         @ DATA XREF: seedRNG__+Cr
ROM:08000584 00 00 02 02 dword_8000584:  .long 0x2020000         @ DATA XREF: seedRNG__+12r
Code:
 
ROM:0806F5F8             @ =============== S U B R O U T I N E =======================================
ROM:0806F5F8
ROM:0806F5F8
ROM:0806F5F8             @ void __fastcall setRNG__(unsigned short T1Dat)
ROM:0806F5F8             setRNG__:                               @ CODE XREF: seedRNG__+8p
ROM:0806F5F8 00 04                       LSLS    R0, R0, #0x10   @ dumb typecasting
ROM:0806F5FA 00 0C                       LSRS    R0, R0, #0x10
ROM:0806F5FC 02 49                       LDR     R1, =0x3005D80  @ rng buffer
ROM:0806F5FE 08 60                       STR     R0, [R1]        @ set rng to T1Dat
ROM:0806F600 02 49                       LDR     R1, =0x20249BC  @ rng frame counter
ROM:0806F602 00 20                       MOVS    R0, #0          @ set counter to 0 to signify starting seed
ROM:0806F604 08 70                       STRB    R0, [R1]
ROM:0806F606 70 47                       BX      LR
ROM:0806F606             @ End of function setRNG__
Reply With Quote
  #5    
Old December 23rd, 2011, 01:42 AM
ArmoredGuns
 
Join Date: Jan 2010
Quote:
Originally Posted by agentgeo View Post


Okay, here you go... However, I really recommend you learn to apply simple hacks like this.

*Note: Routine inserted at 0x9C0D00*
Thank you very much!!! I greatly appreciate it

Quote:
Originally Posted by Bond697 View Post
just FYI, the code to seed emerald's prng actually does exist in the game. all you would need to do is branch to this(and maybe turn on timer1 if it's not already, but that's easy) at some point and you're set. it was going to work exactly like fire red and leaf green.

it's just never used:


Code:
ROM:08000560             @ =============== S U B R O U T I N E =======================================
ROM:08000560
ROM:08000560
ROM:08000560             @ void __fastcall seedRNG__()
ROM:08000560             seedRNG__:
ROM:08000560 10 B5                       PUSH    {R4,LR}         @ this function never runs
ROM:08000562 06 48                       LDR     R0, =0x4000104  @ Timer1Data
ROM:08000564 04 88                       LDRH    R4, [R0]
ROM:08000566 20 1C                       MOVS    R0, R4          @ Timer1Data to r0
ROM:08000568 6F F0 46 F8                 BL      setRNG__        @ set rng state (0x3005D80) to result of timer1
ROM:0800056C 04 49                       LDR     R1, =0x4000106  @ T1CNT
ROM:0800056E 00 20                       MOVS    R0, #0
ROM:08000570 08 80                       STRH    R0, [R1]        @ turn off timer1
ROM:08000572 04 48                       LDR     R0, =0x2020000
ROM:08000574 04 80                       STRH    R4, [R0]        @ store the result of timer1 to 0x2020000
ROM:08000576 10 BC                       POP     {R4}
ROM:08000578 01 BC                       POP     {R0}
ROM:0800057A 00 47                       BX      R0
ROM:0800057A             @ End of function seedRNG__
ROM:0800057A
ROM:0800057A             @ ---------------------------------------------------------------------------
ROM:0800057C 04 01 00 04 dword_800057C:  .long 0x4000104         @ DATA XREF: seedRNG__+2r
ROM:08000580 06 01 00 04 dword_8000580:  .long 0x4000106         @ DATA XREF: seedRNG__+Cr
ROM:08000584 00 00 02 02 dword_8000584:  .long 0x2020000         @ DATA XREF: seedRNG__+12r
Code:
 
ROM:0806F5F8             @ =============== S U B R O U T I N E =======================================
ROM:0806F5F8
ROM:0806F5F8
ROM:0806F5F8             @ void __fastcall setRNG__(unsigned short T1Dat)
ROM:0806F5F8             setRNG__:                               @ CODE XREF: seedRNG__+8p
ROM:0806F5F8 00 04                       LSLS    R0, R0, #0x10   @ dumb typecasting
ROM:0806F5FA 00 0C                       LSRS    R0, R0, #0x10
ROM:0806F5FC 02 49                       LDR     R1, =0x3005D80  @ rng buffer
ROM:0806F5FE 08 60                       STR     R0, [R1]        @ set rng to T1Dat
ROM:0806F600 02 49                       LDR     R1, =0x20249BC  @ rng frame counter
ROM:0806F602 00 20                       MOVS    R0, #0          @ set counter to 0 to signify starting seed
ROM:0806F604 08 70                       STRB    R0, [R1]
ROM:0806F606 70 47                       BX      LR
ROM:0806F606             @ End of function setRNG__
Hmm I wonder if FRLG's PRNG seeding routine is better than Ruby/sapphire's...
Reply With Quote
  #6    
Old January 28th, 2012, 08:52 AM
Kaphotics
♥ Quick Claw Guillotine ♥
 
Join Date: Apr 2011
Quote:
Originally Posted by ArmoredGuns View Post
Hmm I wonder if FRLG's PRNG seeding routine is better than Ruby/sapphire's...
It's not, R/S was better due to the more variant initial starting seeds (hence more random).

FRLG had 0x0000 - 0xFFFF starting seeds, whereas R/S was 0x0 - 0x7FFFFFFF.

Both are definitely more random than Emerald, but R/S did it better. In later games (DPPt and BW) you have a mix of datetime and hardware timers (delay).
Reply With Quote
  #7    
Old September 2nd, 2012, 07:23 AM
AlphaDrache's Avatar
AlphaDrache
 
Join Date: Dec 2009
Gender: Male
Are the addresses the same for the german emerald ROM?
Reply With Quote
  #8    
Old September 2nd, 2012, 07:50 AM
Darthatron's Avatar
Darthatron
巨大なトロール。
Community Supporter Tier 2
 
Join Date: Jan 2006
Location: Melbourne, Australia
Age: 22
Gender: Male
Nature: Modest
Quote:
Originally Posted by AlphaDrache View Post
Are the addresses the same for the german emerald ROM?
Probably, but to check just see if the bytes at the given offsets are the ones described in the tutorial.
__________________
あなた は しきしゃ です
わたし は ばか です
Reply With Quote
  #9    
Old September 3rd, 2012, 12:52 PM
Bond697
 
Join Date: Oct 2008
Gender:
Quote:
Originally Posted by Kaphotics View Post
It's not, R/S was better due to the more variant initial starting seeds (hence more random).

FRLG had 0x0000 - 0xFFFF starting seeds, whereas R/S was 0x0 - 0x7FFFFFFF.

Both are definitely more random than Emerald, but R/S did it better. In later games (DPPt and BW) you have a mix of datetime and hardware timers (delay).
this is wrong. r/s seeds only go 0-0xffff also even though they use a more complex formula. the seeding is 16-bit either way, so no there's not more seeds.

Code:
ROM:080003E4 ; =============== S U B R O U T I N E =======================================
ROM:080003E4
ROM:080003E4
ROM:080003E4 seedRNG                                 ; CODE XREF: main+30p
ROM:080003E4                 PUSH    {LR}
ROM:080003E6                 BL      buildSeed
ROM:080003EA                 MOVS    R2, R0          ; s32 seed to r2
ROM:080003EC                 LSRS    R0, R2, #0x10   ; r0 = seed >> 16
ROM:080003EE                 LDR     R1, =0xFFFF
ROM:080003F0                 ANDS    R1, R2          ; r1 = seed & 0xFFFF (get lower 16 bits of seed)
ROM:080003F2                 EORS    R0, R1          ; upperSeed ^ lowerSeed
ROM:080003F4                 BL      setRNG
ROM:080003F8                 POP     {R0}
ROM:080003FA                 BX      R0
ROM:080003FA ; End of function seedRNG
ROM:080003FA
ROM:080003FA ; ---------------------------------------------------------------------------
ROM:080003FC dword_80003FC   DCD 0xFFFF              ; DATA XREF: seedRNG+Ar
(sapphire)

Last edited by Bond697; September 3rd, 2012 at 01:26 PM.
Reply With Quote
  #10    
Old October 24th, 2012, 10:35 PM
aroenai
Unhatched Egg
 
Join Date: Oct 2012
Gender: Male
Quote:
Originally Posted by Bond697 View Post
just FYI, the code to seed emerald's prng actually does exist in the game. all you would need to do is branch to this(and maybe turn on timer1 if it's not already, but that's easy) at some point and you're set. it was going to work exactly like fire red and leaf green.

it's just never used:


Code:
ROM:08000560             @ =============== S U B R O U T I N E =======================================
ROM:08000560
ROM:08000560
ROM:08000560             @ void __fastcall seedRNG__()
ROM:08000560             seedRNG__:
ROM:08000560 10 B5                       PUSH    {R4,LR}         @ this function never runs
ROM:08000562 06 48                       LDR     R0, =0x4000104  @ Timer1Data
ROM:08000564 04 88                       LDRH    R4, [R0]
ROM:08000566 20 1C                       MOVS    R0, R4          @ Timer1Data to r0
ROM:08000568 6F F0 46 F8                 BL      setRNG__        @ set rng state (0x3005D80) to result of timer1
ROM:0800056C 04 49                       LDR     R1, =0x4000106  @ T1CNT
ROM:0800056E 00 20                       MOVS    R0, #0
ROM:08000570 08 80                       STRH    R0, [R1]        @ turn off timer1
ROM:08000572 04 48                       LDR     R0, =0x2020000
ROM:08000574 04 80                       STRH    R4, [R0]        @ store the result of timer1 to 0x2020000
ROM:08000576 10 BC                       POP     {R4}
ROM:08000578 01 BC                       POP     {R0}
ROM:0800057A 00 47                       BX      R0
ROM:0800057A             @ End of function seedRNG__
ROM:0800057A
ROM:0800057A             @ ---------------------------------------------------------------------------
ROM:0800057C 04 01 00 04 dword_800057C:  .long 0x4000104         @ DATA XREF: seedRNG__+2r
ROM:08000580 06 01 00 04 dword_8000580:  .long 0x4000106         @ DATA XREF: seedRNG__+Cr
ROM:08000584 00 00 02 02 dword_8000584:  .long 0x2020000         @ DATA XREF: seedRNG__+12r
Code:
 
ROM:0806F5F8             @ =============== S U B R O U T I N E =======================================
ROM:0806F5F8
ROM:0806F5F8
ROM:0806F5F8             @ void __fastcall setRNG__(unsigned short T1Dat)
ROM:0806F5F8             setRNG__:                               @ CODE XREF: seedRNG__+8p
ROM:0806F5F8 00 04                       LSLS    R0, R0, #0x10   @ dumb typecasting
ROM:0806F5FA 00 0C                       LSRS    R0, R0, #0x10
ROM:0806F5FC 02 49                       LDR     R1, =0x3005D80  @ rng buffer
ROM:0806F5FE 08 60                       STR     R0, [R1]        @ set rng to T1Dat
ROM:0806F600 02 49                       LDR     R1, =0x20249BC  @ rng frame counter
ROM:0806F602 00 20                       MOVS    R0, #0          @ set counter to 0 to signify starting seed
ROM:0806F604 08 70                       STRB    R0, [R1]
ROM:0806F606 70 47                       BX      LR
ROM:0806F606             @ End of function setRNG__
Can someone post an .ips patch that uses the built in code for Emerald, and possibly port it to R/S? The reason I ask is the batteries finally died in my copies of R/S/E so I wanted to start using my EZ Flash 3in1 and EZ Flash IV which both lack a RTC (gbata patched).

Edit: Oh wait, would that just be 61 05 00 08 at 0x478 for Emerald?
Edit 2: Nope white screen

Last edited by aroenai; October 25th, 2012 at 06:21 PM.
Reply With Quote
  #11    
Old April 7th, 2014, 10:34 PM
ThomasWinwood
 
Join Date: Nov 2013
Gender: Male
Quote:
Originally Posted by aroenai View Post
Can someone post an .ips patch that uses the built in code for Emerald, and possibly port it to R/S?
This isn't an IPS patch (though making one is trivial) but I think that you can use the existing RNG seeding routine by making the following changes. (I would really appreciate someone checking that this does in fact seed the PRNG correctly - I'm on Linux, so the only debugging tools I have available to me are "does the ROM work" and "do I get anything odd, like a trainer ID of 00000".)
  1. At 0x402 change 00 24 04 70 to FE 46 00 47.
  2. At 0x478 change 00 27 00 03 to 61 05 00 08.
  3. At 0x578 change 01 BC 00 47 to 00 BD 08 47.
Reply With Quote
Reply
Quick Reply

Sponsored Links


Advertise here
Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Minimum Characters Per Post: 25



All times are UTC -8. The time now is 11:26 AM.


Style by Nymphadora, artwork by Sa-Dui.
Like our Facebook Page Follow us on Twitter © 2002 - 2014 The PokéCommunity™, pokecommunity.com.
Pokémon characters and images belong to The Pokémon Company International and Nintendo. This website is in no way affiliated with or endorsed by Nintendo, Creatures, GAMEFREAK, The Pokémon Company or The Pokémon Company International. We just love Pokémon.
All forum styles, their images (unless noted otherwise) and site designs are © 2002 - 2014 The PokéCommunity / PokéCommunity.com.
PokéCommunity™ is a trademark of The PokéCommunity. All rights reserved. Sponsor advertisements do not imply our endorsement of that product or service. User generated content remains the property of its creator.