偶久网

 找回密码
 注册会员

QQ登录

只需一步,快速开始

首页 改图教学 查看内容

魔兽改图MPQ技术内幕

2016-6-5 01:40| 发布者: 邪恶叔| 查看: 27980



现在您应该可以饶过所有的障碍,用mpqaddfiletoarchive成功添加文件了吧. 
这时mpqaddfiletoarchive将允许返回TURE. 
如果有错误,它将返回FALSE 。在这种情况下,少量的信息可调用getlasterror 。 
如果该文件lpsourcefilename不存在, getlasterror将返回error_file_not_found (尽管它的有点晚) 如果哈希表是FULL(见第2章) , getlasterror将返回mpq_error_hash_table_full 。 
如果该文件lpdestfilename已经存在 和在dwflags中未指定mafa_replace_existing , getlasterror将返回mpq_error_already_exists 。 
但是,在很多情况下getlasterror将返回其他一些错误代码或没有代码。 



Adding a File with WAV Compression - MpqAddWAVToArchive 
添加WAV压缩文件函数- MpqAddWAVToArchive 

BOOL WINAPI MpqAddWAVToArchive(HANDLE hMPQ, LPCSTR lpSourceFileName, LPCSTR lpDestFileName, DWORD dwFlags, DWORD dwQuality);
Parameter What it is
hMPQ [in] The HANDLE of the MPQ to add the file to, which was acquired earlier with MpqOpenArchiveForUpdate. MpqAddWAVToArchive will fail if this is NULL or aHANDLE not obtained with MpqOpenArchiveForUpdate.
lpSourceFileName [in] A pointer to a NULL-terminated string containing the path of the file on disk to add. MpqAddWAVToArchive will crash if this is NULL.
lpDestFileName [in] A pointer to a NULL-terminated string containing the name that the file will be given in the MPQ. MpqAddWAVToArchive will crash if this is NULL.
dwFlags [in] Flags specifying properties that MpqAddWAVToArchive will apply to the file inside the MPQ. Must be a combination of the following flags specified in lmpqapi.h:
MAFA_ENCRYPT The file will be encrypted.
MAFA_REPLACE_EXISTING If the file lpDestFileName already exists in the MPQ, it will be replaced with the new file to be added
dwQuality [in] Specifies the quality the WAV file will be compressed to. Must be one of the following values defined in lmpqapi.h:
MAWA_QUALITY_HIGH Best sound quality, least compression. WAV lpDestFileName in MPQ will occupy the most space after compression (but still less space than if you had added the file with MpqAddFileToArchive instead)
MAWA_QUALITY_MEDIUM Medium sound quality, medium compression. Balance between quality and compression.
MAWA_QUALITY_LOW Highest compression, worst sound quality. WAV lpDestFileName in MPQ will occupy the least space after compression.

毫无疑问,最流行的新功能的lmpqapi 2.0版(就是我做的) ,便有功能 mpqaddwavtoarchive 。 
虽然mpqaddfiletoarchive能压缩约80 %的文件(非wav文件) ,它对WAV文件的压缩只有平均约5 % 。这是由于wav数据性质和它的不可压缩性。 
在这里,对于wav压缩的压缩是必要的,而 mpqaddwavtoarchive就实现了这个功能。 
尽管工作原理不同,MpqAddWAVToArchive的界面与 MpqAddFileToArchive却是几乎相同的。 
唯一的区别就是多了一个新函数dwQuality。 
参数设置后WAV将会被压缩。 
不过不像mpqaddfiletoarchive的标准压缩, mpqaddwavtoarchive的wav压缩,实际上降低了wav的质量 。质量降低多少依赖于dwquality 。 
如果您有一个音乐WAV而又想保证质量,那您就使用mawa_quality_high ,因为它最好的保留wav的质量;而同一个声音wav , mawa_quality_low通常是不行的,因为声调比较容易压缩失真; mawa_quality_medium往往是最有效的。 


Deleting a File - MpqDeleteFile 
删除文件函数 - MpqDeleteFile 


BOOL WINAPI MpqDeleteFile(HANDLE hMPQ, LPCSTR lpFileName);
Parameter What it is
hMPQ [in] The HANDLE of the MPQ to close, which was acquired earlier with MpqOpenArchiveForUpdate. MpqDelete will fail (or worse) if this is NULL or aHANDLE not obtained with MpqOpenArchiveForUpdate.
lpFileName [in] A pointer to a NULL-terminated name of the file in the MPQ to delete. MpqDeleteFile will crash if this is NULL.

