darkbeast887

Help with Pokemon GBA Block Checksum

11 posts in this topic

Im working on a personal project for some colleagues and myself that allows our Android emulators to trade pokemon. It works by uploading the saves to my private server. From there the server handles the trades.

I've already managed to unscramble the GBA save blocks and unencrypt the pokemon data, so I can read all the pokemon data, but I can't figure out how the checksum is equated so the server can't trade our pokemon yet.

I've come close by taking the sum of 0xF80 bytes of data and modulus that with 0xFFFF, however this gets me off by 0x40-0x140.

If someone could please tell me how Pokemon GBA games calculate their block checksums, it would be very helpful.

Thanks!

P.S. I accientally posted this in the saves section at first thinking it was the right section. If someone could tell me how to delete it , I would appreciate it.

Share this post


Link to post
Share on other sites

Thank you for your quick reply.

I have already checked out those links and LoadingNOW's PSavFix, but unfortunately Im not very skilled at coding in C, so its a little hard to read.

Also, the first time I got that code, parts were missing so when I showed some people I know they couldn't make sense of it either. This completed version should help me.

Again, thanks for your help!

Share this post


Link to post
Share on other sites

darkbeast887 did you made that program? to be honest I want to do the same but i'm a little lazy jaja, so maybe you can share your code with me, or maybe give me some helps. In your program is necessary to upload the save, the android device can't do that?? sorry for my bad english i'm a spanish speaker

Share this post


Link to post
Share on other sites

If you know some C then you can take loadingNOW's PSavFix code and adapt it to suit your needs.

The code can be found at http://projectpokemon.org/forums/showthread.php?15666-Some-questions-about-save-files

In the end, I decided to change course and made a personal online Pokemon GBA stat checker which someone can upload their save to and check all the stats of their pokemon. It was a lot easier than transfering my save from my android to my computer and running it through other programs. The site allows me to download other people's uploaded pokemon also.

However, I am now making a shell script for Linux based machines (including android) that trades pokemon. It's not as polished as an app, but it's written to be run on pretty much any linux machine.

If you don't know C or are having troubles understanding the checksum, then I might be able to help you depending on what you are coding your program in.

Good luck.

Share this post


Link to post
Share on other sites

oh your idea of making 3th gen trade in andorid is what i was looking for. My first idea was that but i didn't know how i can do it but if you can please let me notice, i understand c (some parts but with your help i sure that i will do it). do you want to do an emulator or how will you trade pokemons? i want and hope your script will be quickly. thanks for everything!!!

Share this post


Link to post
Share on other sites

a little question more can you pass me the offset of the things in the save? like the ID OT Name, secret ID, party begin and end, and the others things please

Share this post


Link to post
Share on other sites

Here is my script to trade Pokemon with the android phones. It's pretty primitive and written in bash.

Just a few notes about it: The android terminal can't handle many of the same things that other terminals can handle, such as arrays. Because of this, the script had to be written a bit more inefficient than what it could have been. However, a plus to this is that it is fairly portable, meaning that you can run this script on many other linux machines, such as latptops or computers. Also, to make rebuilding the save more efficient, it creates 32 seperate files of the GBA save's 32 blocks. It does it's best to remove these at the end of the script, but I've noticed that it doesn't work on all machines.

To use this script you need to have a rooted android, busybox installed, and an Android terminal emulator installed.

Save the script as something like PokemonTrade.sh

Usage: sh PokemonTrade.sh [save file location] [kanto or hoenn]

After you start the script, your six party pokemon will be shown to you; select one.

Next, you will be asked if you want to be a server or a client; choose one and have your friend choose the opposite.

The client should type the server's ip into their terminal.

Both people should choose 'yes' when asked if they want to trade their pokemon for their offered pokemon.

Finally, the script rebuilds the GBA save file, calculates the new checksum, and writes the new save to replace the old one.

Now realize that I haven't really tested this script on many different machines, and there are most likely a few bugs in it.

It also uses netcat as it's server and client which certain schools and businesses don't like you to use if you are on their wifi, so be aware.

Also, because of the way the server and client communicate, if either the server or the client starts acting strange, just close both terminals running, on any droid run task killer, then try again. The server is inefficient and doesn't do a good job.

