コード例 #1
0
ファイル: CMemoryStream.cpp プロジェクト: bmer/Alchemy
ALERROR CMemoryReadStream::Read (char *pData, int iLength, int *retiBytesRead)

//	Read

	{
	ASSERT(m_iPos >= 0);	//	This happens if we don't Open the stream first
	ASSERT(iLength >= 0);

	ALERROR error = NOERROR;

	//	If we don't have enough data left, read out what we can

	if (m_iPos + iLength > m_iDataSize)
		{
		iLength = m_iDataSize - m_iPos;
		error = ERR_ENDOFFILE;
		}

	//	Copy the stuff over

	if (pData)
		utlMemCopy(m_pData + m_iPos, pData, iLength);
	m_iPos += iLength;
	if (retiBytesRead)
		*retiBytesRead = iLength;

	return error;
	}
コード例 #2
0
ファイル: CIntArray.cpp プロジェクト: Sdw195/Transcendence
CIntArray &CIntArray::operator= (const CIntArray &Obj)

//	CIntArray operator=

	{
	if (m_pData)
		MemFree(m_pData);

	if (Obj.m_pData)
		{
		m_iAllocSize = Obj.m_iAllocSize;
		m_iLength = Obj.m_iLength;
		m_pData = (int *)::MemAlloc(sizeof(int) * (Obj.m_iAllocSize));
		
		utlMemCopy((char *)Obj.m_pData, (char *)m_pData, sizeof(int) * m_iLength);
		}
	else
		{
		m_iAllocSize = 0;
		m_iLength = 0;
		m_pData = NULL;
		}

	return *this;
	}
コード例 #3
0
ファイル: CDataFile.cpp プロジェクト: Sdw195/Transcendence
ALERROR CDataFile::ReadBuffer (DWORD dwFilePos, DWORD dwLen, void *pBuffer)

//	ReadBuffer
//
//	This is an internal function that reads from the database to a buffer

	{
	if (m_pFile)
		{
		if (dwFilePos + dwLen > (DWORD)m_pFile->GetLength())
			return ERR_FAIL;

		char *pPos = m_pFile->GetPointer(dwFilePos, dwLen);
		utlMemCopy(pPos, (char *)pBuffer, dwLen);
		}
	else if (m_hFile != INVALID_HANDLE_VALUE)
		{
		//	Set the proper position

		if (::SetFilePointer(m_hFile, dwFilePos, NULL, FILE_BEGIN) == 0xFFFFFFFF)
			return ERR_FAIL;

		//	Read

		DWORD dwRead;
		if (!::ReadFile(m_hFile, pBuffer, dwLen, &dwRead, NULL) || dwRead != dwLen)
			return ERR_FAIL;
		}
	else
		ASSERT(false);

	return NOERROR;
	}
コード例 #4
0
ファイル: CAeonRowValue.cpp プロジェクト: gmoromisato/Hexarc
void CAeonRowValue::SetValue (CDatum dValue)

//	SetValue
//
//	Sets the value of a 0D row

	{
	CMemoryBuffer Buffer(4096);
	dValue.Serialize(CDatum::formatAEONScript, Buffer);

	//	Allocate a new block

	DWORD dwSizeUp = AlignUp(Buffer.GetLength(), (int)sizeof(DWORD));
	DWORD dwNewFixedBlockAlloc = sizeof(SItemHeader) + sizeof(SItemHeader) + dwSizeUp;
	void *pNewFixedBlock = new char [dwNewFixedBlockAlloc];

	//	Init

	SItemHeader *pHeader = (SItemHeader *)pNewFixedBlock;
	pHeader->dwSize = sizeof(SItemHeader) + dwSizeUp;

	SItemHeader *pItem = (SItemHeader *)&pHeader[1];
	pItem->dwSize = Buffer.GetLength();

	utlMemCopy(Buffer.GetPointer(), &pItem[1], Buffer.GetLength());

	//	Replace

	if (m_pFixedBlock && m_dwFixedBlockAlloc)
		delete m_pFixedBlock;
	m_pFixedBlock = pNewFixedBlock;
	m_dwFixedBlockAlloc = dwNewFixedBlockAlloc;
	}
コード例 #5
0
ファイル: CComplexBinary.cpp プロジェクト: kronosaur/Hexarc
void CComplexBinary::Append (CDatum dDatum)

