#include "RoomExporter.h" #include "CollisionExporter.h" #include "Utils/BinaryWriter.h" #include "Utils/File.h" #include "Utils/MemoryStream.h" #include "ZRoom/Commands/SetCameraSettings.h" #include "ZRoom/Commands/SetCollisionHeader.h" #include "ZRoom/Commands/SetCsCamera.h" #include "ZRoom/Commands/SetEchoSettings.h" #include "ZRoom/Commands/SetEntranceList.h" #include "ZRoom/Commands/SetLightingSettings.h" #include "ZRoom/Commands/SetMesh.h" #include "ZRoom/Commands/SetRoomBehavior.h" #include "ZRoom/Commands/SetRoomList.h" #include "ZRoom/Commands/SetSkyboxModifier.h" #include "ZRoom/Commands/SetSkyboxSettings.h" #include "ZRoom/Commands/SetSoundSettings.h" #include "ZRoom/Commands/SetSpecialObjects.h" #include "ZRoom/Commands/SetStartPositionList.h" #include "ZRoom/Commands/SetTimeSettings.h" #include "ZRoom/Commands/SetWind.h" void ExporterExample_Room::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) { ZRoom* room = dynamic_cast(res); // MemoryStream* memStream = new MemoryStream(); // BinaryWriter* writer = new BinaryWriter(memStream); for (size_t i = 0; i < room->commands.size() * 8; i++) writer->Write((uint8_t)0); for (size_t i = 0; i < room->commands.size(); i++) { ZRoomCommand* cmd = room->commands[i]; writer->Seek(i * 8, SeekOffsetType::Start); writer->Write((uint8_t)cmd->cmdID); switch (cmd->cmdID) { case RoomCommand::SetWind: { SetWind* cmdSetWind = (SetWind*)cmd; writer->Write((uint8_t)0); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write(cmdSetWind->windWest); // 0x04 writer->Write(cmdSetWind->windVertical); // 0x05 writer->Write(cmdSetWind->windSouth); // 0x06 writer->Write(cmdSetWind->clothFlappingStrength); // 0x07 } break; case RoomCommand::SetTimeSettings: { SetTimeSettings* cmdTime = (SetTimeSettings*)cmd; writer->Write((uint8_t)0); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write(cmdTime->hour); // 0x04 writer->Write(cmdTime->min); // 0x05 writer->Write(cmdTime->unk); // 0x06 writer->Write((uint8_t)0); // 0x07 } break; case RoomCommand::SetSkyboxModifier: { SetSkyboxModifier* cmdSkybox = (SetSkyboxModifier*)cmd; writer->Write((uint8_t)0); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write(cmdSkybox->disableSky); // 0x04 writer->Write(cmdSkybox->disableSunMoon); // 0x05 writer->Write((uint8_t)0); // 0x06 writer->Write((uint8_t)0); // 0x07 } break; case RoomCommand::SetEchoSettings: { SetEchoSettings* cmdEcho = (SetEchoSettings*)cmd; writer->Write((uint8_t)0); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write((uint8_t)0); // 0x04 writer->Write((uint8_t)0); // 0x05 writer->Write((uint8_t)0); // 0x06 writer->Write((uint8_t)cmdEcho->echo); // 0x07 } break; case RoomCommand::SetSoundSettings: { SetSoundSettings* cmdSound = (SetSoundSettings*)cmd; writer->Write((uint8_t)cmdSound->reverb); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write((uint8_t)0); // 0x04 writer->Write((uint8_t)0); // 0x05 writer->Write(cmdSound->nightTimeSFX); // 0x06 writer->Write(cmdSound->musicSequence); // 0x07 } break; case RoomCommand::SetSkyboxSettings: { SetSkyboxSettings* cmdSkybox = (SetSkyboxSettings*)cmd; writer->Write((uint8_t)cmdSkybox->unk1); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write((uint8_t)cmdSkybox->skyboxNumber); // 0x04 writer->Write((uint8_t)cmdSkybox->cloudsType); // 0x05 writer->Write((uint8_t)cmdSkybox->isIndoors); // 0x06 } break; case RoomCommand::SetRoomBehavior: { SetRoomBehavior* cmdRoom = (SetRoomBehavior*)cmd; writer->Write((uint8_t)cmdRoom->gameplayFlags); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write(cmdRoom->gameplayFlags2); // 0x04 } break; case RoomCommand::SetCsCamera: { SetCsCamera* cmdCsCam = (SetCsCamera*)cmd; writer->Write((uint8_t)cmdCsCam->cameras.size()); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write(cmdCsCam->segmentOffset); // 0x04 } break; case RoomCommand::SetMesh: { SetMesh* cmdMesh = (SetMesh*)cmd; int baseStreamEnd = writer->GetStream().get()->GetLength(); writer->Write((uint8_t)cmdMesh->data); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write(baseStreamEnd); // 0x04 uint32_t oldOffset = writer->GetBaseAddress(); writer->Seek(baseStreamEnd, SeekOffsetType::Start); // TODO: NOT DONE writer->Write(cmdMesh->meshHeaderType); if (cmdMesh->meshHeaderType == 0) { // writer->Write(cmdMesh->) } else if (cmdMesh->meshHeaderType == 1) { } else if (cmdMesh->meshHeaderType == 2) { } writer->Seek(oldOffset, SeekOffsetType::Start); } break; case RoomCommand::SetCameraSettings: { SetCameraSettings* cmdCam = (SetCameraSettings*)cmd; writer->Write((uint8_t)cmdCam->cameraMovement); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write(cmdCam->mapHighlight); // 0x04 } break; case RoomCommand::SetLightingSettings: { SetLightingSettings* cmdLight = (SetLightingSettings*)cmd; writer->Write((uint8_t)cmdLight->settings.size()); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write(cmdLight->segmentOffset); // 0x04 uint32_t oldOffset = writer->GetBaseAddress(); writer->Seek(cmdLight->segmentOffset, SeekOffsetType::Start); for (LightingSettings setting : cmdLight->settings) { writer->Write(setting.ambientClrR); writer->Write(setting.ambientClrG); writer->Write(setting.ambientClrB); writer->Write(setting.diffuseClrA_R); writer->Write(setting.diffuseClrA_G); writer->Write(setting.diffuseClrA_B); writer->Write(setting.diffuseDirA_X); writer->Write(setting.diffuseDirA_Y); writer->Write(setting.diffuseDirA_Z); writer->Write(setting.diffuseClrB_R); writer->Write(setting.diffuseClrB_G); writer->Write(setting.diffuseClrB_B); writer->Write(setting.diffuseDirB_X); writer->Write(setting.diffuseDirB_Y); writer->Write(setting.diffuseDirB_Z); writer->Write(setting.fogClrR); writer->Write(setting.fogClrG); writer->Write(setting.fogClrB); writer->Write(setting.unk); writer->Write(setting.drawDistance); } writer->Seek(oldOffset, SeekOffsetType::Start); } break; case RoomCommand::SetRoomList: { SetRoomList* cmdRoom = (SetRoomList*)cmd; writer->Write((uint8_t)cmdRoom->romfile->rooms.size()); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 auto baseStreamEnd = writer->GetLength(); writer->Write(baseStreamEnd); // 0x04 uint32_t oldOffset = writer->GetBaseAddress(); writer->Seek(baseStreamEnd, SeekOffsetType::Start); for (const auto& entry : cmdRoom->romfile->rooms) { writer->Write(entry.virtualAddressStart); writer->Write(entry.virtualAddressEnd); } writer->Seek(oldOffset, SeekOffsetType::Start); } break; case RoomCommand::SetCollisionHeader: { SetCollisionHeader* cmdCollHeader = (SetCollisionHeader*)cmd; int streamEnd = writer->GetStream().get()->GetLength(); writer->Write((uint8_t)0); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write(streamEnd); // 0x04 // TODO: NOT DONE uint32_t oldOffset = writer->GetBaseAddress(); writer->Seek(streamEnd, SeekOffsetType::Start); ExporterExample_Collision colExp = ExporterExample_Collision(); colExp.Save(cmdCollHeader->collisionHeader, outPath, writer); writer->Seek(oldOffset, SeekOffsetType::Start); } break; case RoomCommand::SetEntranceList: { SetEntranceList* cmdEntrance = (SetEntranceList*)cmd; uint32_t baseStreamEnd = writer->GetStream().get()->GetLength(); writer->Write((uint8_t)0); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write(baseStreamEnd); // 0x04 uint32_t oldOffset = writer->GetBaseAddress(); writer->Seek(baseStreamEnd, SeekOffsetType::Start); for (EntranceEntry entry : cmdEntrance->entrances) { writer->Write((uint8_t)entry.startPositionIndex); writer->Write((uint8_t)entry.roomToLoad); } writer->Seek(oldOffset, SeekOffsetType::Start); } break; case RoomCommand::SetSpecialObjects: { SetSpecialObjects* cmdSpecObj = (SetSpecialObjects*)cmd; writer->Write((uint8_t)cmdSpecObj->elfMessage); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write((uint8_t)0); // 0x04 writer->Write((uint8_t)0); // 0x05 writer->Write((uint16_t)cmdSpecObj->globalObject); // 0x06 } break; case RoomCommand::SetStartPositionList: { SetStartPositionList* cmdStartPos = (SetStartPositionList*)cmd; uint32_t baseStreamEnd = writer->GetStream().get()->GetLength(); writer->Write((uint8_t)cmdStartPos->actors.size()); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write(baseStreamEnd); // 0x04 uint32_t oldOffset = writer->GetBaseAddress(); writer->Seek(baseStreamEnd, SeekOffsetType::Start); for (ActorSpawnEntry entry : cmdStartPos->actors) { writer->Write(entry.actorNum); writer->Write(entry.posX); writer->Write(entry.posY); writer->Write(entry.posZ); writer->Write(entry.rotX); writer->Write(entry.rotY); writer->Write(entry.rotZ); writer->Write(entry.initVar); } writer->Seek(oldOffset, SeekOffsetType::Start); } break; case RoomCommand::EndMarker: { writer->Write((uint8_t)0); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write((uint8_t)0); // 0x04 writer->Write((uint8_t)0); // 0x05 writer->Write((uint8_t)0); // 0x06 writer->Write((uint8_t)0); // 0x07 } break; default: printf("UNIMPLEMENTED COMMAND: %i\n", (int)cmd->cmdID); writer->Write((uint8_t)0); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 writer->Write((uint8_t)0); // 0x04 writer->Write((uint8_t)0); // 0x05 writer->Write((uint8_t)0); // 0x06 writer->Write((uint8_t)0); // 0x07 break; } } // writer->Close(); // File::WriteAllBytes(StringHelper::Sprintf("%s", res->GetName().c_str()), // memStream->ToVector()); }