Standard disclaimers apply: I'm not responsible for how you use this script or any trouble that you and this script get in to. I'm posting this on here for educational purposes to hopefully help others who would like to understand the GBA save structure.

PokemonTrade.sh:

#! /bin/bash
if [ -z "${1+xxx}" ] || [ -f $1 ]; then
if [ $2 != "kanto" ] && [ $2 != "hoenn" ]; then
	echo "Usage: $0 [save location] [region]
  Error: Invalid region (ie. kanto or hoenn)"
else
$(cp $1 $1.bak)
clear
letterconv(){
alphabet=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
echo $(echo $alphabet | cut -c $(expr $1 + 1))
}
hexdec(){
printf "%d" "0x"$1
}
dechex(){
printf "%X" $1
}
bindec(){
ans="0"
p="1"
binary=$(echo $1 | sed -e :a -e 's/^.\{1,31\}$/0&/;ta')
while [ $p -le "32" ]
do
	binnum=$(echo $binary | cut -c $p)
	ans=$(($(($ans*2))+$binnum))
	p=$(($p+1))
done
echo $ans
}
hexbin(){
binArray=0000000100100011010001010110011110001001101010111100110111101111
hex=$1
p=1
bin=""
while [ $p -le $(expr length $1) ]
do
	hex2bin=$(hexdec $(echo $hex | cut -c $p))
	bin=$bin$(echo $binArray | cut -c $(($(($hex2bin*4))+1))-$(($(($hex2bin*4))+4)))
	p=$(($p+1))
done
echo $bin
}
xorEnc(){
keyStr=$(hexbin $1)
stringStr=$(hexbin $2)
enc=""
o="1"
while [ $o -le 32 ]
do
	if [ $(echo $keyStr | cut -c $(($o))) -eq $(echo $stringStr | cut -c $(($o))) ]; then
		enc=$enc"0"
	else
		enc=$enc"1"
	fi
	o=$(($o+1))
done
echo $(echo $(echo $(dechex $(bindec $enc)) | sed -e :a -e 's/^.\{1,15\}$/0&/;ta') | cut -c 9-16)
}
blockFind(){
if [ $2 -eq "1" ]; then
	if [ $1 -eq "1" ]; then
		partyBlock=$3
	fi
	if [ $1 -eq "0" ]; then
		partyBlock=$((1+$3))
	fi
	if [ $1 -ge "2" ]; then
		partyBlock=$((15-$1+$3))
	fi
fi
if [ $2 -eq "0" ]; then
	if [ $1 -eq "0" ]; then
		partyBlock=$3
	fi
	if [ $1 -gt "0" ]; then
		partyBlock=$((14-$1+$3))
	fi
fi
if [ $2 -gt "1" ]; then
	if [ $1 -eq $2 ]; then
		partyBlock=$3
	fi
	if [ $1 -ge $(($2+1)) ]; then
		partyBlock=$((14+$2-$1+$3))
	fi
	if [ $1 -lt $(($2-1)) ]; then
		partyBlock=$(($2-$1+$3))
	fi
fi
echo $partyBlock
}
dataForm(){
mod=$(expr $1 % 24)
fromArray="GAEMGAMEGEAMGEMAGMAEGMEAAGEMAGMEAEGMAEMGAMGEAMEGEGAMEGMAEAGMEAMGEMGAEMAGMGAEMGEAMAGEMAEGMEGAMEAG"
form=$(echo $fromArray | cut -c $(($(($mod*4))+1))-$(($(($mod*4))+4)))
if [ $(echo $form | cut -c 1) = $2 ]; then
	growth=$(($3+32))
elif [ $(echo $form | cut -c 2) = $2 ]; then
	growth=$(($3+44))
elif [ $(echo $form | cut -c 3) = $2 ]; then
	growth=$(($3+56))
elif [ $(echo $form | cut -c 4) = $2 ]; then
	growth=$(($3+68))
fi
echo $growth
}
pokeName(){
pokeNameArray="None----------------Bulbasaur-----------Ivysaur-------------Venusaur------------Charmander----------Charmeleon----------Charizard-----------Squirtle------------Wartortle-----------Blastoise-----------Caterpie------------Metapod-------------Butterfree----------Weedle--------------Kakuna--------------Beedrill------------Pidgey--------------Pidgeotto-----------Pidgeot-------------Rattata-------------Raticate------------Spearow-------------Fearow--------------Ekans---------------Arbok---------------Pikachu-------------Raichu--------------Sandshrew-----------Sandslash-----------NidoranF------------Nidorina------------Nidoqueen-----------NidoranM------------Nidorino------------Nidoking------------Clefairy------------Clefable------------Vulpix--------------Ninetales-----------Jigglypuff----------Wigglytuff----------Zubat---------------Golbat--------------Oddish--------------Gloom---------------Vileplume-----------Paras---------------Parasect------------Venonat-------------Venomoth------------Diglett-------------Dugtrio-------------Meowth--------------Persian-------------Psyduck-------------Golduck-------------Mankey--------------Primeape------------Growlithe-----------Arcanine------------Poliwag-------------Poliwhirl-----------Poliwrath-----------Abra----------------Kadabra-------------Alakazam------------Machop--------------Machoke-------------Machamp-------------Bellsprout----------Weepinbell----------Victreebel----------Tentacool-----------Tentacruel----------Geodude-------------Graveler------------Golem---------------Pnyta---------------Rapidash------------Slowpoke------------Slowbro-------------Magnemite-----------Magneton------------Farfetchd-----------Doduo---------------Dodrio--------------Seel----------------Dewgong-------------Grimer--------------Muk-----------------Shellder------------cloyster------------Gastly--------------Haunter-------------Gengar--------------Onix----------------Drowzee-------------Hypno---------------Krabby--------------Kingler-------------Voltorb-------------Electrode-----------Exeggcute-----------Exeggutor-----------Cubone--------------Marowak-------------Hitmonlee-----------Hitmonchan----------Lickitung-----------Koffing-------------Weezing-------------Rhyhorn-------------Rhydon--------------Chansey-------------Tangela-------------Kangaskhan----------Horsea--------------Seadra--------------Goldeen-------------Seaking-------------Staryu--------------Starmie-------------Mr.Mime-------------Scyther-------------Jynx----------------Electabuzz----------Magmar--------------Pinsir--------------Tauros--------------Magikarp------------Gyarados------------Lapras--------------Ditto---------------Eevee---------------Vaporeon------------Jolteon-------------Flareon-------------Porygon-------------Omanyte-------------Omastar-------------Kabuto--------------Kabutops------------Aerodactyl----------Snorlax-------------Articuno------------Zapdos--------------Moltres-------------Dratini-------------Dragonair-----------Dragonite-----------Mewtwo--------------Mew-----------------Chikorita-----------Bayleef-------------Meganium------------cyndaquil-----------Quilava-------------Typhlosion----------Totodile------------Croconaw------------Feraligatr----------Sentret-------------Furret--------------Hoothoot------------Noctowl-------------Ledyba--------------Ledian--------------Spinarak------------Ariados-------------Crobat--------------Chinchou------------Lanturn-------------Pichu---------------Cleffa--------------Igglybuff-----------Togepi--------------Togetic-------------Natu----------------Xatu----------------Mareep--------------Flaaffy-------------Ampharos------------Bellossom-----------Marill--------------Azumarill-----------Sudowoodo-----------Politoed------------Hoppip--------------Skiploom------------Jumpluff------------Aipom---------------Sunkern-------------Sunflora------------Yanma---------------Wooper--------------Quagsire------------Espeon--------------Umbreon-------------Murkrow-------------Slowking------------Misdreavus----------Unown-A-------------Wobbuffet-----------Girafarig-----------Pineco--------------Forretress----------Dunsparce-----------Gligar--------------Steelix-------------Snubbull------------Granbull------------Qwilfish------------Scizor--------------Shuckle-------------Heracross-----------Sneasel-------------Teddiursa-----------Ursaring------------Slugma--------------Magcargo------------Swinub--------------Piloswine-----------Corsola-------------Remoraid------------Octillery-----------Delibird------------Mantine-------------Skarmory------------Houndour------------Houndoom------------Kingdra-------------Phanpy--------------Donphan-------------Porygon2------------Stantler------------Smeargle------------Tyrogue-------------Hitmontop-----------Smoochum------------Elekid--------------Magby---------------Miltank-------------Blissey-------------Raikou--------------Entei---------------Suicune-------------Larvitar------------Pupitar-------------Tyranitar-----------Lugia---------------Ho-Oh---------------Celebi--------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------?-------------------Treecko-------------Grovyle-------------Sceptile------------Torchic-------------Combusken-----------Blaziken------------Mudkip--------------Marshtomp-----------Swampert------------Poochyena-----------Mightyena-----------Zigzagoon-----------Linoone-------------Wurmple-------------Silcoon-------------Beautifly-----------Cascoon-------------Dustox--------------Lotad---------------Lombre--------------Ludicolo------------Seedot--------------Nuzleaf-------------Shiftry-------------Nincada-------------Ninjask-------------Shedinja------------Taillow-------------Swellow-------------Shroomish-----------Breloom-------------Spinda--------------Wingull-------------Pelipper------------Surskit-------------Masquerain----------Wailmer-------------Wailord-------------Skitty--------------Delcatty------------Kecleon-------------Baltoy--------------Claydol-------------Nosepass------------Torkoal-------------Sableye-------------Barboach------------Whiscash------------Luvdisc-------------Corphish------------Crawdaunt-----------Feebas--------------Milotic-------------Carvanha------------Sharpedo------------Trapinch------------Vibrava-------------Flygon--------------Makuhita------------Hariyama------------Electrike-----------Manectric-----------Numel---------------Camerupt------------Spheal--------------Sealeo--------------Walrein-------------Cacnea--------------Cacturne------------Snorunt-------------Glalie--------------Lunatone------------Solrock-------------Azurill-------------Spoink--------------Grumpig-------------Plusle--------------Minun---------------Mawile--------------Meditite------------Medicham------------Swablu--------------Altaria-------------Wynaut--------------Duskull-------------Dusclops------------Roselia-------------Slakoth-------------Vigoroth------------Slaking-------------Gulpin--------------Swalot--------------Tropius-------------Whismur-------------Loudred-------------Exploud-------------Clamperl------------Huntail-------------Gorebyss------------Absol---------------Shuppet-------------Banette-------------Seviper-------------Zangoose------------Relicanth-----------Aron----------------Lairon--------------Aggron--------------Castform------------Volbeat-------------Illumise------------Lileep--------------Cradily-------------Anorith-------------Armaldo-------------Ralts---------------Kirlia--------------Gardevoir-----------Bagon---------------Shelgon-------------Salamence-----------Beldum--------------Metang--------------Metagross-----------Regirock------------Regice--------------Registeel-----------Kyogre--------------Groudon-------------Rayquaza------------Latias--------------Latios--------------Jirachi-------------Deoxys--------------Chimecho------------Egg-----------------Unown-B-------------Unown-C-------------Unown-D-------------Unown-E-------------Unown-F-------------Unown-G-------------Unown-H-------------Unown-I-------------Unown-J-------------Unown-K-------------Unown-L-------------Unown-M-------------Unown-N-------------Unown-O-------------Unown-P-------------Unown-Q-------------Unown-R-------------Unown-S-------------Unown-T-------------Unown-U-------------Unown-V-------------Unown-W-------------Unown-X-------------Unown-Y-------------Unown-Z-------------Unown-EM------------Unown-QM------------"
species=$(echo $pokeNameArray | cut -c $(($(($1*20))+1))-$(($(($1*20))+20)))
echo $species
}
Chksum()
{
i=0
Chk=0
while [ $i -lt 3968 ]
do
dataNum=$(hexdec $(echo $1 | cut -c $(($(($i*2))+7))-$(($(($i*2))+8)))$(echo $1 | cut -c $(($(($i*2))+5))-$(($(($i*2))+6)))$(echo $1 | cut -c $(($(($i*2))+3))-$(($(($i*2))+4)))$(echo $1 | cut -c $(($(($i*2))+1))-$(($(($i*2))+2))))
Chk=$(expr $Chk + $dataNum)
i=$(($i+4))
done
hexChk=$(dechex $Chk)
tmp=$(hexdec $(echo $hexChk | cut -c 1-$(($(expr length $hexChk)-4))))
tmp=$(dechex $(expr $tmp + $Chk))

Chk=$(echo $tmp | cut -c $(($(expr length $tmp)-3))-$(expr length $tmp))
echo $(echo $Chk | cut -c 3-4)$(echo $Chk | cut -c 1-2)
}
hex=$(hexdump -ve '1/1 "%.2X"' $1)
snum=$(echo $hex | cut -c 8185-8186)
snum2=$(echo $hex | cut -c 122873-122874)
saveNum=$(hexdec $snum)
saveNum2=$(hexdec $snum2)
if [ $saveNum -ge $saveNum2 ]; then
extra="0"
hex1=$(echo $hex | cut -c 8169-8170)
$(split -b 4096 $1 PokeSave)
else
extra="14"
hex1=$(echo $hex | cut -c 122857-122858)
$(split -b 4096 $1 PokeSave)
fi
hexVar=$(hexdec $hex1)
partyBlock=$(blockFind $hexVar 1 $extra)
if [ $2 = "kanto" ]; then
more="038"
else
more="238"
fi
partyStart=$(hexdec $(dechex $partyBlock)$more)
partyStartHex=$(dechex $partyBlock)$more
pokeNum1=$(($(($partyStart))*2))
poke1=$(echo $hex | cut -c $(($pokeNum1+1))-$(($pokeNum1+200)))
pokeNum2=$(($(($partyStart+100))*2))
poke2=$(echo $hex | cut -c $(($pokeNum2+1))-$(($pokeNum2+200)))
pokeNum3=$(($(($partyStart+200))*2))
poke3=$(echo $hex | cut -c $(($pokeNum3+1))-$(($pokeNum3+200)))
pokeNum4=$(($(($partyStart+300))*2))
poke4=$(echo $hex | cut -c $(($pokeNum4+1))-$(($pokeNum4+200)))
pokeNum5=$(($(($partyStart+400))*2))
poke5=$(echo $hex | cut -c $(($pokeNum5+1))-$(($pokeNum5+200)))
pokeNum6=$(($(($partyStart+500))*2))
poke6=$(echo $hex | cut -c $(($pokeNum6+1))-$(($pokeNum6+200)))
pidHex1=$(echo $poke1 | cut -c 7-8)$(echo $poke1 | cut -c 5-6)$(echo $poke1 | cut -c 3-4)$(echo $poke1 | cut -c 1-2)
pid1=$(hexdec $pidHex1)
pid2=$(hexdec $(echo $poke2 | cut -c 7-8)$(echo $poke2 | cut -c 5-6)$(echo $poke2 | cut -c 3-4)$(echo $poke2 | cut -c 1-2))
pid3=$(hexdec $(echo $poke3 | cut -c 7-8)$(echo $poke3 | cut -c 5-6)$(echo $poke3 | cut -c 3-4)$(echo $poke3 | cut -c 1-2))
pid4=$(hexdec $(echo $poke4 | cut -c 7-8)$(echo $poke4 | cut -c 5-6)$(echo $poke4 | cut -c 3-4)$(echo $poke4 | cut -c 1-2))
pid5=$(hexdec $(echo $poke5 | cut -c 7-8)$(echo $poke5 | cut -c 5-6)$(echo $poke5 | cut -c 3-4)$(echo $poke5 | cut -c 1-2))
pid6=$(hexdec $(echo $poke6 | cut -c 7-8)$(echo $poke6 | cut -c 5-6)$(echo $poke6 | cut -c 3-4)$(echo $poke6 | cut -c 1-2))
g1=$(dataForm $pid1 "G" "0")
g2=$(dataForm $pid2 "G" "0")
g3=$(dataForm $pid3 "G" "0")
g4=$(dataForm $pid4 "G" "0")
g5=$(dataForm $pid5 "G" "0")
g6=$(dataForm $pid6 "G" "0")

