This commit is contained in:
Crunch (Chaz9) 2024-09-29 22:42:05 +01:00
parent e018a2875c
commit 6c81b5b067
3 changed files with 193 additions and 27 deletions

85
bug_fixes_plan.md Normal file
View file

@ -0,0 +1,85 @@
# Suyu Bug Fixes Plan
## 1. Game-specific issues
### Approach:
- Analyze logs and crash reports for the affected games (e.g., Echoes of Wisdom, Tears of the Kingdom, Shin Megami Tensei V).
- Identify common patterns or specific hardware/API calls causing issues.
- Implement game-specific workarounds if necessary.
### TODO:
- [ ] Review game-specific issues in the issue tracker
- [ ] Analyze logs and crash reports
- [ ] Implement fixes for each game
- [ ] Test fixes thoroughly
## 2. Crashes
### Approach:
- Implement better error handling and logging throughout the codebase.
- Add more robust null checks and boundary checks.
- Review and optimize memory management.
### TODO:
- [ ] Implement a centralized error handling system
- [ ] Add more detailed logging for crash-prone areas
- [ ] Review and improve memory management in core emulation components
## 3. Shader caching and performance issues
### Approach:
- Optimize shader compilation process.
- Implement background shader compilation to reduce stuttering.
- Review and optimize the caching mechanism.
### TODO:
- [ ] Profile shader compilation and identify bottlenecks
- [ ] Implement asynchronous shader compilation
- [ ] Optimize shader cache storage and retrieval
- [ ] Implement shader pre-caching for known games
## 4. Missing features
### Approach:
- Prioritize missing features based on user demand and technical feasibility.
- Implement support for additional file formats (NSZ, XCZ).
- Add custom save data folder selection.
### TODO:
- [ ] Implement NSZ and XCZ file format support
- [ ] Add UI option for custom save data folder selection
- [ ] Update relevant documentation
## 5. Add-ons and mods issues
### Approach:
- Review the current implementation of add-ons and mods support.
- Implement a more robust system for managing and applying mods.
- Improve compatibility checks for mods.
### TODO:
- [ ] Review and refactor the current mod system
- [ ] Implement better mod management UI
- [ ] Add compatibility checks for mods
- [ ] Improve documentation for mod creators
## 6. General optimization
### Approach:
- Profile the emulator to identify performance bottlenecks.
- Optimize core emulation components.
- Implement multi-threading where appropriate.
### TODO:
- [ ] Conduct thorough profiling of the emulator
- [ ] Optimize CPU-intensive operations
- [ ] Implement or improve multi-threading in suitable components
- [ ] Review and optimize memory usage
## Testing and Quality Assurance
- Implement a comprehensive test suite for core emulation components.
- Set up continuous integration to run tests automatically.
- Establish a structured QA process for testing game compatibility and performance.
Remember to update the relevant documentation and changelog after implementing these fixes. Prioritize the issues based on their impact on user experience and the number of affected users.

View file

