mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-08-20 21:33:40 -07:00
git subrepo clone https://github.com/HarbourMasters/ZAPDTR.git
subrepo: subdir: "ZAPDTR" merged: "a53a53ea4" upstream: origin: "https://github.com/HarbourMasters/ZAPDTR.git" branch: "master" commit: "a53a53ea4" git-subrepo: version: "0.4.1" origin: "???" commit: "???"
This commit is contained in:
parent
f52a2a6406
commit
5dda5762ba
217 changed files with 47152 additions and 0 deletions
427
ZAPDTR/ZAPD/ZRoom/ZRoom.cpp
Normal file
427
ZAPDTR/ZAPD/ZRoom/ZRoom.cpp
Normal file
|
@ -0,0 +1,427 @@
|
|||
#include "ZRoom.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <cinttypes>
|
||||
#include <string_view>
|
||||
|
||||
#include "Commands/EndMarker.h"
|
||||
#include "Commands/SetActorCutsceneList.h"
|
||||
#include "Commands/SetActorList.h"
|
||||
#include "Commands/SetAlternateHeaders.h"
|
||||
#include "Commands/SetAnimatedMaterialList.h"
|
||||
#include "Commands/SetCameraSettings.h"
|
||||
#include "Commands/SetCollisionHeader.h"
|
||||
#include "Commands/SetCsCamera.h"
|
||||
#include "Commands/SetCutscenes.h"
|
||||
#include "Commands/SetEchoSettings.h"
|
||||
#include "Commands/SetEntranceList.h"
|
||||
#include "Commands/SetExitList.h"
|
||||
#include "Commands/SetLightList.h"
|
||||
#include "Commands/SetLightingSettings.h"
|
||||
#include "Commands/SetMesh.h"
|
||||
#include "Commands/SetMinimapChests.h"
|
||||
#include "Commands/SetMinimapList.h"
|
||||
#include "Commands/SetObjectList.h"
|
||||
#include "Commands/SetPathways.h"
|
||||
#include "Commands/SetRoomBehavior.h"
|
||||
#include "Commands/SetRoomList.h"
|
||||
#include "Commands/SetSkyboxModifier.h"
|
||||
#include "Commands/SetSkyboxSettings.h"
|
||||
#include "Commands/SetSoundSettings.h"
|
||||
#include "Commands/SetSpecialObjects.h"
|
||||
#include "Commands/SetStartPositionList.h"
|
||||
#include "Commands/SetTimeSettings.h"
|
||||
#include "Commands/SetTransitionActorList.h"
|
||||
#include "Commands/SetWind.h"
|
||||
#include "Commands/SetWorldMapVisited.h"
|
||||
#include "Commands/Unused09.h"
|
||||
#include "Commands/Unused1D.h"
|
||||
#include "Commands/ZRoomCommandUnk.h"
|
||||
#include "Globals.h"
|
||||
#include "Utils/File.h"
|
||||
#include "Utils/Path.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "ZBlob.h"
|
||||
#include "ZCutscene.h"
|
||||
#include "ZFile.h"
|
||||
|
||||
REGISTER_ZFILENODE(Room, ZRoom);
|
||||
REGISTER_ZFILENODE(Scene, ZRoom);
|
||||
REGISTER_ZFILENODE(AltHeader, ZRoom);
|
||||
|
||||
ZRoom::ZRoom(ZFile* nParent) : ZResource(nParent)
|
||||
{
|
||||
roomCount = -1;
|
||||
canHaveInner = true;
|
||||
RegisterOptionalAttribute("HackMode");
|
||||
}
|
||||
|
||||
ZRoom::~ZRoom()
|
||||
{
|
||||
for (ZRoomCommand* cmd : commands)
|
||||
delete cmd;
|
||||
}
|
||||
|
||||
void ZRoom::ExtractFromXML(tinyxml2::XMLElement* reader, uint32_t nRawDataIndex)
|
||||
{
|
||||
ZResource::ExtractFromXML(reader, nRawDataIndex);
|
||||
|
||||
if (hackMode == "syotes_room")
|
||||
{
|
||||
SyotesRoomHack();
|
||||
}
|
||||
else
|
||||
{
|
||||
DeclareVar(name, "");
|
||||
}
|
||||
}
|
||||
|
||||
void ZRoom::ExtractFromBinary(uint32_t nRawDataIndex, ZResourceType parentType)
|
||||
{
|
||||
rawDataIndex = nRawDataIndex;
|
||||
name = GetDefaultName(parent->GetName());
|
||||
|
||||
zroomType = ZResourceType::AltHeader;
|
||||
switch (parentType)
|
||||
{
|
||||
case ZResourceType::Scene:
|
||||
case ZResourceType::Room:
|
||||
case ZResourceType::AltHeader:
|
||||
parentZroomType = parentType;
|
||||
break;
|
||||
|
||||
default:
|
||||
// TODO: error message or something
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
ParseRawData();
|
||||
DeclareVar(name, "");
|
||||
}
|
||||
|
||||
void ZRoom::ParseXML(tinyxml2::XMLElement* reader)
|
||||
{
|
||||
ZResource::ParseXML(reader);
|
||||
|
||||
// TODO: HACK: remove this specific check when the repo uses the correct HackMode="syotes_room"
|
||||
if (name == "syotes_room_0")
|
||||
{
|
||||
hackMode = "syotes_room";
|
||||
}
|
||||
|
||||
std::string nodeName = std::string(reader->Name());
|
||||
if (nodeName == "Scene")
|
||||
{
|
||||
zroomType = ZResourceType::Scene;
|
||||
}
|
||||
else if (nodeName == "Room")
|
||||
zroomType = ZResourceType::Room;
|
||||
else if (nodeName == "AltHeader")
|
||||
zroomType = ZResourceType::AltHeader;
|
||||
|
||||
if (reader->Attribute("HackMode") != nullptr)
|
||||
{
|
||||
hackMode = std::string(reader->Attribute("HackMode"));
|
||||
if (hackMode != "syotes_room")
|
||||
{
|
||||
std::string headerError = StringHelper::Sprintf(
|
||||
"invalid value found for 'HackMode' attribute: '%s'", hackMode.c_str());
|
||||
HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
|
||||
headerError, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ZRoom::ParseRawData()
|
||||
{
|
||||
if (hackMode == "syotes_room")
|
||||
return;
|
||||
|
||||
bool shouldContinue = true;
|
||||
uint32_t currentIndex = 0;
|
||||
uint32_t currentPtr = rawDataIndex;
|
||||
|
||||
const auto& rawData = parent->GetRawData();
|
||||
while (shouldContinue)
|
||||
{
|
||||
RoomCommand opcode = static_cast<RoomCommand>(rawData.at(currentPtr));
|
||||
|
||||
ZRoomCommand* cmd = nullptr;
|
||||
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case RoomCommand::SetStartPositionList:
|
||||
cmd = new SetStartPositionList(parent);
|
||||
break; // 0x00
|
||||
case RoomCommand::SetActorList:
|
||||
cmd = new SetActorList(parent);
|
||||
break; // 0x01
|
||||
case RoomCommand::SetCsCamera:
|
||||
cmd = new SetCsCamera(parent);
|
||||
break; // 0x02 (MM-ONLY)
|
||||
case RoomCommand::SetCollisionHeader:
|
||||
cmd = new SetCollisionHeader(parent);
|
||||
break; // 0x03
|
||||
case RoomCommand::SetRoomList:
|
||||
cmd = new SetRoomList(parent);
|
||||
break; // 0x04
|
||||
case RoomCommand::SetWind:
|
||||
cmd = new SetWind(parent);
|
||||
break; // 0x05
|
||||
case RoomCommand::SetEntranceList:
|
||||
cmd = new SetEntranceList(parent);
|
||||
break; // 0x06
|
||||
case RoomCommand::SetSpecialObjects:
|
||||
cmd = new SetSpecialObjects(parent);
|
||||
break; // 0x07
|
||||
case RoomCommand::SetRoomBehavior:
|
||||
cmd = new SetRoomBehavior(parent);
|
||||
break; // 0x08
|
||||
case RoomCommand::Unused09:
|
||||
cmd = new Unused09(parent);
|
||||
break; // 0x09
|
||||
case RoomCommand::SetMesh:
|
||||
cmd = new SetMesh(parent);
|
||||
break; // 0x0A
|
||||
case RoomCommand::SetObjectList:
|
||||
cmd = new SetObjectList(parent);
|
||||
break; // 0x0B
|
||||
case RoomCommand::SetLightList:
|
||||
cmd = new SetLightList(parent);
|
||||
break; // 0x0C (MM-ONLY)
|
||||
case RoomCommand::SetPathways:
|
||||
cmd = new SetPathways(parent);
|
||||
break; // 0x0D
|
||||
case RoomCommand::SetTransitionActorList:
|
||||
cmd = new SetTransitionActorList(parent);
|
||||
break; // 0x0E
|
||||
case RoomCommand::SetLightingSettings:
|
||||
cmd = new SetLightingSettings(parent);
|
||||
break; // 0x0F
|
||||
case RoomCommand::SetTimeSettings:
|
||||
cmd = new SetTimeSettings(parent);
|
||||
break; // 0x10
|
||||
case RoomCommand::SetSkyboxSettings:
|
||||
cmd = new SetSkyboxSettings(parent);
|
||||
break; // 0x11
|
||||
case RoomCommand::SetSkyboxModifier:
|
||||
cmd = new SetSkyboxModifier(parent);
|
||||
break; // 0x12
|
||||
case RoomCommand::SetExitList:
|
||||
cmd = new SetExitList(parent);
|
||||
break; // 0x13
|
||||
case RoomCommand::EndMarker:
|
||||
cmd = new EndMarker(parent);
|
||||
break; // 0x14
|
||||
case RoomCommand::SetSoundSettings:
|
||||
cmd = new SetSoundSettings(parent);
|
||||
break; // 0x15
|
||||
case RoomCommand::SetEchoSettings:
|
||||
cmd = new SetEchoSettings(parent);
|
||||
break; // 0x16
|
||||
case RoomCommand::SetCutscenes:
|
||||
cmd = new SetCutscenes(parent);
|
||||
break; // 0x17
|
||||
case RoomCommand::SetAlternateHeaders:
|
||||
cmd = new SetAlternateHeaders(parent);
|
||||
break; // 0x18
|
||||
case RoomCommand::SetCameraSettings:
|
||||
if (Globals::Instance->game == ZGame::MM_RETAIL)
|
||||
cmd = new SetWorldMapVisited(parent);
|
||||
else
|
||||
cmd = new SetCameraSettings(parent);
|
||||
break; // 0x19
|
||||
case RoomCommand::SetAnimatedMaterialList:
|
||||
cmd = new SetAnimatedMaterialList(parent);
|
||||
break; // 0x1A (MM-ONLY)
|
||||
case RoomCommand::SetActorCutsceneList:
|
||||
cmd = new SetActorCutsceneList(parent);
|
||||
break; // 0x1B (MM-ONLY)
|
||||
case RoomCommand::SetMinimapList:
|
||||
cmd = new SetMinimapList(parent);
|
||||
break; // 0x1C (MM-ONLY)
|
||||
case RoomCommand::Unused1D:
|
||||
cmd = new Unused1D(parent);
|
||||
break; // 0x1D
|
||||
case RoomCommand::SetMinimapChests:
|
||||
cmd = new SetMinimapChests(parent);
|
||||
break; // 0x1E (MM-ONLY)
|
||||
default:
|
||||
cmd = new ZRoomCommandUnk(parent);
|
||||
}
|
||||
|
||||
cmd->commandSet = rawDataIndex;
|
||||
cmd->ExtractCommandFromRoom(this, currentPtr);
|
||||
|
||||
if (Globals::Instance->profile)
|
||||
{
|
||||
auto end = std::chrono::steady_clock::now();
|
||||
int64_t diff =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||
if (diff > 50)
|
||||
printf("OP: %s, TIME: %" PRIi64 "ms\n", cmd->GetCommandCName().c_str(), diff);
|
||||
}
|
||||
|
||||
cmd->cmdIndex = currentIndex;
|
||||
|
||||
commands.push_back(cmd);
|
||||
|
||||
if (opcode == RoomCommand::EndMarker)
|
||||
shouldContinue = false;
|
||||
|
||||
currentPtr += 8;
|
||||
currentIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
void ZRoom::DeclareReferences(const std::string& prefix)
|
||||
{
|
||||
for (auto& cmd : commands)
|
||||
cmd->DeclareReferences(prefix);
|
||||
}
|
||||
|
||||
void ZRoom::ParseRawDataLate()
|
||||
{
|
||||
for (auto& cmd : commands)
|
||||
cmd->ParseRawDataLate();
|
||||
}
|
||||
|
||||
void ZRoom::DeclareReferencesLate(const std::string& prefix)
|
||||
{
|
||||
for (auto& cmd : commands)
|
||||
cmd->DeclareReferencesLate(prefix);
|
||||
}
|
||||
|
||||
Declaration* ZRoom::DeclareVar(const std::string& prefix, const std::string& body)
|
||||
{
|
||||
std::string auxName = name;
|
||||
if (auxName == "")
|
||||
auxName = GetDefaultName(prefix);
|
||||
if (zroomType == ZResourceType::Scene || zroomType == ZResourceType::Room)
|
||||
auxName = StringHelper::Sprintf("%sCommands", name.c_str());
|
||||
|
||||
Declaration* decl =
|
||||
parent->AddDeclarationArray(rawDataIndex, GetDeclarationAlignment(), GetRawDataSize(),
|
||||
GetSourceTypeName(), auxName, commands.size(), body);
|
||||
decl->staticConf = staticConf;
|
||||
return decl;
|
||||
}
|
||||
|
||||
std::string ZRoom::GetBodySourceCode() const
|
||||
{
|
||||
std::string declaration;
|
||||
|
||||
for (size_t i = 0; i < commands.size(); i++)
|
||||
{
|
||||
ZRoomCommand* cmd = commands[i];
|
||||
declaration += StringHelper::Sprintf("\t%s,", cmd->GetBodySourceCode().c_str());
|
||||
|
||||
if (i + 1 < commands.size())
|
||||
declaration += "\n";
|
||||
}
|
||||
|
||||
return declaration;
|
||||
}
|
||||
|
||||
std::string ZRoom::GetDefaultName(const std::string& prefix) const
|
||||
{
|
||||
return StringHelper::Sprintf("%sSet_%06X", prefix.c_str(), rawDataIndex);
|
||||
}
|
||||
|
||||
/*
|
||||
* There is one room in Ocarina of Time that lacks a header. Room 120, "Syotes", dates
|
||||
* back to very early in the game's development. Since this room is a special case,
|
||||
* declare automatically the data its contains whitout the need of a header.
|
||||
*/
|
||||
void ZRoom::SyotesRoomHack()
|
||||
{
|
||||
PolygonType2 poly(parent, 0, this);
|
||||
|
||||
poly.ParseRawData();
|
||||
poly.DeclareReferences(GetName());
|
||||
parent->AddDeclaration(0, poly.GetDeclarationAlignment(), poly.GetRawDataSize(),
|
||||
poly.GetSourceTypeName(), poly.GetDefaultName(GetName()),
|
||||
poly.GetBodySourceCode());
|
||||
}
|
||||
|
||||
ZRoomCommand* ZRoom::FindCommandOfType(RoomCommand cmdType)
|
||||
{
|
||||
for (size_t i = 0; i < commands.size(); i++)
|
||||
{
|
||||
if (commands[i]->GetRoomCommand() == cmdType)
|
||||
return commands[i];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t ZRoom::GetDeclarationSizeFromNeighbor(uint32_t declarationAddress)
|
||||
{
|
||||
auto currentDecl = parent->declarations.find(declarationAddress);
|
||||
if (currentDecl == parent->declarations.end())
|
||||
return 0;
|
||||
|
||||
auto nextDecl = currentDecl;
|
||||
std::advance(nextDecl, 1);
|
||||
if (nextDecl == parent->declarations.end())
|
||||
return parent->GetRawData().size() - currentDecl->first;
|
||||
|
||||
return nextDecl->first - currentDecl->first;
|
||||
}
|
||||
|
||||
size_t ZRoom::GetCommandSizeFromNeighbor(ZRoomCommand* cmd)
|
||||
{
|
||||
int32_t cmdIndex = -1;
|
||||
|
||||
for (size_t i = 0; i < commands.size(); i++)
|
||||
{
|
||||
if (commands[i] == cmd)
|
||||
{
|
||||
cmdIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmdIndex != -1)
|
||||
{
|
||||
if (cmdIndex + 1 < (int32_t)commands.size())
|
||||
return commands[cmdIndex + 1]->cmdAddress - commands[cmdIndex]->cmdAddress;
|
||||
else
|
||||
return parent->GetRawData().size() - commands[cmdIndex]->cmdAddress;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ZRoom::GetSourceOutputCode([[maybe_unused]] const std::string& prefix)
|
||||
{
|
||||
if (hackMode != "syotes_room")
|
||||
DeclareVar(prefix, GetBodySourceCode());
|
||||
}
|
||||
|
||||
size_t ZRoom::GetRawDataSize() const
|
||||
{
|
||||
size_t size = 0;
|
||||
|
||||
for (ZRoomCommand* cmd : commands)
|
||||
size += cmd->GetRawDataSize();
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
std::string ZRoom::GetSourceTypeName() const
|
||||
{
|
||||
return "SceneCmd";
|
||||
}
|
||||
|
||||
ZResourceType ZRoom::GetResourceType() const
|
||||
{
|
||||
assert(zroomType == ZResourceType::Scene || zroomType == ZResourceType::Room ||
|
||||
zroomType == ZResourceType::AltHeader);
|
||||
return zroomType;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue