backend-infra-engineer: Release v0.3.3 snapshot

This commit is contained in:
scawful
2025-11-21 21:35:50 -05:00
parent 3d71417f62
commit 476dd1cd1c
818 changed files with 65706 additions and 35514 deletions

View File

@@ -5,10 +5,10 @@
// correctly for all three object types (Type1, Type2, Type3) based on
// ZScream's proven implementation.
#include "zelda3/dungeon/room_object.h"
#include <gtest/gtest.h>
#include "zelda3/dungeon/room_object.h"
namespace yaze {
namespace zelda3 {
namespace {
@@ -45,15 +45,16 @@ TEST(RoomObjectEncodingTest, DetermineObjectTypeType3) {
TEST(RoomObjectEncodingTest, Type1EncodeDecodeBasic) {
// Type1: xxxxxxss yyyyyyss iiiiiiii
// Example: Object ID 0x42, position (10, 20), size 3, layer 0
RoomObject obj(0x42, 10, 20, 3, 0);
// Encode
auto bytes = obj.EncodeObjectToBytes();
// Decode
auto decoded = RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 0);
auto decoded =
RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 0);
// Verify
EXPECT_EQ(decoded.id_, obj.id_);
EXPECT_EQ(decoded.x(), obj.x());
@@ -69,10 +70,11 @@ TEST(RoomObjectEncodingTest, Type1MaxValues) {
// - X < 63 OR Size < 12 (b1 >= 0xFC triggers Type2 detection)
// Safe max values: ID=0xF7, X=62, Y=63, Size=15
RoomObject obj(0xF7, 62, 63, 15, 2);
auto bytes = obj.EncodeObjectToBytes();
auto decoded = RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 2);
auto decoded =
RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 2);
EXPECT_EQ(decoded.id_, obj.id_);
EXPECT_EQ(decoded.x(), obj.x());
EXPECT_EQ(decoded.y(), obj.y());
@@ -82,10 +84,11 @@ TEST(RoomObjectEncodingTest, Type1MaxValues) {
TEST(RoomObjectEncodingTest, Type1MinValues) {
// Test minimum values for Type1
RoomObject obj(0x00, 0, 0, 0, 0);
auto bytes = obj.EncodeObjectToBytes();
auto decoded = RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 0);
auto decoded =
RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 0);
EXPECT_EQ(decoded.id_, obj.id_);
EXPECT_EQ(decoded.x(), obj.x());
EXPECT_EQ(decoded.y(), obj.y());
@@ -96,10 +99,11 @@ TEST(RoomObjectEncodingTest, Type1DifferentSizes) {
// Test all valid size values (0-15)
for (int size = 0; size <= 15; size++) {
RoomObject obj(0x30, 15, 20, size, 1);
auto bytes = obj.EncodeObjectToBytes();
auto decoded = RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 1);
auto decoded =
RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 1);
EXPECT_EQ(decoded.size(), size) << "Failed for size " << size;
}
}
@@ -108,9 +112,9 @@ TEST(RoomObjectEncodingTest, Type1RealWorldExample1) {
// Example from actual ROM: Wall object
// Bytes: 0x28 0x50 0x10
// Expected: X=10, Y=20, Size=0, ID=0x10
auto decoded = RoomObject::DecodeObjectFromBytes(0x28, 0x50, 0x10, 0);
EXPECT_EQ(decoded.x(), 10);
EXPECT_EQ(decoded.y(), 20);
EXPECT_EQ(decoded.size(), 0);
@@ -120,9 +124,9 @@ TEST(RoomObjectEncodingTest, Type1RealWorldExample1) {
TEST(RoomObjectEncodingTest, Type1RealWorldExample2) {
// Example: Ceiling object with size
// Correct bytes for X=10, Y=20, Size=3, ID=0x00: 0x28 0x53 0x00
auto decoded = RoomObject::DecodeObjectFromBytes(0x28, 0x53, 0x00, 0);
EXPECT_EQ(decoded.x(), 10);
EXPECT_EQ(decoded.y(), 20);
EXPECT_EQ(decoded.size(), 3);
@@ -136,18 +140,19 @@ TEST(RoomObjectEncodingTest, Type1RealWorldExample2) {
TEST(RoomObjectEncodingTest, Type2EncodeDecodeBasic) {
// Type2: 111111xx xxxxyyyy yyiiiiii
// Example: Object ID 0x125, position (15, 30), size ignored, layer 1
RoomObject obj(0x125, 15, 30, 0, 1);
// Encode
auto bytes = obj.EncodeObjectToBytes();
// Verify b1 starts with 0xFC
EXPECT_GE(bytes.b1, 0xFC);
// Decode
auto decoded = RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 1);
auto decoded =
RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 1);
// Verify
EXPECT_EQ(decoded.id_, obj.id_);
EXPECT_EQ(decoded.x(), obj.x());
@@ -161,10 +166,11 @@ TEST(RoomObjectEncodingTest, Type2MaxValues) {
// Safe max: X=63, Y=59, ID=0x13F (b3 = ((59&0x03)<<6)|(0x3F) = 0xFF still!)
// Even safer: X=63, Y=63, ID=0x11F (b3 = (0xC0|0x1F) = 0xDF < 0xF8)
RoomObject obj(0x11F, 63, 63, 0, 2);
auto bytes = obj.EncodeObjectToBytes();
auto decoded = RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 2);
auto decoded =
RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 2);
EXPECT_EQ(decoded.id_, obj.id_);
EXPECT_EQ(decoded.x(), obj.x());
EXPECT_EQ(decoded.y(), obj.y());
@@ -173,12 +179,13 @@ TEST(RoomObjectEncodingTest, Type2MaxValues) {
TEST(RoomObjectEncodingTest, Type2RealWorldExample) {
// Example: Large brazier (object 0x11C)
// Position (8, 12)
RoomObject obj(0x11C, 8, 12, 0, 0);
auto bytes = obj.EncodeObjectToBytes();
auto decoded = RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 0);
auto decoded =
RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 0);
EXPECT_EQ(decoded.id_, 0x11C);
EXPECT_EQ(decoded.x(), 8);
EXPECT_EQ(decoded.y(), 12);
@@ -191,18 +198,19 @@ TEST(RoomObjectEncodingTest, Type2RealWorldExample) {
TEST(RoomObjectEncodingTest, Type3EncodeDecodeChest) {
// Type3: xxxxxxii yyyyyyii 11111iii
// Example: Small chest (0xF99), position (5, 10)
RoomObject obj(0xF99, 5, 10, 0, 0);
// Encode
auto bytes = obj.EncodeObjectToBytes();
// Verify b3 >= 0xF8
EXPECT_GE(bytes.b3, 0xF8);
// Decode
auto decoded = RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 0);
auto decoded =
RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 0);
// Verify
EXPECT_EQ(decoded.id_, obj.id_);
EXPECT_EQ(decoded.x(), obj.x());
@@ -211,12 +219,13 @@ TEST(RoomObjectEncodingTest, Type3EncodeDecodeChest) {
TEST(RoomObjectEncodingTest, Type3EncodeDcodeBigChest) {
// Example: Big chest (0xFB1), position (15, 20)
RoomObject obj(0xFB1, 15, 20, 0, 1);
auto bytes = obj.EncodeObjectToBytes();
auto decoded = RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 1);
auto decoded =
RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, 1);
EXPECT_EQ(decoded.id_, 0xFB1);
EXPECT_EQ(decoded.x(), 15);
EXPECT_EQ(decoded.y(), 20);
@@ -225,9 +234,9 @@ TEST(RoomObjectEncodingTest, Type3EncodeDcodeBigChest) {
TEST(RoomObjectEncodingTest, Type3RealWorldExample) {
// Example from ROM: Chest at position (10, 15)
// Correct bytes for ID 0xF99: 0x29 0x3E 0xF9
auto decoded = RoomObject::DecodeObjectFromBytes(0x29, 0x3E, 0xF9, 0);
// Expected: X=10, Y=15, ID=0xF99 (small chest)
EXPECT_EQ(decoded.x(), 10);
EXPECT_EQ(decoded.y(), 15);
@@ -242,40 +251,46 @@ TEST(RoomObjectEncodingTest, LayerPreservation) {
// Test that layer information is preserved through encode/decode
for (uint8_t layer = 0; layer <= 2; layer++) {
RoomObject obj(0x42, 10, 20, 3, layer);
auto bytes = obj.EncodeObjectToBytes();
auto decoded = RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, layer);
EXPECT_EQ(decoded.GetLayerValue(), layer) << "Failed for layer " << (int)layer;
auto decoded =
RoomObject::DecodeObjectFromBytes(bytes.b1, bytes.b2, bytes.b3, layer);
EXPECT_EQ(decoded.GetLayerValue(), layer)
<< "Failed for layer " << (int)layer;
}
}
TEST(RoomObjectEncodingTest, BoundaryBetweenTypes) {
// Test boundary values between object types
// NOTE: Type1 can only go up to ID 0xF7 (b3 >= 0xF8 triggers Type3)
// Last safe Type1 object
RoomObject type1(0xF7, 10, 20, 3, 0);
auto bytes1 = type1.EncodeObjectToBytes();
auto decoded1 = RoomObject::DecodeObjectFromBytes(bytes1.b1, bytes1.b2, bytes1.b3, 0);
auto decoded1 =
RoomObject::DecodeObjectFromBytes(bytes1.b1, bytes1.b2, bytes1.b3, 0);
EXPECT_EQ(decoded1.id_, 0xF7);
// First Type2 object
RoomObject type2(0x100, 10, 20, 0, 0);
auto bytes2 = type2.EncodeObjectToBytes();
auto decoded2 = RoomObject::DecodeObjectFromBytes(bytes2.b1, bytes2.b2, bytes2.b3, 0);
auto decoded2 =
RoomObject::DecodeObjectFromBytes(bytes2.b1, bytes2.b2, bytes2.b3, 0);
EXPECT_EQ(decoded2.id_, 0x100);
// Last Type2 object
RoomObject type2_last(0x13F, 10, 20, 0, 0);
auto bytes2_last = type2_last.EncodeObjectToBytes();
auto decoded2_last = RoomObject::DecodeObjectFromBytes(bytes2_last.b1, bytes2_last.b2, bytes2_last.b3, 0);
auto decoded2_last = RoomObject::DecodeObjectFromBytes(
bytes2_last.b1, bytes2_last.b2, bytes2_last.b3, 0);
EXPECT_EQ(decoded2_last.id_, 0x13F);
// Type3 objects (start at 0xF80)
RoomObject type3(0xF99, 10, 20, 0, 0);
auto bytes3 = type3.EncodeObjectToBytes();
auto decoded3 = RoomObject::DecodeObjectFromBytes(bytes3.b1, bytes3.b2, bytes3.b3, 0);
auto decoded3 =
RoomObject::DecodeObjectFromBytes(bytes3.b1, bytes3.b2, bytes3.b3, 0);
EXPECT_EQ(decoded3.id_, 0xF99);
}
@@ -283,13 +298,15 @@ TEST(RoomObjectEncodingTest, ZeroPosition) {
// Test objects at position (0, 0)
RoomObject type1(0x10, 0, 0, 0, 0);
auto bytes1 = type1.EncodeObjectToBytes();
auto decoded1 = RoomObject::DecodeObjectFromBytes(bytes1.b1, bytes1.b2, bytes1.b3, 0);
auto decoded1 =
RoomObject::DecodeObjectFromBytes(bytes1.b1, bytes1.b2, bytes1.b3, 0);
EXPECT_EQ(decoded1.x(), 0);
EXPECT_EQ(decoded1.y(), 0);
RoomObject type2(0x110, 0, 0, 0, 0);
auto bytes2 = type2.EncodeObjectToBytes();
auto decoded2 = RoomObject::DecodeObjectFromBytes(bytes2.b1, bytes2.b2, bytes2.b3, 0);
auto decoded2 =
RoomObject::DecodeObjectFromBytes(bytes2.b1, bytes2.b2, bytes2.b3, 0);
EXPECT_EQ(decoded2.x(), 0);
EXPECT_EQ(decoded2.y(), 0);
}
@@ -301,21 +318,21 @@ TEST(RoomObjectEncodingTest, ZeroPosition) {
TEST(RoomObjectEncodingTest, MultipleObjectsRoundTrip) {
// Test encoding/decoding a batch of different objects
std::vector<RoomObject> objects;
// Add various objects
objects.emplace_back(0x10, 5, 10, 2, 0); // Type1
objects.emplace_back(0x42, 15, 20, 5, 1); // Type1
objects.emplace_back(0x110, 8, 12, 0, 0); // Type2
objects.emplace_back(0x125, 25, 30, 0, 1); // Type2
objects.emplace_back(0xF99, 10, 15, 0, 0); // Type3 (chest)
objects.emplace_back(0xFB1, 20, 25, 0, 2); // Type3 (big chest)
objects.emplace_back(0x10, 5, 10, 2, 0); // Type1
objects.emplace_back(0x42, 15, 20, 5, 1); // Type1
objects.emplace_back(0x110, 8, 12, 0, 0); // Type2
objects.emplace_back(0x125, 25, 30, 0, 1); // Type2
objects.emplace_back(0xF99, 10, 15, 0, 0); // Type3 (chest)
objects.emplace_back(0xFB1, 20, 25, 0, 2); // Type3 (big chest)
for (size_t i = 0; i < objects.size(); i++) {
auto& obj = objects[i];
auto bytes = obj.EncodeObjectToBytes();
auto decoded = RoomObject::DecodeObjectFromBytes(
bytes.b1, bytes.b2, bytes.b3, obj.GetLayerValue());
EXPECT_EQ(decoded.id_, obj.id_) << "Failed at index " << i;
EXPECT_EQ(decoded.x(), obj.x()) << "Failed at index " << i;
EXPECT_EQ(decoded.y(), obj.y()) << "Failed at index " << i;