You are not logged in.
Pages: 1
=====================================
R/B: Editing the "Starter choice" script correctly
=====================================
You need:
- hex editor OR assembler;
- list of Pokemon IDs (link)
OAK's LAB
In the map-script you have to edit the IDs' checks that affect Rival's movement paths:
1) IF = $b1 [charmander] THEN "path-to-squirtle"
2) IF = $b0 [squirtle] THEN "path-to-bulbasaur"
3) ELSE "path-to-charmander
Map-script:
There's an arrow next the locations that need to be edited.
(...)
ROM7:4C80 FA 17 D7 ld a,(d717)
ROM7:4C83 FE B0 cp a,b0 ;<---
ROM7:4C85 28 06 jr z,4c8d
ROM7:4C87 FE B1 cp a,b1 ;<---
ROM7:4C89 28 1D jr z,4ca8
ROM7:4C8B 18 38 jr 4cc5
(...)
ROM7:4DC4 FA 15 D7 ld a,(d715)
ROM7:4DC7 FE B1 cp a,b1 ;<---
ROM7:4DC9 20 04 jr nz,4dcf
ROM7:4DCB 3E 01 ld a,01
ROM7:4DCD 18 0A jr 4dd9
ROM7:4DCF FE 99 cp a,99 ;<---
ROM7:4DD1 20 04 jr nz,4dd7
ROM7:4DD3 3E 02 ld a,02
ROM7:4DD5 18 02 jr 4dd9
ROM7:4DD7 3E 03 ld a,03
ROM7:4DD9 EA 5D D0 ld (d05d),a
(...)
Text-scripts (pokeballs):
By editing these you'll modify the pokedex page displayed when you click on the pokeballs you find on the table and the starter's choice loaded in RAM $d715 and $d717.
ROM7:5102 08 db 08
ROM7:5103 3e b1 ld a,b1 ;<---
ROM7:5105 ea 3d cd ld (cd3d),a
ROM7:5108 3e 03 ld a,03
ROM7:510a ea 3e cd ld (cd3e),a
ROM7:510d 3e b0 ld a,b0 ;<---
ROM7:510f 06 02 ld b,02
ROM7:5111 18 20 jr 5133
ROM7:5113 08 db 08
ROM7:5114 3e 99 ld a,99 ;<---
ROM7:5116 ea 3d cd ld (cd3d),a
ROM7:5119 3e 04 ld a,04
ROM7:511b ea 3e cd ld (cd3e),a
ROM7:511e 3e b1 ld a,b1 ;<---
ROM7:5120 06 03 ld b,03
ROM7:5122 18 0f jr 5133
ROM7:5124 08 db 08
ROM7:5125 3e b0 ld a,b0 ;<---
ROM7:5127 ea 3d cd ld (cd3d),a
ROM7:512a 3e 02 ld a,02
ROM7:512c ea 3e cd ld (cd3e),a
ROM7:512f 3e 99 ld a,99 ;<---
ROM7:5131 06 04 ld b,04
Of course you still need to edit Rival's parties (located starting at address $3A1E4) so that they match your changes.
Also there are other cases during the game where RAM:D717 (player's starter choice) and RAM:D715 (rival's starter choice) is read, so you'll have to edit the comparisons made in those scripts if you want that the battles' scripts work correctly, accordingly to the edited starters.
You could, for example, search for the instances of "FA17D7" ( = "ld a,[$d717]"), using any hex editor's search-function, and then see if there's any comparisons of $B0 or $B1 or $99 and edit those bytes accordingly. This if you just want to edit the game's script as minimally as possible, obviously.
Last edited by Sawakita (2011-07-16 21:48:35)
Offline
Simply following these instructions doesn't seem to produce the desired outcome. This DOES successfully change the starters that the player will receive and the rival will use in battle, however, there are a couple of wrinkles to be smoothed out.
First, and least importantly, it should be noted that you will need to change the text that appears when asked if you want to pick the Pokemon. "So! You want the fire Pokemon, CHARMANDER?" Obviously, you'll want to change this to the desired Pokemon.
Second, when the Pokemon's dex entry is brought up, it isn't complete. It only shows the new starter's sprite, but none of the description/height/weight.
Third, if you choose the third pokeball (on the far right of the table), it doesn't disappear after you receive the Pokemon. It does disappear for the other two pokeballs, though.
Unfortunately, I don't know how to fix these problems. Just thought I would make them known.
Offline
First, and least importantly, it should be noted that you will need to change the text that appears when asked if you want to pick the Pokemon. "So! You want the fire Pokemon, CHARMANDER?" Obviously, you'll want to change this to the desired Pokemon.
Load a table file and go to 94E07. There aren't any "text-from-RAM commands", like Sawakita mentioned here.
I tried it and got a problem with the movement and hide sprite-script. I took the middle Pokeball (I guess the Pokemon aren't necessary, changed them to Machop -> Onix -> Farfetch'd for testing) and Gary walked inside me and took the right Pokeball. Same for the left Pokeball, he went to the right and took the middle Pokeball. Only the other place worked. It seems like there's a special relation between Gary's position and his choice.
Last edited by tekcoR (2011-07-17 17:41:17)
Cya
Offline
The game temporarily turns on flags for owned pokemon; said flags are located in RAM starting at $D2F7 (check RAM Map). So, for example, first byte contains flags for the following eight pokemon:
1st bit = Bulbasaur 1
2nd bit = Ivysaur 1 (this might be a programming mistake)
3rd bit = Venusaur 0
4th bit = Charmander 1
5th bit = Charmeleon 0
6th bit = Charizard 0
7th bit = Squirtle 1
8th bit = Wartortle 0
NOTE:
[01001011] (binary format) = [4B] (hexadecimal format)
$5c0dc: Here it turns ON chosen flags.
ld a,$4b
ld [$d2f7],a
$5c0e6: here it turns OFF those flags to the original value, zero (notice that "XORing a" equals to loading a zero in "a").
xor a
ld [$d2f7],a
As you see this would require a little ASM hacking if your new starters's dex-entries aren't affected by flags located in the same single byte. You could also reorder all the pokemon data and edit the pokedex order so that your new starters are actually located in the starters' places.
Now, about errors in Gary's movements: this is strange, because I tested all the possible choices and I got all the movements working perfectly. Are you sure you edited the bytes correctly? You have to edit every different instance with the respective substitute, you might have unawares switched some of them.
Offline
The game temporarily turns on flags for owned pokemon; said flags are located in RAM starting at $D2F7 (check RAM Map). So, for example, first byte contains flags for the following eight pokemon:
As you see this would require a little ASM hacking if your new starters's dex-entries aren't affected by flags located in the same single byte. You could also reorder all the pokemon data and edit the pokedex order so that your new starters are actually located in the starters' places.
You clarified that up very nicely, and this is an interesting bit of code! It's too bad that the starters I was planning on using aren't within 8 dex entries of each other.
Now, about errors in Gary's movements: this is strange, because I tested all the possible choices and I got all the movements working perfectly. Are you sure you edited the bytes correctly? You have to edit every different instance with the respective substitute, you might have unawares switched some of them.
You're correct about this. I had accidentally changed a byte a little later in the code, and when I changed it back to its original state, the movement worked fine.
Offline
Great tutorial on this Sawakita, it's been a pretty persistant issue with hacks since the very beginning, you're very good at explaining things! However, one issue, I don't know if I'm missing something, but on changing the data in all the locations you mention, plus searching the ROM for locations where D717 and D715 are checked and adjusting them accordingly, I get strange things happening with the rival battles later in the game. Well the first one on Route 22 anyway, seeing as that's the first one I tested.
The rival doesn't use any of the three possible sets of Pokémon, instead calls garbage data from elsewhere in the ROM, which dependant on the starter Pokémon you set, can be any combination of Pokémon or glitch Pokémon. I was just wondering why changing the comparisons with D717 and D715 is affecting the pointer to the correct data!
Sorry for this long incoherant post, it's late lol!!
For Pokémon ROM hacking tools, please visit my site www.swamperttools.co.nr!
Check out my latest tool release, a trainer editor for Pokémon Red and Blue!
Offline
searching the ROM for locations where D717 and D715 are checked and adjusting them accordingly, I get strange things happening with the rival battles later in the game. Well the first one on Route 22 anyway, seeing as that's the first one I tested.
The rival doesn't use any of the three possible sets of Pokémon, instead calls garbage data from elsewhere in the ROM, which dependant on the starter Pokémon you set, can be any combination of Pokémon or glitch Pokémon. I was just wondering why changing the comparisons with D717 and D715 is affecting the pointer to the correct data!
Could you tell me exactly what you edited? I'd like to know, so we can find out what went wrong (my guess, as of now, is that you edited the trainer-sets choices into some out-of-range value, or maybe that you didn't mantain the compatibility among the various ID checks).
Regarding Route 22's script: we know that the player meets the Rival (or, can meet, since if I recall right, the first time that you meet Rival in route 22 can be skipped) twice. Thus there are two different data table (for the two battle scripts) that are structured like dictionaries:
;1st time (Rival has 2 pokemon)
;address $50FAF
B1 04
99 05
B0 06
;2nd time (Rival has 6 pokemon)
;address $510D9
B1 0A
99 0B
B0 0C
As you can see, the first byte is the possible Rival's starter that will be compared with [$D715] in the ASM "script", while the second byte is the trainer-set. If you're wondering where the trainer type is defined, this is the code:
;1st time
RO14:4F9E 3E E1 ld a,e1
RO14:4FA0 EA 59 D0 ld (d059),a
;2nd time
RO14:50C8 3E F2 ld a,f2
RO14:50CA EA 59 D0 ld (d059),a
RAM location $D059 affects what pokemon/trainer you will meet in battle (there is a check inside the game engine that loads a "wild battle" or a "trainer battle" accordingly to the value stored in $D059 (this value must not be zero): if it's less than $C8 then there will be a wild-battle, else there will be a trainer-battle). The value $E1 correspond to "Rival 1", while $F2 is "Rival 2" (they are both the same obnoxious person, but their sprites and pay-outs vary).
Offline
I've got to say, that you're bang on the money again. Whilst editing the comparisons with D717 and D715 by searching the string 'FA17D7' and 'FA15D7' and adjusting the comparisons made afterwards, I did not edit these tables that you're speaking of. In fact, I found 7 instances in the ROM of 'FA15D7' which had checks against the starter Pokémon, so I only changed these, thinking that they must relate to the seven rival battles in the game.
What I see know, is that as these 'dictionaries' where not adjusted accordingly, the game searched in the ROM for example to the next instance of the Pokémon Index number after the start of the dictionary, and then pulled the trainer set from the following byte, giving garbage data.
I'll take a look through the ROM and document here if you like all the locations that need to be edited!
Thanks very much for your reply, solved the problem as usual :D
EDIT: As an update, I've been through the ROM, and have now found all the locations that the script needs to be changed to not cause the game to glitch
If anybody is interested, here they are!
For PokéBall 1 in Oak's Lab (Normally Charmander) The following locations need to be edited with the Index number of the Pokémon that will replace Charmander as the starter.
$1CC84
$1D10E
$1D126
$39CF8
$50FB3
$510DD
For PokéBall 2 in Oak's Lab (Normally Squirtle) The following locations need to be edited with the Index number of the Pokémon that will replace Squirtle as the starter.
$1CC88
$1CDC8
$1D11F
$1D104
$19591
$50FAF
$510D9
$51CAF
$6060E
$61450
$75F9E
For PokéBall 3 in Oak's Lab (Normally Bulbasaur) The following locations need to be edited with the Index number of the Pokémon that will replace Bulbasaur as the starter.
$1CDD0
$1D130
$1D115
$19599
$39CF2
$50FB1
$510DB
$51CB7
$60616
$61458
$75FA6
A bit more than the old starter changers used to change eg. 3 bytes!!
Hope this helps some people!!
Last edited by swampert22 (2011-11-03 08:38:56)
For Pokémon ROM hacking tools, please visit my site www.swamperttools.co.nr!
Check out my latest tool release, a trainer editor for Pokémon Red and Blue!
Offline
I realize I'm trawling some rather old threads, so pardon me for that, but I think its also handy to keep the discussion all in one place.
I wrote a couple new lines to predefs17.asm, the StarterDex code, to accomodate my new PokeMon as discussed above; its as follows:
StarterDex: ; 5c0dc (17:40dc)
ld a,%00000001 ;Flag #152 (the last entry) as owned
ld [$d309],a
ld a,%00100100 ;Flag #155 and #158 as owned
ld [$d30a],a
predef ShowPokedexData
xor a ; unset starter flags
ld [$d309],a
ld [$d30a],a
ret
The addresses d309 and d30A are the specific bytes containing the bits for Pokemon 145-160 in the PokemonOwned array, allowing me access to tag 152, 155, and 158 as the starter pokemon. I appear to be able to write to $d30a just fine and I can view the two starter pokemon pokedex entries as intended. I can't seem to actually register the entry for #152 however. Any ideas?
Pokemon: Project Neo A Pokemon hack 15 years in the making...
Offline
Flag 152 is %10000000.
So you don't have to work it out by hand each time you change it you could do something like this:
set_owned: macro
rept _NARG
address = wPokedexOwned + \1 / 8
ld a, [address]
or 1 << (\1 % 8)
ld [address], a
shift ; next arg
endr
endm
set_owned STARTER1, STARTER2, STARTER3
Having to set flags for Pokedex entries is a little silly, so you could also add a clause to always show the full dex (i.e. if [wForceDex] is 1), through something like IsPokemonBitSet in engine/menu/pokedex.asm.
Offline
Weird...because the other two (155 and 158), in what appears to be the "wrong" spaces if that is right, work just fine...if 152 is the first entry, that should be just like the initial line (10010010) for the original starters.
Pokemon: Project Neo A Pokemon hack 15 years in the making...
Offline
pokered flag arrays start from the least significant bit (1 << x % 8).
Offline
Oh now that's fun then, because the second byte works out to read the same from either direction. Explains why that works :D Thanks for that~
Pokemon: Project Neo A Pokemon hack 15 years in the making...
Offline
Pages: 1