#First Pokemon's Things
RevPID1=$(echo $poke1 | cut -c 1-8)
OTID1=$(echo $poke1 | cut -c 9-16)
key1=$(xorEnc $RevPID1 $OTID1)
growthStr1=$(echo $(xorEnc $key1 $(echo $poke1 | cut -c $(($(($g1*2))+1))-$(($(($g1*2))+8)))) | sed -e :a -e 's/^.\{1,7\}$/0&/;ta')
speciesDec1=$(hexdec $(echo $growthStr1 | cut -c 3-4)$(echo $growthStr1 | cut -c 1-2))

#Second Pokemon's Things
RevPID2=$(echo $poke2 | cut -c 1-8)
OTID2=$(echo $poke2 | cut -c 9-16)
key2=$(xorEnc $RevPID2 $OTID2)
growthStr2=$(echo $(xorEnc $key2 $(echo $poke2 | cut -c $(($(($g2*2))+1))-$(($(($g2*2))+8)))) | sed -e :a -e 's/^.\{1,7\}$/0&/;ta')
speciesDec2=$(hexdec $(echo $growthStr2 | cut -c 3-4)$(echo $growthStr2 | cut -c 1-2))

#Third Pokemon's Things
RevPID3=$(echo $poke3 | cut -c 1-8)
OTID3=$(echo $poke3 | cut -c 9-16)
key3=$(xorEnc $RevPID3 $OTID3)
growthStr3=$(echo $(xorEnc $key3 $(echo $poke3 | cut -c $(($(($g3*2))+1))-$(($(($g3*2))+8)))) | sed -e :a -e 's/^.\{1,7\}$/0&/;ta')
speciesDec3=$(hexdec $(echo $growthStr3 | cut -c 3-4)$(echo $growthStr3 | cut -c 1-2))