@ -1,11 +1,13 @@
#include "core/libretro_wrapper.h"
#include "nintendo_library/nintendo_library.h"
#include <dlfcn.h>
#include <stdexcept>
#include <cstring>
#include <iostream>
namespace Core {
LibretroWrapper::LibretroWrapper() : core_handle(nullptr) {}
LibretroWrapper::LibretroWrapper() : core_handle(nullptr), nintendo_library(std::make_unique<Nintendo::Library>()) {}
LibretroWrapper::~LibretroWrapper() {
Unload();
@ -14,36 +16,42 @@ LibretroWrapper::~LibretroWrapper() {
bool LibretroWrapper::LoadCore(const std::string& core_path) {
core_handle = dlopen(core_path.c_str(), RTLD_LAZY);
if (!core_handle) {
std::cerr << "Failed to load libretro core: " << dlerror() << std::endl;
return false;
}
// Load libretro core functions
retro_init = reinterpret_cast<void (*)()>(dlsym(core_handle, "retro_init"));
retro_deinit = reinterpret_cast<void (*)()>(dlsym(core_handle, "retro_deinit"));
retro_api_version = reinterpret_cast<unsigned (*)()>(dlsym(core_handle, "retro_api_version"));
retro_get_system_info = reinterpret_cast<void (*)(struct retro_system_info*)>(dlsym(core_handle, "retro_get_system_info"));
retro_get_system_av_info = reinterpret_cast<void (*)(struct retro_system_av_info*)>(dlsym(core_handle, "retro_get_system_av_info"));
retro_set_environment = reinterpret_cast<void (*)(retro_environment_t)>(dlsym(core_handle, "retro_set_environment"));
retro_set_video_refresh = reinterpret_cast<void (*)(retro_video_refresh_t)>(dlsym(core_handle, "retro_set_video_refresh"));
retro_set_audio_sample = reinterpret_cast<void (*)(retro_audio_sample_t)>(dlsym(core_handle, "retro_set_audio_sample"));
retro_set_audio_sample_batch = reinterpret_cast<void (*)(retro_audio_sample_batch_t)>(dlsym(core_handle, "retro_set_audio_sample_batch"));
retro_set_input_poll = reinterpret_cast<void (*)(retro_input_poll_t)>(dlsym(core_handle, "retro_set_input_poll"));
retro_set_input_state = reinterpret_cast<void (*)(retro_input_state_t)>(dlsym(core_handle, "retro_set_input_state"));
retro_set_controller_port_device = reinterpret_cast<void (*)(unsigned, unsigned)>(dlsym(core_handle, "retro_set_controller_port_device"));
retro_reset = reinterpret_cast<void (*)()>(dlsym(core_handle, "retro_reset"));
retro_run = reinterpret_cast<void (*)()>(dlsym(core_handle, "retro_run"));
retro_serialize_size = reinterpret_cast<size_t (*)()>(dlsym(core_handle, "retro_serialize_size"));
retro_serialize = reinterpret_cast<bool (*)(void*, size_t)>(dlsym(core_handle, "retro_serialize"));
retro_unserialize = reinterpret_cast<bool (*)(const void*, size_t)>(dlsym(core_handle, "retro_unserialize"));
retro_load_game = reinterpret_cast<bool (*)(const struct retro_game_info*)>(dlsym(core_handle, "retro_load_game"));
retro_unload_game = reinterpret_cast<void (*)()>(dlsym(core_handle, "retro_unload_game"));
#define LOAD_SYMBOL(S) S = reinterpret_cast<decltype(S)>(dlsym(core_handle, #S)); \
if (!S) { \
std::cerr << "Failed to load symbol " #S ": " << dlerror() << std::endl; \
Unload(); \
return false; \
}
if (!retro_init || !retro_deinit || !retro_api_version || !retro_get_system_info ||
!retro_get_system_av_info || !retro_set_environment || !retro_set_video_refresh ||
!retro_set_audio_sample || !retro_set_audio_sample_batch || !retro_set_input_poll ||
!retro_set_input_state || !retro_set_controller_port_device || !retro_reset ||
!retro_run || !retro_serialize_size || !retro_serialize || !retro_unserialize ||
!retro_load_game || !retro_unload_game) {
LOAD_SYMBOL(retro_init)
LOAD_SYMBOL(retro_deinit)
LOAD_SYMBOL(retro_api_version)
LOAD_SYMBOL(retro_get_system_info)
LOAD_SYMBOL(retro_get_system_av_info)
LOAD_SYMBOL(retro_set_environment)
LOAD_SYMBOL(retro_set_video_refresh)
LOAD_SYMBOL(retro_set_audio_sample)
LOAD_SYMBOL(retro_set_audio_sample_batch)
LOAD_SYMBOL(retro_set_input_poll)
LOAD_SYMBOL(retro_set_input_state)
LOAD_SYMBOL(retro_set_controller_port_device)
LOAD_SYMBOL(retro_reset)
LOAD_SYMBOL(retro_run)
LOAD_SYMBOL(retro_serialize_size)
LOAD_SYMBOL(retro_serialize)
LOAD_SYMBOL(retro_unserialize)
LOAD_SYMBOL(retro_load_game)
LOAD_SYMBOL(retro_unload_game)
#undef LOAD_SYMBOL
if (!nintendo_library->Initialize()) {
std::cerr << "Failed to initialize Nintendo Library" << std::endl;
Unload();
return false;
}
@ -54,6 +62,7 @@ bool LibretroWrapper::LoadCore(const std::string& core_path) {
bool LibretroWrapper::LoadGame(const std::string& game_path) {
if (!core_handle) {
std::cerr << "Libretro core not loaded" << std::endl;
return false;
}
@ -62,18 +71,34 @@ bool LibretroWrapper::LoadGame(const std::string& game_path) {
game_info.size = 0;
game_info.meta = nullptr;
return retro_load_game(&game_info);
if (!retro_load_game(&game_info)) {
std::cerr << "Failed to load game through libretro" << std::endl;
return false;
}
if (!nintendo_library->LoadROM(game_path)) {
std::cerr << "Failed to load ROM through Nintendo Library" << std::endl;
return false;
}
return true;
}
void LibretroWrapper::Run() {
if (core_handle) {
retro_run();
nintendo_library->RunFrame();
} else {
std::cerr << "Cannot run: Libretro core not loaded" << std::endl;
}
}
void LibretroWrapper::Reset() {
if (core_handle) {
retro_reset();
// Add any necessary reset logic for Nintendo Library
} else {
std::cerr << "Cannot reset: Libretro core not loaded" << std::endl;
}
}
@ -84,6 +109,9 @@ void LibretroWrapper::Unload() {
dlclose(core_handle);
core_handle = nullptr;
}
nintendo_library->Shutdown();
}
// Add implementations for other libretro functions as needed
} // namespace Core

View file

@ -0,0 +1,53 @@
#pragma once
#include <string>
#include <memory>
// Forward declaration
namespace Nintendo {
class Library;
}
struct retro_game_info;
namespace Core {
class LibretroWrapper {
public:
LibretroWrapper();
~LibretroWrapper();
bool LoadCore(const std::string& core_path);
bool LoadGame(const std::string& game_path);
void Run();
void Reset();
void Unload();
private:
void* core_handle;
retro_game_info game_info;
std::unique_ptr<Nintendo::Library> nintendo_library;
// Libretro function pointers
void (*retro_init)();
void (*retro_deinit)();
unsigned (*retro_api_version)();
void (*retro_get_system_info)(struct retro_system_info *info);
void (*retro_get_system_av_info)(struct retro_system_av_info *info);
void (*retro_set_environment)(void (*)(unsigned, const char*));
void (*retro_set_video_refresh)(void (*)(const void*, unsigned, unsigned, size_t));
void (*retro_set_audio_sample)(void (*)(int16_t, int16_t));
void (*retro_set_audio_sample_batch)(size_t (*)(const int16_t*, size_t));
void (*retro_set_input_poll)(void (*)());
void (*retro_set_input_state)(int16_t (*)(unsigned, unsigned, unsigned, unsigned));
void (*retro_set_controller_port_device)(unsigned, unsigned);
void (*retro_reset)();
void (*retro_run)();
size_t (*retro_serialize_size)();
bool (*retro_serialize)(void*, size_t);
bool (*retro_unserialize)(const void*, size_t);
bool (*retro_load_game)(const struct retro_game_info*);
void (*retro_unload_game)();
};
} // namespace Core