ALERROR CDesignCollection::LoadExtensionDesc (SDesignLoadCtx &Ctx, CXMLElement *pDesc, bool bDefaultResource, SExtensionDesc **retpExtension)

//	LoadExtensionDesc
//
//	Loads a new extension descriptor

	{
	ALERROR error;
	int i;

	//	Load version

	DWORD dwVersion = ::LoadExtensionVersion(pDesc->GetAttribute(VERSION_ATTRIB));
	if (dwVersion == 0)
		{
		Ctx.sError = strPatternSubst(CONSTLIT("Unable to load extension: incompatible version: %s"), pDesc->GetAttribute(VERSION_ATTRIB));
		return ERR_FAIL;
		}

	//	Load UNID

	DWORD dwUNID = pDesc->GetAttributeInteger(UNID_ATTRIB);

	//	See if this is registered
	//	LATER: For now, this is hard-coded

	bool bIsRegistered = (dwUNID == 0x00300000) 
			|| (dwUNID == 0x00200000)
			|| ((dwUNID & 0xF0000000) == 0xA0000000);

	//	Make sure that unregistered extensions are in the correct ranage

	if (!bIsRegistered)
		{
		DWORD dwDomain = (dwUNID & 0xF0000000);
		if (dwDomain < 0xA0000000 || dwDomain > 0xEFFFFFFF)
			{
			Ctx.sError = strPatternSubst(CONSTLIT("Invalid extension UNID: %x"), dwUNID);
			return ERR_FAIL;
			}
		}

	//	Create structure

	SExtensionDesc *pEntry;
	if (error = AddExtension(Ctx, extExtension, dwUNID, bDefaultResource, &pEntry))
		return error;

	pEntry->dwVersion = dwVersion;
	pEntry->bRegistered = bIsRegistered;
	pEntry->bEnabled = true;
	pEntry->bDebugOnly = pDesc->GetAttributeBool(DEBUG_ONLY_ATTRIB);

	//	Load name

	pEntry->sName = pDesc->GetAttribute(NAME_ATTRIB);
	if (pEntry->sName.IsBlank())
		pEntry->sName = strPatternSubst(CONSTLIT("Extension %x"), dwUNID);

	//	Load credits (we parse them into a string array)

	CString sCredits = pDesc->GetAttribute(CREDITS_ATTRIB);
	if (!sCredits.IsBlank())
		strDelimitEx(sCredits, ';', DELIMIT_TRIM_WHITESPACE, 0, &pEntry->Credits);

	//	Load extends attrib

	CString sExtends = pDesc->GetAttribute(EXTENDS_ATTRIB);
	if (!sExtends.IsBlank())
		{
		TArray<CString> Extends;
		strDelimitEx(sExtends, ';', DELIMIT_TRIM_WHITESPACE, 0, &Extends);
		for (i = 0; i < Extends.GetCount(); i++)
			{
			DWORD dwUNID = strToInt(Extends[i], INVALID_UNID);
			if (dwUNID != INVALID_UNID)
				pEntry->Extends.Insert(dwUNID);
			}
		}

	//	If we're an extension in the default resource, load modules

	if (bDefaultResource)
		{
		CXMLElement *pModules = pDesc->GetContentElementByTag(MODULES_TAG);
		if (pModules)
			{
			for (i = 0; i < pModules->GetContentElementCount(); i++)
				{
				CXMLElement *pModule = pModules->GetContentElement(i);
				CString sModule = pModule->GetAttribute(FILENAME_ATTRIB);
				if (!sModule.IsBlank())
					pEntry->Modules.Insert(sModule);
				}
			}
		}

	//	Done

	*retpExtension = pEntry;

	return NOERROR;
	}
