diff --git a/README.md b/README.md index 76dfbd1e..d51dd055 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,11 @@ ZAPD also accepts the following list of extra parameters: - `-us` / `--unaccounted-static` : Mark unaccounted data as `static` - `-s` / `--static` : Mark every asset as `static`. - This behaviour can be overridden per asset using `Static=` in the respective XML node. +- `--cs-float` : How cutscene floats should be extracted. +- Valid values: + - `hex` + - `float` + - `both` - `-W...`: warning flags, see below Additionally, you can pass the flag `--version` to see the current ZAPD version. If that flag is passed, ZAPD will ignore any other parameter passed. diff --git a/ZAPD/Globals.h b/ZAPD/Globals.h index 0bfcaeec..14bd0658 100644 --- a/ZAPD/Globals.h +++ b/ZAPD/Globals.h @@ -16,6 +16,13 @@ enum class VerbosityLevel VERBOSITY_DEBUG }; +enum class CsFloatType +{ + HexOnly, + FloatOnly, + HexAndFloat, +}; + class Globals { public: @@ -31,6 +38,7 @@ class Globals ZFileMode fileMode; fs::path baseRomPath, inputPath, outputPath, sourceOutputPath, cfgPath; TextureType texType; + CsFloatType floatType = CsFloatType::FloatOnly; ZGame game; GameConfig cfg; bool verboseUnaccounted = false; diff --git a/ZAPD/Main.cpp b/ZAPD/Main.cpp index 40a38bc6..eb1737d6 100644 --- a/ZAPD/Main.cpp +++ b/ZAPD/Main.cpp @@ -36,6 +36,7 @@ void Arg_SetExporter(int& i, char* argv[]); void Arg_EnableGCCCompat(int& i, char* argv[]); void Arg_ForceStatic(int& i, char* argv[]); void Arg_ForceUnaccountedStatic(int& i, char* argv[]); +void Arg_CsFloatMode(int& i, char* argv[]); int main(int argc, char* argv[]); @@ -252,6 +253,7 @@ void ParseArgs(int& argc, char* argv[]) {"--static", &Arg_ForceStatic}, {"-us", &Arg_ForceUnaccountedStatic}, {"--unaccounted-static", &Arg_ForceUnaccountedStatic}, + {"--cs-float", &Arg_CsFloatMode}, }; for (int32_t i = 2; i < argc; i++) @@ -392,6 +394,32 @@ void Arg_ForceUnaccountedStatic([[maybe_unused]] int& i, [[maybe_unused]] char* Globals::Instance->forceUnaccountedStatic = true; } +void Arg_CsFloatMode([[maybe_unused]] int& i, [[maybe_unused]] char* argv[]) +{ + i++; + if (std::strcmp(argv[i], "hex") == 0) + { + Globals::Instance->floatType = CsFloatType::HexOnly; + } + else if (std::strcmp(argv[i], "float") == 0) + { + Globals::Instance->floatType = CsFloatType::FloatOnly; + } + else if (std::strcmp(argv[i], "both") == 0) + { + Globals::Instance->floatType = CsFloatType::HexAndFloat; + } + else + { + Globals::Instance->floatType = CsFloatType::FloatOnly; + HANDLE_WARNING( + WarningType::Always, "Invalid CS Float Type", + StringHelper::Sprintf("Invalid CS float type entered. Expected \"hex\", \"float\", or " + "\"both\". Got %s.\n Defaulting to \"float\".", + argv[i])); + } +} + int HandleExtract(ZFileMode fileMode, ExporterSet* exporterSet) { bool procFileModeSuccess = false; diff --git a/ZAPD/OtherStructs/CutsceneMM_Commands.cpp b/ZAPD/OtherStructs/CutsceneMM_Commands.cpp index 5a10ab41..960404e5 100644 --- a/ZAPD/OtherStructs/CutsceneMM_Commands.cpp +++ b/ZAPD/OtherStructs/CutsceneMM_Commands.cpp @@ -6,6 +6,8 @@ #include "Utils/StringHelper.h" #include "WarningHandler.h" +#include "ZCutscene.h" + /**** GENERIC ****/ // Specific for command lists where each entry has size 8 bytes @@ -556,22 +558,29 @@ CutsceneMMSubCommandEntry_ActorCue::CutsceneMMSubCommandEntry_ActorCue( std::string CutsceneMMSubCommandEntry_ActorCue::GetBodySourceCode() const { EnumData* enumData = &Globals::Instance->cfg.enumData; + std::string normalXStr = + ZCutscene::GetCsEncodedFloat(normalX, Globals::Instance->floatType, true); + std::string normalYStr = + ZCutscene::GetCsEncodedFloat(normalY, Globals::Instance->floatType, true); + std::string normalZStr = + ZCutscene::GetCsEncodedFloat(normalZ, Globals::Instance->floatType, true); if (static_cast(commandID) == CutsceneMM_CommandType::CS_CMD_PLAYER_CUE) { return StringHelper::Sprintf("CS_PLAYER_CUE(%s, %i, %i, 0x%04X, 0x%04X, 0x%04X, %i, %i, " - "%i, %i, %i, %i, %.8ef, %.8ef, %.8ef)", + "%i, %i, %i, %i, %s, %s, %s)", enumData->playerCueId[base].c_str(), startFrame, endFrame, rotX, rotY, rotZ, startPosX, startPosY, startPosZ, endPosX, - endPosY, endPosZ, normalX, normalY, normalZ); + endPosY, endPosZ, normalXStr.c_str(), normalYStr.c_str(), + normalZStr.c_str()); } else { return StringHelper::Sprintf("CS_ACTOR_CUE(%i, %i, %i, 0x%04X, 0x%04X, 0x%04X, %i, %i, " - "%i, %i, %i, %i, %.8ef, %.8ef, %.8ef)", + "%i, %i, %i, %i, %s, %s, %s)", base, startFrame, endFrame, rotX, rotY, rotZ, startPosX, - startPosY, startPosZ, endPosX, endPosY, endPosZ, normalX, - normalY, normalZ); + startPosY, startPosZ, endPosX, endPosY, endPosZ, + normalXStr.c_str(), normalYStr.c_str(), normalZStr.c_str()); } } diff --git a/ZAPD/OtherStructs/CutsceneOoT_Commands.cpp b/ZAPD/OtherStructs/CutsceneOoT_Commands.cpp index 8c530f79..f9a5c4f2 100644 --- a/ZAPD/OtherStructs/CutsceneOoT_Commands.cpp +++ b/ZAPD/OtherStructs/CutsceneOoT_Commands.cpp @@ -6,6 +6,8 @@ #include "Utils/BitConverter.h" #include "Utils/StringHelper.h" +#include "ZCutscene.h" + /**** GENERIC ****/ // Specific for command lists where each entry has size 0x30 bytes @@ -139,9 +141,11 @@ std::string CutsceneOoTCommand_CameraPoint::GetBodySourceCode() const if (continueFlag != 0) continueMacro = "CS_CAM_STOP"; - return StringHelper::Sprintf("CS_CAM_POINT(%s, 0x%02X, %i, %ff, %i, %i, %i, 0x%04X)", - continueMacro.c_str(), cameraRoll, nextPointFrame, viewAngle, posX, - posY, posZ, unused); + return StringHelper::Sprintf( + "CS_CAM_POINT(%s, 0x%02X, %i, %s, %i, %i, %i, 0x%04X)", continueMacro.c_str(), cameraRoll, + nextPointFrame, + ZCutscene::GetCsEncodedFloat(viewAngle, Globals::Instance->floatType, false).c_str(), posX, + posY, posZ, unused); } size_t CutsceneOoTCommand_CameraPoint::GetRawSize() const @@ -334,27 +338,34 @@ CutsceneOoTSubCommandEntry_ActorCue::CutsceneOoTSubCommandEntry_ActorCue( normalY = BitConverter::ToFloatBE(rawData, rawDataIndex + 0x28); normalZ = BitConverter::ToFloatBE(rawData, rawDataIndex + 0x2C); } - std::string CutsceneOoTSubCommandEntry_ActorCue::GetBodySourceCode() const { EnumData* enumData = &Globals::Instance->cfg.enumData; + std::string normalXStr = + ZCutscene::GetCsEncodedFloat(normalX, Globals::Instance->floatType, true); + std::string normalYStr = + ZCutscene::GetCsEncodedFloat(normalY, Globals::Instance->floatType, true); + std::string normalZStr = + ZCutscene::GetCsEncodedFloat(normalZ, Globals::Instance->floatType, true); + if (static_cast(commandID) == CutsceneOoT_CommandType::CS_CMD_PLAYER_CUE) { return StringHelper::Sprintf("CS_PLAYER_CUE(%s, %i, %i, 0x%04X, 0x%04X, 0x%04X, %i, %i, " - "%i, %i, %i, %i, %.8ef, %.8ef, %.8ef)", + "%i, %i, %i, %i, %s, %s, %s)", enumData->playerCueId[base].c_str(), startFrame, endFrame, rotX, rotY, rotZ, startPosX, startPosY, startPosZ, endPosX, - endPosY, endPosZ, normalX, normalY, normalZ); + endPosY, endPosZ, normalXStr.c_str(), normalYStr.c_str(), + normalZStr.c_str()); } else { return StringHelper::Sprintf("CS_ACTOR_CUE(%i, %i, %i, 0x%04X, 0x%04X, 0x%04X, %i, %i, " - "%i, %i, %i, %i, %.8ef, %.8ef, %.8ef)", + "%i, %i, %i, %i, %s, %s, %s)", base, startFrame, endFrame, rotX, rotY, rotZ, startPosX, - startPosY, startPosZ, endPosX, endPosY, endPosZ, normalX, - normalY, normalZ); + startPosY, startPosZ, endPosX, endPosY, endPosZ, + normalXStr.c_str(), normalYStr.c_str(), normalZStr.c_str()); } } diff --git a/ZAPD/ZCutscene.cpp b/ZAPD/ZCutscene.cpp index b90fb872..4cf37599 100644 --- a/ZAPD/ZCutscene.cpp +++ b/ZAPD/ZCutscene.cpp @@ -372,3 +372,36 @@ ZResourceType ZCutscene::GetResourceType() const { return ZResourceType::Cutscene; } + +std::string ZCutscene::GetCsEncodedFloat(float f, CsFloatType type, bool useSciNotation) +{ + switch (type) + { + default: + // This default case will NEVER be reached, but GCC still gives a warning. + case CsFloatType::HexOnly: + { + uint32_t i; + std::memcpy(&i, &f, sizeof(i)); + return StringHelper::Sprintf("0x%08X", i); + } + case CsFloatType::FloatOnly: + { + if (useSciNotation) + { + return StringHelper::Sprintf("%.8ef", f); + } + return StringHelper::Sprintf("%ff", f); + } + case CsFloatType::HexAndFloat: + { + uint32_t i; + std::memcpy(&i, &f, sizeof(i)); + if (useSciNotation) + { + return StringHelper::Sprintf("CS_FLOAT(0x%08X, %.8ef)", i, f); + } + return StringHelper::Sprintf("CS_FLOAT(0x%08X, %ff)", i, f); + } + } +} diff --git a/ZAPD/ZCutscene.h b/ZAPD/ZCutscene.h index 5b54426c..5dbf475c 100644 --- a/ZAPD/ZCutscene.h +++ b/ZAPD/ZCutscene.h @@ -10,6 +10,8 @@ #include "ZFile.h" #include "ZResource.h" +enum class CsFloatType; + class ZCutscene : public ZResource { public: @@ -27,6 +29,8 @@ class ZCutscene : public ZResource std::string GetSourceTypeName() const override; ZResourceType GetResourceType() const override; + static std::string GetCsEncodedFloat(float f, CsFloatType type, bool useSciNotation); + int32_t numCommands; int32_t endFrame; std::vector commands;