3#include "absl/status/status.h"
17 : base_ptr(base), index_mask(mask), id_offset(offset) {}
23 if (object_id >= 0xF80) {
27 }
else if (object_id >= 0x100) {
39 static_cast<int>(rhs));
44 static_cast<int>(rhs));
49 static_cast<int>(rhs));
53 return static_cast<ObjectOption>(~static_cast<int>(option));
65 if (
rom_ ==
nullptr) {
67 if (
id_ == 0x001 ||
id_ == 0x002 ||
id_ == 0x061 ||
id_ == 0x062 ||
68 (
id_ >= 0x100 &&
id_ <= 0x103)) {
69 printf(
"[EnsureTilesLoaded] obj=0x%03X: ROM is NULL!\n",
id_);
76 if (parser_status.ok()) {
79 if (
id_ == 0x001 ||
id_ == 0x002 ||
id_ == 0x061 ||
id_ == 0x062 ||
80 (
id_ >= 0x100 &&
id_ <= 0x103)) {
81 printf(
"[EnsureTilesLoaded] obj=0x%03X: Loaded %zu tiles via parser\n",
88 if (
id_ == 0x001 ||
id_ == 0x002 ||
id_ == 0x061 ||
id_ == 0x062 ||
89 (
id_ >= 0x100 &&
id_ <= 0x103)) {
90 printf(
"[EnsureTilesLoaded] obj=0x%03X: Parser failed: %s, trying legacy\n",
91 id_, std::string(parser_status.message()).c_str());
98 SubtypeTableInfo sti = GetSubtypeTable(
id_);
100 int index = ((
id_ - sti.id_offset) & sti.index_mask);
101 int tile_ptr = sti.base_ptr + (index * 2);
104 if (tile_ptr < 0 || tile_ptr + 1 >= (
int)
rom_->
size()) {
106 LOG_DEBUG(
"RoomObject",
"Tile pointer out of bounds for object %04X",
id_);
112 int tile_rel = (int16_t)((rom_data[tile_ptr + 1] << 8) + rom_data[tile_ptr]);
117 if (pos < 0 || pos + 7 >= (
int)
rom_->
size()) {
119 LOG_DEBUG(
"RoomObject",
"Tile data position out of bounds for object %04X",
id_);
126 uint16_t w0 = (uint16_t)(rom_data[pos] | (rom_data[pos + 1] << 8));
127 uint16_t w1 = (uint16_t)(rom_data[pos + 2] | (rom_data[pos + 3] << 8));
128 uint16_t w2 = (uint16_t)(rom_data[pos + 4] | (rom_data[pos + 5] << 8));
129 uint16_t w3 = (uint16_t)(rom_data[pos + 6] | (rom_data[pos + 7] << 8));
141 if (
rom_ ==
nullptr) {
142 return absl::InvalidArgumentError(
"ROM is null");
148 return result.status();
151 tiles_ = std::move(result.value());
153 return absl::OkStatus();
162 return absl::FailedPreconditionError(
"No tiles loaded for object");
165 return std::span<const gfx::TileInfo>(
tiles_.data(),
tiles_.size());
173 if (index < 0 || index >=
static_cast<int>(
tiles_.size())) {
174 return absl::OutOfRangeError(absl::StrFormat(
175 "Tile index %d out of range (0-%d)", index,
tiles_.size() - 1));
228 id = (b3 & 0x3F) | 0x100;
229 x = ((b2 & 0xF0) >> 4) | ((b1 & 0x03) << 4);
230 y = ((b2 & 0x0F) << 2) | ((b3 & 0xC0) >> 6);
233 "Type2: b1=%02X b2=%02X b3=%02X -> id=%04X x=%d y=%d size=%d",
234 b1, b2, b3,
id,
x,
y,
size);
238 else if (b3 >= 0xF8) {
239 id = (
static_cast<uint16_t
>(b3) << 4) | 0x80 |
240 ((
static_cast<uint16_t
>(b2 & 0x03) << 2) + (b1 & 0x03));
241 x = (b1 & 0xFC) >> 2;
242 y = (b2 & 0xFC) >> 2;
243 size = ((b1 & 0x03) << 2) | (b2 & 0x03);
245 "Type3: b1=%02X b2=%02X b3=%02X -> id=%04X x=%d y=%d size=%d",
246 b1, b2, b3,
id,
x,
y,
size);
251 x = (b1 & 0xFC) >> 2;
252 y = (b2 & 0xFC) >> 2;
253 size = ((b1 & 0x03) << 2) | (b2 & 0x03);
255 "Type1: b1=%02X b2=%02X b3=%02X -> id=%04X x=%d y=%d size=%d",
256 b1, b2, b3,
id,
x,
y,
size);
263 if ((
id >= 0x03 &&
id <= 0x04) ||
264 (
id >= 0x63 &&
id <= 0x64) ||
266 id == 0x0C ||
id == 0x0D ||
id == 0x10 ||
id == 0x11 ||
id == 0x14 ||
267 id == 0x15 ||
id == 0x18 ||
id == 0x19 ||
id == 0x1C ||
id == 0x1D ||
270 id == 0x0E ||
id == 0x0F ||
id == 0x12 ||
id == 0x13 ||
id == 0x16 ||
271 id == 0x17 ||
id == 0x1A ||
id == 0x1B ||
id == 0x1E ||
id == 0x1F) {
282 if (
id_ >= 0x100 &&
id_ < 0x200) {
284 bytes.
b1 = 0xFC | ((
x_ & 0x30) >> 4);
285 bytes.
b2 = ((
x_ & 0x0F) << 4) | ((
y_ & 0x3C) >> 2);
286 bytes.
b3 = ((
y_ & 0x03) << 6) | (
id_ & 0x3F);
287 }
else if (
id_ >= 0xF00) {
289 bytes.
b1 = (
x_ << 2) | (
id_ & 0x03);
290 bytes.
b2 = (
y_ << 2) | ((
id_ >> 2) & 0x03);
291 bytes.
b3 = (
id_ >> 4) & 0xFF;
294 uint8_t clamped_size =
size_ > 15 ? 15 :
size_;
295 bytes.
b1 = (
x_ << 2) | ((clamped_size >> 2) & 0x03);
296 bytes.
b2 = (
y_ << 2) | (clamped_size & 0x03);
297 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)