diff options
Diffstat (limited to 'ZAPD/ZBackground.cpp')
| -rw-r--r-- | ZAPD/ZBackground.cpp | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/ZAPD/ZBackground.cpp b/ZAPD/ZBackground.cpp new file mode 100644 index 0000000..70ee1ee --- /dev/null +++ b/ZAPD/ZBackground.cpp @@ -0,0 +1,211 @@ +#include "ZBackground.h" +#include "BitConverter.h" +#include "File.h" +#include "Path.h" +#include "StringHelper.h" +#include "ZFile.h" + +REGISTER_ZFILENODE(Background, ZBackground); +// TODO: make this a configurable value when ZAPD has a configuration file. +#define SCREEN_WIDTH 320 +#define SCREEN_HEIGHT 240 + +#define JPEG_MARKER 0xFFD8FFE0 +#define MARKER_DQT 0xFFDB + +ZBackground::ZBackground(ZFile* nParent) : ZResource(nParent) +{ +} + +ZBackground::ZBackground(const std::string& prefix, const std::vector<uint8_t>& nRawData, + int nRawDataIndex, ZFile* nParent) + : ZResource(nParent) +{ + rawData.assign(nRawData.begin(), nRawData.end()); + rawDataIndex = nRawDataIndex; + name = GetDefaultName(prefix.c_str(), rawDataIndex); + outName = name; + + ParseRawData(); +} + +void ZBackground::ParseRawData() +{ + ZResource::ParseRawData(); + + size_t i = 0; + while (true) + { + uint8_t val = rawData.at(rawDataIndex + i); + data.push_back(val); + + if (BitConverter::ToUInt16BE(rawData, rawDataIndex + i) == 0xFFD9) + { + 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); +} + +void ZBackground::ExtractFromXML(tinyxml2::XMLElement* reader, const std::vector<uint8_t>& nRawData, + int nRawDataIndex, const std::string& nRelPath) +{ + ZResource::ExtractFromXML(reader, nRawData, nRawDataIndex, nRelPath); + DeclareVar("", ""); +} + +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) + { + fprintf(stderr, + "ZBackground::CheckValidJpeg: Warning.\n" + "\t Missing jpeg marker at the beginning of file: '%s'.\n" + "\t The game will skip this jpeg.\n", + filename.c_str()); + } + 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); + fprintf(stderr, + "ZBackground::CheckValidJpeg: Warning.\n" + "\t Missing 'JFIF' identifier. File: '%s'.\n" + "\t This image may be corrupted or not be a jpeg iamge.\n" + "\t The identifier found was '%s'.\n", + filename.c_str(), jfifIdentifier.c_str()); + } + uint8_t majorVersion = data.at(11); + uint8_t minorVersion = data.at(12); + if (majorVersion != 0x01 || minorVersion != 0x01) + { + fprintf(stderr, + "ZBackground::CheckValidJpeg: Warning.\n" + "\t Wrong JFIF version '%i.%02i'. File: '%s'.\n" + "\t The expected version is '1.01'. The game may not be able to decode this image " + "properly.\n", + majorVersion, minorVersion, filename.c_str()); + } + if (BitConverter::ToUInt16BE(data, 20) != MARKER_DQT) + { + // This may happen when creating the image with Exif, XMP, thumbnail, progressive, etc. + // enabled. + fprintf(stderr, + "ZBackground::CheckValidJpeg: Warning.\n" + "\t There seems to be extra data before the image data in file: '%s'.\n" + "\t The game may not be able to decode this image properly.\n", + filename.c_str()); + } + if (data.size() > GetRawDataSize()) + { + fprintf(stderr, + "ZBackground::CheckValidJpeg: Warning.\n" + "\t The image is bigger than the screen buffer. File: '%s'.\n" + "\t Image size: %zu bytes.\n" + "\t Screen buffer size: %i bytes.\n", + filename.c_str(), data.size(), GetRawDataSize()); + } +} + +int ZBackground::GetRawDataSize() +{ + // Jpgs use the whole sceen buffer, which is a u16 matrix. + return SCREEN_HEIGHT * SCREEN_WIDTH * 2; +} + +void ZBackground::DeclareVar(const std::string& prefix, const std::string& bodyStr) +{ + std::string auxName = name; + + if (name == "") + auxName = GetDefaultName(prefix, rawDataIndex); + + parent->AddDeclarationArray(rawDataIndex, DeclarationAlignment::Align8, GetRawDataSize(), + GetSourceTypeName(), auxName, 0, bodyStr); +} + +bool ZBackground::IsExternalResource() +{ + return true; +} + +std::string ZBackground::GetExternalExtension() +{ + return "jpg"; +} + +void ZBackground::Save(const std::string& outFolder) +{ + fs::path folder(outFolder); + fs::path filepath = folder / (outName + "." + GetExternalExtension()); + File::WriteAllBytes(filepath.string(), data); +} + +std::string ZBackground::GetBodySourceCode() +{ + 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::GetSourceOutputCode(const std::string& prefix) +{ + std::string bodyStr = GetBodySourceCode(); + + Declaration* decl = parent->GetDeclaration(rawDataIndex); + + if (decl == nullptr) + DeclareVar(prefix, bodyStr); + else + decl->text = bodyStr; + + return ""; +} + +std::string ZBackground::GetDefaultName(const std::string& prefix, uint32_t address) +{ + return StringHelper::Sprintf("%sBackground_%06X", prefix.c_str(), address); +} + +std::string ZBackground::GetSourceTypeName() +{ + return "u64"; +} + +ZResourceType ZBackground::GetResourceType() +{ + return ZResourceType::Background; +} |
