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.

Reply
 
Thread Tools
  #1    
Old Posted July 3rd, 2014 (10:20 AM).
Warpten's Avatar
Warpten
 
Join Date: May 2014
Location: France
Age: 22
Gender: Male
(Sorry for the lack of links and pictures - The forum actually prevents me from pasting links until I've made fifteen posts)

So quite recently, I've been interested by the workings of Feebas's spawning mechanics in R/S/E. I may not have a lot of experience in Pokémon Hacking, but I have some in reversing, and I figured this'd be a way to get me started.

A lot of Googling has taught me the following:
- Speaking to the NPC in Dewford Town will update the tiles if the new "trendy" sentence passed is accepted (Which is itself something luck-based)
- Saving the game and rebooting keeps the "Feebas tiles".
- Using the same trendy sentence of two games does not yield the same tiles.
- On Feebas tiles, you can either get Feebas or Carvanha.
- There are only 6 Feebas tiles.

I noticed that some save data blocks are not yet documented on Bulbapedia, so I figured that the data would be stored in there. Since tiles persist during saves, the game either saves Feebas tiles raw, or uses some vodoo to achieve the same in a compact way.

Starting from here, everything relates to Pokemon Emerald (U).

I've started by taking a look at Route 119. Looking at the Wild Pokémon Encounters, i saw Magikarp, Tentacool, and ... a ton of Carvanhas.

img11.hostingpics.net/pics/783244Feebas1.png

My first intuiton was then "Oh, the game probably rolls a number and changes one of these encounters to a Feebas if the roll is successful."
I imagined that the map would do something Feebas-related on its scripts - so I went ahead and took a look inside:

In the spoiler below is the result of the map scripts - Nothing useful in there from what I can see, so skip ahead for the related-stuff.
Spoiler:
Code:
#org 0x81F442F
'-----------------------------------
checkflag 0x8C1
if true call 0x81F4439 ' Flag is set
end

#org 0x81F4439
'-----------------------------------
special2 LASTRESULT 0xB7
compare LASTRESULT 0x7
if != jump 0x827374E ' Not Equal To, return out
disappear LASTTALKED
return

#org 0x827374E
'-----------------------------------
return
(This is script type 03.)

Few things caught me offguard. First and foremost, even thought most of this is self-explanatory, I failed to understand what special2 LASTRESULT 0xB7 and disappear LASTTALKED did. I brained for a bit, and realized this was probably related to the trainers in tall tall grass from which you only see the top of the head. So I skipped ahead.

Code:
#org 0x81F444D
'-----------------------------------
call 0x8271ED7
call 0x8271EFB
compare 0x40B3 0x1
if == call 0x81F4466 ' Equal To
special 0x146
end

#org 0x8271ED7
'-----------------------------------
checkgender
compare LASTRESULT BOY
if == jump 0x8271EEF ' Equal To
compare LASTRESULT 0x1
if == jump 0x8271EF5 ' Equal To
end

#org 0x8271EEF
'-----------------------------------
setvar 0x4010 0x69
return

#org 0x8271EFB
'-----------------------------------
checkgender
compare LASTRESULT BOY
if == jump 0x8271F13 ' Equal To
compare LASTRESULT 0x1
if == jump 0x8271F19 ' Equal To
end

#org 0x8271F13
'-----------------------------------
setvar 0x4013 0x6A
return

#org 0x8271F19
'-----------------------------------
setvar 0x4013 0x65
return

#org 0x81F4466
'-----------------------------------
setflag 0x37D
clearflag 0x37C
setvar 0x40B3 0x2
return

#org 0x8271EF5
'-----------------------------------
setvar 0x4010 0x64
return
This is the second script block (type 05). looking at it, all it did was some black magic regarding the player's gender. I assumed it was just setting up the rival sprite for the bridge event (Advance Map displays the sprite as a variant of the crazy talking NPC in Mauville City), and setting up for the Weather Center.


At this point i just went to take a look at the Trendy Sentence NPC's script.

Code:
#org 0x81E9922
'-----------------------------------
lock
faceplayer
call 0x8271E8B
msgbox 0x81EA136 ' I like what's hip, h...
callstd MSG_YESNO ' Yes/No message
compare LASTRESULT YES
if == jump 0x81E9948 ' Equal To
compare LASTRESULT 0x0
if == jump 0x81E9952 ' Equal To
end

#org 0x8271E8B
'-----------------------------------
CMD_2D
setvar 0x8004 0x0
special 0x81
return

#org 0x81E9948
'-----------------------------------
msgbox 0x81EA491 ' Yeah, absolutely rig...
callstd MSG_NOCLOSE ' Non-closing message
release
     ' Release commands close any open messages
end

#org 0x81E9952
'-----------------------------------
msgbox 0x81EA242 ' Hunh?\nIt's not the ...
callstd MSG_NOCLOSE ' Non-closing message
setvar 0x8004 0x9
call 0x8271E7C
lock
faceplayer
compare LASTRESULT 0x1
if == jump 0x81E997D ' Equal To
compare LASTRESULT 0x0
if == jump 0x81E9994 ' Equal To
end

#org 0x8271E7C
'-----------------------------------
fadescreen FADEOUT_BLACK
special 0x62
fadescreen FADEIN_BLACK
return

#org 0x81E997D
'-----------------------------------
CMD_C3 0x2
compare 0x8004 0x0
if == jump 0x81E999E ' Equal To
msgbox 0x81EA2AA ' Hunh?\n"\v\h03["]?\p...
callstd MSG_NOCLOSE ' Non-closing message
release
     ' Release commands close any open messages
end

#org 0x81E999E
'-----------------------------------
msgbox 0x81EA3FE ' Hmm[.]\n"\v\h03,["] ...
callstd MSG_NOCLOSE ' Non-closing message
release
     ' Release commands close any open messages
end

#org 0x81E9994
'-----------------------------------
msgbox 0x81EA443 ' Well, if you hear of...
callstd MSG_NOCLOSE ' Non-closing message
release
     ' Release commands close any open messages
end


#org 0x81EA136
= I like what's hip, happening, and trendy.\nI'm always checking it out.\pListen, have you heard about this new\n"\v\h02["]?\pThat's right!\nOf course you know!\pI mean, sheesh,\n"\v\h02["][.]\lIt's the hottest thing in cool!\pWherever you're from,\n"\v\h02["]\lis the biggest happening thing, right?

