Files
yaze/test/unit/zelda3/object_parser_test.cc
2025-12-22 14:55:59 -05:00

150 lines
4.2 KiB
C++

#include "zelda3/dungeon/object_parser.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <vector>
#include "mocks/mock_rom.h"
namespace yaze {
namespace test {
class ObjectParserTest : public ::testing::Test {
protected:
void SetUp() override {
mock_rom_ = std::make_unique<MockRom>();
SetupMockData();
parser_ = std::make_unique<zelda3::ObjectParser>(mock_rom_.get());
}
void SetupMockData() {
std::vector<uint8_t> mock_data(0x100000, 0x00);
// Set up object subtype tables
SetupSubtypeTable(mock_data, 0x8000, 0x100); // Subtype 1 table
SetupSubtypeTable(mock_data, 0x83F0, 0x80); // Subtype 2 table
SetupSubtypeTable(mock_data, 0x84F0, 0x100); // Subtype 3 table
// Set up tile data
SetupTileData(mock_data, 0x1B52, 0x1000);
static_cast<MockRom*>(mock_rom_.get())->SetTestData(mock_data);
}
void SetupSubtypeTable(std::vector<uint8_t>& data, int base_addr, int count) {
for (int i = 0; i < count; i++) {
int addr = base_addr + (i * 2);
if (addr + 1 < (int)data.size()) {
// Point to tile data at 0x1B52 + (i * 8)
int tile_offset = (i * 8) & 0xFFFF;
data[addr] = tile_offset & 0xFF;
data[addr + 1] = (tile_offset >> 8) & 0xFF;
}
}
}
void SetupTileData(std::vector<uint8_t>& data, int base_addr, int size) {
for (int i = 0; i < size; i += 8) {
int addr = base_addr + i;
if (addr + 7 < (int)data.size()) {
// Create simple tile data (4 words per tile)
for (int j = 0; j < 8; j++) {
data[addr + j] = (i + j) & 0xFF;
}
}
}
}
std::unique_ptr<MockRom> mock_rom_;
std::unique_ptr<zelda3::ObjectParser> parser_;
};
TEST_F(ObjectParserTest, ParseSubtype1Object) {
auto result = parser_->ParseObject(0x01);
ASSERT_TRUE(result.ok());
const auto& tiles = result.value();
EXPECT_EQ(tiles.size(), 8);
// Verify tile data was parsed correctly
for (const auto& tile : tiles) {
EXPECT_NE(tile.id_, 0);
}
}
TEST_F(ObjectParserTest, ParseSubtype2Object) {
auto result = parser_->ParseObject(0x101);
ASSERT_TRUE(result.ok());
const auto& tiles = result.value();
EXPECT_EQ(tiles.size(), 16);
}
TEST_F(ObjectParserTest, ParseSubtype3Object) {
auto result = parser_->ParseObject(0x201);
ASSERT_TRUE(result.ok());
const auto& tiles = result.value();
EXPECT_EQ(tiles.size(), 8);
}
TEST_F(ObjectParserTest, GetObjectSubtype) {
// Subtype 1: Object IDs 0x00-0xFF
auto result1 = parser_->GetObjectSubtype(0x01);
ASSERT_TRUE(result1.ok());
EXPECT_EQ(result1->subtype, 1);
// Subtype 2: Object IDs 0x100-0x1FF
auto result2 = parser_->GetObjectSubtype(0x101);
ASSERT_TRUE(result2.ok());
EXPECT_EQ(result2->subtype, 2);
// Subtype 3: Object IDs 0xF80-0xFFF (decoded from b3 >= 0xF8)
// These map to table indices 0-127 via (id - 0xF80) & 0x7F
auto result3 = parser_->GetObjectSubtype(0xF81);
ASSERT_TRUE(result3.ok());
EXPECT_EQ(result3->subtype, 3);
}
TEST_F(ObjectParserTest, ParseObjectSize) {
// size_byte 0x09 = 0b00001001: size_x = 1 (bits 0-1), size_y = 2 (bits 2-3)
auto result = parser_->ParseObjectSize(0x01, 0x09);
ASSERT_TRUE(result.ok());
const auto& size_info = result.value();
EXPECT_EQ(size_info.width_tiles, 4); // (1 + 1) * 2
EXPECT_EQ(size_info.height_tiles, 6); // (2 + 1) * 2
EXPECT_TRUE(size_info.is_horizontal);
EXPECT_TRUE(size_info.is_repeatable);
EXPECT_EQ(size_info.repeat_count, 0x09);
}
TEST_F(ObjectParserTest, ParseObjectRoutine) {
auto result = parser_->ParseObjectRoutine(0x01);
ASSERT_TRUE(result.ok());
const auto& routine_info = result.value();
EXPECT_NE(routine_info.routine_ptr, 0);
EXPECT_NE(routine_info.tile_ptr, 0);
EXPECT_EQ(routine_info.tile_count, 8);
EXPECT_TRUE(routine_info.is_repeatable);
EXPECT_TRUE(routine_info.is_orientation_dependent);
}
TEST_F(ObjectParserTest, InvalidObjectId) {
auto result = parser_->ParseObject(-1);
EXPECT_FALSE(result.ok());
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument);
}
TEST_F(ObjectParserTest, NullRom) {
zelda3::ObjectParser null_parser(nullptr);
auto result = null_parser.ParseObject(0x01);
EXPECT_FALSE(result.ok());
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument);
}
} // namespace test
} // namespace yaze