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!

TrollandToad.com
Reply
 
Thread Tools
  #1    
Old May 1st, 2010 (6:35 AM).
HackMew's Avatar
HackMew HackMew is offline
Mewtwo Strikes Back
  • Crystal Tier
 
Join Date: Jun 2006
Posts: 1,314

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

Relevant Advertising!

  #2    
Old December 19th, 2011 (11:35 PM).
ArmoredGuns ArmoredGuns is offline
     
    Join Date: Jan 2010
    Posts: 12
    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 (7:38 PM).
    esperance's Avatar
    esperance esperance is offline
    • Platinum Tier
     
    Join Date: Mar 2010
    Location: Ohio
    Age: 20
    Gender: Male
    Nature: Relaxed
    Posts: 3,829
    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*
    __________________
    I was once somebody.
    Reply With Quote
      #4    
    Old December 23rd, 2011 (12:19 AM).
    Bond697 Bond697 is offline
       
      Join Date: Oct 2008
      Gender:
      Posts: 28
      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 (1:42 AM).
      ArmoredGuns ArmoredGuns is offline
         
        Join Date: Jan 2010
        Posts: 12
        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 (8:52 AM).
        Kaphotics Kaphotics is offline
        ♥ Quick Claw Guillotine ♥
           
          Join Date: Apr 2011
          Posts: 22
          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 (7:23 AM).
          AlphaDrache's Avatar
          AlphaDrache AlphaDrache is offline
             
            Join Date: Dec 2009
            Gender: Male
            Posts: 8
            Are the addresses the same for the german emerald ROM?
            Reply With Quote
              #8    
            Old September 2nd, 2012 (7:50 AM).
            Darthatron's Avatar
            Darthatron Darthatron is offline
            巨大なトロール。
            • Silver Tier
             
            Join Date: Jan 2006
            Location: Melbourne, Australia
            Age: 25
            Gender: Male
            Nature: Modest
            Posts: 1,152
            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). Edited September 3rd, 2012 by Bond697.
            Bond697 Bond697 is offline
               
              Join Date: Oct 2008
              Gender:
              Posts: 28
              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)
              Reply With Quote
                #10    
              Old October 24th, 2012 (10:35 PM). Edited October 25th, 2012 by aroenai.
              aroenai aroenai is offline
                 
                Join Date: Oct 2012
                Gender: Male
                Posts: 1
                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
                Reply With Quote
                  #11    
                Old April 7th, 2014 (10:34 PM).
                ThomasWinwood ThomasWinwood is offline
                   
                  Join Date: Nov 2013
                  Gender: Male
                  Nature: Relaxed
                  Posts: 70
                  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
                    #12    
                  Old March 22nd, 2017 (3:44 PM). Edited March 31st, 2017 by MWisBest.
                  MWisBest MWisBest is offline
                     
                    Join Date: Mar 2017
                    Gender: Male
                    Posts: 19
                    Quote:
                    Originally Posted by ThomasWinwood View Post
                    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.
                    Sorry to dig up an old thread, but unfortunately this does not work. As far as I can tell, the issue is timer1 isn't turned on, so the end result is the PRNG is (re)seeded to 0. It would be nice not to rely on the RTC for the seed, but I'm not particularly good at writing assembly, just interpreting it. :/

                    I see the link died for the IPS patch of HackMew's fix, so I've attached a new one that should be identical (routine still inserted at 0x9C0D00).

                    Edit: Actually I was able to whip something up to enable timer1 and then call the seed function, but the timer value is always the same since the timing is never different.
                    It turns out the PRNG is seeded with the built-in function when a new game is started, but not when an existing one is loaded. It turns on timer1 when New Game is pressed (or somewhere around there), and then after the player enters their name it calls the built-in seed-from-timer1 function at 0x560.

                    For this method to work, timer1 needs to be turned on when the opening movie begins playing, and the built-in seed-from-timer1 function needs to be called when "Continue" (Load Game) is pressed. How exactly that can be done, I'm not sure yet.


                    Edit2: Well I've surprised myself. I seem to have gotten this built-in timer-based PRNG seeding working.

                    There's 1 routine required. The byte edit at 0x400 uses the game's built in function for enabling T1, and the added routine is to run the seed function after the "Press Start" screen.

                    Code:
                    .text
                    .align 2
                    .thumb
                    .thumb_func
                    .global EmeraldTimerPrngSeedAtMenu
                    
                    main:
                    	push {lr}
                    	ldr r1, .SEED_RNG_FROM_T1
                    	bl bx_r1
                    	movs r0, #0
                    	ldr r1, .MENU_CB_THING
                    	bl bx_r1
                    	pop {r0}
                    	bx r0
                    
                    bx_r1:
                    	bx r1
                    
                    .align 2
                    .SEED_RNG_FROM_T1:
                    	.word 0x08000560|1
                    .MENU_CB_THING:
                    	.word 0x0802F6F4|1
                    Compile and insert into free space. Byte changes required:
                    1. At 0x400 change 1D 48 00 24 04 70 to 00 F0 A8 F8 C0 46.
                    2. At 0xAAED0 change DD F6 02 08 to XX XX XX 08, where XX XX XX is the location of the routine (EmeraldTimerPrngSeedAtMenu) +1 (e.x. if you insert it at 0x9C0D00, you'd put 01 0D 9C 08).

                    I've also attached an IPS of this for those who would prefer that; the routine was inserted at 0x9C0D00.
                    Attached Files
                    File Type: ips Emerald RNG Fix.ips‎ (74 Bytes, 6 views) (Save to Dropbox)
                    File Type: ips Emerald TIMER RNG Fix.ips‎ (63 Bytes, 14 views) (Save to Dropbox)
                    Reply With Quote
                      #13    
                    Old March 23rd, 2017 (2:31 PM).
                    DizzyEgg's Avatar
                    DizzyEgg DizzyEgg is offline
                       
                      Join Date: Feb 2014
                      Location: Poland
                      Age: 20
                      Gender: Male
                      Nature: Quiet
                      Posts: 711
                      Quote:
                      Originally Posted by MWisBest View Post
                      .
                      Why not use the RTC?
                      Reply With Quote
                        #14    
                      Old March 23rd, 2017 (7:09 PM). Edited March 31st, 2017 by MWisBest.
                      MWisBest MWisBest is offline
                         
                        Join Date: Mar 2017
                        Gender: Male
                        Posts: 19
                        Quote:
                        Originally Posted by DizzyEgg View Post
                        Why not use the RTC?
                        Well that's not the method the game intended to be used. There's clearly a reason they changed to the timer method in FR/LG rather than using the RTC method from R/S; Emerald was released after FR/LG and has this timer method built-in, they just forgot to run it on each reset.


                        Oh, and if anybody is interested, here's a version that seeds the RNG with a full 32-bit value (0x0 to 0xFFFFFFFF instead of 0x0 to 0xFFFF). Requires 2 routines this time.

                        Byte edits required:
                        1. At 0x402 change 00 24 04 70 to FE 46 00 47.
                        2. At 0x478 change 00 27 00 03 to XX XX XX 08, where XX XX XX is the location of the first routine (TimersEnable) +1 (e.x. if you insert it at 0x9C0D00, you'd put 01 0D 9C 08).
                        3. At 0xAAED0 change DD F6 02 08 to XX XX XX 08, where XX XX XX is the location of the second routine (EmeraldTimerPrngSeedAtMenu) +1 (see above).

                        There's an IPS patch attached too.

                        Spoiler:
                        Code:
                        .text
                        .align 2
                        .thumb
                        .thumb_func
                        .global TimersEnable
                        
                        main:
                        	push {lr}
                        	mov r0, #0x80
                        	ldr r1, .TM1CNT
                        	strh r0, [r1]
                        	mov r0, #0x84	@ set timer2 to increment when timer1 overflows ("count-up timing")
                        	ldr r1, .TM2CNT
                        	strh r0, [r1]
                        	pop {pc}
                        
                        .align 2
                        .TM1CNT:
                        	.word 0x04000106
                        .TM2CNT:
                        	.word 0x0400010A
                        Code:
                        .text
                        .align 2
                        .thumb
                        .thumb_func
                        .global EmeraldTimerPrngSeedAtMenu
                        
                        main:
                        	push {lr}
                        	
                        	@ disable the timers immediately so the values remain static
                        	mov r0, #0x00
                        	ldr r1, .TM1CNT
                        	strh r0, [r1]
                        	ldr r1, .TM2CNT
                        	strh r0, [r1]
                        	
                        	@ manually store the values into the rng and init values, half-word at a time
                        	ldr r0, .TM1D
                        	ldrh r0, [r0]
                        	ldr r1, .RNG_STATE_PART_1
                        	strh r0, [r1]
                        	ldr r1, .TIMER_RESULT_PART_1
                        	strh r0, [r1]
                        	
                        	ldr r0, .TM2D
                        	ldrh r0, [r0]
                        	ldr r1, .RNG_STATE_PART_2
                        	strh r0, [r1]
                        	ldr r1, .TIMER_RESULT_PART_2
                        	strh r0, [r1]
                        	
                        	@ reset rng frame counter to 0
                        	@ NOTE: the built-in rng seed function seems to think
                        	@       this value is at 0x020249BC, whereas the rng
                        	@       advancement routine says it's at 0x020249C0. lolwut
                        	mov r0, #0
                        	ldr r1, .RNG_FRAME_COUNTER
                        	strb r0, [r1]
                        	
                        	@ mov r0, #0 is required here as part of the routine this replaces,
                        	@ but it's already done above here now; just noted in case it's changed.
                        	ldr r1, .MENU_CB_THING
                        	bl bx_r1
                        	pop {r0}
                        	bx r0
                        
                        bx_r1:
                        	bx r1
                        
                        .align 2
                        .TM1D:
                        	.word 0x04000104
                        .TM1CNT:
                        	.word 0x04000106
                        .TM2D:
                        	.word 0x04000108
                        .TM2CNT:
                        	.word 0x0400010A
                        .RNG_STATE_PART_1:
                        	.word 0x03005D80
                        .RNG_STATE_PART_2:
                        	.word 0x03005D82
                        .RNG_FRAME_COUNTER:
                        	.word 0x020249C0
                        .TIMER_RESULT_PART_1:
                        	.word 0x02020000
                        .TIMER_RESULT_PART_2:
                        	.word 0x02020002
                        .MENU_CB_THING:
                        	.word 0x0802F6F4|1


                        EDIT: Optimized the original routines I posted and fixed a small bug. Size cut in half! :)

                        Code:
                        .text
                        .align 2
                        .thumb
                        .thumb_func
                        .global TimersEnable
                        
                        main:
                        	push {lr}
                        	ldr r1, .TIMER_REGISTER_BASE
                        	mov r0, #0x80
                        	strh r0, [r1, #0x06] @ TM1CNT
                        	mov r0, #0x84	     @ set timer2 to increment when timer1 overflows ("count-up timing")
                        	strh r0, [r1, #0x0A] @ TM2CNT
                        	pop {pc}
                        
                        .align 2
                        .TIMER_REGISTER_BASE:
                        	.word 0x04000100
                        Code:
                        .text
                        .align 2
                        .thumb
                        .thumb_func
                        .global EmeraldTimerPrngSeedAtMenu
                        
                        main:
                        	push {lr}
                        	
                        	@ disable the timers immediately so the values remain static
                        	mov r0, #0x00
                        	ldr r1, .TIMER_REGISTER_BASE
                        	strh r0, [r1, #0x06] @ TM1CNT
                        	strh r0, [r1, #0x0A] @ TM2CNT
                        	
                        	@ manually store seed into the rng state and init values because
                        	@ the built-in seed function does not read a full 32-bits
                        	ldrh r0, [r1, #0x04] @ TM1D
                        	ldrh r1, [r1, #0x08] @ TM2D
                        	lsl r1, #16          @ shift TM2D to be the upper 16-bits of the seed
                        	orr r0, r1           @ combine TM1D and the shifted TM2D into a full 32-bits
                        	ldr r1, .RNG_STATE
                        	str r0, [r1]
                        	ldr r1, .TIMER_RESULT
                        	str r0, [r1]
                        	
                        	@@ OPTIONAL: reset rng frame counter to 0
                        	@@           This value isn't ever read by the game, so it's not really
                        	@@           necessary to reset it unless you know what you're doing.
                        	@@ NOTE: the built-in rng seed function seems to think
                        	@@       this value is at 0x020249BC, whereas the rng
                        	@@       advancement routine says it's at 0x020249C0. lolwut
                        	@ mov r0, #0
                        	@ ldr r1, .RNG_FRAME_COUNTER
                        	@ str r0, [r1]
                        	
                        	@ if "mov r0, #0" is uncommented above here, comment the one below
                        	mov r0, #0
                        	ldr r1, .MENU_INIT_CB
                        	bl x_r1
                        	pop {r0}
                        	bx r0
                        
                        x_r1:
                        	bx r1
                        
                        .align 2
                        .TIMER_REGISTER_BASE:
                        	.word 0x04000100
                        .RNG_STATE:
                        	.word 0x03005D80
                        @@.RNG_FRAME_COUNTER:
                        @@	.word 0x020249C0
                        .TIMER_RESULT:
                        	.word 0x02020000
                        .MENU_INIT_CB:
                        	.word 0x0802F6F4|1
                        Attached Files
                        File Type: ips Emerald 32-bit TIMER RNG Fix.ips‎ (118 Bytes, 7 views) (Save to Dropbox)
                        Reply With Quote
                          #15    
                        Old March 29th, 2017 (6:47 AM). Edited March 31st, 2017 by MWisBest.
                        MWisBest MWisBest is offline
                           
                          Join Date: Mar 2017
                          Gender: Male
                          Posts: 19
                          One last option I whipped up: another 32-bit seed, bottom 16-bits is timer-based, but the upper 16-bits is RTC based like HackMew's original fix.

                          Byte edits required:
                          1. At 0x400 change 1D 48 00 24 04 70 to 00 F0 A8 F8 C0 46.
                          2. At 0xAAED0 change DD F6 02 08 to XX XX XX 08, where XX XX XX is the location of the routine (EmeraldTimerPrngSeedAtMenu) +1 (e.x. if you insert it at 0x9C0D00, you'd put 01 0D 9C 08).

                          Code:
                          .text
                          .align 2
                          .thumb
                          .thumb_func
                          .global EmeraldTimerAndRTCPrngSeedAtMenu
                          
                          main:
                          	push {lr}
                          	
                          	@ disable the timer immediately so the value remains static
                          	mov r0, #0x00
                          	ldr r1, .TIMER_REGISTER_BASE
                          	strh r0, [r1, #0x06] @ TM1CNT
                          	
                          	@ get the "RTC seed" into r1
                          	ldr r1, .GET_RTC_MINUTES
                          	bl x_r1
                          	lsr r1, r0, #16
                          	@ no need to chop off the upper 16-bits of r0 like the original, it's done for us later
                          	eor r1, r0
                          	
                          	@ get the "timer seed" into r0
                          	ldr r0, .TIMER_REGISTER_BASE
                          	ldrh r0, [r0, #0x04] @ TM1D
                          	
                          	@ make full seed in r0 (RTC seed as upper 16-bits)
                          	lsl r1, #16
                          	orr r0, r1
                          	
                          	@ manually store seed into the rng state and init values because
                          	@ the built-in seed function does not read a full 32-bits
                          	ldr r1, .RNG_STATE
                          	str r0, [r1]
                          	ldr r1, .TIMER_RESULT
                          	str r0, [r1]
                          	
                          	@@ OPTIONAL: reset rng frame counter to 0
                          	@@           This value isn't ever read by the game, so it's not really
                          	@@           necessary to reset it unless you know what you're doing.
                          	@@ NOTE: the built-in rng seed function seems to think
                          	@@       this value is at 0x020249BC, whereas the rng
                          	@@       advancement routine says it's at 0x020249C0. lolwut
                          	@ mov r0, #0
                          	@ ldr r1, .RNG_FRAME_COUNTER
                          	@ str r0, [r1]
                          	
                          	@ if "mov r0, #0" is uncommented above here, comment the one below
                          	mov r0, #0
                          	ldr r1, .MENU_INIT_CB
                          	bl x_r1
                          	pop {r0}
                          	bx r0
                          
                          x_r1:
                          	bx r1
                          
                          .align 2
                          .TIMER_REGISTER_BASE:
                          	.word 0x04000100
                          .RNG_STATE:
                          	.word 0x03005D80
                          @@.RNG_FRAME_COUNTER:
                          @@	.word 0x020249C0
                          .TIMER_RESULT:
                          	.word 0x02020000
                          .GET_RTC_MINUTES:
                          	.word 0x0802F664|1
                          .MENU_INIT_CB:
                          	.word 0x0802F6F4|1
                          Attached Files
                          File Type: ips Emerald 32-bit RTC+TIMER RNG Fix.ips‎ (99 Bytes, 23 views) (Save to Dropbox)
                          Reply With Quote
                          Reply

                          Quick Reply

                          Join the conversation!

                          Create an account to post a reply in this thread, participate in other discussions, and more!

                          Create a PokéCommunity Account

                          Sponsored Links
                          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

                          Forum Jump


                          All times are GMT -8. The time now is 3:21 AM.