#Fourth Pokemon's Things
RevPID4=$(echo $poke4 | cut -c 1-8)
OTID4=$(echo $poke4 | cut -c 9-16)
key4=$(xorEnc $RevPID4 $OTID4)
growthStr4=$(echo $(xorEnc $key4 $(echo $poke4 | cut -c $(($(($g4*2))+1))-$(($(($g4*2))+8)))) | sed -e :a -e 's/^.\{1,7\}$/0&/;ta')
speciesDec4=$(hexdec $(echo $growthStr4 | cut -c 3-4)$(echo $growthStr4 | cut -c 1-2))

#Five Pokemon's Things
RevPID5=$(echo $poke5 | cut -c 1-8)
OTID5=$(echo $poke5 | cut -c 9-16)
key5=$(xorEnc $RevPID5 $OTID5)
growthStr5=$(echo $(xorEnc $key5 $(echo $poke5 | cut -c $(($(($g5*2))+1))-$(($(($g5*2))+8)))) | sed -e :a -e 's/^.\{1,7\}$/0&/;ta')
speciesDec5=$(hexdec $(echo $growthStr5 | cut -c 3-4)$(echo $growthStr5 | cut -c 1-2))

#Sixth Pokemon's Things
RevPID6=$(echo $poke6 | cut -c 1-8)
OTID6=$(echo $poke6 | cut -c 9-16)
key6=$(xorEnc $RevPID6 $OTID6)
growthStr6=$(echo $(xorEnc $key6 $(echo $poke6 | cut -c $(($(($g6*2))+1))-$(($(($g6*2))+8)))) | sed -e :a -e 's/^.\{1,7\}$/0&/;ta')
speciesDec6=$(hexdec $(echo $growthStr6 | cut -c 3-4)$(echo $growthStr6 | cut -c 1-2))
clear
pokeName1=$(echo $(pokeName $speciesDec1) | tr -d '-')
pokeName2=$(echo $(pokeName $speciesDec2) | tr -d '-')
pokeName3=$(echo $(pokeName $speciesDec3) | tr -d '-')
pokeName4=$(echo $(pokeName $speciesDec4) | tr -d '-')
pokeName5=$(echo $(pokeName $speciesDec5) | tr -d '-')
pokeName6=$(echo $(pokeName $speciesDec6) | tr -d '-')
specdec1=$(echo $speciesDec1 | sed -e :a -e 's/^.\{1,2\}$/0&/;ta')
specdec2=$(echo $speciesDec2 | sed -e :a -e 's/^.\{1,2\}$/0&/;ta')
specdec3=$(echo $speciesDec3 | sed -e :a -e 's/^.\{1,2\}$/0&/;ta')
specdec4=$(echo $speciesDec4 | sed -e :a -e 's/^.\{1,2\}$/0&/;ta')
specdec5=$(echo $speciesDec5 | sed -e :a -e 's/^.\{1,2\}$/0&/;ta')
specdec6=$(echo $speciesDec6 | sed -e :a -e 's/^.\{1,2\}$/0&/;ta')
echo "   Pick the pokemon you want to trade:
1) $pokeName1
2) $pokeName2
3) $pokeName3
4) $pokeName4
5) $pokeName5
6) $pokeName6"
read pokeChoice
if [ $pokeChoice != 1 ] && [ $pokeChoice != 2 ] && [ $pokeChoice != 3 ] && [ $pokeChoice != 4 ] && [ $pokeChoice != 5 ] && [ $pokeChoice != 6 ]; then
echo "Not a valid number"
else
if [ $pokeChoice -eq 1 ]; then
pokeGive=$pokeName1
pokeGiveHex=$poke1
elif [ $pokeChoice -eq 2 ]; then
pokeGive=$pokeName2
pokeGiveHex=$poke2
elif [ $pokeChoice -eq 3 ]; then
pokeGive=$pokeName3
pokeGiveHex=$poke3
elif [ $pokeChoice -eq 4 ]; then
pokeGive=$pokeName4
pokeGiveHex=$poke4
elif [ $pokeChoice -eq 5 ]; then
pokeGive=$pokeName5
pokeGiveHex=$poke5
elif [ $pokeChoice -eq 6 ]; then
pokeGive=$pokeName6
pokeGiveHex=$poke6
fi
code=""
rm pokeTrade.pkm
for byte in $(echo $pokeGiveHex | sed 's/../& /g')
do
code=$code$(printf "\x$byte" >>pokeTrade.pkm)
done
clear
$(echo $pokeGive | cat > pokeTrade.txt)
echo "You chose to trade $pokeGive
One person needs to be a Server, the other needs to be the client.
  Which do you wish to be?
