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 <optional>
7#include <string>
8#include <utility>
9#include <vector>
10
11#include "absl/status/status.h"
12#include "absl/status/statusor.h"
13#include "app/gfx/core/bitmap.h"
16#include "rom/rom.h"
19#include "zelda3/dungeon/room.h"
20
21namespace yaze {
22namespace zelda3 {
23
28 uint32_t pc_address = 0;
29 std::vector<uint16_t> expected_words;
30};
31
39 int16_t object_id = -1;
42 std::vector<ObjectTileSourceSpan> spans;
43};
44
49 size_t span_index = 0;
50 size_t word_index = 0;
51};
52
58 int16_t object_id = -1;
59 std::vector<ObjectTileReadRange> overlapping_ranges;
60};
61
63 // Synthesized room object 0x150 reads the unlit/lit torch blocks directly
64 // during initial room drawing; it is not representable in the persisted
65 // dungeon object stream.
67 // Underworld light/extinguish updates read the same literal blocks again
68 // when replacing the torch tiles at runtime.
70};
71
76
86 std::vector<ObjectTileSourceImpactEntry> affected_objects;
87 std::vector<ObjectTileRuntimeConsumerImpactEntry> runtime_consumers;
88
89 size_t consumer_count() const {
90 return affected_objects.size() + runtime_consumers.size();
91 }
92};
93
101 int16_t object_id = 0;
104
105 struct Cell {
106 int rel_x = 0; // 0-based tile X within bounding box
107 int rel_y = 0; // 0-based tile Y within bounding box
108 gfx::TileInfo tile_info; // Decomposed SNES tilemap word
109 uint16_t original_word = 0;
110 // Legacy name retained for preview/test compatibility. This is draw-trace
111 // order only and never authorizes a ROM write; draw order is not generally
112 // source order.
113 int write_index = -1;
114 std::optional<ObjectTileSourceRef> source_ref;
115 bool modified = false;
116 };
117
118 std::vector<Cell> cells;
119 int bounds_width = 0; // Bounding box width in 8px tiles
120 int bounds_height = 0; // Bounding box height in 8px tiles
121
122 // Legacy display/shared-data metadata. Standard writes are authorized only
123 // by source_provenance + per-cell source_ref, never by this base address.
125 std::optional<ObjectTileSourceProvenance> source_provenance;
126 bool is_custom = false;
127 std::string custom_filename;
128
130 const std::vector<ObjectDrawer::TileTrace>& traces);
131
132 // Create an empty layout for new custom object creation
133 static ObjectTileLayout CreateEmpty(int width, int height, int16_t object_id,
134 const std::string& filename);
135
136 Cell* FindCell(int rel_x, int rel_y);
137 const Cell* FindCell(int rel_x, int rel_y) const;
138
139 bool HasModifications() const;
140 void RevertAll();
141};
142
150 public:
151 struct Write {
152 int address = -1;
153 uint16_t expected_word = 0;
154 uint16_t word = 0;
155 };
156
158 int address = -1;
159 uint16_t expected_word = 0;
160 };
161
164 ObjectTileWritePlan& operator=(const ObjectTileWritePlan&) = default;
165 ObjectTileWritePlan& operator=(ObjectTileWritePlan&&) noexcept = default;
166
167 const std::vector<Write>& writes() const { return writes_; }
168 const std::vector<WordPrecondition>& preconditions() const {
169 return preconditions_;
170 }
171 const std::vector<std::pair<uint32_t, uint32_t>>& write_ranges() const {
172 return write_ranges_;
173 }
174
175 private:
176 friend class ObjectTileEditor;
177
179
180 std::vector<Write> writes_;
181 // Includes the pointer descriptor and every captured source word. Apply
182 // rechecks these immediately before opening the transaction.
183 std::vector<WordPrecondition> preconditions_;
184 std::vector<std::pair<uint32_t, uint32_t>> write_ranges_;
185};
186
195 public:
196 static constexpr int kAtlasTilesPerRow = 16;
197 static constexpr int kAtlasTileRows = 64;
199 static constexpr int kAtlasWidthPx = kAtlasTilesPerRow * 8;
200 static constexpr int kAtlasHeightPx = kAtlasTileRows * 8;
201
202 explicit ObjectTileEditor(Rom* rom);
203
204 // Capture: run object draw in trace_only mode, build editable layout
205 absl::StatusOr<ObjectTileLayout> CaptureObjectLayout(
206 int16_t object_id, const Room& room, const gfx::PaletteGroup& palette);
207 absl::StatusOr<ObjectTileLayout> CaptureObjectLayout(
208 int16_t object_id, const Room& room, const gfx::PaletteGroup& palette,
209 uint8_t object_size);
210
211 // Capture a standard object with exact ROM source provenance. The initial
212 // fail-closed allowlist is intentionally limited to the two audited fixed
213 // 2x2 subtype-2 objects (0x11F and 0x120).
214 absl::StatusOr<ObjectTileLayout> CaptureEditableObjectLayout(
215 int16_t object_id, const Room& room, const gfx::PaletteGroup& palette);
216
217 static bool IsEditableStandardObject(int16_t object_id);
218
219 // Render: draw layout to preview bitmap using room's gfx buffer
220 absl::Status RenderLayoutToBitmap(const ObjectTileLayout& layout,
221 gfx::Bitmap& bitmap,
222 const uint8_t* room_gfx_buffer,
223 const gfx::PaletteGroup& palette);
224
225 // Build tile8 atlas from room graphics buffer.
226 absl::Status BuildTile8Atlas(gfx::Bitmap& atlas,
227 const uint8_t* room_gfx_buffer,
228 const gfx::PaletteGroup& palette,
229 int display_palette = 2);
230
231 // Write-back: standard objects patch ROM, custom objects write .bin
232 absl::Status WriteBack(const ObjectTileLayout& layout);
233
234 // Resolve and validate all standard-object writes before any ROM mutation.
235 absl::StatusOr<ObjectTileWritePlan> BuildStandardWritePlan(
236 const ObjectTileLayout& layout) const;
237
238 // Atomically apply a previously validated standard-object write plan.
239 absl::Status ApplyStandardWritePlan(const ObjectTileWritePlan& plan);
240
241 // Enumerate every representable standard object whose parser-visible source
242 // ranges overlap this editable layout, plus the explicit runtime consumers
243 // modeled by this backend. Resolution errors are returned to the caller and
244 // must block writes rather than being interpreted as no sharing. Other
245 // runtime-only behavior remains a separate parity-audit concern.
246 absl::StatusOr<ObjectTileSourceImpact> AnalyzeStandardTileSourceImpact(
247 const ObjectTileLayout& layout) const;
248
249 private:
251};
252
253} // namespace zelda3
254} // namespace yaze
255
256#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:28
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:67
SNES 16-bit tile metadata container.
Definition snes_tile.h:52
Captures and edits the tile8 composition of dungeon objects.
absl::Status WriteBack(const ObjectTileLayout &layout)
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::StatusOr< ObjectTileLayout > CaptureObjectLayout(int16_t object_id, const Room &room, const gfx::PaletteGroup &palette)
absl::Status BuildTile8Atlas(gfx::Bitmap &atlas, const uint8_t *room_gfx_buffer, const gfx::PaletteGroup &palette, int display_palette=2)
absl::StatusOr< ObjectTileLayout > CaptureEditableObjectLayout(int16_t object_id, const Room &room, const gfx::PaletteGroup &palette)
absl::StatusOr< ObjectTileWritePlan > BuildStandardWritePlan(const ObjectTileLayout &layout) const
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
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::optional< ObjectTileSourceProvenance > source_provenance
static ObjectTileLayout CreateEmpty(int width, int height, int16_t object_id, const std::string &filename)
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