Character animations?


Garbage Human
Poking around the game data I managed to find the character walk animations, the character ready stance animations and the character PB animations but I haven't been able to find the character attack animations (swing sword, shoot gun, ect). Anyone know where those are?


Just a wild guess, but don't the basic weapons hold their own animations per class? I've never poked around with those files so it migh be wrong.


Garbage Human
I've been going through and deleting files in PSO PC version 2, restarting the game and seeing what still works.

NpcApcMot.bml contains some walking, running, ready animations. It looks like that's the run/wait animation used when selecting a character. No attack animations were found in the file.

Deleted all of the plAsmp.rel files, game works perfectly fine. Might be used for character creation somehow.

Thought it might be in one of the item.afs packages. ItemCT.afs, ItemKT.afs, ItemModel.afs, ItemPT.afs, ItemRT.afs, and ItemTexture.afs can all be deleted and the game will still let me go from Pioneer down to forest and swing an invisible saber. Game freezes when an item box is opened.

There's a few "PlyMotion" files, PlyEndingMotionData.cpt, PlyMotion.cpt, PlyMotionData.pr2, PlyMotionData.pr3.

PlyMotion.cpt can be deleted and the game still runs fine.

PlyEndingMotionData.cpt can be deleted and the game still runs fine. "EndingMotion" i think refers to the ending credits where it shows your character posed against the background. There's a darkfalz_dat.bml file that contains .njm files for those ending poses, though i'm not sure which takes priority.

The only other likely options remaining options are PlyMotionData.pr2 and PlyMotionData.pr3.

Remove either one of these and the game will crash after selecting a character. I've been trying to get confirmation by messing with the files so see if changing anything would either remove animations or cause them to glitch out. So far even minor changes to the file cause the game to crash after character selection.


Staff member
pr2 and pr3 are PRS and PRC files so if you wasn't already aware you can decompress them using PRS Util or my PRC Tool.


Garbage Human
I decompressed the with the tool, the problem is the data content doesn't make sense. I've been trying to see what's going on using the memory debugger in cheat engine.

PsoBB is a little more forgiving. There's a file named "plymotiondata.rlc" inside the data.gsl file with a header labeled RelChunkVer0.20 and some pretty clear pointers to separated section of the file. The problem is the file format on that one isn't exactly obvious either.


Garbage Human
Tried extracting the .pr2 file with tofu's PRC tool and the inside looks like a bunch of packaged .njm files just with no header or footer. So if it's possible to figure out the offset of each file, it could be possible to unpack them.


Garbage Human
Okay, I'm looking at .njm files to see if I can manage to pop a header onto the extracted plymotion.pr2 files to convert them with Noesis.


Not sure how stupidly obvious this is, but a few notes I made.

First 4 bytes of the file is always NMDM.
Second 4 bytes of the file seems to be a pointer to the end of the file.
P0F0 marks the end of the chuck (cyan box) and is always at an offset of 4 bytes.
The pointer from the second byte always points to P0FO -8 bytes.
Any data after P0F0 can all be deleted and the animation will run perfectly fine.
Not sure if P0F0 - 4 (green) is anything special. If it's a pointer it seems to pop into the middle of the file.
(Maybe the point to return to for repeat animations?)

Returning to the top
Third 4 bytes is always 0C000000
Fourth four bytes is the number of frames in hexadecimal. (1E = 30 frames, 14 = 20 frames, ect)

On the next row, the first 4 bytes seems to always be 03000200
And the second 4 bytes seem to always be 0C040000
And after that, second row with an offset of 8 bytes seems to be where the data for each file starts.

Edit: Okay it looks like the footer (and P0F0) don't matter at all. The second four bytes are a pointer to the end of the animation. Any data beyond that point can be replaced with 00's and the animation will still run. If the file is shorter than the pointer indicated in the second four bytes of the file, the animation will crash.


Here's a copy paste of my post on Schtserv :
Animations should be included in different filetypes as the file extensions themselves do not define the content of the file but rather the IFF headers inside of the file which should be used. See this for reference about all the different data that can be contained in Ninja files:

#define iff_NJINFO 'NJIN' /* data infomation */

#define iff_NJCM 'NJCM' /* ninja chunk model tree */
#define iff_NJBM 'NJBM' /* ninja basic model tree */
#define iff_NJTL 'NJTL' /* ninja texlist */
#define iff_NJLI 'NJLI' /* ninja light */
#define iff_NJCA 'NJCA' /* ninja camera */

