mirror of
https://github.com/RetroDECK/RetroQUEST.git
synced 2025-04-21 01:24:06 +00:00
Checkpoint
This commit is contained in:
parent
6f7436e8d1
commit
c0d9fbd31f
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,12 +1,9 @@
|
||||||
# Godot 4+ specific ignores
|
# Godot 4+ specific ignores
|
||||||
.godot/
|
.godot/
|
||||||
/android/
|
/android/
|
||||||
addons/gdretroplay/build_linux
|
|
||||||
roms
|
roms
|
||||||
cores
|
cores
|
||||||
assets
|
assets
|
||||||
godot-cpp
|
godot-cpp
|
||||||
.sconsign.dblite
|
.sconsign.dblite
|
||||||
libretro_binding/libretro_binding.os
|
gdlibretro
|
||||||
libretro_binding/libretro_binding.so
|
|
||||||
.sconsign.dblite
|
|
||||||
|
|
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,3 +0,0 @@
|
||||||
[submodule "external/gdlibretro"]
|
|
||||||
path = external/gdlibretro
|
|
||||||
url = https://github.com/gabrielmedici/gdlibretro
|
|
BIN
.sconsign.dblite
BIN
.sconsign.dblite
Binary file not shown.
76
.vscode/settings.json
vendored
Normal file
76
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"any": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"bit": "cpp",
|
||||||
|
"*.tcc": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"charconv": "cpp",
|
||||||
|
"chrono": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"codecvt": "cpp",
|
||||||
|
"compare": "cpp",
|
||||||
|
"concepts": "cpp",
|
||||||
|
"condition_variable": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"forward_list": "cpp",
|
||||||
|
"list": "cpp",
|
||||||
|
"map": "cpp",
|
||||||
|
"set": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"unordered_set": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"format": "cpp",
|
||||||
|
"fstream": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iomanip": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"iostream": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"mutex": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"numbers": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"semaphore": "cpp",
|
||||||
|
"span": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"stdfloat": "cpp",
|
||||||
|
"stop_token": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"text_encoding": "cpp",
|
||||||
|
"thread": "cpp",
|
||||||
|
"cinttypes": "cpp",
|
||||||
|
"typeinfo": "cpp",
|
||||||
|
"valarray": "cpp",
|
||||||
|
"variant": "cpp"
|
||||||
|
}
|
||||||
|
}
|
10
addons/LibRetroHost.gdextension
Normal file
10
addons/LibRetroHost.gdextension
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[configuration]
|
||||||
|
|
||||||
|
entry_symbol = "GDExtensionInit"
|
||||||
|
compatibility_minimum = 4.1
|
||||||
|
|
||||||
|
[libraries]
|
||||||
|
windows.release.x86_64 = "lib/Windows-AMD64/LibRetroHost-d.dll"
|
||||||
|
windows.debug.x86_64 = "lib/Windows-AMD64/LibRetroHost-d.dll"
|
||||||
|
linux.release.x86_64 = "res://addons/libLibRetroHost-d.so"
|
||||||
|
linux.debug.x86_64 = "res://addons/libLibRetroHost-d.so"
|
BIN
addons/libLibRetroHost-d.so
Executable file
BIN
addons/libLibRetroHost-d.so
Executable file
Binary file not shown.
9
build_gdlibretro.sh
Executable file
9
build_gdlibretro.sh
Executable file
|
@ -0,0 +1,9 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
git clone https://github.com/gabrielmedici/gdlibretro
|
||||||
|
cd gdlibretro
|
||||||
|
git submodule update --init --recursive
|
||||||
|
cmake -DNO_GIT_REVISION=ON -DCMAKE_BUILD_TYPE=Debug -DLINUX=true -DCMAKE_CXX_FLAGS="-DLINUX" .
|
||||||
|
cmake --build .
|
||||||
|
cd -
|
||||||
|
mv -fv "gdlibretro/LibRetroHost/lib/Linux-x86_64/libLibRetroHost-d.so" "addons"
|
|
@ -1,9 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [ ! -d "godot-cpp" ]; then git clone https://github.com/godotengine/godot-cpp.git; fi
|
|
||||||
cd godot-cpp
|
|
||||||
git pull
|
|
||||||
git submodule update --init --recursive
|
|
||||||
scons platform=linux generate_bindings=yes -j$(nproc)
|
|
||||||
cd ..
|
|
||||||
scons platform=linux -j$(nproc)
|
|
1
external/gdlibretro
vendored
1
external/gdlibretro
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 7ebbf840187f54466988c0b5b20524ad21ca1d58
|
|
|
@ -1,16 +0,0 @@
|
||||||
Import('env')
|
|
||||||
|
|
||||||
# Configurazione di compilazione
|
|
||||||
env_shared = env.Clone()
|
|
||||||
env_shared.Prepend(CPPPATH=[
|
|
||||||
'#godot-cpp/include',
|
|
||||||
'#godot-cpp/include/core',
|
|
||||||
'#godot-cpp/include/gen',
|
|
||||||
'#godot-cpp/gen/include',
|
|
||||||
'#godot-cpp/gdextension',
|
|
||||||
'#godot-cpp/include/godot_cpp'
|
|
||||||
])
|
|
||||||
env_shared.Append(LIBS=['dl']) # Libreria per caricamento dinamico
|
|
||||||
|
|
||||||
# Compilazione del modulo come libreria condivisa
|
|
||||||
env_shared.SharedLibrary(target='libretro_binding', source=['libretro_binding.cpp'])
|
|
|
@ -1,93 +0,0 @@
|
||||||
#include "libretro_binding.h"
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <godot_cpp/core/class_db.hpp>
|
|
||||||
#include <godot_cpp/variant/utility_functions.hpp>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
using namespace godot;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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");
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
retro_init();
|
|
||||||
UtilityFunctions::print("Core successfully initialized.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LibretroCoreBinding::load_game(const PackedByteArray &rom_data) {
|
|
||||||
if (!core_handle) {
|
|
||||||
UtilityFunctions::print("Error: Core not loaded.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the ROM data to the file
|
|
||||||
temp_file.write(reinterpret_cast<const char *>(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;
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"entry_class": "LibretroCoreBinding",
|
|
||||||
"library_path": "res://libretro_binding/libretro_binding.so",
|
|
||||||
"singleton": false,
|
|
||||||
"autoload": false
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
#ifndef LIBRETRO_CORE_BINDING_H
|
|
||||||
#define LIBRETRO_CORE_BINDING_H
|
|
||||||
|
|
||||||
#include <godot_cpp/core/class_db.hpp>
|
|
||||||
#include <godot_cpp/variant/utility_functions.hpp>
|
|
||||||
#include <godot_cpp/variant/packed_byte_array.hpp>
|
|
||||||
#include <godot_cpp/classes/ref.hpp>
|
|
||||||
#include <godot_cpp/classes/object.hpp> // 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:
|
|
||||||
bool initialize(const godot::String &core_path);
|
|
||||||
bool load_game(const godot::PackedByteArray &rom_data);
|
|
||||||
void run();
|
|
||||||
godot::PackedByteArray get_frame_buffer();
|
|
||||||
int get_frame_width() const;
|
|
||||||
int get_frame_height() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // LIBRETRO_CORE_BINDING_H
|
|
|
@ -1,9 +0,0 @@
|
||||||
#include "libretro_binding.h"
|
|
||||||
|
|
||||||
void register_libretro_core_binding_types() {
|
|
||||||
ClassDB::register_class<LibretroCoreBinding>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void unregister_libretro_core_binding_types() {
|
|
||||||
// Non necessario per ora
|
|
||||||
}
|
|
40
main.gd
40
main.gd
|
@ -1,26 +1,26 @@
|
||||||
extends Node3D
|
extends Node
|
||||||
|
|
||||||
var xr_interface: XRInterface
|
@onready var loader = preload("res://scripts/libretro_loader.gd").new()
|
||||||
var emulator_script: Object
|
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
# Inizializzazione OpenXR
|
var core_path = "res://cores/genesis_plus_gx_libretro.so" # Replace with your actual core path
|
||||||
xr_interface = XRServer.find_interface("OpenXR")
|
var rom_path = "res://roms/megadrive/Sonic the Hedgehog.bin" # Replace with your actual ROM path
|
||||||
if xr_interface and xr_interface.is_initialized():
|
|
||||||
print("OpenXR initialized successfully")
|
print("Core path: ", core_path)
|
||||||
DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED)
|
print("ROM path: ", rom_path)
|
||||||
get_viewport().use_xr = true
|
|
||||||
|
var success = await loader.start_emulation(core_path, rom_path) # Use await to call the coroutine
|
||||||
|
if success:
|
||||||
|
print("Game started successfully.")
|
||||||
|
start_emulation_loop()
|
||||||
else:
|
else:
|
||||||
print("OpenXR not initialized, please check if your headset is connected")
|
print("Failed to start the game.")
|
||||||
|
|
||||||
# Carica lo script dell'emulatore
|
func start_emulation_loop():
|
||||||
emulator_script = preload("res://scripts/emulate.gd").new()
|
"""
|
||||||
|
Continuously runs the emulation in the `_process` callback.
|
||||||
|
"""
|
||||||
|
set_process(true)
|
||||||
|
|
||||||
func launch_game():
|
func _process(delta):
|
||||||
var core_path = "res://cores/genesis_plus_gx_libretro.so"
|
loader._process(delta) # Delegate the frame updates to the loader
|
||||||
var rom_path = "res://roms/megadrive/Sonic the Hedgehog.bin"
|
|
||||||
|
|
||||||
if emulator_script.start_game(core_path, rom_path):
|
|
||||||
print("Il gioco è stato avviato con successo!")
|
|
||||||
else:
|
|
||||||
print("Errore durante l'avvio del gioco.")
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ enabled=PackedStringArray("res://addons/godot-xr-tools/plugin.cfg")
|
||||||
|
|
||||||
[gd_extension]
|
[gd_extension]
|
||||||
|
|
||||||
extensions=PackedStringArray("res://libretro_binding/libretro_binding.gdextension")
|
extensions=PackedStringArray("res://addons/LibRetroHost.gdextension")
|
||||||
|
|
||||||
[rendering]
|
[rendering]
|
||||||
|
|
||||||
|
|
51
prompt.sh
Executable file
51
prompt.sh
Executable file
|
@ -0,0 +1,51 @@
|
||||||
|
clear
|
||||||
|
rm "prompt.md"
|
||||||
|
|
||||||
|
write(){
|
||||||
|
echo "$1" >> ./prompt.md
|
||||||
|
}
|
||||||
|
|
||||||
|
write "RetroQUEST is an application mainly written for Meta Quest 3 with Linux non-VR support in Godot 4.3.
|
||||||
|
In the future will be added supporto for Widnows, Mac and other VRs as well.
|
||||||
|
The app is working mainly with VR controls but can be used even with desktop controls (mouse, keyboard, controllers).
|
||||||
|
The app is Quest Native and not PCVR."
|
||||||
|
|
||||||
|
write "The scope of this application is to emulate games and render them on a virtual CRT TV in the VR space, more features will be added later."
|
||||||
|
write "The first iteration will be to be able to run the rom "roms/megadrive/Sonic the Hedgehog.bin" with the libretro core "cores/genesis_plus_gx_libretro.so", more features will be added later, for now I will be happy to see the game just running."
|
||||||
|
write "For this scope I am using gdlibretro (https://github.com/gabrielmedici/gdlibretro) with some modifications to make it work on Linux and Android."
|
||||||
|
|
||||||
|
write "Here is my directory structure"
|
||||||
|
write "$(tree . -L 2)"
|
||||||
|
|
||||||
|
write "Now I will cat you the main files for you to understand better the project."
|
||||||
|
|
||||||
|
files="project.godot main.tscn scripts/emulate.gd scripts/libretro_loader.gd addons/gdlibretro.gdextension addons/LibRetroHost.gdextension gdlibretro/src/CoreEnvironment.cpp gdlibretro/src/RetroHost.cpp gdlibretro/src/RetroHost.hpp gdlibretro/src/Video.cpp gdlibretro/src/RegisterExtension.cpp gdlibretro/src/CMakeLists.txt"
|
||||||
|
|
||||||
|
for file in $files; do
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
write "--- $file ---"
|
||||||
|
write "$(cat $file)"
|
||||||
|
write "--- end of $file ---"
|
||||||
|
write ""
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
write ""
|
||||||
|
write "My issue now is the following, can you help me to fix it?"
|
||||||
|
write "Godot says:
|
||||||
|
[RetroHost] Constructor
|
||||||
|
core/extension/gdextension.cpp:1011 - No GDExtension library found for current OS and architecture (linux.x86_64) in configuration file: res://gdlibretro/LibRetroHost/LibRetroHost.gdextension
|
||||||
|
Failed loading resource: res://gdlibretro/LibRetroHost/LibRetroHost.gdextension. Make sure resources have been imported by opening the project in the editor at least once.
|
||||||
|
Core path: res://cores/genesis_plus_gx_libretro.so
|
||||||
|
ROM path: res://roms/megadrive/Sonic the Hedgehog.bin
|
||||||
|
Starting emulation with core: res://cores/genesis_plus_gx_libretro.so, ROM: res://roms/megadrive/Sonic the Hedgehog.bin
|
||||||
|
Loading core...
|
||||||
|
Failed to start the game.
|
||||||
|
--- Debugging process stopped ---
|
||||||
|
core/extension/gdextension.cpp:1011 - No GDExtension library found for current OS and architecture (linux.x86_64) in configuration file: res://gdlibretro/LibRetroHost/LibRetroHost.gdextension
|
||||||
|
Failed loading resource: res://gdlibretro/LibRetroHost/LibRetroHost.gdextension. Make sure resources have been imported by opening the project in the editor at least once.
|
||||||
|
core/extension/gdextension.cpp:1011 - No GDExtension library found for current OS and architecture (linux.x86_64) in configuration file: res://gdlibretro/LibRetroHost/LibRetroHost.gdextension
|
||||||
|
Failed loading resource: res://gdlibretro/LibRetroHost/LibRetroHost.gdextension. Make sure resources have been imported by opening the project in the editor at least once.
|
||||||
|
"
|
||||||
|
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
extends Node
|
|
||||||
|
|
||||||
var libretro_core = LibretroCoreBinding.new() # Use the class directly
|
|
||||||
|
|
||||||
func start_game(core_path: String, rom_path: String) -> bool:
|
|
||||||
"""
|
|
||||||
Inizializza il core libretro e carica la ROM specificata.
|
|
||||||
Restituisce true se il gioco è stato caricato correttamente, altrimenti false.
|
|
||||||
"""
|
|
||||||
# Carica il gestore libretro
|
|
||||||
var libretro_handler = preload("res://scripts/libretro_loader.gd").new()
|
|
||||||
|
|
||||||
# Inizializzazione del core
|
|
||||||
if not libretro_handler.initialize(core_path):
|
|
||||||
print("Errore: impossibile caricare il core libretro:", core_path)
|
|
||||||
return false
|
|
||||||
|
|
||||||
print("Core caricato con successo:", core_path)
|
|
||||||
|
|
||||||
# Caricamento della ROM
|
|
||||||
var rom_data: PackedByteArray = load_rom_data(rom_path)
|
|
||||||
if not libretro_handler.load_game(rom_data):
|
|
||||||
print("Errore: impossibile caricare la ROM:", rom_path)
|
|
||||||
return false
|
|
||||||
|
|
||||||
print("Gioco caricato con successo:", rom_path)
|
|
||||||
return true
|
|
||||||
|
|
||||||
func load_rom_data(rom_path: String) -> PackedByteArray:
|
|
||||||
"""
|
|
||||||
Carica i dati di una ROM da file.
|
|
||||||
"""
|
|
||||||
var file = FileAccess.open(rom_path, FileAccess.READ)
|
|
||||||
if not file:
|
|
||||||
push_error("Error opening file: " + rom_path)
|
|
||||||
return PackedByteArray()
|
|
||||||
|
|
||||||
var data = file.get_buffer(file.get_length())
|
|
||||||
file.close()
|
|
||||||
return data
|
|
||||||
|
|
||||||
func initialize_core(core_path: String) -> bool:
|
|
||||||
if not libretro_core.initialize(core_path):
|
|
||||||
print("Errore: impossibile caricare il core libretro")
|
|
||||||
return false
|
|
||||||
return true
|
|
54
scripts/emulate.gd.old
Normal file
54
scripts/emulate.gd.old
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
# Reference to the LibRetroHost singleton
|
||||||
|
@onready var libretro_core = Engine.get_singleton("RetroHost")
|
||||||
|
|
||||||
|
func start_game(core_path: String, rom_path: String) -> bool:
|
||||||
|
"""
|
||||||
|
Initializes the LibRetro core and loads the specified ROM.
|
||||||
|
Returns true if the game is loaded successfully, otherwise false.
|
||||||
|
"""
|
||||||
|
if not libretro_core.load_core(core_path):
|
||||||
|
push_error("Error: Unable to load LibRetro core: " + core_path)
|
||||||
|
return false
|
||||||
|
|
||||||
|
print("Core loaded successfully:", core_path)
|
||||||
|
|
||||||
|
if not FileAccess.file_exists(rom_path):
|
||||||
|
push_error("Error: ROM not found: " + rom_path)
|
||||||
|
return false
|
||||||
|
|
||||||
|
var rom_data = load_rom_data(rom_path)
|
||||||
|
if rom_data.is_empty():
|
||||||
|
push_error("Error: Unable to load ROM data: " + rom_path)
|
||||||
|
return false
|
||||||
|
|
||||||
|
if not libretro_core.load_game_from_memory(rom_data):
|
||||||
|
push_error("Error: Unable to load game ROM: " + rom_path)
|
||||||
|
return false
|
||||||
|
|
||||||
|
print("Game loaded successfully:", rom_path)
|
||||||
|
return true
|
||||||
|
|
||||||
|
func load_rom_data(rom_path: String) -> PackedByteArray:
|
||||||
|
"""
|
||||||
|
Loads the ROM data from a file.
|
||||||
|
"""
|
||||||
|
var file = FileAccess.open(rom_path, FileAccess.READ)
|
||||||
|
if not file:
|
||||||
|
push_error("Error: Unable to open ROM file: " + rom_path)
|
||||||
|
return PackedByteArray()
|
||||||
|
|
||||||
|
var rom_data = file.get_buffer(file.get_length())
|
||||||
|
file.close()
|
||||||
|
return rom_data
|
||||||
|
|
||||||
|
func run():
|
||||||
|
"""
|
||||||
|
Starts the emulation loop.
|
||||||
|
"""
|
||||||
|
if not libretro_core:
|
||||||
|
push_error("Error: LibRetroHost is not initialized.")
|
||||||
|
return
|
||||||
|
|
||||||
|
libretro_core.run()
|
|
@ -1,57 +1,98 @@
|
||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
@onready var tv_viewport: SubViewport = $CRTTV/SubViewport
|
@onready var sub_viewport = $room/SubViewport
|
||||||
@onready var tv_texture_rect: TextureRect = $CRTTV/SubViewport/TextureRect
|
@onready var texture_rect = $room/SubViewport/TextureRect
|
||||||
|
|
||||||
var current_core = null
|
var current_core : Object = null # The emulator core (passed dynamically)
|
||||||
var current_rom = null
|
var current_rom : String = "" # Initialize to an empty string
|
||||||
|
|
||||||
func load_libretro_core(core_path: String) -> bool:
|
|
||||||
current_core = load(core_path)
|
|
||||||
if not current_core:
|
|
||||||
push_error("Failed to load core: " + core_path)
|
|
||||||
return false
|
|
||||||
current_core.initialize()
|
|
||||||
return true
|
|
||||||
|
|
||||||
func load_rom(rom_path: String) -> bool:
|
|
||||||
if not FileAccess.file_exists(rom_path):
|
|
||||||
push_error("ROM not found: " + rom_path)
|
|
||||||
return false
|
|
||||||
|
|
||||||
var file = FileAccess.open(rom_path, FileAccess.READ)
|
|
||||||
if not file:
|
|
||||||
push_error("Error opening ROM: " + rom_path)
|
|
||||||
return false
|
|
||||||
|
|
||||||
var rom_data = file.get_buffer(file.get_length())
|
|
||||||
file.close()
|
|
||||||
|
|
||||||
if not current_core.load_game(rom_data):
|
|
||||||
push_error("Failed to load ROM: " + rom_path)
|
|
||||||
return false
|
|
||||||
|
|
||||||
current_rom = rom_path
|
|
||||||
return true
|
|
||||||
|
|
||||||
func start_emulation(core_path: String, rom_path: String) -> bool:
|
func start_emulation(core_path: String, rom_path: String) -> bool:
|
||||||
if not load_libretro_core(core_path):
|
print("Starting emulation with core: ", core_path, ", ROM: ", rom_path)
|
||||||
return false
|
|
||||||
if not load_rom(rom_path):
|
if not core_path or not rom_path:
|
||||||
return false
|
push_error("Core path or ROM path is missing.")
|
||||||
current_core.run()
|
return false
|
||||||
return true
|
|
||||||
|
# Load the core (emulator)
|
||||||
|
print("Loading core...")
|
||||||
|
current_core = load(core_path)
|
||||||
|
if not current_core:
|
||||||
|
push_error("Failed to load core: " + core_path)
|
||||||
|
return false
|
||||||
|
print("Core loaded successfully.")
|
||||||
|
|
||||||
|
current_core.initialize()
|
||||||
|
|
||||||
|
# Load the ROM
|
||||||
|
print("Checking ROM file...")
|
||||||
|
if not FileAccess.file_exists(rom_path):
|
||||||
|
push_error("ROM not found: " + rom_path)
|
||||||
|
return false
|
||||||
|
print("ROM file exists.")
|
||||||
|
|
||||||
|
var file = FileAccess.open(rom_path, FileAccess.READ)
|
||||||
|
if not file:
|
||||||
|
push_error("Error opening ROM: " + rom_path)
|
||||||
|
return false
|
||||||
|
print("ROM file opened successfully.")
|
||||||
|
|
||||||
|
var rom_data = file.get_buffer(file.get_length())
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
if not current_core.load_game(rom_data):
|
||||||
|
push_error("Failed to load ROM: " + rom_path)
|
||||||
|
return false
|
||||||
|
print("ROM loaded successfully.")
|
||||||
|
|
||||||
|
current_rom = rom_path
|
||||||
|
print("Core and ROM loaded successfully.")
|
||||||
|
|
||||||
|
# Wait for SubViewport to render at least one frame
|
||||||
|
sub_viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
|
||||||
|
await get_tree().create_timer(0.1).timeout # Delay ensures rendering starts
|
||||||
|
|
||||||
|
# Assign the SubViewport texture
|
||||||
|
var viewport_texture = sub_viewport.get_texture()
|
||||||
|
if viewport_texture:
|
||||||
|
texture_rect.texture = viewport_texture
|
||||||
|
print("SubViewport texture assigned successfully.")
|
||||||
|
else:
|
||||||
|
push_error("Error: SubViewport texture is not ready.")
|
||||||
|
return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
func _process(delta):
|
func _process(delta):
|
||||||
if current_core:
|
"""
|
||||||
var frame_data = current_core.get_frame_buffer()
|
Dynamically updates the TextureRect's texture during runtime.
|
||||||
if frame_data:
|
"""
|
||||||
var image = Image.create_from_data(
|
if current_core:
|
||||||
current_core.get_frame_width(),
|
current_core.run()
|
||||||
current_core.get_frame_height(),
|
|
||||||
false,
|
var frame_data = current_core.get_frame_buffer()
|
||||||
Image.FORMAT_RGB8,
|
if frame_data:
|
||||||
frame_data
|
var frame_width = current_core.get_frame_width()
|
||||||
)
|
var frame_height = current_core.get_frame_height()
|
||||||
var texture = ImageTexture.create_from_image(image)
|
|
||||||
tv_texture_rect.texture = texture
|
if frame_width > 0 and frame_height > 0:
|
||||||
|
var image = Image.create_from_data(
|
||||||
|
frame_width,
|
||||||
|
frame_height,
|
||||||
|
false,
|
||||||
|
Image.FORMAT_RGB8,
|
||||||
|
frame_data
|
||||||
|
)
|
||||||
|
var texture = ImageTexture.create_from_image(image)
|
||||||
|
texture_rect.texture = texture
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
"""
|
||||||
|
Initializes the SubViewport and TextureRect.
|
||||||
|
"""
|
||||||
|
if sub_viewport and texture_rect:
|
||||||
|
print("SubViewport and TextureRect initialized successfully.")
|
||||||
|
else:
|
||||||
|
push_error("Error: SubViewport or TextureRect is missing.")
|
||||||
|
|
||||||
|
# Ensure SubViewport always renders
|
||||||
|
sub_viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
|
||||||
|
|
Loading…
Reference in a new issue