Archived

This topic is now archived and is closed to further replies.

Creating own file format...

This topic is 4940 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Since i got my hands on a copy of AC3Di have been wondering "Howdo you makeyour own file format". Something like this would be really handy for me, as i would like to make my own map format. This would have to hold: a height field terrain sea level speed of waves positions and models of arbitrary objects (eg. houses) How would i go about doing this. ------------ "Here lies a toppled God, His fall was not a small one, We but built his pedastle, A narrow, and a tall one" Frank Herbert (Dune:Messiah)

Share this post


Link to post
Share on other sites
Something like:

4B File signature, like 87 12 E4 D0 or something..
2B Sea level offset
2B Speed offset
2B Objects offset

offset 11-Sea level offset : Height field (1B height)
offset Sea level - Speed offset : Sea level (1B height)
offset Speed offset - Objects offset : Speed of waves (1B speed or 2 or 65536, it doesn't really matter)
offset Objects - end of file : Objects with something like:
2B number of triangles
current offset - number of tris :
6B X, Y and Z positions (could make it 12B if you need minus positions and you want all 65536 numbers or divide with 100 or 1000 to get decimals?)
Maybe 2B (RGB565) or 3B of color?

Just a proposal which you can play with.
It's not advanced at all but I believe it's up to you to figure out a decent final format. Also RLE is a very good option to improve the size with the height fields and sea levels (if bigger parts are plain of course).

[edited by - nife on May 31, 2004 4:13:32 PM]

Share this post


Link to post
Share on other sites
Are you using C++? fwrite is from a few different languages . I personally use good ol'' fstream To quote directly from the many statements that have been beaten into my head recently


#include <fstream.h>

ofstream outfile; //global variable like cout that

//handles output to a file


void main(void)
{
outfile.open("filename.lol", ios::out);
outfile << data;
}

//Comparatively this is a primitive way of operating but whatever :)

Share this post


Link to post
Share on other sites
quote:
Original post by uber_n00b
Are you using C++? fwrite is from a few different languages . I personally use good ol'' fstream To quote directly from the many statements that have been beaten into my head recently


#include <fstream.h>

ofstream outfile; //global variable like cout that

//handles output to a file


void main(void)
{
outfile.open("filename.lol", ios::out);
outfile << data;
}

//Comparatively this is a primitive way of operating but whatever :)




Tisk tisk, using deprecated header files, and the stream types are not in global namespace, there in std namespace.

Share this post


Link to post
Share on other sites
Sorry but I refuse to give that way up because well why? THEY'RE in the std namespace only if you include <'fstream> buddy. I don't care if they are 'deprecated', but that's how the damned C++ courses still teach them unfortunately.

[edited by - uber_n00b on May 31, 2004 8:43:24 PM]

Share this post


Link to post
Share on other sites
Those header files are not meant to exist, you'll see what will happen when you try compile your code on a newer compiler like VS.NET 2003 and see what will happen!, VS.NET 2003 has completely remove the old header style. At the moment your using code that may be buggy because those headers are likely not have been maintained for a long time. The reason for all this is standardization and thats not standard C++ code. Go ahead use if you like but don't pass on bad habits to other people learning.

[edited by - snk_kid on May 31, 2004 9:56:49 PM]

Share this post


Link to post
Share on other sites
Hey, I think I''ve read enough threads regarding standard headers this week, let''s give it a rest and get back on topic. I think the standard people have made their point.

quote:
Original post by Kris2456
mmm, i get how it wouldwork, i just dont know how to save it. Would i have to do fwrite or something?

fwrite is in the C runtime, but you could certainly use it if you''re writing C code. In C++, you would indeed use an ofstream (and conversely an ifstream for reading), but it''s not as easy as using the overloaded << and >> operators. You''ll have to use write and read. And you must, I deplore you, open your files in binary mode. Or else your data will be transformed without your knowledge and you''ll come back here wondering why

Share this post


Link to post
Share on other sites
quote:
Original post by uber_n00b
Sorry but I refuse to give that way up because well why? THEY''RE in the std namespace only if you include <''fstream> buddy. I don''t care if they are ''deprecated'', but that''s how the damned C++ courses still teach them unfortunately.

[edited by - uber_n00b on May 31, 2004 8:43:24 PM]


So your not allowed to teach yourself?

90% of programming is not what you learn in school, but what you teach yourself as you work in the industry or as a hobby. Don''t be afraid to change the way you do something just because you learned it a different way.



First make it work, then make it fast. --Brian Kernighan

The problems of this world cannot possibly be solved by skeptics or cynics whose horizons are limited by the obvious realities. We need men and women who can dream of things that never were. - John Fitzgerald Kennedy(35th US President)

Do not interrupt your enemy when he is making a mistake. - Napolean Bonaparte

Share this post


Link to post
Share on other sites
errr, ok. Bout half those posts were on headers, so that didnt help much. So, do i do what stk_kid said, or do i open them in binary mode? Im confused. Any chance of a tutorial?

Share this post


Link to post
Share on other sites

FILE* myFile = fopen("theDataISaved.bin","wb");
void* ptr = myData;
fwrite(ptr,theNumberOfBytesOfDataIHave,1,myFile);
fclose(myFile);


For your actually format, do something like

FILE* myFile = fopen("theDataISaved.bin","wb");
unsigned char sig[] = "SIG!"
fwrite(sig,4,1,myFile);
float heightMap[width*height];
fwrite(heightMap,width*height*sizeof(float),1,myFile);
fwrite(&seaLevel,sizeof(float),1,myFile);
fwrite(&speed,sizeof(float),1,myFile);
fclose(myFile);


Also not that the "wb" thing is a flag, the w is a writable file pointer, and the b is a binary file.

--------------------------------------------------------
Life would be so much easier if we could just get the source code.

[edited by - Venerable Vampire on June 1, 2004 8:42:16 AM]

[edited by - Venerable Vampire on June 1, 2004 8:42:37 AM]

Share this post


Link to post
Share on other sites
And of course you can read the data in again using fread. Basically, the fwrite function just dumps memory contents into the file and fread loads file contents into memory.

Share this post


Link to post
Share on other sites
It''s not very hard you just gotta use your noodle a bit.


struct header
{
char name[32];
int map_pos;
int pos...
};


You define a struct for you header with all your data in it.
The pos are the locations in the file where whatever your data is
located.

in simple C code it looks like this


struct header head;
fwrite( &head, sizeof(head), 1, f);
map_pos = ftell(f);
[... write data ...]
fseek( f, SEEK_SET );
fwrite( &head, sizeof(head), 1, f);
fclose(f)..

Share this post


Link to post
Share on other sites
quote:
Original post by Venerable Vampire

For your actually format, do something like

FILE* myFile = fopen("theDataISaved.bin","wb");
unsigned char sig[] = "SIG!"
fwrite(sig,4,1,myFile);
float heightMap[width*height];
fwrite(heightMap,width*height*sizeof(float),1,myFile);
fwrite(&seaLevel,sizeof(float),1,myFile);
fwrite(&speed,sizeof(float),1,myFile);
fclose(myFile);


Also not that the "wb" thing is a flag, the w is a writable file pointer, and the b is a binary file.



So if i wanetd to make a .XYZ file i woul replae the .bin bit with a .XYZ bit right?


[edited by - Kris2456 on June 1, 2004 11:29:31 AM]

Share this post


Link to post
Share on other sites
The file extension doesn''t mean anything except to tell the operating system what program to open the file with when you double-click it and what. So you can use anything you want there.

Share this post


Link to post
Share on other sites
SWEEt, ok i got it working. Ive got it to load a .RAW file into a file format ive called .bel. Basicly in it i have:
Name of file
Description
.RAW file

Here is my source in case someone has a comment on how to do it better:

#define MAX_SIZE 1024

using namespace std;

char MapName[20];
float WaterLevel=0;
char HeightName[20];
char Descript[100];
BYTE HeightMap[MAX_SIZE*MAX_SIZE];

void LoadRawFile(LPSTR strName, int nSize, BYTE *pHeightMap)
{
FILE *pFile = NULL;
pFile = fopen( strName, "rb" );

//Check to see if file was found

if(pFile== NULL)
{
cout<<"ERROR: The .RAW file could not be opened!"<<endl;
return;
}

//Read data in

fread(pHeightMap,1,nSize,pFile);

//Check for errors while reading

int result = ferror( pFile );
if(result)
{
cout<<"ERROR: The .RAW file could not be read!"<<endl;
}

//Close the file

fclose(pFile);
}

int main(int argc, char *argv[])
{
cout<<" Tie Fighter Map Editor v1.0"<<endl<<endl<<endl;

cout<<"Please enter the name of your Map followed by the .bel extention (No Spaces): ";
cin.getline(MapName,20);
cout<<endl;

cout<<"Please enter the description of your Map: ";
cin.getline(Descript,100);
cout<<endl;

cout<<"Please enter the water level: ";
cin>>WaterLevel;
cout<<endl<<endl;


cout<<"Please check if these details are correct:"<<endl
<<" Name: "<<MapName<<endl
<<" Water Level: "<<WaterLevel<<endl
<<" Description: "<<Descript<<endl
<<endl<<endl;

cout<<"Please enter the name of the .RAW file you want to use as a Heightfield Terrain (No Spaces): ";
cin>>HeightName;
cout<<endl<<endl;

LoadRawFile(HeightName, MAX_SIZE*MAX_SIZE, HeightMap);
cout<<endl;
cout<<"Writing to file..."<<endl;

FILE * pFile;
pFile = fopen(MapName,"wb");
//Write Name

fwrite(MapName,sizeof(MapName),1,pFile);
//Write Description

fwrite(Descript,sizeof(Descript),1,pFile);
//Write Water Level

fwrite(&WaterLevel,sizeof(WaterLevel),1,pFile);
//Write HeightField Data

fwrite(HeightMap,MAX_SIZE*MAX_SIZE*sizeof(BYTE),1,pFile);
cout<<endl<<"Writing complete!"<<endl;

system("PAUSE");
return 0;
}

I was also wondering, how would i load it. How woul my game know how big each section is?
thx for all the replies btw...

Share this post


Link to post
Share on other sites
I didn't look at your code but usually when you design a file format you design file/object headers that will give you information on stuff like the number of objects it contains etc, for instance in C++:

header.hpp

#include <string>

struct file_header {
unsigned int num_of_objs;
};

struct some_obj {
//... members

};

some_obj* read_file(const std::string& filename);


header.cpp
    
#include "header.hpp"
#include <fstream>

some_obj* read_file(const std::string& filename) {

std::ifstream ifs(filename.c_str(), std::ifstream::out |std::ifstream::binary);

if(ifs.is_open() && ifs.good()) {
file_header header;

ifs.read(reinterpret_cast< char* >(&header), sizeof(file_header));

some_obj* new_obj = new some_obj[header.num_of_objs];

ifs.read(reinterpret_cast< char* >(new_obj), sizeof(some_obj) * header.num_of_objs);

return new_obj;
} else {
return 0;
}
}

main.cpp

#include "header.hpp"
#include <cstdlib>
int main() {
some_obj* my_objs = read_file("some_file");

if(my_objs != 0) {
//do something

delete[] my_objs; //release the resources back

return EXIT_SUCCESS;
} else {
return -1; //something is wrong

}
}


[edited by - snk_kid on June 1, 2004 4:36:11 PM]

Share this post


Link to post
Share on other sites
OK, i figured out how to read the file,i see that when u call fread it moves along the file and stays there, i thought it went back to the beggining. But the prob is, is that when i want to read in my heightmap array,it only reads in the first line, how can i make it read in whole array???

[edited by - Kris2456 on June 1, 2004 7:11:31 PM]

Share this post


Link to post
Share on other sites
Oik, assuming your height map is something like:

int map[1024*1024];

fwrite(map, 1024*1024*sizeof(int), 1, f);

and

fread(map, 1024*1024*sizeof(int), 1, f);

You can easily use fstream too, I prefer the old C file I/O functions mostly out of habit.


I''d suggest you store the map in a linear array like that. You can always type case it to a pointer and use it like a 2-d array or just use the math and index into it directly (y*width + x).

Peace

Share this post


Link to post
Share on other sites
quote:
Original post by PeterTarkus
Oik, assuming your height map is something like:

int map[1024*1024];

fwrite(map, 1024*1024*sizeof(int), 1, f);

and

fread(map, 1024*1024*sizeof(int), 1, f);




Thats exactly what i did too. Except my Array is in BYTES as in:
BYTE HeightMap[MAX_SIZE*MAX_SIZE];

But it only reads in the first line of my file, so if my file looked like this:

abcde
fghij
klmno
pqrst
uvwxy

It would only readin first line, IE: abcde
Hope that cleans it up

Share this post


Link to post
Share on other sites
what about ReadFile() and WriteFile()??

My oversimplification of the process:
1) come up with a struct you like that has all the data you need to load from the disk.

1.5) Make one. (E.G. " MYSTRUCT MyStruct; ")

2) put information in it ( MyStruct.Blah = Foo; )

3) Write it to a file using WriteFile

to read:
1) MYSTRUCT MyStruct;

2) then use ReadFile(). There ya go.

look at MSDN for how to use WriteFile() and ReadFile(). You''ll also need CreateFile().

Share this post


Link to post
Share on other sites
I don''t see any immediate problem in your code, maybe when you write the RAW file you didn''t write it all or something. I don''t know, sorry, maybe someone else can see the problem, from what I see your code should work.

Share this post


Link to post
Share on other sites