#org 0x81EA491
= Yeah, absolutely right!\p"\v\h02["] is the\ndefinition of "in["] right now.

#org 0x81EA242
= Hunh?\nIt's not the hip and happening thing?\pWell, hey, you have to tell me,\nwhat's new and what's "in["]?

#org 0x81EA2AA
= Hunh?\n"\v\h03["]?\p[.] [.]\p[.]Uh[.] Yeah! That's right!\nYeah, I knew that! Knew it all along!\pOf course I know about that!\n"\v\h03,["] right?\pYeah, that's it, it's there!\nIsn't "\v\h03["]\lthe coolest, or what?\pIt's the hippest thing in hip.\nYou think I'd not know about it?\p"\v\h02["][.]\nIt's, like, so five minutes ago.\pNow, "\v\h03["] is\nwhat's vital and in tune with the times!

#org 0x81EA3FE
= Hmm[.]\n"\v\h03,["] huh?\pBut personally, I think\n"\v\h02["]\lis what's real in cool.

#org 0x81EA443
= Well, if you hear of any happening new\ntrends, come share them with me, okay?
0x81E12AA is the success string, which is called by this chunk of code

Code:
#org 0x81E997D
'-----------------------------------
CMD_C3 0x2
compare 0x8004 0x0
if == jump 0x81E999E ' Equal To
msgbox 0x81EA2AA ' Hunh?\n"\v\h03["]?\p...
Now this beats me. What does CMD_C3 0x2 do ? I get that if data at 0x8004 is equal to 0, the NPC will refuse the new Trendy String. I assume this is calling some magic that rolls to see if the input string will be accepted, and then seeds the "Feebas tiles".

