Refactor CMake and enhance API documentation for YAZE

- Updated CMakeLists.txt to set a minimum required version of 3.5 and removed older policy settings for improved compatibility.
- Enhanced yaze.h and zelda.h with detailed documentation, including versioning information and API descriptions, to improve clarity for developers.
- Added new functions for version compatibility checks and improved error handling in the YAZE API.
- Refactored existing structures and enums for better readability and maintainability, ensuring a more consistent coding style.
This commit is contained in:
scawful
2025-09-25 12:00:03 -04:00
parent 4c6342cb73
commit 77ceb0256b
6 changed files with 1139 additions and 238 deletions

View File

@@ -1,14 +1,8 @@
# Yet Another Zelda3 Editor # Yet Another Zelda3 Editor
# by scawful # by scawful
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.5)
# Set policy for older submodules
if(POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif()
if(POLICY CMP0135)
cmake_policy(SET CMP0135 NEW)
endif()
project(yaze VERSION 0.3.0 project(yaze VERSION 0.3.0
DESCRIPTION "Yet Another Zelda3 Editor" DESCRIPTION "Yet Another Zelda3 Editor"
LANGUAGES CXX C) LANGUAGES CXX C)

View File

@@ -1,6 +1,18 @@
#ifndef YAZE_H #ifndef YAZE_H
#define YAZE_H #define YAZE_H
/**
* @file yaze.h
* @brief Yet Another Zelda3 Editor (YAZE) - Public C API
*
* This header provides the main C API for YAZE, a modern ROM editor for
* The Legend of Zelda: A Link to the Past. This API allows external
* applications to interact with YAZE's functionality.
*
* @version 0.3.0
* @author YAZE Team
*/
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -11,56 +23,290 @@ extern "C" {
#include "zelda.h" #include "zelda.h"
/**
* @defgroup version Version Information
* @{
*/
/** Major version number */
#define YAZE_VERSION_MAJOR 0
/** Minor version number */
#define YAZE_VERSION_MINOR 3
/** Patch version number */
#define YAZE_VERSION_PATCH 0
/** Combined version as a string */
#define YAZE_VERSION_STRING "0.3.0"
/** Combined version as a number (major * 10000 + minor * 100 + patch) */
#define YAZE_VERSION_NUMBER 300
/** @} */
typedef struct yaze_editor_context { typedef struct yaze_editor_context {
zelda3_rom* rom; zelda3_rom* rom;
const char* error_message; const char* error_message;
} yaze_editor_context; } yaze_editor_context;
/**
* @defgroup core Core API
* @{
*/
/**
* @brief Status codes returned by YAZE functions
*
* All YAZE functions that can fail return a status code to indicate
* success or the type of error that occurred.
*/
typedef enum yaze_status { typedef enum yaze_status {
YAZE_UNKNOWN = -1, YAZE_OK = 0, /**< Operation completed successfully */
YAZE_OK = 0, YAZE_ERROR_UNKNOWN = -1, /**< Unknown error occurred */
YAZE_ERROR = 1, YAZE_ERROR_INVALID_ARG = 1, /**< Invalid argument provided */
YAZE_ERROR_FILE_NOT_FOUND = 2, /**< File not found */
YAZE_ERROR_MEMORY = 3, /**< Memory allocation failed */
YAZE_ERROR_IO = 4, /**< I/O operation failed */
YAZE_ERROR_CORRUPTION = 5, /**< Data corruption detected */
YAZE_ERROR_NOT_INITIALIZED = 6, /**< Component not initialized */
} yaze_status; } yaze_status;
/**
* @brief Convert a status code to a human-readable string
*
* @param status The status code to convert
* @return A null-terminated string describing the status
*/
const char* yaze_status_to_string(yaze_status status);
/**
* @brief Initialize the YAZE library
*
* This function must be called before using any other YAZE functions.
* It initializes internal subsystems and prepares the library for use.
*
* @return YAZE_OK on success, error code on failure
*/
yaze_status yaze_library_init(void);
/**
* @brief Shutdown the YAZE library
*
* This function cleans up resources allocated by yaze_library_init().
* After calling this function, no other YAZE functions should be called
* until yaze_library_init() is called again.
*/
void yaze_library_shutdown(void);
/**
* @brief Main entry point for the YAZE application
*
* @param argc Number of command line arguments
* @param argv Array of command line argument strings
* @return Exit code (0 for success, non-zero for error)
*/
int yaze_app_main(int argc, char** argv); int yaze_app_main(int argc, char** argv);
void yaze_check_version(const char* version);
yaze_status yaze_init(yaze_editor_context*, char* rom_filename); /**
yaze_status yaze_shutdown(yaze_editor_context*); * @brief Check if the current YAZE version is compatible with the expected version
*
* @param expected_version Expected version string (e.g., "0.3.0")
* @return true if compatible, false otherwise
*/
bool yaze_check_version_compatibility(const char* expected_version);
/**
* @brief Get the current YAZE version string
*
* @return A null-terminated string containing the version
*/
const char* yaze_get_version_string(void);
/**
* @brief Get the current YAZE version number
*
* @return Version number (major * 10000 + minor * 100 + patch)
*/
int yaze_get_version_number(void);
/**
* @brief Initialize a YAZE editor context
*
* Creates and initializes an editor context for working with ROM files.
* The context manages the ROM data and provides access to editing functions.
*
* @param context Pointer to context structure to initialize
* @param rom_filename Path to the ROM file to load (can be NULL to create empty context)
* @return YAZE_OK on success, error code on failure
*
* @note The caller is responsible for calling yaze_shutdown() to clean up the context
*/
yaze_status yaze_init(yaze_editor_context* context, const char* rom_filename);
/**
* @brief Shutdown and clean up a YAZE editor context
*
* Releases all resources associated with the context, including ROM data.
* After calling this function, the context should not be used.
*
* @param context Pointer to context to shutdown
* @return YAZE_OK on success, error code on failure
*/
yaze_status yaze_shutdown(yaze_editor_context* context);
/** @} */
/**
* @defgroup graphics Graphics and Bitmap Functions
* @{
*/
/**
* @brief Bitmap data structure
*
* Represents a bitmap image with pixel data and metadata.
*/
typedef struct yaze_bitmap { typedef struct yaze_bitmap {
int width; int width; /**< Width in pixels */
int height; int height; /**< Height in pixels */
uint8_t bpp; uint8_t bpp; /**< Bits per pixel (1, 2, 4, 8) */
uint8_t* data; uint8_t* data; /**< Pixel data (caller owns memory) */
} yaze_bitmap; } yaze_bitmap;
/**
* @brief Load a bitmap from file
*
* Loads a bitmap image from the specified file. Supports common
* image formats and SNES-specific formats.
*
* @param filename Path to the image file
* @return Bitmap structure with loaded data, or empty bitmap on error
*
* @note The caller is responsible for freeing the data pointer
*/
yaze_bitmap yaze_load_bitmap(const char* filename); yaze_bitmap yaze_load_bitmap(const char* filename);
/** /**
* @brief Primitive of 16-bit RGB SNES color. * @brief Free bitmap data
*
* Releases memory allocated for bitmap pixel data.
*
* @param bitmap Pointer to bitmap structure to free
*/
void yaze_free_bitmap(yaze_bitmap* bitmap);
/**
* @brief Create an empty bitmap
*
* Allocates a new bitmap with the specified dimensions.
*
* @param width Width in pixels
* @param height Height in pixels
* @param bpp Bits per pixel
* @return Initialized bitmap structure, or empty bitmap on error
*/
yaze_bitmap yaze_create_bitmap(int width, int height, uint8_t bpp);
/**
* @brief SNES color in 15-bit RGB format (BGR555)
*
* Represents a color in the SNES native format. Colors are stored
* as 8-bit values but only the lower 5 bits are used by the SNES.
*/ */
typedef struct snes_color { typedef struct snes_color {
uint16_t red; /**< Red component of the color. */ uint16_t red; /**< Red component (0-255, but SNES uses 0-31) */
uint16_t blue; /**< Blue component of the color. */ uint16_t green; /**< Green component (0-255, but SNES uses 0-31) */
uint16_t green; /**< Green component of the color. */ uint16_t blue; /**< Blue component (0-255, but SNES uses 0-31) */
} snes_color; } snes_color;
/** /**
* @brief Primitive of a SNES color palette. * @brief Convert RGB888 color to SNES color
*
* @param r Red component (0-255)
* @param g Green component (0-255)
* @param b Blue component (0-255)
* @return SNES color structure
*/
snes_color yaze_rgb_to_snes_color(uint8_t r, uint8_t g, uint8_t b);
/**
* @brief Convert SNES color to RGB888
*
* @param color SNES color to convert
* @param r Pointer to store red component (0-255)
* @param g Pointer to store green component (0-255)
* @param b Pointer to store blue component (0-255)
*/
void yaze_snes_color_to_rgb(snes_color color, uint8_t* r, uint8_t* g, uint8_t* b);
/**
* @brief SNES color palette
*
* Represents a color palette used by the SNES. Each palette contains
* up to 256 colors, though most modes use fewer colors per palette.
*/ */
typedef struct snes_palette { typedef struct snes_palette {
unsigned int id; /**< ID of the palette. */ uint16_t id; /**< Palette ID (0-255) */
unsigned int size; /**< Size of the palette. */ uint16_t size; /**< Number of colors in palette (1-256) */
snes_color* colors; /**< Pointer to the colors in the palette. */ snes_color* colors; /**< Array of colors (caller owns memory) */
} snes_palette; } snes_palette;
/**
* @brief Create an empty palette
*
* @param id Palette ID
* @param size Number of colors to allocate
* @return Initialized palette structure, or NULL on error
*/
snes_palette* yaze_create_palette(uint16_t id, uint16_t size);
/**
* @brief Free palette memory
*
* @param palette Pointer to palette to free
*/
void yaze_free_palette(snes_palette* palette);
/**
* @brief Load palette from ROM
*
* @param rom ROM to load palette from
* @param palette_id ID of palette to load
* @return Loaded palette, or NULL on error
*/
snes_palette* yaze_load_palette_from_rom(const zelda3_rom* rom, uint16_t palette_id);
/**
* @brief 8x8 SNES tile data
*
* Represents an 8x8 pixel tile with indexed color data.
* Each pixel value is an index into a palette.
*/
typedef struct snes_tile8 { typedef struct snes_tile8 {
uint32_t id; uint32_t id; /**< Tile ID for reference */
uint32_t palette_id; uint32_t palette_id; /**< Associated palette ID */
uint8_t data[64]; uint8_t data[64]; /**< 64 pixels in row-major order (y*8+x) */
} snes_tile8; } snes_tile8;
/**
* @brief Load tile data from ROM
*
* @param rom ROM to load from
* @param tile_id ID of tile to load
* @param bpp Bits per pixel (1, 2, 4, 8)
* @return Loaded tile data, or empty tile on error
*/
snes_tile8 yaze_load_tile_from_rom(const zelda3_rom* rom, uint32_t tile_id, uint8_t bpp);
/**
* @brief Convert tile data between different bit depths
*
* @param tile Source tile data
* @param from_bpp Source bits per pixel
* @param to_bpp Target bits per pixel
* @return Converted tile data
*/
snes_tile8 yaze_convert_tile_bpp(const snes_tile8* tile, uint8_t from_bpp, uint8_t to_bpp);
typedef struct snes_tile_info { typedef struct snes_tile_info {
uint16_t id; uint16_t id;
uint8_t palette; uint8_t palette;
@@ -80,55 +326,180 @@ typedef struct snes_tile32 {
uint16_t t3; uint16_t t3;
} snes_tile32; } snes_tile32;
/** @} */
/** /**
* @brief Get a color from a palette set. * @defgroup rom ROM Manipulation
* @{
*/
/**
* @brief Load a ROM file
*
* Loads a Zelda 3 ROM file and validates its format.
*
* @param filename Path to ROM file (.sfc, .smc, etc.)
* @return Pointer to ROM structure, or NULL on error
*
* @note Caller must call yaze_unload_rom() to free memory
*/
zelda3_rom* yaze_load_rom_file(const char* filename);
/**
* @brief Validate ROM integrity
*
* Checks if the ROM data is valid and uncorrupted.
*
* @param rom ROM to validate
* @return YAZE_OK if valid, error code if corrupted
*/
yaze_status yaze_validate_rom(const zelda3_rom* rom);
/**
* @brief Get ROM information
*
* @param rom ROM to query
* @param version Pointer to store detected ROM version
* @param size Pointer to store ROM size in bytes
* @return YAZE_OK on success, error code on failure
*/
yaze_status yaze_get_rom_info(const zelda3_rom* rom, zelda3_version* version, uint64_t* size);
/**
* @brief Get a color from a palette set
* *
* @details This function gets a color from a palette set and returns it as a * Retrieves a specific color from a palette set in the ROM.
* snes_color object.
* *
* @param rom The ROM to get the color from. * @param rom The ROM to get the color from
* @param palette_set The palette set to get the color from. * @param palette_set The palette set index (0-255)
* @param palette The palette to get the color from. * @param palette The palette index within the set (0-15)
* @param color The color to get from the palette. * @param color The color index within the palette (0-15)
* @return The color from the palette set. * @return The color from the palette set
*/ */
snes_color yaze_get_color_from_paletteset(const zelda3_rom* rom, snes_color yaze_get_color_from_paletteset(const zelda3_rom* rom,
int palette_set, int palette, int palette_set, int palette,
int color); int color);
/** @} */
/** /**
* @brief Load the overworld from the ROM. * @defgroup overworld Overworld Functions
* @{
*/
/**
* @brief Load the overworld from ROM
* *
* @param rom The ROM to load the overworld from. * Loads and parses the overworld data from the ROM, including all maps,
* @return The status of the operation. If the operation is successful, the * sprites, and related data structures.
* overworld object will be populated with the overworld from the ROM. *
* @param rom The ROM to load the overworld from
* @return Pointer to overworld structure, or NULL on error
*
* @note Caller must free the returned pointer when done
*/ */
zelda3_overworld* yaze_load_overworld(const zelda3_rom* rom); zelda3_overworld* yaze_load_overworld(const zelda3_rom* rom);
/** /**
* @brief Load all rooms from the ROM. * @brief Free overworld data
* *
* @details This function loads all rooms from the ROM and returns them as an * @param overworld Pointer to overworld to free
* array of rooms.
*
* @param rom The ROM to load rooms from.
* @return The status of the operation. If the operation is successful, the
* rooms array will be populated with the rooms from the ROM.
*/ */
zelda3_dungeon_room* yaze_load_all_rooms(const zelda3_rom* rom); void yaze_free_overworld(zelda3_overworld* overworld);
/** /**
* @brief Load all messages from the ROM. * @brief Get overworld map by index
* *
* @details This function loads all messages from the ROM and returns them as an * @param overworld Overworld data
* array of messages. * @param map_index Map index (0-159 for most ROMs)
* * @return Pointer to map data, or NULL if invalid index
* @param rom The ROM to load messages from.
* @param messages Pointer to an array of messages.
* @return The status of the operation. If the operation is successful, the
* messages array will be populated with the messages from the ROM.
*/ */
yaze_status yaze_load_messages(zelda3_rom* rom, zelda3_message** messages); const zelda3_overworld_map* yaze_get_overworld_map(const zelda3_overworld* overworld, int map_index);
/**
* @brief Get total number of overworld maps
*
* @param overworld Overworld data
* @return Number of maps available
*/
int yaze_get_overworld_map_count(const zelda3_overworld* overworld);
/** @} */
/**
* @defgroup dungeon Dungeon Functions
* @{
*/
/**
* @brief Load all dungeon rooms from ROM
*
* Loads and parses all dungeon room data from the ROM.
*
* @param rom The ROM to load rooms from
* @param room_count Pointer to store the number of rooms loaded
* @return Array of room structures, or NULL on error
*
* @note Caller must free the returned array when done
*/
zelda3_dungeon_room* yaze_load_all_rooms(const zelda3_rom* rom, int* room_count);
/**
* @brief Load a specific dungeon room
*
* @param rom ROM to load from
* @param room_id Room ID to load (0-295 for most ROMs)
* @return Pointer to room data, or NULL on error
*/
const zelda3_dungeon_room* yaze_load_room(const zelda3_rom* rom, int room_id);
/**
* @brief Free dungeon room data
*
* @param rooms Array of rooms to free
* @param room_count Number of rooms in array
*/
void yaze_free_rooms(zelda3_dungeon_room* rooms, int room_count);
/** @} */
/**
* @defgroup messages Message System
* @{
*/
/**
* @brief Load all text messages from ROM
*
* Loads and parses all in-game text messages from the ROM.
*
* @param rom The ROM to load messages from
* @param messages Pointer to store array of messages
* @param message_count Pointer to store number of messages loaded
* @return YAZE_OK on success, error code on failure
*
* @note Caller must free the messages array when done
*/
yaze_status yaze_load_messages(const zelda3_rom* rom, zelda3_message** messages, int* message_count);
/**
* @brief Get a specific message by ID
*
* @param rom ROM to load from
* @param message_id Message ID to retrieve
* @return Pointer to message data, or NULL if not found
*/
const zelda3_message* yaze_get_message(const zelda3_rom* rom, int message_id);
/**
* @brief Free message data
*
* @param messages Array of messages to free
* @param message_count Number of messages in array
*/
void yaze_free_messages(zelda3_message* messages, int message_count);
/** @} */
/** /**
* @brief Function pointer to initialize the extension. * @brief Function pointer to initialize the extension.
@@ -139,31 +510,77 @@ typedef void (*yaze_initialize_func)(yaze_editor_context* context);
typedef void (*yaze_cleanup_func)(void); typedef void (*yaze_cleanup_func)(void);
/** /**
* @brief Extension interface for Yaze. * @defgroup extensions Extension System
* @{
*/
/**
* @brief Extension interface for YAZE
* *
* @details Yaze extensions can be written in C or Python. * Defines the interface for YAZE extensions. Extensions can add new
* functionality to YAZE and can be written in C or other languages.
*/ */
typedef struct yaze_extension { typedef struct yaze_extension {
const char* name; const char* name; /**< Extension name (must not be NULL) */
const char* version; const char* version; /**< Extension version string */
const char* description; /**< Brief description of functionality */
const char* author; /**< Extension author */
int api_version; /**< Required YAZE API version */
/** /**
* @brief Function to initialize the extension. * @brief Initialize the extension
* *
* @details This function is called when the extension is loaded. It can be * Called when the extension is loaded. Use this to set up
* used to set up any resources or state needed by the extension. * any resources or state needed by the extension.
*
* @param context Editor context provided by YAZE
* @return YAZE_OK on success, error code on failure
*/ */
yaze_initialize_func initialize; yaze_status (*initialize)(yaze_editor_context* context);
/** /**
* @brief Function to clean up the extension. * @brief Clean up the extension
* *
* @details This function is called when the extension is unloaded. It can be * Called when the extension is unloaded. Use this to clean up
* used to clean up any resources or state used by the extension. * any resources or state used by the extension.
*/ */
yaze_cleanup_func cleanup; void (*cleanup)(void);
/**
* @brief Get extension capabilities
*
* Returns a bitmask indicating what features this extension provides.
*
* @return Capability flags (see YAZE_EXT_CAP_* constants)
*/
uint32_t (*get_capabilities)(void);
} yaze_extension; } yaze_extension;
/** Extension capability flags */
#define YAZE_EXT_CAP_ROM_EDITING (1 << 0) /**< Can edit ROM data */
#define YAZE_EXT_CAP_GRAPHICS (1 << 1) /**< Provides graphics functions */
#define YAZE_EXT_CAP_AUDIO (1 << 2) /**< Provides audio functions */
#define YAZE_EXT_CAP_SCRIPTING (1 << 3) /**< Provides scripting support */
#define YAZE_EXT_CAP_IMPORT_EXPORT (1 << 4) /**< Can import/export data */
/**
* @brief Register an extension with YAZE
*
* @param extension Extension to register
* @return YAZE_OK on success, error code on failure
*/
yaze_status yaze_register_extension(const yaze_extension* extension);
/**
* @brief Unregister an extension
*
* @param name Name of extension to unregister
* @return YAZE_OK on success, error code on failure
*/
yaze_status yaze_unregister_extension(const char* name);
/** @} */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -1,6 +1,17 @@
#ifndef ZELDA_H #ifndef ZELDA_H
#define ZELDA_H #define ZELDA_H
/**
* @file zelda.h
* @brief The Legend of Zelda: A Link to the Past - Data Structures and Constants
*
* This header defines data structures and constants specific to
* The Legend of Zelda: A Link to the Past ROM format and game data.
*
* @version 0.3.0
* @author YAZE Team
*/
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -9,40 +20,126 @@ extern "C" {
#include <stdint.h> #include <stdint.h>
/** /**
* @brief Different versions of the game supported by yaze. * @defgroup rom_types ROM Types and Versions
* @{
*/ */
enum zelda3_version {
US = 1, // US version
JP = 2, // JP version
SD = 3, // Super Donkey Proto (Experimental)
RANDO = 4, // Randomizer (Unimplemented)
};
/** /**
* @brief Pointers for each version of the game. * @brief Different versions of the game supported by YAZE
*
* YAZE supports multiple regional versions and ROM hacks of
* The Legend of Zelda: A Link to the Past.
*/ */
struct zelda3_version_pointers { typedef enum zelda3_version {
uint32_t kGfxAnimatedPointer; ZELDA3_VERSION_UNKNOWN = 0, /**< Unknown or unsupported version */
uint32_t kOverworldGfxGroups1; ZELDA3_VERSION_US = 1, /**< US/North American version */
uint32_t kOverworldGfxGroups2; ZELDA3_VERSION_JP = 2, /**< Japanese version */
uint32_t kCompressedAllMap32PointersHigh; ZELDA3_VERSION_EU = 3, /**< European version */
uint32_t kCompressedAllMap32PointersLow; ZELDA3_VERSION_PROTO = 4, /**< Prototype/development version */
uint32_t kOverworldMapPaletteGroup; ZELDA3_VERSION_RANDOMIZER = 5, /**< Randomizer ROM (experimental) */
uint32_t kOverlayPointers;
uint32_t kOverlayPointersBank; // Legacy aliases for backward compatibility
uint32_t kOverworldTilesType; US = ZELDA3_VERSION_US, /**< @deprecated Use ZELDA3_VERSION_US */
uint32_t kOverworldGfxPtr1; JP = ZELDA3_VERSION_JP, /**< @deprecated Use ZELDA3_VERSION_JP */
uint32_t kOverworldGfxPtr2; SD = ZELDA3_VERSION_PROTO, /**< @deprecated Use ZELDA3_VERSION_PROTO */
uint32_t kOverworldGfxPtr3; RANDO = ZELDA3_VERSION_RANDOMIZER, /**< @deprecated Use ZELDA3_VERSION_RANDOMIZER */
uint32_t kMap32TileTL; } zelda3_version;
uint32_t kMap32TileTR;
uint32_t kMap32TileBL; /**
uint32_t kMap32TileBR; * @brief Detect ROM version from header data
uint32_t kSpriteBlocksetPointer; *
uint32_t kDungeonPalettesGroups; * @param rom_data Pointer to ROM data
}; * @param size Size of ROM data in bytes
* @return Detected version, or ZELDA3_VERSION_UNKNOWN if not recognized
*/
zelda3_version zelda3_detect_version(const uint8_t* rom_data, size_t size);
/**
* @brief Get version name as string
*
* @param version Version enum value
* @return Human-readable version name
*/
const char* zelda3_version_to_string(zelda3_version version);
/**
* @brief ROM data pointers for different game versions
*
* Contains memory addresses where specific data structures are located
* within the ROM. These addresses vary between different regional versions.
*/
typedef struct zelda3_version_pointers {
// New Google C++ style names
uint32_t gfx_animated_pointer; /**< Animated graphics pointer */
uint32_t overworld_gfx_groups1; /**< Overworld graphics group 1 */
uint32_t overworld_gfx_groups2; /**< Overworld graphics group 2 */
uint32_t compressed_map32_pointers_high; /**< Map32 high pointers */
uint32_t compressed_map32_pointers_low; /**< Map32 low pointers */
uint32_t overworld_map_palette_group; /**< Map palette groups */
uint32_t overlay_pointers; /**< Overlay data pointers */
uint32_t overlay_pointers_bank; /**< Overlay bank number */
uint32_t overworld_tiles_type; /**< Tile type definitions */
uint32_t overworld_gfx_ptr1; /**< Graphics pointer 1 */
uint32_t overworld_gfx_ptr2; /**< Graphics pointer 2 */
uint32_t overworld_gfx_ptr3; /**< Graphics pointer 3 */
uint32_t map32_tile_tl; /**< 32x32 tile top-left */
uint32_t map32_tile_tr; /**< 32x32 tile top-right */
uint32_t map32_tile_bl; /**< 32x32 tile bottom-left */
uint32_t map32_tile_br; /**< 32x32 tile bottom-right */
uint32_t sprite_blockset_pointer; /**< Sprite graphics pointer */
uint32_t dungeon_palettes_groups; /**< Dungeon palette groups */
// Legacy aliases for backward compatibility (deprecated)
uint32_t kGfxAnimatedPointer; /**< @deprecated Use gfx_animated_pointer */
uint32_t kOverworldGfxGroups1; /**< @deprecated Use overworld_gfx_groups1 */
uint32_t kOverworldGfxGroups2; /**< @deprecated Use overworld_gfx_groups2 */
uint32_t kCompressedAllMap32PointersHigh; /**< @deprecated Use compressed_map32_pointers_high */
uint32_t kCompressedAllMap32PointersLow; /**< @deprecated Use compressed_map32_pointers_low */
uint32_t kOverworldMapPaletteGroup; /**< @deprecated Use overworld_map_palette_group */
uint32_t kOverlayPointers; /**< @deprecated Use overlay_pointers */
uint32_t kOverlayPointersBank; /**< @deprecated Use overlay_pointers_bank */
uint32_t kOverworldTilesType; /**< @deprecated Use overworld_tiles_type */
uint32_t kOverworldGfxPtr1; /**< @deprecated Use overworld_gfx_ptr1 */
uint32_t kOverworldGfxPtr2; /**< @deprecated Use overworld_gfx_ptr2 */
uint32_t kOverworldGfxPtr3; /**< @deprecated Use overworld_gfx_ptr3 */
uint32_t kMap32TileTL; /**< @deprecated Use map32_tile_tl */
uint32_t kMap32TileTR; /**< @deprecated Use map32_tile_tr */
uint32_t kMap32TileBL; /**< @deprecated Use map32_tile_bl */
uint32_t kMap32TileBR; /**< @deprecated Use map32_tile_br */
uint32_t kSpriteBlocksetPointer; /**< @deprecated Use sprite_blockset_pointer */
uint32_t kDungeonPalettesGroups; /**< @deprecated Use dungeon_palettes_groups */
} zelda3_version_pointers;
/**
* @brief Get version-specific pointers
*
* @param version ROM version
* @return Pointer to version-specific address structure
*/
const zelda3_version_pointers* zelda3_get_version_pointers(zelda3_version version);
const static zelda3_version_pointers zelda3_us_pointers = { const static zelda3_version_pointers zelda3_us_pointers = {
// New style names
0x10275, // gfx_animated_pointer
0x5D97, // overworld_gfx_groups1
0x6073, // overworld_gfx_groups2
0x1794D, // compressed_map32_pointers_high
0x17B2D, // compressed_map32_pointers_low
0x75504, // overworld_map_palette_group
0x77664, // overlay_pointers
0x0E, // overlay_pointers_bank
0x71459, // overworld_tiles_type
0x4F80, // overworld_gfx_ptr1
0x505F, // overworld_gfx_ptr2
0x513E, // overworld_gfx_ptr3
0x18000, // map32_tile_tl
0x1B400, // map32_tile_tr
0x20000, // map32_tile_bl
0x23400, // map32_tile_br
0x5B57, // sprite_blockset_pointer
0x75460, // dungeon_palettes_groups
// Legacy k-prefixed names (same values for backward compatibility)
0x10275, // kGfxAnimatedPointer 0x10275, // kGfxAnimatedPointer
0x5D97, // kOverworldGfxGroups1 0x5D97, // kOverworldGfxGroups1
0x6073, // kOverworldGfxGroups2 0x6073, // kOverworldGfxGroups2
@@ -64,6 +161,27 @@ const static zelda3_version_pointers zelda3_us_pointers = {
}; };
const static zelda3_version_pointers zelda3_jp_pointers = { const static zelda3_version_pointers zelda3_jp_pointers = {
// New style names
0x10624, // gfx_animated_pointer
0x5DD7, // overworld_gfx_groups1
0x60B3, // overworld_gfx_groups2
0x176B1, // compressed_map32_pointers_high
0x17891, // compressed_map32_pointers_low
0x67E74, // overworld_map_palette_group
0x3FAF4, // overlay_pointers
0x07, // overlay_pointers_bank
0x7FD94, // overworld_tiles_type
0x4FC0, // overworld_gfx_ptr1
0x509F, // overworld_gfx_ptr2
0x517E, // overworld_gfx_ptr3
0x18000, // map32_tile_tl
0x1B3C0, // map32_tile_tr
0x20000, // map32_tile_bl
0x233C0, // map32_tile_br
0x5B97, // sprite_blockset_pointer
0x67DD0, // dungeon_palettes_groups
// Legacy k-prefixed names (same values for backward compatibility)
0x10624, // kGfxAnimatedPointer 0x10624, // kGfxAnimatedPointer
0x5DD7, // kOverworldGfxGroups1 0x5DD7, // kOverworldGfxGroups1
0x60B3, // kOverworldGfxGroups2 0x60B3, // kOverworldGfxGroups2
@@ -84,119 +202,296 @@ const static zelda3_version_pointers zelda3_jp_pointers = {
0x67DD0, // kDungeonPalettesGroups 0x67DD0, // kDungeonPalettesGroups
}; };
/**
* @brief ROM data structure
*
* Represents a loaded Zelda 3 ROM with its data and metadata.
*/
typedef struct zelda3_rom { typedef struct zelda3_rom {
const char* filename; const char* filename; /**< Original filename (can be NULL) */
uint8_t* data; uint8_t* data; /**< ROM data (read-only for external users) */
uint64_t size; uint64_t size; /**< Size of ROM data in bytes */
void* impl; // yaze::Rom* zelda3_version version; /**< Detected ROM version */
bool is_modified; /**< True if ROM has been modified */
void* impl; /**< Internal implementation pointer */
} zelda3_rom; } zelda3_rom;
zelda3_rom* yaze_load_rom(const char* filename); /** @} */
void yaze_unload_rom(zelda3_rom* rom);
void yaze_save_rom(zelda3_rom* rom, const char* filename);
/** /**
* @brief Primitive of a message. * @defgroup rom_functions ROM File Operations
* @{
*/
/**
* @brief Load a ROM file
* *
* @param filename Path to ROM file
* @return Loaded ROM structure, or NULL on error
*/
zelda3_rom* yaze_load_rom(const char* filename);
/**
* @brief Unload and free ROM data
*
* @param rom ROM to unload
*/
void yaze_unload_rom(zelda3_rom* rom);
/**
* @brief Save ROM to file
*
* @param rom ROM to save
* @param filename Output filename
* @return YAZE_OK on success, error code on failure
*/
int yaze_save_rom(zelda3_rom* rom, const char* filename);
/**
* @brief Create a copy of ROM data
*
* @param rom Source ROM
* @return Copy of ROM, or NULL on error
*/
zelda3_rom* yaze_copy_rom(const zelda3_rom* rom);
/** @} */
/**
* @defgroup messages Message Data Structures
* @{
*/
/**
* @brief In-game text message data
*
* Represents a text message from the game, including both raw
* ROM data and parsed/decoded text content.
*/ */
typedef struct zelda3_message { typedef struct zelda3_message {
uint8_t id; uint16_t id; /**< Message ID (0-65535) */
uint8_t address; uint32_t rom_address; /**< Address in ROM where message data starts */
uint8_t *raw_string; uint16_t length; /**< Length of message data in bytes */
uint8_t *contents_parsed; uint8_t* raw_data; /**< Raw message data from ROM */
uint8_t *data; char* parsed_text; /**< Decoded text content (UTF-8) */
uint8_t *data_parsed; bool is_compressed; /**< True if message uses compression */
uint8_t encoding_type; /**< Text encoding type used */
} zelda3_message; } zelda3_message;
/** @} */
/** /**
* @brief Primitive of an overworld map. * @defgroup overworld Overworld Data Structures
* @{
*/
/**
* @brief Overworld map data
*
* Represents a single screen/area in the overworld, including
* graphics, palette, music, and sprite information.
*/ */
typedef struct zelda3_overworld_map { typedef struct zelda3_overworld_map {
uint8_t id; /**< ID of the overworld map. */ uint16_t id; /**< Map ID (0-159 for most ROMs) */
uint8_t parent_id; uint8_t parent_id; /**< Parent map ID for sub-areas */
uint8_t quadrant_id; uint8_t quadrant_id; /**< Quadrant within parent (0-3) */
uint8_t world_id; uint8_t world_id; /**< World number (Light/Dark) */
uint8_t game_state; uint8_t game_state; /**< Game state requirements */
uint8_t area_graphics;
uint8_t area_palette; /* Graphics and Visual Properties */
uint8_t area_graphics; /**< Area graphics set ID */
uint8_t sprite_graphics[3]; uint8_t area_palette; /**< Area palette set ID */
uint8_t sprite_palette[3]; uint8_t main_palette; /**< Main palette ID */
uint8_t area_music[4]; uint8_t animated_gfx; /**< Animated graphics ID */
uint8_t static_graphics[16];
/* Sprite Configuration */
uint8_t sprite_graphics[3]; /**< Sprite graphics sets */
uint8_t sprite_palette[3]; /**< Sprite palette sets */
/* Audio Configuration */
uint8_t area_music[4]; /**< Music tracks for different states */
/* Extended Graphics (ZSCustomOverworld) */
uint8_t static_graphics[16]; /**< Static graphics assignments */
uint8_t custom_tileset[8]; /**< Custom tileset assignments */
/* Screen Properties */
uint16_t area_specific_bg_color; /**< Background color override */
uint16_t subscreen_overlay; /**< Subscreen overlay settings */
/* Flags and Metadata */
bool is_large_map; /**< True for 32x32 maps */
bool has_special_gfx; /**< True if uses special graphics */
} zelda3_overworld_map; } zelda3_overworld_map;
/** /**
* @brief Primitive of the overworld. * @brief Complete overworld data
*
* Contains all overworld maps and related data for the entire game world.
*/ */
typedef struct zelda3_overworld { typedef struct zelda3_overworld {
void* impl; // yaze::Overworld* void* impl; /**< Internal implementation pointer */
zelda3_overworld_map** maps; /**< Pointer to the overworld maps. */ zelda3_overworld_map** maps; /**< Array of overworld maps */
int map_count; /**< Number of maps in array */
zelda3_version rom_version; /**< ROM version this data came from */
bool has_zsco_features; /**< True if ZSCustomOverworld features detected */
} zelda3_overworld; } zelda3_overworld;
/** @} */
/**
* @defgroup dungeon Dungeon Data Structures
* @{
*/
/**
* @brief Dungeon sprite definition
*
* Represents a sprite that can appear in dungeon rooms.
*/
typedef struct dungeon_sprite { typedef struct dungeon_sprite {
const char* name; const char* name; /**< Sprite name (for debugging/display) */
uint8_t id; uint8_t id; /**< Sprite type ID */
uint8_t subtype; uint8_t subtype; /**< Sprite subtype/variant */
uint8_t x; /**< X position in room */
uint8_t y; /**< Y position in room */
uint8_t layer; /**< Layer (0=background, 1=foreground) */
uint16_t properties; /**< Additional sprite properties */
} dungeon_sprite; } dungeon_sprite;
typedef enum background2 { /**
Off, * @brief Background layer 2 effects
Parallax, *
Dark, * Defines the different visual effects that can be applied to
OnTop, * background layer 2 in dungeon rooms.
Translucent, */
Addition, typedef enum zelda3_bg2_effect {
Normal, ZELDA3_BG2_OFF = 0, /**< Background layer 2 disabled */
Transparent, ZELDA3_BG2_PARALLAX = 1, /**< Parallax scrolling effect */
DarkRoom ZELDA3_BG2_DARK = 2, /**< Dark overlay effect */
} background2; ZELDA3_BG2_ON_TOP = 3, /**< Layer appears on top */
ZELDA3_BG2_TRANSLUCENT = 4, /**< Semi-transparent overlay */
ZELDA3_BG2_ADDITION = 5, /**< Additive blending */
ZELDA3_BG2_NORMAL = 6, /**< Normal blending */
ZELDA3_BG2_TRANSPARENT = 7, /**< Fully transparent */
ZELDA3_BG2_DARK_ROOM = 8 /**< Dark room effect */
} zelda3_bg2_effect;
// Legacy aliases for backward compatibility
typedef zelda3_bg2_effect background2;
#define Off ZELDA3_BG2_OFF
#define Parallax ZELDA3_BG2_PARALLAX
#define Dark ZELDA3_BG2_DARK
#define OnTop ZELDA3_BG2_ON_TOP
#define Translucent ZELDA3_BG2_TRANSLUCENT
#define Addition ZELDA3_BG2_ADDITION
#define Normal ZELDA3_BG2_NORMAL
#define Transparent ZELDA3_BG2_TRANSPARENT
#define DarkRoom ZELDA3_BG2_DARK_ROOM
/**
* @brief Dungeon door object
*
* Represents a door or passage between rooms.
*/
typedef struct object_door { typedef struct object_door {
short id; uint16_t id; /**< Door ID for reference */
uint8_t x; uint8_t x; /**< X position in room (0-63) */
uint8_t y; uint8_t y; /**< Y position in room (0-63) */
uint8_t size; uint8_t size; /**< Door size (width/height) */
uint8_t type; uint8_t type; /**< Door type (normal, locked, etc.) */
uint8_t layer; uint8_t layer; /**< Layer (0=background, 1=foreground) */
uint8_t key_type; /**< Required key type (0=none) */
bool is_locked; /**< True if door requires key */
} object_door; } object_door;
/**
* @brief Staircase connection
*
* Represents stairs or holes that connect different rooms or levels.
*/
typedef struct staircase { typedef struct staircase {
uint8_t id; uint8_t id; /**< Staircase ID */
uint8_t room; uint8_t room; /**< Target room ID (for backward compatibility) */
const char* label; const char* label; /**< Description (for debugging) */
} staircase; } staircase;
/**
* @brief Treasure chest
*
* Represents a chest containing an item.
*/
typedef struct chest { typedef struct chest {
uint8_t x; uint8_t x; /**< X position in room */
uint8_t y; uint8_t y; /**< Y position in room */
uint8_t item; uint8_t item; /**< Item ID (for backward compatibility) */
bool picker; bool picker; /**< Legacy field */
bool big_chest; bool big_chest; /**< True for large chests */
} chest; } chest;
/**
* @brief Legacy chest data structure
*
* @deprecated Use chest structure instead
*/
typedef struct chest_data { typedef struct chest_data {
uint8_t id; uint8_t id; /**< Chest ID */
bool size; bool size; /**< True for big chest */
} chest_data; } chest_data;
/**
* @brief Room transition destination
*
* Defines where the player goes when using stairs, holes, or other transitions.
*/
typedef struct destination { typedef struct destination {
uint8_t index; uint8_t index; /**< Entrance index */
uint8_t target; uint8_t target; /**< Target room ID */
uint8_t target_layer; uint8_t target_layer; /**< Target layer */
} destination; } destination;
/** @} */
/**
* @brief Complete dungeon room data
*
* Contains all objects, sprites, and properties for a single dungeon room.
*/
typedef struct zelda3_dungeon_room { typedef struct zelda3_dungeon_room {
background2 bg2; uint16_t id; /**< Room ID (0-295) */
dungeon_sprite* sprites; background2 bg2; /**< Background layer 2 effect (legacy) */
object_door* doors;
staircase* staircases; /* Room Contents */
chest* chests; dungeon_sprite* sprites; /**< Array of sprites in room */
chest_data* chests_in_room; int sprite_count; /**< Number of sprites */
destination pits;
destination stairs[4]; object_door* doors; /**< Array of doors */
int door_count; /**< Number of doors */
staircase* staircases; /**< Array of staircases */
int staircase_count; /**< Number of staircases */
chest* chests; /**< Array of chests */
int chest_count; /**< Number of chests */
/* Room Connections */
destination pits; /**< Pit fall destination */
destination stairs[4]; /**< Stair destinations (up to 4) */
/* Room Properties */
uint8_t floor_type; /**< Floor graphics type */
uint8_t wall_type; /**< Wall graphics type */
uint8_t palette_id; /**< Room palette ID */
uint8_t music_track; /**< Background music track */
/* Flags */
bool is_dark; /**< True if room requires lamp */
bool has_water; /**< True if room contains water */
bool blocks_items; /**< True if room blocks certain items */
} zelda3_dungeon_room; } zelda3_dungeon_room;
/** @} */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -351,6 +351,7 @@ void MapPropertiesSystem::DrawGraphicsPopup(int current_map, int game_state) {
} }
} }
ImGui::PopStyleVar(2); // Pop the 2 style variables we pushed
ImGui::EndPopup(); ImGui::EndPopup();
} }
} }
@@ -394,6 +395,7 @@ void MapPropertiesSystem::DrawPalettesPopup(int current_map, int game_state, boo
show_custom_bg_color_editor = !show_custom_bg_color_editor; show_custom_bg_color_editor = !show_custom_bg_color_editor;
} }
ImGui::PopStyleVar(2); // Pop the 2 style variables we pushed
ImGui::EndPopup(); ImGui::EndPopup();
} }
} }
@@ -472,7 +474,7 @@ void MapPropertiesSystem::DrawPropertiesPopup(int current_map, bool& show_map_pr
} }
HOVER_HINT("Open comprehensive properties editor"); HOVER_HINT("Open comprehensive properties editor");
ImGui::PopStyleVar(2); ImGui::PopStyleVar(2); // Pop the 2 style variables we pushed
ImGui::EndPopup(); ImGui::EndPopup();
} }
} }
@@ -905,7 +907,7 @@ void MapPropertiesSystem::DrawViewPopup() {
} }
HOVER_HINT("Toggle fullscreen canvas (F11)"); HOVER_HINT("Toggle fullscreen canvas (F11)");
ImGui::PopStyleVar(2); ImGui::PopStyleVar(2); // Pop the 2 style variables we pushed
ImGui::EndPopup(); ImGui::EndPopup();
} }
} }
@@ -939,7 +941,7 @@ void MapPropertiesSystem::DrawQuickAccessPopup() {
} }
HOVER_HINT("Lock/unlock current map (Ctrl+L)"); HOVER_HINT("Lock/unlock current map (Ctrl+L)");
ImGui::PopStyleVar(2); ImGui::PopStyleVar(2); // Pop the 2 style variables we pushed
ImGui::EndPopup(); ImGui::EndPopup();
} }
} }

