yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
overworld_upgrade_system.cc
Go to the documentation of this file.
2
3#include <filesystem>
4#include <string>
5#include <vector>
6
7#include "absl/strings/str_format.h"
8#include "core/asar_wrapper.h"
9#include "rom/rom.h"
10#include "util/file_util.h"
11#include "util/log.h"
12#include "zelda3/common.h"
14
15namespace yaze {
16namespace zelda3 {
17
19
21 int target_version) {
22 // Validate target version
23 if (target_version < 2 || target_version > 3) {
24 return absl::InvalidArgumentError(absl::StrFormat(
25 "Invalid target version: %d. Must be 2 or 3.", target_version));
26 }
27
28 // Check current ROM version
29 uint8_t current_version = rom_[OverworldCustomASMHasBeenApplied];
30 if (current_version != 0xFF && current_version >= target_version) {
31 return absl::AlreadyExistsError(absl::StrFormat(
32 "ROM is already version %d or higher", current_version));
33 }
34
35 LOG_DEBUG("OverworldUpgradeSystem",
36 "Applying ZSCustomOverworld ASM v%d to ROM...", target_version);
37
38 // Initialize Asar wrapper
39 auto asar_wrapper = std::make_unique<core::AsarWrapper>();
40 RETURN_IF_ERROR(asar_wrapper->Initialize());
41
42 // Create backup of ROM data
43 std::vector<uint8_t> original_rom_data = rom_.vector();
44 std::vector<uint8_t> working_rom_data = original_rom_data;
45
46 try {
47 // Determine which ASM file to apply
48 std::string asm_file_name =
49 (target_version == 3) ? "asm/yaze.asm" : "asm/ZSCustomOverworld.asm";
50
51 std::string asm_file_path = util::GetResourcePath(asm_file_name);
52
53 LOG_DEBUG("OverworldUpgradeSystem", "Using ASM file: %s",
54 asm_file_path.c_str());
55
56 if (!std::filesystem::exists(asm_file_path)) {
57 return absl::NotFoundError(
58 absl::StrFormat("ASM file not found at: %s\n\n"
59 "Expected location: assets/%s\n"
60 "Make sure the assets directory is accessible.",
61 asm_file_path, asm_file_name));
62 }
63
64 // Apply the ASM patch
65 auto patch_result =
66 asar_wrapper->ApplyPatch(asm_file_path, working_rom_data);
67 if (!patch_result.ok()) {
68 return absl::InternalError(absl::StrFormat(
69 "Failed to apply ASM patch: %s", patch_result.status().message()));
70 }
71
72 const auto& result = patch_result.value();
73 if (!result.success) {
74 std::string error_details = "ASM patch failed with errors:\n";
75 for (const auto& error : result.errors) {
76 error_details += " - " + error + "\n";
77 }
78 if (!result.warnings.empty()) {
79 error_details += "Warnings:\n";
80 for (const auto& warning : result.warnings) {
81 error_details += " - " + warning + "\n";
82 }
83 }
84 return absl::InternalError(error_details);
85 }
86
87 // Update ROM with patched data
88 RETURN_IF_ERROR(rom_.LoadFromData(working_rom_data));
89
90 // Update version marker and feature flags
92
93 // Log symbols found during patching
94 LOG_DEBUG("OverworldUpgradeSystem",
95 "ASM patch applied successfully. Found %zu symbols:",
96 result.symbols.size());
97 for (const auto& symbol : result.symbols) {
98 LOG_DEBUG("OverworldUpgradeSystem", " %s @ $%06X", symbol.name.c_str(),
99 symbol.address);
100 }
101
102 LOG_DEBUG("OverworldUpgradeSystem",
103 "ZSCustomOverworld v%d successfully applied to ROM",
104 target_version);
105 return absl::OkStatus();
106
107 } catch (const std::exception& e) {
108 // Restore original ROM data on any exception
109 auto restore_result = rom_.LoadFromData(original_rom_data);
110 if (!restore_result.ok()) {
111 LOG_ERROR("OverworldUpgradeSystem", "Failed to restore ROM data: %s",
112 restore_result.message().data());
113 }
114 return absl::InternalError(
115 absl::StrFormat("Exception during ASM application: %s", e.what()));
116 }
117}
118
120 int target_version) {
121 // Set the main version marker
122 rom_[OverworldCustomASMHasBeenApplied] = static_cast<uint8_t>(target_version);
123
124 // Enable feature flags based on target version
125 if (target_version >= 2) {
128 LOG_DEBUG("OverworldUpgradeSystem",
129 "Enabled v2+ features: Custom BG colors, Main palettes");
130 }
131
132 if (target_version >= 3) {
137
138 LOG_DEBUG("OverworldUpgradeSystem",
139 "Enabled v3+ features: Subscreen overlays, Animated GFX, Tile "
140 "GFX groups, Mosaic");
141
142 for (int i = 0; i < 0xA0; i++) {
144 static_cast<uint8_t>(AreaSizeEnum::SmallArea);
145 }
146
147 const std::vector<int> large_areas = {
148 0x00, 0x02, 0x05, 0x07, 0x0A, 0x0B, 0x0F, 0x10, 0x11, 0x12, 0x13,
149 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1D, 0x1E, 0x25,
150 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2E, 0x2F, 0x30, 0x32, 0x33, 0x34,
151 0x35, 0x37, 0x3A, 0x40, 0x42, 0x45, 0x47, 0x4A, 0x4B, 0x4F, 0x50,
152 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
153 0x5D, 0x5E, 0x65, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6E, 0x6F, 0x70,
154 0x72, 0x73, 0x74, 0x75, 0x77, 0x7A, 0x80, 0x81};
155 for (int area : large_areas) {
156 rom_[kOverworldScreenSize + area] =
157 static_cast<uint8_t>(AreaSizeEnum::LargeArea);
158 }
159 }
160
161 return absl::OkStatus();
162}
163
164} // namespace zelda3
165} // namespace yaze
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:28
const auto & vector() const
Definition rom.h:143
absl::Status LoadFromData(const std::vector< uint8_t > &data, const LoadOptions &options=LoadOptions::Defaults())
Definition rom.cc:255
absl::Status ApplyZSCustomOverworldASM(int target_version)
Apply ZSCustomOverworld ASM patch to upgrade ROM version.
OverworldUpgradeSystem(Rom &rom)
Constructs the upgrade system.
absl::Status UpdateROMVersionMarkers(int target_version)
Update ROM version markers and feature flags after ASM patching. This is an internal sub-step of the ...
#define LOG_DEBUG(category, format,...)
Definition log.h:103
#define LOG_ERROR(category, format,...)
Definition log.h:109
std::string GetResourcePath(const std::string &resource_path)
Definition file_util.cc:70
constexpr int OverworldCustomTileGFXGroupEnabled
constexpr int OverworldCustomAreaSpecificBGEnabled
constexpr int kOverworldScreenSize
Definition overworld.h:146
constexpr int OverworldCustomAnimatedGFXEnabled
constexpr int OverworldCustomMainPaletteEnabled
constexpr int OverworldCustomASMHasBeenApplied
Definition common.h:89
constexpr int OverworldCustomMosaicEnabled
constexpr int OverworldCustomSubscreenOverlayEnabled
#define RETURN_IF_ERROR(expr)
Definition snes.cc:22