yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
yaze.cc
Go to the documentation of this file.
1// C API implementation - no heavy GUI/editor dependencies
2#include <algorithm>
3#include <cstdint>
4#include <cstring>
5#include <limits>
6#include <memory>
7#include <string>
8#include <vector>
9
11#include "rom/rom.h"
12#include "yaze.h"
13#include "yaze_config.h"
14#include "yaze_core.h"
15#include "yaze_errors.h"
16#include "zelda.h"
17#include "zelda3/game_data.h"
19
20extern "C" {
21
22// Static variables for library state
23static bool g_library_initialized = false;
24
25// Version and initialization functions
27 if (g_library_initialized) {
28 return YAZE_OK;
29 }
30
31 // Initialize SDL and other subsystems if needed
32 g_library_initialized = true;
33 return YAZE_OK;
34}
35
37 if (!g_library_initialized) {
38 return;
39 }
40
41 // Cleanup subsystems
42 g_library_initialized = false;
43}
44
46 switch (status) {
47 case YAZE_OK:
48 return "Success";
50 return "Unknown error";
52 return "Invalid argument";
54 return "File not found";
56 return "Memory allocation failed";
57 case YAZE_ERROR_IO:
58 return "I/O operation failed";
60 return "Data corruption detected";
62 return "Component not initialized";
63 default:
64 return "Unknown status code";
65 }
66}
67
70}
71
75
76bool yaze_check_version_compatibility(const char* expected_version) {
77 if (expected_version == nullptr) {
78 return false;
79 }
80 return strcmp(expected_version, YAZE_VERSION_STRING) == 0;
81}
82
83yaze_status yaze_init(yaze_editor_context* context, const char* rom_filename) {
84 if (context == nullptr) {
86 }
87
88 if (!g_library_initialized) {
89 yaze_status init_status = yaze_library_init();
90 if (init_status != YAZE_OK) {
91 return init_status;
92 }
93 }
94
95 context->rom = nullptr;
96 context->error_message = nullptr;
97
98 if (rom_filename != nullptr && strlen(rom_filename) > 0) {
99 context->rom = yaze_load_rom(rom_filename);
100 if (context->rom == nullptr) {
101 context->error_message = "Failed to load ROM file";
103 }
104 }
105
106 return YAZE_OK;
107}
108
110 if (context == nullptr) {
112 }
113
114 if (context->rom != nullptr) {
115 yaze_unload_rom(context->rom);
116 context->rom = nullptr;
117 }
118
119 context->error_message = nullptr;
120 return YAZE_OK;
121}
122
123zelda3_rom* yaze_load_rom(const char* filename) {
124 if (filename == nullptr || strlen(filename) == 0) {
125 return nullptr;
126 }
127
128 auto internal_rom = std::make_unique<yaze::Rom>();
129 if (!internal_rom->LoadFromFile(filename).ok()) {
130 return nullptr;
131 }
132
133 // Create and load GameData
134 auto internal_game_data = std::make_unique<yaze::zelda3::GameData>();
135 auto load_status =
136 yaze::zelda3::LoadGameData(*internal_rom, *internal_game_data);
137 if (!load_status.ok()) {
138 return nullptr;
139 }
140
141 auto* rom = new zelda3_rom();
142 rom->filename = filename;
143 rom->impl = internal_rom.release(); // Transfer ownership
144 rom->game_data = internal_game_data.release(); // Transfer ownership
145 rom->data = const_cast<uint8_t*>(static_cast<yaze::Rom*>(rom->impl)->data());
146 rom->size = static_cast<yaze::Rom*>(rom->impl)->size();
147 rom->version = ZELDA3_VERSION_US; // Default, should be detected
148 rom->is_modified = false;
149 return rom;
150}
151
153 if (rom == nullptr) {
154 return;
155 }
156
157 if (rom->impl != nullptr) {
158 delete static_cast<yaze::Rom*>(rom->impl);
159 rom->impl = nullptr;
160 }
161
162 if (rom->game_data != nullptr) {
163 delete static_cast<yaze::zelda3::GameData*>(rom->game_data);
164 rom->game_data = nullptr;
165 }
166
167 delete rom;
168}
169
170int yaze_save_rom(zelda3_rom* rom, const char* filename) {
171 if (rom == nullptr || filename == nullptr) {
173 }
174
175 if (rom->impl == nullptr) {
177 }
178
179 auto* internal_rom = static_cast<yaze::Rom*>(rom->impl);
180 auto status = internal_rom->SaveToFile(yaze::Rom::SaveSettings{
181 .backup = true, .save_new = false, .filename = filename});
182
183 if (!status.ok()) {
184 return YAZE_ERROR_IO;
185 }
186
187 rom->is_modified = false;
188 return YAZE_OK;
189}
190
191yaze_bitmap yaze_load_bitmap(const char* filename) {
192 yaze_bitmap bitmap;
193 bitmap.width = 0;
194 bitmap.height = 0;
195 bitmap.bpp = 0;
196 bitmap.data = nullptr;
197 return bitmap;
198}
199
201 int palette_set, int palette,
202 int color) {
203 snes_color color_struct;
204 color_struct.red = 0;
205 color_struct.green = 0;
206 color_struct.blue = 0;
207
208 if (rom->game_data) {
209 auto* game_data = static_cast<yaze::zelda3::GameData*>(rom->game_data);
210 auto get_color =
211 game_data->palette_groups
213 ->palette(palette)[color];
214 color_struct = get_color.rom_color();
215
216 return color_struct;
217 }
218
219 return color_struct;
220}
221
223 if (rom->impl == nullptr) {
224 return nullptr;
225 }
226
227 yaze::Rom* internal_rom = static_cast<yaze::Rom*>(rom->impl);
228 auto* game_data = static_cast<yaze::zelda3::GameData*>(rom->game_data);
229 auto internal_overworld =
230 new yaze::zelda3::Overworld(internal_rom, game_data);
231 if (!internal_overworld->Load(internal_rom).ok()) {
232 return nullptr;
233 }
234
235 zelda3_overworld* overworld = new zelda3_overworld();
236 overworld->impl = internal_overworld;
237 int map_id = 0;
238 for (const auto& ow_map : internal_overworld->overworld_maps()) {
239 overworld->maps[map_id] = new zelda3_overworld_map();
240 overworld->maps[map_id]->id = map_id;
241 map_id++;
242 }
243 return overworld;
244}
245
247 int* room_count) {
248 if (room_count != nullptr) {
249 *room_count = 0;
250 }
251 if (rom == nullptr || rom->impl == nullptr) {
252 return nullptr;
253 }
254
255 constexpr int kRoomCount = 256;
256 auto* rooms = new zelda3_dungeon_room[kRoomCount]();
257 for (int i = 0; i < kRoomCount; ++i) {
258 rooms[i].id = static_cast<uint16_t>(i);
259 }
260 if (room_count != nullptr) {
261 *room_count = kRoomCount;
262 }
263 return rooms;
264}
265
267 int* message_count) {
268 if (rom == nullptr || messages == nullptr || message_count == nullptr) {
270 }
271
272 if (rom->impl == nullptr) {
274 }
275 if (rom->data == nullptr ||
276 rom->size <= static_cast<uint64_t>(yaze::editor::kTextData)) {
278 }
279
280 try {
281 const int scan_end = static_cast<int>(std::min<uint64_t>(
282 rom->size, static_cast<uint64_t>(std::numeric_limits<int>::max())));
283 std::vector<yaze::editor::MessageData> message_data =
285 scan_end);
286
287 *message_count = static_cast<int>(message_data.size());
288 *messages = new zelda3_message[*message_count];
289
290 for (size_t i = 0; i < message_data.size(); ++i) {
291 const auto& msg = message_data[i];
292 (*messages)[i].id = msg.ID;
293 (*messages)[i].rom_address = msg.Address;
294 (*messages)[i].length = static_cast<uint16_t>(msg.RawString.length());
295
296 // Allocate and copy string data
297 (*messages)[i].raw_data = new uint8_t[msg.Data.size()];
298 std::memcpy((*messages)[i].raw_data, msg.Data.data(), msg.Data.size());
299
300 (*messages)[i].parsed_text = new char[msg.ContentsParsed.length() + 1];
301 // Safe string copy with bounds checking
302 std::memcpy((*messages)[i].parsed_text, msg.ContentsParsed.c_str(),
303 msg.ContentsParsed.length());
304 (*messages)[i].parsed_text[msg.ContentsParsed.length()] = '\0';
305
306 (*messages)[i].is_compressed = msg.Data.size() != msg.DataParsed.size();
307 (*messages)[i].encoding_type = 1; // ALttP standard encoding
308 }
309 } catch (const std::exception& e) {
310 return YAZE_ERROR_MEMORY;
311 }
312
313 return YAZE_OK;
314}
315
316// Additional API functions implementation
317
318// Graphics functions
320 if (bitmap != nullptr && bitmap->data != nullptr) {
321 delete[] bitmap->data;
322 bitmap->data = nullptr;
323 bitmap->width = 0;
324 bitmap->height = 0;
325 bitmap->bpp = 0;
326 }
327}
328
329yaze_bitmap yaze_create_bitmap(int width, int height, uint8_t bpp) {
330 yaze_bitmap bitmap = {};
331
332 if (width <= 0 || height <= 0 ||
333 (bpp != 1 && bpp != 2 && bpp != 4 && bpp != 8)) {
334 return bitmap; // Return empty bitmap on invalid args
335 }
336
337 bitmap.width = width;
338 bitmap.height = height;
339 bitmap.bpp = bpp;
340 bitmap.data = new uint8_t[width * height]();
341
342 return bitmap;
343}
344
345snes_color yaze_rgb_to_snes_color(uint8_t r, uint8_t g, uint8_t b) {
346 snes_color color = {};
347 color.red = r; // Store full 8-bit values (existing code expects this)
348 color.green = g;
349 color.blue = b;
350 return color;
351}
352
353void yaze_snes_color_to_rgb(snes_color color, uint8_t* r, uint8_t* g,
354 uint8_t* b) {
355 if (r != nullptr)
356 *r = static_cast<uint8_t>(color.red);
357 if (g != nullptr)
358 *g = static_cast<uint8_t>(color.green);
359 if (b != nullptr)
360 *b = static_cast<uint8_t>(color.blue);
361}
362
363// zelda3_detect_version and zelda3_version_to_string live in
364// zelda3/zelda3_version.cc.
365
367 zelda3_version version) {
368 switch (version) {
370 return &zelda3_us_pointers;
372 return &zelda3_jp_pointers;
373 default:
374 return &zelda3_us_pointers; // Default fallback
375 }
376}
377} // extern "C"
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
auto filename() const
Definition rom.h:219
absl::Status SaveToFile(const SaveSettings &settings)
Definition rom.cc:893
auto data() const
Definition rom.h:213
auto size() const
Definition rom.h:212
struct zelda3_overworld_map zelda3_overworld_map
Overworld map data.
struct zelda3_overworld zelda3_overworld
Complete overworld data.
void yaze_unload_rom(zelda3_rom *rom)
Unload and free ROM data.
Definition yaze.cc:152
zelda3_rom * yaze_load_rom(const char *filename)
Load a ROM file.
Definition yaze.cc:123
int yaze_save_rom(zelda3_rom *rom, const char *filename)
Save ROM to file.
Definition yaze.cc:170
struct zelda3_rom zelda3_rom
ROM data structure.
zelda3_version
Different versions of the game supported by YAZE.
Definition zelda.h:33
const zelda3_version_pointers * zelda3_get_version_pointers(zelda3_version version)
Get version-specific pointers.
Definition yaze.cc:366
@ ZELDA3_VERSION_JP
Definition zelda.h:36
@ ZELDA3_VERSION_US
Definition zelda.h:35
#define YAZE_VERSION_NUMBER
#define YAZE_VERSION_STRING
constexpr int kTextData
std::vector< MessageData > ReadAllTextData(uint8_t *rom, int pos, int max_pos, bool allow_bank_switch)
constexpr const char * kPaletteGroupAddressesKeys[]
absl::Status LoadGameData(Rom &rom, GameData &data, const LoadOptions &options)
Loads all Zelda3-specific game data from a generic ROM.
Definition game_data.cc:123
SNES color in 15-bit RGB format (BGR555)
uint16_t green
uint16_t red
uint16_t blue
PaletteGroup * get_group(const std::string &group_name)
auto palette(int i) const
gfx::PaletteGroupMap palette_groups
Definition game_data.h:95
Bitmap data structure.
uint8_t * data
zelda3_rom * rom
Definition yaze_core.h:19
const char * error_message
Definition yaze_core.h:20
Complete dungeon room data.
Definition zelda.h:461
In-game text message data.
Definition zelda.h:272
uint16_t id
Definition zelda.h:273
Complete overworld data.
Definition zelda.h:333
void * impl
Definition zelda.h:334
zelda3_overworld_map ** maps
Definition zelda.h:335
ROM data structure.
Definition zelda.h:210
ROM data pointers for different game versions.
Definition zelda.h:71
snes_color yaze_rgb_to_snes_color(uint8_t r, uint8_t g, uint8_t b)
Convert RGB888 color to SNES color.
Definition yaze.cc:345
zelda3_overworld * yaze_load_overworld(const zelda3_rom *rom)
Load the overworld from ROM.
Definition yaze.cc:222
yaze_bitmap yaze_load_bitmap(const char *filename)
Load a bitmap from file.
Definition yaze.cc:191
void yaze_library_shutdown()
Shutdown the YAZE library.
Definition yaze.cc:36
yaze_bitmap yaze_create_bitmap(int width, int height, uint8_t bpp)
Create an empty bitmap.
Definition yaze.cc:329
bool yaze_check_version_compatibility(const char *expected_version)
Check if the current YAZE version is compatible with the expected version.
Definition yaze.cc:76
yaze_status yaze_shutdown(yaze_editor_context *context)
Shutdown and clean up a YAZE editor context.
Definition yaze.cc:109
zelda3_dungeon_room * yaze_load_all_rooms(const zelda3_rom *rom, int *room_count)
Load all dungeon rooms from ROM.
Definition yaze.cc:246
yaze_status yaze_init(yaze_editor_context *context, const char *rom_filename)
Initialize a YAZE editor context.
Definition yaze.cc:83
int yaze_get_version_number()
Get the current YAZE version number.
Definition yaze.cc:72
snes_color yaze_get_color_from_paletteset(const zelda3_rom *rom, int palette_set, int palette, int color)
Get a color from a palette set.
Definition yaze.cc:200
const char * yaze_get_version_string()
Get the current YAZE version string.
Definition yaze.cc:68
void yaze_free_bitmap(yaze_bitmap *bitmap)
Free bitmap data.
Definition yaze.cc:319
yaze_status yaze_load_messages(const zelda3_rom *rom, zelda3_message **messages, int *message_count)
Load all text messages from ROM.
Definition yaze.cc:266
void yaze_snes_color_to_rgb(snes_color color, uint8_t *r, uint8_t *g, uint8_t *b)
Convert SNES color to RGB888.
Definition yaze.cc:353
yaze_status yaze_library_init()
Initialize the YAZE library.
Definition yaze.cc:26
const char * yaze_status_to_string(yaze_status status)
Convert a status code to a human-readable string.
Definition yaze.cc:45
Public YAZE API umbrella header.
Core initialization and editor context for the YAZE public API.
Status codes and error helpers for the YAZE public API.
yaze_status
Status codes returned by YAZE functions.
Definition yaze_errors.h:19
@ YAZE_OK
Definition yaze_errors.h:20
@ YAZE_ERROR_CORRUPTION
Definition yaze_errors.h:26
@ YAZE_ERROR_IO
Definition yaze_errors.h:25
@ YAZE_ERROR_FILE_NOT_FOUND
Definition yaze_errors.h:23
@ YAZE_ERROR_INVALID_ARG
Definition yaze_errors.h:22
@ YAZE_ERROR_MEMORY
Definition yaze_errors.h:24
@ YAZE_ERROR_NOT_INITIALIZED
Definition yaze_errors.h:27
@ YAZE_ERROR_UNKNOWN
Definition yaze_errors.h:21
The Legend of Zelda: A Link to the Past - Data Structures and Constants.