Hello everybody! I'm currently trying to write my own little archive file format to avoid having hundreds of loose .tgas lying around in my game dir. Now, i'm having trouble figuring out how to get the size of a file opened using fopen(). My code looks something like this: Code: FILE file; loop{ // get filename from script file = fopen(filename, "rt"); // ??? fclose(file); } I need something like what you would get from calling sizeof(something), but sizeof(file) obviously doesn't work, it always returns 4. Does anyone have any ideas?
Gets a stream's file-position indicator Code: int fgetpos( FILE *stream, fpos_t *pos ); declared in stdio.h
Code: nPos = fTell(pFile); fseek(pFile, 0, SEEK_END); nSize = ftell(pFile); fseek(pFile, nPos, SEEK_SET); This is a very basic question. Are you sure you want to implement your own archive format?
Hey, thanks Still confused though. Never worked with fpos_t before.. i typed in: fpos_t pos; int size = fgetpos(file, &pos); but size is always 0? Nevermind (edit) ggambett's code worked. Thanks for the speedy reply guys!
well you confused SIZE with the return code, fgetpos return 0 on success. To be honest, I gave an incomplete answer since fgetpos is the same as ftell. It gives you the current position in the file. To know the file's length, you need to go to the end of the file prior to call fgetpos or ftell. fpos_t *pos; fseek(File, 0, SEEK_END); //move to end of file if (fgetpos(file, &pos)==0) //get position { //the position = length of file }
If you're looking into using an archive to store game assets (most commonly called "packfiles" in context of games I think), there's some good and easy to use existing ones available. I recommend you take a look at e.g. Sol's CFL3 (look for cfl3r3.zip, check out also the ramfile.zip) or the PhysicsFS.
and a nice tutorial for those who are using SDL (the undocumented SDL_RWops will save you the code needed to convert raw image code to SDL_surface): http://www.kekkai.org/roger/sdl/rwops/rwops.html
Basally you want to seek to the end of the file and then ask for the current position in the file to get the file's size. Here is the code I use in my file wrapper class Code: ulong CFileBuf::GetLength() const { if(m_pFile) { long Mark; long Length; Mark = ftell(m_pFile); fseek(m_pFile, 0, SEEK_END ); Length = ftell(m_pFile); fseek(m_pFile, Mark, SEEK_SET ); return Length; } return 0; } The Mark stuff if only needed if you wan't to preserve the curront posion in the file. If you don't mind losing the position, you can just fseek to the end and then use ftell to get the position. For example Code: FILE* pFile = fopen("Afile.txt", "rb"); fseek(m_pFile, 0, SEEK_END ); Length = ftell(m_pFile); Make sure you open the file in binary mode (the "B" in the fopen string). Otherwise the ftell will give unpredictable results due to the way text mode deals with line breaks.
FYI: My pack file format of choice is non-compressed .ZIP files. There are not very difficult to parse yourself and then you don't need to make any custom tools for creating them. Beast of all, the available tools are very robust with the ability to view and edit the contents of the files. All the games I have every worked on have all used (disguised) zip files to store all the games assets. Most of them (such as Ricochet and Big Kahuna) use a file called data.dat which is actually a zip archive.
On the subject of creating your own archive file, and/or protecting your assets from prying eyes, when I was seriously bitten by the programming bug years ago, what I did was to write a small program that would load in individual .wav and .pcx files, replace the 'identifier'(header) byte or bytes then spit the files back out. Then from within my game I would search for my 'marker' byte/s, then after that start to load in the information from the .wav or .pcx file until the end of the file was reached. That way, I still had individual files in the directory, but no original headers to prevent 'normal' programs from reading them. I didn't get around to joining the files together into a single file though, though I would imagine that it would simply be a case of loading one file at a time into an array, writing your own 'identifiers' for the start and maybe end of each file then appending each subsequent file to the outgoing archive. On reloading into your game, you would simply search for the 'beginning' identifier, then load the necessary information until you reach the start of the next file, and continue on until the end of the archive. I know there are many ways to do this, but if I had done this, I would have had 1 sound and 1 graphic archive. I have no real code ( been a long long time since I did any 'C' programming ), so I apologise if I'm way off track here. All the best Mark.
If you do decide to create your own compressed archive format, at least consider using an open-source compression library such as zlib. http://www.zlib.net/ --milo
In general, are there really compelling reasons to hide a game's assets from 'prying eyes'? If I am not mistaken, Popcap just installs the assets 'loose', and they seem to be doing ok. Won't anyone who really wants to get at your assets find a way, anyway?
I personally think that lotsa files look less polished, etc.. At the very least a directory "Data" should be created and everything put in, in my opinion at least. Finding an EXE among hundreds of data files, DLL's and possibly other EXEs is really a pain IMHO. Providing a link in the Start Menu is not a "total solution".
License agreements for sound files, etc, that you licensed from third parties. Sometimes they require this.
Well, i just loaded a sprite into my game from my very own archive Thanks for all the help! It crashes when i try to import files that are larger than 2mb, when i try to create an array of char[filesize]. Guess the size of an array has it's limits.. oh well, i won't need to archive bigger files anyway, so i can't be arsed to do a workaround I don't have any real reason for doing it really. I just like to keep a small tidy directory. My game's probably going to have at least 200-300 small images floating around. Replacing all those with one file seems like a good idea. And coding it was a fun little side-project!
If anyone's interested, here's what i ended up with: http://home.online.no/~mortschu/pac_v1.zip Run extract.bat to get the source, readme, and tools out of the .pac file. Let me know if it works!
You probably shouldn't allocate a 2 MB object on the stack; use the heap instead: Code: unsigned char *lpBuffer = new unsigned char[nBufferSize]; ... delete [] lpBuffer; or Code: unsigned char *lpBuffer = (unsigned char *) malloc (nBufferSize); ... free (lpBuffer); (Insert Cas telling us about garbage collection here ) Best regards, Emmanuel
Guys, the function you're looking for is fstat(). It simply tells you the size of an open file handle. The one fly in the ointment: it doesn't take a FILE *, it takes an int "handle" (like what open() gives you). To convert a FILE * to the appropriate int, call fileno(). On Windows, just to be irritating, all these functions have an underscore in front of them: _fstat(), _fileno(), and even _open(). Then again, if you're on Windows, you should be using native handles--as with CreateFile() and GetFileSize().