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; }
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(); }
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; }