//	Append
//
//	Appends data

	{
	const CString &sNewData = dDatum;
	if (sNewData.GetLength() == 0)
		return;

	//	Compute the new length

	int iOldLen = GetLength();
	int iNewLen = iOldLen + sNewData.GetLength();

	//	Allocate a new buffer

	char *pNewBuffer = new char [sizeof(DWORD) + iNewLen + 1];
	char *pPos = pNewBuffer;
	*(DWORD *)pPos = iNewLen;
	pPos += sizeof(DWORD);

	//	Copy the original data

	if (iOldLen)
		{
		utlMemCopy(m_pData, pPos, iOldLen);
		pPos += iOldLen;
		}

	//	Copy the new data

	utlMemCopy(sNewData.GetParsePointer(), pPos, sNewData.GetLength());
	pPos += sNewData.GetLength();

	//	NULL-terminator

	*pPos++ = '\0';

	//	Free our original buffer and swap

	if (m_pData)
		delete [] GetBuffer();

	m_pData = pNewBuffer + sizeof(DWORD);
	}
コード例 #6
0
ファイル: CBufferedIO.cpp プロジェクト: gmoromisato/Hexarc
int CBufferedIO::Read (void *pData, int iLength)

//	Read
//
//	Reads

	{
	char *pDest = (char *)pData;
	int iDestLeft = iLength;

	while (iDestLeft > 0)
		{
		//	If we have data in our buffer, read data from there.

		if (m_bReadBuffer && m_iBufferPos < m_iBufferLen)
			{
			int iWrite = Min(iDestLeft, m_iBufferLen - m_iBufferPos);
			utlMemCopy(m_pBuffer + m_iBufferPos, pDest, iWrite);

			m_iBufferPos += iWrite;
			pDest += iWrite;
			iDestLeft -= iWrite;
			}

		//	Otherwise, we need to read from the source stream

		else
			{
			Flush();

			//	Read as much as we can.

			m_iBufferStart = m_Stream.GetPos();
            m_iBufferLen = Min(m_iBufferAlloc, m_Stream.GetStreamLength() - m_iBufferStart);
            m_Stream.Read(m_pBuffer, m_iBufferLen);
			m_iBufferPos = 0;

			//	If we don't have more, then we're at the end of the stream.

			if (m_iBufferLen == 0)
				return (int)(pDest - (char *)pData);

			//	Otherwise, continue reading

            m_bReadBuffer = true;
			continue;
			}
		}

	//	Done

	return iLength;
	}
コード例 #7
0
ファイル: CWORM.cpp プロジェクト: Ttech/Transcendence
int CWORM::Write (void *pData, int iLength)

//	Write
//
//	Write to the WORM, returns bytes written

	{
	Commit((m_pPointer - m_pBlock) + iLength);

	utlMemCopy(pData, m_pPointer, iLength);
	m_pPointer += iLength;
	m_iCurrentSize = max(m_iCurrentSize, m_pPointer - m_pBlock);
	return iLength;
	}
コード例 #8
0
ファイル: CWORM.cpp プロジェクト: Ttech/Transcendence
int CWORM::Read (void *pData, int iLength)

//	Read
//
//	Read from the WORM, returns bytes read

	{
	int iLeft = m_iCurrentSize - (m_pPointer - m_pBlock);
	int iRead = min(iLeft, iLength);

	utlMemCopy(m_pPointer, pData, iRead);
	m_pPointer += iRead;
	return iRead;
	}
コード例 #9
0
ファイル: CBufferedIO.cpp プロジェクト: gmoromisato/Hexarc
int CBufferedIO::Write (void *pData, int iLength)

//	Write
//
//	Writes

	{
	char *pDest = (char *)pData;
	int iDestLeft = iLength;

    if (m_bReadBuffer)
        Flush();
	
	while (iDestLeft > 0)
		{
		//	If we can write to our buffer, do it.

		if (m_iBufferPos < m_iBufferAlloc)
			{
			int iWrite = Min(iDestLeft, m_iBufferAlloc - m_iBufferPos);
			utlMemCopy(pDest, m_pBuffer + m_iBufferPos, iWrite);

			m_iBufferPos += iWrite;
			pDest += iWrite;
			iDestLeft -= iWrite;
			m_iBufferLen = Max(m_iBufferPos, m_iBufferLen);
			m_bWriteBuffer = true;
			}

		//	Otherwise, write out the buffer to the stream

		else
			{
			int iWritten = m_Stream.Write(m_pBuffer, m_iBufferAlloc);
			if (iWritten != m_iBufferAlloc)
				return (int)(pDest - (char *)pData);

			m_iBufferPos = 0;
			m_iBufferLen = 0;
            m_bWriteBuffer = false;
			continue;
			}
		}

	//	Done

	return iLength;
	}
