Jump to content

Recommended Posts

Posted

Alright, so I managed to get a little more data on meta-frames with -1 as their image index.

Those files in the "/GROUND/" folder have orphaned images that aren't referred to by meta-frames ( in some all meta-frames have a -1 image index. Which begs the question, what is the image index for actually ?):

"d28p34a3.wan"
"d30p33a4.wan"
"d51p11a1.wan"
"d52p32a3.wan"
"d52p32a9.wan"
"d53p41a1.wan"
"d57p43a2.wan"
"h02p99c4.wan"
"h02p99c5.wan"
"p14p01a1.wan"
"s01p01a1.wan"
"s08p01a1.wan"
"s13p01a1.wan"
"s13p03a1.wan"
"s13p03a2.wan"
"s18p01a3.wan"
"s18p01a4.wan"
"s20p01a1.wan"
"s20p01a2.wan"
"v01p05b1.wan"
"v01p05b2.wan"
"v01p05b3.wan"
"v04p03a1.wan"
"v05p03a1.wan"
"v05p03a2.wan"
"v10p03c1.wan"
"v19p06a1.wan"
"v23p04a1.wan"
"v24p04a2.wan"
"v37p02a1.wan"

And these files are pokemon sprites that got several -1 image indexes in their meta-frames :

0055_diglett
0056_diglett
0057_dugtrio
0058_dugtrio
0102_haunter
0119_koffing
0158_moltres
0277_houndoom
0400_mesprit
0408_magnezone
0423_dusknoir
0424_dusknoir
0425_dusknoir
0436_darkrai
0441_grovyle
0459_beautifly-f
0460_beautifly-m
0485_ninjask
0497_sableye
0502_aggron
0561_tropius
0587_latios
0589_groudon
0591_jirachi

Looking at those and looking a debug output from my utility, I was able to figure out that, in every meta-frames groups* where at least one meta-frame has an image index of -1, the value of the "unk15" byte for that frame, or for preceeding and following frames, is non-zero! Or at least, it seems to be non-zero more often when there is a frame with an image index of -1 around!

At first, I believed that, the value in unk15, only when the image index was -1, would essentially contain the index of the image the meta-frame refer to. And while it worked for a few sprites, its definitely not the case for all of them! And now, I've found sprites that have a unk15 value that wildly exceeds the amount of images stored in the sprite...

For example a sprite with 60 images had unk15 values that would go up to 104!

*Meta-frames groups represent a complete frame to be used as an animated frame. They usually contain a single meta-frame, but it can also contain several assembling them into a more complex resulting image. Meta-frames groups are pointed to by a table, which points to the area right after the SIR0 header, where the meta-frames are stored. The last meta-frame of a group has a bitflag to indicate that its the last frame in a group. All of that and more is detailed in my notes though.

See my personal notes for details: https://dl.dropboxusercontent.com/u/13343993/my_pmd_research_files/FileFormats/SIR0_Sprite.txt

I'm really in need of a second opinion on this. I'm afraid I'm missing something possibly very obvious. That's what held me back last time, until TruePikachu popped up and basically figured most of the missing blocks at the time. If anyone has question on the format and wants to help researching, feel free to ask !

Posted (edited)

I haven't looked at the file format, but with the images you extract, and the xml files generated, I was able to make this program.

Simply open it and point it to a directory that contains the xml files and image folder, and it will to the best of its ability show the animated version of it.

Works (almost) flawlessly on small Pokémon sprites, and probably doesn't render larger ones 100% correctly.

Any parts of the meta frame that do not exist (like -1, which turns into 65535 because I stored it in a uint16) are simply ignored, so you can tell what it's supposed to be.

The background color should become transparent, but may not when those parts aren't loaded.

Good work getting this far!

[Edit] One more thing. Slight typo in the xml for frames.xml...


                       <Resolution>
			<Width>32</Width>
			<[u]Heigth[/u]>32</[u]Heigth[/u]>
		</Resolution>

Animation Viewer.zip

Animation Viewer.zip

Edited by evandixon
Posted
I haven't looked at the file format, but with the images you extract, and the xml files generated, I was able to make this program.

Simply open it and point it to a directory that contains the xml files and image folder, and it will to the best of its ability show the animated version of it.

Works (almost) flawlessly on small Pokémon sprites, and probably doesn't render larger ones 100% correctly.

Any parts of the meta frame that do not exist (like -1, which turns into 65535 because I stored it in a uint16) are simply ignored, so you can tell what it's supposed to be.

The background color should become transparent, but may not when those parts aren't loaded.

Good work getting this far!

[Edit] One more thing. Slight typo in the xml...


                       <Resolution>
			<Width>32</Width>
			<[u]Heigth[/u]>32</[u]Heigth[/u]>
		</Resolution>

Wow, that's so neat ! :D

I wanted to write one, but I never really got around to xD

Well, actually, I had the base layout done and etc in C#, but then I completely messed up my project file because somehow a component is referring to itself and crashing the editor?? The debug output refuses to tell me which component or what line.. :/

Anyways, honestly, I tend to prefer messing with the actual data than making GUIs xD (If I had made a dll with my code it would have been much more fun making UIs IMO)

Also, I recently changed the XML structure a bit for the meta-frames, so for the next release it will be a little different. Here's an example of the new output:

frames.xml

<FrameGroup>
	<!--0-->
	<Frame>
		<ImageIndex>0</ImageIndex>
		<Unk0>0x0</Unk0>
		<Offset>
				<X>492</X>
			<Y>244</Y>
		</Offset>
		<Unk1>0xc</Unk1>
		 <Unk15>0x0</Unk15>
			<Resolution>
			<Width>32</Width>
			<Height>32</Height>
		</Resolution>
		<VFlip>0</VFlip>
		<HFlip>0</HFlip>
		<Mosaic>0</Mosaic>
		<XOffsetBit6>0</XOffsetBit6>
		<XOffsetBit7>0</XOffsetBit7>
		<YOffsetBit3>0</YOffsetBit3>
		<YOffsetBit5>0</YOffsetBit5>
		 <YOffsetBit6>0</YOffsetBit6>
	</Frame>
</FrameGroup>

(Also, the "name" attribute that some element have will be filled eventually, once I properly identify all the animation for each characters types! There are 2 main kinds so far. Regular characters have 13 animation groups, and extended characters (Hero/Partner) have 35. And then some specific pokes have extra animations too for cutscenes.)

However, I probably won't change it again afterwards. Well, I mean, besides the tags that begin with "unk". And possibly the meta-frame offset values. Because, according to what I gathered(turtwig's sprite), the actual perfect center is around 248, 490. So I could basically subtract that from the value to give something relative to the center of the sprite "layer". But, I'm still not sure why the number is that big in the first place, so to be really careful I just write it as-is.

I also feel that the naming for meta-frame and meta-frames group is a bit unintuitive and I'd like to change that to something more accurate. For example, a meta-frame group is basically the actual meta-frame the game refers to, not a group of meta-frames. And meta-frames are really a construct of possibly several images.. If you have any suggestions on that it would be appreciated! I'm not a native english speaker too, so that doesn't help xD

Also, thanks for pointing out the typo! For some obscure reasons I always mix up the way the "th"/"ht" at the end of length and height are written ^^;

And a -1 index doesn't necessarily implies that the image doesn't exist or can't be displayed. If you look at diglett for example, he leaves a little trail of dirt when he moves around. And it seems that, by using -1, the game instead of allocating another slot in memory to load that dirt image again, just refers to the instance of that image that's already loaded.

If you want to have a better idea of what I mean, look at these videos :

This is a modified bulbasaur sprite, where the frames of all the running animations are -1. But the idle animations and etc, are all untouched. You'll notice that the game just takes whatever is loaded in memory at the time and tries to display it according to the parameters of the -1 meta-frame. Its especially obvious when I move from one map to the other, moving into the mess hall and out, or climbing the ladder, etc.. :

This one is another modified bulbasaur sprite, but this time I copied twice the single meta-frame in several meta-frame groups, offset them a little, and changed the image index for those extra meta-frames to -1 ( keeping unk15 set to 0) :

And thanks for the compliment, its really appreciated :)

Posted

Alright, I made a new alpha release. Hopefully it got much more robust now !

I fixed a ton of annoying little things.

And now, you don't have to update the frame.xml file when you change the resolution of an image. As long as the image resolution is one of the valid ones, the utility will automatically fix all references to that image. And it can be turned off using the -noresfix option!

Here's the download link:

https://github.com/PsyCommando/ppmdu/releases/download/ppmd_GfxCrunch_0.13a/ppmd_gfxcrunch_0_13.zip

   * Disabled raw image inport/export for sprites, as it causes issues and is generally not worth it.
     The program will default to PNG if the raw image format is specified at the command line!
   * Changed the format of the XML being outputed. So the output of the earlier version cannot be
     read by this version correctly!
   * Fixed a bug with character sprites(type 1) that had no particle offset. A null pointer would be written
     to the WAN header, but only type 0 sprites can have that pointer null! 
   * Fixed SIR0 encoded pointer list for sprites that had null pointers in their header. The null 
     pointers would not be properly skipped when building the list!
   * Added support for unpacking PKDPX compressed sprites directly.
   * Fixed logging so that its turned off by default!
   * Log files are now named after the input filename/directory name!
   * Added automatic updating of the sprite's meta-frames resolution, when the meta-frame refers to an 
     image in the "imgs" folder, and the resolution of the image differs from the one in the XML data.
   * Added command-line option "noresfix" to disable the above feature.
   * Fixed printing of the readme triggering an exception.
   * Modified the sprite pack file building code so that sprite directories in the input folder do not
     need to begin with a number! The files are instead read in alphanumerical order.
   * And a lot of little things..

