Important information: this site is currently scheduled to go offline indefinitely by end of the year.

Rohan Online: GMF Models

Post questions about game models here, or help out others!
mariokart64n
ultra-veteran
ultra-veteran
Posts: 586
Joined: Sun Jun 05, 2005 12:00 pm
Location: Ontario, Canada
Has thanked: 36 times
Been thanked: 243 times

Post by mariokart64n »

:( no program
spintz
ultra-n00b
Posts: 2
Joined: Thu Jun 19, 2008 4:02 am

Re: Rohan Online: GMF Models

Post by spintz »

These file formats are no longer accurate. I've got meshes parsed out, and have even pared the material files with them, to get models converted into a custom 3D format I use for my 3D engine. To start with, Here's the source code for a program that will extract files from the gel/gem archives :

Code: Select all

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>

struct GELHeader
{
	int i1;
	int i2;
	int numberOfElements;
	int i4;
	int i5;
	int i6;

	void print()
	{
		//printf( "i1 = %d\n", i1 );
		//printf( "i2 = %d\n", i2 );
		printf( "numberOfElements = %d\n", numberOfElements );
		//printf( "i4 = %d\n", i4 );
		//printf( "i5 = %d\n", i5 );
		//printf( "i6 = %d\n", i6 );
		printf( "\n" );
	}
};

struct GELEntry
{
	int i1;
	int i2;
	char filename[128];
	int i3;
	int startOffset;
	int dataSize;
	int i6;

	void print()
	{
		//printf( "i1 = %d\n", i1 );
		//printf( "i2 = %d\n", i2 );
		printf( "filename = %s\n", filename );
		//printf( "i3 = %d\n", i3 );
		printf( "startOffset = %d\n", startOffset );
		printf( "dataSize = %d\n", dataSize );
		//printf( "i6 = %d\n", i6 );
		printf( "\n" );
	}
};

// Set this to the .GEL file that you want to extract
std::string srcGel = "C:\\Rohan\\res\\model\\Building\\skeleton.gel";
// Set this to the .GEM file that matches the .GEL file you want to extract
std::string srcGem = "C:\\Rohan\\res\\model\\Building\\skeleton.gem";
// This is the path where all the files will be extracted to
std::string destPath = "C:\\RohanData\\model\\Building";

int main()
{
	FILE* gelFP = 0;
	fopen_s( &gelFP, srcGel.c_str(), "rb" );

	if( gelFP )
	{
		FILE* gemFP = 0;
		fopen_s( &gemFP, srcGem.c_str(), "rb" );

		if( gemFP )
		{
			GELHeader gelHeader;
			fread( &gelHeader, sizeof( GELHeader ), 1, gelFP );
			//gelHeader.print();

			for( int i=0; i<gelHeader.numberOfElements; i++ )
			{
				GELEntry gelEntry;
				fread( &gelEntry, sizeof( GELEntry ), 1, gelFP );
				//gelEntry.print();
				printf( "\b\b\b\b\b\b\b%d", i + 1 );

				if( gelEntry.dataSize > 0 )
				{
					// Create the file
					std::string sFilename = gelEntry.filename;
					size_t pos = sFilename.find_last_of( "\\" );

					std::string path = sFilename.substr( 0, pos + 1 );
					std::string filename = sFilename.substr( pos + 1, sFilename.length() - pos );
					//printf( "Path = %s\nFile = %s\n", path.c_str(), filename.c_str() );

					std::string newPath = destPath;
					newPath.append( path );
					CreateDirectory( newPath.c_str(), NULL );

					// Detect GTX files (DDS files with the header changed and the extension changed
					pos = filename.find_last_of( "." );
					//printf( "pos = %d\n", pos );
					std::string ext = filename.substr( pos + 1, filename.length() - pos - 1 );
					//printf( "ext = %s\n", ext.c_str() );

					if( ext.find( "gtx" ) != std::string::npos )
					{
						//printf( "Found GTX file!\n" );
						char* data = (char*)malloc( gelEntry.dataSize );
						fseek( gemFP, gelEntry.startOffset, 0 );
						fread( data, gelEntry.dataSize, 1, gemFP );

						if( data[0] == 'G' && data[1] == 'E' && data[2] == 'O' )
						{
							// Most gtx files are DDS files with the "Magic Word" changed to GEO.  We change that here, before
							// writing the file
							filename.replace( pos + 1, 3, "dds" );
							std::string fullPath = newPath;
							fullPath.append( "\\" );
							fullPath.append( filename );

							data[0] = 'D';
							data[1] = 'D';
							data[2] = 'S';
							FILE* outFP = 0;
							fopen_s( &outFP, fullPath.c_str(), "wb" );
							if( outFP )
							{
								fwrite( data, gelEntry.dataSize, 1, outFP );
								fclose( outFP );
							}
						}
						else if( data[0] == 'D' && data[1] == 'D' && data[2] == 'S' )
						{
							// Sometimes, DDS files have the proper header in them
							filename.replace( pos + 1, 3, "dds" );
							std::string fullPath = newPath;
							fullPath.append( "\\" );
							fullPath.append( filename );

							FILE* outFP = 0;
							fopen_s( &outFP, fullPath.c_str(), "wb" );
							if( outFP )
							{
								fwrite( data, gelEntry.dataSize, 1, outFP );
								fclose( outFP );
							}
						}
						else
						{
							// Haven't come across this yet, but just in case, we'll know.
							printf( "\n" );
							printf( "Encountered UNKNOWN GTX file!\n" );
							printf( "%c %c %c\n", data[0], data[1], data[2] );
							printf( "\n" );
						}

						free( data );
					}
					else
					{
						std::string fullPath = newPath;
						fullPath.append( "\\" );
						fullPath.append( filename );
					
						FILE* outFP = 0;
						fopen_s( &outFP, fullPath.c_str(), "wb" );
						if( outFP )
						{
							void* data = malloc( gelEntry.dataSize );
							fseek( gemFP, gelEntry.startOffset, 0 );
							fread( data, gelEntry.dataSize, 1, gemFP );
							fwrite( data, gelEntry.dataSize, 1, outFP );
							free( data );
							fclose( outFP );
						}
					}
				}
			}

			printf( "\n\n" );
			fclose( gemFP );
		}

		fclose( gelFP );
	}

	return 0;
}
Check the comments by the srcGel, srcGem and destPath std::string's. They are pretty self-explanatory, but I added the comments just in case. Soon, I'll post the updated .GMF and .GRF format and source code for converting the .GMF files into .OBJ meshes.

Some teasers tho -

Image
Image
Image
Image
ICON
ultra-n00b
Posts: 6
Joined: Thu Sep 11, 2008 7:51 pm

Re: Rohan Online: GMF Models

Post by ICON »

Thanks for your help on this. Just w8ting to see the converters.
Theran
beginner
Posts: 37
Joined: Wed Jun 11, 2008 6:49 pm
Been thanked: 4 times

Re: Rohan Online: GMF Models

Post by Theran »

I've been looking into the non DDS gtx files. They seem to be Truevision TGA files (uncompressed in ARGB format) but with a slightly different header.

I think I've exported it properly, but if you zoom in, the edges don't seem to align correctly. I've attached my exported file, but if anyone has any ideas on these type of images, please let me know.
You do not have the required permissions to view the files attached to this post.
liquidwad
ultra-n00b
Posts: 2
Joined: Thu Oct 09, 2008 11:47 pm

Re: Rohan Online: GMF Models

Post by liquidwad »

Thank you to fatduck for figuring out and releasing numerous file formats for rohan. Thanks also to Spintz for the extraction code. One problem when extracting all the meshes and textures is that it hard to tell what pieces go together. IEF files contain this information, so I would like to share its format with you:

Code: Select all

/* ROHAN ONLINE .IEF FORMAT
 * BY PRINCEWADII
 * 01/27/08 4:50 AM
 * Description: .ief files group all meshes that 
 * belong together and store their .gmf file names
 * and material names.
 */

//=============
//   HEADER
//=============
dword header		//always 0x00 00 00 00
dword typeCount  	

//============
//    DATA
//============

struct Type[typeCount]   //normal armor, event armor, head deco, etc..
{
	dword typeID     	
	dword setCount 		 

	struct Set[setCount]  //combination of parts that form a full armor for example
	{
		dword setID 
		struct Part[4]
		/*Parts always come in sets of 4 (ex: upper body, 
		lower body, glove, boot)*/
		{
			dword partLen  		
			char[partLen] bodyPart   //Example: Upper Body
			dword meshCount		//Number of meshes per part

			struct Mesh [meshCount]
			{
				dword meshLen		
				char[meshLen] meshName	//example: c_am_body01.gmf 
				dword matCount		//Number of materials per mesh
				struct Materials [matCount]
				{
					dword matLen		
					char[matLen] material	//Example: Material #01001 
				}
			}
		}
	}
}
Just as an example, using .ief files, I was able to do this:

Image

(This tool will also extract and convert full sets from .gmf to .x. I plan on releasing it once it is 100% perfect).
pixellegolas
ultra-veteran
ultra-veteran
Posts: 423
Joined: Mon Aug 11, 2008 11:30 pm
Has thanked: 27 times
Been thanked: 15 times

Re: Rohan Online: GMF Models

Post by pixellegolas »

That's a crazy cool tool! :) I will eagerly wait for a tool. I love the rohan models
Theran
beginner
Posts: 37
Joined: Wed Jun 11, 2008 6:49 pm
Been thanked: 4 times

Re: Rohan Online: GMF Models

Post by Theran »

Very nice liquidwad. Have you figured out what the type/set IDs mean?
Darkfox
VVIP member
VVIP member
Posts: 688
Joined: Fri Jul 04, 2003 6:11 pm
Has thanked: 33 times
Been thanked: 16 times

Re: Rohan Online: GMF Models

Post by Darkfox »

Pretty cool, though the *.x mesh format has little documentation or at least a low support rating for modeling programs. Though ironically, free modeling programs like Blender do.

Still, I love to see converting and viewing of 3D models, and 3D in general, can't wait to see the results. It's good that a converter is being made, and from what I've seen, it was worth the wait. Not exactly familiar with Rohan, but the models look interesting. :)

Oh yeah, does the converter put out the animations intact as well?
pixellegolas
ultra-veteran
ultra-veteran
Posts: 423
Joined: Mon Aug 11, 2008 11:30 pm
Has thanked: 27 times
Been thanked: 15 times

Re: Rohan Online: GMF Models

Post by pixellegolas »

cant you make it fbx that support model, animation lightning etc? :)
Darkfox
VVIP member
VVIP member
Posts: 688
Joined: Fri Jul 04, 2003 6:11 pm
Has thanked: 33 times
Been thanked: 16 times

