Initial commit: multi-platform emulator with PS1 support
Jetpack Compose app with adaptive layouts (phone/tablet/foldable) using Window Size Classes. Integrates a C++ libretro frontend via JNI for actual PS1 emulation using pcsx_rearmed, with AAudio output and ANativeWindow rendering. - Emulation core architecture with interface for NES, SNES, N64, Genesis, PS1, PS2 (PS1 implemented, others placeholder) - Touch controller overlay with D-pad (diagonal support), face buttons, shoulders, and analog sticks - Bluetooth/USB controller detection and input mapping - Customizable controller layout editor with drag-to-reposition - Game library with auto-scan of /sdcard/Games/ subfolders - Auto-import of libretro core .so from /sdcard/Games/cores/ - Save states and SRAM persistence
This commit is contained in:
113
app/src/main/cpp/libretro_frontend.h
Normal file
113
app/src/main/cpp/libretro_frontend.h
Normal file
@@ -0,0 +1,113 @@
|
||||
#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>
|
||||
|
||||
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 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;
|
||||
|
||||
// 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};
|
||||
};
|
||||
Reference in New Issue
Block a user