1) Server
2) Client"
read serverChoice
if [ $(uname -m | cut -c 1-3) = "arm" ]; then
port=" -p"
else
port=""
fi
if [ $serverChoice != 1 ] && [ $serverChoice != 2 ]; then
echo "Not a valid choice!"
else
if [ $serverChoice -eq 1 ]; then
	echo "Started the server.
Type the ip address "$(ifconfig  | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1}')" into the client"
	$(nc -l$port 8765 > pokeGet.txt)
	echo "Looking at trade"
	$(nc -l$port 8765 < pokeTrade.txt)
	clear
	echo "Your friend wants to trade you a "$(cat pokeGet.txt)
	$(nc -l$port 8765 > pokeGet.pkm)
	$(nc -l$port 8765 < pokeTrade.pkm)
	echo "Accept Trade? y/n"
	read yesno
	if [ $yesno = "n" ]; then
		word="Kept"
		$(cp pokeTrade.pkm pokeGet.pkm)
	else
		word="Got"
	fi
else
	echo "You are the client!
Type the ip address of the server:"
	read serverIP
	$(nc -w 10 $serverIP 8765 < pokeTrade.txt)
	echo "Looking at trade"
	$(nc $serverIP 8765 > pokeGet.txt)
	clear
	echo "Your friend wants to trade you a "$(cat pokeGet.txt)
	echo "Accept Trade? y/n"
	read yesno
	if [ $yesno = "y" ]; then
		word="Got"
		$(nc -w 10 $serverIP 8765 < pokeTrade.pkm)
		$(nc $serverIP 8765 > pokeGet.pkm)
	else
		word="Kept"
		$(cp pokeTrade.pkm pokeGet.pkm)
	fi
