예제 #1
0
void Archive_DAT_Bash::updateFileSize(const FATEntry *pid,
	stream::delta sizeDelta)
{
	if (pid->storedSize > 65535) {
		throw stream::error(createString("The file \"" << pid->strName
			<< "\" cannot be expanded to the requested size of " << pid->storedSize
			<< " bytes, as the Monster Bash .DAT file cannot store files larger than "
			"65535 bytes."));
	}
	if (pid->realSize > 65535) {
		throw stream::error(createString("The file \"" << pid->strName
			<< "\" cannot have its decompressed size set to " << pid->storedSize
			<< " bytes, as the Monster Bash .DAT file cannot store files that are "
			"larger than 65535 bytes, before or after decompression."));
	}

	// TESTED BY: fmt_dat_bash_insert*
	// TESTED BY: fmt_dat_bash_resize*
	this->content->seekp(DAT_FILESIZE_OFFSET(pid), stream::start);
	*this->content << u16le(pid->storedSize);

	// Write out the decompressed size too
	this->content->seekp(DAT_FILENAME_FIELD_LEN, stream::cur);
	if (pid->fAttr & File::Attribute::Compressed) {
		*this->content << u16le(pid->realSize);
	} else {
		*this->content << u16le(0);
	}
	return;
}
예제 #2
0
		virtual std::unique_ptr<Image> openImage(const Point& dims,
			std::unique_ptr<stream::inout> content, ImageType::Certainty result,
			bool create)
		{
			if (create) {
				// Create an empty image, 0x0 pixels in size
				content->truncate(4);
				*content << u16le(0) << u16le(0);
			}
			return std::make_unique<Image_DDaveEGA>(std::move(content), false);
		}
