fix(dungeon): align object drawing and tests

This commit is contained in:
scawful
2025-12-22 14:55:59 -05:00
parent 26ce12cd6f
commit d5e06e943f
18 changed files with 256 additions and 189 deletions

View File

@@ -1148,21 +1148,16 @@ std::optional<size_t> DungeonObjectEditor::FindObjectAt(int room_x,
bool DungeonObjectEditor::IsObjectAtPosition(const RoomObject& object, int x,
int y) {
// Convert object position to pixel coordinates
int obj_x = object.x_ * 16;
int obj_y = object.y_ * 16;
// Coordinates are in room tiles.
int obj_x = object.x_;
int obj_y = object.y_;
// Check if point is within object bounds
// This is a simplified implementation - in practice, you'd check
// against the actual tile data
int obj_width = 16; // Default object width
int obj_height = 16; // Default object height
// Adjust size based on object size value
// Simplified bounds: default to 1x1 tile, grow to 2x2 for large objects.
int obj_width = 1;
int obj_height = 1;
if (object.size_ > 0x80) {
obj_width *= 2;
obj_height *= 2;
obj_width = 2;
obj_height = 2;
}
return (x >= obj_x && x < obj_x + obj_width && y >= obj_y &&
@@ -1225,7 +1220,14 @@ int DungeonObjectEditor::SnapToGrid(int coordinate) {
return coordinate;
}
return (coordinate / config_.grid_size) * config_.grid_size;
int grid_size = config_.grid_size;
if (grid_size <= 0) {
return coordinate;
}
// Coordinates are in room tiles; map pixel grid size to tile steps.
int tile_step = std::max(1, grid_size / 16);
return (coordinate / tile_step) * tile_step;
}
void DungeonObjectEditor::UpdatePreviewObject() {

View File

@@ -6,6 +6,7 @@
#include "absl/strings/str_format.h"
#include "app/gfx/types/snes_tile.h"
#include "rom/rom.h"
#include "core/features.h"
#include "rom/snes.h"
#include "util/log.h"
#include "zelda3/dungeon/draw_routines/draw_routine_registry.h"
@@ -340,10 +341,15 @@ void ObjectDrawer::InitializeDrawRoutines() {
object_to_routine_map_[0x30] = 24; // RoomDraw_RightwardsBottomCorners1x2_1to16_plus13
// Custom Objects (0x31-0x32) - Oracle of Secrets minecart tracks and furniture
// These use external binary files instead of ROM tile data.
// Requires CustomObjectManager initialization and enable_custom_objects feature flag.
object_to_routine_map_[0x31] = DrawRoutineIds::kCustomObject; // Custom tracks
object_to_routine_map_[0x32] = DrawRoutineIds::kCustomObject; // Custom furniture
// USDASM marks these as RoomDraw_Nothing; only map to custom routines when enabled.
if (core::FeatureFlags::get().kEnableCustomObjects) {
// These use external binary files instead of ROM tile data.
object_to_routine_map_[0x31] = DrawRoutineIds::kCustomObject; // Custom tracks
object_to_routine_map_[0x32] = DrawRoutineIds::kCustomObject; // Custom furniture
} else {
object_to_routine_map_[0x31] = DrawRoutineIds::kNothing;
object_to_routine_map_[0x32] = DrawRoutineIds::kNothing;
}
object_to_routine_map_[0x33] = 16; // 4x4 Block
object_to_routine_map_[0x34] = 25; // Solid 1x1
object_to_routine_map_[0x35] = 26; // Door Switcher
@@ -633,19 +639,10 @@ void ObjectDrawer::InitializeDrawRoutines() {
object_to_routine_map_[id] = 39; // Chest draw routine
}
// Subtype 2 Object Mappings (0x100-0x1FF)
// LAYOUT CORNERS: 0x100-0x103 are the concave corners used in room layouts
// These must use DrawCorner4x4 (routine 19) NOT DrawRightwards4x4 (routine 16)
// ASM Reference: bank_01.asm RoomDraw_4x4Corner routine
// 0x100 = Corner (top, concave) ▛ (upper-left)
// 0x101 = Corner (top, concave) ▙ (lower-left)
// 0x102 = Corner (top, concave) ▜ (upper-right)
// 0x103 = Corner (top, concave) ▟ (lower-right)
for (int id = 0x100; id <= 0x103; id++) {
object_to_routine_map_[id] = 19; // DrawCorner4x4 for layout corners
}
// 0x104-0x107: Other 4x4 patterns (non-corner)
for (int id = 0x104; id <= 0x107; id++) {
// Subtype 2 Object Mappings (0x100-0x13F)
// ASM Reference: bank_01.asm .type1_subtype_2_routine ($018470)
// 0x100-0x107: RoomDraw_4x4
for (int id = 0x100; id <= 0x107; id++) {
object_to_routine_map_[id] = 16; // Rightwards 4x4
}
for (int id = 0x108; id <= 0x10F; id++) {

View File

@@ -112,6 +112,13 @@ class ObjectDrawer {
*/
int GetDrawRoutineId(int16_t object_id) const;
/**
* @brief Get the total number of registered draw routines
*/
int GetDrawRoutineCount() const {
return static_cast<int>(draw_routines_.size());
}
/**
* @brief Initialize draw routine registry
* Must be called before drawing objects

View File

@@ -118,7 +118,7 @@ absl::StatusOr<ObjectSubtypeInfo> ObjectParser::GetObjectSubtype(
info.subtype_ptr = kRoomObjectSubtype2 + (index * 2);
// Routine table starts 128 bytes (64 entries * 2 bytes) after data table
info.routine_ptr = kRoomObjectSubtype2 + 0x80 + (index * 2);
info.max_tile_count = 8;
info.max_tile_count = GetSubtype2TileCount(object_id);
break;
}
case 3: {
@@ -127,7 +127,7 @@ absl::StatusOr<ObjectSubtypeInfo> ObjectParser::GetObjectSubtype(
int index = (object_id - 0xF80) & 0x7F;
info.subtype_ptr = kRoomObjectSubtype3 + (index * 2);
info.routine_ptr = kRoomObjectSubtype3 + 0x100 + (index * 2);
info.max_tile_count = 8;
info.max_tile_count = GetSubtype3TileCount(object_id);
break;
}
default:
@@ -653,4 +653,4 @@ ObjectDrawInfo ObjectParser::GetObjectDrawInfo(int16_t object_id) const {
}
} // namespace zelda3
} // namespace yaze
} // namespace yaze