yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
object_dimensions.cc
Go to the documentation of this file.
1#include "object_dimensions.h"
2
4
5namespace yaze {
6namespace zelda3 {
7
9 static ObjectDimensionTable instance;
10 return instance;
11}
12
14 if (!rom || !rom->is_loaded()) {
15 return absl::FailedPreconditionError("ROM not loaded");
16 }
17
18 dimensions_.clear();
20
21 // Parse ROM tables for refinement
25
26 loaded_ = true;
27 return absl::OkStatus();
28}
29
30std::pair<int, int> ObjectDimensionTable::GetBaseDimensions(int object_id) const {
31 auto it = dimensions_.find(object_id);
32 if (it != dimensions_.end()) {
33 return {it->second.base_width, it->second.base_height};
34 }
35 return {2, 2}; // Default 16x16 pixels (2x2 tiles)
36}
37
38std::pair<int, int> ObjectDimensionTable::GetDimensions(int object_id, int size) const {
39 auto it = dimensions_.find(object_id);
40 if (it == dimensions_.end()) {
41 // Unknown object - estimate from size
42 // ASM: When size is 0, default to 32 (not 1)
43 int s = (size == 0) ? 32 : size + 1;
44 return {2 * s, 2};
45 }
46
47 const auto& entry = it->second;
48 int w = entry.base_width;
49 int h = entry.base_height;
50
51 // ASM: GetSize_1to15or32 uses 32 when combined size is 0
52 // This affects variable-size objects like floors
53 int effective_size = size;
54 if (entry.use_32_when_zero && size == 0) {
55 effective_size = 32;
56 }
57
58 switch (entry.extend_dir) {
60 w += effective_size * entry.extend_multiplier;
61 break;
63 h += effective_size * entry.extend_multiplier;
64 break;
66 w += effective_size * entry.extend_multiplier;
67 h += effective_size * entry.extend_multiplier;
68 break;
70 // Diagonals extend both dimensions based on count
71 // Width = base_width + size, Height = base_height + size
72 // ASM: Each iteration draws 5 tiles vertically and advances X by 1
73 // Bounding box height = 5 + (count - 1) = count + 4
74 w += effective_size * entry.extend_multiplier;
75 h += effective_size * entry.extend_multiplier;
76 break;
78 // SuperSquare objects use both size nibbles independently
79 // ASM: RoomDraw_4x4BlocksIn4x4SuperSquare and similar
80 // size_x = (size & 0x0F) + 1, size_y = ((size >> 4) & 0x0F) + 1
81 // width = size_x * block_size, height = size_y * block_size
82 int size_x = (size & 0x0F) + 1;
83 int size_y = ((size >> 4) & 0x0F) + 1;
84 w = size_x * entry.extend_multiplier;
85 h = size_y * entry.extend_multiplier;
86 break;
87 }
89 default:
90 break;
91 }
92
93 return {w, h};
94}
95
96std::pair<int, int> ObjectDimensionTable::GetSelectionDimensions(int object_id, int size) const {
97 auto it = dimensions_.find(object_id);
98 if (it == dimensions_.end()) {
99 // Unknown object - use reasonable default based on size
100 int s = std::max(1, size + 1);
101 return {std::min(s * 2, 16), 2}; // Cap at 16 tiles wide for selection
102 }
103
104 const auto& entry = it->second;
105 int w = entry.base_width;
106 int h = entry.base_height;
107
108 // For selection bounds, use actual size (not 32-when-zero)
109 // This gives a more accurate visual selection box
110 int effective_size = size;
111
112 switch (entry.extend_dir) {
114 w += effective_size * entry.extend_multiplier;
115 break;
117 h += effective_size * entry.extend_multiplier;
118 break;
120 w += effective_size * entry.extend_multiplier;
121 h += effective_size * entry.extend_multiplier;
122 break;
124 // Diagonals: both dimensions scale with size
125 w += effective_size * entry.extend_multiplier;
126 h += effective_size * entry.extend_multiplier;
127 break;
129 // SuperSquare: each nibble controls one dimension
130 int size_x = (size & 0x0F) + 1;
131 int size_y = ((size >> 4) & 0x0F) + 1;
132 w = size_x * entry.extend_multiplier;
133 h = size_y * entry.extend_multiplier;
134 break;
135 }
137 default:
138 break;
139 }
140
141 // Ensure minimum visible size
142 w = std::max(w, 2);
143 h = std::max(h, 2);
144
145 return {w, h};
146}
147
148std::tuple<int, int, int, int> ObjectDimensionTable::GetHitTestBounds(
149 const RoomObject& obj) const {
150 auto [w, h] = GetDimensions(obj.id_, obj.size_);
151 return {obj.x_, obj.y_, w, h};
152}
153
155 using Dir = DimensionEntry::ExtendDir;
156
157 // ============================================================================
158 // Subtype 1 objects (0x00-0xF7)
159 // ============================================================================
160
161 // 0x00: Ceiling 2x2 - uses GetSize_1to15or32
162 dimensions_[0x00] = {2, 2, Dir::Horizontal, 2, true};
163
164 // 0x01-0x02: Wall 2x4 - uses GetSize_1to15or26
165 for (int id = 0x01; id <= 0x02; id++) {
166 dimensions_[id] = {2, 4, Dir::Horizontal, 2, false}; // Use 26 when zero
167 }
168
169 // 0x03-0x04: Wall 2x4 spaced 4 - GetSize_1to16
170 for (int id = 0x03; id <= 0x04; id++) {
171 dimensions_[id] = {2, 4, Dir::Horizontal, 2, false};
172 }
173
174 // 0x05-0x06: Wall 2x4 spaced 4 BothBG - GetSize_1to16
175 for (int id = 0x05; id <= 0x06; id++) {
176 dimensions_[id] = {2, 4, Dir::Horizontal, 2, false};
177 }
178
179 // 0x07-0x08: Floor 2x2 - GetSize_1to16
180 for (int id = 0x07; id <= 0x08; id++) {
181 dimensions_[id] = {2, 2, Dir::Horizontal, 2, false};
182 }
183
184 // 0x09-0x14: Diagonal walls - non-BothBG (count = size + 7)
185 // Height = count + 4 tiles (5 tiles per column + diagonal extent)
186 for (int id = 0x09; id <= 0x14; id++) {
187 // Diagonal pattern: width = count tiles, height = count + 4 tiles
188 dimensions_[id] = {7, 11, Dir::Diagonal, 1, false}; // base 7 + size*1, height 11 + size*1
189 }
190
191 // 0x15-0x20: Diagonal walls - BothBG (count = size + 6)
192 for (int id = 0x15; id <= 0x20; id++) {
193 dimensions_[id] = {6, 10, Dir::Diagonal, 1, false}; // base 6 + size*1, height 10 + size*1
194 }
195
196 // 0x21: Edge 1x2 +2 (count = size*2 + 1)
197 dimensions_[0x21] = {1, 2, Dir::Horizontal, 2, false};
198
199 // 0x22: Edge 1x1 +3 (count = size + 2)
200 dimensions_[0x22] = {2, 1, Dir::Horizontal, 1, false};
201
202 // 0x23-0x2E: Edge 1x1 +2 (count = size + 1)
203 for (int id = 0x23; id <= 0x2E; id++) {
204 dimensions_[id] = {1, 1, Dir::Horizontal, 1, false};
205 }
206
207 // 0x2F: Top corners 1x2 +13
208 dimensions_[0x2F] = {10, 2, Dir::Horizontal, 1, false};
209
210 // 0x30: Bottom corners 1x2 +13
211 dimensions_[0x30] = {10, 2, Dir::Horizontal, 1, false};
212
213 // 0x31-0x32: Nothing
214 dimensions_[0x31] = {1, 1, Dir::None, 0, false};
215 dimensions_[0x32] = {1, 1, Dir::None, 0, false};
216
217 // 0x33: 4x4 block - GetSize_1to16
218 dimensions_[0x33] = {4, 4, Dir::Horizontal, 4, false};
219
220 // 0x34: Solid 1x1 +3 (count = size + 4)
221 dimensions_[0x34] = {4, 1, Dir::Horizontal, 1, false};
222
223 // 0x35: Door switcherer - fixed 4x4
224 dimensions_[0x35] = {4, 4, Dir::None, 0, false};
225
226 // 0x36-0x37: Decor 4x4 spaced 2 - spacing 6 tiles
227 for (int id = 0x36; id <= 0x37; id++) {
228 dimensions_[id] = {4, 4, Dir::Horizontal, 6, false};
229 }
230
231 // 0x38: Statue 2x3 spaced 2 - spacing 4 tiles
232 dimensions_[0x38] = {2, 3, Dir::Horizontal, 4, false};
233
234 // 0x39: Pillar 2x4 spaced 4 - spacing 6 tiles
235 dimensions_[0x39] = {2, 4, Dir::Horizontal, 6, false};
236
237 // 0x3A-0x3B: Decor 4x3 spaced 4 - spacing 6 tiles
238 for (int id = 0x3A; id <= 0x3B; id++) {
239 dimensions_[id] = {4, 3, Dir::Horizontal, 6, false};
240 }
241
242 // 0x3C: Doubled 2x2 spaced 2 - spacing 6 tiles
243 dimensions_[0x3C] = {4, 2, Dir::Horizontal, 6, false};
244
245 // 0x3D: Pillar 2x4 spaced 4 - spacing 6 tiles
246 dimensions_[0x3D] = {2, 4, Dir::Horizontal, 6, false};
247
248 // 0x3E: Decor 2x2 spaced 12 - spacing 14 tiles
249 dimensions_[0x3E] = {2, 2, Dir::Horizontal, 14, false};
250
251 // 0x3F-0x46: Edge 1x1 +2 (count = size + 1)
252 for (int id = 0x3F; id <= 0x46; id++) {
253 dimensions_[id] = {1, 1, Dir::Horizontal, 1, false};
254 }
255
256 // 0x47: Waterfall47 - 1x5 columns, width = 2 + (size+1)*2
257 dimensions_[0x47] = {4, 5, Dir::Horizontal, 2, false};
258
259 // 0x48: Waterfall48 - 1x3 columns, width = 2 + (size+1)*2
260 dimensions_[0x48] = {4, 3, Dir::Horizontal, 2, false};
261
262 // 0x49-0x4A: Floor Tile 4x2 - GetSize_1to16
263 for (int id = 0x49; id <= 0x4A; id++) {
264 dimensions_[id] = {4, 2, Dir::Horizontal, 4, false};
265 }
266
267 // 0x4B: Decor 2x2 spaced 12 - spacing 14 tiles
268 dimensions_[0x4B] = {2, 2, Dir::Horizontal, 14, false};
269
270 // 0x4C: Bar 4x3 - spacing 6 tiles
271 dimensions_[0x4C] = {4, 3, Dir::Horizontal, 6, false};
272
273 // 0x4D-0x4F: Shelf 4x4 - spacing 6 tiles
274 for (int id = 0x4D; id <= 0x4F; id++) {
275 dimensions_[id] = {4, 4, Dir::Horizontal, 6, false};
276 }
277
278 // 0x50: Line 1x1 +1 (count = size + 2)
279 dimensions_[0x50] = {2, 1, Dir::Horizontal, 1, false};
280
281 // 0x51-0x52: Cannon Hole 4x3 - GetSize_1to16
282 for (int id = 0x51; id <= 0x52; id++) {
283 dimensions_[id] = {4, 3, Dir::Horizontal, 4, false};
284 }
285
286 // 0x53: Floor 2x2 - GetSize_1to16
287 dimensions_[0x53] = {2, 2, Dir::Horizontal, 2, false};
288
289 // 0x54-0x5A: Nothing
290 for (int id = 0x54; id <= 0x5A; id++) {
291 dimensions_[id] = {1, 1, Dir::None, 0, false};
292 }
293
294 // 0x5B-0x5C: Cannon Hole 4x3
295 for (int id = 0x5B; id <= 0x5C; id++) {
296 dimensions_[id] = {4, 3, Dir::Horizontal, 4, false};
297 }
298
299 // 0x5D: Big Rail 1x3 +5 (count = size + 6)
300 dimensions_[0x5D] = {6, 3, Dir::Horizontal, 1, false};
301
302 // 0x5E: Block 2x2 spaced 2
303 dimensions_[0x5E] = {2, 2, Dir::Horizontal, 4, false};
304
305 // 0x5F: Edge 1x1 +23 (count = size + 1 but offset +23)
306 dimensions_[0x5F] = {1, 1, Dir::Horizontal, 1, false};
307
308 // 0x60: Downwards 2x2 - GetSize_1to15or32
309 dimensions_[0x60] = {2, 2, Dir::Vertical, 2, true};
310
311 // 0x61-0x62: Downwards 4x2 - GetSize_1to15or26
312 for (int id = 0x61; id <= 0x62; id++) {
313 dimensions_[id] = {4, 2, Dir::Vertical, 2, false};
314 }
315
316 // 0x63-0x68: Downwards variants - GetSize_1to16
317 for (int id = 0x63; id <= 0x68; id++) {
318 dimensions_[id] = {4, 2, Dir::Vertical, 2, false};
319 }
320
321 // 0x69: Downwards edge +3
322 dimensions_[0x69] = {1, 2, Dir::Vertical, 1, false};
323
324 // 0x6A-0x6B: Downwards edge
325 for (int id = 0x6A; id <= 0x6B; id++) {
326 dimensions_[id] = {1, 1, Dir::Vertical, 1, false};
327 }
328
329 // 0x6C-0x6D: Downwards corners
330 for (int id = 0x6C; id <= 0x6D; id++) {
331 dimensions_[id] = {2, 1, Dir::Vertical, 1, false};
332 }
333
334 // 0x6E-0x6F: Nothing
335 dimensions_[0x6E] = {1, 1, Dir::None, 0, false};
336 dimensions_[0x6F] = {1, 1, Dir::None, 0, false};
337
338 // 0x70: Downwards Floor 4x4
339 dimensions_[0x70] = {4, 4, Dir::Vertical, 4, false};
340
341 // 0x71: Downwards Solid 1x1 +3
342 dimensions_[0x71] = {1, 4, Dir::Vertical, 1, false};
343
344 // 0x72: Nothing
345 dimensions_[0x72] = {1, 1, Dir::None, 0, false};
346
347 // 0x73-0x74: Downwards Decor 4x4 spaced 2
348 for (int id = 0x73; id <= 0x74; id++) {
349 dimensions_[id] = {4, 4, Dir::Vertical, 6, false};
350 }
351
352 // 0x75: Downwards Pillar 2x4 spaced 2
353 dimensions_[0x75] = {2, 4, Dir::Vertical, 6, false};
354
355 // 0x76-0x77: Downwards Decor 3x4 spaced 4
356 for (int id = 0x76; id <= 0x77; id++) {
357 dimensions_[id] = {3, 4, Dir::Vertical, 6, false};
358 }
359
360 // 0x78, 0x7B: Downwards Decor 2x2 spaced 12
361 dimensions_[0x78] = {2, 2, Dir::Vertical, 14, false};
362 dimensions_[0x7B] = {2, 2, Dir::Vertical, 14, false};
363
364 // 0x79-0x7A: Downwards Edge 1x1
365 for (int id = 0x79; id <= 0x7A; id++) {
366 dimensions_[id] = {1, 1, Dir::Vertical, 1, false};
367 }
368
369 // 0x7C: Downwards Line 1x1 +1
370 dimensions_[0x7C] = {1, 2, Dir::Vertical, 1, false};
371
372 // 0x7D: Downwards 2x2
373 dimensions_[0x7D] = {2, 2, Dir::Vertical, 2, false};
374
375 // 0x7E: Nothing
376 dimensions_[0x7E] = {1, 1, Dir::None, 0, false};
377
378 // 0x7F-0x80: Downwards Decor 2x4 spaced 8
379 for (int id = 0x7F; id <= 0x80; id++) {
380 dimensions_[id] = {2, 4, Dir::Vertical, 10, false};
381 }
382
383 // 0x81-0x84: Downwards Decor 3x4 spaced 2
384 for (int id = 0x81; id <= 0x84; id++) {
385 dimensions_[id] = {3, 4, Dir::Vertical, 5, false};
386 }
387
388 // 0x85-0x86: Downwards Cannon Hole 3x6
389 for (int id = 0x85; id <= 0x86; id++) {
390 dimensions_[id] = {3, 6, Dir::Vertical, 6, false};
391 }
392
393 // 0x87: Downwards Pillar 2x4 spaced 2
394 dimensions_[0x87] = {2, 4, Dir::Vertical, 6, false};
395
396 // 0x88: Downwards Big Rail 3x1 +5
397 dimensions_[0x88] = {3, 6, Dir::Vertical, 1, false};
398
399 // 0x89: Downwards Block 2x2 spaced 2
400 dimensions_[0x89] = {2, 2, Dir::Vertical, 4, false};
401
402 // 0x8A-0x8C: Edge variants
403 for (int id = 0x8A; id <= 0x8C; id++) {
404 dimensions_[id] = {1, 1, Dir::Vertical, 1, false};
405 }
406
407 // 0x8D-0x8E: Downwards Edge 1x1
408 for (int id = 0x8D; id <= 0x8E; id++) {
409 dimensions_[id] = {1, 1, Dir::Vertical, 1, false};
410 }
411
412 // 0x8F: Downwards Bar 2x3
413 dimensions_[0x8F] = {2, 3, Dir::Vertical, 3, false};
414
415 // 0x90-0x94: Staircase objects - 4x4 or 4x2
416 for (int id = 0x90; id <= 0x94; id++) {
417 dimensions_[id] = {4, 4, Dir::None, 0, false};
418 }
419
420 // 0x95: Downwards Pots 2x2
421 dimensions_[0x95] = {2, 2, Dir::Vertical, 2, false};
422
423 // 0x96: Downwards Hammer Pegs 2x2
424 dimensions_[0x96] = {2, 2, Dir::Vertical, 2, false};
425
426 // 0x97-0x9F: Nothing
427 for (int id = 0x97; id <= 0x9F; id++) {
428 dimensions_[id] = {1, 1, Dir::None, 0, false};
429 }
430
431 // ============================================================================
432 // Diagonal ceilings (0xA0-0xAC)
433 // ============================================================================
434 // ASM: These have fixed patterns, 4x4 base size
435 // TopLeft: 0xA0, 0xA5, 0xA9
436 for (int id : {0xA0, 0xA5, 0xA9}) {
437 dimensions_[id] = {4, 4, Dir::Diagonal, 4, false};
438 }
439 // BottomLeft: 0xA1, 0xA6, 0xAA
440 for (int id : {0xA1, 0xA6, 0xAA}) {
441 dimensions_[id] = {4, 4, Dir::Diagonal, 4, false};
442 }
443 // TopRight: 0xA2, 0xA7, 0xAB
444 for (int id : {0xA2, 0xA7, 0xAB}) {
445 dimensions_[id] = {4, 4, Dir::Diagonal, 4, false};
446 }
447 // BottomRight: 0xA3, 0xA8, 0xAC
448 for (int id : {0xA3, 0xA8, 0xAC}) {
449 dimensions_[id] = {4, 4, Dir::Diagonal, 4, false};
450 }
451 // BigHole4x4: 0xA4 - extends both directions
452 dimensions_[0xA4] = {4, 4, Dir::Both, 4, true};
453
454 // 0xAD-0xAF, 0xBE-0xBF: Nothing
455 for (int id : {0xAD, 0xAE, 0xAF, 0xBE, 0xBF}) {
456 dimensions_[id] = {1, 1, Dir::None, 0, false};
457 }
458
459 // 0xB0-0xB1: Rightwards Edge 1x1 +7
460 for (int id = 0xB0; id <= 0xB1; id++) {
461 dimensions_[id] = {7, 1, Dir::Horizontal, 1, false};
462 }
463
464 // 0xB2: 4x4 block
465 dimensions_[0xB2] = {4, 4, Dir::Horizontal, 4, false};
466
467 // 0xB3-0xB4: Edge 1x1
468 for (int id = 0xB3; id <= 0xB4; id++) {
469 dimensions_[id] = {1, 1, Dir::Horizontal, 1, false};
470 }
471
472 // 0xB5: Weird 2x4
473 dimensions_[0xB5] = {2, 4, Dir::Vertical, 2, false};
474
475 // 0xB6-0xB7: Rightwards 2x4
476 for (int id = 0xB6; id <= 0xB7; id++) {
477 dimensions_[id] = {2, 4, Dir::Horizontal, 2, false};
478 }
479
480 // 0xB8-0xB9: Rightwards 2x2
481 for (int id = 0xB8; id <= 0xB9; id++) {
482 dimensions_[id] = {2, 2, Dir::Horizontal, 2, true};
483 }
484
485 // 0xBA: 4x4 block
486 dimensions_[0xBA] = {4, 4, Dir::Horizontal, 4, false};
487
488 // 0xBB: Rightwards Block 2x2 spaced 2
489 dimensions_[0xBB] = {2, 2, Dir::Horizontal, 4, false};
490
491 // 0xBC: Rightwards Pots 2x2
492 dimensions_[0xBC] = {2, 2, Dir::Horizontal, 2, false};
493
494 // 0xBD: Rightwards Hammer Pegs 2x2
495 dimensions_[0xBD] = {2, 2, Dir::Horizontal, 2, false};
496
497 // ============================================================================
498 // SuperSquare objects (0xC0-0xCF, 0xD0-0xDF, 0xE0-0xEF)
499 // These use both size nibbles for independent X/Y sizing.
500 // RoomDraw_4x4BlocksIn4x4SuperSquare, RoomDraw_4x4FloorIn4x4SuperSquare, etc.
501 // width = ((size & 0x0F) + 1) * 4, height = (((size >> 4) & 0x0F) + 1) * 4
502 // ============================================================================
503
504 // 0xC0: Large ceiling (4x4 blocks in super squares)
505 // ASM: RoomDraw_4x4BlocksIn4x4SuperSquare ($018B94)
506 dimensions_[0xC0] = {0, 0, Dir::SuperSquare, 4, false};
507
508 // 0xC2: 4x4 blocks variant (same routine as 0xC0)
509 dimensions_[0xC2] = {0, 0, Dir::SuperSquare, 4, false};
510
511 // 0xC3, 0xD7: 3x3 floor in 4x4 super square
512 dimensions_[0xC3] = {0, 0, Dir::SuperSquare, 4, false};
513 dimensions_[0xD7] = {0, 0, Dir::SuperSquare, 4, false};
514
515 // 0xC4: 4x4 floor one
516 dimensions_[0xC4] = {0, 0, Dir::SuperSquare, 4, false};
517
518 // 0xC5-0xCA: 4x4 floor patterns
519 for (int id = 0xC5; id <= 0xCA; id++) {
520 dimensions_[id] = {0, 0, Dir::SuperSquare, 4, false};
521 }
522
523 // 0xD1-0xD2: 4x4 floor patterns
524 dimensions_[0xD1] = {0, 0, Dir::SuperSquare, 4, false};
525 dimensions_[0xD2] = {0, 0, Dir::SuperSquare, 4, false};
526
527 // 0xD9: 4x4 floor pattern
528 dimensions_[0xD9] = {0, 0, Dir::SuperSquare, 4, false};
529
530 // 0xDB: 4x4 floor two
531 dimensions_[0xDB] = {0, 0, Dir::SuperSquare, 4, false};
532
533 // 0xDF-0xE8: 4x4 floor patterns
534 for (int id = 0xDF; id <= 0xE8; id++) {
535 dimensions_[id] = {0, 0, Dir::SuperSquare, 4, false};
536 }
537
538 // ============================================================================
539 // Chests - fixed 2x2
540 // ============================================================================
541 for (int id : {0xF9, 0xFA, 0xFB, 0xFC, 0xFD}) {
542 dimensions_[id] = {2, 2, Dir::None, 0, false};
543 }
544
545 // ============================================================================
546 // Subtype 2 objects (0x100-0x13F)
547 // ============================================================================
548 // Layout corners - 4x4
549 for (int id = 0x100; id <= 0x103; id++) {
550 dimensions_[id] = {4, 4, Dir::None, 0, false};
551 }
552
553 // Other 4x4 patterns
554 for (int id = 0x104; id <= 0x10F; id++) {
555 dimensions_[id] = {4, 4, Dir::None, 0, false};
556 }
557
558 // Corners - 4x4
559 for (int id = 0x110; id <= 0x11F; id++) {
560 dimensions_[id] = {4, 4, Dir::None, 0, false};
561 }
562
563 // Tables, beds, etc
564 dimensions_[0x122] = {4, 5, Dir::None, 0, false}; // Bed
565 dimensions_[0x123] = {4, 3, Dir::None, 0, false}; // Table
566 dimensions_[0x128] = {4, 5, Dir::None, 0, false}; // Bed variant
567 dimensions_[0x12C] = {3, 6, Dir::None, 0, false}; // 3x6 pattern
568 dimensions_[0x13E] = {6, 3, Dir::None, 0, false}; // Utility 6x3
569
570 // ============================================================================
571 // Subtype 3 objects (0xF80-0xFFF)
572 // ============================================================================
573 // Default for Type 3: most are 2x2 fixed objects
574 for (int id = 0xF80; id <= 0xFFF; id++) {
575 dimensions_[id] = {2, 2, Dir::None, 0, false};
576 }
577
578 // Override specific Type 3 objects with known sizes
579 // 0xFB1-0xFB2: Big Chest 4x3
580 dimensions_[0xFB1] = {4, 3, Dir::None, 0, false};
581 dimensions_[0xFB2] = {4, 3, Dir::None, 0, false};
582
583 // Light beams and boss shells
584 dimensions_[0xFF0] = {2, 4, Dir::None, 0, false}; // Light beam
585 dimensions_[0xFF1] = {4, 8, Dir::None, 0, false}; // Big light beam
586 dimensions_[0xFF8] = {4, 8, Dir::None, 0, false}; // Ganon Triforce floor
587}
588
590 // ROM addresses from ZScream:
591 // Tile data offset table: $018000
592 // Routine pointer table: $018200
593 // These tables help determine object sizes based on tile counts
594
595 constexpr int kSubtype1TileOffsets = 0x8000;
596 constexpr int kSubtype1Routines = 0x8200;
597
598 // Read tile count for each object to refine dimensions
599 for (int id = 0; id < 0xF8; id++) {
600 auto offset_result = rom->ReadWord(kSubtype1TileOffsets + id * 2);
601 if (!offset_result.ok()) continue;
602
603 // Tile count can inform base size
604 // This is a simplified heuristic - full accuracy requires parsing
605 // the actual tile data
606 }
607}
608
610 // Subtype 2 data offset: $0183F0
611 // Subtype 2 routine ptr: $018470
612 constexpr int kSubtype2TileOffsets = 0x83F0;
613 (void)kSubtype2TileOffsets;
614 (void)rom;
615 // Similar parsing for subtype 2 objects
616}
617
619 // Subtype 3 data offset: $0184F0
620 // Subtype 3 routine ptr: $0185F0
621 constexpr int kSubtype3TileOffsets = 0x84F0;
622 (void)kSubtype3TileOffsets;
623 (void)rom;
624 // Similar parsing for subtype 3 objects
625}
626
627} // namespace zelda3
628} // namespace yaze
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:24
absl::StatusOr< uint16_t > ReadWord(int offset)
Definition rom.cc:230
bool is_loaded() const
Definition rom.h:128
ROM-based object dimension lookup table.
std::pair< int, int > GetBaseDimensions(int object_id) const
std::tuple< int, int, int, int > GetHitTestBounds(const RoomObject &obj) const
std::pair< int, int > GetDimensions(int object_id, int size) const
std::unordered_map< int, DimensionEntry > dimensions_
static ObjectDimensionTable & Get()
std::pair< int, int > GetSelectionDimensions(int object_id, int size) const