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