I've been holding back on this one for a while to make sure it works and that it isn't too rough around the edges. So I hope there won't be too many issues with it !

Posted

Alright, since I'm really stuck when it comes to sprite research, I began looking at other formats. And I found the level-up data for all pokemons.

Its all stored in "/BALANCE/m_level.bin". The file is a pack file that can be unpacked using ppmd_packfileutil, and then the individual files are sir0 wrapped pkdpx compressed files. I have updated dopx and unpx to handle those without having to manually remove the SIR0 container with an hex editor.

I'll post the new binaries later today. I'll also update the wiki, but there is still a little doubt in my mind with the order the stats are stored..

/BALANCE/m_level.bin
---------------------
m_level.bin is a pack file, with each of its sub-files compressed into PKDPX files, and then wrapped into SIR0 containers.
The first sub-file index seems deliberately forced to 0x1200, given there is an extra unneeded row of 0xFF padding before the 
first one.

Its purpose is to indicate the total amount of experience required to reach a level, and indicate the stat increase for each 
levels up until level 100, for every pokemon in the game!

The structure of its sub-files, once decompressed, and after having been removed from its SIR0 container, 
is exactly the same for each of them. 

- 571 sub-files. 1 for each pokemons. And possibly a few that are used for special purpose, given there are less pokemon than that in gen 4?
- Exactly 100, 12 bytes entries, one after the other.
- The entry for level 1 is entirely null, given there is no level 0, and no exp requirements or stat growth needed. Base
 stats must be stored somewhere else!

The first three entries are for Bulbasaur, Ivysaur and Venusaur. The 3 are identical though. 
But if someone wanted it'd be possible to change each's stats growth individually!

The format of a single entry goes as follow:

Offset      Length      Type        Description
------      ------      ----        -----------
0x0         4           int32       The total amount of experience needed to reach that level.
0x4         2           uint16      HP growth for this level.
0x6         1           uint8       Attack growth for this level.
0x7         1           uint8       Defense growth for this level.
0x8         1           uint8       Special attack growth for this level.
0x9         1           uint8       Special defense growth for this level.
0xA         2           uint16      Null.
------      ------      ----        -----------
Total:      12 bytes

See my notes : https://dl.dropboxusercontent.com/u/13343993/my_pmd_research_files/FileFormats/m_level.txt

Also, I took a quick look at "/BALANCE/waza_p.bin". And looking at a japanese dictionary, "waza" or "わざ" or 技, means technique/art. It most likely refers to either moves or TMs. So I'm going to take a look at that too.

EDIT:

Here are the new utilities binaries that supports the sir0pkdpx and sir0at4px formats properly!:

ppmd_packfileutil 0.53: https://github.com/PsyCommando/ppmdu/releases/download/ppmd_packfileutil_0.53/ppmd_packfileutil_0_53.zip

ppmd_dopx 0.31 : https://github.com/PsyCommando/ppmdu/releases/download/ppmd_dopx_0.31/ppmd_dopx_0_31.zip

ppmd_unpx 0.41 : https://github.com/PsyCommando/ppmdu/releases/download/ppmd_unpx_0.41/ppmd_unpx_0_41.zip

Will update front page shortly.

Posted
Also, I took a quick look at "/BALANCE/waza_p.bin". And looking at a japanese dictionary, "waza" or "わざ" or 技, means technique/art. It most likely refers to either moves or TMs. So I'm going to take a look at that too.

Seeing that there's 2 waza_p files, I'd speculate that one is level up moves and the other is TMs. But I can't say since I've done no research on it at all. It would be cool to control this sort of thing.

Maybe in the near future I can use your tools/research to make an editor for m_level.bin, so we can be 100% sure which stat is which. It might be ordered differently, because I looked in JEditor's source for handling Pokémon, and the stats are ordered: Attack, Sp. Attack, Defense, Sp. Defense. It's also possible that the developers used an inconsistent order for storing stats, but that'd just feel weird.

Posted

It would be cool indeed ! xD

One thing I noticed is that, one of the section in the waza_p.bin file has a number of entries very close to the pokemon count, so maybe that's actually what it is.

Here's what I got on the file's layout this far:


Offset              Length      Type        Description:
-------             ------      ----        ------------
0x0                 4           char[4]     SIR0 magic number
0x4                 4           uint32      Pointer to WazaHeader
0x8                 4           uint32      Pointer to SIR0 encoded ptr list
0xC                 4           -           Null
DataBlockA                      -           Unknown
[
   ...
]
PaddingBytes        0-3         -           0xAA padding bytes to align the next block on 4 bytes.
DataBlockB                      -           Seems to contain pokemon data. Has 559 entries of 26 bytes each!
[
   Entry           26          -           An entry.
   [
   ]
   ...
]
PaddingBytes        0-15        -           0xAA padding bytes to align the next section  on 16 bytes.
PtrTable                        -           A table of pointers to entries within DataBlockA.
[
   Pointer         4           uint32      A pointer to an entry within DatablockA.
   ...
]
PaddingBytes        0-15        -           0xAA padding bytes to align the next section  on 16 bytes.
WazaHeader          8           -           The header the SIR0 refers to.
[
   PtrDataBlockB   4           uint32      A pointer to the beginning of DataBlockB.
   PtrPtrTable     4           uint32      A pointer to the beginning of the PtrTable.
]
PaddingBytes        0-15        -           0xAA padding bytes to align the next section  on 16 bytes.
SIR0EcodedPtrOffsets            -           The encoded ptr list for the SIR0 container.
[
   ...
]

https://dl.dropboxusercontent.com/u/13343993/my_pmd_research_files/FileFormats/waza_p.txt

Actually I tested changing values in the game, and it worked as expected, but I lost my evening yesterday, because I had a brainfart while trying to figure out which value is which. I forgot that I had a cheat to change the exp for the partner pokemon, which was bulbasaur. And I forgot it was on.

So I thought I was somehow corrupting the values because bulbasaur had always a negative exp count towards the next level. So I wasted a lot of time packing and repacking everything a hundred times, trying to figure out what I was doing wrong..

So, I'm still not too eager to test this yet again. For now xD

But I'm pretty sure this ordering is the correct one..

And what's JEditor ?

Posted
And what's JEditor ?

My program, Sky Editor, was the first save editor for Explorers of Sky. matix2267 did more research, especially on Pokémon, making Sky JEditor (Sky Editor, in Java).

Both our tools are open source, so I incorporated some of his java code into Sky Editor, applying it for the older games (Time/Darkness/Red/Blue).

If the stats are really stored in different orders in the save and ROM, the developers must have a cruel sense of humor. That, or they were made by different people who didn't directly collaborate.

Posted

Oh, alright. I thought you were saying an existing editor was able to edit m_level.bin. xD

And, if you're saying that they're in the opposite order in the savegame, its also possible they're in that order in the stat growth file. I had to guess the value over several level-up, because of that dumb mistake I did yesterday, so even though I put different values in each slots Its possible the reading was inaccurate...

But like I said, after I take a little break, I'll do this properly.

Unless you want to try it yourself ? I put up the updated tools you'd need to make this much much easier to edit than having to remove and put back the SIR0 container over the compressed pkdpx!

I also wrote 3 handy little batch scripts to batch decompress and compress the content of a folder passed as argument:

