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