#include "2s2h/resource/importer/CutsceneFactory.h" #include "2s2h/resource/type/Cutscene.h" extern "C" { #include "z64cutscene.h" } namespace SOH { static inline uint32_t read_CMD_BBBB(std::shared_ptr reader) { uint32_t v; reader->Read((char*)&v, sizeof(uint32_t)); return v; } static inline uint32_t read_CMD_BBH(std::shared_ptr reader) { uint32_t v; reader->Read((char*)&v, sizeof(uint32_t)); // swap the half word to match endianness if (reader->GetEndianness() != Ship::Endianness::Native) { uint8_t* b = (uint8_t*)&v; uint8_t tmp = b[2]; b[2] = b[3]; b[3] = tmp; } return v; } static inline uint32_t read_CMD_HBB(std::shared_ptr reader) { uint32_t v; reader->Read((char*)&v, sizeof(uint32_t)); // swap the half word to match endianness if (reader->GetEndianness() != Ship::Endianness::Native) { uint8_t* b = (uint8_t*)&v; uint8_t tmp = b[0]; b[0] = b[1]; b[1] = tmp; } return v; } static inline uint32_t read_CMD_HH(std::shared_ptr reader) { uint32_t v; reader->Read((char*)&v, sizeof(uint32_t)); // swap the half words to match endianness if (reader->GetEndianness() != Ship::Endianness::Native) { uint8_t* b = (uint8_t*)&v; uint8_t tmp = b[0]; b[0] = b[1]; b[1] = tmp; tmp = b[2]; b[2] = b[3]; b[3] = tmp; } return v; } std::shared_ptr ResourceFactoryBinaryCutsceneV0::ReadResource(std::shared_ptr file, std::shared_ptr initData) { if (!FileHasValidFormatAndReader(file, initData)) { return nullptr; } auto cutscene = std::make_shared(initData); auto reader = std::get>(file->Reader); uint32_t numEntries = reader->ReadUInt32(); cutscene->commands.reserve(numEntries); cutscene->numCommands = reader->ReadUInt32(); cutscene->commands.push_back(cutscene->numCommands); cutscene->endFrame = reader->ReadUInt32(); cutscene->commands.push_back(cutscene->endFrame); // BENTODO detect the game while (true) { uint32_t command = reader->ReadUInt32(); cutscene->commands.push_back(command); if (((command >= CS_CMD_ACTOR_CUE_100) && (command <= CS_CMD_ACTOR_CUE_149)) || (command == CS_CMD_ACTOR_CUE_201) || ((command >= CS_CMD_ACTOR_CUE_450) && (command <= CS_CMD_ACTOR_CUE_599))) { goto actorCue; } switch (command) { case CS_CMD_TEXT: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); } break; } case CS_CMD_CAMERA_SPLINE: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); while (1) { // We need to store the first half of the header to get the number of entries. uint32_t header1 = read_CMD_HH(reader); uint32_t numEntries = header1 & 0xFFFF; if (reader->GetEndianness() != Ship::Endianness::Native) { numEntries = header1 >> 16 & 0xFFFF; } cutscene->commands.push_back(header1); if (numEntries == 0xFFFF) { break; // Last command is HH(0xFFFF, 0004) which was already read in and pushed into the vector } cutscene->commands.push_back(read_CMD_HH(reader)); for (size_t j = 0; j < numEntries * 2; j++) { cutscene->commands.push_back(read_CMD_BBH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); } for (size_t j = 0; j < numEntries; j++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); } } // for (uint32_t i = 0; i < (size / 4); i++) { // cutscene->commands.push_back(read_CMD_HH(reader)); //} break; } case CS_CMD_MISC: case CS_CMD_LIGHT_SETTING: case CS_CMD_TRANSITION: case CS_CMD_MOTION_BLUR: case CS_CMD_GIVE_TATL: case CS_CMD_START_SEQ: case CS_CMD_STOP_SEQ: case CS_CMD_SFX_REVERB_INDEX_2: case CS_CMD_SFX_REVERB_INDEX_1: case CS_CMD_MODIFY_SEQ: case CS_CMD_START_AMBIENCE: case CS_CMD_FADE_OUT_AMBIENCE: case CS_CMD_DESTINATION: case CS_CMD_CHOOSE_CREDITS_SCENES: default: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); } break; } case CS_CMD_TRANSITION_GENERAL: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HBB(reader)); cutscene->commands.push_back(read_CMD_BBBB(reader)); } break; } case CS_CMD_FADE_OUT_SEQ: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(reader->ReadUInt32()); } break; } case CS_CMD_TIME: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HBB(reader)); cutscene->commands.push_back(reader->ReadUInt32()); } break; } case CS_CMD_PLAYER_CUE: { actorCue: uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); } break; } case CS_CMD_RUMBLE: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HBB(reader)); cutscene->commands.push_back(read_CMD_BBBB(reader)); } break; } case 0xFFFFFFFF: { cutscene->commands.push_back(reader->ReadUInt32()); return cutscene; } } } return cutscene; } #if 0 void Ship::CutsceneFactoryV0::ParseFileBinaryOoT(std::shared_ptr reader, std::shared_ptr cutscene) { while (true) { uint32_t commandId = reader->ReadUInt32(); cutscene->commands.push_back(commandId); switch (commandId) { case (uint32_t)CutsceneCommands::SetCameraPos: { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); while (true) { uint32_t val = read_CMD_BBH(reader); int8_t continueFlag = ((int8_t*)&val)[0]; cutscene->commands.push_back(val); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); if (continueFlag == -1) { break; } } } break; case (uint32_t)CutsceneCommands::SetCameraFocus: { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); while (true) { uint32_t val = read_CMD_BBH(reader); int8_t continueFlag = ((int8_t*)&val)[0]; cutscene->commands.push_back(val); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); if (continueFlag == -1) { break; } } break; } case (uint32_t)CutsceneCommands::SpecialAction: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); } break; } case (uint32_t)CutsceneCommands::SetLighting: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); } break; } case (uint32_t)CutsceneCommands::SetCameraPosLink: { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); while (true) { uint32_t val = read_CMD_BBH(reader); int8_t continueFlag = ((int8_t*)&val)[0]; cutscene->commands.push_back(val); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); if (continueFlag == -1) { break; } } break; } case (uint32_t)CutsceneCommands::SetCameraFocusLink: { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); while (true) { uint32_t val = read_CMD_BBH(reader); int8_t continueFlag = ((int8_t*)&val)[0]; cutscene->commands.push_back(val); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); if (continueFlag == -1) { break; } } break; } case (uint32_t)CutsceneCommands::Cmd09: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HBB(reader)); cutscene->commands.push_back(read_CMD_BBH(reader)); } break; } case 0x15: case (uint32_t)CutsceneCommands::Unknown: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); } } break; case (uint32_t)CutsceneCommands::Textbox: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); } break; } case (uint32_t)CutsceneCommands::SetActorAction0: case (uint32_t)CutsceneCommands::SetActorAction1: case 17: case 18: case 23: case 34: case 39: case 46: case 76: case 85: case 93: case 105: case 107: case 110: case 119: case 123: case 138: case 139: case 144: case (uint32_t)CutsceneCommands::SetActorAction2: case 16: case 24: case 35: case 40: case 48: case 64: case 68: case 70: case 78: case 80: case 94: case 116: case 118: case 120: case 125: case 131: case 141: case (uint32_t)CutsceneCommands::SetActorAction3: case 36: case 41: case 50: case 67: case 69: case 72: case 74: case 81: case 106: case 117: case 121: case 126: case 132: case (uint32_t)CutsceneCommands::SetActorAction4: case 37: case 42: case 51: case 53: case 63: case 65: case 66: case 75: case 82: case 108: case 127: case 133: case (uint32_t)CutsceneCommands::SetActorAction5: case 38: case 43: case 47: case 54: case 79: case 83: case 128: case 135: case (uint32_t)CutsceneCommands::SetActorAction6: case 55: case 77: case 84: case 90: case 129: case 136: case (uint32_t)CutsceneCommands::SetActorAction7: case 52: case 57: case 58: case 88: case 115: case 130: case 137: case (uint32_t)CutsceneCommands::SetActorAction8: case 60: case 89: case 111: case 114: case 134: case 142: case (uint32_t)CutsceneCommands::SetActorAction9: case (uint32_t)CutsceneCommands::SetActorAction10: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); } break; } case (uint32_t)CutsceneCommands::SetSceneTransFX: { cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); break; } case (uint32_t)CutsceneCommands::PlayBGM: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); } break; } case (uint32_t)CutsceneCommands::StopBGM: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); } break; } case (uint32_t)CutsceneCommands::FadeBGM: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(reader->ReadUInt32()); } break; } case (uint32_t)CutsceneCommands::SetTime: { uint32_t size = reader->ReadUInt32(); cutscene->commands.push_back(size); for (uint32_t i = 0; i < size; i++) { cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HBB(reader)); cutscene->commands.push_back(reader->ReadUInt32()); } break; } case (uint32_t)CutsceneCommands::Terminator: { cutscene->commands.push_back(reader->ReadUInt32()); cutscene->commands.push_back(read_CMD_HH(reader)); cutscene->commands.push_back(read_CMD_HH(reader)); break; } case 0xFFFFFFFF: // CS_END { cutscene->commands.push_back(reader->ReadUInt32()); return; } default: SPDLOG_TRACE("CutsceneV0: Unknown command {}\n", commandId); // error? break; } } } #endif } // namespace SOH