少数情况下,您可能需要删除MPQ中的某个文件,那么您就需要用到MpqDeleteFile。 
MpqDeleteFile能从已经打开的存档hMPQ中删除文件lpFileName。 
不过这不是看上去那么简单的。 
mpqdeletefile为lpfilename删除哈希和文件表项 ,使其无法进入。 
但是除非文件在MPQ的physical end ,否则MpqDeleteFile无法清除内存。 
这就是说,通常情况下MPQ文件是不会减小大小的。 
不过空间可以添加新文件循环再利用。稍后为您介绍MpqAddFileToArchive 和MpqAddWAVToArchive. 

就像STROM和STAREDIT几乎所有的功能一样,调用MpqDeleteFile成功就返回TURE,失败就返回FALSE。 
失败的话,您可以调用GetLastError去获得一些关于失败原因的信息(假如有的话)。 
在这种情况下GetLastError是惊人的有效。 
因为几乎只有一种会造成MpqDeleteFile失败的原因(除了hMPQ无效): 
该文件lpFileName不存在于MPQ,GetLastError将返回MPQ_ERROR_FILE_NOT_FOUND。 


Renaming a File - MpqRenameFile 
重命名文件函数- MpqRenameFile 


BOOL WINAPI MpqRenameFile(HANDLE hMPQ, LPCSTR lpOldFileName, LPCSTR lpNewFileName);
Parameter What it is
hMPQ [in] The HANDLE of the MPQ that holds the file to be renamed, and was acquired earlier with MpqOpenArchiveForUpdate. MpqRenameFile will fail if this is NULL or aHANDLE not obtained with MpqOpenArchiveForUpdate.
lpOldFileName [in] A pointer to a NULL-terminated string containing the name of the file in the MPQ to be renamed. MpqRenameFile will fail if this is NULL.
lpNewFileName [in] A pointer to a NULL-terminated string containing the name that the file lpOldFileName will be changed to. MpqRenameFile will fail if this is NULL


在我慢慢研究MPQ后发现StarEdit缺少一对非常有用的功能。 
而且那个时候我对与STROM和StarEdit的运做有了相当的了解,所以我决定写个自己的功能。 
MpqRenameFile 非常的简单;它重新把hMPQ中的文件名 由lpOldFileName变为lpNewFileName. 

mpqrenamefile返回给您的依旧是简单的信息。 
mpqrenamefile返回true就成功,FLASH失败,并让您调用getlasterror获得失败的原因 。 
如果hMPQ HANDLE 是NULL或无效,lpoldfilename或lpnewfilename是Null , getlasterror将返回error_invalid_parameter 。 
如果该文件lpoldfilename不存在于MPQ hMPQ中, getlasterror将返回mpq_error_file_not_found 。 
如果该文件lpnewfilename已经存在mpq中 , getlasterror将返回mpq_error_already_exists 。


Compacting an MPQ - MpqCompactArchive 
压缩MPQ函数- MpqCompactArchive 

BOOL WINAPI MpqCompactArchive(HANDLE hMPQ, BOOL bFailOnBadFile);
Parameter What it is
hMPQ [in] The HANDLE of the MPQ to compact, which was acquired earlier with MpqOpenArchiveForUpdate. MpqCompactArchive will fail if this is NULL or aHANDLE not obtained with MpqOpenArchiveForUpdate.
bFailOnBadFile [in] Explained below. Should usually be FALSE


记得我刚才说过调用mpqdeletefile实际上并不删除文件;它只是使它们无法使用。那么, mpqaddfiletoarchive和mpqaddwavtoarchive也是一样。 
当您添加一个已经存在的文件或添加比旧文件大的新文件,新的文件将附加,和原来被占用的空间不会被释放。正因为如此,每当您建立一个大的复杂的包含许多覆盖/删除的档案的mpq,将会有很大的体积,并且没有办法从零重建MPQ。 

解决这个问题的方法是调用mpqcompactarchive :这是我设计的第三个,也是最后一个,最困难的mpq功能。 mpqcompactarchive的功能是把数据压缩到一个缓冲文件,然后再传回。这就是说在压缩的时候,在磁盘上的缓冲文件必须有足够的可用空间(这取决于MPQ的大小)。 

