| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- //===========================================================================================================================
- // Spirenkov Maxim, 2003
- //===========================================================================================================================//
- //
- //===========================================================================================================================
- // MissionLoader
- //============================================================================================
-
- #include "Mission.h"
- #include "MissionLoader.h"
- #include "..\..\Common_h\Mission\MissionFile.h"
- #include "..\..\common_h\corecmds.h"
- //#define MissionLoaderEnableThread
- //#define ENABLE_MEMORY_PROFILE
- #define MEMORY_PROFILE_CPP_FILE "string.h"
- #define MEMORY_PROFILE_CPP_LINE -1
- //============================================================================================
- #ifdef MissionLoaderEnableThread
- DWORD WINAPI MissionLoader::MissionLoaderThreadProc(LPVOID lpParameter)
- {
- ((MissionLoader *)lpParameter)->LoadObjects();
- return 0;
- }
- #endif
- //============================================================================================
- MissionLoader::MissionLoader(Mission & mis, const byte * _data, dword _size) : mission(mis)
- {
- data = _data;
- pnt = 0;
- size = _size;
- Assert(data != 0);
- Assert(size > 0);
- threadID = 0;
- threadHandle = 0;
- objectsCount = 0;
- stopLoading = false;
- }
- MissionLoader::~MissionLoader()
- {
- stopLoading = true;
- for(long i = 0; threadHandle && i < 100; i++)
- {
- Sleep(10);
- }
- #ifndef _XBOX
- if(threadHandle)
- {
- TerminateThread(threadHandle, 0);
- threadHandle = 0;
- }
- #endif
- }
- //============================================================================================
- //Начать процесс загрузки
- bool MissionLoader::StartProcess(float loadProgressRange)
- {
- //Проверим версию данных
- if(!CheckId()) return false;
- if(objectsCount)
- {
- loadStep = loadProgressRange/objectsCount;
- }else{
- loadStep = loadProgressRange;
- }
- #ifdef MissionLoaderEnableThread
- threadHandle = CreateThread(NULL, 0, MissionLoaderThreadProc, this, 0, &threadID);
- #else
- LoadObjects();
- #endif
- return true;
- }
- //Залочить список объектов
- void MissionLoader::LockObjects()
- {
- #ifdef MissionLoaderEnableThread
- critSection.Enter();
- #endif
- }
- //Освободить список объектов
- void MissionLoader::UnLockObjects()
- {
- #ifdef MissionLoaderEnableThread
- critSection.Leave();
- #endif
- }
- //Процесс загрузки окончен
- bool MissionLoader::IsDone()
- {
- LockObjects();
- bool res = !IsCan();
- UnLockObjects();
- return res && (threadHandle == 0);
- }
- //============================================================================================
- //Этапы загрузки
- //============================================================================================
- //Проверить версию
- bool MissionLoader::CheckId()
- {
- MissionFileId * hdr = (MissionFileId *)Get(sizeof(MissionFileId));
- if(!hdr) return false;
- const char * id = MISSION_FILE_ID;
- for(long i = 0; i < sizeof(hdr->id); i++) if(hdr->id[i] != id[i]) return false;
- if(SwizzleLong(hdr->ver) != MISSION_FILE_VER) return false;
- objectsCount = SwizzleLong(hdr->objectsCount);
- return true;
- }
- #ifdef ENABLE_MEMORY_PROFILE
- struct Data
- {
- enum {name_len = 80};
- dword n;
- dword m;
- dword b; char name[name_len];
- Data() : n(0),m(0),b(0) {}
- };
- static array<Data> table(_FL_);
- #endif
- //Загрузить объекты
- void MissionLoader::LoadObjects()
- {
- #ifdef ENABLE_MEMORY_PROFILE
- CoreCommand_GetMemStat stats1(MEMORY_PROFILE_CPP_FILE, MEMORY_PROFILE_CPP_LINE);
- api->ExecuteCoreCommand(stats1);
- api->Trace("Memory state at start loading...\n use memory: %u, blocks: %u; cpp file name: %s, cpp file line: %i",
- stats1.totalAllocSize,
- stats1.numBlocks,
- MEMORY_PROFILE_CPP_FILE,
- MEMORY_PROFILE_CPP_LINE);
- table.DelAll();
- #endif
- //Начинаем загрузку объектов миссии
- while(IsCan())
- {
- //Sleep(40); //Тест асинхронной загрузки
- if(stopLoading) break;
- LockObjects();
- LoadObject();
- UnLockObjects();
- api->SetWatchDog();
- }
- threadHandle = 0;
- stopLoading = true;
- #ifdef ENABLE_MEMORY_PROFILE
- api->Trace("\n%30s %14s %14s %14s %14s %14s","Class name","Objects count","Total memory","Total blocks","Memory","Blocks");
- api->Trace("");
- array<Data *>list(_FL_); list.AddElements(table.Size());
- for( int i = 0 ; i < table ; i++ )
- {
- Data *data = &table[i];
- list[i] = data;
- int j = i;
- while( j > 0 )
- {
- if( list[j - 1]->m < list[j]->m )
- {
- Data *t = list[j - 1];
- list[j - 1] = list[j];
- list[j] = t;
- }
- else
- break;
- j--;
- }
- }
- for( int i = 0 ; i < list ; i++ )
- {
- const Data &data = *list[i];
- api->Trace("%30s %14d %14d %14d %14d %14d",data.name,data.n,data.m,data.b,data.m/data.n,data.b/data.n);
- }
- api->Trace("");
- #endif
- }
- //Загрузить объект
- void MissionLoader::LoadObject()
- {
- //Данные объекта
- dword size = 0;
- const char * objectType = GetObjectData(size);
- if(!objectType)
- {
- api->Trace("MissionLoader::LoadObject -> can't get object information. mis file is damage?");
- return;
- }
- const void * data = Get(size);
- if(!data)
- {
- api->Trace("MissionLoader::LoadObject -> can't get data for object \"%s\"", objectType);
- return;
- }
-
- //Создаём объект
- #ifdef ENABLE_MEMORY_PROFILE
- const char * calcAllocsInFile = MEMORY_PROFILE_CPP_FILE;
- const long calcAllocsInLine = MEMORY_PROFILE_CPP_LINE;
- CoreCommand_GetMemStat stats1(calcAllocsInFile, calcAllocsInLine);
- api->ExecuteCoreCommand(stats1);
- api->Trace("Object %s",objectType);
- #endif
- MOPReader reader(data, size);
- if(!mission.CreateObjectEx(objectType, reader, data, size))
- {
- api->Trace("MissionLoader::LoadObject -> can't create object \"%s\" (type: \"%s\")", reader.GetObjectID(), objectType);
- }
- mission.LoadingProgress(loadStep);
- #ifdef ENABLE_MEMORY_PROFILE
- CoreCommand_GetMemStat stats2(calcAllocsInFile, calcAllocsInLine);
- api->ExecuteCoreCommand(stats2);
- if( stats2.totalAllocSize != stats1.totalAllocSize || stats2.numBlocks != stats1.numBlocks )
- {
- api->Trace("Object %s, use memory: %u, blocks: %u; cpp file name: %s, cpp file line: %i",
- objectType,
- stats2.totalAllocSize - stats1.totalAllocSize,
- stats2.numBlocks - stats1.numBlocks,
- calcAllocsInFile,
- calcAllocsInLine);
- for( int i = 0 ; i < table ; i++ )
- {
- if( string::IsEqual(table[i].name,objectType))
- break;
- }
- Data *data = null;
- if( i < table )
- data = &table[i];
- else
- {
- data = &table[table.Add()];
- strcpy_s(data->name,Data::name_len,objectType);
- }
- data->n++;
- data->m += stats2.totalAllocSize - stats1.totalAllocSize;
- data->b += stats2.numBlocks - stats1.numBlocks;
- }
- #endif
- }
- //Получить данные объекта
- const char * MissionLoader::GetObjectData(dword & datasize)
- {
- //Получаем первый символ
- const char * s = (const char *)Get(1);
- if(!s || !s[0]) return null;
- //Ищем окончание строки
- while(true)
- {
- const char * c = (const char *)Get(1);
- if(!c) return null;
- if(!c[0]) break;
- }
- //Получаем размер данных
- dword * size = (dword *)Get(sizeof(dword));
- if(!size) return null;
- datasize = SwizzleDWord(*size);
- return s;
- }
- //============================================================================================
- //Входные данные
- //============================================================================================
- //Получить данные
- __forceinline const void * MissionLoader::Get(dword s)
- {
- if(pnt + s > size) return null;
- const void * p = data + pnt;
- pnt += s;
- return p;
- }
- //Окончание потока
- bool MissionLoader::IsCan()
- {
- return pnt < size;
- }
|