So from there, where should I look ? I'm soon going to pop open the ROM in Ida Pro and see what i can find, but I only have a vague idea where to look (save file loaders, most probably)

I'd definitely love some help on this, for the sake of documenting, reversing, and fun! So thanks for all your inputs :D
Reply With Quote
  #2    
Old Posted July 4th, 2014 (06:11 AM).
Warpten's Avatar
Warpten
 
Join Date: May 2014
Location: France
Age: 22
Gender: Male
It appears that people over at Smogon have already taken a look at this; see end of post for hidden links (Silly 15 messages limit).

I won't repaste everything, but here is the most important part

Code:
ROM:080B4A98 sub_80B4A98                             ; CODE XREF: ROM:loc_80B4A1Ap
ROM:080B4A98                 LDR     R2, =0x2038C04
ROM:080B4A9A                 LDR     R1, [R2]
ROM:080B4A9C                 LDR     R0, =0x41C64E6D
ROM:080B4A9E                 MULS    R0, R1
ROM:080B4AA0                 LDR     R1, =0x3039
ROM:080B4AA2                 ADDS    R0, R0, R1
ROM:080B4AA4                 STR     R0, [R2]
ROM:080B4AA6                 LSRS    R0, R0, #0x10   ; (Offset 0x2038C04) = (0x41C64E6D * seed + 0x3039)
ROM:080B4AA8                 BX      LR
ROM:080B4AA8 ; End of function sub_80B4A98


               LSLS    R0, R0, #0x10   ; Beginning of feebas stuff
