yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
draw_routine_registry.cc
Go to the documentation of this file.
2
3#include <algorithm>
4
5#include "core/features.h"
11
12namespace yaze {
13namespace zelda3 {
14
16 static DrawRoutineRegistry instance;
17 return instance;
18}
19
24
26
28 custom_objects_enabled_.store(core::FeatureFlags::get().kEnableCustomObjects,
29 std::memory_order_release);
30}
31
50
52 int routine_id) const {
53 auto it = routine_map_.find(routine_id);
54 if (it == routine_map_.end()) {
55 return nullptr;
56 }
57 return it->second;
58}
59
61 const DrawRoutineInfo* info = GetRoutineInfo(routine_id);
62 return info != nullptr && info->draws_to_both_bgs;
63}
64
65bool DrawRoutineRegistry::GetRoutineDimensions(int routine_id, int* base_width,
66 int* base_height) const {
67 const DrawRoutineInfo* info = GetRoutineInfo(routine_id);
68 if (info == nullptr) {
69 return false;
70 }
71 if (base_width)
72 *base_width = info->base_width;
73 if (base_height)
74 *base_height = info->base_height;
75 return true;
76}
77
78int DrawRoutineRegistry::GetRoutineIdForObject(int16_t object_id) const {
80}
81
83 int16_t object_id, bool custom_objects_enabled) const {
84 if (object_id == 0x31 || object_id == 0x32 || object_id == 0x54) {
85 return custom_objects_enabled ? DrawRoutineIds::kCustomObject
87 }
88 auto it = object_to_routine_map_.find(object_id);
89 if (it != object_to_routine_map_.end()) {
90 return it->second;
91 }
92 return -1;
93}
94
95std::vector<int16_t> DrawRoutineRegistry::GetMappedObjectIds() const {
96 std::vector<int16_t> ids;
97 ids.reserve(object_to_routine_map_.size());
98 for (const auto& [object_id, routine_id] : object_to_routine_map_) {
99 ids.push_back(object_id);
100 }
101 std::sort(ids.begin(), ids.end());
102 return ids;
103}
104
107
108 // Subtype 1 Object Mappings (0x00-0xFF)
109 // Based on bank_01.asm routine table at $018200
110 object_to_routine_map_[0x00] = 0;
111 for (int id = 0x01; id <= 0x02; id++) {
113 }
114 for (int id = 0x03; id <= 0x04; id++) {
116 }
117 for (int id = 0x05; id <= 0x06; id++) {
119 }
120 for (int id = 0x07; id <= 0x08; id++) {
122 }
123 object_to_routine_map_[0x09] = 5;
124 for (int id = 0x0A; id <= 0x0B; id++) {
126 }
127
128 // Diagonal walls (0x0C-0x20)
129 for (int id : {0x0C, 0x0D, 0x10, 0x11, 0x14}) {
131 }
132 for (int id : {0x0E, 0x0F, 0x12, 0x13}) {
134 }
135 for (int id : {0x15, 0x18, 0x19, 0x1C, 0x1D, 0x20}) {
136 object_to_routine_map_[id] = 17;
137 }
138 for (int id : {0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F}) {
139 object_to_routine_map_[id] = 18;
140 }
141
142 // Edge and Corner Objects (0x21-0x30)
143 object_to_routine_map_[0x21] = 20;
144 object_to_routine_map_[0x22] = 21;
145 for (int id = 0x23; id <= 0x2E; id++) {
146 object_to_routine_map_[id] = 22;
147 }
148 object_to_routine_map_[0x2F] = 23;
149 object_to_routine_map_[0x30] = 24;
150
151 // Keep the inventory stable. The atomic snapshot selects these IDs at
152 // lookup time, without mutating a map while census workers read it.
156 object_to_routine_map_[0x33] = 16;
157 object_to_routine_map_[0x34] = 25;
158 object_to_routine_map_[0x35] = 26;
159 object_to_routine_map_[0x36] = 27;
160 object_to_routine_map_[0x37] = 27;
161 object_to_routine_map_[0x38] = 28;
162 object_to_routine_map_[0x39] = 29;
163 object_to_routine_map_[0x3A] = 30;
164 object_to_routine_map_[0x3B] = 30;
165 object_to_routine_map_[0x3C] = 31;
166 object_to_routine_map_[0x3D] = 29;
167 object_to_routine_map_[0x3E] = 32;
168
169 for (int id = 0x3F; id <= 0x46; id++) {
170 object_to_routine_map_[id] = 22;
171 }
172 object_to_routine_map_[0x47] = 111;
173 object_to_routine_map_[0x48] = 112;
174 object_to_routine_map_[0x49] = 40;
175 object_to_routine_map_[0x4A] = 40;
176 object_to_routine_map_[0x4B] = 32;
177 object_to_routine_map_[0x4C] = 52;
178 object_to_routine_map_[0x4D] = 53;
179 object_to_routine_map_[0x4E] = 53;
180 object_to_routine_map_[0x4F] = 53;
181
182 object_to_routine_map_[0x50] = 51;
183 object_to_routine_map_[0x51] = 42;
184 object_to_routine_map_[0x52] = 42;
185 object_to_routine_map_[0x53] = 4;
186 object_to_routine_map_[0x55] = 41;
187 object_to_routine_map_[0x56] = 41;
188 object_to_routine_map_[0x57] = 38;
189 object_to_routine_map_[0x58] = 38;
190 object_to_routine_map_[0x59] = 38;
191 object_to_routine_map_[0x5A] = 38;
192 object_to_routine_map_[0x5B] = 42;
193 object_to_routine_map_[0x5C] = 42;
194 object_to_routine_map_[0x5D] = 54;
195 object_to_routine_map_[0x5E] = 55;
198
199 // Vertical (0x60-0x6F)
200 object_to_routine_map_[0x60] = 7;
201 for (int id = 0x61; id <= 0x62; id++) {
203 }
204 for (int id = 0x63; id <= 0x64; id++) {
206 }
207 for (int id = 0x65; id <= 0x66; id++) {
208 object_to_routine_map_[id] = 10;
209 }
210 for (int id = 0x67; id <= 0x68; id++) {
211 object_to_routine_map_[id] = 11;
212 }
213 object_to_routine_map_[0x69] = 12;
214 for (int id = 0x6A; id <= 0x6B; id++) {
215 object_to_routine_map_[id] = 13;
216 }
217 object_to_routine_map_[0x6C] = 14;
218 object_to_routine_map_[0x6D] = 15;
219 object_to_routine_map_[0x6E] = 38;
220 object_to_routine_map_[0x6F] = 38;
221
222 // 0x70-0x7F
223 object_to_routine_map_[0x70] = 43;
224 object_to_routine_map_[0x71] = 44;
225 object_to_routine_map_[0x72] = 38;
226 object_to_routine_map_[0x73] = 45;
227 object_to_routine_map_[0x74] = 45;
228 object_to_routine_map_[0x75] = 46;
229 object_to_routine_map_[0x76] = 47;
230 object_to_routine_map_[0x77] = 47;
231 object_to_routine_map_[0x78] = 48;
232 object_to_routine_map_[0x79] = 13;
233 object_to_routine_map_[0x7A] = 13;
234 object_to_routine_map_[0x7B] = 48;
235 object_to_routine_map_[0x7C] = 49;
236 object_to_routine_map_[0x7D] = 11;
237 object_to_routine_map_[0x7E] = 38;
238 object_to_routine_map_[0x7F] = 50;
239
240 // 0x80-0x8F
241 object_to_routine_map_[0x80] = 50;
242 object_to_routine_map_[0x81] = 65;
243 object_to_routine_map_[0x82] = 65;
244 object_to_routine_map_[0x83] = 65;
245 object_to_routine_map_[0x84] = 65;
246 object_to_routine_map_[0x85] = 68;
247 object_to_routine_map_[0x86] = 68;
248 object_to_routine_map_[0x87] = 46;
249 object_to_routine_map_[0x88] = 66;
250 object_to_routine_map_[0x89] = 67;
251 // USDASM $018314-$018318: 0x8A is the long capped rail, while 0x8B/0x8C
252 // are single-tile jump ledges repeated for size + 8 rows.
257 object_to_routine_map_[0x8D] = 13;
258 object_to_routine_map_[0x8E] = 13;
259 object_to_routine_map_[0x8F] = 69;
260
261 // 0x90-0x9F
262 object_to_routine_map_[0x90] = 8;
263 object_to_routine_map_[0x91] = 8;
264 object_to_routine_map_[0x92] = 7;
265 object_to_routine_map_[0x93] = 7;
266 object_to_routine_map_[0x94] = 43;
267 object_to_routine_map_[0x95] = 70;
268 object_to_routine_map_[0x96] = 71;
269 for (int id = 0x97; id <= 0x9F; id++) {
270 object_to_routine_map_[id] = 38;
271 }
272
273 // 0xA0-0xAF (diagonal ceilings and big hole)
274 object_to_routine_map_[0xA0] = 75;
275 object_to_routine_map_[0xA5] = 75;
276 object_to_routine_map_[0xA9] = 75;
277 object_to_routine_map_[0xA1] = 76;
278 object_to_routine_map_[0xA6] = 76;
279 object_to_routine_map_[0xAA] = 76;
280 object_to_routine_map_[0xA2] = 77;
281 object_to_routine_map_[0xA7] = 77;
282 object_to_routine_map_[0xAB] = 77;
283 object_to_routine_map_[0xA3] = 78;
284 object_to_routine_map_[0xA8] = 78;
285 object_to_routine_map_[0xAC] = 78;
286 object_to_routine_map_[0xA4] = 61;
287 object_to_routine_map_[0xAD] = 38;
288 object_to_routine_map_[0xAE] = 38;
289 object_to_routine_map_[0xAF] = 38;
290
291 // 0xB0-0xBF
292 object_to_routine_map_[0xB0] = 72;
293 object_to_routine_map_[0xB1] = 72;
294 object_to_routine_map_[0xB2] = 16;
295 object_to_routine_map_[0xB3] = 22;
296 object_to_routine_map_[0xB4] = 22;
298 object_to_routine_map_[0xB6] = 1;
299 object_to_routine_map_[0xB7] = 1;
300 object_to_routine_map_[0xB8] = 0;
301 object_to_routine_map_[0xB9] = 0;
302 object_to_routine_map_[0xBA] = 16;
303 object_to_routine_map_[0xBB] = 55;
304 object_to_routine_map_[0xBC] = 73;
305 object_to_routine_map_[0xBD] = 74;
306 object_to_routine_map_[0xBE] = 38;
307 object_to_routine_map_[0xBF] = 38;
308
309 // 0xC0-0xCF (SuperSquare)
310 object_to_routine_map_[0xC0] = 56;
311 object_to_routine_map_[0xC1] = 79;
312 object_to_routine_map_[0xC2] = 56;
313 object_to_routine_map_[0xC3] = 57;
314 object_to_routine_map_[0xC4] = 59;
315 for (int id = 0xC5; id <= 0xCA; id++) {
316 object_to_routine_map_[id] = 58;
317 }
318 object_to_routine_map_[0xCB] = 38;
319 object_to_routine_map_[0xCC] = 38;
320 object_to_routine_map_[0xCD] = 80;
321 object_to_routine_map_[0xCE] = 81;
322 object_to_routine_map_[0xCF] = 38;
323
324 // 0xD0-0xDF
325 object_to_routine_map_[0xD0] = 38;
326 object_to_routine_map_[0xD1] = 58;
327 object_to_routine_map_[0xD2] = 58;
328 object_to_routine_map_[0xD3] = 38;
329 object_to_routine_map_[0xD4] = 38;
330 object_to_routine_map_[0xD5] = 38;
331 object_to_routine_map_[0xD6] = 38;
332 object_to_routine_map_[0xD7] = 57;
333 object_to_routine_map_[0xD8] = 64;
334 object_to_routine_map_[0xD9] = 58;
335 object_to_routine_map_[0xDA] = 64;
336 object_to_routine_map_[0xDB] = 60;
337 object_to_routine_map_[0xDC] = 82;
338 object_to_routine_map_[0xDD] = 63;
339 object_to_routine_map_[0xDE] = 62;
340 object_to_routine_map_[0xDF] = 58;
341
342 // 0xE0-0xEF
343 for (int id = 0xE0; id <= 0xE8; id++) {
344 object_to_routine_map_[id] = 58;
345 }
346 for (int id = 0xE9; id <= 0xEF; id++) {
347 object_to_routine_map_[id] = 38;
348 }
349
350 // 0xF0-0xFF (complete subtype 1 coverage)
351 for (int id = 0xF0; id <= 0xF7; id++) {
352 object_to_routine_map_[id] = 38;
353 }
354 object_to_routine_map_[0xF8] = 39; // Chest variant
355 for (int id = 0xF9; id <= 0xFD; id++) {
356 object_to_routine_map_[id] = 39;
357 }
358 object_to_routine_map_[0xFE] = 38; // Unused in vanilla
359 object_to_routine_map_[0xFF] = 38; // Unused in vanilla
360
361 // Subtype 2 Object Mappings (0x100-0x13F)
362 for (int id = 0x100; id <= 0x107; id++) {
364 }
365 for (int id = 0x108; id <= 0x10F; id++) {
366 object_to_routine_map_[id] = 35;
367 }
368 for (int id = 0x110; id <= 0x113; id++) {
369 object_to_routine_map_[id] = 36;
370 }
371 for (int id = 0x114; id <= 0x117; id++) {
372 object_to_routine_map_[id] = 37;
373 }
374 for (int id = 0x118; id <= 0x11B; id++) {
376 }
378 object_to_routine_map_[0x11D] = 28;
379 object_to_routine_map_[0x11E] = 4;
382 object_to_routine_map_[0x121] = 28;
383 object_to_routine_map_[0x122] = 98;
384 object_to_routine_map_[0x123] = 30;
387 object_to_routine_map_[0x126] = 28;
388 object_to_routine_map_[0x127] = 4;
389 object_to_routine_map_[0x128] = 98;
392 object_to_routine_map_[0x12B] = 4;
393 object_to_routine_map_[0x12C] = 99;
394 object_to_routine_map_[0x12D] = 83;
395 object_to_routine_map_[0x12E] = 84;
396 object_to_routine_map_[0x12F] = 85;
397 for (int id = 0x130; id <= 0x133; id++) {
398 object_to_routine_map_[id] = 86;
399 }
400 object_to_routine_map_[0x134] = 4;
404 object_to_routine_map_[0x138] = 88;
405 object_to_routine_map_[0x139] = 89;
406 object_to_routine_map_[0x13A] = 90;
407 object_to_routine_map_[0x13B] = 91;
409 object_to_routine_map_[0x13D] = 30;
410 object_to_routine_map_[0x13E] = 100;
412
413 // Subtype 3 Object Mappings (0xF80-0xFFF)
414 object_to_routine_map_[0xF80] = 94;
415 object_to_routine_map_[0xF81] = 95;
416 object_to_routine_map_[0xF82] = 96;
417 for (int id = 0xF83; id <= 0xF89; id++) {
418 object_to_routine_map_[id] = 33;
419 }
420 for (int id = 0xF8A; id <= 0xF8C; id++) {
421 object_to_routine_map_[id] = 33;
422 }
423 object_to_routine_map_[0xF8D] = 97;
424 object_to_routine_map_[0xF8E] = 33;
425 object_to_routine_map_[0xF8F] = 33;
426 object_to_routine_map_[0xF90] = 110;
427 object_to_routine_map_[0xF91] = 110;
428 object_to_routine_map_[0xF92] = 115;
429 object_to_routine_map_[0xF93] = 110;
430 // USDASM draws 0xF94, 0xFCE, 0xFE7, 0xFE8 and 0xFF9 once with
431 // RoomDraw_TableRock4x3, and 0xFC8 and 0xFFA once with RoomDraw_4x4. A
432 // type-3 object's size bits are part of its ID, so repeating routines drew
433 // extra copies (confirmed against tilemaps captured from the game).
435 object_to_routine_map_[0xF95] = 106;
437 object_to_routine_map_[0xF97] = 97;
438 object_to_routine_map_[0xF98] = 92;
439 object_to_routine_map_[0xF99] = 39;
440 object_to_routine_map_[0xF9A] = 39;
441 for (int id = 0xF9B; id <= 0xF9D; id++) {
442 object_to_routine_map_[id] = 86;
443 }
444 for (int id = 0xF9E; id <= 0xFA1; id++) {
445 object_to_routine_map_[id] = 87;
446 }
447 for (int id = 0xFA2; id <= 0xFA5; id++) {
448 object_to_routine_map_[id] = 110;
449 }
450 for (int id = 0xFA6; id <= 0xFA9; id++) {
451 object_to_routine_map_[id] = 87;
452 }
453 object_to_routine_map_[0xFAA] = 16;
454 object_to_routine_map_[0xFAB] = 110;
457 object_to_routine_map_[0xFAE] = 16;
458 object_to_routine_map_[0xFAF] = 110;
459 object_to_routine_map_[0xFB0] = 110;
460 object_to_routine_map_[0xFB1] = 114;
461 object_to_routine_map_[0xFB2] = 114;
462 object_to_routine_map_[0xFB3] = 86;
463 for (int id = 0xFB4; id <= 0xFB9; id++) {
464 object_to_routine_map_[id] = 16;
465 }
466 object_to_routine_map_[0xFBA] = 102;
467 object_to_routine_map_[0xFBB] = 102;
468 object_to_routine_map_[0xFBC] = 103;
469 object_to_routine_map_[0xFBD] = 103;
470 for (int id = 0xFBE; id <= 0xFC6; id++) {
471 object_to_routine_map_[id] = 110;
472 }
473 object_to_routine_map_[0xFC7] = 93;
475 object_to_routine_map_[0xFC9] = 110;
476 object_to_routine_map_[0xFCA] = 110;
479 object_to_routine_map_[0xFCD] = 100;
481 for (int id = 0xFCF; id <= 0xFD3; id++) {
482 object_to_routine_map_[id] = 110;
483 }
485 object_to_routine_map_[0xFD5] = 101;
486 for (int id = 0xFD6; id <= 0xFD9; id++) {
487 object_to_routine_map_[id] = 110;
488 }
490 object_to_routine_map_[0xFDB] = 101;
491 object_to_routine_map_[0xFDC] = 103;
492 object_to_routine_map_[0xFDD] = 100;
493 object_to_routine_map_[0xFDE] = 110;
494 object_to_routine_map_[0xFDF] = 110;
495 object_to_routine_map_[0xFE0] = 108;
496 object_to_routine_map_[0xFE1] = 108;
497 object_to_routine_map_[0xFE2] = 16;
498 for (int id = 0xFE3; id <= 0xFE5; id++) {
499 object_to_routine_map_[id] = 110;
500 }
501 object_to_routine_map_[0xFE6] = 116;
504 object_to_routine_map_[0xFE9] = 107;
505 object_to_routine_map_[0xFEA] = 107;
506 object_to_routine_map_[0xFEB] = 113;
507 object_to_routine_map_[0xFEC] = 114;
508 object_to_routine_map_[0xFED] = 114;
509 object_to_routine_map_[0xFEE] = 107;
510 object_to_routine_map_[0xFEF] = 107;
511 object_to_routine_map_[0xFF0] = 104;
512 object_to_routine_map_[0xFF1] = 105;
513 object_to_routine_map_[0xFF2] = 106;
514 object_to_routine_map_[0xFF3] = 38;
516 object_to_routine_map_[0xFF5] = 110;
519 object_to_routine_map_[0xFF8] = 109;
523 for (int id = 0xFFC; id <= 0xFFE; id++) {
524 object_to_routine_map_[id] = 110;
525 }
526 object_to_routine_map_[0xFFF] = 38;
527}
528
529} // namespace zelda3
530} // namespace yaze
static Flags & get()
Definition features.h:119
Unified draw routine registry.
const DrawRoutineInfo * GetRoutineInfo(int routine_id) const
bool GetRoutineDimensions(int routine_id, int *base_width, int *base_height) const
std::vector< int16_t > GetMappedObjectIds() const
std::unordered_map< int16_t, int > object_to_routine_map_
bool RoutineDrawsToBothBGs(int routine_id) const
std::unordered_map< int, const DrawRoutineInfo * > routine_map_
int GetRoutineIdForObject(int16_t object_id) const
std::vector< DrawRoutineInfo > routines_
static DrawRoutineRegistry & Get()
void RegisterDiagonalRoutines(std::vector< DrawRoutineInfo > &registry)
Register all diagonal draw routines to the registry.
void RegisterCornerRoutines(std::vector< DrawRoutineInfo > &registry)
Register all corner draw routines to the registry.
void RegisterDownwardsRoutines(std::vector< DrawRoutineInfo > &registry)
Register all downwards draw routines to the registry.
void RegisterRightwardsRoutines(std::vector< DrawRoutineInfo > &registry)
Register all rightwards draw routines to the registry.
void RegisterSpecialRoutines(std::vector< DrawRoutineInfo > &registry)
Register all special/miscellaneous draw routines to the registry.
Metadata about a draw routine.