bool SuperAnimDefMgr::LoadSuperAnimMainDef(std::string theSuperAnimFile)
	{
		std::string aFullPath = theSuperAnimFile;
		
		std::string aCurDir = "";
		int aLastSlash = max((int) theSuperAnimFile.rfind('\\'), (int) theSuperAnimFile.rfind('/'));
		if (aLastSlash != std::string::npos){
			aCurDir = theSuperAnimFile.substr(0, aLastSlash);
		}
		
		FILE *aFile = fopen(aFullPath.c_str(), "rb");
		if (aFile == NULL)
		{
			assert(false && "Can't open animation file.");
			return false;
		}
		
		fseek(aFile, 0, SEEK_END);
		unsigned long aFileSize = ftell(aFile);
		fseek(aFile, 0, SEEK_SET);
		unsigned char *aFileBuffer = new unsigned char[aFileSize];
		if (aFileBuffer == NULL)
		{
			assert(false && "Cannot allocate memory.");
			return false;
		}
		aFileSize = fread(aFileBuffer, sizeof(unsigned char), aFileSize, aFile);
		fclose(aFile);
		BufferReader aBuffer;
		aBuffer.SetData(aFileBuffer, aFileSize);
		// free memory
		delete[] aFileBuffer;
		aFileBuffer = NULL;
		
		if (aBuffer.ReadLong() != 0x2E53414D)
		{
			assert(false && "Bad file format.");
			return false;
		}
		
		int aVersion = aBuffer.ReadLong();
		
		if (aVersion != SAM_VERSION)
		{
			assert(false && "Wrong version.");
			return false;
		}
		
		SuperAnimMainDef &aMainDef = mMainDefCache[theSuperAnimFile]; 
		aMainDef.mAnimRate = aBuffer.ReadByte();
		aMainDef.mX = aBuffer.ReadShort() / TWIPS_PER_PIXEL;
		aMainDef.mY = aBuffer.ReadShort() / TWIPS_PER_PIXEL;
		aMainDef.mWidth = aBuffer.ReadShort() / TWIPS_PER_PIXEL;
		aMainDef.mHeight = aBuffer.ReadShort() / TWIPS_PER_PIXEL;
		
		int aNumImages = aBuffer.ReadShort();
		aMainDef.mImageVector.resize(aNumImages);
		for (int anImageNum = 0; anImageNum < aNumImages; ++anImageNum)
		{
			SuperAnimImage &aSuperAnimImage = aMainDef.mImageVector[anImageNum];
			aSuperAnimImage.mImageName = aBuffer.ReadString();
			aSuperAnimImage.mWidth = aBuffer.ReadShort();
			aSuperAnimImage.mHeight = aBuffer.ReadShort();
			
			aSuperAnimImage.mTransform.mMatrix.m00 = aBuffer.ReadLong() / (LONG_TO_FLOAT * TWIPS_PER_PIXEL);
			aSuperAnimImage.mTransform.mMatrix.m01 = -aBuffer.ReadLong() / (LONG_TO_FLOAT * TWIPS_PER_PIXEL);
			aSuperAnimImage.mTransform.mMatrix.m10 = -aBuffer.ReadLong() / (LONG_TO_FLOAT * TWIPS_PER_PIXEL);
			aSuperAnimImage.mTransform.mMatrix.m11 = aBuffer.ReadLong() / (LONG_TO_FLOAT * TWIPS_PER_PIXEL);
			aSuperAnimImage.mTransform.mMatrix.m02 = aBuffer.ReadShort() / TWIPS_PER_PIXEL;
			aSuperAnimImage.mTransform.mMatrix.m12 = aBuffer.ReadShort() / TWIPS_PER_PIXEL;
			
			std::string aImagePath;
			if (aCurDir.empty()) {
				aImagePath = aSuperAnimImage.mImageName;
			} else {
				aImagePath = aCurDir + '/' + aSuperAnimImage.mImageName;
			}
			
			aSuperAnimImage.mSpriteId = LoadSuperAnimSprite(aImagePath);
		}
		
		int aNumFrames = aBuffer.ReadShort();
		assert(aNumFrames > 0 && "We don't have valid frames.");
		aMainDef.mStartFrameNum = 0;
		aMainDef.mEndFrameNum = aNumFrames - 1;
		aMainDef.mFrames.resize(aNumFrames);
		IntToSuperAnimObjectMap aCurObjectMap;
		for (int aFrameNum = 0; aFrameNum < aNumFrames; ++aFrameNum)
		{
			SuperAnimFrame &aFrame = aMainDef.mFrames[aFrameNum];
			uchar aFrameFlags = aBuffer.ReadByte();
			
			if (aFrameFlags & FRAMEFLAGS_REMOVES)
			{
				int aNumRemoves = aBuffer.ReadByte();
				for (int aRemoveNum = 0; aRemoveNum < aNumRemoves; ++ aRemoveNum)
				{
					int anObjectId = aBuffer.ReadShort();
					IntToSuperAnimObjectMap::iterator anIt = aCurObjectMap.find(anObjectId);
					if (anIt != aCurObjectMap.end())
					{
						aCurObjectMap.erase(anIt);
					}
				}
			}
			
			if (aFrameFlags & FRAMEFLAGS_ADDS)
			{
				int aNumAdds = aBuffer.ReadByte();
				for(int anAddNum = 0; anAddNum < aNumAdds; ++anAddNum)
				{
					SuperAnimObject aSuperAnimObject;
					aSuperAnimObject.mObjectNum = (aBuffer.ReadShort() & 0x07FF);
					aSuperAnimObject.mResNum = aBuffer.ReadByte();
					aSuperAnimObject.mColor = Color(255, 255, 255, 255);
					aCurObjectMap.insert(IntToSuperAnimObjectMap::value_type(aSuperAnimObject.mObjectNum, aSuperAnimObject));
				}
			}
			
			if (aFrameFlags & FRAMEFLAGS_MOVES)
			{
				int aNumMoves = aBuffer.ReadByte();
				for (int aMoveNum = 0; aMoveNum < aNumMoves; ++ aMoveNum)
				{
					unsigned short aFlagsAndObjectNum = aBuffer.ReadShort();
					int anObjectNum = aFlagsAndObjectNum & 0x03FF;
					
					IntToSuperAnimObjectMap::iterator anIt = aCurObjectMap.find(anObjectNum);
					if (anIt == aCurObjectMap.end())
						continue;
					SuperAnimObject &aSuperAnimObject = anIt->second;
					aSuperAnimObject.mTransform.mMatrix.LoadIdentity();
					
					if (aFlagsAndObjectNum & MOVEFLAGS_MATRIX)
					{
						aSuperAnimObject.mTransform.mMatrix.m00 = aBuffer.ReadLong() / LONG_TO_FLOAT;
						aSuperAnimObject.mTransform.mMatrix.m01 = -aBuffer.ReadLong() / LONG_TO_FLOAT;
						aSuperAnimObject.mTransform.mMatrix.m10 = -aBuffer.ReadLong() / LONG_TO_FLOAT;
						aSuperAnimObject.mTransform.mMatrix.m11 = aBuffer.ReadLong() / LONG_TO_FLOAT;
					}
					else if (aFlagsAndObjectNum & MOVEFLAGS_ROTATE)
					{
						float aRot = aBuffer.ReadShort() / 1000.0f;
						float sinRot = sinf(aRot);
						float cosRot = cosf(aRot);
						aSuperAnimObject.mTransform.mMatrix.m00 = cosRot;
						aSuperAnimObject.mTransform.mMatrix.m01 = sinRot;
						aSuperAnimObject.mTransform.mMatrix.m10 = -sinRot;
						aSuperAnimObject.mTransform.mMatrix.m11 = cosRot;
					}
					
					SuperAnimMatrix3 aMatrix;
					aMatrix.LoadIdentity();
					if (aFlagsAndObjectNum & MOVEFLAGS_LONGCOORDS)
					{
						aMatrix.m02 = aBuffer.ReadLong() / TWIPS_PER_PIXEL;
						aMatrix.m12 = aBuffer.ReadLong() / TWIPS_PER_PIXEL;
					}
					else
					{
						aMatrix.m02 = aBuffer.ReadShort() / TWIPS_PER_PIXEL;
						aMatrix.m12 = aBuffer.ReadShort() / TWIPS_PER_PIXEL;
					}
					aSuperAnimObject.mTransform.mMatrix = aMatrix * aSuperAnimObject.mTransform.mMatrix;
					
					if (aFlagsAndObjectNum & MOVEFLAGS_COLOR)
					{
						aSuperAnimObject.mColor.mRed = aBuffer.ReadByte();
						aSuperAnimObject.mColor.mGreen = aBuffer.ReadByte();
						aSuperAnimObject.mColor.mBlue = aBuffer.ReadByte();
						aSuperAnimObject.mColor.mAlpha = aBuffer.ReadByte();
					}
				}
			}
			
			if (aFrameFlags & FRAMEFLAGS_FRAME_NAME)
			{
				std::string aFrameName = aBuffer.ReadString();
				aMainDef.mLabels.insert(StringToIntMap::value_type(aFrameName, aFrameNum));
			}
			
			aFrame.mObjectVector.resize(aCurObjectMap.size());
			int anObjectNum = 0;
			for (IntToSuperAnimObjectMap::iterator anIt = aCurObjectMap.begin(); anIt != aCurObjectMap.end(); ++anIt, ++anObjectNum)
			{
				SuperAnimObject &anObject = anIt->second;
				aFrame.mObjectVector[anObjectNum] = anObject;
			}
		}
		
		return true;
	}
