57 "A tile match does not prove a reachable Link approach or a completed "
58 "transition. Link samples at (x+8,y+12); direction is arrival behavior.";
60 if (!overworld.
is_loaded() || map ==
nullptr) {
61 result.
provenance =
"Unavailable: no loaded overworld map";
68 (parent->has_overlay() || parent->render_subscreen_overlay() != 0x00FF);
73 constexpr size_t kReader = 0x75E49;
74 constexpr size_t kTable = 0x75E29;
75 constexpr std::array<uint8_t, 17> kReaderPrefix = {
76 0xC2, 0x31, 0x20, 0x9A, 0xDE, 0xBF, 0x00, 0x80, 0xBD,
77 0x29, 0xFF, 0x01, 0x85, 0x00, 0xA2, 0x08, 0x00};
78 constexpr std::array<uint8_t, 18> kReaderComparisons = {
79 0xDF, 0x29, 0xDE, 0x0E, 0xD0, 0xF6, 0xA5, 0x8A, 0xDF,
80 0x31, 0xDE, 0x0E, 0xD0, 0xEC, 0xBF, 0x41, 0xDE, 0x0E};
81 if (rom.
size() < kReader + 0x52 ||
82 !std::equal(kReaderPrefix.begin(), kReaderPrefix.end(),
83 rom.
data() + kReader) ||
84 !std::equal(kReaderComparisons.begin(), kReaderComparisons.end(),
85 rom.
data() + kReader + 0x17)) {
87 "Unavailable: loaded ROM does not have the verified four-row $0EDE49 "
91 const auto read_word = [&rom](
size_t offset) -> uint16_t {
92 return static_cast<uint16_t
>(rom.
data()[offset] |
93 (rom.
data()[offset + 1] << 8));
95 for (
int i = 0; i < 4; ++i) {
96 const uint16_t marker = read_word(kTable + 24 + i * 2);
97 result.
rows[i] = {read_word(kTable + i * 2), read_word(kTable + 8 + i * 2),
98 read_word(kTable + 16 + i * 2), marker,
99 marker >= 0x0180 && marker <= 0x019F
100 ?
static_cast<int>(marker & 0xFF)
105 ": compiled $0EDE49 reader and $0EDE29 table";
106 const int world = map_id / 0x40;
108 const auto& definitions = overworld.
tiles16();
109 for (
int screen = world * 0x40;
112 if (candidate ==
nullptr || candidate->parent() != result.
parent_area) {
115 const int left = (screen % 8) * 32;
116 const int top = ((screen % 0x40) / 8) * 32;
117 for (
int y = 0; y < 32; ++y) {
118 for (
int x = 0; x < 32; ++x) {
119 if (left + x >=
static_cast<int>(grid.size()) ||
120 top + y >=
static_cast<int>(grid[left + x].size())) {
123 const uint16_t tile16_id = grid[left + x][top + y];
124 if (tile16_id >= definitions.size()) {
127 const uint16_t first_word =
129 const uint16_t masked = first_word & 0x01FF;
132 for (
int row = 3; row >= 0; --row) {
134 result.
rows[row].trigger == masked) {
136 left + x, top + y, tile16_id, first_word,