yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
dungeon_stream_allocator.h
Go to the documentation of this file.
1#ifndef YAZE_ZELDA3_DUNGEON_DUNGEON_STREAM_ALLOCATOR_H_
2#define YAZE_ZELDA3_DUNGEON_DUNGEON_STREAM_ALLOCATOR_H_
3
4#include <cstdint>
5#include <string>
6#include <vector>
7
8#include "absl/status/status.h"
9#include "absl/status/statusor.h"
10
11namespace yaze {
12
13class Rom;
14
15namespace zelda3 {
16
17// The three variable-length, per-room dungeon stream formats supported by the
18// copy-on-write planner.
20 kObject,
21 kSprite,
23};
24
29
31 uint32_t begin = 0;
32 uint32_t end = 0;
33
34 bool operator==(const DungeonStreamPcRange&) const = default;
35};
36
37// All addresses in a layout are headerless PC offsets. data_ranges describe
38// where existing streams are allowed to live. allocation_ranges are the
39// explicitly allocator-owned subset; the planner never allocates merely
40// because ROM bytes happen to look unused.
43 uint32_t pointer_table_pc = 0;
44 uint32_t pointer_count = 0;
46 uint8_t pointer_bank = 0; // Used only by kFixedBank16.
47 std::vector<DungeonStreamPcRange> data_ranges;
48 std::vector<DungeonStreamPcRange> allocation_ranges;
49};
50
56
63
65 uint32_t room_id = 0;
66 uint32_t pointer_slot_pc = 0;
67 uint32_t data_pc = 0;
68 uint32_t logical_end_pc = 0;
69 bool valid = false;
70 // Immutable logical payload captured with the inventory snapshot. Keeping
71 // the bytes here lets a full repack preserve rooms that have no replacement
72 // without consulting a ROM that may have changed since inventory.
73 std::vector<uint8_t> encoded_stream;
74
75 uint32_t size() const {
77 }
78};
79
81 uint32_t data_pc = 0;
82 std::vector<uint32_t> room_ids;
83};
84
86 // The second stream starts inside the first and shares its logical end.
87 kSuffix,
88 // The logical intervals intersect but neither is an exact alias or suffix.
90};
91
98
99// An inventory is an immutable snapshot of the source ROM. occupied_intervals
100// is the union of all successfully parsed logical streams. free_intervals is
101// its complement inside data_ranges; allocatable_free_intervals is the much
102// narrower complement inside allocation_ranges and is the only space consumed
103// by PlanDungeonStreamWrites.
106 uint32_t source_size = 0;
107 uint32_t source_crc32 = 0;
108 std::vector<DungeonStreamRecord> streams;
109 std::vector<DungeonStreamAliasGroup> aliases;
110 std::vector<DungeonStreamOverlap> overlaps;
111 std::vector<DungeonStreamIssue> issues;
112 std::vector<DungeonStreamPcRange> occupied_intervals;
113 std::vector<DungeonStreamPcRange> free_intervals;
114 std::vector<DungeonStreamPcRange> allocatable_free_intervals;
115
116 bool ok() const { return issues.empty(); }
117};
118
120 uint32_t room_id = 0;
121 // The complete logical stream, including format header(s) and terminator.
122 std::vector<uint8_t> encoded_stream;
123};
124
126 uint32_t room_id = 0;
127 uint32_t address = 0;
128 std::vector<uint8_t> bytes;
129
130 bool operator==(const DungeonStreamWrite&) const = default;
131};
132
136};
137
140 uint32_t source_size = 0;
141 uint32_t source_crc32 = 0;
143 // Kept separate so apply can guarantee all payloads land before any pointer
144 // becomes live.
145 std::vector<DungeonStreamWrite> payload_writes;
146 std::vector<DungeonStreamWrite> pointer_writes;
147 // Object relocation also needs the runtime door pointer updated to the
148 // first door byte (or the final terminator for a doorless stream).
149 std::vector<DungeonStreamWrite> auxiliary_pointer_writes;
150};
151
152// Read one object stream through the ROM's live pointer table. This validates
153// structure without imposing allocator ownership ranges or changing ROM data.
154// Parsing stops at the nearest later room pointer, known object-region end,
155// LoROM bank end, or ROM end. Exact shared pointers are permitted.
156absl::StatusOr<DungeonStreamRecord> ReadDungeonObjectStream(const Rom& rom,
157 int room_id);
158
159// Strict read-only counterparts for the live bank-09 sprite table and fixed
160// bank-01 pot-item table. Parsing cannot cross a pointer table/source, a known
161// data-region boundary, the next distinct room pointer, or a ROM/bank boundary.
162// Exact aliases are allowed; suffix/interior overlaps are not inferred safe.
163absl::StatusOr<DungeonStreamRecord> ReadDungeonSpriteStream(const Rom& rom,
164 int room_id);
165absl::StatusOr<DungeonStreamRecord> ReadDungeonPotItemStream(const Rom& rom,
166 int room_id);
167
168// Reads and strictly parses every pointer-table entry without modifying rom.
169// Fatal layout/source-table errors are returned as a non-OK status; per-room
170// pointer and stream errors are retained in DungeonStreamInventory::issues.
171absl::StatusOr<DungeonStreamInventory> InventoryDungeonStreams(
172 const Rom& rom, const DungeonStreamLayout& layout);
173
174// Deterministic first-fit copy-on-write planning. Replacements are validated as
175// complete streams, sorted by room ID, and allocated only from the inventory's
176// declared allocation-range complement. Existing streams are never reclaimed.
177absl::StatusOr<DungeonStreamWritePlan> PlanDungeonStreamWrites(
178 const DungeonStreamInventory& inventory,
179 const std::vector<DungeonStreamReplacement>& replacements);
180
181// Deterministically repacks every pot-item stream into one normalized declared
182// allocation range. Exact byte-identical payloads share one placement owned by
183// their lowest room ID, while every pointer-table entry receives an update.
184// Untouched rooms come from the immutable inventory snapshot. No ROM bytes are
185// changed during planning, and the operation fails before producing a plan if
186// all unique payloads cannot fit without crossing the fixed pointer bank.
187absl::StatusOr<DungeonStreamWritePlan> PlanDungeonStreamRepack(
188 const DungeonStreamInventory& inventory,
189 const std::vector<DungeonStreamReplacement>& replacements);
190
191// Applies a source-CRC-guarded plan transactionally. The complete ROM and dirty
192// flag are restored if any write fails. Payload writes always precede pointer
193// writes.
194absl::Status ApplyDungeonStreamWritePlan(Rom* rom,
195 const DungeonStreamWritePlan& plan);
196
197} // namespace zelda3
198} // namespace yaze
199
200#endif // YAZE_ZELDA3_DUNGEON_DUNGEON_STREAM_ALLOCATOR_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
absl::StatusOr< DungeonStreamWritePlan > PlanDungeonStreamRepack(const DungeonStreamInventory &inventory, const std::vector< DungeonStreamReplacement > &requested_replacements)
absl::Status ApplyDungeonStreamWritePlan(Rom *rom, const DungeonStreamWritePlan &plan)
absl::StatusOr< DungeonStreamRecord > ReadDungeonPotItemStream(const Rom &rom, int room_id)
absl::StatusOr< DungeonStreamWritePlan > PlanDungeonStreamWrites(const DungeonStreamInventory &inventory, const std::vector< DungeonStreamReplacement > &requested_replacements)
absl::StatusOr< DungeonStreamInventory > InventoryDungeonStreams(const Rom &rom, const DungeonStreamLayout &requested_layout)
absl::StatusOr< DungeonStreamRecord > ReadDungeonObjectStream(const Rom &rom, int room_id)
absl::StatusOr< DungeonStreamRecord > ReadDungeonSpriteStream(const Rom &rom, int room_id)
std::vector< DungeonStreamPcRange > allocatable_free_intervals
std::vector< DungeonStreamPcRange > occupied_intervals
std::vector< DungeonStreamPcRange > free_intervals
std::vector< DungeonStreamAliasGroup > aliases
std::vector< DungeonStreamIssue > issues
std::vector< DungeonStreamOverlap > overlaps
std::vector< DungeonStreamRecord > streams
std::vector< DungeonStreamPcRange > allocation_ranges
std::vector< DungeonStreamPcRange > data_ranges
bool operator==(const DungeonStreamPcRange &) const =default
std::vector< DungeonStreamWrite > pointer_writes
std::vector< DungeonStreamWrite > payload_writes
std::vector< DungeonStreamWrite > auxiliary_pointer_writes
bool operator==(const DungeonStreamWrite &) const =default