Re: Rohan Online: GMF Models

Post by Darkfox »

Hm... fbx IS a good format and seems widely supported. Though isn't it difficult to make a converter for? Not sure, but I do like the format for those perks, and even Milkshape seems to support it WITH animations (most imports in MS3D come WITHOUT animations).
pixellegolas
ultra-veteran
ultra-veteran
Posts: 423
Joined: Mon Aug 11, 2008 11:30 pm
Has thanked: 27 times
Been thanked: 15 times

Re: Rohan Online: GMF Models

Post by pixellegolas »

.ms3d is also quite a good format. i think looking at blender scripts can give alot of hints...but dont ask me cause i dont know anything about those things :)
pixellegolas
ultra-veteran
ultra-veteran
Posts: 423
Joined: Mon Aug 11, 2008 11:30 pm
Has thanked: 27 times
Been thanked: 15 times

Re: Rohan Online: GMF Models

Post by pixellegolas »

bumping this :)

another good format is md5 :)
ChaosPower
ultra-n00b
Posts: 6
Joined: Thu May 21, 2009 7:51 pm

Re: Rohan Online: GMF Models

Post by ChaosPower »

EDITED: How did you delete the first 3 hexes in the file?

This is what I did,

file.gtx -> containing geo header -> replace with dds characters.

