HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

SFmpq examples?

02-10-2005, 11:42 PM#1
Guest
I am curious if there is any example code of using SFmpq out there? I couldn't find any with numerous googles. The only thing I could find on ShadowFlare's page was a VB console app that used MpqControl.

I am writing an asynchronous MPQ loader in C# for my World of Warcraft interface building tool. I can easily DLL import the functions, and marshall the data types (even pointers) in to the managed world, but I need to know the usage patterns of some of the functions (SFileListFiles for instance).

Is there anywhere that I could find an example like this?
02-11-2005, 02:43 AM#2
Guest
Also, I wanted to add, that specifically, I am looking for the usage on SFileGetFiles. What is the use of the lpFileLists parameter? For that matter, how does the SFILE_LIST_MEMORY_LIST that behavior?

I hate to ask such silly questions, but I really can't seem to find any docs for the library.
02-11-2005, 04:28 AM#3
Mr. Euthanasia
I don't think there is any official documentation, unfortunately.
Though this may be of some help, http://www.campaigncreations.org/sta.../inside_mopaq/
02-11-2005, 11:59 AM#4
BlacKDicK
SFileListFiles can be used 2 different ways.

1)When you don't use dwFlags with SFILE_LIST_MEMORY, the lpFileLists parameter is used to set the filepath of the listfiles, for an example:

Code:
LPCSTR lpFileName = "C:\\WinMpq\\MyMpq.mpq";
MPQHANDLE hMPQ;
DWORD dwPriority = 666;
if (SFileOpenArchive(lpFileName, dwPriority, SFILE_OPEN_HARD_DISK_FILE, &hMPQ) == TRUE)
{
  DWORD dwHashTableSize = SFileGetFileInfo(hMPQ, SFILE_INFO_HASH_TABLE_SIZE);
  FILELISTENTRY *lpListBuffer = new FILELISTENTRY[dwHashTableSize];
  LPCSTR lpFileLists = "C:\\WinMpq\\MyListFile.txt";
  BOOL r = SFileListFiles(hMPQ, lpFileLists, lpListBuffer, SFILE_LIST_ONLY_KNOWN);
  for (DWORD i = 0; i < dwHashTableSize; i++)
  {
     if (lpListBuffer[i].dwFileExists != 0)
     {
       printf("Found: %s\n", lpListBuffer[i].szFileName);
       printf("Compressed size: %u\n", lpListBuffer[i].dwCompressedSize);
       printf("Uncompressed size: %u\n", lpListBuffer[i].dwFullSize);
     }
  }
  delete(lpListBuffer);
  SFileCloseArchive(hMPQ);
}
2) Whenever using dwFlags with SFILE_LIST_MEMORY the lpFileLists parameter is used as a list buffer itself. One possible way is to read the "(listfile)" from the MPQ into the lpFileLists and then call SFileListFiles using SFILE_LIST_MEMORY.
02-11-2005, 03:35 PM#5
Guest
So, what is the use of SFileListFiles over just reading the (listfile) from the MPQ? I guess its that SFileListFiles gives more info, such as the size, compressed size, etc? Will a file be listed in (listfile) if it doesn't actually exist in the MPQ?

The concept of unknown/known files is confusing the hell out of me :P
02-11-2005, 05:22 PM#6
BlacKDicK
Quote:
Will a file be listed in (listfile) if it doesn't actually exist in the MPQ?
Yes, it is possible. When Blizzard developed the MPQ archive, MPQs didn´t store the filenames inside them. They store the hash of the filename. Later they changed their mind and introduced the (listfile) inside the MPQs. The (listfile) is a simple text-based file that is suposed to have the filenames of the other files of that MPQ on it. Keep in mind that (listfile) is just another file inside the MPQ: it can store the name of the other files or something else, like a cooking recipe for example. You can read the internal MPQ (listfile) or use external listfiles and check your MPQ wether those files actually exists or not inside the archive.

Quote:
The concept of unknown/known files is confusing the hell out of me :P
The SFileListFiles will try to locate some files on the MPQ basaed on the file list you have given. Some files may still remain "unknown" after this procedure due using an incomplete listfile. The files that are on the file list you suply AND on the mpq archive are considered "known" files. The remaining are considered "unknown".
02-11-2005, 05:40 PM#7
Guest
Okay, I understand it now. Thank you very very much for the concise explanation. Will make my job of wrapping this in managed code much easier :)