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 <cstdint>
3#include <cstring>
4#include <memory>
5#include <string>
6#include <vector>
7
9#include "rom/rom.h"
10#include "yaze.h"
11#include "yaze_config.h"
12#include "yaze_core.h"
13#include "yaze_errors.h"
14#include "zelda.h"
15#include "zelda3/game_data.h"
17
18extern "C" {
19
20// Static variables for library state
21static bool g_library_initialized = false;
22
23// Version and initialization functions
25 if (g_library_initialized) {
26 return YAZE_OK;
27 }
28
29 // Initialize SDL and other subsystems if needed
30 g_library_initialized = true;
31 return YAZE_OK;
32}
33
35 if (!g_library_initialized) {
36 return;
37 }
38
39 // Cleanup subsystems
40 g_library_initialized = false;
41}
42
44 switch (status) {
45 case YAZE_OK:
46 return "Success";
48 return "Unknown error";
50 return "Invalid argument";
52 return "File not found";
54 return "Memory allocation failed";
55 case YAZE_ERROR_IO:
56 return "I/O operation failed";
58 return "Data corruption detected";
60 return "Component not initialized";
61 default:
62 return "Unknown status code";
63 }
64}
65
68}
69
73
74bool yaze_check_version_compatibility(const char* expected_version) {
75 if (expected_version == nullptr) {
76 return false;
77 }
78 return strcmp(expected_version, YAZE_VERSION_STRING) == 0;
79}
80
81yaze_status yaze_init(yaze_editor_context* context, const char* rom_filename) {
82 if (context == nullptr) {
84 }
85
86 if (!g_library_initialized) {
87 yaze_status init_status = yaze_library_init();
88 if (init_status != YAZE_OK) {
89 return init_status;
90 }
91 }
92
93 context->rom = nullptr;
94 context->error_message = nullptr;
95
96 if (rom_filename != nullptr && strlen(rom_filename) > 0) {
97 context->rom = yaze_load_rom(rom_filename);
98 if (context->rom == nullptr) {
99 context->error_message = "Failed to load ROM file";
101 }
102 }
103
104 return YAZE_OK;
105}
106
108 if (context == nullptr) {
110 }
111
112 if (context->rom != nullptr) {
113 yaze_unload_rom(context->rom);
114 context->rom = nullptr;
115 }
116
117 context->error_message = nullptr;
118 return YAZE_OK;
119}
120
121zelda3_rom* yaze_load_rom(const char* filename) {
122 if (filename == nullptr || strlen(filename) == 0) {
123 return nullptr;
124 }
125
126 auto internal_rom = std::make_unique<yaze::Rom>();
127 if (!internal_rom->LoadFromFile(filename).ok()) {
128 return nullptr;
129 }
130
131 // Create and load GameData
132 auto internal_game_data = std::make_unique<yaze::zelda3::GameData>();
133 auto load_status =
134 yaze::zelda3::LoadGameData(*internal_rom, *internal_game_data);
135 if (!load_status.ok()) {
136 return nullptr;
137 }
138
139 auto* rom = new zelda3_rom();
140 rom->filename = filename;
141 rom->impl = internal_rom.release(); // Transfer ownership
142 rom->game_data = internal_game_data.release(); // Transfer ownership
143 rom->data = const_cast<uint8_t*>(static_cast<yaze::Rom*>(rom->impl)->data());
144 rom->size = static_cast<yaze::Rom*>(rom->impl)->size();
145 rom->version = ZELDA3_VERSION_US; // Default, should be detected
146 rom->is_modified = false;
147 return rom;
148}
149
151 if (rom == nullptr) {
152 return;
153 }
154
155 if (rom->impl != nullptr) {
156 delete static_cast<yaze::Rom*>(rom->impl);
157 rom->impl = nullptr;
158 }
159
160 if (rom->game_data != nullptr) {
161 delete static_cast<yaze::zelda3::GameData*>(rom->game_data);
162 rom->game_data = nullptr;
163 }
164
165 delete rom;
166}
167
168int yaze_save_rom(zelda3_rom* rom, const char* filename) {
169 if (rom == nullptr || filename == nullptr) {
171 }
172
173 if (rom->impl == nullptr) {
175 }
176
177 auto* internal_rom = static_cast<yaze::Rom*>(rom->impl);
178 auto status = internal_rom->SaveToFile(yaze::Rom::SaveSettings{
179 .backup = true, .save_new = false, .filename = filename});
180
181 if (!status.ok()) {
182 return YAZE_ERROR_IO;
183 }
184
185 rom->is_modified = false;
186 return YAZE_OK;
187}
188
189yaze_bitmap yaze_load_bitmap(const char* filename) {
190 yaze_bitmap bitmap;
191 bitmap.width = 0;
192 bitmap.height = 0;
193 bitmap.bpp = 0;
194 bitmap.data = nullptr;
195 return bitmap;
196}
197
199 int palette_set, int palette,
200 int color) {
201 snes_color color_struct;
202 color_struct.red = 0;
203 color_struct.green = 0;
204 color_struct.blue = 0;
205
206 if (rom->game_data) {
207 auto* game_data = static_cast<yaze::zelda3::GameData*>(rom->game_data);
208 auto get_color =
209 game_data->palette_groups
211 ->palette(palette)[color];
212 color_struct = get_color.rom_color();
213
214 return color_struct;
215 }
216
217 return color_struct;
218}
219
221 if (rom->impl == nullptr) {
222 return nullptr;
223 }
224
225 yaze::Rom* internal_rom = static_cast<yaze::Rom*>(rom->impl);
226 auto* game_data = static_cast<yaze::zelda3::GameData*>(rom->game_data);
227 auto internal_overworld =
228 new yaze::zelda3::Overworld(internal_rom, game_data);
229 if (!internal_overworld->Load(internal_rom).ok()) {
230 return nullptr;
231 }
232
233 zelda3_overworld* overworld = new zelda3_overworld();
234 overworld->impl = internal_overworld;
235 int map_id = 0;
236 for (const auto& ow_map : internal_overworld->overworld_maps()) {
237 overworld->maps[map_id] = new zelda3_overworld_map();
238 overworld->maps[map_id]->id = map_id;
239 map_id++;
240 }
241 return overworld;
242}
243
245 int* room_count) {
246 if (room_count != nullptr) {
247 *room_count = 0;
248 }
249 if (rom == nullptr || rom->impl == nullptr) {
250 return nullptr;
251 }
252
253 constexpr int kRoomCount = 256;
254 auto* rooms = new zelda3_dungeon_room[kRoomCount]();
255 for (int i = 0; i < kRoomCount; ++i) {
256 rooms[i].id = static_cast<uint16_t>(i);
257 }
258 if (room_count != nullptr) {
259 *room_count = kRoomCount;
260 }
261 return rooms;
262}
263
265 int* message_count) {
266 if (rom == nullptr || messages == nullptr || message_count == nullptr) {
268 }
269
270 if (rom->impl == nullptr) {
272 }
273
274 try {
275 // Use LoadAllTextData from message_data.h
276 std::vector<yaze::editor::MessageData> message_data =
278
279 *message_count = static_cast<int>(message_data.size());
280 *messages = new zelda3_message[*message_count];
281
282 for (size_t i = 0; i < message_data.size(); ++i) {
283 const auto& msg = message_data[i];
284 (*messages)[i].id = msg.ID;
285 (*messages)[i].rom_address = msg.Address;
286 (*messages)[i].length = static_cast<uint16_t>(msg.RawString.length());
287
288 // Allocate and copy string data
289 (*messages)[i].raw_data = new uint8_t[msg.Data.size()];
290 std::memcpy((*messages)[i].raw_data, msg.Data.data(), msg.Data.size());
291
292 (*messages)[i].parsed_text = new char[msg.ContentsParsed.length() + 1];
293 // Safe string copy with bounds checking
294 std::memcpy((*messages)[i].parsed_text, msg.ContentsParsed.c_str(),
295 msg.ContentsParsed.length());
296 (*messages)[i].parsed_text[msg.ContentsParsed.length()] = '\0';
297
298 (*messages)[i].is_compressed = msg.Data.size() != msg.DataParsed.size();
299 (*messages)[i].encoding_type = 1; // ALttP standard encoding
300 }
301 } catch (const std::exception& e) {
302 return YAZE_ERROR_MEMORY;
303 }
304
305 return YAZE_OK;
306}
307
308// Additional API functions implementation
309
310// Graphics functions
312 if (bitmap != nullptr && bitmap->data != nullptr) {
313 delete[] bitmap->data;
314 bitmap->data = nullptr;
315 bitmap->width = 0;
316 bitmap->height = 0;
317 bitmap->bpp = 0;
318 }
319}
320
321yaze_bitmap yaze_create_bitmap(int width, int height, uint8_t bpp) {
322 yaze_bitmap bitmap = {};
323
324 if (width <= 0 || height <= 0 ||
325 (bpp != 1 && bpp != 2 && bpp != 4 && bpp != 8)) {
326 return bitmap; // Return empty bitmap on invalid args
327 }
328
329 bitmap.width = width;
330 bitmap.height = height;
331 bitmap.bpp = bpp;
332 bitmap.data = new uint8_t[width * height]();
333
334 return bitmap;
335}
336
337snes_color yaze_rgb_to_snes_color(uint8_t r, uint8_t g, uint8_t b) {
338 snes_color color = {};
339 color.red = r; // Store full 8-bit values (existing code expects this)
340 color.green = g;
341 color.blue = b;
342 return color;
343}
344
345void yaze_snes_color_to_rgb(snes_color color, uint8_t* r, uint8_t* g,
346 uint8_t* b) {
347 if (r != nullptr)
348 *r = static_cast<uint8_t>(color.red);
349 if (g != nullptr)
350 *g = static_cast<uint8_t>(color.green);
351 if (b != nullptr)
352 *b = static_cast<uint8_t>(color.blue);
353}
354
355// Version detection functions
356zelda3_version zelda3_detect_version(const uint8_t* rom_data, size_t size) {
357 if (rom_data == nullptr || size < 0x8000) {
359 }
360
361 // SNES LoROM header titles at 0x7FC0 (PC offset)
362 // Titles are 21 bytes long
363 std::string title;
364 for (int i = 0; i < 21; ++i) {
365 char c = static_cast<char>(rom_data[0x7FC0 + i]);
366 if (c >= 0x20 && c < 0x7F) {
367 title += c;
368 }
369 }
370
371 if (absl::StrContains(title, "THE LEGEND OF ZELDA")) {
372 // US or EU version often share this title
373 // Check destination code at 0x7FD9: 0x01 = USA, 0x02+ = PAL regions
374 uint8_t region = rom_data[0x7FD9];
375 if (region == 0x00)
376 return ZELDA3_VERSION_JP;
377 if (region == 0x01)
378 return ZELDA3_VERSION_US;
379 return ZELDA3_VERSION_EU;
380 }
381
382 if (absl::StrContains(title, "ZELDA NO DENSETSU")) {
383 return ZELDA3_VERSION_JP;
384 }
385
386 // Fallback: Check for common randomizer indicators
387 if (absl::StrContains(title, "VT RANDO") ||
388 absl::StrContains(title, "Z3 RANDOMIZER")) {
390 }
391
392 return ZELDA3_VERSION_US; // Default assumption for ALttP clones/hacks
393}
394
396 switch (version) {
398 return "US/North American";
400 return "Japanese";
402 return "European";
404 return "Prototype";
406 return "Randomizer";
407 default:
408 return "Unknown";
409 }
410}
411
413 zelda3_version version) {
414 switch (version) {
416 return &zelda3_us_pointers;
418 return &zelda3_jp_pointers;
419 default:
420 return &zelda3_us_pointers; // Default fallback
421 }
422}
423} // 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:28
auto filename() const
Definition rom.h:157
absl::Status SaveToFile(const SaveSettings &settings)
Definition rom.cc:371
auto data() const
Definition rom.h:151
auto size() const
Definition rom.h:150
Represents the full Overworld data, light and dark world.
Definition overworld.h:389
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:150
zelda3_rom * yaze_load_rom(const char *filename)
Load a ROM file.
Definition yaze.cc:121
int yaze_save_rom(zelda3_rom *rom, const char *filename)
Save ROM to file.
Definition yaze.cc:168
const char * zelda3_version_to_string(zelda3_version version)
Get version name as string.
Definition yaze.cc:395
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:412
zelda3_version zelda3_detect_version(const uint8_t *rom_data, size_t size)
Detect ROM version from header data.
Definition yaze.cc:356
@ ZELDA3_VERSION_JP
Definition zelda.h:36
@ ZELDA3_VERSION_PROTO
Definition zelda.h:38
@ ZELDA3_VERSION_EU
Definition zelda.h:37
@ ZELDA3_VERSION_US
Definition zelda.h:35
@ ZELDA3_VERSION_RANDOMIZER
Definition zelda.h:39
@ ZELDA3_VERSION_UNKNOWN
Definition zelda.h:34
#define YAZE_VERSION_NUMBER
#define YAZE_VERSION_STRING
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:92
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:337
zelda3_overworld * yaze_load_overworld(const zelda3_rom *rom)
Load the overworld from ROM.
Definition yaze.cc:220
yaze_bitmap yaze_load_bitmap(const char *filename)
Load a bitmap from file.
Definition yaze.cc:189
void yaze_library_shutdown()
Shutdown the YAZE library.
Definition yaze.cc:34
yaze_bitmap yaze_create_bitmap(int width, int height, uint8_t bpp)
Create an empty bitmap.
Definition yaze.cc:321
bool yaze_check_version_compatibility(const char *expected_version)
Check if the current YAZE version is compatible with the expected version.
Definition yaze.cc:74
yaze_status yaze_shutdown(yaze_editor_context *context)
Shutdown and clean up a YAZE editor context.
Definition yaze.cc:107
zelda3_dungeon_room * yaze_load_all_rooms(const zelda3_rom *rom, int *room_count)
Load all dungeon rooms from ROM.
Definition yaze.cc:244
yaze_status yaze_init(yaze_editor_context *context, const char *rom_filename)
Initialize a YAZE editor context.
Definition yaze.cc:81
int yaze_get_version_number()
Get the current YAZE version number.
Definition yaze.cc:70
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:198
const char * yaze_get_version_string()
Get the current YAZE version string.
Definition yaze.cc:66
void yaze_free_bitmap(yaze_bitmap *bitmap)
Free bitmap data.
Definition yaze.cc:311
yaze_status yaze_load_messages(const zelda3_rom *rom, zelda3_message **messages, int *message_count)
Load all text messages from ROM.
Definition yaze.cc:264
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:345
yaze_status yaze_library_init()
Initialize the YAZE library.
Definition yaze.cc:24
const char * yaze_status_to_string(yaze_status status)
Convert a status code to a human-readable string.
Definition yaze.cc:43
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.