Files
yaze/test/unit/zelda3/overworld_test.cc
2025-11-21 21:35:50 -05:00

298 lines
8.3 KiB
C++

#include "zelda3/overworld/overworld.h"
#include <gtest/gtest.h>
#include <memory>
#include "app/rom.h"
#include "zelda3/overworld/overworld_map.h"
namespace yaze {
namespace zelda3 {
class OverworldTest : public ::testing::Test {
protected:
void SetUp() override {
// Skip tests on Linux for automated github builds
#if defined(__linux__)
GTEST_SKIP();
#endif
// Create a mock ROM for testing
rom_ = std::make_unique<Rom>();
// Initialize with minimal ROM data for testing
std::vector<uint8_t> mock_rom_data(0x200000,
0x00); // 2MB ROM filled with 0x00
// Set up some basic ROM data that OverworldMap expects
mock_rom_data[0x140145] =
0xFF; // OverworldCustomASMHasBeenApplied = vanilla
// Message IDs (2 bytes per map)
for (int i = 0; i < 160; i++) { // 160 maps total
mock_rom_data[0x3F51D + (i * 2)] = 0x00;
mock_rom_data[0x3F51D + (i * 2) + 1] = 0x00;
}
// Area graphics (1 byte per map)
for (int i = 0; i < 160; i++) {
mock_rom_data[0x7C9C + i] = 0x00;
}
// Area palettes (1 byte per map)
for (int i = 0; i < 160; i++) {
mock_rom_data[0x7D1C + i] = 0x00;
}
// Screen sizes (1 byte per map)
for (int i = 0; i < 160; i++) {
mock_rom_data[0x1788D + i] = 0x01; // Small area by default
}
// Sprite sets (1 byte per map)
for (int i = 0; i < 160; i++) {
mock_rom_data[0x7A41 + i] = 0x00;
}
// Sprite palettes (1 byte per map)
for (int i = 0; i < 160; i++) {
mock_rom_data[0x7B41 + i] = 0x00;
}
// Music (1 byte per map)
for (int i = 0; i < 160; i++) {
mock_rom_data[0x14303 + i] = 0x00;
mock_rom_data[0x14303 + 0x40 + i] = 0x00;
mock_rom_data[0x14303 + 0x80 + i] = 0x00;
mock_rom_data[0x14303 + 0xC0 + i] = 0x00;
}
// Dark World music
for (int i = 0; i < 64; i++) {
mock_rom_data[0x14403 + i] = 0x00;
}
// Special world graphics and palettes
for (int i = 0; i < 32; i++) {
mock_rom_data[0x16821 + i] = 0x00;
mock_rom_data[0x16831 + i] = 0x00;
}
// Special world sprite graphics and palettes
for (int i = 0; i < 32; i++) {
mock_rom_data[0x0166E1 + i] = 0x00;
mock_rom_data[0x016701 + i] = 0x00;
}
rom_->LoadFromData(mock_rom_data);
overworld_ = std::make_unique<Overworld>(rom_.get());
}
void TearDown() override {
overworld_.reset();
rom_.reset();
}
std::unique_ptr<Rom> rom_;
std::unique_ptr<Overworld> overworld_;
};
TEST_F(OverworldTest, OverworldMapInitialization) {
// Test that OverworldMap can be created with valid parameters
OverworldMap map(0, rom_.get());
EXPECT_EQ(map.area_graphics(), 0);
EXPECT_EQ(map.area_palette(), 0);
EXPECT_EQ(map.message_id(), 0);
EXPECT_EQ(map.area_size(), AreaSizeEnum::SmallArea);
EXPECT_EQ(map.main_palette(), 0);
EXPECT_EQ(map.area_specific_bg_color(), 0);
EXPECT_EQ(map.subscreen_overlay(), 0);
EXPECT_EQ(map.animated_gfx(), 0);
}
TEST_F(OverworldTest, AreaSizeEnumValues) {
// Test that AreaSizeEnum has correct values
EXPECT_EQ(static_cast<int>(AreaSizeEnum::SmallArea), 0);
EXPECT_EQ(static_cast<int>(AreaSizeEnum::LargeArea), 1);
EXPECT_EQ(static_cast<int>(AreaSizeEnum::WideArea), 2);
EXPECT_EQ(static_cast<int>(AreaSizeEnum::TallArea), 3);
}
TEST_F(OverworldTest, OverworldMapSetters) {
OverworldMap map(0, rom_.get());
// Test main palette setter
map.set_main_palette(5);
EXPECT_EQ(map.main_palette(), 5);
// Test area-specific background color setter
map.set_area_specific_bg_color(0x7FFF);
EXPECT_EQ(map.area_specific_bg_color(), 0x7FFF);
// Test subscreen overlay setter
map.set_subscreen_overlay(0x1234);
EXPECT_EQ(map.subscreen_overlay(), 0x1234);
// Test animated GFX setter
map.set_animated_gfx(10);
EXPECT_EQ(map.animated_gfx(), 10);
// Test custom tileset setter
map.set_custom_tileset(0, 20);
EXPECT_EQ(map.custom_tileset(0), 20);
// Test area size setter
map.SetAreaSize(AreaSizeEnum::LargeArea);
EXPECT_EQ(map.area_size(), AreaSizeEnum::LargeArea);
}
TEST_F(OverworldTest, OverworldMapLargeMapSetup) {
OverworldMap map(0, rom_.get());
// Test SetAsLargeMap
map.SetAsLargeMap(10, 2);
EXPECT_EQ(map.parent(), 10);
EXPECT_EQ(map.large_index(), 2);
EXPECT_TRUE(map.is_large_map());
EXPECT_EQ(map.area_size(), AreaSizeEnum::LargeArea);
// Test SetAsSmallMap
map.SetAsSmallMap(5);
EXPECT_EQ(map.parent(), 5);
EXPECT_EQ(map.large_index(), 0);
EXPECT_FALSE(map.is_large_map());
EXPECT_EQ(map.area_size(), AreaSizeEnum::SmallArea);
}
TEST_F(OverworldTest, OverworldMapCustomTilesetArray) {
OverworldMap map(0, rom_.get());
// Test setting all 8 custom tileset slots
for (int i = 0; i < 8; i++) {
map.set_custom_tileset(i, i + 10);
EXPECT_EQ(map.custom_tileset(i), i + 10);
}
// Test mutable access
for (int i = 0; i < 8; i++) {
*map.mutable_custom_tileset(i) = i + 20;
EXPECT_EQ(map.custom_tileset(i), i + 20);
}
}
TEST_F(OverworldTest, OverworldMapSpriteProperties) {
OverworldMap map(0, rom_.get());
// Test sprite graphics setters
map.set_sprite_graphics(0, 1);
map.set_sprite_graphics(1, 2);
map.set_sprite_graphics(2, 3);
EXPECT_EQ(map.sprite_graphics(0), 1);
EXPECT_EQ(map.sprite_graphics(1), 2);
EXPECT_EQ(map.sprite_graphics(2), 3);
// Test sprite palette setters
map.set_sprite_palette(0, 4);
map.set_sprite_palette(1, 5);
map.set_sprite_palette(2, 6);
EXPECT_EQ(map.sprite_palette(0), 4);
EXPECT_EQ(map.sprite_palette(1), 5);
EXPECT_EQ(map.sprite_palette(2), 6);
}
TEST_F(OverworldTest, OverworldMapBasicProperties) {
OverworldMap map(0, rom_.get());
// Test basic property setters
map.set_area_graphics(15);
EXPECT_EQ(map.area_graphics(), 15);
map.set_area_palette(8);
EXPECT_EQ(map.area_palette(), 8);
map.set_message_id(0x1234);
EXPECT_EQ(map.message_id(), 0x1234);
}
TEST_F(OverworldTest, OverworldMapMutableAccessors) {
OverworldMap map(0, rom_.get());
// Test mutable accessors
*map.mutable_area_graphics() = 25;
EXPECT_EQ(map.area_graphics(), 25);
*map.mutable_area_palette() = 12;
EXPECT_EQ(map.area_palette(), 12);
*map.mutable_message_id() = 0x5678;
EXPECT_EQ(map.message_id(), 0x5678);
*map.mutable_main_palette() = 7;
EXPECT_EQ(map.main_palette(), 7);
*map.mutable_animated_gfx() = 15;
EXPECT_EQ(map.animated_gfx(), 15);
*map.mutable_subscreen_overlay() = 0x9ABC;
EXPECT_EQ(map.subscreen_overlay(), 0x9ABC);
}
TEST_F(OverworldTest, OverworldMapDestroy) {
OverworldMap map(0, rom_.get());
// Set some properties
map.set_area_graphics(10);
map.set_main_palette(5);
map.SetAreaSize(AreaSizeEnum::LargeArea);
// Destroy and verify reset
map.Destroy();
EXPECT_EQ(map.area_graphics(), 0);
EXPECT_EQ(map.main_palette(), 0);
EXPECT_EQ(map.area_size(), AreaSizeEnum::SmallArea);
EXPECT_FALSE(map.is_initialized());
}
// Integration test for world-based sprite filtering
TEST_F(OverworldTest, WorldBasedSpriteFiltering) {
// This test verifies the logic used in DrawOverworldSprites
// for filtering sprites by world
int current_world = 1; // Dark World
int sprite_map_id = 0x50; // Map 0x50 (Dark World)
// Test that sprite should be shown for Dark World
bool should_show = (sprite_map_id < 0x40 + (current_world * 0x40) &&
sprite_map_id >= (current_world * 0x40));
EXPECT_TRUE(should_show);
// Test that sprite should NOT be shown for Light World
current_world = 0; // Light World
should_show = (sprite_map_id < 0x40 + (current_world * 0x40) &&
sprite_map_id >= (current_world * 0x40));
EXPECT_FALSE(should_show);
// Test boundary conditions
current_world = 1; // Dark World
sprite_map_id = 0x40; // First Dark World map
should_show = (sprite_map_id < 0x40 + (current_world * 0x40) &&
sprite_map_id >= (current_world * 0x40));
EXPECT_TRUE(should_show);
sprite_map_id = 0x7F; // Last Dark World map
should_show = (sprite_map_id < 0x40 + (current_world * 0x40) &&
sprite_map_id >= (current_world * 0x40));
EXPECT_TRUE(should_show);
sprite_map_id = 0x80; // First Special World map
should_show = (sprite_map_id < 0x40 + (current_world * 0x40) &&
sprite_map_id >= (current_world * 0x40));
EXPECT_FALSE(should_show);
}
} // namespace zelda3
} // namespace yaze