コード例 #10
0
ファイル: CComplexBinary.cpp プロジェクト: kronosaur/Hexarc
IComplexDatum *CComplexBinary::Clone (void) const

//	Clone
//
//	Creates a clone

	{
	CComplexBinary *pDest = new CComplexBinary;
	if (m_pData)
		{
		int iAllocLen = sizeof(DWORD) + GetLength() + 1;
		pDest->m_pData = new char [iAllocLen];
		utlMemCopy(m_pData, pDest->m_pData, iAllocLen);
		}

	return pDest;
	}
コード例 #11
0
ファイル: CAeonRowValue.cpp プロジェクト: gmoromisato/Hexarc
void CAeonRowValue::Copy (const CAeonRowValue &Src)

//	Copy
//
//	Assumes that we are clean

	{
	if (Src.m_pFixedBlock)
		{
		m_dwFixedBlockAlloc = Src.m_dwFixedBlockAlloc;
		m_pFixedBlock = new char [m_dwFixedBlockAlloc];
		utlMemCopy(Src.m_pFixedBlock, m_pFixedBlock, GetFixedBlockSize());
		}
	else
		{
		m_pFixedBlock = NULL;
		m_dwFixedBlockAlloc = 0;
		}
	}
コード例 #12
0
ファイル: CDataFile.cpp プロジェクト: bmer/Alchemy
ALERROR CDataFile::ReadBuffer (DWORD dwFilePos, DWORD dwLen, void *pBuffer)

//	ReadBuffer
//
//	This is an internal function that reads from the database to a buffer

	{
	if (m_pFile)
		{
		if (dwFilePos + dwLen > (DWORD)m_pFile->GetLength())
			{
			::kernelDebugLogMessage("I/O Error [%s]: Not enough data in file.", m_sFilename);
			return ERR_FAIL;
			}

		char *pPos = m_pFile->GetPointer(dwFilePos, dwLen);
		utlMemCopy(pPos, (char *)pBuffer, dwLen);
		}
	else if (m_hFile != INVALID_HANDLE_VALUE)
		{
		//	Set the proper position

		if (::SetFilePointer(m_hFile, dwFilePos, NULL, FILE_BEGIN) == 0xFFFFFFFF)
			{
			::kernelDebugLogMessage("I/O Error [%s]: Cannot seek to %d.", m_sFilename, dwFilePos);
			return ERR_FAIL;
			}

		//	Read

		DWORD dwRead;
		if (!::ReadFile(m_hFile, pBuffer, dwLen, &dwRead, NULL) || dwRead != dwLen)
			{
			::kernelDebugLogMessage("I/O Error [%s]: Cannot read %d bytes at %d.", m_sFilename, dwLen, dwFilePos);
			return ERR_FAIL;
			}
		}
	else
		ASSERT(false);

	return NOERROR;
	}
コード例 #13
0
ファイル: CDataFile.cpp プロジェクト: bmer/Alchemy
ALERROR CDataFile::GrowEntryTable (int *retiEntry)

//	GrowEntryTable
//
//	Grows the entry table and returns the first newly allocated free entry

	{
	int iNewEntryTableCount = m_iEntryTableCount + ENTRY_TABLE_GRANULARITY;
	int iNewEntryTableSize = iNewEntryTableCount * sizeof(ENTRYSTRUCT);
	PENTRYSTRUCT pNewEntryTable;
	int i;

	pNewEntryTable = (PENTRYSTRUCT)MemAlloc(iNewEntryTableSize);
	if (pNewEntryTable == NULL)
		return ERR_MEMORY;

	//	Copy over the old table

	utlMemCopy((char *)m_pEntryTable, (char *)pNewEntryTable, (DWORD)m_iEntryTableCount * sizeof(ENTRYSTRUCT));

	//	Initialize the rest of the  table

	for (i = m_iEntryTableCount; i < iNewEntryTableCount; i++)
		pNewEntryTable[i].dwBlock = FREE_ENTRY;

	//	Set the next free entry

	if (retiEntry)
		*retiEntry = m_iEntryTableCount;

	//	Do the move

	MemFree(m_pEntryTable);
	m_pEntryTable = pNewEntryTable;
	m_iEntryTableCount = iNewEntryTableCount;
	m_fEntryTableModified = TRUE;

	return NOERROR;
	}
