yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
zscustomoverworld_upgrade_test.cc
Go to the documentation of this file.
1#include <gtest/gtest.h>
2#include <filesystem>
3#include <memory>
4#include <vector>
5#include <string>
6#include <map>
7
8#include "app/rom.h"
9#include "testing.h"
10
11namespace yaze {
12namespace test {
13
24class ZSCustomOverworldUpgradeTest : public ::testing::Test {
25 protected:
26 void SetUp() override {
27 // Skip tests if ROM is not available
28 if (getenv("YAZE_SKIP_ROM_TESTS")) {
29 GTEST_SKIP() << "ROM tests disabled";
30 }
31
32 // Get ROM path from environment or use default
33 const char* rom_path_env = getenv("YAZE_TEST_ROM_PATH");
34 vanilla_rom_path_ = rom_path_env ? rom_path_env : "zelda3.sfc";
35
36 if (!std::filesystem::exists(vanilla_rom_path_)) {
37 GTEST_SKIP() << "Test ROM not found: " << vanilla_rom_path_;
38 }
39
40 // Create test ROM copies for each version
41 vanilla_test_path_ = "test_vanilla.sfc";
42 v2_test_path_ = "test_v2.sfc";
43 v3_test_path_ = "test_v3.sfc";
44
45 // Copy vanilla ROM for testing
46 std::filesystem::copy_file(vanilla_rom_path_, vanilla_test_path_);
47
48 // Define version-specific addresses and features
50 }
51
52 void TearDown() override {
53 // Clean up test files
54 std::vector<std::string> test_files = {
56 };
57
58 for (const auto& file : test_files) {
59 if (std::filesystem::exists(file)) {
60 std::filesystem::remove(file);
61 }
62 }
63 }
64
66 // Vanilla ROM addresses and values
68 {"version_flag", {0x140145, 0xFF}}, // OverworldCustomASMHasBeenApplied
69 {"message_ids", {0x3F51D, 0x00}}, // Message ID table start
70 {"area_graphics", {0x7C9C, 0x00}}, // Area graphics table
71 {"area_palettes", {0x7D1C, 0x00}}, // Area palettes table
72 {"screen_sizes", {0x1788D, 0x01}}, // Screen sizes table
73 {"sprite_sets", {0x7A41, 0x00}}, // Sprite sets table
74 {"sprite_palettes", {0x7B41, 0x00}}, // Sprite palettes table
75 };
76
77 // v2 ROM addresses and values
78 v2_data_ = {
79 {"version_flag", {0x140145, 0x02}}, // v2 version
80 {"message_ids", {0x1417F8, 0x00}}, // Expanded message ID table
81 {"area_graphics", {0x7C9C, 0x00}}, // Same as vanilla
82 {"area_palettes", {0x7D1C, 0x00}}, // Same as vanilla
83 {"screen_sizes", {0x1788D, 0x01}}, // Same as vanilla
84 {"sprite_sets", {0x7A41, 0x00}}, // Same as vanilla
85 {"sprite_palettes", {0x7B41, 0x00}}, // Same as vanilla
86 {"main_palettes", {0x140160, 0x00}}, // New v2 feature
87 };
88
89 // v3 ROM addresses and values
90 v3_data_ = {
91 {"version_flag", {0x140145, 0x03}}, // v3 version
92 {"message_ids", {0x1417F8, 0x00}}, // Same as v2
93 {"area_graphics", {0x7C9C, 0x00}}, // Same as vanilla
94 {"area_palettes", {0x7D1C, 0x00}}, // Same as vanilla
95 {"screen_sizes", {0x1788D, 0x01}}, // Same as vanilla
96 {"sprite_sets", {0x7A41, 0x00}}, // Same as vanilla
97 {"sprite_palettes", {0x7B41, 0x00}}, // Same as vanilla
98 {"main_palettes", {0x140160, 0x00}}, // Same as v2
99 {"bg_colors", {0x140000, 0x00}}, // New v3 feature
100 {"subscreen_overlays", {0x140340, 0x00}}, // New v3 feature
101 {"animated_gfx", {0x1402A0, 0x00}}, // New v3 feature
102 {"custom_tiles", {0x140480, 0x00}}, // New v3 feature
103 };
104 }
105
106 // Helper to apply version-specific patches
107 absl::Status ApplyVersionPatch(Rom& rom, const std::string& version) {
108 const auto* data = &vanilla_data_;
109 if (version == "v2") {
110 data = &v2_data_;
111 } else if (version == "v3") {
112 data = &v3_data_;
113 }
114
115 // Apply version-specific data
116 for (const auto& [key, value] : *data) {
117 RETURN_IF_ERROR(rom.WriteByte(value.first, value.second));
118 }
119
120 // Apply version-specific features
121 if (version == "v2") {
122 // Enable v2 features
123 RETURN_IF_ERROR(rom.WriteByte(0x140146, 0x01)); // Enable main palettes
124 } else if (version == "v3") {
125 // Enable v3 features
126 RETURN_IF_ERROR(rom.WriteByte(0x140146, 0x01)); // Enable main palettes
127 RETURN_IF_ERROR(rom.WriteByte(0x140147, 0x01)); // Enable area-specific BG
128 RETURN_IF_ERROR(rom.WriteByte(0x140148, 0x01)); // Enable subscreen overlay
129 RETURN_IF_ERROR(rom.WriteByte(0x140149, 0x01)); // Enable animated GFX
130 RETURN_IF_ERROR(rom.WriteByte(0x14014A, 0x01)); // Enable custom tile GFX groups
131 RETURN_IF_ERROR(rom.WriteByte(0x14014B, 0x01)); // Enable mosaic
132 }
133
134 return absl::OkStatus();
135 }
136
137 // Helper to validate version-specific addresses
138 bool ValidateVersionAddresses(Rom& rom, const std::string& version) {
139 const auto* data = &vanilla_data_;
140 if (version == "v2") {
141 data = &v2_data_;
142 } else if (version == "v3") {
143 data = &v3_data_;
144 }
145
146 for (const auto& [key, value] : *data) {
147 auto byte_value = rom.ReadByte(value.first);
148 if (!byte_value.ok() || *byte_value != value.second) {
149 return false;
150 }
151 }
152
153 return true;
154 }
155
156 std::string vanilla_rom_path_;
158 std::string v2_test_path_;
159 std::string v3_test_path_;
160
161 std::map<std::string, std::pair<uint32_t, uint8_t>> vanilla_data_;
162 std::map<std::string, std::pair<uint32_t, uint8_t>> v2_data_;
163 std::map<std::string, std::pair<uint32_t, uint8_t>> v3_data_;
164};
165
166// Test vanilla ROM baseline
168 std::unique_ptr<Rom> rom = std::make_unique<Rom>();
169 ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
170
171 // Validate vanilla addresses
172 EXPECT_TRUE(ValidateVersionAddresses(*rom, "vanilla"));
173
174 // Verify version flag
175 auto version_byte = rom->ReadByte(0x140145);
176 ASSERT_TRUE(version_byte.ok());
177 EXPECT_EQ(*version_byte, 0xFF);
178}
179
180// Test vanilla to v2 upgrade
182 // Load vanilla ROM
183 std::unique_ptr<Rom> rom = std::make_unique<Rom>();
184 ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
185
186 // Apply v2 patch
187 ASSERT_OK(ApplyVersionPatch(*rom, "v2"));
188
189 // Validate v2 addresses
190 EXPECT_TRUE(ValidateVersionAddresses(*rom, "v2"));
191
192 // Save v2 ROM
193 ASSERT_OK(rom->SaveToFile(Rom::SaveSettings{.filename = v2_test_path_}));
194
195 // Reload and verify
196 std::unique_ptr<Rom> reloaded_rom = std::make_unique<Rom>();
197 ASSERT_OK(reloaded_rom->LoadFromFile(v2_test_path_));
198
199 EXPECT_TRUE(ValidateVersionAddresses(*reloaded_rom, "v2"));
200 auto version_byte = reloaded_rom->ReadByte(0x140145);
201 ASSERT_TRUE(version_byte.ok());
202 EXPECT_EQ(*version_byte, 0x02);
203}
204
205// Test v2 to v3 upgrade
207 // Load vanilla ROM
208 std::unique_ptr<Rom> rom = std::make_unique<Rom>();
209 ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
210
211 // Apply v2 patch first
212 ASSERT_OK(ApplyVersionPatch(*rom, "v2"));
213
214 // Apply v3 patch
215 ASSERT_OK(ApplyVersionPatch(*rom, "v3"));
216
217 // Validate v3 addresses
218 EXPECT_TRUE(ValidateVersionAddresses(*rom, "v3"));
219
220 // Save v3 ROM
221 ASSERT_OK(rom->SaveToFile(Rom::SaveSettings{.filename = v3_test_path_}));
222
223 // Reload and verify
224 std::unique_ptr<Rom> reloaded_rom = std::make_unique<Rom>();
225 ASSERT_OK(reloaded_rom->LoadFromFile(v3_test_path_));
226
227 EXPECT_TRUE(ValidateVersionAddresses(*reloaded_rom, "v3"));
228 auto version_byte = reloaded_rom->ReadByte(0x140145);
229 ASSERT_TRUE(version_byte.ok());
230 EXPECT_EQ(*version_byte, 0x03);
231}
232
233// Test direct vanilla to v3 upgrade
235 // Load vanilla ROM
236 std::unique_ptr<Rom> rom = std::make_unique<Rom>();
237 ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
238
239 // Apply v3 patch directly
240 ASSERT_OK(ApplyVersionPatch(*rom, "v3"));
241
242 // Validate v3 addresses
243 EXPECT_TRUE(ValidateVersionAddresses(*rom, "v3"));
244
245 // Save v3 ROM
246 ASSERT_OK(rom->SaveToFile(Rom::SaveSettings{.filename = v3_test_path_}));
247
248 // Reload and verify
249 std::unique_ptr<Rom> reloaded_rom = std::make_unique<Rom>();
250 ASSERT_OK(reloaded_rom->LoadFromFile(v3_test_path_));
251
252 EXPECT_TRUE(ValidateVersionAddresses(*reloaded_rom, "v3"));
253 auto version_byte = reloaded_rom->ReadByte(0x140145);
254 ASSERT_TRUE(version_byte.ok());
255 EXPECT_EQ(*version_byte, 0x03);
256}
257
258// Test address validation for each version
260 // Test vanilla addresses
261 std::unique_ptr<Rom> vanilla_rom = std::make_unique<Rom>();
262 ASSERT_OK(vanilla_rom->LoadFromFile(vanilla_test_path_));
263 EXPECT_TRUE(ValidateVersionAddresses(*vanilla_rom, "vanilla"));
264
265 // Test v2 addresses
266 ASSERT_OK(ApplyVersionPatch(*vanilla_rom, "v2"));
267 EXPECT_TRUE(ValidateVersionAddresses(*vanilla_rom, "v2"));
268
269 // Test v3 addresses
270 ASSERT_OK(ApplyVersionPatch(*vanilla_rom, "v3"));
271 EXPECT_TRUE(ValidateVersionAddresses(*vanilla_rom, "v3"));
272}
273
274// Test feature enablement/disablement
276 std::unique_ptr<Rom> rom = std::make_unique<Rom>();
277 ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
278 ASSERT_OK(ApplyVersionPatch(*rom, "v3"));
279
280 // Test feature flags
281 auto main_palettes = rom->ReadByte(0x140146);
282 auto area_bg = rom->ReadByte(0x140147);
283 auto subscreen_overlay = rom->ReadByte(0x140148);
284 auto animated_gfx = rom->ReadByte(0x140149);
285 auto custom_tiles = rom->ReadByte(0x14014A);
286 auto mosaic = rom->ReadByte(0x14014B);
287
288 ASSERT_TRUE(main_palettes.ok());
289 ASSERT_TRUE(area_bg.ok());
290 ASSERT_TRUE(subscreen_overlay.ok());
291 ASSERT_TRUE(animated_gfx.ok());
292 ASSERT_TRUE(custom_tiles.ok());
293 ASSERT_TRUE(mosaic.ok());
294
295 EXPECT_EQ(*main_palettes, 0x01); // Main palettes enabled
296 EXPECT_EQ(*area_bg, 0x01); // Area-specific BG enabled
297 EXPECT_EQ(*subscreen_overlay, 0x01); // Subscreen overlay enabled
298 EXPECT_EQ(*animated_gfx, 0x01); // Animated GFX enabled
299 EXPECT_EQ(*custom_tiles, 0x01); // Custom tile GFX groups enabled
300 EXPECT_EQ(*mosaic, 0x01); // Mosaic enabled
301
302 // Disable some features
303 ASSERT_OK(rom->WriteByte(0x140147, 0x00)); // Disable area-specific BG
304 ASSERT_OK(rom->WriteByte(0x140149, 0x00)); // Disable animated GFX
305
306 // Verify features are disabled
307 auto disabled_area_bg = rom->ReadByte(0x140147);
308 auto disabled_animated_gfx = rom->ReadByte(0x140149);
309 ASSERT_TRUE(disabled_area_bg.ok());
310 ASSERT_TRUE(disabled_animated_gfx.ok());
311
312 EXPECT_EQ(*disabled_area_bg, 0x00);
313 EXPECT_EQ(*disabled_animated_gfx, 0x00);
314
315 // Re-enable features
316 ASSERT_OK(rom->WriteByte(0x140147, 0x01));
317 ASSERT_OK(rom->WriteByte(0x140149, 0x01));
318
319 // Verify features are re-enabled
320 auto reenabled_area_bg = rom->ReadByte(0x140147);
321 auto reenabled_animated_gfx = rom->ReadByte(0x140149);
322 ASSERT_TRUE(reenabled_area_bg.ok());
323 ASSERT_TRUE(reenabled_animated_gfx.ok());
324
325 EXPECT_EQ(*reenabled_area_bg, 0x01);
326 EXPECT_EQ(*reenabled_animated_gfx, 0x01);
327}
328
329// Test data integrity during upgrades
331 std::unique_ptr<Rom> rom = std::make_unique<Rom>();
332 ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
333
334 // Store some original data
335 auto original_graphics = rom->ReadByte(0x7C9C);
336 auto original_palette = rom->ReadByte(0x7D1C);
337 auto original_sprite_set = rom->ReadByte(0x7A41);
338
339 ASSERT_TRUE(original_graphics.ok());
340 ASSERT_TRUE(original_palette.ok());
341 ASSERT_TRUE(original_sprite_set.ok());
342
343 // Upgrade to v3
344 ASSERT_OK(ApplyVersionPatch(*rom, "v3"));
345
346 // Verify original data is preserved
347 auto preserved_graphics = rom->ReadByte(0x7C9C);
348 auto preserved_palette = rom->ReadByte(0x7D1C);
349 auto preserved_sprite_set = rom->ReadByte(0x7A41);
350
351 ASSERT_TRUE(preserved_graphics.ok());
352 ASSERT_TRUE(preserved_palette.ok());
353 ASSERT_TRUE(preserved_sprite_set.ok());
354
355 EXPECT_EQ(*preserved_graphics, *original_graphics);
356 EXPECT_EQ(*preserved_palette, *original_palette);
357 EXPECT_EQ(*preserved_sprite_set, *original_sprite_set);
358
359 // Verify new v3 data is initialized
360 auto bg_colors = rom->ReadByte(0x140000);
361 auto subscreen_overlays = rom->ReadByte(0x140340);
362 auto animated_gfx = rom->ReadByte(0x1402A0);
363 auto custom_tiles = rom->ReadByte(0x140480);
364
365 ASSERT_TRUE(bg_colors.ok());
366 ASSERT_TRUE(subscreen_overlays.ok());
367 ASSERT_TRUE(animated_gfx.ok());
368 ASSERT_TRUE(custom_tiles.ok());
369
370 EXPECT_EQ(*bg_colors, 0x00); // BG colors
371 EXPECT_EQ(*subscreen_overlays, 0x00); // Subscreen overlays
372 EXPECT_EQ(*animated_gfx, 0x00); // Animated GFX
373 EXPECT_EQ(*custom_tiles, 0x00); // Custom tiles
374}
375
376} // namespace test
377} // namespace yaze
The Rom class is used to load, save, and modify Rom data.
Definition rom.h:71
absl::Status WriteByte(int addr, uint8_t value)
Definition rom.cc:725
absl::StatusOr< uint8_t > ReadByte(int offset)
Definition rom.cc:658
ZSCustomOverworld upgrade testing suite.
absl::Status ApplyVersionPatch(Rom &rom, const std::string &version)
std::map< std::string, std::pair< uint32_t, uint8_t > > v2_data_
bool ValidateVersionAddresses(Rom &rom, const std::string &version)
std::map< std::string, std::pair< uint32_t, uint8_t > > vanilla_data_
std::map< std::string, std::pair< uint32_t, uint8_t > > v3_data_
#define RETURN_IF_ERROR(expression)
Definition macro.h:53
TEST_F(DungeonObjectRenderingE2ETests, RunAllTests)
Main namespace for the application.
#define ASSERT_OK(expr)
Definition testing.h:12