fi
fi
pokeGetHex=$(hexdump -ve '1/1 "%.2X"' "pokeGet.pkm")
pidGet=$(hexdec $(echo $pokeGetHex | cut -c 7-8)$(echo $pokeGetHex | cut -c 5-6)$(echo $pokeGetHex | cut -c 3-4)$(echo $pokeGetHex | cut -c 1-2))
gGet=$(dataForm $pidGet "G" "0")
RevPIDGet=$(echo $pokeGetHex | cut -c 1-8)
OTIDGet=$(echo $pokeGetHex | cut -c 9-16)
keyGet=$(xorEnc $RevPIDGet $OTIDGet)
growthStrGet=$(echo $(xorEnc $keyGet $(echo $pokeGetHex | cut -c $(($(($gGet*2))+1))-$(($(($gGet*2))+8)))) | sed -e :a -e 's/^.\{1,7\}$/0&/;ta')
speciesDecGet=$(hexdec $(echo $growthStrGet | cut -c 3-4)$(echo $growthStrGet | cut -c 1-2))
pokeNameGet=$(echo $(pokeName $speciesDecGet) | tr -d '-')
clear
echo "$word a $pokeNameGet!"
if [ $pokeChoice -eq 1 ]; then
party=$poke2$poke3$poke4$poke5$poke6$pokeGetHex
elif [ $pokeChoice -eq 2 ]; then
party=$poke1$poke3$poke4$poke5$poke6$pokeGetHex
elif [ $pokeChoice -eq 3 ]; then
party=$poke1$poke2$poke4$poke5$poke6$pokeGetHex
elif [ $pokeChoice -eq 4 ]; then
party=$poke1$poke2$poke3$poke5$poke6$pokeGetHex
elif [ $pokeChoice -eq 5 ]; then
party=$poke1$poke2$poke3$poke4$poke6$pokeGetHex
elif [ $pokeChoice -eq 6 ]; then
party=$poke1$poke2$poke3$poke4$poke5$pokeGetHex
fi
echo "Adding pokemon to save"
partyBlockStart=$(($(($(hexdec $partyBlock"000")*2))+1))
partyStartPos=$(($(($partyStart*2))))
partyEnd=$(($(($partyStart*2))+1201))
partyBlockStop=$(($(($(hexdec $partyBlock"FFF")*2))+2))
partyBlockHex=$(echo $hex | cut -c $partyBlockStart-$partyStartPos)$party$(echo $hex | cut -c $partyEnd-$partyBlockStop)
$(echo $partyBlockHex | cat > partyBlockHex.txt)
echo "Calculating new checksum"
checksum=$(Chksum $partyBlockHex)
echo "New checksum = $checksum!"
partyBlockFinal=$(echo $partyBlockHex | cut -c 1-8172)$checksum$(echo $partyBlockHex | cut -c 8177-8200)
echo "Compiling new save"
for byte in $(echo $partyBlockFinal | sed 's/../& /g')
do
$(printf "\x$byte" >>partyBlock.sav.part)
done
$(echo $(echo $partyBlockFinal | sed 's/../& /g') | cat > partyBlockFinal.txt)
echo "Writing new save"
$(rm $1)
i=0
while [ $i -lt 26 ]
do
if [ $i -eq $partyBlock ]; then
	$(cat partyBlock.sav.part >>$1)