in hex editor, there contain readable character which is TRUEVISION-XFile which is a tga file located at the bottom.

These are the first 16

44 44 53 00 00 02 00 00 00 00 00 00 00 00 00 20

Target
00 00 02 00 00 00 00 00 00 00 00 00 20

I need to delete index 0 1 2 in the c++ code, how to do this?

I'm thinking if I rewrite the output to skip data[2] and start with data[3] onwards

EDITED: Used another programming language for solution
pixellegolas
ultra-veteran
ultra-veteran
Posts: 423
Joined: Mon Aug 11, 2008 11:30 pm
Has thanked: 27 times
Been thanked: 15 times

Re: Rohan Online: GMF Models

Post by pixellegolas »

bumping this beauty again. just saw a character creatin vid on youtube and remember this still has some cool models. Any viewer/converter out there longing for my harddrive?
User avatar
Rimbros
ultra-veteran
ultra-veteran
Posts: 495
Joined: Fri Jul 09, 2010 12:23 am
Has thanked: 41 times
Been thanked: 16 times

Re: Rohan Online: GMF Models

Post by Rimbros »

Nothing News abouth the program to convert?
Renders Art by Rimbros
http://s303.photobucket.com/albums/nn12 ... E/Renders/

Personal Game repository samples, send PM
Post Reply