View File

@@ -13,7 +13,11 @@ ImVec4 ConvertSnesColorToImVec4(const gfx::SnesColor& color) {
} }
gfx::SnesColor ConvertImVec4ToSnesColor(const ImVec4& color) { gfx::SnesColor ConvertImVec4ToSnesColor(const ImVec4& color) {
return gfx::SnesColor(color.x, color.y, color.z); // Convert from float (0.0-1.0) to uint8_t (0-255)
uint8_t r = static_cast<uint8_t>(color.x * 255.0f);
uint8_t g = static_cast<uint8_t>(color.y * 255.0f);
uint8_t b = static_cast<uint8_t>(color.z * 255.0f);
return gfx::SnesColor(r, g, b);
} }
IMGUI_API bool SnesColorButton(absl::string_view id, gfx::SnesColor& color, IMGUI_API bool SnesColorButton(absl::string_view id, gfx::SnesColor& color,

View File

@@ -3,6 +3,8 @@
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <sstream> #include <sstream>
#include <cstring>
#include <stdexcept>
#include "app/core/controller.h" #include "app/core/controller.h"
#include "app/core/platform/app_delegate.h" #include "app/core/platform/app_delegate.h"
@@ -16,6 +18,9 @@ DEFINE_FLAG(std::string, rom_file, "",
"Path to the ROM file to load. " "Path to the ROM file to load. "
"If not specified, the app will run without a ROM."); "If not specified, the app will run without a ROM.");
// Static variables for library state
static bool g_library_initialized = false;
int yaze_app_main(int argc, char **argv) { int yaze_app_main(int argc, char **argv) {
yaze::util::FlagParser parser(yaze::util::global_flag_registry()); yaze::util::FlagParser parser(yaze::util::global_flag_registry());
RETURN_IF_EXCEPTION(parser.Parse(argc, argv)); RETURN_IF_EXCEPTION(parser.Parse(argc, argv));
@@ -42,72 +47,161 @@ int yaze_app_main(int argc, char **argv) {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
void yaze_check_version(const char *version) { // Version and initialization functions
std::string current_version; yaze_status yaze_library_init() {
std::stringstream ss; if (g_library_initialized) {
ss << YAZE_VERSION_MAJOR << "." << YAZE_VERSION_MINOR << "." return YAZE_OK;
<< YAZE_VERSION_PATCH; }
ss >> current_version;
// Initialize SDL and other subsystems if needed
g_library_initialized = true;
return YAZE_OK;
}
if (version != current_version) { void yaze_library_shutdown() {
std::cout << "Yaze version mismatch: expected " << current_version if (!g_library_initialized) {
<< ", got " << version << std::endl; return;
exit(1); }
// Cleanup subsystems
g_library_initialized = false;
return;
}
const char* yaze_status_to_string(yaze_status status) {
switch (status) {
case YAZE_OK:
return "Success";
case YAZE_ERROR_UNKNOWN:
return "Unknown error";
case YAZE_ERROR_INVALID_ARG:
return "Invalid argument";
case YAZE_ERROR_FILE_NOT_FOUND:
return "File not found";
case YAZE_ERROR_MEMORY:
return "Memory allocation failed";
case YAZE_ERROR_IO:
return "I/O operation failed";
case YAZE_ERROR_CORRUPTION:
return "Data corruption detected";
case YAZE_ERROR_NOT_INITIALIZED:
return "Component not initialized";
default:
return "Unknown status code";
} }
} }
yaze_status yaze_init(yaze_editor_context *yaze_ctx, char *rom_filename) { const char* yaze_get_version_string() {
yaze_ctx->rom = yaze_load_rom(rom_filename); return YAZE_VERSION_STRING;
if (yaze_ctx->rom == nullptr) {
yaze_ctx->error_message = "Failed to load ROM";
return yaze_status::YAZE_ERROR;
}
return yaze_status::YAZE_OK;
} }
yaze_status yaze_shutdown(yaze_editor_context *yaze_ctx) { int yaze_get_version_number() {
if (yaze_ctx->rom) { return YAZE_VERSION_NUMBER;
yaze_unload_rom(yaze_ctx->rom);
}
return yaze_status::YAZE_OK;
} }
zelda3_rom *yaze_load_rom(const char *filename) { bool yaze_check_version_compatibility(const char* expected_version) {
yaze::Rom *internal_rom; if (expected_version == nullptr) {
internal_rom = new yaze::Rom(); return false;
}
return strcmp(expected_version, YAZE_VERSION_STRING) == 0;
}
yaze_status yaze_init(yaze_editor_context* context, const char* rom_filename) {
if (context == nullptr) {
return YAZE_ERROR_INVALID_ARG;
}
if (!g_library_initialized) {
yaze_status init_status = yaze_library_init();
if (init_status != YAZE_OK) {
return init_status;
}
}
context->rom = nullptr;
context->error_message = nullptr;
if (rom_filename != nullptr && strlen(rom_filename) > 0) {
context->rom = yaze_load_rom(rom_filename);
if (context->rom == nullptr) {
context->error_message = "Failed to load ROM file";
return YAZE_ERROR_FILE_NOT_FOUND;
}
}
return YAZE_OK;
}
yaze_status yaze_shutdown(yaze_editor_context* context) {
if (context == nullptr) {
return YAZE_ERROR_INVALID_ARG;
}
if (context->rom != nullptr) {
yaze_unload_rom(context->rom);
context->rom = nullptr;
}
context->error_message = nullptr;
return YAZE_OK;
}
zelda3_rom* yaze_load_rom(const char* filename) {
if (filename == nullptr || strlen(filename) == 0) {
return nullptr;
}
auto internal_rom = std::make_unique<yaze::Rom>();
if (!internal_rom->LoadFromFile(filename).ok()) { if (!internal_rom->LoadFromFile(filename).ok()) {
delete internal_rom;
return nullptr; return nullptr;
} }
zelda3_rom *rom = new zelda3_rom(); auto* rom = new zelda3_rom();
rom->filename = filename; rom->filename = filename;
rom->impl = internal_rom; rom->impl = internal_rom.release(); // Transfer ownership
rom->data = const_cast<uint8_t *>(internal_rom->data()); rom->data = const_cast<uint8_t*>(static_cast<yaze::Rom*>(rom->impl)->data());
rom->size = internal_rom->size(); rom->size = static_cast<yaze::Rom*>(rom->impl)->size();
rom->version = ZELDA3_VERSION_US; // Default, should be detected
rom->is_modified = false;
return rom; return rom;
} }
void yaze_unload_rom(zelda3_rom *rom) { void yaze_unload_rom(zelda3_rom* rom) {
if (rom->impl) { if (rom == nullptr) {
delete static_cast<yaze::Rom *>(rom->impl); return;
}
if (rom->impl != nullptr) {
delete static_cast<yaze::Rom*>(rom->impl);
rom->impl = nullptr;
} }
if (rom) { delete rom;
delete rom;
}
} }
void yaze_save_rom(zelda3_rom *rom, const char *filename) { int yaze_save_rom(zelda3_rom* rom, const char* filename) {
if (rom->impl) { if (rom == nullptr || filename == nullptr) {
yaze::Rom *internal_rom = static_cast<yaze::Rom *>(rom->impl); return YAZE_ERROR_INVALID_ARG;
if (auto status = internal_rom->SaveToFile(yaze::Rom::SaveSettings{
.backup = true, .save_new = false, .filename = filename});
!status.ok()) {
throw std::runtime_error(status.message().data());
}
} }
if (rom->impl == nullptr) {
return YAZE_ERROR_NOT_INITIALIZED;
}
auto* internal_rom = static_cast<yaze::Rom*>(rom->impl);
auto status = internal_rom->SaveToFile(yaze::Rom::SaveSettings{
.backup = true,
.save_new = false,
.filename = filename
});
if (!status.ok()) {
return YAZE_ERROR_IO;
}
rom->is_modified = false;
return YAZE_OK;
} }
yaze_bitmap yaze_load_bitmap(const char *filename) { yaze_bitmap yaze_load_bitmap(const char *filename) {
@@ -172,27 +266,122 @@ zelda3_dungeon_room *yaze_load_all_rooms(const zelda3_rom *rom) {
return rooms; return rooms;
} }
yaze_status yaze_load_messages(zelda3_rom *rom, zelda3_message **messages) { yaze_status yaze_load_messages(const zelda3_rom* rom, zelda3_message** messages, int* message_count) {
if (rom == nullptr || messages == nullptr || message_count == nullptr) {
return YAZE_ERROR_INVALID_ARG;
}
if (rom->impl == nullptr) { if (rom->impl == nullptr) {
return yaze_status::YAZE_ERROR; return YAZE_ERROR_NOT_INITIALIZED;
} }
// Use LoadAllTextData from message_data.h try {
std::vector<yaze::editor::MessageData> message_data = // Use LoadAllTextData from message_data.h
yaze::editor::ReadAllTextData(rom->data, 0); std::vector<yaze::editor::MessageData> message_data =
for (const auto &message : message_data) { yaze::editor::ReadAllTextData(rom->data, 0);
messages[message.ID] = new zelda3_message();
messages[message.ID]->id = message.ID; *message_count = static_cast<int>(message_data.size());
messages[message.ID]->address = message.Address; *messages = new zelda3_message[*message_count];
messages[message.ID]->raw_string = reinterpret_cast<uint8_t *>(
const_cast<char *>(message.RawString.data())); for (size_t i = 0; i < message_data.size(); ++i) {
messages[message.ID]->contents_parsed = reinterpret_cast<uint8_t *>( const auto& msg = message_data[i];
const_cast<char *>(message.ContentsParsed.data())); (*messages)[i].id = msg.ID;
messages[message.ID]->data = (*messages)[i].rom_address = msg.Address;
reinterpret_cast<uint8_t *>(const_cast<uint8_t *>(message.Data.data())); (*messages)[i].length = static_cast<uint16_t>(msg.RawString.length());
messages[message.ID]->data_parsed = reinterpret_cast<uint8_t *>(
const_cast<uint8_t *>(message.DataParsed.data())); // Allocate and copy string data
(*messages)[i].raw_data = new uint8_t[msg.Data.size()];
std::memcpy((*messages)[i].raw_data, msg.Data.data(), msg.Data.size());
(*messages)[i].parsed_text = new char[msg.ContentsParsed.length() + 1];
std::strcpy((*messages)[i].parsed_text, msg.ContentsParsed.c_str());
(*messages)[i].is_compressed = false; // TODO: Detect compression
(*messages)[i].encoding_type = 0; // TODO: Detect encoding
}
} catch (const std::exception& e) {
return YAZE_ERROR_MEMORY;
} }
return yaze_status::YAZE_OK; return YAZE_OK;
}
// Additional API functions implementation
// Graphics functions
void yaze_free_bitmap(yaze_bitmap* bitmap) {
if (bitmap != nullptr && bitmap->data != nullptr) {
delete[] bitmap->data;
bitmap->data = nullptr;
bitmap->width = 0;
bitmap->height = 0;
bitmap->bpp = 0;
}
}
yaze_bitmap yaze_create_bitmap(int width, int height, uint8_t bpp) {
yaze_bitmap bitmap = {};
if (width <= 0 || height <= 0 || (bpp != 1 && bpp != 2 && bpp != 4 && bpp != 8)) {
return bitmap; // Return empty bitmap on invalid args
}
bitmap.width = width;
bitmap.height = height;
bitmap.bpp = bpp;
bitmap.data = new uint8_t[width * height]();
return bitmap;
}
snes_color yaze_rgb_to_snes_color(uint8_t r, uint8_t g, uint8_t b) {
snes_color color = {};
color.red = r; // Store full 8-bit values (existing code expects this)
color.green = g;
color.blue = b;
return color;
}
void yaze_snes_color_to_rgb(snes_color color, uint8_t* r, uint8_t* g, uint8_t* b) {
if (r != nullptr) *r = static_cast<uint8_t>(color.red);
if (g != nullptr) *g = static_cast<uint8_t>(color.green);
if (b != nullptr) *b = static_cast<uint8_t>(color.blue);
}
// Version detection functions
zelda3_version zelda3_detect_version(const uint8_t* rom_data, size_t size) {
if (rom_data == nullptr || size < 0x100000) {
return ZELDA3_VERSION_UNKNOWN;
}
// TODO: Implement proper version detection based on ROM header
return ZELDA3_VERSION_US; // Default assumption
}
const char* zelda3_version_to_string(zelda3_version version) {
switch (version) {
case ZELDA3_VERSION_US:
return "US/North American";
case ZELDA3_VERSION_JP:
return "Japanese";
case ZELDA3_VERSION_EU:
return "European";
case ZELDA3_VERSION_PROTO:
return "Prototype";
case ZELDA3_VERSION_RANDOMIZER:
return "Randomizer";
default:
return "Unknown";
}
}
const zelda3_version_pointers* zelda3_get_version_pointers(zelda3_version version) {
switch (version) {
case ZELDA3_VERSION_US:
return &zelda3_us_pointers;
case ZELDA3_VERSION_JP:
return &zelda3_jp_pointers;
default:
return &zelda3_us_pointers; // Default fallback
}
} }