mirror of https://github.com/axmolengine/axmol.git
Add PVR.CCZ encryption support to ZipUtils based upon http://www.codeandweb.com/texturepacker/contentprotection
Add sample to TestCPP.
This commit is contained in:
parent
bd4f2b51a2
commit
f89d39953e
|
@ -1,26 +1,26 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2010 cocos2d-x.org
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
Copyright (c) 2010 cocos2d-x.org
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include <zlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -33,6 +33,106 @@ THE SOFTWARE.
|
|||
|
||||
NS_CC_BEGIN
|
||||
|
||||
static unsigned int caw_key[4] = {0,0,0,0};
|
||||
static unsigned int caw_longKey[1024];
|
||||
static bool caw_longKeyValid = false;
|
||||
|
||||
void caw_setkey_part(int index, unsigned int value)
|
||||
{
|
||||
CCAssert(index >= 0, "Cocos2d: key part index cannot be less than 0");
|
||||
CCAssert(index <= 3, "Cocos2d: key part index cannot be greater than 3");
|
||||
|
||||
if(caw_key[index] != value)
|
||||
{
|
||||
caw_key[index] = value;
|
||||
caw_longKeyValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void caw_encdec (unsigned int *data, int len)
|
||||
{
|
||||
const int enclen = 1024;
|
||||
const int securelen = 512;
|
||||
const int distance = 64;
|
||||
|
||||
// check if key was set
|
||||
// make sure to call caw_setkey_part() for all 4 key parts
|
||||
CCAssert(caw_key[0] != 0, "Cocos2D: CCZ file is encrypted but key part 0 is not set. Did you call caw_setkey_part(...)?");
|
||||
CCAssert(caw_key[1] != 0, "Cocos2D: CCZ file is encrypted but key part 1 is not set. Did you call caw_setkey_part(...)?");
|
||||
CCAssert(caw_key[2] != 0, "Cocos2D: CCZ file is encrypted but key part 2 is not set. Did you call caw_setkey_part(...)?");
|
||||
CCAssert(caw_key[3] != 0, "Cocos2D: CCZ file is encrypted but key part 3 is not set. Did you call caw_setkey_part(...)?");
|
||||
|
||||
// create long key
|
||||
if(!caw_longKeyValid)
|
||||
{
|
||||
unsigned int y, p, e;
|
||||
unsigned int rounds = 6;
|
||||
unsigned int sum = 0;
|
||||
unsigned int z = caw_longKey[enclen-1];
|
||||
|
||||
do
|
||||
{
|
||||
#define DELTA 0x9e3779b9
|
||||
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (caw_key[(p&3)^e] ^ z)))
|
||||
|
||||
sum += DELTA;
|
||||
e = (sum >> 2) & 3;
|
||||
|
||||
for (p = 0; p < enclen - 1; p++)
|
||||
{
|
||||
y = caw_longKey[p + 1];
|
||||
z = caw_longKey[p] += MX;
|
||||
}
|
||||
|
||||
y = caw_longKey[0];
|
||||
z = caw_longKey[enclen - 1] += MX;
|
||||
|
||||
} while (--rounds);
|
||||
|
||||
caw_longKeyValid = true;
|
||||
}
|
||||
|
||||
int b = 0;
|
||||
int i = 0;
|
||||
|
||||
// encrypt first part completely
|
||||
for(; i < len && i < securelen; i++)
|
||||
{
|
||||
data[i] ^= caw_longKey[b++];
|
||||
|
||||
if(b >= enclen)
|
||||
{
|
||||
b = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// encrypt second section partially
|
||||
for(; i < len; i += distance)
|
||||
{
|
||||
data[i] ^= caw_longKey[b++];
|
||||
|
||||
if(b >= enclen)
|
||||
{
|
||||
b = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned int caw_checksum(const unsigned int *data, int len)
|
||||
{
|
||||
unsigned int cs = 0;
|
||||
const int cslen = 128;
|
||||
|
||||
len = (len < cslen) ? len : cslen;
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
cs = cs ^ data[i];
|
||||
}
|
||||
|
||||
return cs;
|
||||
}
|
||||
|
||||
// --------------------- ZipUtils ---------------------
|
||||
|
||||
// memory in iPhone is precious
|
||||
|
@ -43,63 +143,63 @@ int ZipUtils::ccInflateMemoryWithHint(unsigned char *in, unsigned int inLength,
|
|||
{
|
||||
/* ret value */
|
||||
int err = Z_OK;
|
||||
|
||||
|
||||
int bufferSize = outLenghtHint;
|
||||
*out = new unsigned char[bufferSize];
|
||||
|
||||
z_stream d_stream; /* decompression stream */
|
||||
|
||||
z_stream d_stream; /* decompression stream */
|
||||
d_stream.zalloc = (alloc_func)0;
|
||||
d_stream.zfree = (free_func)0;
|
||||
d_stream.opaque = (voidpf)0;
|
||||
|
||||
|
||||
d_stream.next_in = in;
|
||||
d_stream.avail_in = inLength;
|
||||
d_stream.next_out = *out;
|
||||
d_stream.avail_out = bufferSize;
|
||||
|
||||
|
||||
/* window size to hold 256k */
|
||||
if( (err = inflateInit2(&d_stream, 15 + 32)) != Z_OK )
|
||||
return err;
|
||||
|
||||
for (;;)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
err = inflate(&d_stream, Z_NO_FLUSH);
|
||||
|
||||
|
||||
if (err == Z_STREAM_END)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
switch (err)
|
||||
|
||||
switch (err)
|
||||
{
|
||||
case Z_NEED_DICT:
|
||||
err = Z_DATA_ERROR;
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
inflateEnd(&d_stream);
|
||||
return err;
|
||||
case Z_NEED_DICT:
|
||||
err = Z_DATA_ERROR;
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
inflateEnd(&d_stream);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
// not enough memory ?
|
||||
if (err != Z_STREAM_END)
|
||||
if (err != Z_STREAM_END)
|
||||
{
|
||||
delete [] *out;
|
||||
*out = new unsigned char[bufferSize * BUFFER_INC_FACTOR];
|
||||
|
||||
|
||||
/* not enough memory, ouch */
|
||||
if (! *out )
|
||||
if (! *out )
|
||||
{
|
||||
CCLOG("cocos2d: ZipUtils: realloc failed");
|
||||
inflateEnd(&d_stream);
|
||||
return Z_MEM_ERROR;
|
||||
}
|
||||
|
||||
|
||||
d_stream.next_out = *out + bufferSize;
|
||||
d_stream.avail_out = bufferSize;
|
||||
bufferSize *= BUFFER_INC_FACTOR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*outLength = bufferSize - d_stream.avail_out;
|
||||
err = inflateEnd(&d_stream);
|
||||
return err;
|
||||
|
@ -109,30 +209,30 @@ int ZipUtils::ccInflateMemoryWithHint(unsigned char *in, unsigned int inLength,
|
|||
{
|
||||
unsigned int outLength = 0;
|
||||
int err = ccInflateMemoryWithHint(in, inLength, out, &outLength, outLengthHint);
|
||||
|
||||
|
||||
if (err != Z_OK || *out == NULL) {
|
||||
if (err == Z_MEM_ERROR)
|
||||
{
|
||||
CCLOG("cocos2d: ZipUtils: Out of memory while decompressing map data!");
|
||||
} else
|
||||
if (err == Z_VERSION_ERROR)
|
||||
{
|
||||
CCLOG("cocos2d: ZipUtils: Incompatible zlib version!");
|
||||
} else
|
||||
if (err == Z_DATA_ERROR)
|
||||
{
|
||||
CCLOG("cocos2d: ZipUtils: Incorrect zlib compressed data!");
|
||||
}
|
||||
else
|
||||
{
|
||||
CCLOG("cocos2d: ZipUtils: Unknown error while decompressing map data!");
|
||||
}
|
||||
|
||||
} else
|
||||
if (err == Z_VERSION_ERROR)
|
||||
{
|
||||
CCLOG("cocos2d: ZipUtils: Incompatible zlib version!");
|
||||
} else
|
||||
if (err == Z_DATA_ERROR)
|
||||
{
|
||||
CCLOG("cocos2d: ZipUtils: Incorrect zlib compressed data!");
|
||||
}
|
||||
else
|
||||
{
|
||||
CCLOG("cocos2d: ZipUtils: Unknown error while decompressing map data!");
|
||||
}
|
||||
|
||||
delete[] *out;
|
||||
*out = NULL;
|
||||
outLength = 0;
|
||||
}
|
||||
|
||||
|
||||
return outLength;
|
||||
}
|
||||
|
||||
|
@ -146,30 +246,30 @@ int ZipUtils::ccInflateGZipFile(const char *path, unsigned char **out)
|
|||
{
|
||||
int len;
|
||||
unsigned int offset = 0;
|
||||
|
||||
|
||||
CCAssert(out, "");
|
||||
CCAssert(&*out, "");
|
||||
|
||||
|
||||
gzFile inFile = gzopen(path, "rb");
|
||||
if( inFile == NULL ) {
|
||||
CCLOG("cocos2d: ZipUtils: error open gzip file: %s", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* 512k initial decompress buffer */
|
||||
unsigned int bufferSize = 512 * 1024;
|
||||
unsigned int totalBufferSize = bufferSize;
|
||||
|
||||
|
||||
*out = (unsigned char*)malloc( bufferSize );
|
||||
if( ! out )
|
||||
if( ! out )
|
||||
{
|
||||
CCLOG("cocos2d: ZipUtils: out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
for (;;) {
|
||||
len = gzread(inFile, *out + offset, bufferSize);
|
||||
if (len < 0)
|
||||
if (len < 0)
|
||||
{
|
||||
CCLOG("cocos2d: ZipUtils: error in gzread");
|
||||
free( *out );
|
||||
|
@ -180,108 +280,150 @@ int ZipUtils::ccInflateGZipFile(const char *path, unsigned char **out)
|
|||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
offset += len;
|
||||
|
||||
|
||||
// finish reading the file
|
||||
if( (unsigned int)len < bufferSize )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
bufferSize *= BUFFER_INC_FACTOR;
|
||||
totalBufferSize += bufferSize;
|
||||
unsigned char *tmp = (unsigned char*)realloc(*out, totalBufferSize );
|
||||
|
||||
if( ! tmp )
|
||||
|
||||
if( ! tmp )
|
||||
{
|
||||
CCLOG("cocos2d: ZipUtils: out of memory");
|
||||
free( *out );
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
*out = tmp;
|
||||
}
|
||||
|
||||
|
||||
if (gzclose(inFile) != Z_OK)
|
||||
{
|
||||
CCLOG("cocos2d: ZipUtils: gzclose failed");
|
||||
}
|
||||
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
int ZipUtils::ccInflateCCZFile(const char *path, unsigned char **out)
|
||||
{
|
||||
CCAssert(out, "");
|
||||
CCAssert(&*out, "");
|
||||
|
||||
// load file into memory
|
||||
unsigned char* compressed = NULL;
|
||||
CCAssert(out, "");
|
||||
CCAssert(&*out, "");
|
||||
|
||||
unsigned long fileLen = 0;
|
||||
compressed = CCFileUtils::sharedFileUtils()->getFileData(path, "rb", &fileLen);
|
||||
|
||||
if(NULL == compressed || 0 == fileLen)
|
||||
{
|
||||
CCLOG("cocos2d: Error loading CCZ compressed file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct CCZHeader *header = (struct CCZHeader*) compressed;
|
||||
|
||||
// verify header
|
||||
if( header->sig[0] != 'C' || header->sig[1] != 'C' || header->sig[2] != 'Z' || header->sig[3] != '!' )
|
||||
{
|
||||
CCLOG("cocos2d: Invalid CCZ file");
|
||||
delete [] compressed;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// verify header version
|
||||
unsigned int version = CC_SWAP_INT16_BIG_TO_HOST( header->version );
|
||||
if( version > 2 )
|
||||
{
|
||||
CCLOG("cocos2d: Unsupported CCZ header format");
|
||||
delete [] compressed;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// verify compression format
|
||||
if( CC_SWAP_INT16_BIG_TO_HOST(header->compression_type) != CCZ_COMPRESSION_ZLIB )
|
||||
{
|
||||
CCLOG("cocos2d: CCZ Unsupported compression method");
|
||||
delete [] compressed;
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned int len = CC_SWAP_INT32_BIG_TO_HOST( header->len );
|
||||
|
||||
*out = (unsigned char*)malloc( len );
|
||||
if(! *out )
|
||||
{
|
||||
CCLOG("cocos2d: CCZ: Failed to allocate memory for texture");
|
||||
delete [] compressed;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
unsigned long destlen = len;
|
||||
unsigned long source = (unsigned long) compressed + sizeof(*header);
|
||||
int ret = uncompress(*out, &destlen, (Bytef*)source, fileLen - sizeof(*header) );
|
||||
|
||||
delete [] compressed;
|
||||
|
||||
if( ret != Z_OK )
|
||||
{
|
||||
CCLOG("cocos2d: CCZ: Failed to uncompress data");
|
||||
free( *out );
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
// load file into memory
|
||||
unsigned char* compressed = NULL;
|
||||
|
||||
unsigned long fileLen = 0;
|
||||
compressed = CCFileUtils::sharedFileUtils()->getFileData(path, "rb", &fileLen);
|
||||
|
||||
if(NULL == compressed || 0 == fileLen)
|
||||
{
|
||||
CCLOG("cocos2d: Error loading CCZ compressed file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct CCZHeader *header = (struct CCZHeader*) compressed;
|
||||
|
||||
// verify header
|
||||
if( header->sig[0] == 'C' && header->sig[1] == 'C' && header->sig[2] == 'Z' && header->sig[3] == '!' )
|
||||
{
|
||||
// verify header version
|
||||
unsigned int version = CC_SWAP_INT16_BIG_TO_HOST( header->version );
|
||||
if( version > 2 )
|
||||
{
|
||||
CCLOG("cocos2d: Unsupported CCZ header format");
|
||||
delete [] compressed;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// verify compression format
|
||||
if( CC_SWAP_INT16_BIG_TO_HOST(header->compression_type) != CCZ_COMPRESSION_ZLIB )
|
||||
{
|
||||
CCLOG("cocos2d: CCZ Unsupported compression method");
|
||||
delete [] compressed;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if( header->sig[0] == 'C' && header->sig[1] == 'C' && header->sig[2] == 'Z' && header->sig[3] == 'p' )
|
||||
{
|
||||
// encrypted ccz file
|
||||
header = (struct CCZHeader*) compressed;
|
||||
|
||||
// verify header version
|
||||
unsigned int version = CC_SWAP_INT16_BIG_TO_HOST( header->version );
|
||||
if( version > 0 )
|
||||
{
|
||||
CCLOG("cocos2d: Unsupported CCZ header format");
|
||||
delete [] compressed;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// verify compression format
|
||||
if( CC_SWAP_INT16_BIG_TO_HOST(header->compression_type) != CCZ_COMPRESSION_ZLIB )
|
||||
{
|
||||
CCLOG("cocos2d: CCZ Unsupported compression method");
|
||||
delete [] compressed;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// decrypt
|
||||
unsigned int* ints = (unsigned int*)(compressed+12);
|
||||
int enclen = (fileLen-12)/4;
|
||||
|
||||
caw_encdec(ints, enclen);
|
||||
|
||||
#if COCOS2D_DEBUG > 0
|
||||
// verify checksum in debug mode
|
||||
unsigned int calculated = caw_checksum(ints, enclen);
|
||||
unsigned int required = CC_SWAP_INT32_BIG_TO_HOST( header->reserved );
|
||||
|
||||
if(calculated != required)
|
||||
{
|
||||
CCLOG("cocos2d: Can't decrypt image file: Invalid decryption key");
|
||||
delete [] compressed;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
CCLOG("cocos2d: Invalid CCZ file");
|
||||
delete [] compressed;
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned int len = CC_SWAP_INT32_BIG_TO_HOST( header->len );
|
||||
|
||||
*out = (unsigned char*)malloc( len );
|
||||
if(! *out )
|
||||
{
|
||||
CCLOG("cocos2d: CCZ: Failed to allocate memory for texture");
|
||||
delete [] compressed;
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned long destlen = len;
|
||||
unsigned long source = (unsigned long) compressed + sizeof(*header);
|
||||
int ret = uncompress(*out, &destlen, (Bytef*)source, fileLen - sizeof(*header) );
|
||||
|
||||
delete [] compressed;
|
||||
|
||||
if( ret != Z_OK )
|
||||
{
|
||||
CCLOG("cocos2d: CCZ: Failed to uncompress data");
|
||||
free( *out );
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// --------------------- ZipFile ---------------------
|
||||
|
@ -298,14 +440,14 @@ class ZipFilePrivate
|
|||
{
|
||||
public:
|
||||
unzFile zipFile;
|
||||
|
||||
|
||||
// std::unordered_map is faster if available on the platform
|
||||
typedef std::map<std::string, struct ZipEntryInfo> FileListContainer;
|
||||
FileListContainer fileList;
|
||||
};
|
||||
|
||||
ZipFile::ZipFile(const std::string &zipFile, const std::string &filter)
|
||||
: m_data(new ZipFilePrivate)
|
||||
: m_data(new ZipFilePrivate)
|
||||
{
|
||||
m_data->zipFile = unzOpen(zipFile.c_str());
|
||||
if (m_data->zipFile)
|
||||
|
@ -330,17 +472,17 @@ bool ZipFile::setFilter(const std::string &filter)
|
|||
{
|
||||
CC_BREAK_IF(!m_data);
|
||||
CC_BREAK_IF(!m_data->zipFile);
|
||||
|
||||
|
||||
// clear existing file list
|
||||
m_data->fileList.clear();
|
||||
|
||||
|
||||
// UNZ_MAXFILENAMEINZIP + 1 - it is done so in unzLocateFile
|
||||
char szCurrentFileName[UNZ_MAXFILENAMEINZIP + 1];
|
||||
unz_file_info64 fileInfo;
|
||||
|
||||
|
||||
// go through all files and store position information about the required files
|
||||
int err = unzGoToFirstFile64(m_data->zipFile, &fileInfo,
|
||||
szCurrentFileName, sizeof(szCurrentFileName) - 1);
|
||||
szCurrentFileName, sizeof(szCurrentFileName) - 1);
|
||||
while (err == UNZ_OK)
|
||||
{
|
||||
unz_file_pos posInfo;
|
||||
|
@ -360,12 +502,12 @@ bool ZipFile::setFilter(const std::string &filter)
|
|||
}
|
||||
// next file - also get the information about it
|
||||
err = unzGoToNextFile64(m_data->zipFile, &fileInfo,
|
||||
szCurrentFileName, sizeof(szCurrentFileName) - 1);
|
||||
szCurrentFileName, sizeof(szCurrentFileName) - 1);
|
||||
}
|
||||
ret = true;
|
||||
|
||||
|
||||
} while(false);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -375,10 +517,10 @@ bool ZipFile::fileExists(const std::string &fileName) const
|
|||
do
|
||||
{
|
||||
CC_BREAK_IF(!m_data);
|
||||
|
||||
|
||||
ret = m_data->fileList.find(fileName) != m_data->fileList.end();
|
||||
} while(false);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -389,34 +531,34 @@ unsigned char *ZipFile::getFileData(const std::string &fileName, unsigned long *
|
|||
{
|
||||
*pSize = 0;
|
||||
}
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
CC_BREAK_IF(!m_data->zipFile);
|
||||
CC_BREAK_IF(fileName.empty());
|
||||
|
||||
|
||||
ZipFilePrivate::FileListContainer::const_iterator it = m_data->fileList.find(fileName);
|
||||
CC_BREAK_IF(it == m_data->fileList.end());
|
||||
|
||||
|
||||
ZipEntryInfo fileInfo = it->second;
|
||||
|
||||
|
||||
int nRet = unzGoToFilePos(m_data->zipFile, &fileInfo.pos);
|
||||
CC_BREAK_IF(UNZ_OK != nRet);
|
||||
|
||||
|
||||
nRet = unzOpenCurrentFile(m_data->zipFile);
|
||||
CC_BREAK_IF(UNZ_OK != nRet);
|
||||
|
||||
|
||||
pBuffer = new unsigned char[fileInfo.uncompressed_size];
|
||||
int CC_UNUSED nSize = unzReadCurrentFile(m_data->zipFile, pBuffer, fileInfo.uncompressed_size);
|
||||
CCAssert(nSize == 0 || nSize == (int)fileInfo.uncompressed_size, "the file size is wrong");
|
||||
|
||||
|
||||
if (pSize)
|
||||
{
|
||||
*pSize = fileInfo.uncompressed_size;
|
||||
}
|
||||
unzCloseCurrentFile(m_data->zipFile);
|
||||
} while (0);
|
||||
|
||||
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,26 @@ THE SOFTWARE.
|
|||
|
||||
namespace cocos2d
|
||||
{
|
||||
/**
|
||||
* Set the TexturePacker encryption key
|
||||
*
|
||||
* If your key used to encrypt the pvr.ccz file is
|
||||
* aaaaaaaabbbbbbbbccccccccdddddddd
|
||||
* you have to call this function 4 times:
|
||||
* caw_setkey_part(0, 0xaaaaaaaa);
|
||||
* caw_setkey_part(1, 0xbbbbbbbb);
|
||||
* caw_setkey_part(2, 0xcccccccc);
|
||||
* caw_setkey_part(3, 0xdddddddd);
|
||||
*
|
||||
* Distribute the call accross some files but make sure
|
||||
* to call all of the parts *before* loading the first
|
||||
* spritesheet.
|
||||
*
|
||||
* @param index part of the key [0..3]
|
||||
* @param value value of the key part
|
||||
*/
|
||||
void caw_setkey_part(int index, uint32_t value);
|
||||
|
||||
/* XXX: pragma pack ??? */
|
||||
/** @struct CCZHeader
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
#include "TextureAtlasEncryptionTest.h"
|
||||
#include "../testResource.h"
|
||||
#include "support/zip_support/ZipUtils.h"
|
||||
|
||||
std::string TextureAtlasEncryptionDemo::title()
|
||||
{
|
||||
return "Texture Atlas Encryption";
|
||||
}
|
||||
|
||||
std::string TextureAtlasEncryptionDemo::subtitle()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void TextureAtlasEncryptionDemo::onEnter()
|
||||
{
|
||||
CCLayer::onEnter();
|
||||
|
||||
CCSize s = CCDirector::sharedDirector()->getWinSize();
|
||||
|
||||
CCLabelTTF* label = CCLabelTTF::create(title().c_str(), "Arial", 28);
|
||||
label->setPosition( ccp(s.width/2, s.height * 0.75f) );
|
||||
this->addChild(label, 1);
|
||||
|
||||
std::string strSubtitle = subtitle();
|
||||
if(strSubtitle.empty() == false)
|
||||
{
|
||||
CCLabelTTF* subLabel = CCLabelTTF::create(strSubtitle.c_str(), "Thonburi", 16);
|
||||
subLabel->setPosition( ccp(s.width/2, s.height-80) );
|
||||
this->addChild(subLabel, 1);
|
||||
}
|
||||
|
||||
// Load the non-encrypted atlas
|
||||
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("Images/nonencryptedAtlas.plist", "Images/nonencryptedAtlas.pvr.ccz");
|
||||
|
||||
// Create a sprite from the non-encrypted atlas
|
||||
CCSprite *nonencryptedSprite = CCSprite::createWithSpriteFrameName("Icon.png");
|
||||
nonencryptedSprite->setPosition(ccp(s.width * 0.25f, s.height * 0.5f));
|
||||
this->addChild(nonencryptedSprite);
|
||||
|
||||
CCLabelTTF* nonencryptedSpriteLabel = CCLabelTTF::create("non-encrypted", "Arial", 28);
|
||||
nonencryptedSpriteLabel->setPosition(ccp(s.width * 0.25f, nonencryptedSprite->boundingBox().getMinY() - nonencryptedSprite->getContentSize().height/2));
|
||||
this->addChild(nonencryptedSpriteLabel, 1);
|
||||
|
||||
// Load the encrypted atlas
|
||||
// 1) Set the encryption keys or step 2 will fail
|
||||
caw_setkey_part(0, 0xaaaaaaaa);
|
||||
caw_setkey_part(1, 0xbbbbbbbb);
|
||||
caw_setkey_part(2, 0xcccccccc);
|
||||
caw_setkey_part(3, 0xdddddddd);
|
||||
|
||||
// 2) Load the encrypted atlas
|
||||
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("Images/encryptedAtlas.plist", "Images/encryptedAtlas.pvr.ccz");
|
||||
|
||||
// 3) Create a sprite from the encrypted atlas
|
||||
CCSprite *encryptedSprite = CCSprite::createWithSpriteFrameName("powered.png");
|
||||
encryptedSprite->setPosition(ccp(s.width * 0.75f, s.height * 0.5f));
|
||||
this->addChild(encryptedSprite);
|
||||
|
||||
CCLabelTTF* encryptedSpriteLabel = CCLabelTTF::create("encrypted", "Arial", 28);
|
||||
encryptedSpriteLabel->setPosition(ccp(s.width * 0.75f, encryptedSprite->boundingBox().getMinY() - encryptedSpriteLabel->getContentSize().height/2));
|
||||
this->addChild(encryptedSpriteLabel, 1);
|
||||
}
|
||||
|
||||
void TextureAtlasEncryptionTestScene::runThisTest()
|
||||
{
|
||||
CCLayer *layer = new TextureAtlasEncryptionDemo;
|
||||
layer->autorelease();
|
||||
|
||||
addChild(layer);
|
||||
|
||||
CCDirector::sharedDirector()->replaceScene(this);
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef _TextureAtlasEncryption_TEST_H_
|
||||
#define _TextureAtlasEncryption_TEST_H_
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "../testBasic.h"
|
||||
#include <string>
|
||||
|
||||
class TextureAtlasEncryptionDemo : public CCLayer
|
||||
{
|
||||
public:
|
||||
virtual std::string title();
|
||||
virtual std::string subtitle();
|
||||
virtual void onEnter();
|
||||
|
||||
protected:
|
||||
std::string m_strTitle;
|
||||
};
|
||||
|
||||
class TextureAtlasEncryptionTestScene : public TestScene
|
||||
{
|
||||
public:
|
||||
virtual void runThisTest();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -122,6 +122,9 @@ static TestScene* CreateTestScene(int nIdx)
|
|||
case TEST_SPINE:
|
||||
pScene = new SpineTestScene();
|
||||
break;
|
||||
case TEST_TEXTUREPACKER_ENCRYPTION:
|
||||
pScene = new TextureAtlasEncryptionTestScene();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#endif
|
||||
#include "FileUtilsTest/FileUtilsTest.h"
|
||||
#include "SpineTest/SpineTest.h"
|
||||
#include "TexturePackerEncryptionTest/TextureAtlasEncryptionTest.h"
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -111,6 +112,7 @@ enum
|
|||
#endif
|
||||
TEST_FILEUTILS,
|
||||
TEST_SPINE,
|
||||
TEST_TEXTUREPACKER_ENCRYPTION,
|
||||
TESTS_COUNT,
|
||||
};
|
||||
|
||||
|
@ -168,7 +170,8 @@ const std::string g_aTestNames[TESTS_COUNT] = {
|
|||
"ClippingNodeTest",
|
||||
#endif
|
||||
"FileUtilsTest",
|
||||
"SpineTest"
|
||||
"SpineTest",
|
||||
"TexturePackerEncryption"
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1 +1 @@
|
|||
655a6ce855dabb133120b19537ed3879b2fc8194
|
||||
2560c2b2abf0916bf27c47de3987b1567c690df9
|
Loading…
Reference in New Issue