ROM:080B49F4                 LSRS    R0, R0, #0x10
ROM:080B49F6                 CMP     R0, #0x31
ROM:080B49F8                 BLS     loc_80B4A08
ROM:080B49FA                 B       loc_80B4A7A     ; If calculated slot is not feebas, skip determination routine
ROM:080B49FA ; ---------------------------------------------------------------------------
ROM:080B49FC dword_80B49FC   DCD 0x3005D8C           ; DATA XREF: ROM:080B4990r
ROM:080B4A00 off_80B4A00     DCD unk_8553A7C         ; DATA XREF: ROM:080B49BCr
ROM:080B4A04 ; ---------------------------------------------------------------------------
ROM:080B4A04
ROM:080B4A04 loc_80B4A04                             ; CODE XREF: ROM:080B4A6Ej
ROM:080B4A04                 MOVS    R0, #1
ROM:080B4A06                 B       loc_80B4A7C
ROM:080B4A08 ; ---------------------------------------------------------------------------
ROM:080B4A08
ROM:080B4A08 loc_80B4A08                             ; CODE XREF: ROM:080B49F8j
ROM:080B4A08                 LDR     R0, =0x3005D8C
ROM:080B4A0A                 LDR     R0, [R0]
ROM:080B4A0C                 LDR     R3, =0x2E6A
ROM:080B4A0E                 ADDS    R0, R0, R3
ROM:080B4A10                 LDRH    R0, [R0]        ; Feebas seed is in R0
ROM:080B4A12                 BL      sub_80B4AB8
ROM:080B4A16                 MOVS    R5, #0          ; R5 (loop counter) = 0
ROM:080B4A18                 LDR     R6, =0x1BF      ; R6 = 0x01BF
ROM:080B4A1A
ROM:080B4A1A loc_80B4A1A                             ; CODE XREF: ROM:080B4A4Cj
ROM:080B4A1A                 BL      sub_80B4A98     ; Stores recalculated seed at 0x2038C04
ROM:080B4A1E                 LSLS    R1, R5, #1      ; R1 = 0
ROM:080B4A20                 MOV     R2, SP          ; R2 = SP
ROM:080B4A22                 ADDS    R4, R2, R1      ; R4 = R2 + (R1 = 0)
ROM:080B4A24                 LSLS    R0, R0, #0x10
ROM:080B4A26                 LSRS    R0, R0, #0x10
ROM:080B4A28                 MOVS    R1, R6          ; R1 = R6 = 0x01BF
ROM:080B4A2A                 BL      sub_82E7BE0     ; R0 = R0 % R1
ROM:080B4A2E                 STRH    R0, [R4]        ; Stores R0 (Current tile) on stack
ROM:080B4A30                 LSLS    R0, R0, #0x10
ROM:080B4A32                 CMP     R0, #0          ; If R0 == 0
ROM:080B4A34                 BNE     loc_80B4A38     ; Load calculated feebas tile into R0
ROM:080B4A36                 STRH    R6, [R4]        ; Store 0x1BF instead
ROM:080B4A38
ROM:080B4A38 loc_80B4A38                             ; CODE XREF: ROM:080B4A34j
ROM:080B4A38                 LDRH    R0, [R4]        ; Load calculated feebas tile into R0
ROM:080B4A3A                 SUBS    R0, #1          ; R0 -= 1
ROM:080B4A3C                 LSLS    R0, R0, #0x10   ; These LSLS and LSLR clear a bit
ROM:080B4A3E                 LSRS    R0, R0, #0x10
ROM:080B4A40                 CMP     R0, #2          ; Tile type. If it's <= 3, don't increment the loop counter (R5), so generate new tiles to check against
ROM:080B4A42                 BLS     loc_80B4A4A
ROM:080B4A44                 ADDS    R0, R5, #1      ; R0 = R5 + 1
ROM:080B4A46                 LSLS    R0, R0, #0x18
ROM:080B4A48                 LSRS    R5, R0, #0x18   ; R5 = R0 (This basically does ++R5)
ROM:080B4A4A
ROM:080B4A4A loc_80B4A4A                             ; CODE XREF: ROM:080B4A42j
ROM:080B4A4A                 CMP     R5, #6          ; If R5 < 6
ROM:080B4A4C                 BNE     loc_80B4A1A     ; Calculate another feebas tile to check against
ROM:080B4A4E                 MOV     R3, R9          ; R3 = R9
ROM:080B4A50                 MOVS    R1, #0          ; R1 = 0
ROM:080B4A52                 LDRSH   R0, [R3,R1]     ; R0 = rod->map.x (Fishing X coordinate)
ROM:080B4A54                 MOV     R2, R8
ROM:080B4A56                 MOVS    R3, #0
ROM:080B4A58                 LDRSH   R1, [R2,R3]     ; R1 = rod->map.y (Fishing Y coordinate)
ROM:080B4A5A                 MOVS    R2, R7          ; R2 = R7
ROM:080B4A5C                 BL      sub_80B48C4     ; From current fishing coordinates return tile number in R0
ROM:080B4A60                 LSLS    R0, R0, #0x10   ; R0 = R0 << 0x10
ROM:080B4A62                 LSRS    R1, R0, #0x10   ; R1 = R0 >> 0x10
ROM:080B4A64                 MOVS    R5, #0          ; R5 = 0
ROM:080B4A66
ROM:080B4A66 loc_80B4A66                             ; CODE XREF: ROM:080B4A78j
ROM:080B4A66                 LSLS    R0, R5, #1      ; R0 = R5 << 0x1
ROM:080B4A68                 ADD     R0, SP          ; R0 += SP
ROM:080B4A6A                 LDRH    R0, [R0]        ; Load *R0 into R0
ROM:080B4A6C                 CMP     R1, R0          ; Compare R0 and R1
ROM:080B4A6C                                         ; If result flag is set to 1, this is a feebas tile. BREAKPOINT HERE
ROM:080B4A6E                 BEQ     loc_80B4A04     ; feebasTile = true
ROM:080B4A70                 ADDS    R0, R5, #1      ; ...
ROM:080B4A72                 LSLS    R0, R0, #0x18   ; ...
ROM:080B4A74                 LSRS    R5, R0, #0x18   ; ... Increments R5
ROM:080B4A76                 CMP     R5, #5          ; if  R5 < 6 ...
ROM:080B4A78                 BLS     loc_80B4A66     ; ... loop again
ROM:080B4A7A
ROM:080B4A7A loc_80B4A7A                             ; CODE XREF: ROM:080B499Cj
ROM:080B4A7A                                         ; ROM:080B49FAj
ROM:080B4A7A                 MOVS    R0, #0          ; R0 is not a feebas tile.
ROM:080B4A7C
ROM:080B4A7C loc_80B4A7C                             ; CODE XREF: ROM:080B4A06j
ROM:080B4A7C                 ADD     SP, SP, #0x10
ROM:080B4A7E                 POP     {R3,R4}
ROM:080B4A80                 MOV     R8, R3
ROM:080B4A82                 MOV     R9, R4
ROM:080B4A84                 POP     {R4-R7}
ROM:080B4A86                 POP     {R1}
ROM:080B4A88                 BX      R1
From there, we can do the following:
if result of 080B4A6C != 0 // Feebas tile
--> execute 080B4A4E to 080B4A58 to get tile X and Y coordinates
--> highlight tiles on the map.