虽然mpqcompactarchive可以让几乎所有的文件变得紧凑,但是还是有不能成功的类型:有mafa_encrypt和mafa_modcryptkey属性,但缺乏mafa_compress和mafa_compress2属性的文件(如需详细资讯,请参阅第5章) 。当mpqcompactarchve调用这种文件,getlasterror会返回错误代码mpq_error_compact_error ,然后删除违规档案,并继续压缩过程。 

mpqcompactarchive返回TURE就成功,FLASH就失败。您可以调用getlasterror获得错误信息 。 
如果hmpq是Null或无效的staredit HANDLE, getlasterror将返回error_invalid_parameter 。 
如果没有足够的可用记忆体为mpqcompactarchive拨出2.5 MB的读取缓冲区, getlasterror将返回error_outofmemory 。 
如果没有足够的可用磁盘空间mpqcompactarchive分配缓冲文件, GetLastError返回error_disk_full 。在某些特殊的情况下, getlasterror可能会返回其他一些奇怪的错误代码。 


Getting Information About a File - SFileGetFileInfo 
获取文件有关信息函数 - SFileGetFileInfo 


DWORD WINAPI SFileGetFileInfo(HANDLE hMPQorFile, DWORD dwInfoType);
Parameter What it is
hMPQorFile [in] The HANDLE of the either the MPQ or file inside an MPQ to obtain info about, which was acquired earlier with either SFileOpenArchive or SFileOpenFileEx.SFileGetFileInfo will fail (or worse) if this is NULL or a HANDLE not obtained with SFileOpenArchive or SFileOpenFileEx.
dwInfoType [in] The type of info to obtain about the file or MPQ. Must be one of the following values defined in lmpqapi.h:
SFILE_INFO_HASH_TABLE_SIZE SFileGetFileInfo will return the hash table size of hMPQorFile (see chapters 2 and 5 for more info). hMPQorFile must be a HANDLE of an MPQ.
SFILE_INFO_NUM_FILES SFileGetFileInfo will return the number of files inside hMPQorFile. hMPQorFile must be a HANDLE of an MPQ.
SFILE_INFO_SIZE SFileGetFileInfo will return the size of the MPQ hMPQorFile or the uncompressed size of the file hMPQorFile. This is functionally equivalent to theSFileGetFileSize function. hMPQorFile can be either a HANDLE of an MPQ or a HANDLE of a file inside.
SFILE_INFO_COMPRESSED_SIZE SFileGetFileInfo will return the compressed size (or uncompressed size if the file isn't compressed) of the file hMPQorFile in an MPQ. hMPQorFilemust be a HANDLE of a file inside an MPQ.
SFILE_INFO_FLAGS SFileGetFileInfo will return the flags (see chapter 5 for the meaning of specific flags) of the file hMPQorFile in an MPQ. hMPQorFile must be aHANDLE of a file inside an MPQ.
SFILE_INFO_POSITION SFileGetFileInfo will return the absolute position of the file pointer for the file hMPQorFile in an MPQ. hMPQorFile must be a HANDLE of a file inside an MPQ.


SFileGetFileInfo 是 LMPQAPI中最古怪的功能函数. 
不仅是唯一可以通过LMPQAPI而不能通过STROM接口库的STROM功能。 
它唯一的函数就是能够接受MPQ或者文件HANDLE,但在大多数情况下它根本不存在于STROM里。 
为了补救这个,我自己写了了这个SFileGetFileInfo。 

sfilegetfileinfo是专门设计来提供有用的mpq和其内档案的信息;包括mpq中压缩文件的大小,文件指针的位置。它使用简单,但相当有效。它使用已经打开了的mpq或文件的HANDLE,以获取有关hmpqorfile的信息 ,以及在dwinfotype中需要的信息类型代码。 

如果sfilegetfileinfo成功,返回值就是有关文件或MPQ的资料 。 
但是,如果失败的话,它会返回0xFFFFFFFF,并设置一个错误代码,您可以调用getlasterror查看 。 
如果因为hmpqorfile HANDLE是无效的, getlasterror将返回error_invalid_parameter 。 
如果因为dwinfotype是一个无效的信息代码,getlasterror将返回error_unknown_property 。 sfilegetfileinfo只在一种情况下会调用失败(除了严重的内部lmpqapi错误)。 
因为一个mpq HANDLE和dwinfotype指定的信息只能得到一个文件HANDLE,或反之亦然,在这种情况下, getlasterror将返回error_unknown_property。
123456
返回顶部