Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
1340 lines
37 KiB
C++
1340 lines
37 KiB
C++
#include "AdeptHeaders.hpp"
|
|
#include <GameOS\ToolOS.hpp>
|
|
#include "Application.hpp"
|
|
#include "Tool.hpp"
|
|
#include "Network.hpp"
|
|
|
|
//#############################################################################
|
|
//############################ ResourceID ###############################
|
|
//#############################################################################
|
|
|
|
ResourceID
|
|
ResourceID::Null(-1, 0);
|
|
|
|
bool Stuff::Close_Enough(
|
|
const ResourceID &id1,
|
|
const ResourceID &id2,
|
|
Scalar e
|
|
)
|
|
{
|
|
Check_Object(&id1);
|
|
Check_Object(&id2);
|
|
|
|
return
|
|
id1 == id2;
|
|
}
|
|
|
|
//#############################################################################
|
|
//############################# Resource ################################
|
|
//#############################################################################
|
|
|
|
FileDependencies
|
|
*Resource::ParentFileDependencies = NULL;
|
|
|
|
static ResourceFile* CurrentFileSearched = NULL;
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
Resource::Resource():
|
|
MemoryStream(NULL, 0),
|
|
m_ID(ResourceID::Null)
|
|
{
|
|
Check_Pointer(this);
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// For this resource type, we do not even know which resource file to use
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
m_ID.m_fileID = -1;
|
|
m_handle.m_databaseHandle = NULL;
|
|
m_handle.m_ID = -1;
|
|
m_handle.m_record = NULL;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
Resource::Resource(const ResourceID &resource_id, bool load):
|
|
MemoryStream(NULL, 0),
|
|
m_ID(resource_id)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Object(&resource_id);
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// Find the database where the resource should live and look up the ID in
|
|
// it. It is assumed to be there if you are asking by ID
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
Check_Object(ResourceManager::Instance);
|
|
ResourceFile *file =
|
|
ResourceManager::Instance->GetResourceFile(m_ID.m_fileID);
|
|
Check_Object(file);
|
|
m_handle.m_databaseHandle = file->m_fileHandle;
|
|
Verify(m_handle.m_databaseHandle);
|
|
m_handle.m_ID = resource_id.m_recordID;
|
|
#if defined(_ARMOR)
|
|
bool result =
|
|
#endif
|
|
m_handle.FindID(load);
|
|
Verify(result);
|
|
|
|
//
|
|
//-------------------------------------
|
|
// Set the pointers to look at the data
|
|
//-------------------------------------
|
|
//
|
|
streamStart = currentPosition = (BYTE*)(m_handle.m_data);
|
|
streamSize = m_handle.m_length;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
Resource::Resource(const char* name, bool load):
|
|
MemoryStream(NULL, 0),
|
|
m_ID(ResourceID::Null)
|
|
{
|
|
Check_Pointer(this);
|
|
|
|
//
|
|
//--------------------------------------------
|
|
// Find the current resource file to deal with
|
|
//--------------------------------------------
|
|
//
|
|
Check_Object(ResourceManager::Instance);
|
|
TableIteratorOf<ResourceFile*, short> files(&ResourceManager::Instance->m_openedFiles);
|
|
ResourceFile *file;
|
|
|
|
//
|
|
//---------------------------------------
|
|
// If we were given a name, search for it
|
|
//---------------------------------------
|
|
//
|
|
if (name)
|
|
{
|
|
Check_Pointer(name);
|
|
Verify(name[1] != ':');
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// Make sure that the name is tool-friendly
|
|
//-----------------------------------------
|
|
//
|
|
name = Tool::GetToolFileName(name);
|
|
m_handle.m_name = name;
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// Look for the file to place the resource in, and if we find it, set up
|
|
// the pointers
|
|
//----------------------------------------------------------------------
|
|
//
|
|
files.Last();
|
|
while ((file = files.ReadAndPrevious()) != NULL)
|
|
{
|
|
m_handle.m_databaseHandle = file->m_fileHandle;
|
|
Verify(m_handle.m_databaseHandle);
|
|
if (m_handle.FindName(load))
|
|
{
|
|
m_ID.m_fileID = file->m_fileID;
|
|
m_ID.m_recordID = m_handle.m_ID;
|
|
streamStart = currentPosition = (BYTE*)(m_handle.m_data);
|
|
streamSize = m_handle.m_length;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------
|
|
// If no name was given, we cannot pre-allocate
|
|
//---------------------------------------------
|
|
//
|
|
else
|
|
m_handle.m_name = NULL;
|
|
|
|
//
|
|
//--------------------------------------------------------------
|
|
// Use the m_fileID of the resource file chosen and get its handle
|
|
//--------------------------------------------------------------
|
|
//
|
|
files.Last();
|
|
file = files.GetCurrent();
|
|
Check_Object(file);
|
|
m_ID.m_fileID = file->m_fileID;
|
|
m_handle.m_databaseHandle = file->m_fileHandle;
|
|
Verify(m_handle.m_databaseHandle);
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// Clear out the pointers so that nothing will be unlocked if the data is
|
|
// not dealt with
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
m_handle.m_record = NULL;
|
|
m_handle.m_ID = -1;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
Resource::Resource(const char* name, ResourceFile *resource_file, bool load):
|
|
MemoryStream(NULL, 0),
|
|
m_ID(ResourceID::Null)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Object(resource_file);
|
|
|
|
//
|
|
//---------------------------------------
|
|
// If we were given a name, search for it
|
|
//---------------------------------------
|
|
//
|
|
if (name)
|
|
{
|
|
Check_Pointer(name);
|
|
Verify(name[1] != ':');
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// Make sure that the name is tool-friendly
|
|
//-----------------------------------------
|
|
//
|
|
name = Tool::GetToolFileName(name);
|
|
m_handle.m_name = name;
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
// Setup the Pointers for the Resource to the File that was given
|
|
//---------------------------------------------------------------
|
|
//
|
|
|
|
m_handle.m_databaseHandle = resource_file->m_fileHandle;
|
|
Verify(m_handle.m_databaseHandle);
|
|
if (m_handle.FindName(load))
|
|
{
|
|
m_ID.m_fileID = resource_file->m_fileID;
|
|
m_ID.m_recordID = m_handle.m_ID;
|
|
streamStart = currentPosition = (BYTE*)(m_handle.m_data);
|
|
streamSize = m_handle.m_length;
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------
|
|
// If no name was given, we cannot pre-allocate
|
|
//---------------------------------------------
|
|
//
|
|
else
|
|
m_handle.m_name = NULL;
|
|
|
|
//
|
|
//--------------------------------------------------------------
|
|
// Use the m_fileID of the resource file chosen and get its handle
|
|
//--------------------------------------------------------------
|
|
//
|
|
m_ID.m_fileID = resource_file->m_fileID;
|
|
m_handle.m_databaseHandle = resource_file->m_fileHandle;
|
|
Verify(m_handle.m_databaseHandle);
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// Clear out the pointers so that nothing will be unlocked if the data is
|
|
// not dealt with
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
m_handle.m_record = NULL;
|
|
m_handle.m_ID = -1;
|
|
}
|
|
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
Resource::~Resource()
|
|
{
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void Resource::FindID(const ResourceID &resource_id, bool load)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(&resource_id);
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Since we are looking something up by ID, it is assumed to be there
|
|
//-------------------------------------------------------------------
|
|
//
|
|
m_ID = resource_id;
|
|
Check_Object(ResourceManager::Instance);
|
|
ResourceFile *resource_file =
|
|
ResourceManager::Instance->GetResourceFile(m_ID.m_fileID);
|
|
Check_Object(resource_file);
|
|
m_handle.m_databaseHandle = resource_file->m_fileHandle;
|
|
Verify(m_handle.m_databaseHandle);
|
|
m_handle.m_ID = resource_id.m_recordID;
|
|
#if defined(_ARMOR)
|
|
bool result =
|
|
#endif
|
|
m_handle.FindID(load);
|
|
Verify(result);
|
|
|
|
//
|
|
//-------------------------
|
|
// Set up the data pointers
|
|
//-------------------------
|
|
//
|
|
streamStart = currentPosition = (BYTE*)(m_handle.m_data);
|
|
streamSize = m_handle.m_length;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void Resource::FindName(const char* name, bool load)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(name);
|
|
Verify(name[1] != ':');
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// Make sure the name is tool-friendly, then set the pointers if we were
|
|
// able to find the given name
|
|
//----------------------------------------------------------------------
|
|
//
|
|
name = Tool::GetToolFileName(name);
|
|
m_handle.m_name = name;
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// Look for the file to place the resource in, and if we find it, set up
|
|
// the pointers
|
|
//----------------------------------------------------------------------
|
|
//
|
|
Check_Object(ResourceManager::Instance);
|
|
TableIteratorOf<ResourceFile*, short> files(&ResourceManager::Instance->m_openedFiles);
|
|
files.Last();
|
|
ResourceFile *file;
|
|
while ((file = files.ReadAndPrevious()) != NULL)
|
|
{
|
|
m_handle.m_databaseHandle = file->m_fileHandle;
|
|
Verify(m_handle.m_databaseHandle);
|
|
if (m_handle.FindName(load))
|
|
{
|
|
m_ID.m_fileID = file->m_fileID;
|
|
m_ID.m_recordID = m_handle.m_ID;
|
|
streamStart = currentPosition = (BYTE*)(m_handle.m_data);
|
|
streamSize = m_handle.m_length;
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------
|
|
// We couldn't find it, so mark the stream as empty
|
|
//-------------------------------------------------
|
|
//
|
|
files.Last();
|
|
file = files.GetCurrent();
|
|
Check_Object(file);
|
|
m_ID.m_fileID = file->m_fileID;
|
|
m_handle.m_databaseHandle = file->m_fileHandle;
|
|
Verify(m_handle.m_databaseHandle);
|
|
m_handle.m_record = NULL;
|
|
m_handle.m_ID = -1;
|
|
streamStart = currentPosition = NULL;
|
|
streamSize = 0;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void Resource::LoadData()
|
|
{
|
|
Check_Object(this);
|
|
Verify(DoesResourceExist());
|
|
m_handle.LoadData();
|
|
streamStart = currentPosition = (BYTE*)(m_handle.m_data);
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void Resource::UnloadData()
|
|
{
|
|
Check_Object(this);
|
|
Verify(DoesResourceExist());
|
|
m_handle.UnloadData();
|
|
streamStart = currentPosition = (BYTE*)(m_handle.m_data);
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void Resource::AbandonData()
|
|
{
|
|
Check_Object(this);
|
|
Verify(DoesResourceExist());
|
|
m_handle.AbandonData();
|
|
streamStart = currentPosition = (BYTE*)(m_handle.m_data);
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
int Resource::GetDiskOffset()
|
|
{
|
|
Check_Object(this);
|
|
Verify(DoesResourceExist());
|
|
return m_handle.GetDiskOffset();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void Resource::First(ResourceFile *file)
|
|
{
|
|
Check_Object(this);
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// If we are supplied a resource file to search, search just that one
|
|
//-------------------------------------------------------------------
|
|
//
|
|
if (file)
|
|
{
|
|
Check_Object(file);
|
|
CurrentFileSearched = NULL;
|
|
m_ID.m_fileID = file->m_fileID;
|
|
m_handle.m_databaseHandle = file->m_fileHandle;
|
|
Verify(m_handle.m_databaseHandle);
|
|
m_handle.First();
|
|
}
|
|
|
|
//
|
|
//---------------------------------------
|
|
// Otherwise, search the whole core chain
|
|
//---------------------------------------
|
|
//
|
|
else
|
|
{
|
|
Check_Object(ResourceManager::Instance);
|
|
TableIteratorOf<ResourceFile*, short> files(&ResourceManager::Instance->m_openedFiles);
|
|
files.Last();
|
|
CurrentFileSearched = files.GetCurrent();
|
|
if (CurrentFileSearched)
|
|
{
|
|
m_ID.m_fileID = CurrentFileSearched->m_fileID;
|
|
m_handle.m_databaseHandle = CurrentFileSearched->m_fileHandle;
|
|
Verify(m_handle.m_databaseHandle);
|
|
m_handle.First();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
|
|
bool Resource::ReadAndNext()
|
|
{
|
|
Check_Object(this);
|
|
|
|
//
|
|
//-------------------------------------------------
|
|
// Make sure to unlock the resource if it is locked
|
|
//-------------------------------------------------
|
|
//
|
|
#if defined(_ARMOR)
|
|
if (!GetResourceID())
|
|
Verify(!streamStart);
|
|
#endif
|
|
|
|
//
|
|
//--------------------
|
|
// Get the next record
|
|
//--------------------
|
|
//
|
|
Try_Again:
|
|
bool result = m_handle.ReadAndNext();
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// If it exists, set the pointers correctly
|
|
//-----------------------------------------
|
|
//
|
|
if (result)
|
|
{
|
|
m_ID.m_recordID = m_handle.m_ID;
|
|
streamStart = currentPosition = (BYTE*)(m_handle.m_data);
|
|
streamSize = m_handle.m_length;
|
|
}
|
|
|
|
//
|
|
//-------------------------------------
|
|
// Otherwise, we look for the next file
|
|
//-------------------------------------
|
|
//
|
|
else if (CurrentFileSearched)
|
|
{
|
|
m_handle.m_record = NULL;
|
|
TableIteratorOf<ResourceFile*, short> files(&ResourceManager::Instance->m_openedFiles);
|
|
ResourceFile *file = files.GetCurrent();
|
|
if (!file || file == CurrentFileSearched)
|
|
{
|
|
CurrentFileSearched = NULL;
|
|
return false;
|
|
}
|
|
ResourceFile *prev_file;
|
|
do
|
|
{
|
|
Check_Object(file);
|
|
prev_file = file;
|
|
file = files.ReadAndNext();
|
|
Check_Object(file);
|
|
} while (file != CurrentFileSearched);
|
|
CurrentFileSearched = prev_file;
|
|
m_ID.m_fileID = CurrentFileSearched->m_fileID;
|
|
m_handle.m_databaseHandle = CurrentFileSearched->m_fileHandle;
|
|
m_handle.First();
|
|
goto Try_Again;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
bool Resource::IsResourceUpToDate()
|
|
{
|
|
Check_Object(this);
|
|
Verify(m_handle.m_databaseHandle);
|
|
Verify(m_handle.m_record);
|
|
|
|
//
|
|
//------------------------------------------------
|
|
// Check the early out to see if we are up to date
|
|
//------------------------------------------------
|
|
//
|
|
bool up_to_date = true;
|
|
Check_Object(FileStreamManager::Instance);
|
|
if (m_handle.m_timeStamp == gos_GetTimeDate())
|
|
return true;
|
|
|
|
//
|
|
//--------------------------------------------------
|
|
// If there is no dependency file, we are up to date
|
|
//--------------------------------------------------
|
|
//
|
|
Check_Object(ResourceManager::Instance);
|
|
ResourceFile *resource_file =
|
|
ResourceManager::Instance->GetResourceFile(m_ID.m_fileID);
|
|
Check_Object(resource_file);
|
|
|
|
// fwang 01/12/01 need this for brb to work
|
|
if (!resource_file->m_dependencyHandle)
|
|
return true;
|
|
|
|
Verify(resource_file->m_dependencyHandle);
|
|
|
|
//
|
|
//--------------------------------------------
|
|
// Get the dependency string from the database
|
|
//--------------------------------------------
|
|
//
|
|
RecordHandle dep_record = m_handle;
|
|
Verify(dep_record.m_ID == m_ID.m_recordID);
|
|
dep_record.m_databaseHandle = resource_file->m_dependencyHandle;
|
|
dep_record.FindID(true);
|
|
MemoryStream
|
|
our_stream((BYTE*)(dep_record.m_data), dep_record.m_length);
|
|
|
|
while (our_stream.GetBytesRemaining() > 0)
|
|
{
|
|
const char* name = Cast_Pointer(const char*, our_stream.GetPointer());
|
|
int len = strlen(name);
|
|
if (FileStreamManager::Instance->CompareModificationDate(name, m_handle.m_timeStamp))
|
|
{
|
|
up_to_date = false;
|
|
break;
|
|
}
|
|
our_stream.AdvancePointer(len+1);
|
|
}
|
|
return up_to_date;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
bool Resource::IsRegistered()
|
|
{
|
|
Check_Object(this);
|
|
|
|
Check_Object(ResourceManager::Instance);
|
|
ResourceFile *resource_file =
|
|
ResourceManager::Instance->GetResourceFile(m_ID.m_fileID);
|
|
Check_Object(resource_file);
|
|
DWORD record_id = resource_file->m_lastRegisteredRecordID;
|
|
return
|
|
static_cast<unsigned>(m_handle.m_ID) <= record_id && record_id != -1;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void Resource::Save(
|
|
Stuff::MemoryStream *stream,
|
|
const FileDependencies *dependencies
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
|
|
#if defined(FIND_CORE_ERFS)
|
|
if (m_ID.m_fileID == 1)
|
|
{
|
|
if (strstr(m_handle.m_name, ".erf"))
|
|
SPEW(("jmalbert", "file=%s", m_handle.m_name));
|
|
}
|
|
#endif
|
|
|
|
//
|
|
//----------------------------------
|
|
// Should we deal with dependencies?
|
|
//----------------------------------
|
|
//
|
|
ResourceFile *resource_file =
|
|
ResourceManager::Instance->GetResourceFile(m_ID.m_fileID);
|
|
Check_Object(resource_file);
|
|
RecordHandle dep_record, *dep_data=NULL;
|
|
if (resource_file->m_dependencyHandle)
|
|
{
|
|
|
|
//
|
|
//---------------------------------
|
|
// Build the dependency data record
|
|
//---------------------------------
|
|
//
|
|
dep_data = &dep_record;
|
|
dep_record.m_databaseHandle = resource_file->m_dependencyHandle;
|
|
dep_record.m_name = m_handle.m_name;
|
|
if (dependencies)
|
|
{
|
|
dep_record.m_length =
|
|
dependencies->m_fileNameStream.GetBytesUsed();
|
|
// Verify(dep_record.m_length > 0);
|
|
BYTE *data =
|
|
static_cast<BYTE*>(dependencies->m_fileNameStream.GetPointer()) - dep_record.m_length;
|
|
dep_record.m_data = data;
|
|
#if defined(_ARMOR)
|
|
SPEW((
|
|
GROUP_ADEPT_RESOURCE,
|
|
"Dependencies for %s:",
|
|
m_handle.m_name
|
|
));
|
|
Check_Object(dependencies);
|
|
MemoryStream our_stream(data, dep_record.m_length);
|
|
while (our_stream.GetBytesRemaining() > 0)
|
|
{
|
|
const char* name = Cast_Pointer(const char*, our_stream.GetPointer());
|
|
int len = strlen(name);
|
|
SPEW((GROUP_ADEPT_RESOURCE, " %s", name));
|
|
our_stream.AdvancePointer(len+1);
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
dep_record.m_length = 0;
|
|
dep_record.m_data = NULL;
|
|
}
|
|
dep_record.m_record = NULL;
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Rewind the stream, and set the record data pointers to look at the
|
|
// given stream
|
|
//-------------------------------------------------------------------
|
|
//
|
|
if (stream)
|
|
{
|
|
Check_Object(stream);
|
|
stream->Rewind();
|
|
m_handle.m_data = stream->GetPointer();
|
|
m_handle.m_length = stream->GetSize();
|
|
}
|
|
else
|
|
{
|
|
m_handle.m_data = NULL;
|
|
m_handle.m_length = 0;
|
|
}
|
|
Verify(m_handle.m_databaseHandle);
|
|
Verify(m_ID.m_fileID != ResourceID::Null.m_fileID);
|
|
|
|
//
|
|
//--------------------------------------------------
|
|
// If the data was already there, replace the record
|
|
//--------------------------------------------------
|
|
//
|
|
if (m_handle.m_record)
|
|
{
|
|
Verify(m_handle.m_ID == m_ID.m_recordID);
|
|
m_handle.Replace();
|
|
Verify(m_handle.m_ID == m_ID.m_recordID);
|
|
if (dep_data)
|
|
{
|
|
dep_data->m_ID = m_ID.m_recordID;
|
|
dep_data->FindID(true);
|
|
dep_record.m_length =
|
|
dependencies->m_fileNameStream.GetBytesUsed();
|
|
Verify(dep_record.m_length > 0);
|
|
BYTE *data =
|
|
static_cast<BYTE*>(dependencies->m_fileNameStream.GetPointer()) - dep_record.m_length;
|
|
dep_record.m_data = data;
|
|
dep_data->Replace();
|
|
Verify(dep_data->m_ID == m_ID.m_recordID);
|
|
Verify(dep_data->m_record);
|
|
}
|
|
}
|
|
|
|
//
|
|
//----------------------------
|
|
// Otherwise, add a new record
|
|
//----------------------------
|
|
//
|
|
else
|
|
{
|
|
m_handle.Add();
|
|
m_ID.m_recordID = m_handle.m_ID;
|
|
if (dep_data)
|
|
{
|
|
dep_data->Add();
|
|
Verify(m_ID.m_recordID == dep_data->m_ID);
|
|
Verify(dep_data->m_record != NULL);
|
|
}
|
|
}
|
|
|
|
//
|
|
//------------------------------------------------------------------
|
|
// Now, point the resource stream at the database's copy of the data
|
|
//------------------------------------------------------------------
|
|
//
|
|
streamStart = currentPosition = (BYTE*)(m_handle.m_data);
|
|
streamSize = m_handle.m_length;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void Resource::ChangeName(const char* name)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(name);
|
|
Verify(name[1] != ':');
|
|
|
|
//
|
|
//------------------------------------
|
|
// Make sure the name is tool-friendly
|
|
//------------------------------------
|
|
//
|
|
name = Tool::GetToolFileName(name);
|
|
m_handle.m_name = name;
|
|
|
|
//
|
|
//----------------------------------
|
|
// Should we deal with dependencies?
|
|
//----------------------------------
|
|
//
|
|
ResourceFile *resource_file =
|
|
ResourceManager::Instance->GetResourceFile(m_ID.m_fileID);
|
|
Check_Object(resource_file);
|
|
RecordHandle dep_record, *dep_data=NULL;
|
|
if (resource_file->m_dependencyHandle)
|
|
{
|
|
|
|
//
|
|
//---------------------------------
|
|
// Build the dependency data record
|
|
//---------------------------------
|
|
//
|
|
dep_data = &dep_record;
|
|
dep_record.m_databaseHandle = resource_file->m_dependencyHandle;
|
|
dep_record.m_ID = m_handle.m_ID;
|
|
#if defined(_ARMOR)
|
|
bool result =
|
|
#endif
|
|
dep_record.FindID(false);
|
|
dep_record.m_name = name;
|
|
dep_record.m_data = NULL;
|
|
dep_record.m_length = 0;
|
|
Verify(result);
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Rewind the stream, and set the record data pointers to look at the
|
|
// given stream
|
|
//-------------------------------------------------------------------
|
|
//
|
|
Verify(m_handle.m_databaseHandle);
|
|
Verify(m_ID.m_fileID != ResourceID::Null.m_fileID);
|
|
|
|
//
|
|
//--------------------------------------------------
|
|
// If the data was already there, replace the record
|
|
//--------------------------------------------------
|
|
//
|
|
Verify(m_handle.m_ID == m_ID.m_recordID);
|
|
m_handle.Replace();
|
|
Verify(m_handle.m_ID == m_ID.m_recordID);
|
|
if (dep_data)
|
|
{
|
|
dep_data->Replace();
|
|
Verify(dep_data->m_ID == m_ID.m_recordID);
|
|
Verify(dep_data->m_record);
|
|
}
|
|
|
|
//
|
|
//------------------------------------------------------------------
|
|
// Now, point the resource stream at the database's copy of the data
|
|
//------------------------------------------------------------------
|
|
//
|
|
streamStart = currentPosition = (BYTE*)(m_handle.m_data);
|
|
streamSize = m_handle.m_length;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void Resource::AddFileDependenciesTo(Stuff::FileDependencies *dependencies)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(dependencies);
|
|
Verify(m_handle.m_databaseHandle);
|
|
Verify(m_handle.m_record);
|
|
Verify(!IsRegistered());
|
|
|
|
//
|
|
//-----------------------------------
|
|
// Get the file dependencies database
|
|
//-----------------------------------
|
|
//
|
|
Check_Object(ResourceManager::Instance);
|
|
ResourceFile *resource_file =
|
|
ResourceManager::Instance->GetResourceFile(m_ID.m_fileID);
|
|
Check_Object(resource_file);
|
|
Verify(resource_file->m_dependencyHandle);
|
|
TableIteratorOf<ResourceFile*, short> files(&ResourceManager::Instance->m_openedFiles);
|
|
files.Last();
|
|
if (files.GetCurrent() != resource_file)
|
|
PAUSE((
|
|
"%d:%d (%s) needs to be in a .build file!",
|
|
m_ID.m_fileID,
|
|
m_ID.m_recordID,
|
|
m_handle.m_name
|
|
));
|
|
|
|
//
|
|
//-------------------------------------------
|
|
// Find our file info, and add it to the list
|
|
//-------------------------------------------
|
|
//
|
|
RecordHandle dep_record = m_handle;
|
|
Verify(dep_record.m_ID == m_ID.m_recordID);
|
|
dep_record.m_databaseHandle = resource_file->m_dependencyHandle;
|
|
dep_record.FindID(true);
|
|
MemoryStream
|
|
our_stream((BYTE*)(dep_record.m_data), dep_record.m_length);
|
|
dependencies->AddDependencies(&our_stream);
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void Resource::GetFileDependencies(Stuff::FileDependencies *dependencies)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(dependencies);
|
|
Verify(m_handle.m_databaseHandle);
|
|
Verify(m_handle.m_record);
|
|
|
|
//
|
|
//-----------------------------------
|
|
// Get the file dependencies database
|
|
//-----------------------------------
|
|
//
|
|
Check_Object(ResourceManager::Instance);
|
|
ResourceFile *resource_file =
|
|
ResourceManager::Instance->GetResourceFile(m_ID.m_fileID);
|
|
Check_Object(resource_file);
|
|
Verify(resource_file->m_dependencyHandle);
|
|
TableIteratorOf<ResourceFile*, short> files(&ResourceManager::Instance->m_openedFiles);
|
|
files.Last();
|
|
|
|
//
|
|
//-------------------------------------------
|
|
// Find our file info, and add it to the list
|
|
//-------------------------------------------
|
|
//
|
|
RecordHandle dep_record = m_handle;
|
|
Verify(dep_record.m_ID == m_ID.m_recordID);
|
|
dep_record.m_databaseHandle = resource_file->m_dependencyHandle;
|
|
dep_record.FindID(true);
|
|
MemoryStream
|
|
our_stream((BYTE*)(dep_record.m_data), dep_record.m_length);
|
|
dependencies->AddDependencies(&our_stream);
|
|
}
|
|
|
|
//#############################################################################
|
|
//############################ ResourceFile #############################
|
|
//#############################################################################
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
ResourceFile::~ResourceFile()
|
|
{
|
|
Check_Object(this);
|
|
|
|
//
|
|
//-----------------------
|
|
// Close the opened files
|
|
//-----------------------
|
|
//
|
|
Check_Object(m_fileHandle);
|
|
delete m_fileHandle;
|
|
if (m_dependencyHandle)
|
|
{
|
|
Check_Object(m_dependencyHandle);
|
|
delete m_dependencyHandle;
|
|
}
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void ResourceFile::Save()
|
|
{
|
|
Check_Object(this);
|
|
|
|
//
|
|
//-----------------------
|
|
// Close the opened files
|
|
//-----------------------
|
|
//
|
|
Check_Object(m_fileHandle);
|
|
m_fileHandle->Save();
|
|
if (m_dependencyHandle)
|
|
{
|
|
Check_Object(m_dependencyHandle);
|
|
m_dependencyHandle->Save();
|
|
}
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
__int64 ResourceFile::CalculateCRC(int core_key)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(m_fileHandle);
|
|
return m_fileHandle->CalculateCRC(core_key);
|
|
};
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void ResourceFile::ScatterSave()
|
|
{
|
|
Check_Object(this);
|
|
|
|
//
|
|
//-----------------------
|
|
// Close the opened files
|
|
//-----------------------
|
|
//
|
|
Check_Object(m_fileHandle);
|
|
m_fileHandle->ScatterSave();
|
|
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void ResourceFile::SaveAs(const char* filename)
|
|
{
|
|
Check_Object(this);
|
|
|
|
//
|
|
//-----------------------
|
|
// Close the opened files
|
|
//-----------------------
|
|
//
|
|
Check_Object(m_fileHandle);
|
|
m_fileHandle->SaveAs(filename);
|
|
Verify(!m_dependencyHandle);
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void ResourceFile::UnloadRecordData()
|
|
{
|
|
Check_Object(this);
|
|
|
|
m_fileHandle->UnloadRecords();
|
|
if (m_dependencyHandle)
|
|
{
|
|
Check_Object(m_dependencyHandle);
|
|
m_dependencyHandle->UnloadRecords();
|
|
}
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void ResourceFile::SetLastRegisteredResourceID(const ResourceID &res_id)
|
|
{
|
|
Check_Object(this);
|
|
Verify(res_id.GetFileID() == m_fileID);
|
|
m_lastRegisteredRecordID = res_id.GetRecordID();
|
|
}
|
|
|
|
//#############################################################################
|
|
//########################### ResourceManager ###########################
|
|
//#############################################################################
|
|
|
|
ResourceManager*
|
|
ResourceManager::Instance = NULL;
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
ResourceManager::ResourceManager():
|
|
Plug(DefaultData),
|
|
m_openedFiles(NULL, true),
|
|
m_nonCoreFiles(NULL)
|
|
{
|
|
m_nextResourceFileID = 0;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
ResourceManager::~ResourceManager()
|
|
{
|
|
Check_Object(this);
|
|
|
|
//
|
|
//-----------------------
|
|
// Close the opened files
|
|
//-----------------------
|
|
//
|
|
TableIteratorOf<ResourceFile*,short> files(&m_openedFiles);
|
|
ResourceFile *file;
|
|
while ((file = files.ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(file);
|
|
delete file;
|
|
}
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void ResourceManager::CloseAllButCore()
|
|
{
|
|
//
|
|
//-------------------------
|
|
// Close the non-core files
|
|
//-------------------------
|
|
//
|
|
ChainIteratorOf<ResourceFile*> files(&m_nonCoreFiles);
|
|
ResourceFile *file;
|
|
while ((file = files.ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(file);
|
|
if(file->DoesCloseOnCloseAll())
|
|
delete file;
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------------------
|
|
// Now step through all the core files and unload their records
|
|
//-------------------------------------------------------------
|
|
//
|
|
TableIteratorOf<ResourceFile*,short> core_files(&m_openedFiles);
|
|
while ((file = core_files.ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(file);
|
|
file->UnloadRecordData();
|
|
}
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void ResourceManager::SpewLoadedResources()
|
|
{
|
|
//
|
|
//-----------------------
|
|
// Close the opened files
|
|
//-----------------------
|
|
//
|
|
TableIteratorOf<ResourceFile*,short> files(&m_openedFiles);
|
|
ResourceFile *file;
|
|
while ((file = files.ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(file);
|
|
file->m_fileHandle->SpewLoadedRecords();
|
|
}
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
short ResourceManager::FindOpenResourceID()
|
|
{
|
|
|
|
// start all custom mechs at 10
|
|
for (short i = 20; i < Maximum_Players+20; ++i)
|
|
{
|
|
if (!m_openedFiles.Find(i))
|
|
return i;
|
|
}
|
|
|
|
STOP(("No open resources"));
|
|
return -1;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
ResourceFile* ResourceManager::OpenResourceFile(
|
|
const char *file_name,
|
|
const char *dep_file,
|
|
short file_ID,
|
|
DWORD content_version,
|
|
bool core,
|
|
bool overwrite,
|
|
bool close_on_close_all
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(file_name);
|
|
Verify(strlen(file_name) > 0);
|
|
Verify(!m_openedFiles.Find(file_ID));
|
|
|
|
//
|
|
//-------------------------------------
|
|
// Erase the file if we are overwriting
|
|
//-------------------------------------
|
|
//
|
|
if (overwrite)
|
|
{
|
|
gos_DeleteFile(file_name);
|
|
gos_DeleteFile(dep_file);
|
|
}
|
|
bool build = dep_file != NULL;
|
|
|
|
//
|
|
//-------------------------------
|
|
// Open up the new resource files
|
|
//-------------------------------
|
|
//
|
|
ResourceFile *file =
|
|
new ResourceFile(
|
|
new DatabaseHandle(file_name, !overwrite, content_version),
|
|
(build) ? new DatabaseHandle(dep_file, !overwrite, content_version) : NULL,
|
|
file_ID,
|
|
close_on_close_all
|
|
);
|
|
Register_Object(file);
|
|
Verify(file->m_fileHandle != 0);
|
|
m_openedFiles.AddValue(file, file_ID);
|
|
|
|
//
|
|
//------------------------------------------------
|
|
// If this is a core file, hook it up to the chain
|
|
//------------------------------------------------
|
|
//
|
|
if (!core)
|
|
m_nonCoreFiles.Add(file);
|
|
return file;
|
|
}
|
|
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
ResourceFile* ResourceManager::OpenResourceFile(
|
|
MemoryStream *stream,
|
|
const char *file_name,
|
|
const char *dep_file,
|
|
short file_ID,
|
|
DWORD content_version,
|
|
bool core,
|
|
bool close_on_close_all
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(file_name);
|
|
Verify(strlen(file_name) > 0);
|
|
Verify(!m_openedFiles.Find(file_ID));
|
|
|
|
|
|
bool build = dep_file != NULL;
|
|
|
|
//
|
|
//-------------------------------
|
|
// Open up the new resource files
|
|
//-------------------------------
|
|
//
|
|
ResourceFile *file =
|
|
new ResourceFile(
|
|
new DatabaseHandle(file_name, stream, content_version),
|
|
(build) ? new DatabaseHandle(dep_file, stream, content_version) : NULL,
|
|
file_ID,
|
|
close_on_close_all
|
|
);
|
|
Register_Object(file);
|
|
Verify(file->m_fileHandle != 0);
|
|
m_openedFiles.AddValue(file, file_ID);
|
|
|
|
//
|
|
//------------------------------------------------
|
|
// If this is a core file, hook it up to the chain
|
|
//------------------------------------------------
|
|
//
|
|
if (!core)
|
|
m_nonCoreFiles.Add(file);
|
|
return file;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
ResourceFile* ResourceManager::OpenResourceFile(
|
|
Stuff::DatabaseHandle *database,
|
|
short file_ID,
|
|
bool core,
|
|
bool close_on_close_all
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(database);
|
|
Verify(!m_openedFiles.Find(file_ID));
|
|
|
|
//
|
|
//-------------------------------
|
|
// Open up the new resource files
|
|
//-------------------------------
|
|
//
|
|
ResourceFile *file = new ResourceFile(database, NULL, file_ID, close_on_close_all);
|
|
Register_Object(file);
|
|
Verify(file->m_fileHandle != 0);
|
|
m_openedFiles.AddValue(file, file_ID);
|
|
|
|
//
|
|
//------------------------------------------------
|
|
// If this is a core file, hook it up to the chain
|
|
//------------------------------------------------
|
|
//
|
|
if (!core)
|
|
m_nonCoreFiles.Add(file);
|
|
return file;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
ResourceFile* ResourceManager::OpenResourceFile(
|
|
Stuff::DatabaseHandle *database,
|
|
const char *dep_file,
|
|
short file_ID,
|
|
DWORD content_version,
|
|
bool core,
|
|
bool overwrite,
|
|
bool close_on_close_all
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(database);
|
|
Verify(!m_openedFiles.Find(file_ID));
|
|
|
|
//
|
|
//-------------------------------------
|
|
// Erase the file if we are overwriting
|
|
//-------------------------------------
|
|
//
|
|
if (overwrite)
|
|
{
|
|
gos_DeleteFile(dep_file);
|
|
}
|
|
|
|
//
|
|
//-------------------------------
|
|
// Open up the new resource files
|
|
//-------------------------------
|
|
//
|
|
ResourceFile *file = new ResourceFile(database, new DatabaseHandle(dep_file, false, content_version), file_ID, close_on_close_all);
|
|
Register_Object(file);
|
|
Verify(file->m_fileHandle != 0);
|
|
m_openedFiles.AddValue(file, file_ID);
|
|
|
|
//
|
|
//------------------------------------------------
|
|
// If this is a core file, hook it up to the chain
|
|
//------------------------------------------------
|
|
//
|
|
if (!core)
|
|
m_nonCoreFiles.Add(file);
|
|
return file;
|
|
}
|