yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
dungeon_stream_layout_adapter.cc
Go to the documentation of this file.
2
3#include <cstdint>
4#include <string>
5
6#include "absl/status/status.h"
7#include "rom/snes.h"
8#include "util/macro.h"
10
11namespace yaze::core {
12namespace {
13
14absl::Status ValidateMappedLoRomAddress(uint32_t address,
15 const char* description) {
16 if ((address & 0xFFFFu) < 0x8000u) {
17 return absl::InvalidArgumentError(std::string(description) +
18 " is not a mapped LoROM address");
19 }
20 return absl::OkStatus();
21}
22
23} // namespace
24
25absl::StatusOr<zelda3::DungeonStreamLayout> ToDungeonStreamAllocatorLayout(
26 DungeonStreamType stream_type, const DungeonStreamLayout& manifest_layout) {
27 zelda3::DungeonStreamLayout allocator_layout;
28 switch (stream_type) {
31 break;
34 break;
37 break;
38 default:
39 return absl::InvalidArgumentError("Unknown dungeon stream type");
40 }
41
42 RETURN_IF_ERROR(ValidateMappedLoRomAddress(manifest_layout.pointer_table,
43 "Dungeon pointer table"));
44 allocator_layout.pointer_table_pc = SnesToPc(manifest_layout.pointer_table);
45 allocator_layout.pointer_count = manifest_layout.pointer_count;
46
47 switch (manifest_layout.pointer_encoding) {
49 if (manifest_layout.pointer_bank.has_value()) {
50 return absl::InvalidArgumentError(
51 "long24 dungeon layout must not define pointer_bank");
52 }
53 allocator_layout.pointer_encoding =
55 break;
57 if (!manifest_layout.pointer_bank.has_value()) {
58 return absl::InvalidArgumentError(
59 "bank16 dungeon layout requires pointer_bank");
60 }
61 allocator_layout.pointer_encoding =
63 allocator_layout.pointer_bank = *manifest_layout.pointer_bank;
64 break;
65 default:
66 return absl::InvalidArgumentError(
67 "Unknown dungeon pointer encoding in manifest");
68 }
69
70 allocator_layout.data_ranges.reserve(manifest_layout.data_regions.size());
71 for (const SnesAddressRange& range : manifest_layout.data_regions) {
73 ValidateMappedLoRomAddress(range.start, "Dungeon data range start"));
75 ValidateMappedLoRomAddress(range.end, "Dungeon data range end"));
76 const uint32_t begin = SnesToPc(range.start);
77 const uint32_t end = SnesToPc(range.end);
78 if (begin >= end) {
79 return absl::InvalidArgumentError(
80 "Dungeon data range must be non-empty in PC space");
81 }
82 allocator_layout.data_ranges.push_back({begin, end});
83 }
84
85 allocator_layout.allocation_ranges.reserve(
86 manifest_layout.allocation_regions.size());
87 for (const SnesAddressRange& range : manifest_layout.allocation_regions) {
88 RETURN_IF_ERROR(ValidateMappedLoRomAddress(
89 range.start, "Dungeon allocation range start"));
91 ValidateMappedLoRomAddress(range.end, "Dungeon allocation range end"));
92 const uint32_t begin = SnesToPc(range.start);
93 const uint32_t end = SnesToPc(range.end);
94 if (begin >= end) {
95 return absl::InvalidArgumentError(
96 "Dungeon allocation range must be non-empty in PC space");
97 }
98 // Room::SaveSprites() still discovers physical stream bounds through the
99 // vanilla bank-09 hard end. Keep manifest-backed COW allocations inside
100 // that same boundary so a relocated stream remains readable on the next
101 // save. Layout-aware sprite discovery can relax this restriction later.
102 if (stream_type == DungeonStreamType::kSprites &&
103 end > static_cast<uint32_t>(zelda3::kSpritesDataEndExclusive)) {
104 return absl::InvalidArgumentError(
105 "Sprite allocation range extends beyond the legacy sprite data "
106 "boundary");
107 }
108 allocator_layout.allocation_ranges.push_back({begin, end});
109 }
110
111 return allocator_layout;
112}
113
114} // namespace yaze::core
absl::Status ValidateMappedLoRomAddress(uint32_t address, const char *description)
DungeonStreamType
Dungeon stream kinds with allocator layouts in the hack manifest.
absl::StatusOr< zelda3::DungeonStreamLayout > ToDungeonStreamAllocatorLayout(DungeonStreamType stream_type, const DungeonStreamLayout &manifest_layout)
constexpr int kSpritesDataEndExclusive
uint32_t SnesToPc(uint32_t addr) noexcept
Definition snes.h:8
#define RETURN_IF_ERROR(expr)
Definition snes.cc:22
Explicit pointer and storage layout for one dungeon stream.
std::vector< SnesAddressRange > allocation_regions
std::optional< uint8_t > pointer_bank
std::vector< SnesAddressRange > data_regions
DungeonPointerEncoding pointer_encoding
A half-open [start, end) range of canonical LoROM SNES addresses.
std::vector< DungeonStreamPcRange > allocation_ranges
std::vector< DungeonStreamPcRange > data_ranges