ROM Hack Developing PHP-based open source PokéSAV script

MarkusE

Well-Known Member
OP
Newcomer
Joined
Aug 28, 2007
Messages
54
Trophies
0
XP
82
Country
United States
Hi all,

Good news. For all the Mac and Linux users out there who aren't able to use PokéSAV, I'm currently developing a PHP port of the popular application. I'm planning to introduce additional functionality, such as
- the ability to mass-edit Pokémon in the PC boxes, e.g. set global gender, level, OT, etc.
- the ability to retrieve default values for move PPs, "met at" levels/locations, and more*
- the ability to filter out abilities, moves, etc. that aren't (legitimately) compatible with a Pokémon*
and more.
* Will involve a database backend to store the data.

With language packs, multi-language support should be a breeze.

As I'm sure you can understand, this is a large and difficult project. Hence, I'm currently looking for knowledgeable PHP coders who can effectively assist me in undertaking this task.

If you're interested in helping:

This handy document explains from start to finish how the Pokemon data is organized, stored, and encrypted. Though it was originally written for Emerald, there have been very few changes made to Diamond and Pearl, and hence this is a must-read.

Here are the steps:
1. The user must be able to upload a .sav
2. When the user chooses a box number and position (1-30), the script should decrypt the appropriate 136-byte chunk of the .sav (0xC104 Box 01-01 + 0x88 per Pokemon)
3. The individual Pokemon editor should have drop downs and inputs as in Pokesav, and upon submission of the new inputs, a new .pkm file equivalent should be generated, then encrypted for packing into the .sav
4. The script should output a new .sav that can be downloaded.

Anyone interested in helping? If you are, I can show you what I've accomplished so far. I plan to make this open source upon completion, so that others can add to it, debug it, and make it better.
smile.gif
 

Maikel Steneker

M3 Fanboy
Member
Joined
May 16, 2007
Messages
3,394
Trophies
1
Age
32
Website
ndss.nl
XP
383
Country
Netherlands
Wow, that's great! Unfortunately I don't know anything about PHP... If it's not too hard I can translate it to Dutch though. Let me know if you need my help with it
smile.gif
 

MarkusE

Well-Known Member
OP
Newcomer
Joined
Aug 28, 2007
Messages
54
Trophies
0
XP
82
Country
United States
The hardest part of the whole thing will be the encryption and decryption. The game uses XOR encryption and then arranges the data in a corresponding 4-permutation.

I'd like to have everything PokeSAV has to offer in addition to those features. I'm definitely going to need help from PHP coders, though, seeing as how I have a day job and hence very limited time to devote to this...
 

SuperDinoYoshi

Active Member
Newcomer
Joined
Dec 23, 2006
Messages
44
Trophies
0
XP
47
Country
United States
I know a little bit of php, probablly not enough to help you with the decryption, but if you managed to get that out of the way, I could do some grunt work.
 

MarkusE

Well-Known Member
OP
Newcomer
Joined
Aug 28, 2007
Messages
54
Trophies
0
XP
82
Country
United States
I know a little bit of php, probablly not enough to help you with the decryption, but if you managed to get that out of the way, I could do some grunt work.
Excellent. Can you please write a PHP script that generates attribute strings for a Pokemon?

The first four bytes of each Pokemon is an attribute string that determines a Pokemon's nature, gender, shininess, form (Unown, Burmy, etc.), and encryption order. You'll need an additional input, OTString (2 high bytes = trainer ID from 0 to 65535 and 2 lower bytes = secret trainer ID from 0 to 65535)

Nature = AttStr modulo 25
00 = Hardy
01 = Lonely
02 = Brave
03 = Adament
04 = Naughty
05 = Bold
06 = Docile
07 = Relaxed
08 = Impish
09 = Lax
10 = Timid
11 = Hasty
12 = Serious
13 = Jolly
14 = Naive
15 = Modest
16 = Mild
17 = Quiet
18 = Bashful
19 = Rash
20 = Calm
21 = Gentle
22 = Sassy
23 = Careful
24 = Quirky

Gender = AttStr modulo 256
0-255 = Genderless for Pokemon whose gender distributions are "100% Genderless, 0% Male, 0% Female"
0-255 = Male for Pokemon whose gender distributions are "100% Male, 0% Female"
0-255 = Female for Pokemon whose gender distributions are "0% Male, 100% Female"

0-30 = Female For "12.5% Female 87.5% Male"
31-255 = Male For "12.5% Female 87.5% Male"

0-63 = Female For "25% Female 75% Male"
64-255 = Male For "25% Female 75% Male"

0-126 = Female For "50% Female 50% Male"
127-255 = Male For "50% Female 50% Male"

0-190 = Female For "75% Female 50% Male"
191-255 = Male For "75% Female 50% Male"

Unown Shape
$d = Math.floor(PokemonID Mod 4);
$c = (Math.floor(PokemonID/256)Mod 4) * 4;
$b = (Math.floor(PokemonID/65536)Mod 4) * 16;
$a = (Math.floor(PokemonID/16777216)Mod 4) * 64;
Unown = Math.floor(($a + $b + $c + $d) Mod 28);

(hex)
00=A
01=B
02=C
03=D
04=E
05=F
06=G
07=H
08=I
09=J
0A=K
0B=L
0C=M
0D=N
0E=O
0F=P
10=Q
11=R
12=S
13=T
14=U
15=V
16=W
17=X
18=Y
19=Z
1A=!
1B=?

Encryption Key
EncKey = AttStr XOR OTString

