mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-30 05:12:18 -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>
671 lines
22 KiB
C++
671 lines
22 KiB
C++
/**
|
|
* File: ZTextureAnimation.cpp
|
|
* ZResources defined: ZTextureAnimation, ZTextureAnimationParams (XML declaration not supported for
|
|
* the latter)
|
|
* Purpose: extracting texture animating structures from asset files
|
|
* Note: data type is exclusive to Majora's Mask
|
|
*
|
|
* Structure of data:
|
|
* A texture animation consists of a main array of data of the form
|
|
* `SS 00 00 0T PPPPPPPP`,
|
|
* where `S` is the segment that the functionality is sent to (and read by DLists), `T` is the
|
|
* "type" (see below), and `P` is a pointer to the type's subsidiary information, which is
|
|
* invariably just above this main array. Details of this subsidiary data are given below.
|
|
*
|
|
* Segment
|
|
* ===
|
|
* The segment starts at 1 and is incremented in each entry; the final one is negated, which is used
|
|
* as the indication to stop reading. The actual segment the game will use to draw is S + 7.
|
|
*
|
|
* Types
|
|
* ===
|
|
* There are 7 values that `T` can take:
|
|
* `0`: A single texture scroll (Implemented by Gfx_TexScroll): subsidiary params are given as
|
|
* an array with one entry, a struct `XX YY WW HH` containing xStep, yStep, width, height
|
|
* (all u8).
|
|
*
|
|
* `1`: A dual texture scroll (Implementated by Gfx_TwoTexScroll): same as type `0`, but with
|
|
* two entries in the params array.
|
|
*
|
|
* `2`: Color changing: Changes the primColor (with a LOD factor) and envColor
|
|
* `KKKK LLLL PPPPPPPP QQQQQQQQ RRRRRRRR`
|
|
* - `K` (u16) is the total length of the animation (and in this case, the total number of
|
|
* colors)
|
|
* - `L` (u16) is seemingly always 0 for this type, and not used in the code
|
|
* - `P` segmented pointer to array of augmented primColors
|
|
* - `Q` segmented pointer to array of envColors, and can be NULL
|
|
* - `R` segmented pointer to array of frameData (u8), which is also seemingly always NULL
|
|
* for this type.
|
|
*
|
|
* envColors take the form `RR GG BB AA` as usual, while primColors have an extra LODFrac
|
|
* element: RR GG BB AA LL
|
|
*
|
|
* `3`: Color changing (LERP): similar to type `2`, but uses linear interpolation. The structure
|
|
* is similar to `2`, but
|
|
* - `K` is now just the animation length, while
|
|
* - `L` is the total number of colors, and
|
|
* - the frameData is used to determine which colors to interpolate.
|
|
*
|
|
* `4`: Color changing (Lagrange interpolation): For extraction purposes identical to type 3.
|
|
* Uses a nonlinear interpolation formula to change the colours more smoothly.
|
|
*
|
|
* `5`: Texture cycle: functions like a gif. Subsidiary params:
|
|
* `FFFF 0000 PPPPPPPP QQQQQQQQ`
|
|
* where
|
|
* - `F` (u16) time between changes in frames
|
|
* - `P` pointer to array of segmented pointers to textures to cycle through
|
|
* - `Q` array of indices, indicating which texture to use next when a change frame is
|
|
* reached. The maximum indicates the number of textures in the texture array.
|
|
*
|
|
* `6`: This is used to indicate an empty/unimplemented params set. It is ignored by the game's
|
|
* function provided that the segment is 0. A generic empty one takes the form
|
|
* `00 00 00 06 00000000`,
|
|
* and has no extra data.
|
|
*
|
|
* Implementation
|
|
* ===
|
|
* - ZTextureAnimation requires a declaration in the XML to extract anything. It handles the main
|
|
* array. It uses a POD struct for each entry, and declares references to the params structs.
|
|
*
|
|
* - ZTextureAnimationParams is not (currently) declarable in an XML. It is a parent class for the
|
|
* three classes that handle the various cases:
|
|
* - TextureScrollingParams for types `0` and `1`
|
|
* - TextureColorChangingParams for types `2`,`3`,`4`
|
|
* - TextureCyclingParams for type `5`
|
|
* Each of these will declare all its subsidiary arrays, using POD structs.
|
|
*/
|
|
#include "ZTextureAnimation.h"
|
|
|
|
#include <cassert>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "Globals.h"
|
|
#include "Utils/BitConverter.h"
|
|
#include "WarningHandler.h"
|
|
#include "ZFile.h"
|
|
#include "ZResource.h"
|
|
#include "tinyxml2.h"
|
|
|
|
REGISTER_ZFILENODE(TextureAnimation, ZTextureAnimation);
|
|
|
|
/* Constructors */
|
|
ZTextureAnimationParams::ZTextureAnimationParams(ZFile* parent) : ZResource::ZResource(parent)
|
|
{
|
|
}
|
|
TextureScrollingParams::TextureScrollingParams(ZFile* parent)
|
|
: ZTextureAnimationParams::ZTextureAnimationParams(parent)
|
|
{
|
|
}
|
|
TextureColorChangingParams::TextureColorChangingParams(ZFile* parent)
|
|
: ZTextureAnimationParams::ZTextureAnimationParams(parent)
|
|
{
|
|
}
|
|
TextureCyclingParams::TextureCyclingParams(ZFile* parent)
|
|
: ZTextureAnimationParams::ZTextureAnimationParams(parent)
|
|
{
|
|
}
|
|
|
|
/* TextureAnimationParams */
|
|
/* This class only implements the functions common to all or most its inheritors */
|
|
|
|
void ZTextureAnimationParams::ExtractFromBinary(uint32_t nRawDataIndex)
|
|
{
|
|
rawDataIndex = nRawDataIndex;
|
|
|
|
ParseRawData();
|
|
}
|
|
|
|
// Implemented by TextureScrollingParams only
|
|
void ZTextureAnimationParams::ExtractFromBinary([[maybe_unused]] uint32_t nRawDataIndex,
|
|
[[maybe_unused]] int count)
|
|
{
|
|
}
|
|
|
|
std::string
|
|
ZTextureAnimationParams::GetDefaultName([[maybe_unused]] const std::string& prefix) const
|
|
{
|
|
return "ShouldNotBeVIsible";
|
|
}
|
|
|
|
ZResourceType ZTextureAnimationParams::GetResourceType() const
|
|
{
|
|
return ZResourceType::TextureAnimationParams;
|
|
}
|
|
|
|
/* TextureScrollingParams */
|
|
|
|
void TextureScrollingParams::ParseRawData()
|
|
{
|
|
const auto& rawData = parent->GetRawData();
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
rows[i].xStep = BitConverter::ToUInt8BE(rawData, rawDataIndex + 4 * i);
|
|
rows[i].yStep = BitConverter::ToUInt8BE(rawData, rawDataIndex + 4 * i + 1);
|
|
rows[i].width = BitConverter::ToUInt8BE(rawData, rawDataIndex + 4 * i + 2);
|
|
rows[i].height = BitConverter::ToUInt8BE(rawData, rawDataIndex + 4 * i + 3);
|
|
}
|
|
}
|
|
|
|
void TextureScrollingParams::ExtractFromBinary(uint32_t nRawDataIndex, int nCount)
|
|
{
|
|
rawDataIndex = nRawDataIndex;
|
|
count = nCount;
|
|
|
|
ParseRawData();
|
|
}
|
|
|
|
std::string TextureScrollingParams::GetSourceTypeName() const
|
|
{
|
|
return "AnimatedMatTexScrollParams"; // TODO: Better name
|
|
}
|
|
|
|
std::string TextureScrollingParams::GetDefaultName(const std::string& prefix) const
|
|
{
|
|
return StringHelper::Sprintf("%sTexScrollParams_%06X", prefix.c_str(), rawDataIndex);
|
|
}
|
|
|
|
size_t TextureScrollingParams::GetRawDataSize() const
|
|
{
|
|
return 4 * count;
|
|
}
|
|
|
|
/**
|
|
* Overrides the parent version to declare an array of the params rather than just one entry.
|
|
*/
|
|
Declaration* TextureScrollingParams::DeclareVar(const std::string& prefix,
|
|
const std::string& bodyStr)
|
|
{
|
|
std::string auxName = name;
|
|
|
|
if (name == "")
|
|
auxName = GetDefaultName(prefix);
|
|
|
|
return parent->AddDeclarationArray(rawDataIndex, GetDeclarationAlignment(), GetRawDataSize(),
|
|
GetSourceTypeName(), auxName, count, bodyStr);
|
|
}
|
|
|
|
std::string TextureScrollingParams::GetBodySourceCode() const
|
|
{
|
|
std::string bodyStr;
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
bodyStr += StringHelper::Sprintf("\t{ %d, %d, 0x%02X, 0x%02X },\n", rows[i].xStep,
|
|
rows[i].yStep, rows[i].width, rows[i].height);
|
|
}
|
|
|
|
bodyStr.pop_back();
|
|
|
|
return bodyStr;
|
|
}
|
|
|
|
/* TextureColorChangingParams */
|
|
|
|
/**
|
|
* Also parses the color and frameData arrays
|
|
*/
|
|
void TextureColorChangingParams::ParseRawData()
|
|
{
|
|
const auto& rawData = parent->GetRawData();
|
|
|
|
animLength = BitConverter::ToUInt16BE(rawData, rawDataIndex);
|
|
colorListCount = BitConverter::ToUInt16BE(rawData, rawDataIndex + 2);
|
|
|
|
// Handle type 2 separately
|
|
uint16_t listLength =
|
|
((type == TextureAnimationParamsType::ColorChange) ? animLength : colorListCount);
|
|
|
|
if (listLength == 0)
|
|
HANDLE_ERROR_RESOURCE(WarningType::Always, parent, this, rawDataIndex,
|
|
"color list length cannot be 0", "");
|
|
|
|
primColorListAddress = BitConverter::ToUInt32BE(rawData, rawDataIndex + 4);
|
|
envColorListAddress = BitConverter::ToUInt32BE(rawData, rawDataIndex + 8);
|
|
frameDataListAddress = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0xC);
|
|
|
|
uint32_t primColorListOffset = Seg2Filespace(primColorListAddress, parent->baseAddress);
|
|
uint32_t envColorListOffset = Seg2Filespace(envColorListAddress, parent->baseAddress);
|
|
uint32_t frameDataListOffset = Seg2Filespace(frameDataListAddress, parent->baseAddress);
|
|
|
|
uint32_t currentPtr;
|
|
|
|
F3DPrimColor currentPrimColor;
|
|
|
|
for (currentPtr = primColorListOffset; currentPtr < primColorListOffset + 5 * listLength;
|
|
currentPtr += 5)
|
|
{
|
|
currentPrimColor = {BitConverter::ToUInt8BE(rawData, currentPtr),
|
|
BitConverter::ToUInt8BE(rawData, currentPtr + 1),
|
|
BitConverter::ToUInt8BE(rawData, currentPtr + 2),
|
|
BitConverter::ToUInt8BE(rawData, currentPtr + 3),
|
|
BitConverter::ToUInt8BE(rawData, currentPtr + 4)};
|
|
primColorList.push_back(currentPrimColor);
|
|
}
|
|
|
|
F3DEnvColor currentEnvColor;
|
|
|
|
for (currentPtr = envColorListOffset; currentPtr < envColorListOffset + 4 * listLength;
|
|
currentPtr += 4)
|
|
{
|
|
currentEnvColor = {BitConverter::ToUInt8BE(rawData, currentPtr),
|
|
BitConverter::ToUInt8BE(rawData, currentPtr + 1),
|
|
BitConverter::ToUInt8BE(rawData, currentPtr + 2),
|
|
BitConverter::ToUInt8BE(rawData, currentPtr + 3)};
|
|
envColorList.push_back(currentEnvColor);
|
|
}
|
|
|
|
uint16_t currentFrameData;
|
|
|
|
for (currentPtr = frameDataListOffset; currentPtr < frameDataListOffset + 2 * listLength;
|
|
currentPtr += 2)
|
|
{
|
|
currentFrameData = BitConverter::ToUInt16BE(rawData, currentPtr);
|
|
frameDataList.push_back(currentFrameData);
|
|
}
|
|
}
|
|
|
|
std::string TextureColorChangingParams::GetSourceTypeName() const
|
|
{
|
|
return "AnimatedMatColorParams"; // TODO: Better name
|
|
}
|
|
|
|
std::string TextureColorChangingParams::GetDefaultName(const std::string& prefix) const
|
|
{
|
|
return StringHelper::Sprintf("%sColorParams_%06X", prefix.c_str(), rawDataIndex);
|
|
}
|
|
|
|
size_t TextureColorChangingParams::GetRawDataSize() const
|
|
{
|
|
return 0x10;
|
|
}
|
|
|
|
void TextureColorChangingParams::DeclareReferences([[maybe_unused]] const std::string& prefix)
|
|
{
|
|
if (primColorListAddress != 0) // NULL
|
|
{
|
|
std::string primColorBodyStr;
|
|
|
|
for (const auto& color : primColorList)
|
|
{
|
|
primColorBodyStr += StringHelper::Sprintf("\t{ %d, %d, %d, %d, %d },\n", color.r,
|
|
color.g, color.b, color.a, color.lodFrac);
|
|
}
|
|
|
|
primColorBodyStr.pop_back();
|
|
|
|
parent->AddDeclarationArray(
|
|
Seg2Filespace(primColorListAddress, parent->baseAddress), DeclarationAlignment::Align4,
|
|
primColorList.size() * 5, "F3DPrimColor",
|
|
StringHelper::Sprintf("%sTexColorChangingPrimColors_%06X", parent->GetName().c_str(),
|
|
Seg2Filespace(primColorListAddress, parent->baseAddress)),
|
|
primColorList.size(), primColorBodyStr);
|
|
}
|
|
|
|
if (envColorListAddress != 0) // NULL
|
|
{
|
|
std::string envColorBodyStr;
|
|
|
|
for (const auto& color : envColorList)
|
|
{
|
|
envColorBodyStr += StringHelper::Sprintf("\t{ %d, %d, %d, %d },\n", color.r, color.g,
|
|
color.b, color.a);
|
|
}
|
|
|
|
envColorBodyStr.pop_back();
|
|
|
|
parent->AddDeclarationArray(
|
|
Seg2Filespace(envColorListAddress, parent->baseAddress), DeclarationAlignment::Align4,
|
|
envColorList.size() * 4, "F3DEnvColor",
|
|
StringHelper::Sprintf("%sTexColorChangingEnvColors_%06X", parent->GetName().c_str(),
|
|
Seg2Filespace(envColorListAddress, parent->baseAddress)),
|
|
envColorList.size(), envColorBodyStr);
|
|
}
|
|
|
|
if (frameDataListAddress != 0) // NULL
|
|
{
|
|
std::string frameDataBodyStr = "\t";
|
|
|
|
for (const auto& frame : frameDataList)
|
|
{
|
|
frameDataBodyStr += StringHelper::Sprintf("%d, ", frame);
|
|
}
|
|
|
|
frameDataBodyStr.pop_back();
|
|
|
|
parent->AddDeclarationArray(
|
|
Seg2Filespace(frameDataListAddress, parent->baseAddress), DeclarationAlignment::Align4,
|
|
frameDataList.size() * 2, "u16",
|
|
StringHelper::Sprintf("%sTexColorChangingFrameData_%06X", parent->GetName().c_str(),
|
|
Seg2Filespace(frameDataListAddress, parent->baseAddress)),
|
|
frameDataList.size(), frameDataBodyStr);
|
|
}
|
|
}
|
|
|
|
std::string TextureColorChangingParams::GetBodySourceCode() const
|
|
{
|
|
std::string primColorListName;
|
|
std::string envColorListName;
|
|
std::string frameDataListName;
|
|
|
|
Globals::Instance->GetSegmentedPtrName(primColorListAddress, parent, "", primColorListName,
|
|
parent->workerID);
|
|
Globals::Instance->GetSegmentedPtrName(envColorListAddress, parent, "", envColorListName,
|
|
parent->workerID);
|
|
Globals::Instance->GetSegmentedPtrName(frameDataListAddress, parent, "", frameDataListName,
|
|
parent->workerID);
|
|
|
|
std::string bodyStr = StringHelper::Sprintf(
|
|
"\n %d, %d, %s, %s, %s,\n", animLength, colorListCount, primColorListName.c_str(),
|
|
envColorListName.c_str(), frameDataListName.c_str());
|
|
|
|
return bodyStr;
|
|
}
|
|
|
|
/* TextureCyclingParams */
|
|
|
|
void TextureCyclingParams::ParseRawData()
|
|
{
|
|
const auto& rawData = parent->GetRawData();
|
|
|
|
cycleLength = BitConverter::ToUInt16BE(rawData, rawDataIndex);
|
|
if (cycleLength == 0)
|
|
HANDLE_ERROR_RESOURCE(WarningType::Always, parent, this, rawDataIndex,
|
|
"cycle length cannot be 0", "");
|
|
|
|
textureListAddress = BitConverter::ToUInt32BE(rawData, rawDataIndex + 4);
|
|
textureIndexListAddress = BitConverter::ToUInt32BE(rawData, rawDataIndex + 8);
|
|
|
|
uint32_t textureListOffset = Seg2Filespace(textureListAddress, parent->baseAddress);
|
|
uint32_t textureIndexListOffset = Seg2Filespace(textureIndexListAddress, parent->baseAddress);
|
|
|
|
uint32_t currentPtr;
|
|
|
|
uint8_t currentIndex;
|
|
uint8_t maxIndex = 0; // To find the length of the texture list
|
|
|
|
for (currentPtr = textureIndexListOffset; currentPtr < textureIndexListOffset + cycleLength;
|
|
currentPtr++)
|
|
{
|
|
currentIndex = BitConverter::ToUInt8BE(rawData, currentPtr);
|
|
textureIndexList.push_back(currentIndex);
|
|
if (currentIndex > maxIndex)
|
|
maxIndex = currentIndex;
|
|
}
|
|
|
|
for (currentPtr = textureListOffset; currentPtr <= textureListOffset + 4 * maxIndex;
|
|
currentPtr += 4)
|
|
{
|
|
textureList.push_back(BitConverter::ToUInt32BE(rawData, currentPtr));
|
|
}
|
|
}
|
|
|
|
std::string TextureCyclingParams::GetSourceTypeName() const
|
|
{
|
|
return "AnimatedMatTexCycleParams"; // TODO: Better name
|
|
}
|
|
|
|
std::string TextureCyclingParams::GetDefaultName(const std::string& prefix) const
|
|
{
|
|
return StringHelper::Sprintf("%sTexCycleParams_%06X", prefix.c_str(), rawDataIndex);
|
|
}
|
|
|
|
size_t TextureCyclingParams::GetRawDataSize() const
|
|
{
|
|
return 0xC;
|
|
}
|
|
|
|
void TextureCyclingParams::DeclareReferences([[maybe_unused]] const std::string& prefix)
|
|
{
|
|
if (textureListAddress != 0) // NULL
|
|
{
|
|
std::string texturesBodyStr;
|
|
std::string texName;
|
|
std::string comment;
|
|
|
|
for (const auto& tex : textureList)
|
|
{
|
|
bool texFound =
|
|
Globals::Instance->GetSegmentedPtrName(tex, parent, "", texName, parent->workerID);
|
|
|
|
// texName is a raw segmented pointer. This occurs if the texture is not declared
|
|
// separately since we cannot read the format. In theory we could scan DLists for the
|
|
// format on the appropriate segments.
|
|
if (!texFound)
|
|
{
|
|
comment = " // Raw pointer, declare texture in XML to use proper symbol";
|
|
|
|
auto msgHeader = StringHelper::Sprintf(
|
|
"TexCycle texture array declared here points to unknown texture at address %s",
|
|
texName.c_str());
|
|
HANDLE_WARNING_RESOURCE(
|
|
WarningType::HardcodedPointer, parent, this, rawDataIndex, msgHeader,
|
|
"Please declare the texture in the XML to use the proper symbol.");
|
|
}
|
|
texturesBodyStr += StringHelper::Sprintf("\t%s,%s\n", texName.c_str(), comment.c_str());
|
|
}
|
|
|
|
texturesBodyStr.pop_back();
|
|
|
|
parent->AddDeclarationArray(
|
|
Seg2Filespace(textureListAddress, parent->baseAddress), DeclarationAlignment::Align4,
|
|
textureList.size() * 4, "TexturePtr",
|
|
StringHelper::Sprintf("%sTexCycleTexPtrs_%06X", parent->GetName().c_str(),
|
|
Seg2Filespace(textureListAddress, parent->baseAddress)),
|
|
textureList.size(), texturesBodyStr);
|
|
}
|
|
|
|
if (textureIndexListAddress != 0) // NULL
|
|
{
|
|
std::string indicesBodyStr = "\t";
|
|
|
|
for (uint8_t index : textureIndexList)
|
|
{
|
|
indicesBodyStr += StringHelper::Sprintf("%d, ", index);
|
|
}
|
|
|
|
indicesBodyStr.pop_back();
|
|
|
|
parent->AddDeclarationArray(
|
|
Seg2Filespace(textureIndexListAddress, parent->baseAddress),
|
|
DeclarationAlignment::Align4, textureIndexList.size(), "u8",
|
|
StringHelper::Sprintf("%sTexCycleTexIndices_%06X", parent->GetName().c_str(),
|
|
Seg2Filespace(textureIndexListAddress, parent->baseAddress)),
|
|
textureIndexList.size(), indicesBodyStr);
|
|
}
|
|
}
|
|
|
|
std::string TextureCyclingParams::GetBodySourceCode() const
|
|
{
|
|
std::string textureListName;
|
|
std::string textureIndexListName;
|
|
|
|
Globals::Instance->GetSegmentedPtrName(textureListAddress, parent, "", textureListName,
|
|
parent->workerID);
|
|
Globals::Instance->GetSegmentedPtrName(textureIndexListAddress, parent, "",
|
|
textureIndexListName, parent->workerID);
|
|
|
|
std::string bodyStr = StringHelper::Sprintf(
|
|
"\n %d, %s, %s,\n", cycleLength, textureListName.c_str(), textureIndexListName.c_str());
|
|
|
|
return bodyStr;
|
|
}
|
|
|
|
/* ZTextureAnimation */
|
|
|
|
ZTextureAnimation::ZTextureAnimation(ZFile* nParent) : ZResource(nParent)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Builds the array of params
|
|
*/
|
|
void ZTextureAnimation::ParseRawData()
|
|
{
|
|
ZResource::ParseRawData();
|
|
|
|
TextureAnimationEntry currentEntry;
|
|
auto rawData = parent->GetRawData();
|
|
int16_t type;
|
|
|
|
for (uint32_t currentPtr = rawDataIndex;; currentPtr += 8)
|
|
{
|
|
type = BitConverter::ToInt16BE(rawData, currentPtr + 2);
|
|
|
|
currentEntry.segment = BitConverter::ToInt8BE(rawData, currentPtr);
|
|
currentEntry.type = (TextureAnimationParamsType)type;
|
|
currentEntry.paramsPtr = BitConverter::ToUInt32BE(rawData, currentPtr + 4);
|
|
entries.push_back(currentEntry);
|
|
|
|
if ((type < 0) || (type > 6))
|
|
{
|
|
HANDLE_ERROR_RESOURCE(
|
|
WarningType::Always, parent, this, rawDataIndex,
|
|
StringHelper::Sprintf(
|
|
"unknown TextureAnimationParams type 0x%02X in TextureAnimation", type),
|
|
StringHelper::Sprintf(
|
|
"Entry reads { 0x%02X, 0x%02X, 0x%08X } , but type should be "
|
|
"between 0x00 and 0x06 inclusive.",
|
|
currentEntry.segment, type, currentEntry.paramsPtr));
|
|
}
|
|
|
|
if (currentEntry.segment <= 0)
|
|
break;
|
|
}
|
|
}
|
|
|
|
#include <optional>
|
|
/**
|
|
* For each params entry,
|
|
*/
|
|
void ZTextureAnimation::DeclareReferences(const std::string& prefix)
|
|
{
|
|
std::string varPrefix = name;
|
|
if (varPrefix == "")
|
|
varPrefix = prefix;
|
|
|
|
ZResource::DeclareReferences(varPrefix);
|
|
|
|
for (const auto& entry : entries)
|
|
{
|
|
if (entry.paramsPtr != 0 && GETSEGNUM(entry.paramsPtr) == parent->segment)
|
|
{
|
|
uint32_t paramsOffset = Seg2Filespace(entry.paramsPtr, parent->baseAddress);
|
|
if (!parent->HasDeclaration(paramsOffset))
|
|
{
|
|
ZTextureAnimationParams* params;
|
|
int count;
|
|
switch (entry.type)
|
|
{
|
|
case TextureAnimationParamsType::SingleScroll:
|
|
if (true)
|
|
{
|
|
count = 1;
|
|
// The else now allows SingleScroll to fall through to params = ... without
|
|
// touching the code in the else block
|
|
}
|
|
else
|
|
{
|
|
// The contents of this block can only be run by jumping into it with the
|
|
// case label
|
|
[[fallthrough]];
|
|
case TextureAnimationParamsType::DualScroll:
|
|
count = 2;
|
|
}
|
|
params = new TextureScrollingParams(parent);
|
|
params->ExtractFromBinary(paramsOffset, count);
|
|
break;
|
|
|
|
case TextureAnimationParamsType::ColorChange:
|
|
case TextureAnimationParamsType::ColorChangeLERP:
|
|
case TextureAnimationParamsType::ColorChangeLagrange:
|
|
params = new TextureColorChangingParams(parent);
|
|
params->type = entry.type;
|
|
params->ExtractFromBinary(paramsOffset);
|
|
break;
|
|
|
|
case TextureAnimationParamsType::TextureCycle:
|
|
params = new TextureCyclingParams(parent);
|
|
params->ExtractFromBinary(paramsOffset);
|
|
break;
|
|
|
|
case TextureAnimationParamsType::Empty:
|
|
HANDLE_WARNING_RESOURCE(
|
|
WarningType::InvalidExtractedData, parent, this, rawDataIndex,
|
|
"TextureAnimationParams entry has empty type (6), but params pointer is "
|
|
"not NULL",
|
|
StringHelper::Sprintf("Params read { 0x%02X, 0x%02X, 0x%08X } .",
|
|
entry.segment, (int)entry.type, entry.paramsPtr));
|
|
return;
|
|
default:
|
|
// Because GCC is worried this could happen
|
|
assert(entry.type < TextureAnimationParamsType::SingleScroll ||
|
|
entry.type > TextureAnimationParamsType::Empty);
|
|
return;
|
|
}
|
|
|
|
params->SetName(params->GetDefaultName(varPrefix));
|
|
params->DeclareVar(varPrefix, "");
|
|
parent->AddResource(params);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
std::string ZTextureAnimation::GetSourceTypeName() const
|
|
{
|
|
return "AnimatedMaterial"; // TODO: Better name
|
|
}
|
|
|
|
ZResourceType ZTextureAnimation::GetResourceType() const
|
|
{
|
|
return ZResourceType::TextureAnimation;
|
|
}
|
|
|
|
/**
|
|
* The size of the main array
|
|
*/
|
|
size_t ZTextureAnimation::GetRawDataSize() const
|
|
{
|
|
return entries.size() * 8;
|
|
}
|
|
|
|
std::string ZTextureAnimation::GetDefaultName(const std::string& prefix) const
|
|
{
|
|
return StringHelper::Sprintf("%sTexAnim_%06X", prefix.c_str(), rawDataIndex);
|
|
}
|
|
|
|
Declaration* ZTextureAnimation::DeclareVar(const std::string& prefix, const std::string& bodyStr)
|
|
{
|
|
std::string auxName = name;
|
|
|
|
if (name == "")
|
|
auxName = GetDefaultName(prefix);
|
|
|
|
Declaration* decl =
|
|
parent->AddDeclarationArray(rawDataIndex, GetDeclarationAlignment(), GetRawDataSize(),
|
|
GetSourceTypeName(), auxName, entries.size(), bodyStr);
|
|
decl->staticConf = staticConf;
|
|
return decl;
|
|
}
|
|
|
|
std::string ZTextureAnimation::GetBodySourceCode() const
|
|
{
|
|
std::string bodyStr;
|
|
|
|
for (const auto& entry : entries)
|
|
{
|
|
std::string paramName;
|
|
Globals::Instance->GetSegmentedPtrName(entry.paramsPtr, parent, "", paramName,
|
|
parent->workerID);
|
|
|
|
bodyStr += StringHelper::Sprintf("\t{ %d, %d, %s },\n", entry.segment, entry.type,
|
|
paramName.c_str());
|
|
}
|
|
|
|
bodyStr.pop_back();
|
|
|
|
return bodyStr;
|
|
}
|