コード例 #14
0
ファイル: DIB.cpp プロジェクト: Sdw195/Transcendence
ALERROR ReadDIBInfo (IReadBlock *pBlock, HANDLE *rethDIB, int *retiBitsOffset, BITMAPINFOHEADER *retbi)

//	ReadDIBInfo
//
//	Reads the DIB info from a block of memory

	{
	int iLen = pBlock->GetLength();
	char *pPos = pBlock->GetPointer(0, iLen);
	char *pEnd = pPos + iLen;
	BITMAPFILEHEADER bf;
	BITMAPINFOHEADER bi;
	int iBitmapInfoOffset;

	//	Read in the type WORD

	if (pPos + sizeof(WORD) + sizeof(DWORD) > pEnd)	return ERR_FAIL;
	utlMemCopy(pPos, (char *)&bf.bfType, sizeof(WORD));
	pPos += sizeof(WORD);

	//	Read in the next three DWORDs

	utlMemCopy(pPos, (char *)&bf.bfSize, sizeof(DWORD) * 3);
	pPos += sizeof(DWORD) * 3;

	//	Do we have an RC HEADER?

	if (bf.bfType != BFT_BITMAP)
		{
		bf.bfOffBits = 0;
		pPos = pBlock->GetPointer(0, iLen);
		iBitmapInfoOffset = 0;
		}
	else
		iBitmapInfoOffset = sizeof(WORD) + 3 * sizeof(DWORD);

	//	Read the info header

	if (pPos + sizeof(bi) > pEnd) return ERR_FAIL;
	utlMemCopy(pPos, (char *)&bi, sizeof(bi));
	pPos += sizeof(bi);

	DWORD dwNumColors = dibNumColors(&bi);

	//	Check the nature of the info block and extract the field
	//	information accordingly. Convert to a BITMAPINFOHEADER,
	//	if necessary.

	int iSize = (int)bi.biSize;
	switch (iSize)
		{
		case sizeof(BITMAPINFOHEADER):
			break;

		case sizeof(BITMAPCOREHEADER):
			{
			BITMAPCOREHEADER bc = *(BITMAPCOREHEADER *)&bi;
			DWORD dwWidth = (DWORD)bc.bcWidth;
			DWORD dwHeight = (DWORD)bc.bcHeight;
			WORD wPlanes = bc.bcPlanes;
			WORD wBitCount = bc.bcBitCount;

			bi.biSize = sizeof(BITMAPINFOHEADER);
			bi.biWidth = dwWidth;
			bi.biHeight = dwHeight;
			bi.biPlanes = wPlanes;
			bi.biBitCount = wBitCount;
			bi.biCompression = BI_RGB;
			bi.biSizeImage = 0;
			bi.biXPelsPerMeter = 0;
			bi.biYPelsPerMeter = 0;
			bi.biClrUsed = dwNumColors;
			bi.biClrImportant = dwNumColors;

			pPos += (int)(sizeof BITMAPCOREHEADER) - (int)(sizeof BITMAPINFOHEADER);
			break;
			}

		//	Not a DIB!

		default:
			return ERR_FAIL;
		}

	//	Fill in some default values if they are zero

	if (bi.biSizeImage == 0)
		bi.biSizeImage = WIDTHBYTES((DWORD)bi.biWidth * bi.biBitCount) * bi.biHeight;

	if (bi.biClrUsed == 0)
        bi.biClrUsed = dwNumColors;

	//	Allocate memory for the BITMAPINFO struct and the color table

	HANDLE hbi = GlobalAlloc(GHND, (LONG)bi.biSize + dwNumColors * sizeof(RGBQUAD));
	if (!hbi)
		return ERR_MEMORY;

	LPBITMAPINFOHEADER lpbi = (BITMAPINFOHEADER *)GlobalLock(hbi);
	*lpbi = bi;

	//	Get the pointer to the color table

	RGBQUAD *pRGB = (RGBQUAD *)((char *)lpbi + bi.biSize);
	if (dwNumColors)
		{
		if (iSize == sizeof(BITMAPCOREHEADER))
			{
			//	Convert an old color table (3 byte RGBTRIPLEs) to a 
			//	new table (4 byte RGBQUADs)

			if (pPos + dwNumColors * sizeof(RGBTRIPLE) > pEnd) return ERR_FAIL;
			utlMemCopy(pPos, (char *)pRGB, dwNumColors * sizeof(RGBTRIPLE));
			pPos += dwNumColors * sizeof(RGBTRIPLE);

			for (int i = dwNumColors - 1; i >= 0; i--)
				{
				RGBQUAD rgb;

				rgb.rgbRed = ((RGBTRIPLE *)pRGB)[i].rgbtRed;
				rgb.rgbGreen = ((RGBTRIPLE *)pRGB)[i].rgbtGreen;
				rgb.rgbBlue = ((RGBTRIPLE *)pRGB)[i].rgbtBlue;
				rgb.rgbReserved = (BYTE)0;

				pRGB[i] = rgb;
				}
			}
		else
			{
			if (pPos + dwNumColors * sizeof(RGBQUAD) > pEnd) return ERR_FAIL;
			utlMemCopy(pPos, (char *)pRGB, dwNumColors * sizeof(RGBQUAD));
			pPos += dwNumColors * sizeof(RGBQUAD);
			}
		}

	//	Done

	if (bf.bfOffBits)
		*retiBitsOffset = bf.bfOffBits;
	else
		*retiBitsOffset = pPos - pBlock->GetPointer(0, 1);

	if (retbi)
		*retbi = bi;

	GlobalUnlock(hbi);
	*rethDIB = (HBITMAP)hbi;

	return NOERROR;
	}