(just replace the exe names with however they're named on your side ^^;)

Batch compress to "sir0pkdpx" the content of a folder, and delete the input file:

@echo off
for %%f in (%1\*.*) do ( 
ppmd_dopx_xp.exe -z "%%f" "%%f.sir0pkdpx"
del "%%f"
)

Batch decompress only "sir0pkdpx" files inside a folder, and delete the input file:

@echo off
for %%f in (%1\*.sir0pkdpx) do (
ppmd_unpx_xp.exe "%%f"
del %%f
)

And here's another one to build the m_level.bin file with the forced fist file offset:

@Echo off
ppmd_packfileutil_xp.exe -a 0x1200 %1

All of these work with drag and drop, which is really convenient!

Howver, it might just be easier to just decompress, edit and recompress a single file xD

I recommend using bulbasaur, if you want to try, because we're sure he's always the very first pokemon!

Posted

Alright, I figured out the exact order of the stats:

Offset      Length      Type        Description
------      ------      ----        -----------
0x0         4           int32       The total amount of experience required to reach that level. The value is absolute, not relative to the last level!
0x4         2           uint16      HP growth for this level.
0x6         1           uint8       Attack growth for this level.
0x7         1           uint8       Special attack growth for this level.
0x8         1           uint8       Defense growth for this level.
0x9         1           uint8       Special defense growth for this level.
0xA         2           uint16      Null.
------      ------      ----        -----------
Total:      12 bytes

Its basically Attack, SpAttack, Defense, SpDefense.

I had to set to 0 the stats growth for the previous levels to get a better reading. And at the same time I noticed that the base stats for bulbasaur are :

Atk 3

Def 2

SpA 4

SpD 3

This will probably help finding where base stats are stored.

Posted (edited)

I figured out a big part of the format of "/BALANCE/monster.md" !

Its very straightforward. I was able to deduct a lot of it just by cross referencing and comparing pokemon with similarities together!

monster.md
-----------

This file contains the base data for every pokemon in the game.

NOTES:
- The first entry is a dummy entry.
- The file contains 1,155 entries.


Offset:                     Length:             Type:           Description:
-------                     -------             -------         -----------------------------------
0x0                         4                   char[4]         Magic number "MD\0\0" { 0x4D, 0x44, 0x0, 0x0 }
0x4                         4                   uint32          NbPokemonEntries
PokemonData                 (NbPokemonEntries-1)                This contains the data for all the pokemon in the game!
[
   PokemonEntry            68                                  Entry for a single pokemon.
   [
   0x00 NatDexNb#1          2                   uint16          National pokedex number. (Can be null in some entries)
   0x02 Category            2                   uint16          The index of the pokemon's category string. "Seed Pokemon" for example.(Can be null)
   0x04 NatDexNb#2          2                   uint16          The national pokedex number, again?
   0x06 Unk#1               2                   uint16          unknown, seems to be 0x1 for most pokemon ! In the later entries, it contains a number that increases.
   0x08 PreEvoDexNb         2                   uint16          The national pokdex number for this pokemon's pre-evo. Is 0 if no pre-evo!
   0x0A EvolutionMethod?    2                   uint16          The evolution method required to evolve to this pokemon. Null if unused. (See evolution methods below)
   0x0C EvoParam#1          2                   uint16          The first parameter for the evolution method. Null if unused.
   0x0E EvoParam#2          2                   uint16          The second parameter for the evolution method. Null if unused.
   0x10 SpriteIndex         2                   uint16          The index of the pokemon's sprite. Its the index inside the three pokemon sprite files inside the "/MONSTER/" directory!
   0x12 Unk#4               1                   uint8           Unknown
   0x13 Unk#5               1                   uint8           Unknown
   0x14 PrimaryType         1                   uint8           The pokemon's primary type. (see pokemon types below)
   0x15 SecondaryType       1                   uint8           The pokemon's secomdary type.
   0x16 Unk#8               1                   uint8           Unknown
   0x17 IQGroup             1                   uint8           The pokemon's IQ group (see IQ group below)
   0x18 PrimaryAbility?     1                   uint8           The pokemon's primary ability's ID. (see abilities below)
   0x19 SecondaryAbility?   1                   uint8           The pokemon's secondary ability's ID. (can be null)
   0x1A Unk#11              2                   uint16          Unknown 
   0x1C Unk#12              2                   uint16          Unknown
   0x1E Unk#13              2                   uint16          Unknown, often is the same value as Unk#14 !
   0x20 BaseHp?             2                   uint16          The hp the pokemon has at lvl 1?
   0x22 Unk#14              2                   uint16          Unknown, seems to often be the same value as Unk#13 !
   0x24 BaseAtk             1                   uint8           The attack stat of the pokemon at lvl 1.
   0x25 BaseSpAtk           1                   uint8           The special attack stat of the pokemon at lvl 1.
   0x26 BaseDef             1                   uint8           The defense stat of the pokemon at lvl 1.
   0x27 BaseSpDef           1                   uint8           The base special defense of the pokemon at lvl 1.
   0x28 Unk#15              2                   uint16          Unknown, seems to be 0x99 on several pre-evos.
   0x2A Unk#16              2                   uint16          Unknown
   0x2C Unk#17              1                   uint8           Unknown 
   0x2D Unk#18              1                   uint8           Unknown 
   0x2E Unk#19              1                   uint8           Unknown 
   0x2F Unk#20              1                   uint8           Unknown 
   0x30 Unk#21              2                   uint16          Possibly max level for the pokemon ?
   0x32 Unk#22              2                   uint16          Unknown.

   0x34 Unk#23              2                   uint16          Seems to be part of an array together with the 3 next values 
   0x36 Unk#24              2                   uint16      
   0x38 Unk#25              2                   uint16          
   0x3A Unk#26              2                   uint16          End of array.

   0x3C Unk#27              2                   uint16          Unknown
   0x3E Unk#28              2                   uint16          Unknown
   0x40 Unk#29              2                   uint16          Unknown 
   0x42 Unk#30              2                   uint16          Unknown 
   ]
   ...
]
-------                     -------             -------         -----------------------------------

===========================
  Evolution Requirements
===========================
Here are the possible values for the evolution requirement, 
and how the value of the parameter is used / split :

*NOT 100% sure*

Value       Method                  Parameter(s) ( 4 bytes available )
-----       ------                  -------------------------------------------------
0x01        Level(+Item)            (uint16)Level required to evolve,(uint16)Item ID
0x02        IQ(+Item)               (uint16)IQ Req,                  (uint16)Additional Item ID?       
0x03        Item(s)                 (uint16)Item ID ?                (uint16)Additional Item ID?

0x05        Link Cable              (uint16)0x00,                    (uint16)0x01    

Known Item IDs
---------------
0x8B - Up-Grade
0x8C - King's Rock
0x8D - Thunderstone
0x8E - Deep Sea Scale
0x8F - Deep Sea Tooth

0x91 - Moonstone 
0x92 - Fire Stone
0x93 - Water Stone
0x94 - Metal Coat

0x96 - Dragon Scale

0x98 - Dubious Disc

0x9A - Reaper Cloth
0x9B - Razor Fang
0x9C - Razor Claw
0x9D - Electirizer
0x9E - Magmarizer

0xA3 - Coronet Rock
0xA4 - Mossy Rock
0xA5 - Icy Rock

Known Other Item IDs ?
------------------
0x01 - Link Cable ?

0x04 - 
0x05 - Sun Ribbon
0x06 - Lunar Ribbon
0x07 - Beauty Scarf



### NOTE TO SELF : 3 evo-related uint16 for the following evos

IQ 
   Togetic     0x02 0x96 0x00
   Crobat      0x02 0x96 0x00
   Pikachu     0x02 0xC8 0x00

IQ + Item
   Espeon      0x02 0x64 0x05
   Umbreon     0x02 0x64 0x06

Link Cable
   Gengar      0x05 0x00 0x01

Item + Link Cable
   Slowing     0x03 0x8C 0x01
   Steelix     0x03 0x94 0x01 
   Kingdra     0x03 0x96 0x01
   Electivire  0x03 0x9D 0x01
   Magmortar   0x03 0x9E 0x01
   Porygon2    0x03 0x8B 0x01
   Porygon-Z   0x03 0x98 0x01
   Dusknoir    0x03 0x9A 0x01
   Gorebyss    0x03 0x8E 0x01 
   Huntail     0x03 0x8F 0x01

###


=======================
   Pokemon Types
=======================
Here are the possible values for the pokemon type bytes :

Value       Type
-----       ----------
0x00        -NONE-
0x01        Normal
0x02        Fire
0x03        Water
0x04        Grass
0x05        Electric
0x06        Ice
0x07        Fighting
0x08        Poison
0x09        Ground
0x0A        Flying
0x0B        Psychic
0x0C        Bug
0x0D        Rock
0x0E        Ghost
0x0F        Dragon
0x10        Dark
0x11        Steel


==============
  IQ Group
==============
Here are the possible values for a pokemon's IQ group:

Value       IQ Group
-----       ---------
0x00        A
0x01        B
0x02        C
0x03        D
0x04        E
0x05        F
0x06        G
0x07        H
0x08        -   (Not sure why those two are skipped )
0x09        -
0x0A        I
0x0B        J

=========================
   Pokemon Abilities
=========================
Here are the possible abilities:

Value           Ability
-----           ------------

0x06            Intimidate

0x10            Torrent

0x13            Shell Armor

0x24            Water Absorb

0x2B            Run Away

0x46            Blaze
0x47            Pickup

0x4C            Shield Dust

0x59            Gluttony

0x63            Adaptability

0x6D            Quick Feet

0x1A            Overgrow

(Latest version of my personal notes : https://dl.dropboxusercontent.com/u/13343993/my_pmd_research_files/FileFormats/monster.md.txt )

I'm also working on a utility to organize and convert all the stats data spread over several files inside the /BALANCE/ directory into XML, along with possibly the other data directories introduced in EoS.

I'm going for a one file per pokemon and per category approach this time, since its much less complex than the sprites! Of course, the utility will be able to put everything back together into the appropriate files from the XML!

(For the "mappa_*.bin" and "mappa_g*.bin" files I'll have to do something differently probably, as those are tightly linked to every individual dungeons.)

EDIT:

Seems like I forgot that truepikachu already had figured out a big chunk of "monster.md" and the stats growth..

http://projectpokemon.org/forums/showthread.php?40199-Pokemon-Mystery-Dungeon-2-Psy_commando-s-Tools-and-research-notes&p=192560&viewfull=1#post192560

Anyways, I guess at least I validated some of those things... Though I wasted a lot of time doing all that from scratch.. :/

Edited by psy_commando
Posted
Here I have what I found from part of the RAM.

This is just about a pokemon while in a dungeon, at some point I will post the other bits I found.

If PMD2's Pokemon data is set up like PMD1's is (which is likely), the block you found does not contain all of the hero Pokemon's data. The tile the Pokemon is currently standing on has a pointer to the beginning of the Pokemon's data, which in turn has a pointer to the beginning of that block.

Posted

So I learned some more stuff on the monster.md, m_level.bin, and waza_p.bin files!

waza_p.bin contains the list of level-up moves, HM/TM moves, and egg moves that each pokemon can learn! Each group of 3 pointers points to the 3 lists for a single pokemon. The lists are encoded integers, and should be decoded in a similar fashion to the SIR0 encoded ptr offset list, without adding each subsequent results to each others, just like the stats growth entries in m_level.bin!

The level-up move list is basically just the move id, and then the level at which its learned. The HM/TMs list and egg moves list are just a list of move ids.

Here are the values for Bulbasaur decoded by hand:

Level-Up list:
81 1A 01    => 0x9A,   1  => Tackle         lvl  1
81 59 03    => 0xD9,   3  => Growl          lvl  3
82 49 07    => 0x149,  7  => Leech Seed     lvl  7
81 36 09    => 0xB6,   9  => Vine Whip      lvl  9
81 47 0D    => 0xC7,  13  => Poison Powder  lvl 13
81 67 0D    => 0xE7,  13  => Sleep Powder   lvl 13
81 4B 0F    => 0xCB,  15  => Take Down      lvl 15
81 7B 13    => 0xFB,  19  => Razor Leaf     lvl 19
0A 15       => 0x0A,  21  => Sweet Scent    lvl 21
81 14 19    => 0x94,  25  => Growth         lvl 25
81 0C 1B    => 0x8C,  27  => Double-Edge    lvl 27
83 78 1F    => 0x1F8, 31  => Worry Seed     lvl 31
5E 21       => 0x5E,  33  => Synthesis      lvl 33
83 66 25    => 0x1E6, 37  => Seed Bomb      lvl 37
00

HM/TMs list:
0x12        => 18         => Cut
0x18        => 24         => Swagger
0x1D        => 29         => Rock Smash
0x30        => 48         => Return
0x32        => 50         => Strength
0x38        => 56         => Double Team
0x43        => 67         => Facade
0x4C        => 76         => Giga-Drain
0x68        => 104        => Endure
0x81 0x17   => 151        => Solar Beam
0x81 0x23   => 163        => Bullet Seed
0x81 0x35   => 181        => Swords Dance
0x81 0x45   => 197        => Toxic
0x81 0x5F   => 223        => Sunny Day 
0x81 0x63   => 227        => Sleep Talk
0x81 0x68   => 232        => Rest
0x82 0x07   => 263        => Secret Power
0x82 0x11   => 273        => Flash
0x82 0x18   => 280        => Sludge Bomb
0x82 0x2D   => 301        => Protect
0x82 0x30   => 304        => Substitute
0x82 0x44   => 324        => Hidden Power
0x82 0x46   => 326        => Attract
0x82 0x48   => 328        => Frustration
0x82 0x68   => 360        => Wide Slash
0x83 0x0A   => 394        => Vacuum-Cut
0x83 0x3B   => 443        => Energy Ball
0x83 0x4A   => 458        => Grass Knot
0x83 0x57   => 471        => Natural Gift
0x84 0x16   => 534        => Captivate
0x00 

egg moves list:
0x0B        => 11         => Charm
0x54        => 84         => Grass Whistle
0x77        => 119        => Nature Power
0x81 0x06   => 134        => Safeguard
0x81 0x57   => 215        => Amnesia
0x81 0x69   => 233        => Ingrain
0x81 0x6D   => 237        => Curse
0x81 0x7D   => 253        => Petal Dance
0x82 0x03   => 259        => Light Screen
0x82 0x29   => 297        => Magical Leaf
0x82 0x5C   => 348        => Skull Bash
0x84 0x19   => 537        => Leaf Storm
0x00 

(I used the "item_p_Sky.xlsx" excel datasheet (the keyvalues sheet) from over there to get the move ids : http://apointlessplace.net/wms/research/ )

Here are my latest notes on the format:

https://dl.dropboxusercontent.com/u/13343993/my_pmd_research_files/FileFormats/waza_p.txt

The other part of the file contains data for every single moves in the game! They're all ordered in the same way as in the excel sheet.

Move #1 is Iron Tail for example. The typing of the move is not contained in there however.. Replacing everything with random junk changed the way the move worked, the effects, the amount of PPs, the accuracy, and etc. But not the typing..

Also, I'm able to parse and write back perfectly the waza_p.bin and monster.md files now with my code!

m_level.bin isn't perfect, but only because my PX compression algorithm is a little less efficient on that kind of data. The file is read fine in-game however. They probably have some kind of optimization going on depending on the type of content. I usually get better compression on images, by on data that doesn't repeat itself a lot I get worse results than the original files. Still its like 5% bigger, so not such a big issue..

I still don't know what the waza_p2.bin file is for exactly... waza_p2.bin is only in EoS, and has a lot of duplicate entries with waza_p.bin, from looking at a binary comparison. I don't know yet how the game decides which one to use, or if its even using both!

Also, changing all entries in "monster.md" to 0 or 1 randomly will cause this :

https://dl.dropboxusercontent.com/u/13343993/my_pmd_research_files/randomvals_monstermd4.avi

https://dl.dropboxusercontent.com/u/13343993/my_pmd_research_files/randomvals_monstermd5.avi

Notice how for some reasons some pokes that don't evolve normally, like chatot are the evolved form of bulbasaur, instead of being a bulbasaur..

Also notice how the AI refuses to move around, I'm not exactly sure why.. And the base experience gain seems to be stored somewhere in monster.md, since I would only get 1 exp from fainting starly.

The game seems fairly robust with random values (still nowhere near as robust as Pokemon xD: Gale of Darkness! That game was unkillable xD )

Now, the big issue I'm left with, is that I have no ideas how the game associates the data in monster.md, with the rest spread around several other files.. :/

They all have a different amount of entries..

   MoveSets    : 553
   StatsGrowth : 571
   MonsterMD   : 1,155
   Kaomado     : 1,155

And it appears that, "monster.md" doesn't contain info on what entry in each files to use.. kaomado.kao and monster.md are however perfectly aligned to eachothers, and the portraits are most likely assigned by matching entry indexes from both files! But, it doesn't appear to be the case for the others.

This is very, very problematic, because as long as I can't figure this out, I'm stuck. I can't output or label properly the data I'd convert from those files, if I can't link them together! Any input or ideas on how to find those links would be really much appreciated !! I'm guessing there is a possibility its a table inside the overlays, or the main binary..

And while I'm working on ppmd_statsutil, here are 2 little utilities for ROM researchers. If you have no ideas what they're for, you probably don't need those. They're just more convenient than having to decode all those numbers by hand :

  • SIR0PtrOffsetsDecoder : Use this to decode a SIR0 pointer offset list, which can help tremendously in finding out more about what a sir0 file contains! Just copy/paste the SIR0's ptr offset list only, and put it into its own separate file, and drag-and-drop that onto the .bat file, it will output the result in "decoded.txt". The program itself only output the result to the console, so use the batch script, or pipe the output!
  • IntegerListDecoder : Use this one to decode a list of encoded integers. Things like the stats growths in "m_level.bin", the move lists in "waza_p.bin". You can just put all the lists one after the other in a new file, and drag-and-drop that onto the .bat file and all the decoded lists will be outputed to "decoded.txt" !

Here I have what I found from part of the RAM.

This is just about a pokemon while in a dungeon, at some point I will post the other bits I found.

Thanks! It might come in handy later!

That "faction" ally/enemy byte stands out as pretty interesting to me! Its an odd way of doing things.

Posted

Alright, so I figured out how they're all linked together..

Its something I was told several times over, but I never really believed...

The pokemons in kaomado.kao, and monster.md, aren't pokemon, but more like unique entities. And for every single pokemon, there is duplicate entity with for only difference its gender. For pokemons with a single gender or one that's genderless, that second entry has an invalid gender value.

This basically means that, it would be possiblt to add face portraits for the females of any species if you've want to xD

Also for people using the awesome Hex Edit hexeditor(I don't think I could have figured half of everything I did without that hexeditor! xD Rainbow hex data color scheme ftw! Source code is also available), I managed to implement integer decoding and sir0 offset decoding! Using this I was able to make a move data viewer, and a SIR0 pointer locator. It makes things so easy.

So I'm going to share them here (Just put the xml files in your Hexedit appdata folder. Or wherever you put your template folder if you changed it from the default. By default, just open up a file explorer window and type this in the address bar : "%APPDATA%\ECSoftware\HexEdit" without quotes, and paste the xml files in there. )

And then to open them, just open the file you want to use this on, and go into the top menu bar "Template->Open Other->waza_p.bin" for the waza_p.bin file, or "Template->Open File Type->SIR0 File". If your SIR0 file has .sir0 file extension, hex edit will open it automatically once you open the template sidebar ! To open the template sidebar, just go into the "Template" menu, and check either "Split Window" or "Tabbed Window". To hide the template sidebar, just check "Hide Tree View".

For people looking to find the pointer location in an unknown SIR0 file, this would probably come in handy :

SIR0_TemplateExample.png

Template file here: https://dl.dropboxusercontent.com/u/13343993/my_pmd_research_files/hexedit_templates/_sir0.xml

And for those looking to investigate or modify move data in the waza_p.bin files :

DisplaysExample_Bulbasaur.png

Template file here : https://dl.dropboxusercontent.com/u/13343993/my_pmd_research_files/hexedit_templates/waza_p.bin.xml

By default however, Hex Edit will only display the first 20 elements in all lists. To change that, go into "Tools->Options->Workspace->Templates" and set the value to something bigger, I usually set mine to 600+, when not testing, and I set it to a lower value when testing, because some templates can freeze the whole thing when they're very complex!

IncreaseTheAmountOfEntriesDisplayedInTreeView.png

And to see the actual values, and edit them easily, you should right click on the grey bar with the name of the template, and check the "Data" entry in the popup menu.

SeeDataFieldRightClickOnGrayBarAndCheckOption.png

Stretch the sidebar as needed. And then, when its possible to edit data, you can just double click on the data, and you'll be able to edit the value and input it as either hex or decimal, or when its an enum field, you'll even get a nice dropdown menu for picking an option !

Just be sure to uncheck "Design Mode" in the "Template" menu, because it will freeze. The structure of the whole thing in design mode is a little too much to handle for the tree display. I wrote it all directly in the XML, so I didn't use design mode much.

https://dl.dropboxusercontent.com/u/13343993/my_pmd_research_files/Tutorials/UsingHexEditTemplate/RecommendedSettings.png

Both of those template are pretty complex, and might freeze Hex Edit for a minute, so give it some time. Mainly the waza_p.bin.xml one, because its doing a lot of processing, and I'm not good at optimizing those things xD The SIR0 one is nearly instant on my computer though, on a file with a good amount of pointers offsets to parse.

Of course, those are just research tools, and I'm still working on ppmd_statsutil and etc..

IncreaseTheAmountOfEntriesDisplayedInTre

SeeDataFieldRightClickOnGrayBarAndCheckO

  • 2 weeks later...
Posted

So, after nearly a month of messing around, here's the first alpha release for ppmd_statsutil! :D

https://github.com/PsyCommando/ppmdu/releases/download/ppmd_statsutil_0.1a/ppmd_statsutil_0_1.zip

Its nothing all that great yet though, but I figured I might as well release something, and see if it helps figuring out the remaining details about the game data!

Right now, it supports only exporting/importing Pokemon data, move data, and the game text. And it only works with Explorers of Sky this far, at least AFAIK(didn't test with the others yet). And only doing so one at a time!

Don't try drag and drop on this one! It won't work. There's no way to figure out what you want from doing that!

You have to specify at the command line whether you're importing or exporting with the "-i" or "-e" option. And then you must specify what you want to export/import using the "-pk" "-mv" or "-str" option, for respectively, pokemon data, move data, and game strings.

Move data and Pokemon data are exported to XML, and the game strings are exported to a text file, where each line is a single string entry. All control characters are escaped using a backslash. For example \n is a newline, and \0 marks the end of the string. Other unprintable characters are represented using a decimal number after a backslash, instead of a character.

To edit anything you'll need to have a reference for the move IDs and ability, type, movement ids and etc.. This is because while nearly all of those have strings associated, most of those values contain duplicate strings, which makes it unpractical and extremely error prone. Plus, the tool is mainly intended to be used by another more complete tool with a user interface that would handle this kind of things.

Luckily, you can find references in a couple of places, namely the project pokemon wiki ! :

http://projectpokemon.org/wiki/Pmd2_monster.md

and the item_p_Sky.xlsx file over there !:

http://apointlessplace.net/wms/research/

Here's bulbasaur's XML data as example :

<?xml version="1.0"?>
<Pokemon GameVersion="EoS">
<!--In-game text-->
<Strings>
	<Name>Bulbasaur</Name>
	<Category>Seed</Category>
</Strings>
<!--Primary gender entity-->
<GenderedEntity>
	<PokeID>1</PokeID>
	<Unk31>1</Unk31>
	<PokedexNumber>1</PokedexNumber>
	<Unk1>1</Unk1>
	<EvolutionReq>
		<PreEvoIndex>0</PreEvoIndex>
		<Method>0</Method>
		<Param1>0</Param1>
		<Param2>0</Param2>
	</EvolutionReq>
	<SpriteIndex>0</SpriteIndex>
	<Gender>1</Gender>
	<BodySize>1</BodySize>
	<PrimaryType>4</PrimaryType>
	<SecondaryType>8</SecondaryType>
	<MovementType>0</MovementType>
	<IQGroup>5</IQGroup>
	<PrimaryAbility>26</PrimaryAbility>
	<SecondaryAbility>0</SecondaryAbility>
	<Bitfield>0x70</Bitfield>
	<ExpYield>7</ExpYield>
	<RecruitRate1>82</RecruitRate1>
	<RecruitRate2>82</RecruitRate2>
	<BaseStats>
		<HP>22</HP>
		<Attack>3</Attack>
		<SpAttack>4</SpAttack>
		<Defense>2</Defense>
		<SpDefense>3</SpDefense>
	</BaseStats>
	<Weight>153</Weight>
	<Size>27</Size>
	<Unk17>0xa</Unk17>
	<Unk18>0xa</Unk18>
	<Unk19>0x1</Unk19>
	<Unk20>0x8</Unk20>
	<Unk21>0x64</Unk21>
	<BasePokemonIndex>1</BasePokemonIndex>
	<ExclusiveItems>
		<ItemID>574</ItemID>
		<ItemID>575</ItemID>
		<ItemID>576</ItemID>
		<ItemID>577</ItemID>
	</ExclusiveItems>
	<Unk27>0x2ee</Unk27>
	<Unk28>0x15</Unk28>
	<Unk29>0x1b</Unk29>
	<Unk30>0x1c</Unk30>
</GenderedEntity>
<!--Secondary gender entity-->
<GenderedEntity>
	<PokeID>1</PokeID>
	<Unk31>1</Unk31>
	<PokedexNumber>1</PokedexNumber>
	<Unk1>1</Unk1>
	<EvolutionReq>
		<PreEvoIndex>0</PreEvoIndex>
		<Method>0</Method>
		<Param1>0</Param1>
		<Param2>0</Param2>
	</EvolutionReq>
	<SpriteIndex>0</SpriteIndex>
	<Gender>2</Gender>
	<BodySize>1</BodySize>
	<PrimaryType>4</PrimaryType>
	<SecondaryType>8</SecondaryType>
	<MovementType>0</MovementType>
	<IQGroup>5</IQGroup>
	<PrimaryAbility>26</PrimaryAbility>
	<SecondaryAbility>0</SecondaryAbility>
	<Bitfield>0x70</Bitfield>
	<ExpYield>7</ExpYield>
	<RecruitRate1>82</RecruitRate1>
	<RecruitRate2>82</RecruitRate2>
	<BaseStats>
		<HP>22</HP>
		<Attack>3</Attack>
		<SpAttack>4</SpAttack>
		<Defense>2</Defense>
		<SpDefense>3</SpDefense>
	</BaseStats>
	<Weight>153</Weight>
	<Size>27</Size>
	<Unk17>0xa</Unk17>
	<Unk18>0xa</Unk18>
	<Unk19>0x1</Unk19>
	<Unk20>0x8</Unk20>
	<Unk21>0x64</Unk21>
	<BasePokemonIndex>1</BasePokemonIndex>
	<ExclusiveItems>
		<ItemID>574</ItemID>
		<ItemID>575</ItemID>
		<ItemID>576</ItemID>
		<ItemID>577</ItemID>
	</ExclusiveItems>
	<Unk27>0x2ee</Unk27>
	<Unk28>0x15</Unk28>
	<Unk29>0x1b</Unk29>
	<Unk30>0x1c</Unk30>
</GenderedEntity>
<StatsGrowth>
	<!--Level 1-->
	<Level>
		<RequiredExp>0</RequiredExp>
		<HP>0</HP>
		<Attack>0</Attack>
		<SpAttack>0</SpAttack>
		<Defense>0</Defense>
		<SpDefense>0</SpDefense>
	</Level>
	<!--Level 2-->
	<Level>
		<RequiredExp>9</RequiredExp>
		<HP>3</HP>
		<Attack>1</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 3-->
	<Level>
		<RequiredExp>23</RequiredExp>
		<HP>2</HP>
		<Attack>1</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 4-->
	<Level>
		<RequiredExp>40</RequiredExp>
		<HP>2</HP>
		<Attack>2</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 5-->
	<Level>
		<RequiredExp>88</RequiredExp>
		<HP>3</HP>
		<Attack>2</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 6-->
	<Level>
		<RequiredExp>193</RequiredExp>
		<HP>3</HP>
		<Attack>2</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 7-->
	<Level>
		<RequiredExp>300</RequiredExp>
		<HP>2</HP>
		<Attack>2</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 8-->
	<Level>
		<RequiredExp>563</RequiredExp>
		<HP>2</HP>
		<Attack>2</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 9-->
	<Level>
		<RequiredExp>1136</RequiredExp>
		<HP>3</HP>
		<Attack>2</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 10-->
	<Level>
		<RequiredExp>1711</RequiredExp>
		<HP>2</HP>
		<Attack>2</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 11-->
	<Level>
		<RequiredExp>2616</RequiredExp>
		<HP>2</HP>
		<Attack>2</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 12-->
	<Level>
		<RequiredExp>4828</RequiredExp>
		<HP>3</HP>
		<Attack>2</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 13-->
	<Level>
		<RequiredExp>7046</RequiredExp>
		<HP>2</HP>
		<Attack>2</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 14-->
	<Level>
		<RequiredExp>10985</RequiredExp>
		<HP>3</HP>
		<Attack>2</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 15-->
	<Level>
		<RequiredExp>14927</RequiredExp>
		<HP>2</HP>
		<Attack>2</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 16-->
	<Level>
		<RequiredExp>19348</RequiredExp>
		<HP>3</HP>
		<Attack>2</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 17-->
	<Level>
		<RequiredExp>23774</RequiredExp>
		<HP>2</HP>
		<Attack>2</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 18-->
	<Level>
		<RequiredExp>28688</RequiredExp>
		<HP>3</HP>
		<Attack>2</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 19-->
	<Level>
		<RequiredExp>33607</RequiredExp>
		<HP>2</HP>
		<Attack>2</Attack>
		<SpAttack>2</SpAttack>
		<Defense>2</Defense>
		<SpDefense>2</SpDefense>
	</Level>
	<!--Level 20-->
	<Level>
		<RequiredExp>38528</RequiredExp>
		<HP>3</HP>
		<Attack>1</Attack>
		<SpAttack>2</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 21-->
	<Level>
		<RequiredExp>43488</RequiredExp>
		<HP>3</HP>
		<Attack>1</Attack>
		<SpAttack>2</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 22-->
	<Level>
		<RequiredExp>49233</RequiredExp>
		<HP>3</HP>
		<Attack>1</Attack>
		<SpAttack>2</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 23-->
	<Level>
		<RequiredExp>54983</RequiredExp>
		<HP>3</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 24-->
	<Level>
		<RequiredExp>60739</RequiredExp>
		<HP>3</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 25-->
	<Level>
		<RequiredExp>68068</RequiredExp>
		<HP>3</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 26-->
	<Level>
		<RequiredExp>76985</RequiredExp>
		<HP>3</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 27-->
	<Level>
		<RequiredExp>86688</RequiredExp>
		<HP>3</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 28-->
	<Level>
		<RequiredExp>97176</RequiredExp>
		<HP>3</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 29-->
	<Level>
		<RequiredExp>108451</RequiredExp>
		<HP>3</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 30-->
	<Level>
		<RequiredExp>120511</RequiredExp>
		<HP>3</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 31-->
	<Level>
		<RequiredExp>133358</RequiredExp>
		<HP>3</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 32-->
	<Level>
		<RequiredExp>146991</RequiredExp>
		<HP>3</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 33-->
	<Level>
		<RequiredExp>162993</RequiredExp>
		<HP>3</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 34-->
	<Level>
		<RequiredExp>179782</RequiredExp>
		<HP>3</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 35-->
	<Level>
		<RequiredExp>197356</RequiredExp>
		<HP>2</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 36-->
	<Level>
		<RequiredExp>215717</RequiredExp>
		<HP>2</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 37-->
	<Level>
		<RequiredExp>234863</RequiredExp>
		<HP>2</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 38-->
	<Level>
		<RequiredExp>254795</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 39-->
	<Level>
		<RequiredExp>275513</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 40-->
	<Level>
		<RequiredExp>297017</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>0</SpDefense>
	</Level>
	<!--Level 41-->
	<Level>
		<RequiredExp>319308</RequiredExp>
		<HP>1</HP>
		<Attack>0</Attack>
		<SpAttack>1</SpAttack>
		<Defense>0</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 42-->
	<Level>
		<RequiredExp>342385</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>0</SpAttack>
		<Defense>1</Defense>
		<SpDefense>0</SpDefense>
	</Level>
	<!--Level 43-->
	<Level>
		<RequiredExp>366247</RequiredExp>
		<HP>1</HP>
		<Attack>0</Attack>
		<SpAttack>1</SpAttack>
		<Defense>0</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 44-->
	<Level>
		<RequiredExp>391681</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>0</SpAttack>
		<Defense>1</Defense>
		<SpDefense>0</SpDefense>
	</Level>
	<!--Level 45-->
	<Level>
		<RequiredExp>418687</RequiredExp>
		<HP>1</HP>
		<Attack>0</Attack>
		<SpAttack>1</SpAttack>
		<Defense>0</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 46-->
	<Level>
		<RequiredExp>447265</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>0</SpAttack>
		<Defense>1</Defense>
		<SpDefense>0</SpDefense>
	</Level>
	<!--Level 47-->
	<Level>
		<RequiredExp>477415</RequiredExp>
		<HP>1</HP>
		<Attack>0</Attack>
		<SpAttack>1</SpAttack>
		<Defense>0</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 48-->
	<Level>
		<RequiredExp>509138</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>0</SpAttack>
		<Defense>1</Defense>
		<SpDefense>0</SpDefense>
	</Level>
	<!--Level 49-->
	<Level>
		<RequiredExp>542432</RequiredExp>
		<HP>1</HP>
		<Attack>0</Attack>
		<SpAttack>1</SpAttack>
		<Defense>0</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 50-->
	<Level>
		<RequiredExp>577298</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>0</SpAttack>
		<Defense>1</Defense>
		<SpDefense>0</SpDefense>
	</Level>
	<!--Level 51-->
	<Level>
		<RequiredExp>613736</RequiredExp>
		<HP>1</HP>
		<Attack>0</Attack>
		<SpAttack>1</SpAttack>
		<Defense>0</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 52-->
	<Level>
		<RequiredExp>651746</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>0</SpAttack>
		<Defense>1</Defense>
		<SpDefense>0</SpDefense>
	</Level>
	<!--Level 53-->
	<Level>
		<RequiredExp>691054</RequiredExp>
		<HP>1</HP>
		<Attack>0</Attack>
		<SpAttack>1</SpAttack>
		<Defense>0</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 54-->
	<Level>
		<RequiredExp>730368</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>0</SpAttack>
		<Defense>1</Defense>
		<SpDefense>0</SpDefense>
	</Level>
	<!--Level 55-->
	<Level>
		<RequiredExp>769691</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>0</SpAttack>
		<Defense>1</Defense>
		<SpDefense>0</SpDefense>
	</Level>
	<!--Level 56-->
	<Level>
		<RequiredExp>809022</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>0</SpAttack>
		<Defense>1</Defense>
		<SpDefense>0</SpDefense>
	</Level>
	<!--Level 57-->
	<Level>
		<RequiredExp>848361</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>0</SpAttack>
		<Defense>1</Defense>
		<SpDefense>0</SpDefense>
	</Level>
	<!--Level 58-->
	<Level>
		<RequiredExp>887707</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>0</SpAttack>
		<Defense>1</Defense>
		<SpDefense>0</SpDefense>
	</Level>
	<!--Level 59-->
	<Level>
		<RequiredExp>927061</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>0</SpAttack>
		<Defense>1</Defense>
		<SpDefense>0</SpDefense>
	</Level>
	<!--Level 60-->
	<Level>
		<RequiredExp>966424</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 61-->
	<Level>
		<RequiredExp>1005793</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 62-->
	<Level>
		<RequiredExp>1045171</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 63-->
	<Level>
		<RequiredExp>1084557</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 64-->
	<Level>
		<RequiredExp>1123951</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 65-->
	<Level>
		<RequiredExp>1163352</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 66-->
	<Level>
		<RequiredExp>1202761</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 67-->
	<Level>
		<RequiredExp>1242179</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 68-->
	<Level>
		<RequiredExp>1281604</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 69-->
	<Level>
		<RequiredExp>1321036</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 70-->
	<Level>
		<RequiredExp>1360477</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 71-->
	<Level>
		<RequiredExp>1399926</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 72-->
	<Level>
		<RequiredExp>1439383</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 73-->
	<Level>
		<RequiredExp>1478847</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 74-->
	<Level>
		<RequiredExp>1518319</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 75-->
	<Level>
		<RequiredExp>1557799</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 76-->
	<Level>
		<RequiredExp>1597287</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 77-->
	<Level>
		<RequiredExp>1636783</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 78-->
	<Level>
		<RequiredExp>1676287</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 79-->
	<Level>
		<RequiredExp>1715798</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 80-->
	<Level>
		<RequiredExp>1755317</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 81-->
	<Level>
		<RequiredExp>1794845</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 82-->
	<Level>
		<RequiredExp>1834380</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 83-->
	<Level>
		<RequiredExp>1873922</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 84-->
	<Level>
		<RequiredExp>1913473</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 85-->
	<Level>
		<RequiredExp>1953032</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 86-->
	<Level>
		<RequiredExp>1992599</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 87-->
	<Level>
		<RequiredExp>2032173</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 88-->
	<Level>
		<RequiredExp>2071756</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 89-->
	<Level>
		<RequiredExp>2111345</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 90-->
	<Level>
		<RequiredExp>2150943</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 91-->
	<Level>
		<RequiredExp>2190549</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 92-->
	<Level>
		<RequiredExp>2230163</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 93-->
	<Level>
		<RequiredExp>2269785</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 94-->
	<Level>
		<RequiredExp>2309414</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 95-->
	<Level>
		<RequiredExp>2349052</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 96-->
	<Level>
		<RequiredExp>2388696</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 97-->
	<Level>
		<RequiredExp>2428349</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 98-->
	<Level>
		<RequiredExp>2468010</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 99-->
	<Level>
		<RequiredExp>2507679</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
	<!--Level 100-->
	<Level>
		<RequiredExp>2547402</RequiredExp>
		<HP>1</HP>
		<Attack>1</Attack>
		<SpAttack>1</SpAttack>
		<Defense>1</Defense>
		<SpDefense>1</SpDefense>
	</Level>
</StatsGrowth>
<!--Moveset from waza_p.bin-->
<Moveset>
	<!--Learns 14 move(s)-->
	<LevelUpMoves>
		<Learn>
			<Level>1</Level>
			<MoveID>154</MoveID>
		</Learn>
		<Learn>
			<Level>3</Level>
			<MoveID>217</MoveID>
		</Learn>
		<Learn>
			<Level>7</Level>
			<MoveID>329</MoveID>
		</Learn>
		<Learn>
			<Level>9</Level>
			<MoveID>182</MoveID>
		</Learn>
		<Learn>
			<Level>13</Level>
			<MoveID>199</MoveID>
		</Learn>
		<Learn>
			<Level>13</Level>
			<MoveID>231</MoveID>
		</Learn>
		<Learn>
			<Level>15</Level>
			<MoveID>203</MoveID>
		</Learn>
		<Learn>
			<Level>19</Level>
			<MoveID>251</MoveID>
		</Learn>
		<Learn>
			<Level>21</Level>
			<MoveID>10</MoveID>
		</Learn>
		<Learn>
			<Level>25</Level>
			<MoveID>148</MoveID>
		</Learn>
		<Learn>
			<Level>27</Level>
			<MoveID>140</MoveID>
		</Learn>
		<Learn>
			<Level>31</Level>
			<MoveID>504</MoveID>
		</Learn>
		<Learn>
			<Level>33</Level>
			<MoveID>94</MoveID>
		</Learn>
		<Learn>
			<Level>37</Level>
			<MoveID>486</MoveID>
		</Learn>
	</LevelUpMoves>
	<!--Has 12 egg move(s)-->
	<EggMoves>
		<MoveID>11</MoveID>
		<MoveID>84</MoveID>
		<MoveID>119</MoveID>
		<MoveID>134</MoveID>
		<MoveID>215</MoveID>
		<MoveID>233</MoveID>
		<MoveID>237</MoveID>
		<MoveID>253</MoveID>
		<MoveID>259</MoveID>
		<MoveID>297</MoveID>
		<MoveID>348</MoveID>
		<MoveID>537</MoveID>
	</EggMoves>
	<!--Can learn 30 HM/TM move(s)-->
	<HmTmMoves>
		<MoveID>18</MoveID>
		<MoveID>24</MoveID>
		<MoveID>29</MoveID>
		<MoveID>48</MoveID>
		<MoveID>50</MoveID>
		<MoveID>56</MoveID>
		<MoveID>67</MoveID>
		<MoveID>76</MoveID>
		<MoveID>104</MoveID>
		<MoveID>151</MoveID>
		<MoveID>163</MoveID>
		<MoveID>181</MoveID>
		<MoveID>197</MoveID>
		<MoveID>223</MoveID>
		<MoveID>227</MoveID>
		<MoveID>232</MoveID>
		<MoveID>263</MoveID>
		<MoveID>273</MoveID>
		<MoveID>280</MoveID>
		<MoveID>301</MoveID>
		<MoveID>304</MoveID>
		<MoveID>324</MoveID>
		<MoveID>326</MoveID>
		<MoveID>328</MoveID>
		<MoveID>360</MoveID>
		<MoveID>394</MoveID>
		<MoveID>443</MoveID>
		<MoveID>458</MoveID>
		<MoveID>471</MoveID>
		<MoveID>534</MoveID>
	</HmTmMoves>
</Moveset>
<!--Moveset from waza_p2.bin-->
<Moveset>
	<!--Learns 14 move(s)-->
	<LevelUpMoves>
		<Learn>
			<Level>1</Level>
			<MoveID>154</MoveID>
		</Learn>
		<Learn>
			<Level>3</Level>
			<MoveID>217</MoveID>
		</Learn>
		<Learn>
			<Level>7</Level>
			<MoveID>329</MoveID>
		</Learn>
		<Learn>
			<Level>9</Level>
			<MoveID>182</MoveID>
		</Learn>
		<Learn>
			<Level>13</Level>
			<MoveID>199</MoveID>
		</Learn>
		<Learn>
			<Level>13</Level>
			<MoveID>231</MoveID>
		</Learn>
		<Learn>
			<Level>15</Level>
			<MoveID>203</MoveID>
		</Learn>
		<Learn>
			<Level>19</Level>
			<MoveID>251</MoveID>
		</Learn>
		<Learn>
			<Level>21</Level>
			<MoveID>10</MoveID>
		</Learn>
		<Learn>
			<Level>25</Level>
			<MoveID>148</MoveID>
		</Learn>
		<Learn>
			<Level>27</Level>
			<MoveID>140</MoveID>
		</Learn>
		<Learn>
			<Level>31</Level>
			<MoveID>504</MoveID>
		</Learn>
		<Learn>
			<Level>33</Level>
			<MoveID>94</MoveID>
		</Learn>
		<Learn>
			<Level>37</Level>
			<MoveID>486</MoveID>
		</Learn>
	</LevelUpMoves>
	<!--Has 12 egg move(s)-->
	<EggMoves>
		<MoveID>11</MoveID>
		<MoveID>84</MoveID>
		<MoveID>119</MoveID>
		<MoveID>134</MoveID>
		<MoveID>215</MoveID>
		<MoveID>233</MoveID>
		<MoveID>237</MoveID>
		<MoveID>253</MoveID>
		<MoveID>259</MoveID>
		<MoveID>297</MoveID>
		<MoveID>348</MoveID>
		<MoveID>537</MoveID>
	</EggMoves>
	<!--Can learn 30 HM/TM move(s)-->
	<HmTmMoves>
		<MoveID>18</MoveID>
		<MoveID>24</MoveID>
		<MoveID>29</MoveID>
		<MoveID>48</MoveID>
		<MoveID>50</MoveID>
		<MoveID>56</MoveID>
		<MoveID>67</MoveID>
		<MoveID>76</MoveID>
		<MoveID>104</MoveID>
		<MoveID>151</MoveID>
		<MoveID>163</MoveID>
		<MoveID>181</MoveID>
		<MoveID>197</MoveID>
		<MoveID>223</MoveID>
		<MoveID>227</MoveID>
		<MoveID>232</MoveID>
		<MoveID>263</MoveID>
		<MoveID>273</MoveID>
		<MoveID>280</MoveID>
		<MoveID>301</MoveID>
		<MoveID>304</MoveID>
		<MoveID>324</MoveID>
		<MoveID>326</MoveID>
		<MoveID>328</MoveID>
		<MoveID>360</MoveID>
		<MoveID>394</MoveID>
		<MoveID>443</MoveID>
		<MoveID>458</MoveID>
		<MoveID>471</MoveID>
		<MoveID>534</MoveID>
	</HmTmMoves>
</Moveset>
</Pokemon>

And here's the XML data for the move Iron Tail as an example :

<?xml version="1.0"?>
<Move>
<!--Pokemon Mystery Dungeon: Explorers of Sky move data-->
<!--In-game text-->
<Strings>
	<Name>Iron Tail</Name>
	<Description>"Basic Information"[CS:E][bAR][CR]\nInflicts damage on the target. It may\nalso reduce the target's [CS:E]Defense[CR] by\n1 level.\n\n\n\n\nDetailed Information:[CLUM_SET:108][M:B20]\n[C]\n"Detailed Information"[CS:E][bAR][CR]\nRange:[CLUM_SET:36] Enemy in front\nType:[CLUM_SET:36] Steel/Physical\nHit Ratio[CLUM_SET:54]:[CLUM_SET:62][move_hit_ratio]\nPower[CLUM_SET:54]:[CLUM_SET:62][move_power]\n\n\n\nBasic Information:[CLUM_SET:100][M:B20]</Description>
</Strings>
<!--Move data from waza_p.bin-->
<Data>
	<BasePower>40</BasePower>
	<Type>17</Type>
	<Category>0</Category>
	<Unk4>0</Unk4>
	<Unk5>0</Unk5>
	<BasePP>10</BasePP>
	<Unk6>15</Unk6>
	<Unk7>125</Unk7>
	<Accuracy>78</Accuracy>
	<Unk9>75</Unk9>
	<Unk10>1</Unk10>
	<Unk11>99</Unk11>
	<Unk12>8</Unk12>
	<Unk13>0</Unk13>
	<Unk14>0</Unk14>
	<Unk15>0</Unk15>
	<Unk16>1</Unk16>
	<Unk17>1</Unk17>
	<Unk18>11</Unk18>
	<MoveID>1</MoveID>
	<Unk19>0</Unk19>
</Data>
<!--Move data from waza_p2.bin-->
<Data>
	<BasePower>40</BasePower>
	<Type>17</Type>
	<Category>0</Category>
	<Unk4>0</Unk4>
	<Unk5>0</Unk5>
	<BasePP>10</BasePP>
	<Unk6>15</Unk6>
	<Unk7>125</Unk7>
	<Accuracy>78</Accuracy>
	<Unk9>75</Unk9>
	<Unk10>1</Unk10>
	<Unk11>99</Unk11>
	<Unk12>8</Unk12>
	<Unk13>0</Unk13>
	<Unk14>0</Unk14>
	<Unk15>0</Unk15>
	<Unk16>1</Unk16>
	<Unk17>1</Unk17>
	<Unk18>11</Unk18>
	<MoveID>1</MoveID>
	<Unk19>0</Unk19>
</Data>
</Move>

Also, one of the more powerful feature of this tool is the "gamelang.xml" file. Its a very simple XML file that contains the name of the "text_*.str" file for all supported languages, along with a locale string associated with that language to allow parsing special charactersets, and a list of string indexes for move names, pokemon names and etc, within the the "text_*.str" file!

This XML file can be edited by anyone and more languages can be added, along with the appropriate string indexes for all the relevant things in the game text! The gamelang.xml file included is very incomplete for now though, with only support for the English game!

Here's the current entry for Explorers of Sky for example:

   <!--Begin List for Explorers of Sky-->
   <Game name="EoS">
       <Language name="English" strfile="text_e.str" locale="en-US">
           <StringBlock>
               <Name>Pokemon Names</Name> 
               <Begin>8734</Begin>
               <End>9334</End>
           </StringBlock>
           <StringBlock>
               <Name>Pokemon Categories</Name> 
               <Begin>9334</Begin>
               <End>9934</End>
           </StringBlock>
           <StringBlock>
               <Name>Move Names</Name> 
               <Begin>8173</Begin>
               <End>8734</End>
           </StringBlock>
           <StringBlock>
             <Name>Move Descriptions</Name>
             <Begin>10145</Begin>
             <End>10704</End>
           </StringBlock>
           <StringBlock>
               <Name>Item Names</Name> 
               <Begin>6773</Begin>
               <End>8173</End>
           </StringBlock>
           <StringBlock>
             <Name>Item Short Descriptions</Name>
             <Begin>12104</Begin>
             <End>13504</End>
           </StringBlock>
           <StringBlock>
             <Name>Item Long Descriptions</Name>
             <Begin>10704</Begin>
             <End>12104</End>
           </StringBlock>
           <StringBlock>
             <Name>Ability Names</Name>
             <Begin>13789</Begin>
             <End>13913</End>
           </StringBlock>
           <StringBlock>
             <Name>Ability Descriptions</Name>
             <Begin>13913</Begin>
             <End>14037</End>
           </StringBlock>
           <StringBlock>
             <Name>Type Names</Name>
             <Begin>13770</Begin>
             <End>13989</End>
           </StringBlock>
       </Language>

I could probably add stuff for exporting small sections of the game text, like only abilities, or only pokemon, or types, etc, if anyone would have any use for that.

If there are any feature requests, or any issues with the tool, let me know!

Posted

Well, from what I could find out, the "en-US" locale on Windows is basically ANSI codepage 1252. http://web.archive.org/web/20130813083656/http://msdn.microsoft.com/en-us/goglobal/bb896001.aspx

And that works pretty well from what I've seen this far!

Also, all symbols that appears in the text are triggered by a tag that changes the font to use, so its possible you lost some characters while parsing the file, and those tags aren't read properly anymore ?

Also, I wrote obscenities in the game and didn't have any issues XP

modified_bulbasaur_stats_28_12001.png

EDIT:

Also, wouldn't Shift-JIS be more appropriate for "text_j.str" ? Because, the name of the file changes based on the language and the encoding too.

modified_bulbasaur_stats_28_12001.png.e3

Posted

Hi, I've not read the whole thread but I want to say a big THANKS for you psy_commando and for all of those who contribuate to the research on PMD :)

However I've barely download your ppmd_statutil and I have a problem when I try to run it. It simply open un close immediately, I don't know what to do to solve this :/

Thank's in advance for your help, and thank's again for your research (un edited judgment attack hitting the whole floor is really awesome :P)

Posted
Hi, I've not read the whole thread but I want to say a big THANKS for you psy_commando and for all of those who contribuate to the research on PMD :)

However I've barely download your ppmd_statutil and I have a problem when I try to run it. It simply open un close immediately, I don't know what to do to solve this :/

Thank's in advance for your help, and thank's again for your research (un edited judgment attack hitting the whole floor is really awesome :P)

It's a command line tool, so drag an appropriate file onto the program.

Posted

It doesn't work either :/ A window appears for just 0,5 second and then disappears immediately

EDIT : I've put the program directly in system32 to run it and see if there is some problem, but nothing particular appears, it just says "To export data, do... to import data, do..." and so on

Posted
It doesn't work either :/ A window appears for just 0,5 second and then disappears immediately

Try this:

1. Copy the appropriate file into the same folder as the program.

2. While holding shift, right click next to the program (make sure you're right-clicking the folder while inside of it).

3. Select "open command window here".

4. Type ppmd_statutil.exe "myfile.ext" (replacing myfile.ext with your file)

5. You should be presented with a message of success, or an error message (which can be used to investigate further).

Posted

It's a command line tool, so drag an appropriate file onto the program.

Well, that won't work with this one right now, you have to either make a shortcut or a batch file. Actually, I could even ship it with a few batch files that would handle the drag-and-drop..

There's an issue with the item data parser, so just dragging and dropping the game's data dir onto it will just end with an "not implemented" exception ^^;

It should be fixed next release, but I figured it was good enough for testing xD

Hi, I've not read the whole thread but I want to say a big THANKS for you psy_commando and for all of those who contribuate to the research on PMD :)

However I've barely download your ppmd_statutil and I have a problem when I try to run it. It simply open un close immediately, I don't know what to do to solve this :/

Thank's in advance for your help, and thank's again for your research (un edited judgment attack hitting the whole floor is really awesome :P)

You're welcome :)

But, like evandixon said, its a command line utility, so you have to do extra work. Well, for now anyways.

So, if you're using windows vista/7, go to the directory you're extracted the whole zip to, hold the shift key, right click on some empty space in the folder window, and click "Open command window here..".

Then, the readme has a few pre-made lines for specific operations:

----------------------------------------------------------------------------------------------------
How to use:
----------------------------------------------------------------------------------------------------

Exporting:
----------

* Exporting Pokemon data to XML:
   Type this at the command line (without the first set of quotes): 
       "ppmd_statsutil.exe -e -pk "path/To/PMD2/ROM/Data/Directory" "Path/To/Output/Directory""
       Replace the paths with the appropriate paths! You can omit the output path, 
       and the xml data will be exported to a default directory.

* Exporting move data to XML:
   Type this at the command line (without the first set of quotes): 
       "ppmd_statsutil.exe -e -mv "path/To/PMD2/ROM/Data/Directory" "Path/To/Output/Directory""
       Replace the paths with the appropriate paths! You can omit the output path, 
       and the xml data will be exported to a default directory.

* Exporting game text to text file:
   Type this at the command line (without the first set of quotes): 
       "ppmd_statsutil.exe -e -str "path/To/PMD2/ROM/DataDir" "Path/To/Output/File/text.txt""
       Replace the paths with the appropriate paths! And replace the filenames as desired. 
       You can omit the output path, and the text data will be exported to a text file with the default name.

Importing:
----------

* Importing Pokemon data from XML back into the game:
   Enter this at the commandline (without the first set of quotes):
       "ppmd_statsutil.exe -i -pk "Path/To/Input/XMLdata/Directory" "path/To/Target/PMD2/ROM/Data/Directory""
       Replace the paths with the appropriate paths! The output path is mandatory!

* Importing moves data from XML back into the game:
   Enter this at the commandline (without the first set of quotes):
       "ppmd_statsutil.exe -i -mv "Path/To/Input/XMLdata/Directory" "path/To/Target/PMD2/ROM/Data/Directory""
       Replace the paths with the appropriate paths! The output path is mandatory!

* Importing game text from a text file back into the game:
   Enter this at the commandline (without the first set of quotes):
       "ppmd_statsutil.exe -i -str "Path/To/Input/File/text.txt" "path/To/PMD2/ROM/DataDir""
       Replace the paths with the appropriate paths! The output path is mandatory!

So if you want to export Pokemon data from the extracted ROM data located at "C:/directory/pmd2rom/data", you'd write this in the command prompt:

ppmd_statsutil.exe -e -pk "C:/directory/pmd2rom/data"

"-e" tells the program you want to export.

"-pk" tells the program you want to operate on pokemon data.

"C:/directory/pmd2rom/data" is the path to the extracted rom's data.

The utility is mainly meant to be used by software devs to make their own more user friendly tools however. That's why its command line, because its way faster to develop and easier to use from any other GUI utility.

I'm also going to make a very rudimentary GUI for this one too, pretty much the same thing as packfileutil and kaoutil, just to make it easier to handle for most people until more complete and user friendly tools are available.

EDIT: Oh well, got ninja-ed xD

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
×
×
  • Create New...