However, one more place where I am clueless: Are there any emulators out there that allow to write small programs in any language, that then interpretes given code, and spits out the result in a console ? I could go slowpoke and breakpoint all three instructions (if feebas tile, tile X, tile Y) and store tile X & Y values IFF feebas tile is true, but that'd be slow since I'm going to loop over all the tiles in the river.

Alternatively, one can easily extract the seed, redo what this thing does in C, and compute the tiles on the fly.

This was done on a Pokemon Emerald (U) ROM.

Links used:
(Smogon) forums/ threads/ past-gen-rng-research.61090/ page-34 (Huge kudos to you, good sir!)
__________________
Reply With Quote
  #3    
Old Posted July 13th, 2014 (09:44 AM).
Warpten's Avatar
Warpten
 
Join Date: May 2014
Location: France
Age: 22
Gender: Male
More looking at this in VBA's debugger told me that the value at the actual pointer changes everytime you fish - looks like it's actually moved around: I saw it a few bytes further away, then it dissapeared from the memory viewer's screen for some time, then reappeared. So reading it from memory is not actually relevant at all time. I'll toy more with this.

I don't think I'll write a VBA addin for that though, because A) code in C is already there in the link on my previous post, and you can just put it on ideone.com, enter initial seed, and compute your tiles, and B) reason A is long enough.
__________________
Reply With Quote
  #4    
Old Posted July 13th, 2014 (09:46 AM).
Shimokane's Avatar
Shimokane
 
Join Date: Oct 2013
Gender: Male
Man, Feebas was so darn hard to catch..... I wonder if they will do the same in ORAS.... :/
__________________
2406-5121-3908
ShimokaneShimokun
Shiny Value: 35!!!

Please click these dragons to help them grow :3
Reply With Quote
  #5    
Old Posted July 15th, 2014 (08:25 AM).
Team Fail's Avatar
Team Fail
See that, Aster?
Community Supporter
 
Join Date: May 2009
Age: 19
Gender: Male
Nature: Brave
Have you taken a look using the Debugger Pokémon Ruby? There's a testing menu option that shows you the Feebas fishing spots. And it works, too. I've been able to actually fish for them and catch them in their locations.
__________________

You are challenged by Lorekeeper Zinnia!
Pairs | Twitter | Alt | Alt II | PHO
Reply With Quote
  #6    
Old Posted July 17th, 2014 (01:56 AM).
Warpten's Avatar
Warpten
 
Join Date: May 2014
Location: France
Age: 22
Gender: Male
Quote:
Originally Posted by Team Fail View Post
Have you taken a look using the Debugger Pokémon Ruby? There's a testing menu option that shows you the Feebas fishing spots. And it works, too. I've been able to actually fish for them and catch them in their locations.
I had no clue this was leaked, I'll dig it! Thanks for sharing the info
__________________
Reply With Quote
Reply
Quick Reply

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
Minimum Characters Per Post: 25



All times are UTC -8. The time now is 09:14 PM.


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.