コード例 #15
0
ファイル: CMemoryStream.cpp プロジェクト: bmer/Alchemy
ALERROR CMemoryWriteStream::Write (char *pData, int iLength, int *retiBytesWritten)

//	Write
//
//	Writes the given bytes to the file. If this call returns NOERROR, it is
//	guaranteed that the requested number of bytes were written.

	{
	//	Make sure we called Create

	ASSERT(m_pBlock);
	ASSERT(iLength >= 0);

	//	Commit the required space

	if (m_iCurrentSize + iLength > m_iCommittedSize)
		{
		int iAdditionalSize;

		//	Figure out how much to add

		iAdditionalSize = AlignUp(m_iCurrentSize + iLength, ALLOC_SIZE) - m_iCommittedSize;

		//	Figure out if we're over the limit. We cannot rely on VirtualAlloc
		//	to keep track of our maximum reservation

		if (m_iCommittedSize + iAdditionalSize > m_iMaxSize)
			{
			//	Allocate a new, bigger virtual block

			int iNewMaxSize = (m_iMaxSize < 0x3fff0000 ? m_iMaxSize * 2 : 0x7fff0000);
			char *pNewBlock = (char *)::VirtualAlloc(NULL, iNewMaxSize, MEM_RESERVE, PAGE_NOACCESS);
			if (pNewBlock == NULL)
				{
				::kernelDebugLogMessage("Out of Memory: VirtualAlloc failed reserving %d bytes.", iNewMaxSize);
				return ERR_MEMORY;
				}

			//	Commit and copy the new block

			if (m_iCommittedSize > 0)
				{
				if (::VirtualAlloc(pNewBlock, m_iCommittedSize, MEM_COMMIT, PAGE_READWRITE) == NULL)
					{
					::kernelDebugLogMessage("Out of Memory: VirtualAlloc failed committing %d bytes.", m_iCommittedSize);
					return ERR_MEMORY;
					}

				//	Copy over to the new block

				utlMemCopy(m_pBlock, pNewBlock, m_iCommittedSize);

				//	Free the old block

				::VirtualFree(m_pBlock, m_iCommittedSize, MEM_DECOMMIT);
				}

			//	Free original

			::VirtualFree(m_pBlock, 0, MEM_RELEASE);

			//	Flip over

			m_pBlock = pNewBlock;
			m_iMaxSize = iNewMaxSize;
			}

		//	Commit

		if (VirtualAlloc(m_pBlock + m_iCommittedSize,
				iAdditionalSize,
				MEM_COMMIT,
				PAGE_READWRITE) == NULL)
			{
			::kernelDebugLogMessage("Out of Memory: VirtualAlloc failed committing %d bytes.", m_iCommittedSize + iAdditionalSize);
			return ERR_MEMORY;
			}

		m_iCommittedSize += iAdditionalSize;
		}

	//	Copy the stuff over

	if (pData)
		utlMemCopy(pData, m_pBlock + m_iCurrentSize, iLength);

	m_iCurrentSize += iLength;
	if (retiBytesWritten)
		*retiBytesWritten = iLength;

	return NOERROR;
	}
コード例 #16
0
ファイル: CG8bitSparseImage.cpp プロジェクト: bmer/Alchemy
void CG8bitSparseImage::Copy (const CG8bitSparseImage &Src)

