Files
yaze/src/app/zelda3/dungeon/object_drawer.h
scawful 78b7d38359 feat: Implement Downwards Drawing Routines in ObjectDrawer
- Added multiple downwards drawing routines for various object types, enhancing the rendering capabilities of the ObjectDrawer.
- Implemented methods for drawing 2x2 and 4x2 tiles with specific patterns and sizes, including edge cases for certain object IDs.
- Updated the initialization logic to map new object IDs to their respective drawing routines, ensuring comprehensive coverage for downwards rendering.
- Introduced debug logging for object drawing to facilitate troubleshooting and performance monitoring.
2025-10-10 02:40:59 -04:00

184 lines
9.4 KiB
C++

#ifndef YAZE_APP_ZELDA3_DUNGEON_OBJECT_DRAWER_H
#define YAZE_APP_ZELDA3_DUNGEON_OBJECT_DRAWER_H
#include <vector>
#include <unordered_map>
#include <functional>
#include "absl/status/status.h"
#include "app/gfx/background_buffer.h"
#include "app/gfx/snes_tile.h"
#include "app/gfx/snes_palette.h"
#include "app/rom.h"
#include "app/zelda3/dungeon/room_object.h"
namespace yaze {
namespace zelda3 {
/**
* @brief Draws dungeon objects to background buffers using game patterns
*
* This class interprets object IDs and draws them to BG1/BG2 buffers
* using the patterns extracted from the game's drawing routines.
* Based on ZScream's DungeonObjectData.cs and Subtype1_Draw.cs patterns.
*
* Architecture:
* 1. Load tile data from ROM for the object
* 2. Look up draw routine ID from object ID mapping
* 3. Execute appropriate draw routine with size/orientation
* 4. Write tiles to BackgroundBuffer according to pattern
* 5. Handle palette coordination and graphics sheet access
*/
class ObjectDrawer {
public:
explicit ObjectDrawer(Rom* rom, const uint8_t* room_gfx_buffer = nullptr);
/**
* @brief Draw a room object to background buffers
* @param object The object to draw
* @param bg1 Background layer 1 buffer
* @param bg2 Background layer 2 buffer
* @param palette_group Current palette group for color mapping
* @return Status of the drawing operation
*/
absl::Status DrawObject(const RoomObject& object,
gfx::BackgroundBuffer& bg1,
gfx::BackgroundBuffer& bg2,
const gfx::PaletteGroup& palette_group);
/**
* @brief Draw all objects in a room
* @param objects Vector of room objects
* @param bg1 Background layer 1 buffer
* @param bg2 Background layer 2 buffer
* @param palette_group Current palette group for color mapping
* @return Status of the drawing operation
*/
absl::Status DrawObjectList(const std::vector<RoomObject>& objects,
gfx::BackgroundBuffer& bg1,
gfx::BackgroundBuffer& bg2,
const gfx::PaletteGroup& palette_group);
/**
* @brief Get draw routine ID for an object
* @param object_id The object ID to look up
* @return Draw routine ID (0-24) based on ZScream mapping
*/
int GetDrawRoutineId(int16_t object_id) const;
/**
* @brief Initialize draw routine registry
* Must be called before drawing objects
*/
void InitializeDrawRoutines();
/**
* @brief Draw a single tile directly to bitmap
* @param bitmap Target bitmap to draw to
* @param tile_info Tile information (ID, palette, mirroring)
* @param pixel_x X pixel coordinate in bitmap
* @param pixel_y Y pixel coordinate in bitmap
* @param tiledata Source graphics data from ROM
*/
void DrawTileToBitmap(gfx::Bitmap& bitmap, const gfx::TileInfo& tile_info,
int pixel_x, int pixel_y, const uint8_t* tiledata);
private:
// Draw routine function type
using DrawRoutine = std::function<void(ObjectDrawer*, const RoomObject&, gfx::BackgroundBuffer&,
const std::vector<gfx::Tile16>&)>;
// Core draw routines (based on ZScream's subtype1_routines table)
void DrawRightwards2x2_1to15or32(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwards2x4_1to15or26(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwards2x4spaced4_1to16(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwards2x4spaced4_1to16_BothBG(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwards2x2_1to16(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawDiagonalAcute_1to16(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawDiagonalGrave_1to16(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawDiagonalAcute_1to16_BothBG(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawDiagonalGrave_1to16_BothBG(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwards1x2_1to16_plus2(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwardsHasEdge1x1_1to16_plus3(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwardsHasEdge1x1_1to16_plus2(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwardsTopCorners1x2_1to16_plus13(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwardsBottomCorners1x2_1to16_plus13(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void CustomDraw(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwards4x4_1to16(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwards1x1Solid_1to16_plus3(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawDoorSwitcherer(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwardsDecor4x4spaced2_1to16(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwardsStatue2x3spaced2_1to16(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwardsPillar2x4spaced4_1to16(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwardsDecor4x3spaced4_1to16(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwardsDoubled2x2spaced2_1to16(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawRightwardsDecor2x2spaced12_1to16(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
// Downwards draw routines (missing implementation)
void DrawDownwards2x2_1to15or32(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawDownwards4x2_1to15or26(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawDownwards4x2_1to16_BothBG(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawDownwardsDecor4x2spaced4_1to16(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawDownwards2x2_1to16(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawDownwardsHasEdge1x1_1to16_plus3(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawDownwardsEdge1x1_1to16(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawDownwardsLeftCorners2x1_1to16_plus12(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
void DrawDownwardsRightCorners2x1_1to16_plus12(const RoomObject& obj, gfx::BackgroundBuffer& bg,
const std::vector<gfx::Tile16>& tiles);
// Utility methods
void WriteTile8(gfx::BackgroundBuffer& bg, int tile_x, int tile_y,
const gfx::TileInfo& tile_info);
bool IsValidTilePosition(int tile_x, int tile_y) const;
// Draw routine registry
std::unordered_map<int16_t, int> object_to_routine_map_;
std::vector<DrawRoutine> draw_routines_;
bool routines_initialized_ = false;
Rom* rom_;
const uint8_t* room_gfx_buffer_; // Room-specific graphics buffer (current_gfx16_)
// Canvas dimensions in tiles (64x64 = 512x512 pixels)
static constexpr int kMaxTilesX = 64;
static constexpr int kMaxTilesY = 64;
};
} // namespace zelda3
} // namespace yaze
#endif // YAZE_APP_ZELDA3_DUNGEON_OBJECT_DRAWER_H