mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-10 11:35:19 -05:00
c80f9fbd57
* WIP Multiversion support * GC PAL Non-MQ support complete * Updated OtrGui to handle different game versions * Added version file * Added new extract mode to ZAPD and optimized OTR gen time * Fixed bug causing crash * Further optimized OTRExporter, saving around ~20 seconds. * ZAPD is now multi-threaded. * Fixed merge issue * Fixed memory leak and fog issue on pause screen. * Additional fog fixes. Co-authored-by: Jack Walker <7463599+Jack-Walker@users.noreply.github.com>
196 lines
5.1 KiB
C++
196 lines
5.1 KiB
C++
#include "ZBackground.h"
|
|
|
|
#include "Globals.h"
|
|
#include "Utils/BitConverter.h"
|
|
#include "Utils/File.h"
|
|
#include "Utils/Path.h"
|
|
#include "Utils/StringHelper.h"
|
|
#include "WarningHandler.h"
|
|
#include "ZFile.h"
|
|
|
|
REGISTER_ZFILENODE(Background, ZBackground);
|
|
|
|
#define JPEG_MARKER 0xFFD8FFE0
|
|
#define MARKER_DQT 0xFFDB
|
|
#define MARKER_EOI 0xFFD9
|
|
|
|
ZBackground::ZBackground(ZFile* nParent) : ZResource(nParent)
|
|
{
|
|
}
|
|
|
|
void ZBackground::ParseRawData()
|
|
{
|
|
ZResource::ParseRawData();
|
|
|
|
const auto& rawData = parent->GetRawData();
|
|
size_t i = 0;
|
|
while (true)
|
|
{
|
|
uint8_t val = rawData.at(rawDataIndex + i);
|
|
data.push_back(val);
|
|
|
|
if (BitConverter::ToUInt16BE(rawData, rawDataIndex + i) == MARKER_EOI)
|
|
{
|
|
data.push_back(rawData.at(rawDataIndex + i + 1));
|
|
break;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void ZBackground::ParseBinaryFile(const std::string& inFolder, bool appendOutName)
|
|
{
|
|
fs::path filepath(inFolder);
|
|
|
|
if (appendOutName)
|
|
filepath = filepath / (outName + "." + GetExternalExtension());
|
|
|
|
data = File::ReadAllBytes(filepath.string());
|
|
|
|
// Add padding.
|
|
data.insert(data.end(), GetRawDataSize() - data.size(), 0x00);
|
|
CheckValidJpeg(filepath.generic_string());
|
|
}
|
|
|
|
void ZBackground::CheckValidJpeg(const std::string& filepath)
|
|
{
|
|
std::string filename = outName;
|
|
if (filepath != "")
|
|
{
|
|
filename = filepath;
|
|
}
|
|
|
|
uint32_t jpegMarker = BitConverter::ToUInt32BE(data, 0);
|
|
if (jpegMarker != JPEG_MARKER)
|
|
{
|
|
HANDLE_WARNING_PROCESS(
|
|
WarningType::InvalidJPEG,
|
|
StringHelper::Sprintf("missing jpeg marker at beginning of file: '%s'",
|
|
filename.c_str()),
|
|
"The game will skip this jpeg.");
|
|
}
|
|
if (data.at(6) != 'J' || data.at(7) != 'F' || data.at(8) != 'I' || data.at(9) != 'F' ||
|
|
data.at(10) != '\0')
|
|
{
|
|
std::string jfifIdentifier(data.begin() + 6, data.begin() + 6 + 5);
|
|
HANDLE_WARNING_PROCESS(
|
|
WarningType::InvalidJPEG, "missing 'JFIF' identifier",
|
|
StringHelper::Sprintf(
|
|
"This image may be corrupted, or not a jpeg. The identifier found was: '%s'",
|
|
jfifIdentifier.c_str()));
|
|
}
|
|
uint8_t majorVersion = data.at(11);
|
|
uint8_t minorVersion = data.at(12);
|
|
if (majorVersion != 0x01 || minorVersion != 0x01)
|
|
{
|
|
HANDLE_WARNING_PROCESS(
|
|
WarningType::InvalidJPEG,
|
|
StringHelper::Sprintf("wrong JFIF version '%i.%02i'", majorVersion, minorVersion),
|
|
"The expected version is '1.01'. The game may be unable to decode this image "
|
|
"correctly.");
|
|
}
|
|
if (BitConverter::ToUInt16BE(data, 20) != MARKER_DQT)
|
|
{
|
|
// This may happen when creating a custom image with Exif, XMP, thumbnail, progressive, etc.
|
|
// enabled.
|
|
HANDLE_WARNING_PROCESS(WarningType::InvalidJPEG,
|
|
"there seems to be extra data before the image data in this file",
|
|
"The game may not be able to decode this image correctly.");
|
|
}
|
|
if (data.size() > GetRawDataSize())
|
|
{
|
|
HANDLE_WARNING_PROCESS(
|
|
WarningType::InvalidJPEG, "the image is bigger than the screen buffer",
|
|
StringHelper::Sprintf("Image size: %zu bytes\nScreen buffer size: %zu bytes",
|
|
data.size(), GetRawDataSize()));
|
|
}
|
|
}
|
|
|
|
size_t ZBackground::GetRawDataSize() const
|
|
{
|
|
// Jpgs use the whole sceen buffer, which is a u16 matrix.
|
|
return Globals::Instance->cfg.bgScreenHeight * Globals::Instance->cfg.bgScreenWidth * 2;
|
|
}
|
|
|
|
Declaration* ZBackground::DeclareVar(const std::string& prefix,
|
|
[[maybe_unused]] const std::string& bodyStr)
|
|
{
|
|
std::string auxName = name;
|
|
std::string auxOutName = outName;
|
|
|
|
if (auxName == "")
|
|
auxName = GetDefaultName(prefix);
|
|
|
|
if (auxOutName == "")
|
|
auxOutName = GetDefaultName(prefix);
|
|
|
|
auto filepath = Globals::Instance->outputPath / fs::path(auxOutName).stem();
|
|
|
|
std::string incStr =
|
|
StringHelper::Sprintf("%s.%s.inc.c", filepath.c_str(), GetExternalExtension().c_str());
|
|
|
|
Declaration* decl = parent->AddDeclarationIncludeArray(rawDataIndex, incStr, GetRawDataSize(),
|
|
GetSourceTypeName(), auxName, 0);
|
|
decl->arrayItemCntStr = "SCREEN_WIDTH * SCREEN_HEIGHT / 4";
|
|
decl->forceArrayCnt = true;
|
|
decl->staticConf = staticConf;
|
|
return decl;
|
|
}
|
|
|
|
bool ZBackground::IsExternalResource() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
std::string ZBackground::GetExternalExtension() const
|
|
{
|
|
return "jpg";
|
|
}
|
|
|
|
void ZBackground::Save(const fs::path& outFolder)
|
|
{
|
|
if (!Globals::Instance->otrMode)
|
|
{
|
|
fs::path filepath = outFolder / (outName + "." + GetExternalExtension());
|
|
File::WriteAllBytes(filepath.string(), data);
|
|
}
|
|
}
|
|
|
|
std::string ZBackground::GetBodySourceCode() const
|
|
{
|
|
std::string bodyStr = " ";
|
|
|
|
for (size_t i = 0; i < data.size() / 8; ++i)
|
|
{
|
|
bodyStr += StringHelper::Sprintf("0x%016llX, ", BitConverter::ToUInt64BE(data, i * 8));
|
|
|
|
if (i % 8 == 7)
|
|
bodyStr += "\n ";
|
|
}
|
|
|
|
bodyStr += "\n";
|
|
|
|
return bodyStr;
|
|
}
|
|
|
|
std::string ZBackground::GetDefaultName(const std::string& prefix) const
|
|
{
|
|
return StringHelper::Sprintf("%sBackground_%06X", prefix.c_str(), rawDataIndex);
|
|
}
|
|
|
|
std::string ZBackground::GetSourceTypeName() const
|
|
{
|
|
return "u64";
|
|
}
|
|
|
|
ZResourceType ZBackground::GetResourceType() const
|
|
{
|
|
return ZResourceType::Background;
|
|
}
|
|
|
|
DeclarationAlignment ZBackground::GetDeclarationAlignment() const
|
|
{
|
|
return DeclarationAlignment::Align8;
|
|
}
|