Beispiel #2
0
void CreateTDB (const CString &sInputFilespec, CXMLElement *pCmdLine)
	{
	ALERROR error;
	CString sError;
	int i;

	//	Prepare a context block

	CTDBCompiler Ctx;

	//	Figure out the output filespec

	CString sOutputFilespec = pCmdLine->GetAttribute(ATTRIB_OUTPUT);
	if (sOutputFilespec.IsBlank() && !sInputFilespec.IsBlank())
		sOutputFilespec = strPatternSubst(CONSTLIT("%s.tdb"), pathStripExtension(pathGetFilename(sInputFilespec)));

	//	Optional entities file.

	CString sEntities = pCmdLine->GetAttribute(ATTRIB_ENTITIES);
	TArray<CString> EntityFilespecs;
	if (strDelimitEx(sEntities, ',', DELIMIT_TRIM_WHITESPACE, 0, &EntityFilespecs) != NOERROR)
		{
		printf("error : Unable to parse list of entity filespecs.\n");
		return;
		}

	//	Initialize our compiler.

	if (!Ctx.Init(sInputFilespec, sOutputFilespec, EntityFilespecs, pCmdLine, &sError))
		{
		printf("error: %s.\n", sError.GetASCIIZPointer());
		return;
		}

	//	Create the output file

	if (error = CDataFile::Create(sOutputFilespec, 4096, 0))
		{
		printf("error : Unable to create '%s'\n", sOutputFilespec.GetASCIIZPointer());
		return;
		}

	CDataFile Out(sOutputFilespec);
	if (error = Out.Open())
		{
		printf("error : Unable to open '%s'\n", sOutputFilespec.GetASCIIZPointer());
		return;
		}

	//	Write out the main module and recurse

	int iGameFile;
	if (error = WriteModule(Ctx, pathGetFilename(sInputFilespec), NULL_STR, Out, &iGameFile))
		goto Done;

	//	Write out the header

	if (error = WriteHeader(Ctx, iGameFile, Out))
		goto Done;

	//	Done with the file

	Out.Close();

	//	If necessary create a digest

	if (pCmdLine->GetAttributeBool(ATTRIB_DIGEST))
		{
		CIntegerIP Digest;

		if (fileCreateDigest(sOutputFilespec, &Digest) != NOERROR)
			{
			Ctx.ReportError(strPatternSubst(CONSTLIT("Unable to create digest for '%s'."), sOutputFilespec));
			goto Done;
			}

		//	Output C++ style constant

		printf("\nstatic BYTE g_Digest[] =\n\t{");

		BYTE *pDigest = Digest.GetBytes();
		for (i = 0; i < Digest.GetLength(); i++)
			{
			if ((i % 10) == 0)
				printf("\n\t");

			printf("%3d, ", (DWORD)pDigest[i]);
			}
			
		printf("\n\t};\n");
		}

Done:

	Ctx.ReportErrorCount();
	}
Beispiel #3
0
ALERROR CExtension::CreateExtensionFromRoot (const CString &sFilespec, CXMLElement *pDesc, EFolderTypes iFolder, CExternalEntityTable *pEntities, DWORD dwInheritAPIVersion, CExtension **retpExtension, CString *retsError)

