예제 #1
0
/* ArchiveManager::addArchive
 * Adds an archive to the archive list
 *******************************************************************/
bool ArchiveManager::addArchive(Archive* archive)
{
	// Only add if archive is a valid pointer
	if (archive)
	{
		// Add to the list
		archive_t n_archive;
		n_archive.archive = archive;
		n_archive.resource = true;
		open_archives.push_back(n_archive);

		// Listen to the archive
		listenTo(archive);

		// Announce the addition
		announce("archive_added");

		// Add to resource manager
		theResourceManager->addArchive(archive);

		// ZDoom also loads any WADs found in the root of a PK3 or directory
		if ((archive->getType() == ARCHIVE_ZIP || archive->getType() == ARCHIVE_FOLDER) && auto_open_wads_root)
		{
			ArchiveTreeNode* root = archive->getRoot();
			ArchiveEntry* entry;
			EntryType* type;
			for (unsigned a = 0; a < root->numEntries(); a++)
			{
				entry = root->getEntry(a);

				if (entry->getType() == EntryType::unknownType())
					EntryType::detectEntryType(entry);

				type = entry->getType();

				if (type->getId() == "wad")
					// First true: yes, manage this
					// Second true: open silently, don't open a tab for it
					openArchive(entry, true, true);
			}
		}

		return true;
	}
	else
		return false;
}
예제 #2
0
/* EntryOperations::setGfxOffsets
 * Changes the offsets of the given gfx entry. Returns false if the
 * entry is invalid or not an offset-supported format, true otherwise
 *******************************************************************/
bool EntryOperations::setGfxOffsets(ArchiveEntry* entry, int x, int y)
{
	if (entry == NULL || entry->getType() == NULL)
		return false;

	// Check entry type
	EntryType* type = entry->getType();
	string entryformat = type->getFormat();
	if (!(entryformat == "img_doom" || entryformat == "img_doom_arah" ||
		entryformat == "img_doom_alpha" || entryformat == "img_doom_beta" ||
		entryformat == "img_png"))
	{
		wxLogMessage("Entry \"%s\" is of type \"%s\" which does not support offsets", entry->getName(), entry->getType()->getName());
		return false;
	}

	// Doom gfx format, normal and beta version.
	// Also arah format from alpha 0.2 because it uses the same header format.
	if (entryformat == "img_doom" || entryformat == "img_doom_beta" || entryformat == "image_doom_arah")
	{
		// Get patch header
		patch_header_t header;
		entry->seek(0, SEEK_SET);
		entry->read(&header, 8);

		// Apply new offsets
		header.left = wxINT16_SWAP_ON_BE((int16_t)x);
		header.top = wxINT16_SWAP_ON_BE((int16_t)y);

		// Write new header to entry
		entry->seek(0, SEEK_SET);
		entry->write(&header, 8);
	}

	// Doom alpha gfx format
	else if (entryformat == "img_doom_alpha")
	{
		// Get patch header
		entry->seek(0, SEEK_SET);
		oldpatch_header_t header;
		entry->read(&header, 4);

		// Apply new offsets
		header.left = (int8_t)x;
		header.top = (int8_t)y;

		// Write new header to entry
		entry->seek(0, SEEK_SET);
		entry->write(&header, 4);
	}

	// PNG format
	else if (entryformat == "img_png")
	{
		// Find existing grAb chunk
		const uint8_t* data = entry->getData(true);
		uint32_t grab_start = 0;
		for (uint32_t a = 0; a < entry->getSize(); a++)
		{
			// Check for 'grAb' header
			if (data[a] == 'g' && data[a + 1] == 'r' &&
				data[a + 2] == 'A' && data[a + 3] == 'b')
			{
				grab_start = a - 4;
				break;
			}

			// Stop when we get to the 'IDAT' chunk
			if (data[a] == 'I' && data[a + 1] == 'D' &&
				data[a + 2] == 'A' && data[a + 3] == 'T')
				break;
		}

		// Create new grAb chunk
		uint32_t csize = wxUINT32_SWAP_ON_LE(8);
		grab_chunk_t gc ={ { 'g', 'r', 'A', 'b' }, wxINT32_SWAP_ON_LE(x), wxINT32_SWAP_ON_LE(y) };
		uint32_t dcrc = wxUINT32_SWAP_ON_LE(Misc::crc((uint8_t*)&gc, 12));

		// Build new PNG from the original w/ the new grAb chunk
		MemChunk npng;
		uint32_t rest_start = 33;

		// Init new png data size
		if (grab_start == 0)
			npng.reSize(entry->getSize() + 20);
		else
			npng.reSize(entry->getSize());

		// Write PNG header and IHDR chunk
		npng.write(data, 33);

		// If no existing grAb chunk was found, write new one here
		if (grab_start == 0)
		{
			npng.write(&csize, 4);
			npng.write(&gc, 12);
			npng.write(&dcrc, 4);
		}
		else
		{
			// Otherwise write any other data before the existing grAb chunk
			uint32_t to_write = grab_start - 33;
			npng.write(data + 33, to_write);
			rest_start = grab_start + 20;

			// And now write the new grAb chunk
			npng.write(&csize, 4);
			npng.write(&gc, 12);
			npng.write(&dcrc, 4);
		}

		// Write the rest of the PNG data
		uint32_t to_write = entry->getSize() - rest_start;
		npng.write(data + rest_start, to_write);

		// Load new png data to the entry
		entry->importMemChunk(npng);

		// Set its type back to png
		entry->setType(type);
	}
	else
		return false;

	return true;
}
예제 #3
0
/* EntryType::loadEntryTypes
 * Loads all built-in and custom user entry types
 *******************************************************************/