예제 #3
0
TilesetPtr TilesetType_CComic2::create(stream::inout_sptr psGraphics,
	SuppData& suppData) const
{
	psGraphics->seekp(0, stream::start);
	psGraphics
		<< u16le(0)
		<< u16le(0)
		<< u16le(0)
	;
	// Zero tiles, 0x0
	return TilesetPtr(new Tileset_CComic2(psGraphics, NUMPLANES_TILES));
}
예제 #4
0
void Tileset_MonsterBashSprite::updateFileSize(const Tileset_FAT::FATEntry *pid,
	stream::len sizeDelta)
{
	this->data->seekp(pid->offset, stream::start);
	this->data << u16le(pid->size);
	return;
}
void Archive_Resource_TIM_FAT::updateFileCount(uint32_t iNewCount)
{
	// TESTED BY: fmt_resource_tim_fat_insert*
	// TESTED BY: fmt_resource_tim_fat_remove*
	this->content->seekp(TIM_FILECOUNT_OFFSET, stream::start);
	*this->content << u16le(iNewCount);
	return;
}
예제 #6
0
void Archive_DAT_Bash::postInsertFile(FATEntry *pNewEntry)
{
	this->content->seekp(pNewEntry->iOffset, stream::start);

	int typeNum;

	int newLen = pNewEntry->strName.length();
	std::string ext = pNewEntry->strName.substr(newLen - 4);
	if (camoto::icasecmp(ext, ".mif")) typeNum = 0;
	else if (camoto::icasecmp(ext, ".mbg")) typeNum = 1;
	else if (camoto::icasecmp(ext, ".mfg")) typeNum = 2;
	else if (camoto::icasecmp(ext, ".tbg")) typeNum = 3;
	else if (camoto::icasecmp(ext, ".tfg")) typeNum = 4;
	else if (camoto::icasecmp(ext, ".tbn")) typeNum = 5;
	else if (camoto::icasecmp(ext, ".sgl")) typeNum = 6;
	else if (camoto::icasecmp(ext, ".msp")) typeNum = 7;
	else if (camoto::icasecmp(ext, ".snd")) typeNum = 8;
	else if (camoto::icasecmp(ext, ".pbg")) typeNum = 12;
	else if (camoto::icasecmp(ext, ".pfg")) typeNum = 13;
	else if (camoto::icasecmp(ext, ".pal")) typeNum = 14;
	else if (camoto::icasecmp(ext, ".pbn")) typeNum = 16;
	else if (camoto::icasecmp(ext, ".spr")) typeNum = 64;
	else typeNum = 32;

	if ((typeNum != 32) && (typeNum != 8)) {
		// Custom file, chop off extension
		pNewEntry->strName = pNewEntry->strName.substr(0, newLen - 4);
	}

	uint16_t expandedSize;
	if (pNewEntry->fAttr & File::Attribute::Compressed) {
		expandedSize = pNewEntry->realSize;
	} else {
		expandedSize = 0;
	}

	// Write out the entry
	*this->content
		<< u16le(typeNum)
		<< u16le(pNewEntry->storedSize)
		<< nullPadded(pNewEntry->strName, DAT_FILENAME_FIELD_LEN)
		<< u16le(expandedSize)
	;
	return;
}
예제 #7
0
void Tileset_MonsterBashSprite::postInsertFile(Tileset_FAT::FATEntry *pNewEntry)
{
	/// @todo Not necessary because of updateFileSize()?
	this->data->seekp(pNewEntry->offset, stream::start);
	this->data
		<< u16le(pNewEntry->size)
		<< u8(0)
		<< u8(0)
		<< u8(0)
		<< u8(0)
		<< s16le(0)
		<< s16le(0)
		<< u16le(0)
		<< u16le(0)
		<< u8(0) // EOF plane flag
	;
	return;
}
예제 #8
0
TilesetType_CComic2::Certainty TilesetType_CComic2::isInstance(stream::input_sptr psGraphics) const
{
	stream::pos len = psGraphics->size();
	if (len > 65535) return DefinitelyNo; // file too large (probably)
	psGraphics->seekg(0, stream::start);
	uint16_t num;
	for (int i = 0; i < 3; i++) {
		psGraphics >> u16le(num);
		if (num > 512) return DefinitelyNo; // too many tiles (probably)
	}
	return Unsure;
}
void Archive_Resource_TIM_FAT::updateFileSize(const FATEntry *pid, stream::delta sizeDelta)
{
	// TESTED BY: fmt_resource_tim_fat_insert*
	// TESTED BY: fmt_resource_tim_fat_resize*

	if (pid->storedSize % TIM_CONTENT_ITEM_LEN) {
		throw stream::error("Files in this archive must be a multiple of "
			TOSTRING(TIM_CONTENT_ITEM_LEN) " bytes.");
	}

	// Update embedded FAT
	this->content->seekp(pid->iOffset + TIM_EFAT_FILESIZE_OFFSET, stream::start);
	uint16_t actualSize = pid->storedSize / TIM_CONTENT_ITEM_LEN;
	*this->content << u16le(actualSize);

	return;
}
예제 #10
0
void Tileset_CComic2::flush()
{
	if (numPlanes == PlaneCount::Solid) {
		// Write any changed attributes
		this->content->seekp(0, stream::start);
		for (auto& a : this->v_attributes) {
			if (a.changed) {
				uint16_t val = (uint16_t)a.integerValue;
				if (a.integerValue < 0) val = 0xFFFF;
				*this->content << u16le(val);
				a.changed = false;
			} else {
				this->content->seekp(2, stream::cur);
			}
		}
	}
	this->Tileset_FAT::flush();
	return;
}
예제 #11
0
TilesetType_MonsterBashSprite::Certainty TilesetType_MonsterBashSprite::isInstance(
	stream::input_sptr psGraphics) const
{
	stream::len lenRemaining = psGraphics->size();
	psGraphics->seekg(0, stream::start);

	// TESTED BY: tls_bash_sprite_isinstance_c02
	if (lenRemaining < MB_MIN_FILE_LEN) return DefinitelyNo;

	uint8_t sig;
	psGraphics >> u8(sig);
	lenRemaining--;

	// TESTED BY: tls_bash_sprite_isinstance_c03
	if (sig != 0xFF) return DefinitelyNo;

	while (lenRemaining >= MB_SPR_EFAT_ENTRY_LEN) {
		uint16_t lenBlock;
		psGraphics >> u16le(lenBlock);
		lenRemaining -= 2;

		// TESTED BY: tls_bash_sprite_isinstance_c04
		if (lenBlock < MB_MIN_IMAGE_LEN) return DefinitelyNo;

		// TESTED BY: tls_bash_sprite_isinstance_c05
		if (lenBlock > lenRemaining) return DefinitelyNo;

		psGraphics->seekg(lenBlock - 1, stream::cur);
		uint8_t lastByte;
		psGraphics >> u8(lastByte);
		// TESTED BY: tls_bash_sprite_isinstance_c06
		if (lastByte != 0x00) return DefinitelyNo;

		lenRemaining -= lenBlock;
	}

	// TESTED BY: tls_bash_sprite_isinstance_c00
	// TESTED BY: tls_bash_sprite_isinstance_c01
	return DefinitelyYes;
}
예제 #12
0
void Archive_DAT_Bash::updateFileName(const FATEntry *pid, const std::string& strNewName)
{
	int typeNum;
	int newLen = strNewName.length();
	std::string ext = strNewName.substr(newLen - 4);
	if (camoto::icasecmp(ext, ".mif")) typeNum = 0;
	else if (camoto::icasecmp(ext, ".mbg")) typeNum = 1;
	else if (camoto::icasecmp(ext, ".mfg")) typeNum = 2;
	else if (camoto::icasecmp(ext, ".tbg")) typeNum = 3;
	else if (camoto::icasecmp(ext, ".tfg")) typeNum = 4;
	else if (camoto::icasecmp(ext, ".tbn")) typeNum = 5;
	else if (camoto::icasecmp(ext, ".sgl")) typeNum = 6;
	else if (camoto::icasecmp(ext, ".msp")) typeNum = 7;
	else if (camoto::icasecmp(ext, ".snd")) typeNum = 8;
	else if (camoto::icasecmp(ext, ".pbg")) typeNum = 12;
	else if (camoto::icasecmp(ext, ".pfg")) typeNum = 13;
	else if (camoto::icasecmp(ext, ".pal")) typeNum = 14;
	else if (camoto::icasecmp(ext, ".pbn")) typeNum = 16;
	else if (camoto::icasecmp(ext, ".spr")) typeNum = 64;
	else typeNum = 32;

	std::string strNativeName; // name to write to .dat file
	if ((typeNum != 32) && (typeNum != 8)) {
		// Custom file, chop off extension
		strNativeName = strNewName.substr(0, newLen - 4);
		newLen -= 4;
	} else {
		strNativeName = strNewName;
	}

	// TESTED BY: fmt_dat_bash_rename
	assert(newLen <= DAT_MAX_FILENAME_LEN);

	this->content->seekp(DAT_FILETYPE_OFFSET(pid), stream::start);
	*this->content << u16le(typeNum);

	this->content->seekp(DAT_FILENAME_OFFSET(pid), stream::start);
	*this->content << nullPadded(strNativeName, DAT_FILENAME_FIELD_LEN);
	return;
}
void Archive_Resource_TIM_FAT::preInsertFile(const FATEntry *idBeforeThis, FATEntry *pNewEntry)
{
	// TESTED BY: fmt_resource_tim_fat_insert*
	int len = pNewEntry->strName.length();
	assert(len <= TIM_MAX_FILENAME_LEN);

	if (pNewEntry->storedSize % TIM_CONTENT_ITEM_LEN) {
		throw stream::error("Files in this archive must be a multiple of "
			TOSTRING(TIM_CONTENT_ITEM_LEN) " bytes.");
	}

	// Set the format-specific variables
	pNewEntry->lenHeader = TIM_EFAT_ENTRY_LEN;

	boost::to_upper(pNewEntry->strName);

	// Write out the new embedded FAT entry
	this->content->seekp(pNewEntry->iOffset, stream::start);
	this->content->insert(TIM_EFAT_ENTRY_LEN);

	uint16_t actualSize = pNewEntry->storedSize / TIM_CONTENT_ITEM_LEN;

	// Write the header
	*this->content
		<< nullPadded(pNewEntry->strName, TIM_FILENAME_FIELD_LEN)
		<< u16le(actualSize)
	;

	// Since we've inserted some data for the embedded header, we need to update
	// the other file offsets accordingly.  This call updates the offset of the
	// files, then calls updateFileOffset() on them, using the *new* offset, so
	// we need to do this after the insert() call above to make sure the extra
	// data has been inserted.  Then when updateFileOffset() writes data out it
	// will go into the correct spot.
	this->shiftFiles(NULL, pNewEntry->iOffset, pNewEntry->lenHeader, 0);

	this->updateFileCount(this->vcFAT.size() + 1);
	return;
}
예제 #14
0
Tileset_MonsterBashSprite::Tileset_MonsterBashSprite(stream::inout_sptr data)
	:	Tileset_FAT(data, MB_FIRST_TILE_OFFSET)
{
	// Skip signature byte
	data->seekg(1, stream::start);
	stream::pos offset = 1;
	stream::len lenRemaining = this->data->size() - 1;

	int i = 0;
	while (lenRemaining >= MB_SPR_EFAT_ENTRY_LEN) {
		uint16_t lenBlock;
		data >> u16le(lenBlock);
		lenRemaining -= 2;

		FATEntry *fat = new FATEntry();
		EntryPtr ep(fat);
		fat->valid = true;
		fat->attr = 0;
		fat->index = i;
		fat->offset = offset;
		fat->size = lenBlock;
		fat->lenHeader = MB_SPR_EFAT_ENTRY_LEN;
		this->items.push_back(ep);
		if (lenBlock > lenRemaining) {
			std::cerr << "Warning: Ignoring incomplete image in Monster Bash sprite "
				"(image is " << lenBlock << " bytes, but file only contains another "
				<< lenRemaining << " bytes)" << std::endl;
			break;
		}
		data->seekg(lenBlock, stream::cur);
		lenRemaining -= lenBlock;
		offset += lenBlock + MB_SPR_EFAT_ENTRY_LEN; // MB_SPR_EFAT_ENTRY_LEN == sizeof(uint16le)
		i++;
	}

}