yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
object_tile_editor.h
Go to the documentation of this file.
1#ifndef YAZE_ZELDA3_DUNGEON_OBJECT_TILE_EDITOR_H_
2#define YAZE_ZELDA3_DUNGEON_OBJECT_TILE_EDITOR_H_
3
4#include <cstddef>
5#include <cstdint>
6#include <filesystem>
7#include <optional>
8#include <string>
9#include <utility>
10#include <vector>
11
12#include "absl/status/status.h"
13#include "absl/status/statusor.h"
14#include "app/gfx/core/bitmap.h"
17#include "rom/rom.h"
20#include "zelda3/dungeon/room.h"
21
22namespace yaze {
23namespace zelda3 {
24
29 uint32_t pc_address = 0;
30 std::vector<uint16_t> expected_words;
31};
32
40 int16_t object_id = -1;
43 std::vector<ObjectTileSourceSpan> spans;
44};
45
50 size_t span_index = 0;
51 size_t word_index = 0;
52};
53
59 int16_t object_id = -1;
60 std::vector<ObjectTileReadRange> overlapping_ranges;
61};
62
64 // Synthesized room object 0x150 reads the unlit/lit torch blocks directly
65 // during initial room drawing; it is not representable in the persisted
66 // dungeon object stream.
68 // Underworld light/extinguish updates read the same literal blocks again
69 // when replacing the torch tiles at runtime.
71};
72
77
87 std::vector<ObjectTileSourceImpactEntry> affected_objects;
88 std::vector<ObjectTileRuntimeConsumerImpactEntry> runtime_consumers;
89
90 size_t consumer_count() const {
91 return affected_objects.size() + runtime_consumers.size();
92 }
93};
94
102 int16_t object_id = 0;
105
106 struct Cell {
107 int rel_x = 0; // 0-based tile X within bounding box
108 int rel_y = 0; // 0-based tile Y within bounding box
109 gfx::TileInfo tile_info; // Decomposed SNES tilemap word
110 uint16_t original_word = 0;
111 // Legacy name retained for preview/test compatibility. This is draw-trace
112 // order only and never authorizes a ROM write; draw order is not generally
113 // source order.
114 int write_index = -1;
115 std::optional<ObjectTileSourceRef> source_ref;
116 bool modified = false;
117 };
118
119 std::vector<Cell> cells;
120 int bounds_width = 0; // Bounding box width in 8px tiles
121 int bounds_height = 0; // Bounding box height in 8px tiles
122
123 // Legacy display/shared-data metadata. Standard writes are authorized only
124 // by source_provenance + per-cell source_ref, never by this base address.
126 std::optional<ObjectTileSourceProvenance> source_provenance;
127 std::shared_ptr<const DungeonTilePatterns> pattern_source;
128 bool is_custom = false;
130 std::string custom_filename;
131 std::filesystem::path custom_resolved_path;
132 std::vector<uint8_t> custom_source_bytes;
133
135 const std::vector<ObjectDrawer::TileTrace>& traces);
136
137 Cell* FindCell(int rel_x, int rel_y);
138 const Cell* FindCell(int rel_x, int rel_y) const;
139
140 bool HasModifications() const;
141 void RevertAll();
142};
143
151 public:
152 struct Write {
153 int address = -1;
154 uint16_t expected_word = 0;
155 uint16_t word = 0;
156 };
157
159 int address = -1;
160 uint16_t expected_word = 0;
161 };
162
165 ObjectTileWritePlan& operator=(const ObjectTileWritePlan&) = default;
166 ObjectTileWritePlan& operator=(ObjectTileWritePlan&&) noexcept = default;
167
168 bool writes_pattern_source() const { return pattern_source_ != nullptr; }
169 const std::vector<Write>& writes() const { return writes_; }
170 const std::vector<WordPrecondition>& preconditions() const {
171 return preconditions_;
172 }
173 const std::vector<std::pair<uint32_t, uint32_t>>& write_ranges() const {
174 return write_ranges_;
175 }
176
177 private:
178 friend class ObjectTileEditor;
179
181
182 std::shared_ptr<const DungeonTilePatterns> pattern_source_;
183 std::vector<Write> writes_;
184 // Includes the pointer descriptor and every captured source word. Apply
185 // rechecks these immediately before opening the transaction.
186 std::vector<WordPrecondition> preconditions_;
187 std::vector<std::pair<uint32_t, uint32_t>> write_ranges_;
188};
189
198 public:
199 static constexpr int kAtlasTilesPerRow = 16;
200 static constexpr int kAtlasTileRows = 64;
202 static constexpr int kAtlasWidthPx = kAtlasTilesPerRow * 8;
203 static constexpr int kAtlasHeightPx = kAtlasTileRows * 8;
204
205 explicit ObjectTileEditor(Rom* rom);
206
207 // Capture: run object draw in trace_only mode, build editable layout
208 absl::StatusOr<ObjectTileLayout> CaptureObjectLayout(
209 int16_t object_id, const Room& room, const gfx::PaletteGroup& palette);
210 absl::StatusOr<ObjectTileLayout> CaptureObjectLayout(
211 int16_t object_id, const Room& room, const gfx::PaletteGroup& palette,
212 uint8_t object_size);
213
214 // Capture a standard object with exact ROM source provenance. The initial
215 // source maps cover straight walls, 4x4 corners and fixed 2x2 objects.
216 // Repeating walls capture one source unit, independent of placed length.
217 absl::StatusOr<ObjectTileLayout> CaptureEditableObjectLayout(
218 int16_t object_id, const Room& room, const gfx::PaletteGroup& palette);
219
220 // Load one existing fixed runtime custom-object asset directly from its
221 // binary source, including no-op words and exact bytes for stale-write CAS.
222 absl::StatusOr<ObjectTileLayout> LoadCustomObjectLayout(int16_t object_id,
223 int subtype);
224
225 static bool IsEditableStandardObject(int16_t object_id);
226
227 // Render: draw layout to preview bitmap using room's gfx buffer
228 absl::Status RenderLayoutToBitmap(const ObjectTileLayout& layout,
229 gfx::Bitmap& bitmap,
230 const uint8_t* room_gfx_buffer,
231 const gfx::PaletteGroup& palette);
232
233 // Build a source-ID atlas from room graphics. Custom objects show the
234 // runtime-effective tile at each raw source ID without changing saved words.
235 // Retained H/V/priority attributes affect zero-word detection only; atlas
236 // images remain unflipped so their orientation is consistent when browsing.
237 absl::Status BuildTile8Atlas(
238 gfx::Bitmap& atlas, const uint8_t* room_gfx_buffer,
239 const gfx::PaletteGroup& palette, int display_palette = 2,
240 std::optional<int16_t> custom_object_id = std::nullopt,
241 uint16_t retained_attributes = 0);
242
243 // Write-back: standard objects patch ROM, custom objects write .bin
244 absl::Status WriteBack(ObjectTileLayout& layout);
245
246 // Resolve and validate all standard-object writes before any ROM mutation.
247 absl::StatusOr<ObjectTileWritePlan> BuildStandardWritePlan(
248 const ObjectTileLayout& layout) const;
249
250 // Atomically apply a previously validated standard-object write plan.
251 absl::Status ApplyStandardWritePlan(const ObjectTileWritePlan& plan);
252
253 // Enumerate every representable standard object whose parser-visible source
254 // ranges overlap this editable layout, plus the explicit runtime consumers
255 // modeled by this backend. Resolution errors are returned to the caller and
256 // must block writes rather than being interpreted as no sharing. Other
257 // runtime-only behavior remains a separate parity-audit concern.
258 absl::StatusOr<ObjectTileSourceImpact> AnalyzeStandardTileSourceImpact(
259 const ObjectTileLayout& layout) const;
260
261 private:
263};
264
265} // namespace zelda3
266} // namespace yaze
267
268#endif // YAZE_ZELDA3_DUNGEON_OBJECT_TILE_EDITOR_H_
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:49
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:70
SNES 16-bit tile metadata container.
Definition snes_tile.h:52
Captures and edits the tile8 composition of dungeon objects.
absl::StatusOr< ObjectTileSourceImpact > AnalyzeStandardTileSourceImpact(const ObjectTileLayout &layout) const
absl::Status ApplyStandardWritePlan(const ObjectTileWritePlan &plan)
static constexpr int kAtlasTilesPerRow
absl::Status RenderLayoutToBitmap(const ObjectTileLayout &layout, gfx::Bitmap &bitmap, const uint8_t *room_gfx_buffer, const gfx::PaletteGroup &palette)
static bool IsEditableStandardObject(int16_t object_id)
absl::Status BuildTile8Atlas(gfx::Bitmap &atlas, const uint8_t *room_gfx_buffer, const gfx::PaletteGroup &palette, int display_palette=2, std::optional< int16_t > custom_object_id=std::nullopt, uint16_t retained_attributes=0)
absl::StatusOr< ObjectTileLayout > CaptureObjectLayout(int16_t object_id, const Room &room, const gfx::PaletteGroup &palette)
absl::Status WriteBack(ObjectTileLayout &layout)
absl::StatusOr< ObjectTileLayout > CaptureEditableObjectLayout(int16_t object_id, const Room &room, const gfx::PaletteGroup &palette)
absl::StatusOr< ObjectTileWritePlan > BuildStandardWritePlan(const ObjectTileLayout &layout) const
absl::StatusOr< ObjectTileLayout > LoadCustomObjectLayout(int16_t object_id, int subtype)
Fully resolved standard-object ROM writes.
std::vector< std::pair< uint32_t, uint32_t > > write_ranges_
const std::vector< Write > & writes() const
const std::vector< WordPrecondition > & preconditions() const
std::vector< WordPrecondition > preconditions_
ObjectTileWritePlan(const ObjectTileWritePlan &)=default
const std::vector< std::pair< uint32_t, uint32_t > > & write_ranges() const
std::shared_ptr< const DungeonTilePatterns > pattern_source_
ObjectTileWritePlan(ObjectTileWritePlan &&) noexcept=default
Represents a group of palettes.
std::optional< ObjectTileSourceRef > source_ref
Editable tile8 layout captured from an object's draw trace.
std::shared_ptr< const DungeonTilePatterns > pattern_source
std::vector< uint8_t > custom_source_bytes
std::optional< ObjectTileSourceProvenance > source_provenance
std::filesystem::path custom_resolved_path
Cell * FindCell(int rel_x, int rel_y)
static ObjectTileLayout FromTraces(const std::vector< ObjectDrawer::TileTrace > &traces)
std::vector< ObjectTileReadRange > overlapping_ranges
One standard object whose parser-visible tile sources overlap an editable layout's authorized source ...
std::vector< ObjectTileReadRange > overlapping_ranges
Fail-closed impact inventory within ObjectParser's source model plus explicitly modeled runtime consu...
std::vector< ObjectTileRuntimeConsumerImpactEntry > runtime_consumers
std::vector< ObjectTileSourceImpactEntry > affected_objects
ROM descriptor and source snapshot authorizing an editable capture.
std::vector< ObjectTileSourceSpan > spans
A cell's exact word within an authorized source span.
One contiguous ROM-backed source span for an object's tile words.
std::vector< uint16_t > expected_words