bool EntryType::loadEntryTypes()
{
	EntryDataFormat* fmt_any = EntryDataFormat::anyFormat();

	// Setup unknown type
	etype_unknown.format = fmt_any;
	etype_unknown.icon = "e_unknown";
	etype_unknown.detectable = false;
	etype_unknown.reliability = 0;
	etype_unknown.addToList();

	// Setup folder type
	etype_folder.format = fmt_any;
	etype_folder.icon = "e_folder";
	etype_folder.name = "Folder";
	etype_folder.detectable = false;
	etype_folder.addToList();

	// Setup marker type
	etype_marker.format = fmt_any;
	etype_marker.icon = "e_marker";
	etype_marker.name = "Marker";
	etype_marker.detectable = false;
	etype_marker.category = "";		// No category, markers only appear when 'All' categories shown
	etype_marker.addToList();

	// Setup map marker type
	etype_map.format = fmt_any;
	etype_map.icon = "e_map";
	etype_map.name = "Map Marker";
	etype_map.category = "Maps";	// Should appear with maps
	etype_map.detectable = false;
	etype_map.colour = rgba_t(0, 255, 0);
	etype_map.addToList();

	// -------- READ BUILT-IN TYPES ---------

	// Get builtin entry types from resource archive
	Archive* res_archive = theArchiveManager->programResourceArchive();

	// Check resource archive exists
	if (!res_archive)
	{
		wxLogMessage("Error: No resource archive open!");
		return false;
	}

	// Get entry types directory
	ArchiveTreeNode* et_dir = res_archive->getDir("config/entry_types/");

	// Check it exists
	if (!et_dir)
	{
		wxLogMessage("Error: config/entry_types does not exist in slade.pk3");
		return false;
	}

	// Read in each file in the directory
	bool etypes_read = false;
	for (unsigned a = 0; a < et_dir->numEntries(); a++)
	{
		if (readEntryTypeDefinition(et_dir->getEntry(a)->getMCData()))
			etypes_read = true;
	}

	// Warn if no types were read (this shouldn't happen unless the resource archive is corrupted)
	if (!etypes_read)
		wxLogMessage("Warning: No built-in entry types could be loaded from slade.pk3");

	// -------- READ CUSTOM TYPES ---------

	// If the directory doesn't exist create it
	if (!wxDirExists(appPath("entry_types", DIR_USER)))
		wxMkdir(appPath("entry_types", DIR_USER));

	// Open the custom palettes directory
	wxDir res_dir;
	res_dir.Open(appPath("entry_types", DIR_USER));

	// Go through each file in the directory
	string filename = wxEmptyString;
	bool files = res_dir.GetFirst(&filename, wxEmptyString, wxDIR_FILES);
	while (files)
	{
		// Load file data
		MemChunk mc;
		mc.importFile(res_dir.GetName() + "/" + filename);

		// Parse file
		readEntryTypeDefinition(mc);

		// Next file
		files = res_dir.GetNext(&filename);
	}

	return true;
}
예제 #4
0
/* EntryType::readEntryTypeDefinition
 * Reads in a block of entry type definitions. Returns false if there
 * was a parsing error, true otherwise
 *******************************************************************/