//	Copy
//
//	Copy

	{
	int i, j;

	switch (Src.m_Tiles.GetType())
		{
		case typeByte:
			m_Tiles.SetByte(Src.m_Tiles.GetByte());
			m_xTileCount = 0;
			m_yTileCount = 0;
			break;

		case typeNodeArray:
			{
			int iTileCount = Src.m_xTileCount * Src.m_yTileCount;
			CNode *SrcNodes = Src.m_Tiles.GetNodeArray();

			m_Tiles.SetNodeArray(iTileCount);
			CNode *DestNodes = m_Tiles.GetNodeArray();

			for (i = 0; i < iTileCount; i++)
				{
				switch (SrcNodes[i].GetType())
					{
					//	The entire tile is a single value.

					case typeByte:
						DestNodes[i].SetByte(SrcNodes[i].GetByte());
						break;

					//	The tile is an array of rows, each of which may be 
					//	either a BYTE array or a value.

					case typeNodeArray:
						{
						CNode *SrcRows = SrcNodes[i].GetNodeArray();

						DestNodes[i].SetNodeArray(Src.m_cyTile);
						CNode *DestRows = DestNodes[i].GetNodeArray();

						for (j = 0; j < Src.m_cyTile; j++)
							{
							switch (SrcRows[j].GetType())
								{
								case typeByte:
									DestRows[j].SetByte(SrcRows[j].GetByte());
									break;

								case typeByteArray:
									{
									DestRows[j].SetByteArray(m_cxTile);
									utlMemCopy((char *)DestRows[j].GetByteArray(), (char *)SrcRows[j].GetByteArray(), m_cxTile);
									break;
									}

								default:
									ASSERT(false);
								}
							}

						break;
						}

					default:
						ASSERT(false);
					}
				}

			m_xTileCount = Src.m_xTileCount;
			m_yTileCount = Src.m_yTileCount;
			break;
			}

		default:
			ASSERT(false);
		}

	m_cxTile = Src.m_cxTile;
	m_cyTile = Src.m_cyTile;

	m_cxWidth = Src.m_cxWidth;
	m_cyHeight = Src.m_cyHeight;
	m_rcClip = Src.m_rcClip;
	}
コード例 #17
0
void CFractureEffect::InitParticleArray (void)

//	InitParticleArray
//
//	Initializes the particle array based on cell size and the image

	{
	ASSERT(m_pParticles == NULL);
	ASSERT(m_iCellSize >= 1);

	//	Get the source image and metrics

	CG16bitImage &Source = m_Image.GetImage(NULL_STR);
	int xCenter, yCenter;
	RECT rcSource = m_Image.GetImageRect(m_iImageTick, m_iImageRotation, &xCenter, &yCenter);

	//	Allocate a structure for particles

	int iAlloc = ALLOC_GRANULARITY;
	m_pParticles = new SParticle [iAlloc];
	m_iParticleCount = 0;

	int y = rcSource.top;
	while (y + m_iCellSize <= rcSource.bottom)
		{
		int x = rcSource.left;
		while (x + m_iCellSize <= rcSource.right)
			{
			//	Initialize the entry

			if (true)
				{
				//	Add an entry to the array

				if (m_iParticleCount + 1 == iAlloc)
					{
					iAlloc += ALLOC_GRANULARITY;
					SParticle *pNewArray = new SParticle [iAlloc];
					utlMemCopy((char *)m_pParticles, (char *)pNewArray, sizeof(SParticle) * m_iParticleCount);
					delete [] m_pParticles;
					m_pParticles = pNewArray;
					}

				SParticle *pNewParticle = &m_pParticles[m_iParticleCount++];

				//	Initialize position

				pNewParticle->x = (x - xCenter) * FIXED_POINT;
				pNewParticle->y = (y - yCenter) * FIXED_POINT;

				//	Velocity of each particle is away from the center

				CVector vAway(pNewParticle->x, pNewParticle->y);
				vAway = vAway.Normal() * (Metric)mathRandom(0, FIXED_POINT * 4);
				pNewParticle->xV = (int)vAway.GetX();
				pNewParticle->yV = (int)vAway.GetY();

				//	Other

				pNewParticle->iTicks = 0;

				pNewParticle->xSrc = x;
				pNewParticle->ySrc = y;
				pNewParticle->iShape = 0;
				}

			x += m_iCellSize;
			}

		y += m_iCellSize;
		}
	}