3#include "absl/status/status.h"
4#include "absl/strings/str_format.h"
18 : base_ptr(base), index_mask(mask), id_offset(offset) {}
24 if (object_id >= 0xF80) {
28 }
else if (object_id >= 0x100) {
40 static_cast<int>(rhs));
45 static_cast<int>(rhs));
50 static_cast<int>(rhs));
54 return static_cast<ObjectOption>(~static_cast<int>(option));
66 if (
rom_ ==
nullptr) {
68 if (
id_ == 0x001 ||
id_ == 0x002 ||
id_ == 0x061 ||
id_ == 0x062 ||
69 (
id_ >= 0x100 &&
id_ <= 0x103)) {
70 LOG_DEBUG(
"RoomObject",
"EnsureTilesLoaded: obj=0x%03X ROM is NULL!",
78 if (parser_status.ok()) {
81 if (
id_ == 0x001 ||
id_ == 0x002 ||
id_ == 0x061 ||
id_ == 0x062 ||
82 (
id_ >= 0x100 &&
id_ <= 0x103)) {
84 "EnsureTilesLoaded: obj=0x%03X loaded %zu tiles via parser",
91 if (
id_ == 0x001 ||
id_ == 0x002 ||
id_ == 0x061 ||
id_ == 0x062 ||
92 (
id_ >= 0x100 &&
id_ <= 0x103)) {
94 "EnsureTilesLoaded: obj=0x%03X parser failed: %s, trying legacy",
95 id_, std::string(parser_status.message()).c_str());
102 SubtypeTableInfo sti = GetSubtypeTable(
id_);
104 int index = ((
id_ - sti.id_offset) & sti.index_mask);
105 int tile_ptr = sti.base_ptr + (index * 2);
108 if (tile_ptr < 0 || tile_ptr + 1 >= (
int)
rom_->
size()) {
110 LOG_DEBUG(
"RoomObject",
"Tile pointer out of bounds for object %04X",
id_);
116 int tile_rel = (int16_t)((rom_data[tile_ptr + 1] << 8) + rom_data[tile_ptr]);
121 if (pos < 0 || pos + 7 >= (
int)
rom_->
size()) {
123 LOG_DEBUG(
"RoomObject",
"Tile data position out of bounds for object %04X",
131 uint16_t w0 = (uint16_t)(rom_data[pos] | (rom_data[pos + 1] << 8));
132 uint16_t w1 = (uint16_t)(rom_data[pos + 2] | (rom_data[pos + 3] << 8));
133 uint16_t w2 = (uint16_t)(rom_data[pos + 4] | (rom_data[pos + 5] << 8));
134 uint16_t w3 = (uint16_t)(rom_data[pos + 6] | (rom_data[pos + 7] << 8));
146 if (
rom_ ==
nullptr) {
147 return absl::InvalidArgumentError(
"ROM is null");
153 return result.status();
156 tiles_ = std::move(result.value());
158 return absl::OkStatus();
167 return absl::FailedPreconditionError(
"No tiles loaded for object");
170 return std::span<const gfx::TileInfo>(
tiles_.data(),
tiles_.size());
178 if (index < 0 || index >=
static_cast<int>(
tiles_.size())) {
179 return absl::OutOfRangeError(absl::StrFormat(
180 "Tile index %d out of range (0-%d)", index,
tiles_.size() - 1));
233 id = (b3 & 0x3F) | 0x100;
234 x = ((b2 & 0xF0) >> 4) | ((b1 & 0x03) << 4);
235 y = ((b2 & 0x0F) << 2) | ((b3 & 0xC0) >> 6);
238 "Type2: b1=%02X b2=%02X b3=%02X -> id=%04X x=%d y=%d size=%d", b1,
243 else if (b3 >= 0xF8) {
244 id = (
static_cast<uint16_t
>(b3) << 4) | 0x80 |
245 ((
static_cast<uint16_t
>(b2 & 0x03) << 2) + (b1 & 0x03));
246 x = (b1 & 0xFC) >> 2;
247 y = (b2 & 0xFC) >> 2;
248 size = ((b1 & 0x03) << 2) | (b2 & 0x03);
250 "Type3: b1=%02X b2=%02X b3=%02X -> id=%04X x=%d y=%d size=%d", b1,
256 x = (b1 & 0xFC) >> 2;
257 y = (b2 & 0xFC) >> 2;
258 size = ((b1 & 0x03) << 2) | (b2 & 0x03);
260 "Type1: b1=%02X b2=%02X b3=%02X -> id=%04X x=%d y=%d size=%d", b1,
268 if ((
id >= 0x03 &&
id <= 0x04) ||
269 (
id >= 0x63 &&
id <= 0x64) ||
271 id == 0x0C ||
id == 0x0D ||
id == 0x10 ||
id == 0x11 ||
id == 0x14 ||
272 id == 0x15 ||
id == 0x18 ||
id == 0x19 ||
id == 0x1C ||
id == 0x1D ||
275 id == 0x0E ||
id == 0x0F ||
id == 0x12 ||
id == 0x13 ||
id == 0x16 ||
276 id == 0x17 ||
id == 0x1A ||
id == 0x1B ||
id == 0x1E ||
id == 0x1F) {
287 if (
id_ >= 0x100 &&
id_ < 0x200) {
289 bytes.
b1 = 0xFC | ((
x_ & 0x30) >> 4);
290 bytes.
b2 = ((
x_ & 0x0F) << 4) | ((
y_ & 0x3C) >> 2);
291 bytes.
b3 = ((
y_ & 0x03) << 6) | (
id_ & 0x3F);
292 }
else if (
id_ >= 0xF00) {
294 bytes.
b1 = (
x_ << 2) | (
id_ & 0x03);
295 bytes.
b2 = (
y_ << 2) | ((
id_ >> 2) & 0x03);
296 bytes.
b3 = (
id_ >> 4) & 0xFF;
299 uint8_t clamped_size =
size_ > 15 ? 15 :
size_;
300 bytes.
b1 = (
x_ << 2) | ((clamped_size >> 2) & 0x03);
301 bytes.
b2 = (
y_ << 2) | (clamped_size & 0x03);
302 bytes.
b3 =
static_cast<uint8_t
>(
id_);
Direct ROM parser for dungeon objects.
absl::StatusOr< std::vector< gfx::TileInfo > > ParseObject(int16_t object_id)
Parse object data directly from ROM.
absl::StatusOr< const gfx::TileInfo * > GetTile(int index) const
static RoomObject DecodeObjectFromBytes(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t layer)
std::vector< gfx::TileInfo > tiles_
ObjectBytes EncodeObjectToBytes() const
static int DetermineObjectType(uint8_t b1, uint8_t b3)
absl::Status LoadTilesWithParser()
absl::StatusOr< std::span< const gfx::TileInfo > > GetTiles() const
RoomObject(int16_t id, uint8_t x, uint8_t y, uint8_t size, uint8_t layer=0)
#define LOG_DEBUG(category, format,...)
TileInfo WordToTileInfo(uint16_t word)
SubtypeTableInfo GetSubtypeTable(int object_id)
constexpr int kRoomObjectSubtype3
ObjectOption operator|(ObjectOption lhs, ObjectOption rhs)
ObjectOption operator^(ObjectOption lhs, ObjectOption rhs)
constexpr int kRoomObjectSubtype1
constexpr int kRoomObjectSubtype2
constexpr int kRoomObjectTileAddress
ObjectOption operator~(ObjectOption option)
ObjectOption operator&(ObjectOption lhs, ObjectOption rhs)
SubtypeTableInfo(int base, int mask, int offset=0)