bool EntryType::readEntryTypeDefinition(MemChunk& mc)
{
	// Parse the definition
	Parser p;
	p.parseText(mc);

	// Get entry_types tree
	ParseTreeNode* pt_etypes = (ParseTreeNode*)(p.parseTreeRoot()->getChild("entry_types"));

	// Check it exists
	if (!pt_etypes)
		return false;

	// Go through all parsed types
	for (unsigned a = 0; a < pt_etypes->nChildren(); a++)
	{
		// Get child as ParseTreeNode
		ParseTreeNode* typenode = (ParseTreeNode*)pt_etypes->getChild(a);

		// Create new entry type
		EntryType* ntype = new EntryType(typenode->getName().Lower());

		// Copy from existing type if inherited
		if (!typenode->getInherit().IsEmpty())
		{
			EntryType* parent_type = EntryType::getType(typenode->getInherit().Lower());

			if (parent_type != EntryType::unknownType())
				parent_type->copyToType(ntype);
			else
				wxLogMessage("Warning: Entry type %s inherits from unknown type %s", CHR(ntype->getId()), CHR(typenode->getInherit()));
		}

		// Go through all parsed fields
		for (unsigned b = 0; b < typenode->nChildren(); b++)
		{
			// Get child as ParseTreeNode
			ParseTreeNode* fieldnode = (ParseTreeNode*)typenode->getChild(b);

			// Process it
			if (S_CMPNOCASE(fieldnode->getName(), "name"))  				// Name field
			{
				ntype->name = fieldnode->getStringValue();
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "detectable"))  		// Detectable field
			{
				ntype->detectable = fieldnode->getBoolValue();
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "export_ext"))  		// Export Extension field
			{
				ntype->extension = fieldnode->getStringValue();
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "format"))  			// Format field
			{
				string format_string = fieldnode->getStringValue();
				ntype->format = EntryDataFormat::getFormat(format_string);

				// Warn if undefined format
				if (ntype->format == EntryDataFormat::anyFormat())
					wxLogMessage("Warning: Entry type %s requires undefined format %s", CHR(ntype->getId()), CHR(format_string));
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "icon"))  			// Icon field
			{
				ntype->icon = fieldnode->getStringValue();
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "editor"))  			// Editor field (to be removed)
			{
				ntype->editor = fieldnode->getStringValue();
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "section"))  		// Section field
			{
				ntype->section = fieldnode->getStringValue();
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "match_ext"))  		// Match Extension field
			{
				for (unsigned v = 0; v < fieldnode->nValues(); v++)
					ntype->match_extension.push_back(fieldnode->getStringValue(v).Lower());
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "match_name"))  		// Match Name field
			{
				for (unsigned v = 0; v < fieldnode->nValues(); v++)
					ntype->match_name.push_back(fieldnode->getStringValue(v).Lower());
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "match_extorname"))  // Match name or extension
			{
				ntype->matchextorname = fieldnode->getBoolValue();
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "size"))  			// Size field
			{
				for (unsigned v = 0; v < fieldnode->nValues(); v++)
					ntype->match_size.push_back(fieldnode->getIntValue(v));
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "min_size"))  		// Min Size field
			{
				ntype->size_limit[0] = fieldnode->getIntValue();
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "max_size"))  		// Max Size field
			{
				ntype->size_limit[1] = fieldnode->getIntValue();
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "size_multiple"))  	// Size Multiple field
			{
				for (unsigned v = 0; v < fieldnode->nValues(); v++)
					ntype->size_multiple.push_back(fieldnode->getIntValue(v));
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "reliability"))  	// Reliability field
			{
				ntype->reliability = fieldnode->getIntValue();
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "match_archive"))  	// Archive field
			{
				for (unsigned v = 0; v < fieldnode->nValues(); v++)
					ntype->match_archive.push_back(fieldnode->getStringValue(v).Lower());
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "extra"))  			// Extra properties
			{
				for (unsigned v = 0; v < fieldnode->nValues(); v++)
					ntype->extra.addFlag(fieldnode->getStringValue(v));
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "category"))  		// Type category
			{
				ntype->category = fieldnode->getStringValue();

				// Add to category list if needed
				bool exists = false;
				for (unsigned b = 0; b < entry_categories.size(); b++)
				{
					if (S_CMPNOCASE(entry_categories[b], ntype->category))
					{
						exists = true;
						break;
					}
				}
				if (!exists) entry_categories.push_back(ntype->category);
			}
			else if (S_CMPNOCASE(fieldnode->getName(), "image_format"))		// Image format hint
				ntype->extra["image_format"] = fieldnode->getStringValue(0);
			else if (S_CMPNOCASE(fieldnode->getName(), "colour"))  			// Colour
			{
				if (fieldnode->nValues() >= 3)
					ntype->colour = rgba_t(fieldnode->getIntValue(0), fieldnode->getIntValue(1), fieldnode->getIntValue(2));
				else
					wxLogMessage("Not enough colour components defined for entry type %s", CHR(ntype->getId()));
			}
			else
			{
				// Unhandled properties can go into 'extra', only their first value is kept
				ntype->extra[fieldnode->getName()] = fieldnode->getStringValue();
			}
		}

		//ntype->dump();
		ntype->addToList();
	}

	return true;
}
예제 #5
0
파일: RefStats.hpp 프로젝트: genome/joinx
 Result match(EntryType const& entry) {
     return match(entry.chrom(), Region(entry.start(), entry.stop()));
 }