bool SuperAnimDefMgr::LoadSuperAnimMainDef(const std::string &theSuperAnimFile)
{
    std::string aFullPath = theSuperAnimFile;
    
    std::string aCurDir = "";
    int aLastSlash = max((int) theSuperAnimFile.rfind('\\'), (int) theSuperAnimFile.rfind('/'));
    if (aLastSlash != std::string::npos){
        aCurDir = theSuperAnimFile.substr(0, aLastSlash);
    }

    size_t aFileSize = 0;
    unsigned char *aFileBuffer = CCFileUtils::sharedFileUtils()->getFileData(aFullPath.c_str(), "rb", &aFileSize);
    if (aFileBuffer == NULL)
    {
        assert(false && "Cannot allocate memory.");
        return false;
    }
    BufferReader aBuffer;
    aBuffer.SetData(aFileBuffer, (int)aFileSize);
    // free memory
    delete[] aFileBuffer;
    
    if (aBuffer.ReadLong() != 0x2E53414D)
    {
        assert(false && "Bad file format.");
        return false;
    }
    
    int aVersion = (int)aBuffer.ReadLong();
    
    if (aVersion != SAM_VERSION)
    {
        assert(false && "Wrong version.");
        return false;
    }
    
    SuperAnimMainDef &aMainDef = mMainDefCache[theSuperAnimFile]; 
    aMainDef.mAnimRate = aBuffer.ReadByte();
    aMainDef.mX = aBuffer.ReadLong() / TWIPS_PER_PIXEL;
    aMainDef.mY = aBuffer.ReadLong() / TWIPS_PER_PIXEL;
    aMainDef.mWidth = aBuffer.ReadLong() / TWIPS_PER_PIXEL;
    aMainDef.mHeight = aBuffer.ReadLong() / TWIPS_PER_PIXEL;
    
    SuperAnimLabelArray aSuperAnimLabelArray;
    
    int aNumImages = aBuffer.ReadShort();
    aMainDef.mImageVector.resize(aNumImages);
    for (int anImageNum = 0; anImageNum < aNumImages; ++anImageNum)
    {
        SuperAnimImage &aSuperAnimImage = aMainDef.mImageVector[anImageNum];
        aSuperAnimImage.mImageName = aBuffer.ReadString();
        aSuperAnimImage.mWidth = aBuffer.ReadShort();
        aSuperAnimImage.mHeight = aBuffer.ReadShort();
        
        aSuperAnimImage.mTransform.mMatrix.m00 = aBuffer.ReadLong() / (LONG_TO_FLOAT * TWIPS_PER_PIXEL);
        aSuperAnimImage.mTransform.mMatrix.m01 = -aBuffer.ReadLong() / (LONG_TO_FLOAT * TWIPS_PER_PIXEL);
        aSuperAnimImage.mTransform.mMatrix.m10 = -aBuffer.ReadLong() / (LONG_TO_FLOAT * TWIPS_PER_PIXEL);
        aSuperAnimImage.mTransform.mMatrix.m11 = aBuffer.ReadLong() / (LONG_TO_FLOAT * TWIPS_PER_PIXEL);
        aSuperAnimImage.mTransform.mMatrix.m02 = aBuffer.ReadShort() / TWIPS_PER_PIXEL;
        aSuperAnimImage.mTransform.mMatrix.m12 = aBuffer.ReadShort() / TWIPS_PER_PIXEL;
        
        std::string aImagePath;
        if (aCurDir.empty()) {
            aImagePath = aSuperAnimImage.mImageName;
        } else {
            aImagePath = aCurDir + '/' + aSuperAnimImage.mImageName;
        }
        
        aSuperAnimImage.mSpriteId = LoadSuperAnimSprite(aImagePath);
    }
    
    int aNumFrames = aBuffer.ReadShort();
    assert(aNumFrames > 0 && "We don't have valid frames.");
    aMainDef.mStartFrameNum = 0;
    aMainDef.mEndFrameNum = aNumFrames - 1;
    aMainDef.mFrames.resize(aNumFrames);
    IntToSuperAnimObjectMap aCurObjectMap;
    for (int aFrameNum = 0; aFrameNum < aNumFrames; ++aFrameNum)
    {
        SuperAnimFrame &aFrame = aMainDef.mFrames[aFrameNum];
        uchar aFrameFlags = aBuffer.ReadByte();
        
        if (aFrameFlags & FRAMEFLAGS_REMOVES)
        {
            int aNumRemoves = aBuffer.ReadByte();
            for (int aRemoveNum = 0; aRemoveNum < aNumRemoves; ++ aRemoveNum)
            {
                int anObjectId = aBuffer.ReadShort();
                IntToSuperAnimObjectMap::iterator anIt = aCurObjectMap.find(anObjectId);
                if (anIt != aCurObjectMap.end())
                {
                    aCurObjectMap.erase(anIt);
                }
            }
        }
        
        if (aFrameFlags & FRAMEFLAGS_ADDS)
        {
            int aNumAdds = aBuffer.ReadByte();
            for(int anAddNum = 0; anAddNum < aNumAdds; ++anAddNum)
            {
                int anObjNum = (aBuffer.ReadShort() & 0x07FF);
                SuperAnimObject& aSuperAnimObject = aCurObjectMap[anObjNum];
                aSuperAnimObject.mObjectNum = anObjNum;
                aSuperAnimObject.mResNum = aBuffer.ReadByte();
                aSuperAnimObject.mColor = Color(255, 255, 255, 255);
            }
        }
        
        if (aFrameFlags & FRAMEFLAGS_MOVES)
        {
            int aNumMoves = aBuffer.ReadByte();
            for (int aMoveNum = 0; aMoveNum < aNumMoves; ++ aMoveNum)
            {
                unsigned short aFlagsAndObjectNum = aBuffer.ReadShort();
                int anObjectNum = aFlagsAndObjectNum & 0x03FF;
                
                IntToSuperAnimObjectMap::iterator anIt = aCurObjectMap.find(anObjectNum);
                if (anIt == aCurObjectMap.end())
                    continue;
                SuperAnimObject &aSuperAnimObject = anIt->second;
                aSuperAnimObject.mTransform.mMatrix.LoadIdentity();
                
                if (aFlagsAndObjectNum & MOVEFLAGS_MATRIX)
                {
                    aSuperAnimObject.mTransform.mMatrix.m00 = aBuffer.ReadLong() / LONG_TO_FLOAT;
                    aSuperAnimObject.mTransform.mMatrix.m01 = -aBuffer.ReadLong() / LONG_TO_FLOAT;
                    aSuperAnimObject.mTransform.mMatrix.m10 = -aBuffer.ReadLong() / LONG_TO_FLOAT;
                    aSuperAnimObject.mTransform.mMatrix.m11 = aBuffer.ReadLong() / LONG_TO_FLOAT;
                }
                else if (aFlagsAndObjectNum & MOVEFLAGS_ROTATE)
                {
                    float aRot = aBuffer.ReadShort() / 1000.0f;
                    float sinRot = sinf(aRot);
                    float cosRot = cosf(aRot);
                    aSuperAnimObject.mTransform.mMatrix.m00 = cosRot;
                    aSuperAnimObject.mTransform.mMatrix.m01 = sinRot;
                    aSuperAnimObject.mTransform.mMatrix.m10 = -sinRot;
                    aSuperAnimObject.mTransform.mMatrix.m11 = cosRot;
                }
                
                SuperAnimMatrix3 aMatrix;
                aMatrix.LoadIdentity();
                if (aFlagsAndObjectNum & MOVEFLAGS_LONGCOORDS)
                {
                    aMatrix.m02 = aBuffer.ReadLong() / TWIPS_PER_PIXEL;
                    aMatrix.m12 = aBuffer.ReadLong() / TWIPS_PER_PIXEL;
                }
                else
                {
                    aMatrix.m02 = aBuffer.ReadShort() / TWIPS_PER_PIXEL;
                    aMatrix.m12 = aBuffer.ReadShort() / TWIPS_PER_PIXEL;
                }
                aSuperAnimObject.mTransform.mMatrix = aMatrix * aSuperAnimObject.mTransform.mMatrix;
                
                if (aFlagsAndObjectNum & MOVEFLAGS_COLOR)
                {
                    aSuperAnimObject.mColor.mRed = aBuffer.ReadByte();
                    aSuperAnimObject.mColor.mGreen = aBuffer.ReadByte();
                    aSuperAnimObject.mColor.mBlue = aBuffer.ReadByte();
                    aSuperAnimObject.mColor.mAlpha = aBuffer.ReadByte();
                }
            }
        }
        
        if (aFrameFlags & FRAMEFLAGS_FRAME_NAME)
        {
            std::string aFrameName = aBuffer.ReadString();
            SuperAnimLabel aLabel;
            aLabel.mLabelName = aFrameName;
            aLabel.mStartFrameNum = aFrameNum;
            //aMainDef.mLabels.insert(StringToIntMap::value_type(aFrameName, aFrameNum));
            aSuperAnimLabelArray.push_back(aLabel);
        }
        
        aFrame.mObjectVector.resize(aCurObjectMap.size());
        aFrame.mObjectVector.clear();
        for (IntToSuperAnimObjectMap::iterator anIt = aCurObjectMap.begin(); anIt != aCurObjectMap.end(); ++anIt)
        {
            SuperAnimObject &anObject = anIt->second;
            aFrame.mObjectVector.push_back(anObject);
        }

    }
    
    // sort the label array & calculate the end frame for each label
    std::sort(aSuperAnimLabelArray.begin(), aSuperAnimLabelArray.end(), SuperAnimLabelLess);
    if (aSuperAnimLabelArray.size() > 1) {
        for (int i = 0; i < aSuperAnimLabelArray.size() - 1; i++) {
            SuperAnimLabel& aCurLabel = aSuperAnimLabelArray[i];
            const SuperAnimLabel& aNextLabel = aSuperAnimLabelArray[i + 1];
            aCurLabel.mEndFrameNum = aNextLabel.mStartFrameNum - 1;
        }
        SuperAnimLabel& aLastLabel = aSuperAnimLabelArray[aSuperAnimLabelArray.size() - 1];
        aLastLabel.mEndFrameNum = aMainDef.mEndFrameNum;
    } else {
        // only have one section
        SuperAnimLabel& aLabel = aSuperAnimLabelArray[0];
        aLabel.mEndFrameNum = aMainDef.mEndFrameNum;
    }
    aMainDef.mLabels.clear();
    for (int i = 0; i < aSuperAnimLabelArray.size(); i++) {
        aMainDef.mLabels.push_back(aSuperAnimLabelArray[i]);
    }
    
    return true;
}