#define iff_NMDM 'NMDM' /* ninja model motion */
#define iff_NLIM 'NLIM' /* ninja light motion */
#define iff_NCAM 'NCAM' /* ninja camera motion */
#define iff_NSSM 'NSSM' /* ninja simple shape motion */

#define iff_NJAD 'NJAD' /* absolute address */
#define iff_POF0 'POF0' /* pointer offset list type 0 */
#define iff_POF1 'POF1' /* pointer offset list type 1 */

* texture chunk name
/* pvr */
#define iff_PVRT 'PVRT' /* PowerVR texture */
#define iff_GBIX 'GBIX' /* globalIndex */
#define iff_PVRI 'PVRI' /* texture Info */

/* pvm */
#define iff_PVMH 'PVMH' /* PVM header */
#define iff_COMM 'COMM' /* Comment */
#define iff_CONV 'CONV' /* PVM Converter */
#define iff_MDLN 'MDLN' /* model name */
#define iff_IMGC 'IMGC' /* Image Container */

Alot of these files could be Ôö¼┬¢ archives Ôö¼Ôòù and contain more than one IFF header. So yeah, njm files should contain animations but it doesn't mean another filetype can't include this data. Unfortunately, rel files do not follow this IFF standard since it's not part of Ninja library.
IFF headers are simple, they have a 4 byte header and the next 4 bytes specify the size of the next data entry so that you can loop through all the entries. IFF header is NOT part of the content, it only defines what's inside. Interchange file format is a container filetype, see


Garbage Human
Last night I got the hands to twitch, today I made a slight improvement. I copied part of the file into an NJM container and set the animation time for a really long time to see what would happen. ...

I'm guessing/hoping this is the saber swing from the arc of the arm and the wrist movement. Rotation and timing are completely wrong, but it's alot better than flat out crashing.


Garbage Human
Found some more information on .njm

First 4 bytes are NMDM
Second 4 bytes is a null pointer to P0F0 - 8

Third 4 bytes is a pointer to the motion list
Fourth four bytes is the number of frames

typedef struct {
void *p[1]; /* Motion pointer*/
Uint32 nb[1]; /* Number of keyframes*/

The problem is in the documentation there doesn't seem to be a decent description of what void *p[1] is. Some places it's referred to as the motion list or the motion pointer. The best guess i have at the moment is that's an array of NJS_MOTION.

typedef struct {
void *mdata; /* Array for object tree */
Uint16 nbFrame; /* Number of motion frames */
Uint16 type; /* Motion element bit string */

I found that by following the pointer for p[1] and replacing values with zeros, I could stop different parts of the animation from playing. For instance with the rappy attack animation, the wings, legs, head, and beak sections can be turned off or on independently. As far at the character animations go, if I can find an offset for the motion list pointer, then I think that might be enough to export them as .njms. Though in general it would be nice to document the .njm format documented.


Garbage Human
Okay, I have a better idea of the .njm file structure. I'll try to write it up when I get home. Also I managed to find the pointers to the animations in the plymotiondata.pr2 file to preview it as an njm file. Still have a lot more tinkering to do though.



Garbage Human
kk managed to extract all 341 player animations from Pso PC Version 2.

1. Use tofu's tool to extract PlyMotionData.pr2 to PlyMotionDataPr2.bin
PRCTool.exe /D PlyMotionData.pr2 PlyMotionDataPr2.bin

2. Copy PlyMotionDataPr2.bin into a folder somewhere

3. Make a folder named "output" inside that folder

4. Run the following nodejs script in the same folder as PlyMotionDataPr2.bin
var fs = require("fs");

var filename;
var index = 0;
var buffer = fs.readFileSync("PlyMotionDataPr2.bin");

var tmp;
var nmdm = new Buffer("4E4D444D30CA1C00", "hex");
var njm = fs.readFileSync("PlyMotionDataPr2.bin");

njm = njm.slice(12, njm.length);

for(var i = 0; i < buffer.length - 4; i += 4){
var str = buffer.toString("hex", i, i+4);

if(str != "03000200"){

str = buffer.toString("hex", i-8, i+4);
tmp = new Buffer(str, "hex");

str = str.match(/.{1,8}/g);
str = str.join(" ");

filename = (index > 9) ? index : "0" + index;
filename = "output/motion"+filename+".njm";
fs.writeFileSync(filename, nmdm);
fs.appendFileSync(filename, tmp);
fs.appendFileSync(filename, njm);

4. Use one of the nj player body models to preview or export the animations with noesis.