else
	$(cat PokeSavea$(letterconv $i) >>$1)
fi
i=$(expr $i + 1)
done
while [ $i -lt 32 ]
do
if [ $i -eq $partyBlock ]; then
	$(cat partyBlock.sav.part >>$1)
else
	$(cat PokeSaveb$(letterconv $i) >>$1)
fi
i=$(expr $i + 1)
done
i=0
while [ $i -lt 26 ]
do
$(rm PokeSavea$(letterconv $i))
i=$(expr $i + 1)
done
while [ $i -lt 32 ]
do
$(rm PokeSaveb$(letterconv $i))
i=$(expr $i + 1)
done
$(rm partyBlock.sav.part)
$(rm pokeGet.txt)
$(rm pokeTrade.txt)
$(rm pokeGet.pkm)
$(rm pokeTrade.pkm)
echo "Done!"
fi
fi
else
echo "Usage: $0 [save location] [region]
  Error: No such File"
fi

This couldn't have been done without LoadingNOW's PSavFix or Bulbapedia.

I've only written this script during my free time in the past few days, so if anyone could improve on this, please do.

I've done a couple projects involving the GBA save structure, so if you need any help with it, just ask, and I may be able to help!

Share this post


Link to post
Share on other sites

you are the best i'm going to check it if it works in my droid (xperia 10 mini pro) i'm gonna learn bash and if i have some free time i will make a apk, one more question i need a access point to trade the pokemon, i gess that is only needed 2 phones and that's it

Share this post


Link to post
Share on other sites

If you're just looking to test and debug the program, then you can open up two terminals on a linux distribution of some sort (ubuntu, fedora, debian, etc.) and run both the server and client on one machine. However, if you do this, make sure that the two saves that you are trading are in two separate folders.

The bash script should have all you need to know as far as basic offsets and decryption of Pokemon files go, but if you need more help then I'll be glad to pass along information.

Share this post


Link to post
Share on other sites

thanks if i have some more questions i will let you know, but for now can you give the name of a program that can run your script line by line in order to understand better how it works? thanks again

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now