6#include "absl/strings/str_format.h"
11static constexpr int kRoomObjectSubtype1 = 0x0A8000;
12static constexpr int kRoomObjectSubtype2 = 0x0A9000;
13static constexpr int kRoomObjectSubtype3 = 0x0AA000;
14static constexpr int kRoomObjectTileAddress = 0x0AB000;
20 if (
rom_ ==
nullptr) {
21 return absl::InvalidArgumentError(
"ROM is null");
34 return absl::InvalidArgumentError(
35 absl::StrFormat(
"Invalid object subtype for ID: %#04x", object_id));
40 if (
rom_ ==
nullptr) {
41 return absl::InvalidArgumentError(
"ROM is null");
45 if (!subtype_info.ok()) {
46 return subtype_info.status();
50 routine_info.
routine_ptr = subtype_info->routine_ptr;
51 routine_info.
tile_ptr = subtype_info->subtype_ptr;
52 routine_info.
tile_count = subtype_info->max_tile_count;
65 int index = object_id & 0xFF;
72 int index = object_id & 0x7F;
79 int index = object_id & 0xFF;
86 return absl::InvalidArgumentError(
87 absl::StrFormat(
"Invalid object subtype for ID: %#04x", object_id));
97 int size_x = size_byte & 0x03;
98 int size_y = (size_byte >> 2) & 0x03;
105 if (object_id >= 0x80 && object_id <= 0xFF) {
121 int index = object_id & 0xFF;
124 if (tile_ptr + 1 >= (
int)
rom_->
size()) {
125 return absl::OutOfRangeError(
126 absl::StrFormat(
"Tile pointer out of range: %#06x", tile_ptr));
130 uint8_t low =
rom_->
data()[tile_ptr];
131 uint8_t high =
rom_->
data()[tile_ptr + 1];
139 int index = object_id & 0x7F;
142 if (tile_ptr + 1 >= (
int)
rom_->
size()) {
143 return absl::OutOfRangeError(
144 absl::StrFormat(
"Tile pointer out of range: %#06x", tile_ptr));
148 uint8_t low =
rom_->
data()[tile_ptr];
149 uint8_t high =
rom_->
data()[tile_ptr + 1];
157 int index = object_id & 0xFF;
160 if (tile_ptr + 1 >= (
int)
rom_->
size()) {
161 return absl::OutOfRangeError(
162 absl::StrFormat(
"Tile pointer out of range: %#06x", tile_ptr));
166 uint8_t low =
rom_->
data()[tile_ptr];
167 uint8_t high =
rom_->
data()[tile_ptr + 1];
177 if (address < 0 || address + (tile_count * 2) >= (
int)
rom_->
size()) {
178 return absl::OutOfRangeError(
179 absl::StrFormat(
"Tile data address out of range: %#06x", address));
182 std::vector<gfx::TileInfo> tiles;
183 tiles.reserve(tile_count);
186 static int debug_read_count = 0;
187 bool should_log = (debug_read_count < 3);
189 for (
int i = 0; i < tile_count; i++) {
190 int tile_offset = address + (i * 2);
193 uint16_t tile_word =
rom_->
data()[tile_offset] | (
rom_->
data()[tile_offset + 1] << 8);
196 tiles.push_back(tile_info);
199 if (should_log && i < 4) {
200 printf(
"[ObjectParser] ReadTile[%d]: addr=0x%06X word=0x%04X → id=0x%03X pal=%d mirror=(h:%d,v:%d)\n",
201 i, tile_offset, tile_word, tile_info.id_, tile_info.palette_,
202 tile_info.horizontal_mirror_, tile_info.vertical_mirror_);
207 printf(
"[ObjectParser] ReadTileData: addr=0x%06X count=%d → loaded %zu tiles\n",
208 address, tile_count, tiles.size());
216 if (object_id >= 0x200) {
218 }
else if (object_id >= 0x100) {
231 if (object_id == 0x00) {
237 else if (object_id >= 0x01 && object_id <= 0x02) {
243 else if (object_id >= 0x03 && object_id <= 0x04) {
249 else if (object_id >= 0x05 && object_id <= 0x06) {
251 info.
routine_name =
"Rightwards2x4spaced4_1to16_BothBG";
256 else if (object_id >= 0x07 && object_id <= 0x08) {
262 else if (object_id == 0x09) {
268 else if (object_id >= 0x0A && object_id <= 0x0B) {
274 else if (object_id >= 0x15 && object_id <= 0x1F) {
281 else if (object_id >= 0x16 && object_id <= 0x20) {
288 else if (object_id == 0x21) {
294 else if (object_id == 0x22) {
300 else if (object_id >= 0x23 && object_id <= 0x2E) {
306 else if (object_id == 0x2F) {
308 info.
routine_name =
"RightwardsTopCorners1x2_1to16_plus13";
312 else if (object_id == 0x30) {
314 info.
routine_name =
"RightwardsBottomCorners1x2_1to16_plus13";
318 else if (object_id >= 0x31 && object_id <= 0x32) {
323 else if (object_id == 0x33) {
329 else if (object_id == 0x34) {
335 else if (object_id == 0x35) {
340 else if (object_id >= 0x36 && object_id <= 0x37) {
346 else if (object_id == 0x38) {
352 else if (object_id == 0x39 || object_id == 0x3D) {
358 else if (object_id >= 0x3A && object_id <= 0x3B) {
364 else if (object_id == 0x3C) {
366 info.
routine_name =
"RightwardsDoubled2x2spaced2_1to16";
370 else if (object_id == 0x3E) {
376 else if (object_id >= 0x3F && object_id <= 0x40) {
378 info.
routine_name =
"RightwardsHasEdge1x1_1to16_plus2_variant";
absl::StatusOr< ObjectSubtypeInfo > GetObjectSubtype(int16_t object_id)
Get object subtype information.
absl::StatusOr< ObjectRoutineInfo > ParseObjectRoutine(int16_t object_id)
Parse object routine data.
absl::StatusOr< ObjectSizeInfo > ParseObjectSize(int16_t object_id, uint8_t size_byte)
Parse object size and orientation.
absl::StatusOr< std::vector< gfx::TileInfo > > ParseSubtype2(int16_t object_id)
Parse subtype 2 objects (0x100-0x1FF)
absl::StatusOr< std::vector< gfx::TileInfo > > ParseObject(int16_t object_id)
Parse object data directly from ROM.
absl::StatusOr< std::vector< gfx::TileInfo > > ParseSubtype1(int16_t object_id)
Parse subtype 1 objects (0x00-0xFF)
absl::StatusOr< std::vector< gfx::TileInfo > > ParseSubtype3(int16_t object_id)
Parse subtype 3 objects (0x200+)
absl::StatusOr< std::vector< gfx::TileInfo > > ReadTileData(int address, int tile_count)
Read tile data from ROM.
ObjectDrawInfo GetObjectDrawInfo(int16_t object_id) const
Get draw routine information for an object.
int DetermineSubtype(int16_t object_id) const
Determine object subtype from ID.
TileInfo WordToTileInfo(uint16_t word)
constexpr int kRoomObjectSubtype3
constexpr int kRoomObjectSubtype1
constexpr int kRoomObjectSubtype2
constexpr int kRoomObjectTileAddress
Main namespace for the application.
Draw routine information for object rendering.
Object routine information.
bool is_orientation_dependent
Object size and orientation information.
Object subtype information.