Renders the emulator framebuffer into a calculated sub-rect with nearest-neighbor scaling and black bars, driven by the core's reported aspect ratio. Adds a cycle button in the game HUD and a display mode setting in the settings screen.
125 lines
4.1 KiB
C++
125 lines
4.1 KiB
C++
#pragma once
|
|
|
|
#include "libretro.h"
|
|
#include "audio_engine.h"
|
|
|
|
#include <android/native_window.h>
|
|
#include <atomic>
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <thread>
|
|
#include <unordered_map>
|
|
|
|
enum class DisplayMode : int {
|
|
STRETCH = 0,
|
|
ASPECT_RATIO = 1,
|
|
INTEGER_SCALE = 2
|
|
};
|
|
|
|
class LibretroFrontend {
|
|
public:
|
|
static LibretroFrontend& instance();
|
|
|
|
bool loadCore(const char* soPath);
|
|
bool loadGame(const char* romPath);
|
|
void start();
|
|
void pause();
|
|
void resume();
|
|
void stop();
|
|
void reset();
|
|
|
|
void setWindow(ANativeWindow* window);
|
|
void releaseWindow();
|
|
|
|
void setButtonState(uint16_t state);
|
|
void setAnalogState(int stick, int16_t x, int16_t y);
|
|
|
|
bool saveState(const char* path);
|
|
bool loadState(const char* path);
|
|
|
|
void setAudioEnabled(bool enabled);
|
|
void setFrameSkip(int skip);
|
|
void setDisplayMode(int mode);
|
|
|
|
void setSystemDir(const char* dir);
|
|
void setSaveDir(const char* dir);
|
|
|
|
bool isRunning() const { return running_.load(); }
|
|
|
|
private:
|
|
LibretroFrontend() = default;
|
|
~LibretroFrontend();
|
|
|
|
void runLoop();
|
|
void unloadCore();
|
|
|
|
// Libretro callbacks (static because libretro uses C function pointers)
|
|
static bool environmentCallback(unsigned cmd, void* data);
|
|
static void videoRefreshCallback(const void* data, unsigned width, unsigned height, size_t pitch);
|
|
static size_t audioSampleBatchCallback(const int16_t* data, size_t frames);
|
|
static void audioSampleCallback(int16_t left, int16_t right);
|
|
static void inputPollCallback();
|
|
static int16_t inputStateCallback(unsigned port, unsigned device, unsigned index, unsigned id);
|
|
static void logCallback(enum retro_log_level level, const char* fmt, ...);
|
|
|
|
// Core function pointers (resolved via dlsym)
|
|
void* core_handle_ = nullptr;
|
|
|
|
retro_init_t core_init_ = nullptr;
|
|
retro_deinit_t core_deinit_ = nullptr;
|
|
retro_api_version_t core_api_version_ = nullptr;
|
|
retro_get_system_info_t core_get_system_info_ = nullptr;
|
|
retro_get_system_av_info_t core_get_system_av_info_ = nullptr;
|
|
retro_set_environment_t core_set_environment_ = nullptr;
|
|
retro_set_video_refresh_t core_set_video_refresh_ = nullptr;
|
|
retro_set_audio_sample_t core_set_audio_sample_ = nullptr;
|
|
retro_set_audio_sample_batch_t core_set_audio_sample_batch_ = nullptr;
|
|
retro_set_input_poll_t core_set_input_poll_ = nullptr;
|
|
retro_set_input_state_t core_set_input_state_ = nullptr;
|
|
retro_set_controller_port_device_t core_set_controller_port_device_ = nullptr;
|
|
retro_load_game_t core_load_game_ = nullptr;
|
|
retro_unload_game_t core_unload_game_ = nullptr;
|
|
retro_run_t core_run_ = nullptr;
|
|
retro_reset_t core_reset_ = nullptr;
|
|
retro_serialize_size_t core_serialize_size_ = nullptr;
|
|
retro_serialize_t core_serialize_ = nullptr;
|
|
retro_unserialize_t core_unserialize_ = nullptr;
|
|
retro_get_memory_data_t core_get_memory_data_ = nullptr;
|
|
retro_get_memory_size_t core_get_memory_size_ = nullptr;
|
|
|
|
// State
|
|
std::atomic<bool> running_{false};
|
|
std::atomic<bool> paused_{false};
|
|
std::atomic<bool> game_loaded_{false};
|
|
std::thread emu_thread_;
|
|
|
|
// Video
|
|
ANativeWindow* window_ = nullptr;
|
|
std::mutex window_mutex_;
|
|
unsigned pixel_format_ = RETRO_PIXEL_FORMAT_RGB565;
|
|
std::atomic<DisplayMode> display_mode_{DisplayMode::STRETCH};
|
|
float core_aspect_ratio_ = 0.0f;
|
|
unsigned core_base_width_ = 0;
|
|
unsigned core_base_height_ = 0;
|
|
|
|
// Audio
|
|
AudioEngine audio_engine_;
|
|
|
|
// Input
|
|
std::atomic<uint16_t> button_state_{0};
|
|
std::atomic<int16_t> analog_lx_{0}, analog_ly_{0};
|
|
std::atomic<int16_t> analog_rx_{0}, analog_ry_{0};
|
|
|
|
// Paths
|
|
std::string system_dir_;
|
|
std::string save_dir_;
|
|
|
|
// Frame timing
|
|
double target_fps_ = 60.0;
|
|
int frame_skip_ = 0;
|
|
|
|
// Core options
|
|
std::unordered_map<std::string, std::string> core_options_;
|
|
std::atomic<bool> options_updated_{false};
|
|
};
|