yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
overworld_allocation.h
Go to the documentation of this file.
1#ifndef YAZE_ZELDA3_OVERWORLD_OVERWORLD_ALLOCATION_H
2#define YAZE_ZELDA3_OVERWORLD_OVERWORLD_ALLOCATION_H
3
4#include <array>
5#include <cstddef>
6#include <cstdint>
7#include <functional>
8#include <map>
9#include <optional>
10#include <string>
11#include <vector>
12
13#include "absl/status/statusor.h"
14#include "rom/rom.h"
15
16namespace yaze::zelda3 {
17
31inline constexpr int kAllocationAreaCount = 0xC0;
32inline constexpr int kSpecialTailFirstArea = 0xA0;
33
35
37
38const char* AllocationWorldName(AllocationWorld world);
41
44 std::string id; // Stable key, e.g. "pool_parent".
45 std::string label; // Human-readable name.
46 std::string group; // map, gfx, transition, sprites, text, music, items,
47 // sram
48 bool in_rom = true; // false for WRAM/SRAM tables.
49 uint32_t pc = 0; // PC address of the entry for `first_area`.
50 uint32_t snes = 0; // SNES address of the same entry (LoROM or WRAM).
51 int entry_bytes = 1;
52 int first_area = 0;
53 int last_area = 0; // Inclusive.
54 std::string past_end; // What an ID past `last_area` reads.
55 std::string note;
56 // IDs the game reads this table for. Special-world tables are read only
57 // for $80+, the light-world music table only for $00-$3F.
58 int applies_first = 0x00;
59 int applies_last = 0xBF;
60
61 bool Covers(int area) const {
62 return area >= first_area && area <= last_area;
63 }
64 bool Applies(int area) const {
65 return area >= applies_first && area <= applies_last;
66 }
68 bool Misses(int area) const { return Applies(area) && !Covers(area); }
69};
70
73std::vector<AreaTableInfo> OverworldAreaTableCatalogue(uint8_t asm_version);
74
78 uint32_t snes = 0;
79 uint32_t pc = 0;
80 bool in_rom = false;
81 bool terminated = false; // Reached the $FF terminator.
82 int compressed_bytes = 0; // Bytes read, including the terminator.
84 std::string error; // Empty, or why decoding stopped early.
85 std::vector<uint8_t> decoded;
86};
87
90MapStreamScan ScanMapStream(const uint8_t* data, size_t size, uint32_t pc,
91 size_t max_output = 0x4000);
92
94 int area = 0;
96 std::string name; // From the project registry, when given.
97
98 bool used = false;
99 std::vector<std::string> evidence; // Why the ID counts as used.
100
101 // Parent and size as the game reads them. `parent` is empty when no parent
102 // table covers the ID; `parent_past_end` then holds the byte a read would
103 // return from the data after the table.
104 std::optional<int> parent;
105 std::optional<int> parent_past_end;
107
108 // Map data. `map_pointer_source` is "vanilla_table", "tail_table" or
109 // "none". A pointer is valid when both streams are inside the ROM, end
110 // with $FF and decode to at least 256 bytes.
111 std::string map_pointer_source = "none";
112 bool map_pointer_valid = false;
113 MapStreamScan high; // decoded bytes are cleared after classification
116 std::optional<int> duplicate_of; // Lower ID with the same two pointers.
117
118 int entrances = 0;
119 int holes = 0;
120 int exits = 0;
121 int sprites = 0;
122 std::vector<int> overlay_users; // Areas whose subscreen overlay is this ID.
124
125 std::vector<std::string> uncovered_tables; // AreaTableInfo::id values.
126};
127
129 std::string key; // light, dark, special, special_tail
130 int first_area = 0;
131 int last_area = 0;
132 int used = 0;
133 int free = 0;
134 int free_with_map_data = 0; // Free, and a valid map pointer exists.
135 int free_without_map_data = 0; // Free, and no valid map pointer.
136};
137
139 bool scan_entities = true; // Entrances, holes and exits.
140 bool scan_sprites = true; // Overworld sprite lists (ZS v3 only).
141 std::map<int, std::string> area_names;
142};
143
145 std::string rom_name;
146 size_t rom_size = 0;
147 uint8_t asm_version = 0xFF;
148 std::string catalogue; // "zscustom_v3" or "vanilla"
150 std::vector<AreaTableInfo> tables;
151 std::vector<AreaAllocation> areas; // kAllocationAreaCount entries.
152 std::vector<WorldAllocationSummary> summary;
153
154 // Ids of tables the game reads for $A0 that have no entry for it.
155 std::vector<std::string> TablesStoppingBeforeTail() const;
156};
157
158absl::StatusOr<OverworldAllocationReport> BuildOverworldAllocationReport(
159 Rom* rom, const OverworldAllocationOptions& options = {});
160
161// ---------------------------------------------------------------------------
162// TailMapExpansion.asm compatibility check
163// ---------------------------------------------------------------------------
164
168 uint32_t marker_snes = 0x28A3FF;
169 uint8_t marker_value = 0xEA;
170 uint32_t high_table_snes = 0x28A400;
171 uint32_t low_table_snes = 0x28A640;
172 int table_entries = 192;
173 uint32_t blank_high_snes = 0x308000;
174 std::vector<uint8_t> blank_high = std::vector<uint8_t>(188, 0x00);
175 uint32_t blank_low_snes = 0x309000;
176 std::vector<uint8_t> blank_low = std::vector<uint8_t>(4, 0x00);
177 // SNES addresses of the 3-byte LDA.l operands the patch rewrites, the
178 // vanilla table address each holds, and the address the patch writes.
179 std::array<uint32_t, 8> operand_snes = {0x02F59E, 0x02F5A4, 0x02F5C9,
180 0x02F5CF, 0x02F7E4, 0x02F7EA,
181 0x02F80F, 0x02F815};
182 std::array<uint32_t, 8> operand_vanilla = {0x02F94D, 0x02F94E, 0x02FB2D,
183 0x02FB2E, 0x02F94D, 0x02F94E,
184 0x02FB2D, 0x02FB2E};
185 std::array<uint32_t, 8> operand_patched = {0x28A400, 0x28A401, 0x28A640,
186 0x28A641, 0x28A400, 0x28A401,
187 0x28A640, 0x28A641};
188 // yaze facts the verdict depends on. Overworld::SaveOverworldMaps writes
189 // map pointers to 0x1794D/0x17B2D only, and yaze loads 160 maps.
191 int yaze_map_count = 160;
192};
193
196
197const char* TailCheckVerdictName(TailCheckVerdict verdict);
198const char* TailCheckScopeName(TailCheckScope scope);
199
202 std::string id;
203 std::string message;
204 bool blocking = true;
205};
206
208 std::string id; // marker, high_table, low_table, blank_high, blank_low
209 std::string label;
210 uint32_t snes = 0;
211 uint32_t pc = 0;
212 int length = 0;
213 bool in_rom = false; // The whole region is inside the current ROM.
215 std::string first_bytes; // Up to 16 bytes, hex.
216 std::string owner; // From the annotator (hack manifest).
217 std::string symbol; // From the annotator (symbol file).
218};
219
221 uint32_t snes = 0;
222 uint32_t pc = 0;
223 bool in_rom = false;
224 uint8_t opcode = 0;
225 uint32_t current = 0;
226 uint32_t vanilla = 0;
227 uint32_t patched = 0;
228 std::string state; // vanilla, patched, other, missing
229};
230
232 std::string id; // blank_high, blank_low
233 uint32_t snes = 0;
234 int stream_bytes = 0; // Bytes the patch writes (or 0 when applied).
235 bool terminated = false;
239 std::string stopped_at; // SNES address where decoding stopped.
240 std::string error;
241 bool valid = false; // $FF inside the stream and >= 256 decoded bytes.
242};
243
247 std::function<std::optional<std::pair<std::string, bool>>(uint32_t)>
250 std::function<std::string(uint32_t)> symbol;
251};
252
254 size_t rom_size = 0;
255 uint8_t asm_version = 0xFF;
256 bool marker_present = false;
257 uint8_t marker_value = 0;
258 std::vector<TailCheckRegion> regions;
259 std::vector<TailStreamCheck> streams;
260 std::vector<TailCheckOperand> operands;
261 bool zs_code_found = false;
262 uint32_t zs_code_end_snes = 0; // Last non-zero byte before the marker.
264 std::vector<std::string> tables_stopping_before_tail;
265 std::vector<TailCheckFinding> findings;
267 bool rom_compatible = false; // No blocking finding with scope kRom.
268
269 bool IsSafe() const { return verdict == TailCheckVerdict::kSafe; }
271 std::string BlockingSummary() const;
272};
273
274TailMapExpansionCheck CheckTailMapExpansion(
275 const Rom& rom, const TailMapExpansionPlan& plan = {},
276 const TailCheckAnnotator& annotator = {});
277
280absl::Status TailMapExpansionApplyGuard(const Rom& rom);
281
282// ---------------------------------------------------------------------------
283// Output
284// ---------------------------------------------------------------------------
285
286std::string OverworldAllocationToJson(const OverworldAllocationReport& report,
287 const TailMapExpansionCheck* tail_check);
289 const OverworldAllocationReport& report,
290 const TailMapExpansionCheck* tail_check);
291
292} // namespace yaze::zelda3
293
294#endif // YAZE_ZELDA3_OVERWORLD_OVERWORLD_ALLOCATION_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
Zelda 3 specific classes and functions.
std::vector< AreaTableInfo > OverworldAreaTableCatalogue(uint8_t asm_version)
constexpr int kAllocationAreaCount
const char * AllocationAreaSizeName(AllocationAreaSize size)
absl::Status TailMapExpansionApplyGuard(const Rom &rom)
TailMapExpansionCheck CheckTailMapExpansion(const Rom &rom, const TailMapExpansionPlan &plan, const TailCheckAnnotator &annotator)
const char * AllocationWorldName(AllocationWorld world)
const char * TailCheckScopeName(TailCheckScope scope)
std::string FormatOverworldAllocationText(const OverworldAllocationReport &report, const TailMapExpansionCheck *tail_check)
const char * TailCheckVerdictName(TailCheckVerdict verdict)
constexpr int kSpecialTailFirstArea
std::string OverworldAllocationToJson(const OverworldAllocationReport &report, const TailMapExpansionCheck *tail_check)
AllocationWorld AllocationWorldForArea(int area)
MapStreamScan ScanMapStream(const uint8_t *data, size_t size, uint32_t pc, size_t max_output)
absl::StatusOr< OverworldAllocationReport > BuildOverworldAllocationReport(Rom *rom, const OverworldAllocationOptions &options)
std::vector< std::string > evidence
std::vector< std::string > uncovered_tables
One table the game or yaze indexes with an overworld area ID.
bool Misses(int area) const
The game reads this table for area but has no entry for it.
std::vector< uint8_t > decoded
std::vector< WorldAllocationSummary > summary
std::vector< std::string > TablesStoppingBeforeTail() const
std::function< std::string(uint32_t)> symbol
Returns a symbol for a SNES address (empty when none).
std::function< std::optional< std::pair< std::string, bool > >(uint32_t)> ownership
std::vector< TailStreamCheck > streams
std::vector< TailCheckRegion > regions
std::string BlockingSummary() const
One line per blocking finding, for error messages.
std::vector< TailCheckOperand > operands
std::vector< std::string > tables_stopping_before_tail
std::vector< TailCheckFinding > findings
std::array< uint32_t, 8 > operand_patched
std::array< uint32_t, 8 > operand_vanilla