20 return absl::FailedPreconditionError(
21 absl::StrFormat(
"Cannot load connection room %03X: %s", room_id,
22 stream.status().message()));
26 const auto header_table_bank = (header_table >> 16) & 0xFF;
27 if ((header_table & 0xFFFF) < 0x8000 || header_table_bank == 0x7E ||
28 header_table_bank == 0x7F || header_table_bank == 0xFE ||
29 header_table_bank == 0xFF) {
30 return absl::FailedPreconditionError(
"Invalid room header pointer table");
36 const auto header_pc =
SnesToPc((bank << 16) | header);
37 if (header < 0x8000 || bank == 0x7E || bank == 0x7F || bank == 0xFE ||
38 bank == 0xFF ||
static_cast<size_t>(header_pc) + 14 > rom.
size()) {
39 return absl::FailedPreconditionError(
"Invalid connection room header");
41 return absl::OkStatus();
59 return absl::FailedPreconditionError(
"Connection room is unavailable");
62 if (existing && existing->rom() !=
rom_) {
63 return absl::FailedPreconditionError(
64 "Connection room belongs to another ROM");
66 if (existing && existing->IsLoaded() && existing->AreObjectsLoaded()) {
67 return absl::OkStatus();
69 if (existing && existing->HasUnsavedChanges()) {
70 return absl::FailedPreconditionError(
71 "Open the destination room to finish loading its unsaved edits");
75 if (!loaded.AreObjectsLoaded()) {
76 return absl::FailedPreconditionError(
77 "Connection room objects did not load");
84 const auto& zone = existing->water_fill_zone();
85 loaded.set_water_fill_sram_bit_mask(zone.sram_bit_mask);
86 for (
size_t tile = 0; tile < zone.tiles.size(); ++tile) {
87 if (zone.tiles[tile] != 0) {
88 loaded.SetWaterFillTile(
static_cast<int>(tile % 64),
89 static_cast<int>(tile / 64),
true);
92 loaded.ClearWaterFillDirty();
95 rooms_[room_id] = std::move(loaded);
96 return absl::OkStatus();
103 !source->AreObjectsLoaded()) {
104 return absl::FailedPreconditionError(
105 "Source connection room is not loaded");
108 return absl::OutOfRangeError(
"Selected door is no longer available");
122 return absl::FailedPreconditionError(
123 "Connection preview belongs to another ROM");
126 if (!SameConnectionPlan(preview, current)) {
127 return absl::FailedPreconditionError(
128 "Connection changed since preview; review the endpoints again");
130 if (!current.changed()) {
131 return absl::OkStatus();
137 if (!SameConnectionPlan(preview, current)) {
138 return absl::FailedPreconditionError(
139 "Connection changed while finishing a gesture; review the endpoints "
143 auto capture = [&](
int room_id,
const std::vector<zelda3::Room::Door>& before,
144 const std::vector<zelda3::Room::Door>& after) {
149 bool captured =
false;
151 if (!viewer || captured || viewer->current_room_id() != room_id)
153 auto& interaction = viewer->object_interaction();
155 interaction.entity_coordinator().tile_handler().context();
160 interaction.entity_coordinator().SelectedEntitiesForEdit();
165 [&](
int, std::unique_ptr<DungeonCanvasViewer>& viewer) {
166 read_selection(viewer.get());
173 std::vector<DungeonSelectionEditPlan> edits;
174 edits.push_back(capture(current.request.source_room_id, current.source_before,
175 current.source_after));
176 edits.push_back(capture(current.target_room_id, current.target_before,
177 current.target_after));
185 "dungeon connection authoring",
"DungeonEditorV2",
nullptr));
192 absl::StrFormat(
"Connect rooms %03X and %03X",
193 current.request.source_room_id, current.target_room_id));
194 return absl::OkStatus();
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
absl::StatusOr< uint8_t > ReadByte(int offset) const
absl::StatusOr< uint16_t > ReadWord(int offset) const
absl::StatusOr< uint32_t > ReadLong(int offset) const
bool loaded() const
Check if the manifest has been loaded.
util::LruCache< int, std::unique_ptr< DungeonCanvasViewer > > room_viewers_
absl::Status ApplyDoorConnection(const DungeonConnectionPlan &plan)
void FinalizePendingUndoActions()
absl::StatusOr< std::vector< std::pair< uint32_t, uint32_t > > > PlanPendingRoomStreamRanges(const std::vector< DungeonSelectionEditPlan > &candidates) const
absl::Status RestoreSelectionEditBatch(const std::vector< DungeonSelectionEditPlan > &plans, bool after)
std::unique_ptr< DungeonCanvasViewer > workbench_compare_viewer_
static bool IsValidRoomId(int room_id)
absl::Status EnsureConnectionRoomLoaded(int room_id)
zelda3::GameData * game_data_
std::unique_ptr< DungeonCanvasViewer > workbench_viewer_
absl::StatusOr< DungeonConnectionPlan > PreviewDoorConnection(const DungeonConnectionRequest &request)
void PushSelectionUndoBatch(std::vector< DungeonSelectionEditPlan > plans, std::string description)
zelda3::Room * GetIfMaterialized(int room_id)
zelda3::Room * GetIfLoaded(int room_id)
EditorContext context() const
EditorDependencies dependencies_
#define ASSIGN_OR_RETURN(type_variable_name, expression)
bool SameConnectionPlan(const DungeonConnectionPlan &a, const DungeonConnectionPlan &b)
absl::Status ValidateConnectionRoomSource(const Rom &rom, int room_id)
Editors are the view controllers for the application.
bool SameDungeonDoors(const std::vector< Door > &first, const std::vector< Door > &second)
absl::Status ValidateHackManifestSaveConflicts(const core::HackManifest &manifest, project::RomWritePolicy write_policy, const std::vector< std::pair< uint32_t, uint32_t > > &ranges, absl::string_view save_scope, const char *log_tag, ToastManager *toast_manager)
absl::StatusOr< int > DungeonConnectionTargetRoom(int source_room_id, const Door &door)
constexpr uint8_t kSelectionDoors
absl::StatusOr< DungeonConnectionPlan > PlanDungeonDoorConnection(const zelda3::Room &source, const zelda3::Room &target, const DungeonConnectionRequest &request)
Room LoadRoomFromRom(Rom *rom, int room_id)
absl::StatusOr< DungeonStreamRecord > ReadDungeonObjectStream(const Rom &rom, int room_id)
constexpr int kRoomHeaderPointer
constexpr int kRoomHeaderPointerBank
uint32_t SnesToPc(uint32_t addr) noexcept
#define RETURN_IF_ERROR(expr)
std::vector< zelda3::Room::Door > target_after
DungeonConnectionRequest request
std::vector< zelda3::Room::Door > target_before
std::vector< zelda3::Room::Door > source_before
std::vector< zelda3::Room::Door > source_after
DungeonSelectionEditState before
DungeonSelectionEditState after
std::vector< SelectedEntity > selected_entities
std::vector< zelda3::Room::Door > doors
std::vector< size_t > selected_objects
project::YazeProject * project
core::HackManifest hack_manifest