Пример #1
0
string Decode(CSequence inSequence)
{
	string result;
	for (CSequence::iterator i = inSequence.begin(); i != inSequence.end(); ++i)
		result.push_back(Decode(*i));
	return result;
}
Пример #2
0
int CModel::AnimEnumInUse(LPCSTR psAnimEnum)
{
	int iCount = 0;
	if (strlen(psAnimEnum))	// added for G2 models, which don't necessarily use enums yet
	{		
		CSequence *curSequence = GetFirstSequence();

		while (curSequence)
		{
			if (!strcmp(psAnimEnum,curSequence->GetEnum()))
			{
				iCount++;// return true;
			}

			// new bit, ask the additional sequences as well...
			//
			for (int i=0; i<MAX_ADDITIONAL_SEQUENCES; i++)
			{
				if (!strcmp(psAnimEnum,curSequence->AdditionalSeqs[i]->GetEnum()))
				{
					iCount++;// return true;
				}
			}

			curSequence = curSequence->GetNext();
		}
	}
	return iCount;//false;
}
Пример #3
0
void CModel::ReOrderSequences()
{
	typedef vector<CSequence*> sequences_t; sequences_t sequences;

	// add sequences to list...

	CSequence *curSequence = m_sequences;
	while (curSequence)
	{
		sequences.push_back(curSequence);
		curSequence = curSequence->GetNext();
	}

	// re-order sequences...

	qsort( (void *)&sequences[0], (size_t)(sequences.size()), sizeof(CSequence *), ModelSequenceCompareFunc );

	// now rebuild links...

	int iTotMasterSequences = GetTotMasterSequences();	// this needs to be eval'd here, you can't do it in the for-next below
	m_sequences = NULL;
	for (int i=0; i<iTotMasterSequences; i++)
	{
		curSequence = sequences[i];
		curSequence->SetNext(NULL);

		AddSequence(curSequence);
	}

	Resequence();
}
Пример #4
0
void CInstrumentEditorN163::OnCloneSequence()
{
	CFamiTrackerDoc *pDoc = GetDocument();
	int FreeIndex = pDoc->GetFreeSequenceN163(m_iSelectedSetting);
	CSequence *pSeq = pDoc->GetSequence(SNDCHIP_N163, FreeIndex, m_iSelectedSetting);
	pSeq->Copy(m_pSequence);
	SetDlgItemInt(IDC_SEQ_INDEX, FreeIndex, FALSE);
}
Пример #5
0
int CModel::GetTotMasterSequences()
{
	int tot = 0;
	CSequence* curSequence = m_sequences;
	while(curSequence != NULL)
	{
		tot++;
		curSequence = curSequence->GetNext();
	}
	return tot;
}
Пример #6
0
CSequence *CSequence::Create( void )
{
	CSequence *seq = new CSequence;

	//TODO: Emit warning
	assert(seq);
	if ( seq == NULL )
		return NULL;

	seq->SetFlag( SQ_COMMON );

	return seq;
}
Пример #7
0
void CModel::GetMasterEnumBoundaryFrameNumbers(int *piFirstFrameAfterBOTH, int *piFirstFrameAfterTORSO)
{
	ENUMTYPE prevET = ET_INVALID;
	int iFirstFrameAfterBOTH = 0;
	int iFirstFrameAfterTORSO= 0;	
	
	CSequence* curSequence = m_sequences;
	while(curSequence != NULL)
	{
		ENUMTYPE thisET = curSequence->GetEnumType();

		// update any frame markers first...

		if (prevET == ET_BOTH && thisET != ET_BOTH)
		{
			iFirstFrameAfterBOTH = curSequence->GetTargetFrame();
			iFirstFrameAfterTORSO= curSequence->GetTargetFrame();	// set this as well in case there are no TORSOs at all
		}

		if (prevET == ET_TORSO && thisET != ET_TORSO)
		{
			iFirstFrameAfterTORSO= curSequence->GetTargetFrame();	
		}

		prevET = thisET;

		curSequence = curSequence->GetNext();
	}
	// bug fix, if there are no leg frames at all, then we need to check if the ...AfterTORSO marker needs moving...

	if (prevET == ET_BOTH)
	{
		iFirstFrameAfterBOTH = GetTotFrames();
		iFirstFrameAfterTORSO= GetTotFrames();
	}
	if (prevET == ET_TORSO)
	{		
		iFirstFrameAfterTORSO = GetTotFrames();
	}

	if (piFirstFrameAfterBOTH)
	{
		*piFirstFrameAfterBOTH = iFirstFrameAfterBOTH;
	}

	if (piFirstFrameAfterTORSO)
	{
		*piFirstFrameAfterTORSO= iFirstFrameAfterTORSO;
	}
}
Пример #8
0
LPCSTR CModel::GLAName(void)
{
	CSequence* curSequence = GetFirstSequence();
	while (curSequence)
	{
		if (curSequence->IsGLA())
		{
			return curSequence->GetName();
		}
		curSequence = curSequence->GetNext();
	}

	return NULL;
}
Пример #9
0
bool CModel::HasGLA()
{
	CSequence* curSequence = GetFirstSequence();
	while (curSequence)
	{
		if (curSequence->IsGLA())
		{
			return true;
		}
		curSequence = curSequence->GetNext();
	}

	return false;
}
Пример #10
0
void CModel::AddSequence(CSequence* sequence)
{
	if (m_sequences == NULL)
	{
		m_sequences = sequence;
	}
	else
	{
		CSequence* curSequence = m_sequences;
		while(curSequence->GetNext() != NULL)
		{
			curSequence = curSequence->GetNext();
		}
		curSequence->SetNext(sequence);
	}
}
Пример #11
0
int main()
{
	CSequence seq;

	if (seq.ReadSequence("test5.txt"))
	{
		seq.CalculationSequence();
		cout << seq.GetCount() << endl;
	}
	else
	{
		cout << "error input file";
	}
	cout << "runtime = " << clock() / 1000.0 << endl;
	return 0;
}
Пример #12
0
void CModel::Delete()
{
	while(m_comments != NULL)
	{
		CComment* curComment = m_comments;
		m_comments = curComment->GetNext();
		curComment->Delete();
	}
	while(m_sequences != NULL)
	{
		CSequence* curSequence = m_sequences;
		m_sequences = curSequence->GetNext();
		curSequence->Delete();
	}
	if (m_name != NULL)
	{
		free(m_name);
		m_name = NULL;
	}
	if (m_path != NULL)
	{
		free(m_path);
		m_path = NULL;
	}
	if (m_psSkelPath != NULL)
	{
		free(m_psSkelPath);
		m_psSkelPath = NULL;
	}
	if (m_psMakeSkelPath != NULL)
	{
		free(m_psMakeSkelPath);
		m_psMakeSkelPath = NULL;
	}
	if (m_psRefGLAPath != NULL)
	{
		free(m_psRefGLAPath);
		m_psRefGLAPath = NULL;
	}
	m_curSequence = NULL;

	PCJList_Clear();	// not really necessary, but useful reminder

	delete this;
}
Пример #13
0
void CModel::DeleteSequence(CSequence* deleteSequence)
{
	// linklist is only 1-way, so we need to find the stage previous to this (if any)...

	CSequence* prevSequence = NULL;
	CSequence* scanSequence = GetFirstSequence();

	while (scanSequence && scanSequence != deleteSequence)
	{
		prevSequence = scanSequence;
		scanSequence = scanSequence->GetNext();
	}
	if (scanSequence == deleteSequence)
	{
		// we found it, so was this the first sequence in the list?

		if (prevSequence)
		{
			prevSequence->SetNext(scanSequence->GetNext());	// ...no
		}
		else
		{
			m_sequences = scanSequence->GetNext();			// ...yes
		}
		scanSequence->Delete();
	}
}
Пример #14
0
int CModel::GetTotSequences()
{
	int tot = 0;
	CSequence* curSequence = m_sequences;
	while(curSequence != NULL)
	{
		tot++;

		for (int i=0; i<MAX_ADDITIONAL_SEQUENCES; i++)
		{
			if (curSequence->AdditionalSeqs[i]->AdditionalSequenceIsValid())
				tot++;
		}

		curSequence = curSequence->GetNext();
	}
	return tot;
}
Пример #15
0
bool CModel::ContainsFile(LPCSTR psFilename)
{	
	if (m_sequences == NULL)
	{
		return false;
	}
	else
	{
		CSequence* curSequence = m_sequences;
		while(curSequence)
		{
			if (_stricmp(curSequence->GetPath(),psFilename)==0)
				return true;
			curSequence = curSequence->GetNext();
		}		
	}

	return false;
}
Пример #16
0
void PrintAlignment(
	const CSequence& inQuery, uint32 inQueryStart,
	const CSequence& inTarget, uint32 inTargetStart)
{
	assert(inQuery.length() == inTarget.length());
	
	CMutableSequence q(inQuery.begin(), inQuery.end());
	CMutableSequence s(inTarget.begin(), inTarget.end());
	
	while (q.length())
	{
		uint32 n = q.length();
		if (n > 60)
			n = 60;
		
		cout << setw(6) << inQueryStart << " ";
		for (uint32 i = 0; i < n; ++i)
		{
			if (q[i] == '-')
				cout << '-';
			else
			{
				cout << Decode(q[i]);
				++inQueryStart;
			}
		}
		cout << endl;

		cout << "       ";
		for (uint32 i = 0; i < n; ++i)
		{
			if (s[i] == q[i])
				cout << '|';
			else
				cout << " ";
		}
		cout << endl;

		cout << setw(6) << inTargetStart << " ";
		for (uint32 i = 0; i < n; ++i)
		{
			if (s[i] == '-')
				cout << '-';
			else
			{
				cout << Decode(s[i]);
				++inTargetStart;
			}
		}
		cout << endl << endl;
		
		q.erase(q.begin(), q.begin() + n);
		s.erase(s.begin(), s.begin() + n);
	}
	cout << endl;
}
Пример #17
0
void CInstrumentN163::SaveFile(CFile *pFile, CFamiTrackerDoc *pDoc)
{
	// Sequences
	unsigned char SeqCount = SEQUENCE_COUNT;
	pFile->Write(&SeqCount, sizeof(char));

	for (int i = 0; i < SEQUENCE_COUNT; ++i) {
		int Sequence = GetSeqIndex(i);

		if (GetSeqEnable(i)) {
			CSequence *pSeq = pDoc->GetSequence(SNDCHIP_N163, Sequence, i);
			char Enabled = 1;
			int ItemCount = pSeq->GetItemCount();
			int LoopPoint = pSeq->GetLoopPoint();
			int ReleasePoint = pSeq->GetReleasePoint();
			int Setting = pSeq->GetSetting();
			pFile->Write(&Enabled, sizeof(char));
			pFile->Write(&ItemCount, sizeof(int));
			pFile->Write(&LoopPoint, sizeof(int));
			pFile->Write(&ReleasePoint, sizeof(int));
			pFile->Write(&Setting, sizeof(int));
			for (unsigned int j = 0; j < pSeq->GetItemCount(); j++) {
				int Value = pSeq->GetItem(j);
				pFile->Write(&Value, sizeof(char));
			}
		}
		else {
			char Enabled = 0;
			pFile->Write(&Enabled, sizeof(char));
		}
	}

	// Write wave config
	int WaveSize = GetWaveSize();
	pFile->Write(&WaveSize, sizeof(int));
	int WavePos = GetWavePos();
	pFile->Write(&WavePos, sizeof(int));
	int WaveCount = GetWaveCount();
	pFile->Write(&WaveCount, sizeof(int));

	for (int i = 0; i < WaveCount; ++i) {
		for (int j = 0; j < WaveSize; ++j) {
			char w = GetSample(i, j);
			pFile->Write(&w, sizeof(char));
		}
	}
}
Пример #18
0
CSequence* CSequence::CreateFromFile(LPCTSTR path, CComment* comments)
{
	CSequence* retval = new CSequence();
	CString name = path;
	name.Replace('\\', '/');
	name.MakeLower();
	retval->_Init(false,!!(strstr(path,".gla")),name, 0, 0, 0, iDEFAULTSEQFRAMESPEED,iDEFAULTSEQFRAMESPEED,comments);	// (noticed) this fills in certain fields wrongly until the next 2 lines correct them
	retval->DeriveName();
	retval->ReadHeader();
	//
	// at this point the m_path member is wrong because it contains the full path including "\quake\...", so...
	//
	CString newPath = retval->GetPath();	
	Filename_RemoveBASEQ(newPath);
	retval->SetPath(newPath);	
	return retval;
}
Пример #19
0
void MidLine(const CSequence& inQuery, const CSequence& inTarget,
	const CMatrix& inMatrix, uint32& outIdentity, uint32& outPositives,
	uint32& outGaps, string& outMidline)
{
	outMidline.clear();
	outIdentity = 0;
	outPositives = 0;
	outGaps = 0;
	
	assert(inQuery.length() == inTarget.length());
	if (inQuery.length() != inTarget.length())
		THROW(("To calculate a midline you need a query and a target of the same length"));

	for (CSequence::const_iterator a = inQuery.begin(), b = inTarget.begin();
		a != inQuery.end(); ++a, ++b)
	{
		if (*a == *b)
		{
			++outIdentity;
			++outPositives;
			outMidline += Decode(*a);
		}
		else if (inMatrix(*a, *b) > 0)
		{
			++outPositives;
			outMidline += '+';
		}
		else
		{
			if (*a == kSignalGapCode or *b == kSignalGapCode)
				++outGaps;
				
			outMidline += ' ';
		}
	}	
}
Пример #20
0
void CInstrument2A03::SaveFile(CFile *pFile, CFamiTrackerDoc *pDoc)
{
	// Saves an 2A03 instrument
	// Current version 2.2

	// Sequences
	unsigned char SeqCount = SEQUENCE_COUNT;
	pFile->Write(&SeqCount, sizeof(char));

	for (int i = 0; i < SEQUENCE_COUNT; ++i) {
		int Sequence = GetSeqIndex(i);

		if (GetSeqEnable(i)) {
			CSequence *pSeq = pDoc->GetSequence(Sequence, i);
			char Enabled = 1;
			int ItemCount = pSeq->GetItemCount();
			int LoopPoint = pSeq->GetLoopPoint();
			int ReleasePoint = pSeq->GetReleasePoint();
			int Setting = pSeq->GetSetting();
			pFile->Write(&Enabled, sizeof(char));
			pFile->Write(&ItemCount, sizeof(int));
			pFile->Write(&LoopPoint, sizeof(int));
			pFile->Write(&ReleasePoint, sizeof(int));
			pFile->Write(&Setting, sizeof(int));
			for (unsigned int j = 0; j < pSeq->GetItemCount(); j++) {
				int Value = pSeq->GetItem(j);
				pFile->Write(&Value, sizeof(char));
			}
		}
		else {
			char Enabled = 0;
			pFile->Write(&Enabled, sizeof(char));
		}
	}

	unsigned int Count = 0;

	// Count assigned keys
	for (int i = 0; i < 6; i++) {	// octaves
		for (int j = 0; j < 12; j++) {	// notes
			if (GetSample(i, j) > 0)
				Count++;
		}
	}

	pFile->Write(&Count, sizeof(int));

	bool UsedSamples[MAX_DSAMPLES];
	memset(UsedSamples, 0, sizeof(bool) * MAX_DSAMPLES);

	// DPCM
	for (int i = 0; i < 6; ++i) {	// octaves
		for (int j = 0; j < 12; ++j) {	// notes
			if (GetSample(i, j) > 0) {
				unsigned char Index = i * 12 + j, Sample, Pitch;
				pFile->Write(&Index, sizeof(char));
				Sample = GetSample(i, j);
				Pitch = GetSamplePitch(i, j);
				pFile->Write(&Sample, sizeof(char));
				pFile->Write(&Pitch, sizeof(char));
				UsedSamples[GetSample(i, j) - 1] = true;
			}
		}
	}

	int SampleCount = 0;

	// Count samples
	for (int i = 0; i < MAX_DSAMPLES; ++i) {
		if (pDoc->GetSampleSize(i) > 0 && UsedSamples[i])
			SampleCount++;
	}

	// Write the number
	pFile->Write(&SampleCount, sizeof(int));

	// List of sample names, the samples itself won't be stored
	for (int i = 0; i < MAX_DSAMPLES; ++i) {
		if (pDoc->GetSampleSize(i) > 0 && UsedSamples[i]) {
			CDSample *pSample = pDoc->GetDSample(i);
			int Len = (int)strlen(pSample->Name);
			pFile->Write(&i, sizeof(int));
			pFile->Write(&Len, sizeof(int));
			pFile->Write(pSample->Name, Len);
			pFile->Write(&pSample->SampleSize, sizeof(int));
			pFile->Write(pSample->SampleData, pSample->SampleSize);
		}
	}
}
Пример #21
0
bool CInstrumentN163::LoadFile(CFile *pFile, int iVersion, CFamiTrackerDoc *pDoc)
{
	// Sequences
	unsigned char SeqCount;
	pFile->Read(&SeqCount, sizeof(char));

	// Loop through all instrument effects
	for (unsigned int i = 0; i < SeqCount; ++i) {

		unsigned char Enabled;
		pFile->Read(&Enabled, sizeof(char));

		if (Enabled == 1) {
			// Read the sequence
			int Count;
			pFile->Read(&Count, sizeof(int));

			if (Count < 0 || Count > MAX_SEQUENCE_ITEMS)
				return false;

			// Find a free sequence
			int Index = pDoc->GetFreeSequenceN163(i);
			CSequence *pSeq = pDoc->GetSequenceN163(Index, i);

			pSeq->SetItemCount(Count);
			int LoopPoint;
			int Setting;
			pFile->Read(&LoopPoint, sizeof(int));
			pSeq->SetLoopPoint(LoopPoint);
			int ReleasePoint;
			pFile->Read(&ReleasePoint, sizeof(int));
			pSeq->SetReleasePoint(ReleasePoint);
			pFile->Read(&Setting, sizeof(int));
			pSeq->SetSetting(Setting);

			for (int j = 0; j < Count; ++j) {
				char Val;
				pFile->Read(&Val, sizeof(char));
				pSeq->SetItem(j, Val);
			}
			SetSeqEnable(i, true);
			SetSeqIndex(i, Index);
		}
		else {
			SetSeqEnable(i, false);
			SetSeqIndex(i, 0);
		}
	}

	// Read wave config
	int WaveSize, WavePos, WaveCount;
	pFile->Read(&WaveSize, sizeof(int));
	pFile->Read(&WavePos, sizeof(int));
	pFile->Read(&WaveCount, sizeof(int));

	if (WaveSize <= 0 || WaveSize > 32)
		return false;
	if (WaveCount <= 0 || WaveCount > MAX_WAVE_COUNT)
		return false;

	SetWaveSize(WaveSize);
	SetWavePos(WavePos);
	SetWaveCount(WaveCount);

	for (int i = 0; i < WaveCount; ++i) {
		for (int j = 0; j < WaveSize; ++j) {
			char w;
			pFile->Read(&w, sizeof(char));
			SetSample(i, j, w);
		}
	}

	return true;
}
Пример #22
0
CSequence* CSequence::_Create(bool bGenLoopFrame, bool bIsGLA, LPCTSTR path, int startFrame, int targetFrame, int frameCount, int frameSpeed, int frameSpeedFromHeader, CComment* comments)
{
	CSequence* retval = new CSequence();
	retval->_Init(bGenLoopFrame, bIsGLA, path, startFrame, targetFrame, frameCount, frameSpeed, frameSpeedFromHeader, comments);
	return retval;
}
Пример #23
0
// this writes the CFG file... (it's also now recursive, albeit with changing 'this' ptrs, so be aware of that)
//
void CSequence::WriteExternal(CModel *pModel, CTxtFile* file, bool bMultiPlayerFormat)
{
	// this now keeps the spacing nicer for cutting and pasting into source...
	//
	CString sOutputEnum = m_enum;
	if (sOutputEnum.IsEmpty())
	{
		sOutputEnum = "???";
	}

	if (bMultiPlayerFormat)
	{
		// Format:  targetFrame, frameCount, loopFrame, frameSpeed
		//0	47	0	10	//BOTH_DEATH1

		file->Write(m_targetFrame);
		file->Write("\t");
		file->Write(m_frameCount);
		file->Write("\t");
		if (m_loopFrame == -1)		
			file->Write(0);
		else
			file->Write(m_frameCount-m_loopFrame);
		file->Write("\t");
		file->Write(m_frameSpeed);
		file->Write("\t");

		if (!m_validEnum)
		{
			file->Write("// fix me - invalid enum -");
		}
		else
		{
			file->Write("//");
			file->Write(sOutputEnum);
			file->Writeln();
		}
	}
	else
	{
		while(sOutputEnum.GetLength()<20) sOutputEnum+=" ";

		file->Write(sOutputEnum, "\t");	

	//	file->Write(m_startFrame);
	//	file->Write("\t");

		// special code, if this is a LEGS type enum then we need to adjust the target frame to 'lose' the chunk
		//	of frames occupied by the TORSO types...
		//
		int iTargetFrame = m_targetFrame;
		file->Write(iTargetFrame);
		file->Write("\t");
		file->Write(m_frameCount);
		file->Write("\t");
		file->Write(m_loopFrame);
		file->Write("\t");
		file->Write(m_frameSpeed);
		if (!m_validEnum && !pModel->IsGhoul2())
		{
			file->Write("\t// fix me - invalid enum -");
		}
		if (m_sound != NULL)
		{
			file->Write("\t// sound - ");
		}
		if (m_action != NULL)
		{
			file->Write ("\t// action - ");
		}
		if (m_fill > -1)
		{
			file->Write("\t// fill = ");
			file->Write(m_fill);
		}
		file->Writeln();
	}

	// now for a bit of recursion, write out any additional sequences that this sequence owns...
	//
	for (int i=0; i<MAX_ADDITIONAL_SEQUENCES; i++)
	{
		CSequence *seq = AdditionalSeqs[i];
		if (seq)
		{
			if (seq->AdditionalSequenceIsValid())
			{
				seq->WriteExternal(pModel, file, bMultiPlayerFormat);
			}
		}
	}
}
Пример #24
0
void CSequence::Write(CTxtFile* file, bool bPreQuat)
{
	CComment* curComment = m_comments;
	while(curComment != NULL)
	{
		curComment->Write(file);
		curComment = curComment->GetNext();
	}

	file->Write("$", CAssimilateDoc::GetKeyword(IsGLA()?TK_AS_GRAB_GLA:TK_AS_GRAB, TABLE_QDT), " ");
	CString path = m_path;
	int loc = path.Find("/base");
	if (loc > -1)
	{
		path = path.Right(path.GetLength() - loc - 5);
		loc = path.Find("/");
		path = path.Right(path.GetLength() - loc - 1);
	}
	if (!path.GetLength())	// check that some dopey artist hasn't use the name "base" on the right hand side
	{
		path = m_path;
	}

	Filename_AccountForLOD(path, giLODLevelOverride);
	file->Write(path);	
/*
	if (m_frameCount > -1)
	{
		file->Space();
		file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_FRAMES, TABLE_GRAB), " ");
		file->Write(m_startFrame);
		file->Space();
		file->Write(m_targetFrame);
		file->Space();
		file->Write(m_frameCount);
	}
*/

//	if (strstr(path,"death16"))
//	{
//		int z=1;
//	}

	if (!IsGLA())
	{
		if (m_fill > -1)
		{
			file->Space();
			file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_FILL, TABLE_GRAB), " ");
	//		file->Space();
			file->Write(m_fill);
		}
		if (m_loopFrame != 0)
		{
			file->Space();
			file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_LOOP, TABLE_GRAB), " ");
	//		file->Space();
			file->Write(m_loopFrame);
		}
	//	if (m_enum && (strcmp(m_name, m_enum) != 0))
		if (m_enum.GetLength() && (strcmp(m_name, m_enum) != 0))
		{
			file->Space();
			file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_ENUM, TABLE_GRAB), " ");
	//		file->Space();
			file->Write(m_enum);
		}
		if (m_sound != NULL)
		{
			file->Space();
			file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_SOUND, TABLE_GRAB), " ");
	//		file->Space();
			file->Write(m_sound);
		}
		if (m_action != NULL)
		{
			file->Space();
			file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_ACTION, TABLE_GRAB), " ");
	//		file->Space();
			file->Write(m_action);
		}	

		if (m_bGenLoopFrame)
		{
			file->Space();
			file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_GENLOOPFRAME, TABLE_GRAB), " ");
		}

		if (m_frameSpeed != m_iFrameSpeedFromHeader ||
			GetValidAdditionalSequences() ||
			bPreQuat
			)
		{
			// write out start marker (and stop-marker at bottom) so qdata can skip this more easily...
			//
			file->Space();
			file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_QDSKIPSTART, TABLE_GRAB));
			
			if (m_frameSpeed != m_iFrameSpeedFromHeader)
			{
				file->Space();
				file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_FRAMESPEED, TABLE_GRAB), " ");
				file->Write(m_frameSpeed);
			}
			
			for (int i=0; i<MAX_ADDITIONAL_SEQUENCES; i++)
			{
				CSequence* additionalSeq = AdditionalSeqs[i];
				
				if (additionalSeq->AdditionalSequenceIsValid())
				{
					file->Space();
					file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_ADDITIONAL, TABLE_GRAB), " ");
					file->Write(additionalSeq->GetStartFrame());
					file->Space();
					file->Write(additionalSeq->GetFrameCount());
					file->Space();
					file->Write(additionalSeq->GetLoopFrame());
					file->Space();
					file->Write(additionalSeq->GetFrameSpeed());
					file->Space();
					file->Write(additionalSeq->GetEnum());
				}
			}

			// this is an unpleasant abuse, but needed to retro-hack into old versions of carcass...
			//
			if (bPreQuat)
			{
				file->Space();
				file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_PREQUAT, TABLE_GRAB));
			}

			// any other stuff in future (sound events etc)...
			//
			// ...

			// write end marker (so QData knows to start reading again)...
			//
			file->Space();
			file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_QDSKIPSTOP, TABLE_GRAB));
		}
	}

	file->Writeln();
}
Пример #25
0
void CBlastIndex::AddSequence(const CSequence& inSequence)
{
	fSequences.push_back(inSequence);
	++fSequenceCount;
	fTotalSequenceLength += inSequence.length();
}
Пример #26
0
void CModel::Write(CTxtFile* file)
{
	file->Write("$");
	file->Writeln(CAssimilateDoc::GetKeyword(TK_AS_GRABINIT, TABLE_QDT));

	if (!HasGLA())
	{
		if (GetScale() != 1.0f)
		{
			file->Write("$");
			file->Write(CAssimilateDoc::GetKeyword(TK_AS_SCALE, TABLE_QDT)," ");
			file->Writeln(va("%g",GetScale()));
		}

		if (GetKeepMotion())
		{
			file->Write("$");
			file->Writeln(CAssimilateDoc::GetKeyword(TK_AS_KEEPMOTION, TABLE_QDT));
		}

		if (GetRefGLAPath())
		{
			file->Write("$");
			file->Write(CAssimilateDoc::GetKeyword(TK_AS_REF_GLA, TABLE_QDT), " ");
			file->Writeln(va("%s", GetRefGLAPath()));
		}

		for (int iPCJ=0; iPCJ < PCJList_GetEntries(); iPCJ++)
		{
			file->Write("$");
			file->Write(CAssimilateDoc::GetKeyword(TK_AS_PCJ, TABLE_QDT)," ");
			file->Writeln( PCJList_GetEntry(iPCJ) );
		}
	}

	CComment* curComment = m_comments;
	while(curComment != NULL)
	{
		curComment->Write(file);
		curComment = curComment->GetNext();
	}

	bool bFirstSeqWritten = false;
	CSequence* curSequence = m_sequences;
	while(curSequence != NULL)
	{
		curSequence->Write(file, !bFirstSeqWritten && GetPreQuat());
		curSequence = curSequence->GetNext();

		bFirstSeqWritten = true;
	}

	file->Writeln("$", CAssimilateDoc::GetKeyword(TK_AS_GRABFINALIZE, TABLE_QDT));

	if (m_path != NULL)
	{
		file->Write("$", CAssimilateDoc::GetKeyword(GetConvertType(), TABLE_QDT));
		CString path = m_path;
	
		int loc = path.Find("/base");
		if (loc > -1)
		{
			path = path.Right(path.GetLength() - loc - 5);
			loc = path.Find("/");
			path = path.Right(path.GetLength() - loc - 1);
		}
		if (!path.GetLength())	// check that some dopey artist hasn't use the name "base" on the right hand side
		{
			path = m_path;
		}

		file->Write(" ", path, " ");

		// params stuff...

		if (IsGhoul2())
		{
			if	(GetMakeSkin())
			{
				file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_MAKESKIN,	TABLE_CONVERT), " ");
			}
			if	(GetSmooth())
			{
				file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_SMOOTH,	TABLE_CONVERT), " ");
			}
			if (GetLoseDupVerts())
			{
				file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_LOSEDUPVERTS, TABLE_CONVERT), " ");
			}
			if  (GetIgnoreBaseDeviations())
			{
				file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_IGNOREBASEDEVIATIONS, TABLE_CONVERT), " ");
			}
			if	(GetSkew90())
			{
				file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_SKEW90,	TABLE_CONVERT), " ");
			}
			if	(GetNoSkew90())
			{
				file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_NOSKEW90, TABLE_CONVERT), " ");
			}
			if	(GetMakeSkelPath() && strlen(GetMakeSkelPath()))
			{
				file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_MAKESKEL,	TABLE_CONVERT), " ");
				file->Write(GetMakeSkelPath(), " ");
			}

			// params below not used for ghoul2
		}
		else
		{
			if (giLODLevelOverride)
			{
				file->Write(va("-lod %d ",giLODLevelOverride));
			}

			file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_PLAYERPARMS, TABLE_CONVERT), " ");
			file->Write(0);//m_skipStart+1);	// ignore these, but don't want to update parser and have invalid prev files
			file->Space();
			file->Write(0);//m_skipEnd);//max upper frames);
			file->Space();		
		}

		if (m_originx || m_originy || m_originz)
		{
			file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_ORIGIN, TABLE_CONVERT), " ");
			file->Write(m_originx);
			file->Space();
			file->Write(m_originy);
			file->Space();
			file->Write(m_originz);
		}

		file->Writeln();
	}
}
Пример #27
0
bool CModel::WriteExternal(bool bPromptForNames, bool& bCFGWritten)
{
	bCFGWritten = false;

	CString filename;
	if (bPromptForNames)
	{
		CString strInitialPrompt(ghAssimilateView->GetDocument()->GetPathName());
		Filename_RemoveFilename(strInitialPrompt);
		strInitialPrompt.Replace("/","\\");
		strInitialPrompt += "\\";
		strInitialPrompt += sANIMATION_CFG_NAME;
		
		CFileDialog dialog(FALSE, ".cfg", strInitialPrompt, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Config Data Files (*.cfg)|*.cfg|All Files (*.*)|*.*||", NULL);
		if (dialog.DoModal() != IDOK)
		{
			return false;
		}
		filename = dialog.GetPathName();	// eg. {"Q:\quake\baseq3\models\players\ste_assimilate_test\ste_assimilate_test.cfg"}
	}
	else
	{
		filename = ((CAssimilateApp*)AfxGetApp())->GetQuakeDir();
		filename+= GetPath();
		filename.MakeLower();
		filename.Replace('\\', '/');
		int loc = filename.Find(m_name);//"/root");
		if (loc>=0)
		{
			filename = filename.Left(loc+strlen(m_name));
		}
		// dup the dirname to use as the model name... (eg "/.../.../klingon" becomes "/.../.../klingon/klingon"
		filename += "/"; filename += sANIMATION_CFG_NAME;	
	}
	CTxtFile* file = CTxtFile::Create(filename);
	if (file == NULL || !file->IsValid())
	{
		ErrorBox(va("Error creating file \"%s\"!",filename));
		return false;
	}

	// new bit, check for the existance of an animation.pre file, which means export this in Q3 format (rather than trek)

	CString strQ3FormatCheckName(filename);
	Filename_RemoveFilename(strQ3FormatCheckName);
	strQ3FormatCheckName += "\\";
	strQ3FormatCheckName += sANIMATION_PRE_NAME;
	strQ3FormatCheckName.Replace("/","\\");

	bool bExportFormatIsQuake3Multiplayer = //FileExists(strQ3FormatCheckName);
											((CAssimilateApp*)AfxGetApp())->GetMultiPlayerMode();	

	CString strPrePend;
	if (bExportFormatIsQuake3Multiplayer)
	{
		// multi-player format, check for optional animation.pre file...

		FILE *fhPRE = fopen(strQ3FormatCheckName, "rt");
		
		if (fhPRE)
		{
			// read all the lines in this file and just write them straight to the output file...

			char sLine[16384];
			char *psLine;
			CString strTrimmed;

			while ((psLine = fgets( sLine, sizeof(sLine), fhPRE ))!=NULL)
			{
				strTrimmed = psLine;
				strTrimmed.Replace("\n","");
				strTrimmed.TrimRight();
				strTrimmed.TrimLeft();

				file->Writeln(strTrimmed);
			}

			if (ferror(fhPRE))
			{
				ErrorBox(va("Error during reading of file \"%s\"!\n\n( this shouldn't happen )",(LPCSTR)strQ3FormatCheckName));
			}

			fclose(fhPRE);
		}		

		file->Writeln("");
		file->Writeln("//");
		file->Writeln("// Format:  targetFrame, frameCount, loopFrame, frameSpeed");
		file->Writeln("//");
	}
	else
	{
		// single-player format...

		CString commentLine;
		CTime time = CTime::GetCurrentTime();
		commentLine.Format("// %s %d frames; %d sequences; updated %s", filename, m_totFrames, GetTotSequences(), time.Format("%H:%M %A, %B %d, %Y"));
		file->Writeln(commentLine);

		// the Writeln functions I have to call don't handle "\n" chars properly because of being opened in binary mode
		//	(sigh), so I have to explicitly call the Writeln() functions to output CRs... :-(

		file->Writeln("//");
		file->Writeln("// Format:  enum, targetFrame, frameCount, loopFrame, frameSpeed");	
		file->Writeln("//");
	}

	CSequence* curSequence = m_sequences;
	while(curSequence != NULL)
	{
		curSequence->WriteExternal(this, file, bExportFormatIsQuake3Multiplayer);
		curSequence = curSequence->GetNext();
	}
	file->Delete();

	if (HasGLA())
	{
		_unlink(filename);	// zap it, since it's meaningless here (only has one seq/enum: the whole GLA)
	}
	else
	{
		bCFGWritten = true;
	}

	return true;
}
Пример #28
0
void CModel::Resequence(bool bReScanASEFiles /* = false */)
{
	CWaitCursor wait;
	CRect Rect;

	CProgressCtrl *pProgress = NULL;

	if (bReScanASEFiles && ((CAssimilateApp*)AfxGetApp())->m_pMainWnd)
	{
		pProgress = new CProgressCtrl;
		bool bOK = !!pProgress->Create(	WS_CHILD|WS_VISIBLE|PBS_SMOOTH,		// DWORD dwStyle, 
									CRect(100,100,200,200),				// const RECT& rect, 
									((CAssimilateApp*)AfxGetApp())->m_pMainWnd,	// CWnd* pParentWnd, 
									1									// UINT nID 
									);
		if (!bOK)
		{
			delete pProgress;
			pProgress = NULL;
		}
	}
	
	int iTotMasterSequences = GetTotMasterSequences();
	if (pProgress)
	{			
		pProgress->SetRange(0,iTotMasterSequences);
	}
	int iSequenceNumber=0;

	int curFrame = 0;
	CSequence* curSequence = m_sequences;
	while(curSequence != NULL)
	{
		if (pProgress)
		{
			pProgress->SetPos(iSequenceNumber++);
			wait.Restore();
		}
		
		// mark current enums as valid or not...

		curSequence->SetValidEnum(((CAssimilateApp*)AfxGetApp())->ValidEnum(curSequence->GetEnum()));
	
		for (int _i=0; _i<MAX_ADDITIONAL_SEQUENCES; _i++)
		{
			CSequence *additionalSeq = curSequence->AdditionalSeqs[_i];

			additionalSeq->SetValidEnum(((CAssimilateApp*)AfxGetApp())->ValidEnum(additionalSeq->GetEnum()));
		}

		if ( bReScanASEFiles )
		{
			// new code, first of all check for changed framecounts (ie updated ASE file), and update sequence if nec...

			CString nameASE = ((CAssimilateApp*)AfxGetApp())->GetQuakeDir();
					nameASE+= curSequence->GetPath();

			if (!FileExists(nameASE))
			{
				if (gbCarWash_DoingScan)
				{
					strCarWashErrors += va("Model file missing: \"%s\"\n",nameASE);
				}
				else
				{
					if ( gbReportMissingASEs )
					{	
						gbReportMissingASEs = GetYesNo(va("Model file missing: \"%s\"\n\nContinue recieving this message?",nameASE));
					}
				}
			}
			else
			{
				int iStartFrame, iFrameCount, iFrameSpeed;

				iFrameCount = curSequence->GetFrameCount();	// default it in case we skip an XSI read
				iFrameSpeed = curSequence->GetFrameSpeed();	// default it in case we cache this file

				curSequence->ReadASEHeader( nameASE, iStartFrame, iFrameCount, iFrameSpeed, true);	// true = can skip XSI read

				if ( iFrameCount != curSequence->GetFrameCount() )
				{
					if (gbCarWash_DoingScan)
					{
						strCarWashErrors += va("file: \"%s\" has a framecount of %d, but .CAR file says %d\n",nameASE,iFrameCount,curSequence->GetFrameCount());
					}
					else
					{
						// don't mention it if the current count is zero, it's probably a new anim we've just added...

						if ( curSequence->GetFrameCount() )
						{
							if (giFixUpdatedASEFrameCounts == YES || giFixUpdatedASEFrameCounts == NO)
							{
								CYesNoYesAllNoAll query(	va("Model file: \"%s\"",nameASE),
															"",
															va("... has a framecount of %d instead of %d as the QDT/CAR file says",iFrameCount, curSequence->GetFrameCount()),
															"",
															"",
															"Do you want me to fix this?"
															);
								giFixUpdatedASEFrameCounts = query.DoModal();
							}
						}

						// update the sequence?...

						if (giFixUpdatedASEFrameCounts == YES || giFixUpdatedASEFrameCounts == YES_ALL 
							|| !curSequence->GetFrameCount()	// update: I think this should be here?
							)
						{
							curSequence->SetFrameCount( iFrameCount );
						}
					}
				}
			}

			// findmeste:	this no longer seems to do anything under JK2, presumablt EF1-only?
#if 0
			// now try to do any auto-associate between the ASE filename base and the existing enums, 
			//	so if we find (eg) /...../...../CROUCH.ASE and we have BOTH_CROUCH then auto-set the enum to BOTH_CROUCH

			CString stringASEName = nameASE;
			Filename_BaseOnly(stringASEName);	// now = (eg) "falldeath" or "injured" etc 			

			for (int i=0; ; i++)
			{
				LPCSTR p = ((CAssimilateApp*)AfxGetApp())->GetEnumEntry(i);	

				if (!p)		// EOS?
					break;

				CString stringEnum = p;

				// note, I could check stuff like "IsEnumSeperator(LPCSTR lpString)" on <p>, but you'd never
				//	have one of those enums assigned to a sequence anyway.

				char *psEnumPosAfterUnderScore = strchr(stringEnum,'_');
				if (psEnumPosAfterUnderScore++)	// check it, and skip to next char 
				{
					// does this enum match the ASE name?

					if ( !stricmp( psEnumPosAfterUnderScore, stringASEName ) )
					{
						// ok, we've found a good candidate, so set it...  (no need for query-prev code, but I wanted to)

						if ( strcmp( curSequence->GetEnum(), stringEnum))
						{
							curSequence->SetEnum(stringEnum);
						}
					}
				}
				else
				{						
					// this should never happen...

					if (gbCarWash_DoingScan)
					{
						strCarWashErrors += va("found an anim enum with no underscore: \"%s\"\n",stringEnum);
					}
					else
					{
						ASSERT(0);
						ErrorBox(va("Error! Somehow I found an anim enum with no underscore: \"%s\"",stringEnum));
					}
				}
			}
#endif
		}

		// More bollox for Gummelt... :-)
		// now do the other freaky trick (you'd better be grateful for all this Mike!!! <g>), which is:

		// If you find the substring DEATH in this (master) sequence's enum, then ensure that the first *additional*
		//	sequence of it is set to be the corresponding DEAD enum, but using the last frame only (and non-looping)
		//
		// (... or something...)

		{	// keep scope local for neatness

			if ( strstr (curSequence->GetEnum(), "DEATH") )
			{
				// scan this sequence's additional sequences for a DEAD of the same basic type...

				CString stringEnumDEAD = curSequence->GetEnum();

				ASSERT(!IsEnumSeperator(stringEnumDEAD));

				stringEnumDEAD.Replace("DEATH","DEAD");

				// 1st, is there even a corresponding DEAD enum in the global enum table that we can look for...

				CString stringEnum;
				bool bEnumFound = false;
				for (int iEnumEntry=0; !bEnumFound; iEnumEntry++)
				{
					LPCSTR p = ((CAssimilateApp*)AfxGetApp())->GetEnumEntry(iEnumEntry);	

					if (!p)		// EOS?
						break;

					stringEnum = p;

					// note, I could check stuff like "IsEnumSeperator(LPCSTR lpString)" on <p>, but you'd never
					//	have one of those enums assigned to a sequence anyway.

					// does this enum match the one we've built?

					if ( !_stricmp( stringEnum, stringEnumDEAD ) )
					{
						bEnumFound = true;
					}
				}

				if ( bEnumFound )
				{
					// ok, there *is* one of these, so let's scan this sequence's additional sequences to see if we've
					//	got it...

					CSequence *additionalSeq;	// outside FOR scope
					for (int i=0; i<MAX_ADDITIONAL_SEQUENCES; i++)
					{
						additionalSeq = curSequence->AdditionalSeqs[i];

						if (additionalSeq->AdditionalSequenceIsValid())
						{
							if (!strcmp(additionalSeq->GetEnum(),stringEnum))
							{
								break;	// we've found one!
							}
						}
					}

					// if we didn't find one, NULL the ptr
					if (int i=MAX_ADDITIONAL_SEQUENCES)
					{
						additionalSeq = NULL;
					}

					// did we find one? (or did it have the wrong info in?)

					if ( additionalSeq == NULL // didn't find one
						|| additionalSeq->GetFrameCount()!=1
						|| additionalSeq->GetLoopFrame() !=-1
						|| additionalSeq->GetStartFrame()!= curSequence->GetFrameCount()-1
						|| additionalSeq->GetFrameSpeed()!= curSequence->GetFrameSpeed()
						)
					{
						// find a slot to add this new sequence to, or use the faulty one...

						if (additionalSeq == NULL)
						{
							for (int i=0; i<MAX_ADDITIONAL_SEQUENCES; i++)
							{
								additionalSeq = curSequence->AdditionalSeqs[i];

								if (!additionalSeq->AdditionalSequenceIsValid())
								{
									break;	// found an unused slot
								}
							}
						}

						// so have we got a slot to work with?

						if ( additionalSeq == NULL )
						{
							if (gbCarWash_DoingScan)
							{
								strCarWashErrors += va( "F**k!!!: I need an 'additional sequence' slot free in the entry: \"%s\" to generate a DEAD seq, but there isn't one spare. Edit this yourself later.\n",curSequence->GetPath());
							}
							else
							{
								ErrorBox( va( "F**k!!!\n\nI need an 'additional sequence' slot free in the ASE:\n\n\"%s\"\n\n... to generate a DEAD seq, but there isn't one spare. Edit this yourself later.",curSequence->GetPath()));
							}
						}
						else
						{
							additionalSeq->SetStartFrame( curSequence->GetFrameCount()-1 );
							additionalSeq->SetFrameCount( 1 );
							additionalSeq->SetLoopFrame (-1 );
							additionalSeq->SetFrameSpeed( curSequence->GetFrameSpeed() );
							additionalSeq->SetEnum ( stringEnumDEAD );
						}
					}
				}
			}
		}

		curSequence->SetTargetFrame(curFrame + curSequence->GetStartFrame());	// slightly more legal than just (curFrame)

		// update: now set any additional sequences within it...

		for (int i=0; i<MAX_ADDITIONAL_SEQUENCES; i++)
		{
			curSequence->AdditionalSeqs[i]->SetTargetFrame(curFrame + curSequence->AdditionalSeqs[i]->GetStartFrame());
		}

		curFrame += curSequence->GetFrameCount();
		curFrame += curSequence->GetGenLoopFrame()?1:0;	// findme:  is this right?  I hate this system
		curSequence = curSequence->GetNext();
	}
	m_totFrames = curFrame;

	ghAssimilateView->GetDocument()->SetModifiedFlag();

	if (pProgress)
	{
		delete pProgress;
		pProgress = 0;
	}
}
Пример #29
0
bool CInstrument2A03::LoadFile(CFile *pFile, int iVersion, CFamiTrackerDoc *pDoc)
{
	// Reads an FTI file
	//

	//CFamiTrackerDoc *pDoc = (CFamiTrackerDoc*)theApp.GetFirstDocument();
	char SampleNames[MAX_DSAMPLES][256];
	stSequence OldSequence;

	// Sequences
	unsigned char SeqCount;
	pFile->Read(&SeqCount, sizeof(char));

	// Loop through all instrument effects
	for (unsigned int i = 0; i < SeqCount; ++i) {

		unsigned char Enabled;
		pFile->Read(&Enabled, sizeof(char));

		if (Enabled == 1) {
			// Read the sequence
			int Count;
			pFile->Read(&Count, sizeof(int));

			if (Count < 0 || Count > MAX_SEQUENCE_ITEMS)
				return false;

			// Find a free sequence
			int Index = pDoc->GetFreeSequence(i);
			CSequence *pSeq = pDoc->GetSequence(Index, i);

			if (iVersion < 20) {
				OldSequence.Count = Count;
				for (int j = 0; j < Count; ++j) {
					pFile->Read(&OldSequence.Length[j], sizeof(char));
					pFile->Read(&OldSequence.Value[j], sizeof(char));
				}
				pDoc->ConvertSequence(&OldSequence, pSeq, i);	// convert
			}
			else {
				pSeq->SetItemCount(Count);
				int LoopPoint;
				int Setting;
				pFile->Read(&LoopPoint, sizeof(int));
				pSeq->SetLoopPoint(LoopPoint);
				if (iVersion > 20) {
					int ReleasePoint;
					pFile->Read(&ReleasePoint, sizeof(int));
					pSeq->SetReleasePoint(ReleasePoint);
				}
				if (iVersion >= 23) {
					pFile->Read(&Setting, sizeof(int));
					pSeq->SetSetting(Setting);
				}
				for (int j = 0; j < Count; ++j) {
					char Val;
					pFile->Read(&Val, sizeof(char));
					pSeq->SetItem(j, Val);
				}
			}
			SetSeqEnable(i, true);
			SetSeqIndex(i, Index);
		}
		else {
			SetSeqEnable(i, false);
			SetSeqIndex(i, 0);
		}
	}

	bool SamplesFound[MAX_DSAMPLES];
	memset(SamplesFound, 0, sizeof(bool) * MAX_DSAMPLES);

	unsigned int Count;
	pFile->Read(&Count, sizeof(int));

	// DPCM instruments
	for (unsigned int i = 0; i < Count; ++i) {
		unsigned char InstNote;
		pFile->Read(&InstNote, sizeof(char));
		int Octave = InstNote / 12;
		int Note = InstNote % 12;
		unsigned char Sample, Pitch;
		pFile->Read(&Sample, sizeof(char));
		pFile->Read(&Pitch, sizeof(char));
		SetSamplePitch(Octave, Note, Pitch);
		SetSample(Octave, Note, Sample);
	}

	// DPCM samples list
	bool bAssigned[OCTAVE_RANGE][NOTE_RANGE];
	memset(bAssigned, 0, sizeof(bool) * OCTAVE_RANGE * NOTE_RANGE);

	unsigned int SampleCount;
	pFile->Read(&SampleCount, sizeof(int));

	for (unsigned int i = 0; i < SampleCount; ++i) {
		int Index, Len;
		pFile->Read(&Index, sizeof(int));
		pFile->Read(&Len, sizeof(int));
		if (Index >= MAX_DSAMPLES || Len >= 256)
			return false;
		pFile->Read(SampleNames[Index], Len);
		SampleNames[Index][Len] = 0;
		int Size;
		pFile->Read(&Size, sizeof(int));
		char *SampleData = new char[Size];
		pFile->Read(SampleData, Size);
		bool Found = false;
		for (int j = 0; j < MAX_DSAMPLES; ++j) {
			CDSample *pSample = pDoc->GetDSample(j);
			// Compare size and name to see if identical sample exists
			if (pSample->SampleSize == Size && !strcmp(pSample->Name, SampleNames[Index])) {
				Found = true;
				// Assign sample
				for (int o = 0; o < OCTAVE_RANGE; ++o) {
					for (int n = 0; n < NOTE_RANGE; ++n) {
						if (GetSample(o, n) == (Index + 1) && !bAssigned[o][n]) {
							SetSample(o, n, j + 1);
							bAssigned[o][n] = true;
						}
					}
				}
			}
		}

		if (!Found) {
			// Load sample
			int FreeSample = pDoc->GetFreeDSample();
			if (FreeSample != -1) {
				if ((pDoc->GetTotalSampleSize() + Size) <= MAX_SAMPLE_SPACE) {
					CDSample *Sample = pDoc->GetDSample(FreeSample);
					strcpy(Sample->Name, SampleNames[Index]);
					Sample->SampleSize = Size;
					Sample->SampleData = SampleData;
					// Assign it
					for (int o = 0; o < OCTAVE_RANGE; ++o) {
						for (int n = 0; n < NOTE_RANGE; ++n) {
							if (GetSample(o, n) == (Index + 1) && !bAssigned[o][n]) {
								SetSample(o, n, FreeSample + 1);
								bAssigned[o][n] = true;
							}
						}
					}
				}
				else {
//					AfxMessageBox(IDS_OUT_OF_SAMPLEMEM, MB_ICONERROR);
					SAFE_RELEASE_ARRAY(SampleData);
					return false;
				}
			}
			else {
//				AfxMessageBox(IDS_OUT_OF_SLOTS, MB_ICONERROR);
				SAFE_RELEASE_ARRAY(SampleData);
				return false;
			}
		}
		else {
			SAFE_RELEASE_ARRAY(SampleData);
		}
	}

	return true;
}