//	CreateExtension
//
//	Loads the given extension or adventure. We take ownership of pEntities.

	{
	int i;

	//	Create an extension object

	CExtension *pExtension = new CExtension;
	pExtension->m_sFilespec = sFilespec;
	pExtension->m_dwUNID = pDesc->GetAttributeInteger(UNID_ATTRIB);
	if (pExtension->m_dwUNID == 0)
		{
		delete pExtension;
		*retsError = CONSTLIT("Invalid UNID.");
		return ERR_FAIL;
		}

	if (strEquals(pDesc->GetTag(), TRANSCENDENCE_ADVENTURE_TAG))
		{
		pExtension->m_iGame = gameTranscendence;
		pExtension->m_iType = extAdventure;
		}
	else if (strEquals(pDesc->GetTag(), TRANSCENDENCE_LIBRARY_TAG))
		{
		pExtension->m_iGame = gameTranscendence;
		pExtension->m_iType = extLibrary;
		}
	else if (strEquals(pDesc->GetTag(), TRANSCENDENCE_EXTENSION_TAG))
		{
		pExtension->m_iGame = gameTranscendence;
		pExtension->m_iType = extExtension;
		}
	else if (strEquals(pDesc->GetTag(), CORE_LIBRARY_TAG))
		{
		//	For core libraries, we don't care what game it is. It's always 
		//	whatever game the base file is.

		pExtension->m_iGame = gameUnknown;
		pExtension->m_iType = extLibrary;
		}
	else
		{
		delete pExtension;
		*retsError = strPatternSubst(CONSTLIT("Unknown root element: %s"), pDesc->GetTag());
		return ERR_FAIL;
		}
	
	pExtension->m_iLoadState = loadEntities;
	pExtension->m_iFolderType = iFolder;
	pExtension->m_pEntities = pEntities;
	pExtension->m_ModifiedTime = fileGetModifiedTime(sFilespec);
	pExtension->m_bDebugOnly = pDesc->GetAttributeBool(DEBUG_ONLY_ATTRIB);
	pExtension->m_bRegistered = IsRegisteredUNID(pExtension->m_dwUNID);
	pExtension->m_bPrivate = pDesc->GetAttributeBool(PRIVATE_ATTRIB);
	pExtension->m_bAutoInclude = pDesc->GetAttributeBool(AUTO_INCLUDE_ATTRIB);
	pExtension->m_bUsesXML = pDesc->GetAttributeBool(USES_XML_ATTRIB);

	//	API version

	CString sAPIVersion;
	if (pDesc->FindAttribute(API_VERSION_ATTRIB, &sAPIVersion))
		{
		pExtension->m_dwAPIVersion = (DWORD)strToInt(sAPIVersion, 0);
		if (pExtension->m_dwAPIVersion < 12)
			pExtension->m_dwAPIVersion = 0;
		pExtension->m_sVersion = pDesc->GetAttribute(VERSION_ATTRIB);
		}
	else if (dwInheritAPIVersion)
		{
		pExtension->m_dwAPIVersion = dwInheritAPIVersion;
		pExtension->m_sVersion = pDesc->GetAttribute(VERSION_ATTRIB);
		}
	else
		{
		sAPIVersion = pDesc->GetAttribute(VERSION_ATTRIB);
		pExtension->m_dwAPIVersion = ::LoadExtensionVersion(sAPIVersion);
		}

	if (pExtension->m_dwAPIVersion == 0)
		{
		pExtension->m_pEntities = NULL;	//	Let our parent clean up.
		delete pExtension;
		*retsError = strPatternSubst(CONSTLIT("Unable to load extension: incompatible version: %s"), sAPIVersion);
		return ERR_FAIL;
		}

	//	If this is a later version, then disabled it

	if (pExtension->m_dwAPIVersion > API_VERSION)
		pExtension->SetDisabled(CONSTLIT("Requires a newer version of Transcendence.exe"));

	//	Release

	pExtension->m_dwRelease = pDesc->GetAttributeInteger(RELEASE_ATTRIB);

	//	Registered extensions default to release 1.

	if (pExtension->m_dwRelease == 0 && iFolder == folderCollection)
		pExtension->m_dwRelease = 1;

	//	Name

	pExtension->m_sName = pDesc->GetAttribute(NAME_ATTRIB);
	if (pExtension->m_sName.IsBlank())
		pExtension->m_sName = strPatternSubst(CONSTLIT("Extension %x"), pExtension->m_dwUNID);

	//	Image

	pExtension->m_dwCoverUNID = (DWORD)pDesc->GetAttributeInteger(COVER_IMAGE_UNID_ATTRIB);

	//	Load credits (we parse them into a string array)

	CString sCredits = pDesc->GetAttribute(CREDITS_ATTRIB);
	if (!sCredits.IsBlank())
		strDelimitEx(sCredits, ';', DELIMIT_TRIM_WHITESPACE, 0, &pExtension->m_Credits);

	//	Load extends attrib

	CString sExtends = pDesc->GetAttribute(EXTENDS_ATTRIB);
	if (!sExtends.IsBlank())
		{
		TArray<CString> Extends;
		strDelimitEx(sExtends, ';', DELIMIT_TRIM_WHITESPACE, 0, &Extends);
		for (i = 0; i < Extends.GetCount(); i++)
			{
			DWORD dwUNID = strToInt(Extends[i], INVALID_UNID);
			if (dwUNID != INVALID_UNID)
				pExtension->m_Extends.Insert(dwUNID);
			}
		}

	//	Other options

	pExtension->m_dwAutoIncludeAPIVersion = (DWORD)pDesc->GetAttributeIntegerBounded(AUTO_INCLUDE_FOR_COMPATIBILITY_ATTRIB, 0, -1, 0);

	//	Done

	*retpExtension = pExtension;

	return NOERROR;
	}