mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-12 09:09:47 +12:00
Merge 22f533daef
into 80ccede765
This commit is contained in:
commit
d77bee0504
2 changed files with 188 additions and 13 deletions
|
@ -579,11 +579,13 @@ void RendererGL::display() {
|
|||
OpenGL::draw(OpenGL::TriangleStrip, 4);
|
||||
}
|
||||
|
||||
#ifndef __LIBRETRO__
|
||||
if constexpr (!Helpers::isHydraCore()) {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
screenFramebuffer.bind(OpenGL::ReadFramebuffer);
|
||||
glBlitFramebuffer(0, 0, 400, 480, 0, 0, outputWindowWidth, outputWindowHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <stdexcept>
|
||||
#include <cstdio>
|
||||
#include <regex>
|
||||
#include <chrono>
|
||||
|
||||
#include <libretro.h>
|
||||
|
||||
|
@ -17,8 +18,32 @@ static retro_input_state_t inputStateCallback;
|
|||
static retro_hw_render_callback hwRender;
|
||||
static std::filesystem::path savePath;
|
||||
|
||||
static bool screenTouched;
|
||||
static std::string touchScreenMode;
|
||||
static bool renderTouchScreen;
|
||||
|
||||
static auto cursorTimeout = 0;
|
||||
static auto cursorMovedAt = std::chrono::steady_clock::now();
|
||||
static bool cursorVisible = false;
|
||||
|
||||
static bool screenTouched;
|
||||
static int lastMouseX;
|
||||
static int lastMouseY;
|
||||
|
||||
static int touchX = 0;
|
||||
static int touchY = 0;
|
||||
|
||||
class CursorRenderer {
|
||||
OpenGL::Program shader;
|
||||
OpenGL::VertexArray vao;
|
||||
OpenGL::VertexBuffer vbo;
|
||||
|
||||
public:
|
||||
void init();
|
||||
void deinit();
|
||||
void draw(float x, float y, float size = 5);
|
||||
};
|
||||
|
||||
std::unique_ptr<CursorRenderer> cursorRenderer;
|
||||
std::unique_ptr<Emulator> emulator;
|
||||
RendererGL* renderer;
|
||||
|
||||
|
@ -46,9 +71,11 @@ static void videoResetContext() {
|
|||
#endif
|
||||
|
||||
emulator->initGraphicsContext(nullptr);
|
||||
cursorRenderer->init();
|
||||
}
|
||||
|
||||
static void videoDestroyContext() {
|
||||
cursorRenderer->deinit();
|
||||
emulator->deinitGraphicsContext();
|
||||
}
|
||||
|
||||
|
@ -123,8 +150,11 @@ static void inputInit() {
|
|||
{0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L"},
|
||||
{0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "X"},
|
||||
{0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Y"},
|
||||
{0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "Screen Touch"},
|
||||
{0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Circle Pad X"},
|
||||
{0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Circle Pad Y"},
|
||||
{0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Pointer X"},
|
||||
{0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Pointer Y"},
|
||||
{0},
|
||||
};
|
||||
|
||||
|
@ -183,6 +213,9 @@ static void configInit() {
|
|||
{"panda3ds_write_protect_virtual_sd", "Write protect virtual SD card; disabled|enabled"},
|
||||
{"panda3ds_battery_level", "Battery percentage; 5|10|20|30|50|70|90|100"},
|
||||
{"panda3ds_use_charger", "Charger plugged; enabled|disabled"},
|
||||
{"panda3ds_touchscreen_mode", "Touchscreen touch mode; Auto|Pointer|Joystick|None"},
|
||||
{"panda3ds_render_touchscreen", "Render touchscreen pointer; disabled|enabled"},
|
||||
{"panda3ds_hide_cursor_timeout", "Hide touchScreen pointer timeout; 3 Seconds|5 Seconds|10 Seconds|15 Seconds|20 Seconds|Never Hide"},
|
||||
{nullptr, nullptr},
|
||||
};
|
||||
|
||||
|
@ -215,8 +248,13 @@ static void configUpdate() {
|
|||
config.lightShadergenThreshold = fetchVariableRange("panda3ds_ubershader_lighting_override_threshold", 1, 8);
|
||||
config.discordRpcEnabled = false;
|
||||
|
||||
touchScreenMode = fetchVariable("panda3ds_touchscreen_mode", "Auto");
|
||||
renderTouchScreen = fetchVariableBool("panda3ds_render_touchscreen", false);
|
||||
cursorTimeout = fetchVariableInt("panda3ds_hide_cursor_timeout", 3);
|
||||
|
||||
// Handle any settings that might need the emulator core to be notified when they're changed, and save the config.
|
||||
emulator->setAudioEnabled(config.audioEnabled);
|
||||
|
||||
config.save();
|
||||
}
|
||||
|
||||
|
@ -229,6 +267,95 @@ static void configCheckVariables() {
|
|||
}
|
||||
}
|
||||
|
||||
static void updateCursorVisibility() {
|
||||
if (renderTouchScreen && cursorTimeout) {
|
||||
if (cursorVisible) {
|
||||
auto current = std::chrono::steady_clock::now();
|
||||
auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(current - cursorMovedAt).count();
|
||||
|
||||
if (elapsed >= cursorTimeout) {
|
||||
cursorVisible = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cursorVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CursorRenderer::init() {
|
||||
#ifdef USING_GLES
|
||||
static const std::string version = R"(
|
||||
#version 300 es
|
||||
precision mediump float;
|
||||
)";
|
||||
#else
|
||||
static const std::string version = R"(
|
||||
#version 410 core
|
||||
)";
|
||||
#endif
|
||||
|
||||
std::string vertex = version + R"(
|
||||
in vec2 position;
|
||||
void main() { gl_Position = vec4(position, 0.0, 1.0); }
|
||||
)";
|
||||
|
||||
std::string fragment = version + R"(
|
||||
out vec4 color;
|
||||
void main() { color = vec4(1.0, 1.0, 1.0, 1.0); }
|
||||
)";
|
||||
|
||||
OpenGL::Shader vertCursor(vertex.c_str(), OpenGL::Vertex);
|
||||
OpenGL::Shader fragCursor(fragment.c_str(), OpenGL::Fragment);
|
||||
shader.create({vertCursor, fragCursor});
|
||||
|
||||
vbo.createFixedSize(12 * 12 * sizeof(GLfloat));
|
||||
vbo.bind();
|
||||
|
||||
vao.create();
|
||||
vao.bind();
|
||||
|
||||
vao.setAttributeFloat<float>(0, 2, 4 * sizeof(GLfloat), nullptr);
|
||||
vao.enableAttribute(0);
|
||||
|
||||
vertCursor.free();
|
||||
fragCursor.free();
|
||||
}
|
||||
|
||||
void CursorRenderer::deinit() {
|
||||
shader.free();
|
||||
vao.free();
|
||||
vbo.free();
|
||||
}
|
||||
|
||||
void CursorRenderer::draw(float x, float y, float size) {
|
||||
shader.use();
|
||||
vao.bind();
|
||||
vbo.bind();
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR);
|
||||
|
||||
float centerX = (x / 320) * 2.0f - 1.0f;
|
||||
float centerY = 1.0f - (y / 240) * 2.0f;
|
||||
|
||||
GLfloat sizeX = size / 320;
|
||||
GLfloat sizeY = size / 240;
|
||||
|
||||
GLfloat cursor[] = {
|
||||
centerX - sizeX, centerY - sizeY, -0.5f, -0.5f,
|
||||
centerX + sizeX, centerY - sizeY, 0.5f, -0.5f,
|
||||
centerX + sizeX, centerY + sizeY, 0.5f, 0.5f,
|
||||
centerX - sizeX, centerY + sizeY, -0.5f, 0.5f
|
||||
};
|
||||
|
||||
vbo.bufferVertsSub(cursor, 12 * sizeof(GLfloat));
|
||||
|
||||
OpenGL::setViewport(40, 0, 320, 240);
|
||||
OpenGL::draw(OpenGL::TriangleFan, 0, 4);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void retro_get_system_info(retro_system_info* info) {
|
||||
info->need_fullpath = true;
|
||||
info->valid_extensions = "3ds|3dsx|elf|axf|cci|cxi|app";
|
||||
|
@ -285,10 +412,12 @@ void retro_init() {
|
|||
}
|
||||
|
||||
emulator = std::make_unique<Emulator>();
|
||||
cursorRenderer = std::make_unique<CursorRenderer>();
|
||||
}
|
||||
|
||||
void retro_deinit() {
|
||||
emulator = nullptr;
|
||||
cursorRenderer = nullptr;
|
||||
}
|
||||
|
||||
bool retro_load_game(const retro_game_info* game) {
|
||||
|
@ -321,6 +450,7 @@ void retro_reset() {
|
|||
|
||||
void retro_run() {
|
||||
configCheckVariables();
|
||||
updateCursorVisibility();
|
||||
|
||||
renderer->setFBO(hwRender.get_current_framebuffer());
|
||||
renderer->resetStateManager();
|
||||
|
@ -351,26 +481,62 @@ void retro_run() {
|
|||
|
||||
bool touchScreen = false;
|
||||
|
||||
const int posX = inputStateCallback(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X);
|
||||
const int posY = inputStateCallback(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y);
|
||||
|
||||
const int newX = static_cast<int>((posX + 0x7fff) / (float)(0x7fff * 2) * emulator->width);
|
||||
const int newY = static_cast<int>((posY + 0x7fff) / (float)(0x7fff * 2) * emulator->height);
|
||||
int pointerX = touchX;
|
||||
int pointerY = touchY;
|
||||
|
||||
const int offsetX = 40;
|
||||
const int offsetY = emulator->height / 2;
|
||||
|
||||
const bool inScreenX = newX >= offsetX && newX <= emulator->width - offsetX;
|
||||
const bool inScreenY = newY >= offsetY && newY <= emulator->height;
|
||||
if (touchScreenMode == "Pointer" || touchScreenMode == "Auto") {
|
||||
const int posX = inputStateCallback(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X);
|
||||
const int posY = inputStateCallback(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y);
|
||||
|
||||
if (inScreenX && inScreenY) {
|
||||
touchScreen |= inputStateCallback(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT);
|
||||
touchScreen |= inputStateCallback(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED);
|
||||
const int newX = static_cast<int>((posX + 0x7fff) / (float)(0x7fff * 2) * emulator->width);
|
||||
const int newY = static_cast<int>((posY + 0x7fff) / (float)(0x7fff * 2) * emulator->height);
|
||||
|
||||
const bool inScreenX = newX >= offsetX && newX <= emulator->width - offsetX;
|
||||
const bool inScreenY = newY >= offsetY && newY <= emulator->height;
|
||||
|
||||
if (inScreenX && inScreenY) {
|
||||
touchScreen |= inputStateCallback(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT);
|
||||
touchScreen |= inputStateCallback(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED);
|
||||
}
|
||||
|
||||
if ((posX != 0 || posY != 0) && (lastMouseX != newX || lastMouseY != newY)) {
|
||||
lastMouseX = newX;
|
||||
lastMouseY = newY;
|
||||
|
||||
pointerX = newX - offsetX;
|
||||
pointerY = newY - offsetY;
|
||||
}
|
||||
}
|
||||
|
||||
if (touchScreenMode == "Joystick" || touchScreenMode == "Auto") {
|
||||
const float speedX = (emulator->width / 60.0);
|
||||
const float speedY = (emulator->height / 2 / 60.0);
|
||||
|
||||
const float moveX = getAxisState(RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X);
|
||||
const float moveY = getAxisState(RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y);
|
||||
|
||||
touchScreen |= getButtonState(RETRO_DEVICE_ID_JOYPAD_R3);
|
||||
|
||||
if (moveX != 0 || moveY != 0) {
|
||||
pointerX += static_cast<int>((moveX / 32767) * speedX);
|
||||
pointerY += static_cast<int>((moveY / 32767) * speedY);
|
||||
}
|
||||
}
|
||||
|
||||
if (cursorTimeout && (pointerX != touchX || pointerY != touchY)) {
|
||||
cursorVisible = true;
|
||||
cursorMovedAt = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
touchX = std::clamp(pointerX, 0, (int)(emulator->width - (offsetX * 2)));
|
||||
touchY = std::clamp(pointerY, 0, (int)(emulator->height - offsetY));
|
||||
|
||||
if (touchScreen) {
|
||||
u16 x = static_cast<u16>(newX - offsetX);
|
||||
u16 y = static_cast<u16>(newY - offsetY);
|
||||
u16 x = static_cast<u16>(touchX);
|
||||
u16 y = static_cast<u16>(touchY);
|
||||
|
||||
hid.setTouchScreenPress(x, y);
|
||||
screenTouched = true;
|
||||
|
@ -382,6 +548,13 @@ void retro_run() {
|
|||
hid.updateInputs(emulator->getTicks());
|
||||
emulator->runFrame();
|
||||
|
||||
if (renderTouchScreen && cursorVisible) {
|
||||
cursorRenderer->draw(touchX, touchY);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glBlitFramebuffer(0, 0, 400, 480, 0, 0, 400, 480, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
|
||||
videoCallback(RETRO_HW_FRAME_BUFFER_VALID, emulator->width, emulator->height, 0);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue