mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-23 22:37:55 +02:00
Fixed decompression of slayer.h3c from french version from gog.com
This commit is contained in:
@@ -66,7 +66,7 @@ std::unique_ptr<Campaign> CampaignHandler::getHeader( const std::string & name)
|
|||||||
|
|
||||||
auto ret = std::make_unique<Campaign>();
|
auto ret = std::make_unique<Campaign>();
|
||||||
auto fileStream = CResourceHandler::get(modName)->load(resourceID);
|
auto fileStream = CResourceHandler::get(modName)->load(resourceID);
|
||||||
std::vector<ui8> cmpgn = getFile(std::move(fileStream), true)[0];
|
std::vector<ui8> cmpgn = getFile(std::move(fileStream), name, true)[0];
|
||||||
|
|
||||||
readCampaign(ret.get(), cmpgn, resourceID.getName(), modName, encoding);
|
readCampaign(ret.get(), cmpgn, resourceID.getName(), modName, encoding);
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ std::shared_ptr<CampaignState> CampaignHandler::getCampaign( const std::string &
|
|||||||
|
|
||||||
auto fileStream = CResourceHandler::get(modName)->load(resourceID);
|
auto fileStream = CResourceHandler::get(modName)->load(resourceID);
|
||||||
|
|
||||||
std::vector<std::vector<ui8>> files = getFile(std::move(fileStream), false);
|
std::vector<std::vector<ui8>> files = getFile(std::move(fileStream), name, false);
|
||||||
|
|
||||||
readCampaign(ret.get(), files[0], resourceID.getName(), modName, encoding);
|
readCampaign(ret.get(), files[0], resourceID.getName(), modName, encoding);
|
||||||
|
|
||||||
@@ -578,19 +578,32 @@ CampaignTravel CampaignHandler::readScenarioTravelFromMemory(CBinaryReader & rea
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector< std::vector<ui8> > CampaignHandler::getFile(std::unique_ptr<CInputStream> file, bool headerOnly)
|
std::vector< std::vector<ui8> > CampaignHandler::getFile(std::unique_ptr<CInputStream> file, const std::string & filename, bool headerOnly)
|
||||||
{
|
{
|
||||||
CCompressedStream stream(std::move(file), true);
|
CCompressedStream stream(std::move(file), true);
|
||||||
|
|
||||||
std::vector< std::vector<ui8> > ret;
|
std::vector< std::vector<ui8> > ret;
|
||||||
do
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
std::vector<ui8> block(stream.getSize());
|
do
|
||||||
stream.read(block.data(), block.size());
|
{
|
||||||
ret.push_back(block);
|
std::vector<ui8> block(stream.getSize());
|
||||||
ret.back().shrink_to_fit();
|
stream.read(block.data(), block.size());
|
||||||
|
ret.push_back(block);
|
||||||
|
ret.back().shrink_to_fit();
|
||||||
|
}
|
||||||
|
while (!headerOnly && stream.getNextBlock());
|
||||||
|
}
|
||||||
|
catch (const DecompressionException & e)
|
||||||
|
{
|
||||||
|
// Some campaigns in French version from gog.com have trailing garbage bytes
|
||||||
|
// For example, slayer.h3c consist from 5 parts: header + 4 maps
|
||||||
|
// However file also contains ~100 "extra" bytes after those 5 parts are decompressed that do not represent gzip stream
|
||||||
|
// leading to exception "Incorrect header check"
|
||||||
|
// Since H3 handles these files correctly, simply log this as warning and proceed
|
||||||
|
logGlobal->warn("Failed to read file %s. Encountered error during decompression: %s", filename, e.what());
|
||||||
}
|
}
|
||||||
while (!headerOnly && stream.getNextBlock());
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class DLL_LINKAGE CampaignHandler
|
|||||||
static CampaignTravel readScenarioTravelFromMemory(CBinaryReader & reader, CampaignVersion version);
|
static CampaignTravel readScenarioTravelFromMemory(CBinaryReader & reader, CampaignVersion version);
|
||||||
/// returns h3c split in parts. 0 = h3c header, 1-end - maps (binary h3m)
|
/// returns h3c split in parts. 0 = h3c header, 1-end - maps (binary h3m)
|
||||||
/// headerOnly - only header will be decompressed, returned vector wont have any maps
|
/// headerOnly - only header will be decompressed, returned vector wont have any maps
|
||||||
static std::vector<std::vector<ui8>> getFile(std::unique_ptr<CInputStream> file, bool headerOnly);
|
static std::vector<std::vector<ui8>> getFile(std::unique_ptr<CInputStream> file, const std::string & filename, bool headerOnly);
|
||||||
|
|
||||||
static VideoPath prologVideoName(ui8 index);
|
static VideoPath prologVideoName(ui8 index);
|
||||||
static AudioPath prologMusicName(ui8 index);
|
static AudioPath prologMusicName(ui8 index);
|
||||||
|
|||||||
@@ -162,9 +162,9 @@ si64 CCompressedStream::readMore(ui8 *data, si64 size)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (inflateState->msg == nullptr)
|
if (inflateState->msg == nullptr)
|
||||||
throw std::runtime_error("Decompression error. Return code was " + std::to_string(ret));
|
throw DecompressionException("Error code " + std::to_string(ret));
|
||||||
else
|
else
|
||||||
throw std::runtime_error(std::string("Decompression error: ") + inflateState->msg);
|
throw DecompressionException(inflateState->msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (!endLoop && inflateState->avail_out != 0 );
|
while (!endLoop && inflateState->avail_out != 0 );
|
||||||
|
|||||||
@@ -15,6 +15,12 @@ struct z_stream_s;
|
|||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class DecompressionException : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using runtime_error::runtime_error;
|
||||||
|
};
|
||||||
|
|
||||||
/// Abstract class that provides buffer for one-directional input streams (e.g. compressed data)
|
/// Abstract class that provides buffer for one-directional input streams (e.g. compressed data)
|
||||||
/// Used for zip archives support and in .lod deflate compression
|
/// Used for zip archives support and in .lod deflate compression
|
||||||
class CBufferedStream : public CInputStream
|
class CBufferedStream : public CInputStream
|
||||||
|
|||||||
Reference in New Issue
Block a user