mirror of
https://github.com/ihhub/fheroes2.git
synced 2026-10-12 02:16:11 +00:00
Expand H2D file to have an optional info section for each file entry (#11040)
This commit is contained in:
Binary file not shown.
+27
-22
@@ -24,6 +24,7 @@
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
#include "image.h"
|
||||
#include "zzlib.h"
|
||||
@@ -37,7 +38,7 @@ namespace
|
||||
// 5 bytes - file name
|
||||
const size_t minFileSize = 4 + 4 + 4 + 4 + 5 + 1;
|
||||
|
||||
const uint8_t version{ 2U };
|
||||
const uint8_t version{ 3U };
|
||||
const std::array<uint8_t, 4> magicSequence{ 'H', '2', 'D', version };
|
||||
}
|
||||
|
||||
@@ -45,7 +46,7 @@ namespace fheroes2
|
||||
{
|
||||
bool H2DReader::open( const std::string & path )
|
||||
{
|
||||
_fileNameAndOffset.clear();
|
||||
_fileNameVsInfo.clear();
|
||||
_fileStream.close();
|
||||
|
||||
if ( !_fileStream.open( path, "rb" ) ) {
|
||||
@@ -73,11 +74,14 @@ namespace fheroes2
|
||||
const uint32_t size = _fileStream.getLE32();
|
||||
std::string name;
|
||||
_fileStream >> name;
|
||||
|
||||
std::string extraInfo;
|
||||
_fileStream >> extraInfo;
|
||||
if ( size == 0 || static_cast<size_t>( offset ) + size > fileSize || name.empty() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
_fileNameAndOffset.try_emplace( std::move( name ), std::make_pair( offset, size ) );
|
||||
_fileNameVsInfo.try_emplace( std::move( name ), EntryInfo{ offset, size, std::move( extraInfo ) } );
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -85,13 +89,13 @@ namespace fheroes2
|
||||
|
||||
std::vector<uint8_t> H2DReader::getFile( const std::string & fileName )
|
||||
{
|
||||
const auto it = _fileNameAndOffset.find( fileName );
|
||||
if ( it == _fileNameAndOffset.end() ) {
|
||||
const auto it = _fileNameVsInfo.find( fileName );
|
||||
if ( it == _fileNameVsInfo.end() ) {
|
||||
return {};
|
||||
}
|
||||
|
||||
_fileStream.seek( it->second.first );
|
||||
const auto compressedData = _fileStream.getRaw( it->second.second );
|
||||
_fileStream.seek( it->second.offset );
|
||||
const auto compressedData = _fileStream.getRaw( it->second.size );
|
||||
|
||||
return Compression::unzipData( compressedData.data(), compressedData.size() );
|
||||
}
|
||||
@@ -100,7 +104,7 @@ namespace fheroes2
|
||||
{
|
||||
std::set<std::string, std::less<>> names;
|
||||
|
||||
for ( const auto & [name, offset] : _fileNameAndOffset ) {
|
||||
for ( const auto & [name, info] : _fileNameVsInfo ) {
|
||||
names.insert( name );
|
||||
}
|
||||
|
||||
@@ -127,42 +131,43 @@ namespace fheroes2
|
||||
|
||||
// Calculate file info section size.
|
||||
size_t fileInfoSection = ( 4 + 4 ) * _fileData.size();
|
||||
for ( const auto & [name, data] : _fileData ) {
|
||||
for ( const auto & [name, info] : _fileData ) {
|
||||
// 4 byte for string size.
|
||||
fileInfoSection += ( name.size() + 4 );
|
||||
fileInfoSection += ( info.extraInfo.size() + 4 );
|
||||
}
|
||||
|
||||
// 4 bytes for magic sequence and 4 bytes for the number of files.
|
||||
size_t offset = fileInfoSection + 4 + 4;
|
||||
for ( const auto & [name, data] : _fileData ) {
|
||||
for ( const auto & [name, info] : _fileData ) {
|
||||
fileStream.putLE32( static_cast<uint32_t>( offset ) );
|
||||
fileStream.putLE32( static_cast<uint32_t>( data.size() ) );
|
||||
fileStream.putLE32( static_cast<uint32_t>( info.data.size() ) );
|
||||
fileStream << name;
|
||||
offset += data.size();
|
||||
fileStream << info.extraInfo;
|
||||
offset += info.data.size();
|
||||
}
|
||||
|
||||
for ( const auto & [name, data] : _fileData ) {
|
||||
fileStream.putRaw( data.data(), data.size() );
|
||||
for ( const auto & [name, info] : _fileData ) {
|
||||
fileStream.putRaw( info.data.data(), info.data.size() );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool H2DWriter::add( const std::string & name, const std::vector<uint8_t> & data )
|
||||
bool H2DWriter::add( const std::string & name, const std::vector<uint8_t> & data, std::string extraInfo )
|
||||
{
|
||||
if ( name.empty() || data.empty() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_fileData[name] = Compression::zipData( data.data(), data.size(), true );
|
||||
_fileData[name] = { Compression::zipData( data.data(), data.size(), true ), std::move( extraInfo ) };
|
||||
return true;
|
||||
}
|
||||
|
||||
bool H2DWriter::add( H2DReader & reader )
|
||||
{
|
||||
const std::set<std::string, std::less<>> names = reader.getAllFileNames();
|
||||
|
||||
for ( const std::string & name : names ) {
|
||||
if ( !add( name, reader.getFile( name ) ) ) {
|
||||
for ( const auto & [name, info] : reader.getAllEntries() ) {
|
||||
if ( !add( name, reader.getFile( name ), info.info ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -209,7 +214,7 @@ namespace fheroes2
|
||||
return true;
|
||||
}
|
||||
|
||||
bool writeImageToH2D( H2DWriter & writer, const std::string & name, const Sprite & image )
|
||||
bool writeImageToH2D( H2DWriter & writer, const std::string & name, const Sprite & image, std::string extraInfo )
|
||||
{
|
||||
assert( !image.empty() );
|
||||
|
||||
@@ -226,6 +231,6 @@ namespace fheroes2
|
||||
stream.putRaw( image.transform(), imageSize );
|
||||
}
|
||||
|
||||
return writer.add( name, stream.getRaw( 0 ) );
|
||||
return writer.add( name, stream.getRaw( 0 ), std::move( extraInfo ) );
|
||||
}
|
||||
}
|
||||
|
||||
+26
-6
@@ -1,6 +1,6 @@
|
||||
/***************************************************************************
|
||||
* fheroes2: https://github.com/ihhub/fheroes2 *
|
||||
* Copyright (C) 2021 - 2024 *
|
||||
* Copyright (C) 2021 - 2026 *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "serialize.h"
|
||||
@@ -38,17 +37,31 @@ namespace fheroes2
|
||||
class H2DReader
|
||||
{
|
||||
public:
|
||||
struct EntryInfo final
|
||||
{
|
||||
uint32_t offset{ 0 };
|
||||
|
||||
uint32_t size{ 0 };
|
||||
|
||||
std::string info;
|
||||
};
|
||||
|
||||
// Returns true if file opening is successful.
|
||||
bool open( const std::string & path );
|
||||
|
||||
// Returns non-empty vector if requested file exists.
|
||||
std::vector<uint8_t> getFile( const std::string & fileName );
|
||||
|
||||
const std::map<std::string, EntryInfo, std::less<>> & getAllEntries() const
|
||||
{
|
||||
return _fileNameVsInfo;
|
||||
}
|
||||
|
||||
std::set<std::string, std::less<>> getAllFileNames() const;
|
||||
|
||||
private:
|
||||
// Relationship between file name in non-capital letters and its offset from the start of the archive.
|
||||
std::map<std::string, std::pair<uint32_t, uint32_t>, std::less<>> _fileNameAndOffset;
|
||||
std::map<std::string, EntryInfo, std::less<>> _fileNameVsInfo;
|
||||
|
||||
// Stream for reading h2d file.
|
||||
StreamFile _fileStream;
|
||||
@@ -61,16 +74,23 @@ namespace fheroes2
|
||||
// Returns true if file opening is successful.
|
||||
bool write( const std::string & path ) const;
|
||||
|
||||
bool add( const std::string & name, const std::vector<uint8_t> & data );
|
||||
bool add( const std::string & name, const std::vector<uint8_t> & data, std::string extraInfo = {} );
|
||||
|
||||
// Add all entries from a H2D reader.
|
||||
bool add( H2DReader & reader );
|
||||
|
||||
private:
|
||||
std::map<std::string, std::vector<uint8_t>, std::less<>> _fileData;
|
||||
struct FileInfo final
|
||||
{
|
||||
std::vector<uint8_t> data;
|
||||
|
||||
std::string extraInfo;
|
||||
};
|
||||
|
||||
std::map<std::string, FileInfo, std::less<>> _fileData;
|
||||
};
|
||||
|
||||
bool readImageFromH2D( H2DReader & reader, const std::string & name, Sprite & image );
|
||||
|
||||
bool writeImageToH2D( H2DWriter & writer, const std::string & name, const Sprite & image );
|
||||
bool writeImageToH2D( H2DWriter & writer, const std::string & name, const Sprite & image, std::string extraInfo = {} );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user