diff --git a/libretro_binding/libretro_binding.cpp b/libretro_binding/libretro_binding.cpp index 49ba60c..c0fb75d 100644 --- a/libretro_binding/libretro_binding.cpp +++ b/libretro_binding/libretro_binding.cpp @@ -1,112 +1,93 @@ -// libretro_binding.cpp #include "libretro_binding.h" +#include #include #include -#include -#include -#include -#include - +#include using namespace godot; -// Funzioni richieste dai core libretro -typedef void (*retro_init_t)(); -typedef void (*retro_deinit_t)(); -typedef bool (*retro_load_game_t)(const char *); -typedef void (*retro_run_t)(); -typedef void (*retro_get_system_info_t)(struct retro_system_info *); -typedef void (*retro_get_video_frame_t)(void **frame, unsigned *width, unsigned *height); - -class LibretroCoreBinding : public GodotObject { - GDCLASS(LibretroCoreBinding, Object); - -private: - void *core_handle = nullptr; // Handle del core caricato - retro_init_t retro_init = nullptr; - retro_deinit_t retro_deinit = nullptr; - retro_load_game_t retro_load_game = nullptr; - retro_run_t retro_run = nullptr; - retro_get_video_frame_t retro_get_video_frame = nullptr; - - unsigned frame_width = 0; - unsigned frame_height = 0; - PackedByteArray frame_buffer; - -public: - bool initialize(const String &core_path) { - UtilityFunctions::print("Caricamento del core: ", core_path); - core_handle = dlopen(core_path.utf8().get_data(), RTLD_LAZY); - if (!core_handle) { - UtilityFunctions::print("Errore nel caricamento del core: ", dlerror()); - return false; - } - - // Collegamento delle funzioni - retro_init = (retro_init_t)dlsym(core_handle, "retro_init"); - retro_deinit = (retro_deinit_t)dlsym(core_handle, "retro_deinit"); - retro_load_game = (retro_load_game_t)dlsym(core_handle, "retro_load_game"); - retro_run = (retro_run_t)dlsym(core_handle, "retro_run"); - retro_get_video_frame = (retro_get_video_frame_t)dlsym(core_handle, "retro_get_video_frame"); - - if (!retro_init || !retro_deinit || !retro_load_game || !retro_run || !retro_get_video_frame) { - UtilityFunctions::print("Errore: funzioni mancanti nel core."); - dlclose(core_handle); - core_handle = nullptr; - return false; - } - - retro_init(); - UtilityFunctions::print("Core inizializzato con successo."); - return true; +bool LibretroCoreBinding::initialize(const String &core_path) { + UtilityFunctions::print("Loading core: ", core_path); + core_handle = dlopen(core_path.utf8().get_data(), RTLD_LAZY); + if (!core_handle) { + UtilityFunctions::print("Error loading core: ", dlerror()); + return false; } - bool load_game(const PackedByteArray &rom_data) { - if (!core_handle || !retro_load_game) { - UtilityFunctions::print("Errore: Core non inizializzato."); - return false; - } + // Link functions + retro_init = (retro_init_t)dlsym(core_handle, "retro_init"); + retro_deinit = (retro_deinit_t)dlsym(core_handle, "retro_deinit"); + retro_load_game = (retro_load_game_t)dlsym(core_handle, "retro_load_game"); + retro_run = (retro_run_t)dlsym(core_handle, "retro_run"); + retro_get_video_frame = (retro_get_video_frame_t)dlsym(core_handle, "retro_get_video_frame"); - // Salviamo temporaneamente il file ROM - String temp_rom_path = "/tmp/libretro_temp.rom"; - File *temp_file = File::open(temp_rom_path, File::WRITE); - temp_file->store_buffer(rom_data); - temp_file->close(); - memdelete(temp_file); - - bool result = retro_load_game(temp_rom_path.utf8().get_data()); - if (result) { - UtilityFunctions::print("ROM caricata con successo: ", temp_rom_path); - } else { - UtilityFunctions::print("Errore nel caricamento della ROM."); - } - - return result; + if (!retro_init || !retro_deinit || !retro_load_game || !retro_run || !retro_get_video_frame) { + UtilityFunctions::print("Error: Missing functions in core."); + dlclose(core_handle); + core_handle = nullptr; + return false; } - void run() { - if (!core_handle || !retro_run) { - UtilityFunctions::print("Errore: Core non inizializzato."); - return; - } + retro_init(); + UtilityFunctions::print("Core successfully initialized."); + return true; +} - retro_run(); +bool LibretroCoreBinding::load_game(const PackedByteArray &rom_data) { + if (!core_handle) { + UtilityFunctions::print("Error: Core not loaded."); + return false; } - PackedByteArray get_frame_buffer() { - if (!core_handle || !retro_get_video_frame) { - UtilityFunctions::print("Errore: Core non inizializzato."); - return PackedByteArray(); - } - - void *frame = nullptr; - retro_get_video_frame(&frame, &frame_width, &frame_height); - - frame_buffer.resize(frame_width * frame_height * 4); // Assumiamo formato RGBA - memcpy(frame_buffer.ptrw(), frame, frame_buffer.size()); - return frame_buffer; + // Save ROM to a temporary file + std::string temp_rom_path = "/tmp/libretro_temp.rom"; + std::ofstream temp_file(temp_rom_path, std::ios::binary); + if (!temp_file.is_open()) { + UtilityFunctions::print("Error: Unable to open temporary ROM file."); + return false; } - int get_frame_width() const { return frame_width; } - int get_frame_height() const { return frame_height; } -}; + // Write the ROM data to the file + temp_file.write(reinterpret_cast(rom_data.ptr()), rom_data.size()); + temp_file.close(); + + bool result = retro_load_game(temp_rom_path.c_str()); + if (result) { + UtilityFunctions::print("ROM successfully loaded: ", temp_rom_path.c_str()); + } else { + UtilityFunctions::print("Error: Failed to load ROM."); + } + + return result; +} + +void LibretroCoreBinding::run() { + if (!core_handle || !retro_run) { + UtilityFunctions::print("Error: Core not initialized."); + return; + } + + retro_run(); +} + +PackedByteArray LibretroCoreBinding::get_frame_buffer() { + if (!core_handle || !retro_get_video_frame) { + UtilityFunctions::print("Error: Core not initialized."); + return PackedByteArray(); + } + + void *frame = nullptr; + retro_get_video_frame(&frame, &frame_width, &frame_height); + + frame_buffer.resize(frame_width * frame_height * 4); // Assume RGBA format + memcpy(frame_buffer.ptrw(), frame, frame_buffer.size()); + return frame_buffer; +} + +int LibretroCoreBinding::get_frame_width() const { + return frame_width; +} + +int LibretroCoreBinding::get_frame_height() const { + return frame_height; +} diff --git a/libretro_binding/libretro_binding.h b/libretro_binding/libretro_binding.h index 088d0b3..942c108 100644 --- a/libretro_binding/libretro_binding.h +++ b/libretro_binding/libretro_binding.h @@ -1,12 +1,41 @@ -// libretro_binding.h -class LibretroCoreBinding : public GodotObject { +#ifndef LIBRETRO_CORE_BINDING_H +#define LIBRETRO_CORE_BINDING_H + +#include +#include +#include +#include +#include // Correct base class + +// Typedefs for libretro core functions +typedef void (*retro_init_t)(); +typedef void (*retro_deinit_t)(); +typedef bool (*retro_load_game_t)(const char *); +typedef void (*retro_run_t)(); +typedef void (*retro_get_video_frame_t)(void **, unsigned *, unsigned *); + +class LibretroCoreBinding : public godot::Object { + GDCLASS(LibretroCoreBinding, godot::Object); + +private: + void *core_handle = nullptr; + retro_init_t retro_init = nullptr; + retro_deinit_t retro_deinit = nullptr; + retro_load_game_t retro_load_game = nullptr; + retro_run_t retro_run = nullptr; + retro_get_video_frame_t retro_get_video_frame = nullptr; + + unsigned frame_width = 0; + unsigned frame_height = 0; + godot::PackedByteArray frame_buffer; + public: - // Metodi da esporre a GDScript - bool initialize(); - bool load_game(const PackedByteArray& rom_data); + bool initialize(const godot::String &core_path); + bool load_game(const godot::PackedByteArray &rom_data); void run(); - PackedByteArray get_frame_buffer(); - int get_frame_width(); - int get_frame_height(); - void handle_input(const Ref& event); + godot::PackedByteArray get_frame_buffer(); + int get_frame_width() const; + int get_frame_height() const; }; + +#endif // LIBRETRO_CORE_BINDING_H