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// Reads and strictly parses every pointer-table entry without modifying rom.
153// Fatal layout/source-table errors are returned as a non-OK status; per-room
154// pointer and stream errors are retained in DungeonStreamInventory::issues.
155absl::StatusOr<DungeonStreamInventory> InventoryDungeonStreams(
156 const Rom& rom, const DungeonStreamLayout& layout);
157
158// Deterministic first-fit copy-on-write planning. Replacements are validated as
159// complete streams, sorted by room ID, and allocated only from the inventory's
160// declared allocation-range complement. Existing streams are never reclaimed.
161absl::StatusOr<DungeonStreamWritePlan> PlanDungeonStreamWrites(
162 const DungeonStreamInventory& inventory,
163 const std::vector<DungeonStreamReplacement>& replacements);
164
165// Deterministically repacks every pot-item stream into one normalized declared
166// allocation range. Exact byte-identical payloads share one placement owned by
167// their lowest room ID, while every pointer-table entry receives an update.
168// Untouched rooms come from the immutable inventory snapshot. No ROM bytes are
169// changed during planning, and the operation fails before producing a plan if
170// all unique payloads cannot fit without crossing the fixed pointer bank.
171absl::StatusOr<DungeonStreamWritePlan> PlanDungeonStreamRepack(
172 const DungeonStreamInventory& inventory,
173 const std::vector<DungeonStreamReplacement>& replacements);
174
175// Applies a source-CRC-guarded plan transactionally. The complete ROM and dirty
176// flag are restored if any write fails. Payload writes always precede pointer
177// writes.
178absl::Status ApplyDungeonStreamWritePlan(Rom* rom,
179 const DungeonStreamWritePlan& plan);
180
181} // namespace zelda3
182} // namespace yaze
183
184#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:28
absl::StatusOr< DungeonStreamWritePlan > PlanDungeonStreamRepack(const DungeonStreamInventory &inventory, const std::vector< DungeonStreamReplacement > &requested_replacements)
absl::Status ApplyDungeonStreamWritePlan(Rom *rom, const DungeonStreamWritePlan &plan)
absl::StatusOr< DungeonStreamWritePlan > PlanDungeonStreamWrites(const DungeonStreamInventory &inventory, const std::vector< DungeonStreamReplacement > &requested_replacements)
absl::StatusOr< DungeonStreamInventory > InventoryDungeonStreams(const Rom &rom, const DungeonStreamLayout &requested_layout)
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