Shininess
EncKeyHigh = Integer(XKey/65536)
EncKeyLow = XKey Mod 65536
IsShiny = XKeyHigh XOR XKeyLow
If IsShiny < 8, the Pokemon is shiny.

More detailed information can be found at this website:
http://www.princeton.edu/~jdonald/pokemon/...onMakerHelp.txt

In short, just write a function in PHP that takes those various inputs (numerical is okay, as long as they're within the valid ranges -- I'll worry drop-down menus later) and outputs a valid attribute string in the range of 0 to 4294967295. You need not worry about packing the data (converting to little-endian, writing the bytes, et cetera) into the actual .pkm/.sav file.
 

gamefreakfatty

Active Member
Newcomer
Joined
Dec 28, 2006
Messages
28
Trophies
0
XP
227
Country
United States
i would really like to help with this if i could. i do not know much about php or decryption but i can learn. i need to learn php anyways, so it might be a good start. give me a nice reference for PHP, and i could probably help.
 

MarkusE

Well-Known Member
OP
Newcomer
Joined
Aug 28, 2007
Messages
54
Trophies
0
XP
82
Country
United States
That's great! A good starting point would be writing the attribute string generator -- I've gotten most of the rest of the .pkm file generator taken care of. Details for how the attribute string works are in post #12 of this topic.

A great PHP reference is the official site at www.php.net
smile.gif
 

gamefreakfatty

Active Member
Newcomer
Joined
Dec 28, 2006
Messages
28
Trophies
0
XP
227
Country
United States
thanks for the reference! i would be glad to help if i can

edit: i forgot to add: how do you find where the pokemon are? i've done a comparison of the saves, but i dont know how to search for the pokemon name. i've used whats in the document for PokemonMaker, but it doesnt find anything. if i could find it then i could probably find the pokemonid/reversepokemonid.
thanks in advance
 

MarkusE

Well-Known Member
OP
Newcomer
Joined
Aug 28, 2007
Messages
54
Trophies
0
XP
82
Country
United States
thanks for the reference! i would be glad to help if i can

edit: i forgot to add: how do you find where the pokemon are? i've done a comparison of the saves, but i dont know how to search for the pokemon name. i've used whats in the document for PokemonMaker, but it doesnt find anything. if i could find it then i could probably find the pokemonid/reversepokemonid.
thanks in advance

136 bytes make up a .pkm
0x48 = first character slot
0x4A = second character slot
0x4C = third character slot
0x4E = fourth character slot
...
0x58 = tenth character slot
0x5C = eleventh character slot

01 (space)
21 0
22 1
23 2
24 3
25 4
26 5
27 6
28 7
29 8
2a 9
2b A
2c B
2d C
2e D
2f E
30 F
31 G
32 H
33 I
34 J
35 K
36 L
37 M
38 N
39 O
3a P
3b Q
3c R
3d S
3e T
3f U
40 V
41 W
42 X
43 Y
44 Z
45 a
46 b
47 c
48 d
49 e
4a f
4b g
4c h
4d i
4e j
4f k
50 l
51 m
52 n
53 o
54 p
55 q
56 r
57 s
58 t
59 u
5a v
5b w
5c x
5d y
5e z

ab !
c0 #

for the odd bytes (0x49, 0x4B, etc.) put a 01 if the character in the previous byte is NOT the last character of the Pokemon's name, and 00 otherwise. Use "ff ff" (null terminator) in the character slot after your last one. (If your Pokemon's name has the max length of 10, go onto the eleventh. The eleventh slot cannot be used for anything other than ff ff.)
 

gamefreakfatty

Active Member
Newcomer
Joined
Dec 28, 2006
Messages
28
Trophies
0
XP
227
Country
United States
ok... i dont know why i cant find the names... im using UltraEdit-32. what hex editor do i need? it shouldnt make a difference though should it?

also, i think i might be able to help with the attribute part, but i dont understand the "Math" part of the Unknown shape. if there is a different way to find out that's easier please tell

---------------------
Unown Shape(if Unown)
---------------------
is found by selecting certain bits from the PokemonID
ff47e89d-Hex = 1111 1111 0100 0111 1110 1000 1001 1101-Binary

Looking at Pokemon ID in Binary
1111 1111 0100 0111 1110 1000 1001 1101-Binary
-------WW--------XX--------YY--------ZZ
Bit32-Dec to Bit00-Dec

Bits26-25 WW "11"
Bits17-16 XX "11"
Bits09-08 YY "00"
Bits01-00 ZZ "01"

Are combined together
WWXXYYZZ "1111 0001"-Binary
In Hex F1-Hex

Then MOD 28-Dec or 1C-Hex
F1 Mod 1C = 11-Hex

00=A
01=B
02=C
03=D
04=E
05=F
06=G
07=H
08=I
09=J
0A=K
0B=L
0C=M
0D=N
0E=O
0F=P
10=Q
11=R
12=S
13=T
14=U
15=V
16=W
17=X
18=Y
19=Z
1A=!
1B=?

11="R" is the Unown Shape.(if it where an Unown)

Math way
Bits26-25 WW "11"
Bits17-16 XX "11"
Bits09-08 YY "00"
Bits01-00 ZZ "01"

ZZ= Math.floor(PokemonID Mod 4)
YY=(Math.floor(PokemonID/256)Mod 4) * 4
XX=(Math.floor(PokemonID/65536)Mod 4) * 16
WW=(Math.floor(PokemonID/16777216)Mod 4) * 64
Combine = WW + XX + YY + ZZ
Unown = Math.floor(Combine Mod 28)



i dont understand the "Mod 4" and the "Mod 28" parts either.
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    Xdqwerty @ Xdqwerty: