From 5c952021b7bd27994f2a86a8a8258cbf1bcd22d5 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Thu, 8 Jul 2021 20:09:09 +0200 Subject: [PATCH] libretro: vmu and crosshair display. lightgun fixes --- core/rend/dx9/dxcontext.cpp | 1 + core/rend/gl4/gldraw.cpp | 155 +++++++++++++++++++++++++++++ core/rend/gl4/gles.cpp | 19 ++++ core/rend/gles/gldraw.cpp | 112 ++++++--------------- core/rend/gles/gles.cpp | 6 +- core/rend/osd.cpp | 10 ++ core/rend/vulkan/overlay.cpp | 61 ++++++++++-- core/rend/vulkan/vulkan_renderer.h | 2 +- shell/libretro/libretro.cpp | 130 ++++++++++++------------ shell/libretro/vmu_xhair.cpp | 8 +- 10 files changed, 341 insertions(+), 163 deletions(-) diff --git a/core/rend/dx9/dxcontext.cpp b/core/rend/dx9/dxcontext.cpp index b9659fa03..d4eafefe0 100644 --- a/core/rend/dx9/dxcontext.cpp +++ b/core/rend/dx9/dxcontext.cpp @@ -19,6 +19,7 @@ #include "dxcontext.h" #include "d3d_renderer.h" #include "rend/gui.h" +#include "rend/osd.h" #ifdef USE_SDL #include "sdl/sdl.h" #endif diff --git a/core/rend/gl4/gldraw.cpp b/core/rend/gl4/gldraw.cpp index 4c873bcd9..ed5d661b4 100644 --- a/core/rend/gl4/gldraw.cpp +++ b/core/rend/gl4/gldraw.cpp @@ -19,6 +19,7 @@ #include "gl4.h" #include "rend/gles/glcache.h" #include "rend/tileclip.h" +#include "rend/osd.h" static gl4PipelineShader* CurrentShader; extern u32 gcflip; @@ -680,3 +681,157 @@ void gl4DrawStrips(GLuint output_fbo, int width, int height) glBindTexture(GL_TEXTURE_2D, opaqueTexId); renderABuffer(); } + +#ifdef LIBRETRO +#include "vmu_xhair.h" + +extern GLuint vmuTextureId[4]; +extern GLuint lightgunTextureId[4]; + +void UpdateVmuTexture(int vmu_screen_number); +void UpdateLightGunTexture(int port); + +void gl4DrawVmuTexture(u8 vmu_screen_number) +{ + glActiveTexture(GL_TEXTURE0); + + const float vmu_padding = 8.f; + float x = (config::Widescreen && config::ScreenStretching == 100 ? -(640.f * 4.f / 3.f - 640.f) / 2 : 0) + vmu_padding; + float y = vmu_padding; + float w = VMU_SCREEN_WIDTH * vmu_screen_params[vmu_screen_number].vmu_screen_size_mult; + float h = VMU_SCREEN_HEIGHT * vmu_screen_params[vmu_screen_number].vmu_screen_size_mult; + + if (vmu_lcd_changed[vmu_screen_number * 2] || vmuTextureId[vmu_screen_number] == 0) + UpdateVmuTexture(vmu_screen_number); + + switch (vmu_screen_params[vmu_screen_number].vmu_screen_position) + { + case UPPER_LEFT: + break; + case UPPER_RIGHT: + x = 640 - x - w; + break; + case LOWER_LEFT: + y = 480 - y - h; + break; + case LOWER_RIGHT: + x = 640 - x - w; + y = 480 - y - h; + break; + } + + glcache.BindTexture(GL_TEXTURE_2D, vmuTextureId[vmu_screen_number]); + + glcache.Disable(GL_SCISSOR_TEST); + glcache.Disable(GL_DEPTH_TEST); + glcache.Disable(GL_STENCIL_TEST); + glcache.Disable(GL_CULL_FACE); + glcache.Enable(GL_BLEND); + glcache.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + gl4SetupMainVBO(); + + gl4ShaderUniforms.trilinear_alpha = 1.0; + + CurrentShader = gl4GetProgram(false, + 0, + true, + true, + false, + 0, + false, + 2, + false, + false, + false, + false, + false, + Pass::Color); + glcache.UseProgram(CurrentShader->program); + gl4ShaderUniforms.Set(CurrentShader); + + { + struct Vertex vertices[] = { + { x, y+h, 1, { 255, 255, 255, 255 }, { 0, 0, 0, 0 }, 0, 0 }, + { x, y, 1, { 255, 255, 255, 255 }, { 0, 0, 0, 0 }, 0, 1 }, + { x+w, y+h, 1, { 255, 255, 255, 255 }, { 0, 0, 0, 0 }, 1, 0 }, + { x+w, y, 1, { 255, 255, 255, 255 }, { 0, 0, 0, 0 }, 1, 1 }, + }; + GLushort indices[] = { 0, 1, 2, 1, 3 }; + + glBindBuffer(GL_ARRAY_BUFFER, gl4.vbo.geometry); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STREAM_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl4.vbo.idxs); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STREAM_DRAW); + } + + glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, (void *)0); +} + +void gl4DrawGunCrosshair(u8 port) +{ + if ( lightgun_params[port].offscreen || (lightgun_params[port].colour==0) ) + return; + + glActiveTexture(GL_TEXTURE0); + + float x=0; + float y=0; + float w=LIGHTGUN_CROSSHAIR_SIZE; + float h=LIGHTGUN_CROSSHAIR_SIZE; + + x = lightgun_params[port].x - ( LIGHTGUN_CROSSHAIR_SIZE / 2 ); + y = lightgun_params[port].y - ( LIGHTGUN_CROSSHAIR_SIZE / 2 ); + + if (lightgun_params[port].dirty || lightgunTextureId[port] == 0) + UpdateLightGunTexture(port); + + glcache.BindTexture(GL_TEXTURE_2D, lightgunTextureId[port]); + + glcache.Disable(GL_SCISSOR_TEST); + glcache.Disable(GL_DEPTH_TEST); + glcache.Disable(GL_STENCIL_TEST); + glcache.Disable(GL_CULL_FACE); + glcache.Enable(GL_BLEND); + glcache.BlendFunc(GL_SRC_ALPHA, GL_ONE); + + gl4SetupMainVBO(); + + gl4ShaderUniforms.trilinear_alpha = 1.0; + CurrentShader = gl4GetProgram(false, + 0, + true, + true, + false, + 0, + false, + 2, + false, + false, + false, + false, + false, + Pass::Color); + glcache.UseProgram(CurrentShader->program); + gl4ShaderUniforms.Set(CurrentShader); + + { + struct Vertex vertices[] = { + { x, y+h, 1, { 255, 255, 255, 255 }, { 0, 0, 0, 0 }, 0, 1 }, + { x, y, 1, { 255, 255, 255, 255 }, { 0, 0, 0, 0 }, 0, 0 }, + { x+w, y+h, 1, { 255, 255, 255, 255 }, { 0, 0, 0, 0 }, 1, 1 }, + { x+w, y, 1, { 255, 255, 255, 255 }, { 0, 0, 0, 0 }, 1, 0 }, + }; + GLushort indices[] = { 0, 1, 2, 1, 3 }; + + glBindBuffer(GL_ARRAY_BUFFER, gl4.vbo.geometry); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STREAM_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl4.vbo.idxs); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STREAM_DRAW); + } + + glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, (void *)0); + + glcache.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} +#endif diff --git a/core/rend/gl4/gles.cpp b/core/rend/gl4/gles.cpp index 97914fe4a..e092609c7 100644 --- a/core/rend/gl4/gles.cpp +++ b/core/rend/gl4/gles.cpp @@ -19,6 +19,7 @@ #include "gl4.h" #include "rend/gles/glcache.h" #include "rend/transform_matrix.h" +#include "rend/osd.h" //Fragment and vertex shaders code @@ -916,6 +917,24 @@ struct OpenGL4Renderer : OpenGLRenderer { return render_output_framebuffer(); } + +#ifdef LIBRETRO + void DrawOSD(bool clearScreen) override + { + void gl4DrawVmuTexture(u8 vmu_screen_number); + void gl4DrawGunCrosshair(u8 port); + + if (settings.platform.system == DC_PLATFORM_DREAMCAST) + { + for (int vmu_screen_number = 0 ; vmu_screen_number < 4 ; vmu_screen_number++) + if (vmu_lcd_status[vmu_screen_number * 2]) + gl4DrawVmuTexture(vmu_screen_number); + } + + for (int lightgun_port = 0 ; lightgun_port < 4 ; lightgun_port++) + gl4DrawGunCrosshair(lightgun_port); + } +#endif }; Renderer* rend_GL4() diff --git a/core/rend/gles/gldraw.cpp b/core/rend/gles/gldraw.cpp index 14792df08..34cc6bc12 100644 --- a/core/rend/gles/gldraw.cpp +++ b/core/rend/gles/gldraw.cpp @@ -749,18 +749,6 @@ GLuint lightgunTextureId[4]={0,0,0,0}; void UpdateVmuTexture(int vmu_screen_number) { -// s32 x,y ; -// u8 temp_tex_buffer[VMU_SCREEN_HEIGHT*VMU_SCREEN_WIDTH*4]; -// u8 *dst = temp_tex_buffer; -// u8 *src = NULL ; -// u8 vmu_pixel_on_R = vmu_screen_params[vmu_screen_number].vmu_pixel_on_R ; -// u8 vmu_pixel_on_G = vmu_screen_params[vmu_screen_number].vmu_pixel_on_G ; -// u8 vmu_pixel_on_B = vmu_screen_params[vmu_screen_number].vmu_pixel_on_B ; -// u8 vmu_pixel_off_R = vmu_screen_params[vmu_screen_number].vmu_pixel_off_R ; -// u8 vmu_pixel_off_G = vmu_screen_params[vmu_screen_number].vmu_pixel_off_G ; -// u8 vmu_pixel_off_B = vmu_screen_params[vmu_screen_number].vmu_pixel_off_B ; -// u8 vmu_screen_opacity = vmu_screen_params[vmu_screen_number].vmu_screen_opacity ; - if (vmuTextureId[vmu_screen_number] == 0) { vmuTextureId[vmu_screen_number] = glcache.GenTexture(); @@ -772,79 +760,39 @@ void UpdateVmuTexture(int vmu_screen_number) glcache.BindTexture(GL_TEXTURE_2D, vmuTextureId[vmu_screen_number]); - u8 *origsrc = (u8 *)vmu_lcd_data[vmu_screen_number]; - - if ( origsrc == NULL ) - return ; -/* TODO - - for ( y = VMU_SCREEN_HEIGHT-1 ; y >= 0 ; y--) - { - src = origsrc + (y*VMU_SCREEN_WIDTH) ; - - for ( x = 0 ; x < VMU_SCREEN_WIDTH ; x++) - { - if ( *src++ > 0 ) - { - *dst++ = vmu_pixel_on_R ; - *dst++ = vmu_pixel_on_G ; - *dst++ = vmu_pixel_on_B ; - *dst++ = vmu_screen_opacity ; - } - else - { - *dst++ = vmu_pixel_off_R ; - *dst++ = vmu_pixel_off_G ; - *dst++ = vmu_pixel_off_B ; - *dst++ = vmu_screen_opacity ; - } - } - } -*/ - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, VMU_SCREEN_WIDTH, VMU_SCREEN_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, origsrc); - - vmu_lcd_changed[vmu_screen_number] = false; + const u32 *data = vmu_lcd_data[vmu_screen_number * 2]; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, VMU_SCREEN_WIDTH, VMU_SCREEN_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + vmu_lcd_changed[vmu_screen_number * 2] = false; } void DrawVmuTexture(u8 vmu_screen_number) { glActiveTexture(GL_TEXTURE0); - float x=0 ; - float y=0 ; - float w=VMU_SCREEN_WIDTH*vmu_screen_params[vmu_screen_number].vmu_screen_size_mult ; - float h=VMU_SCREEN_HEIGHT*vmu_screen_params[vmu_screen_number].vmu_screen_size_mult ; + const float vmu_padding = 8.f; + float x = (config::Widescreen && config::ScreenStretching == 100 ? -(640.f * 4.f / 3.f - 640.f) / 2 : 0) + vmu_padding; + float y = vmu_padding; + float w = VMU_SCREEN_WIDTH * vmu_screen_params[vmu_screen_number].vmu_screen_size_mult; + float h = VMU_SCREEN_HEIGHT * vmu_screen_params[vmu_screen_number].vmu_screen_size_mult; - if (vmu_lcd_changed[vmu_screen_number] || vmuTextureId[vmu_screen_number] == 0) - UpdateVmuTexture(vmu_screen_number) ; + if (vmu_lcd_changed[vmu_screen_number * 2] || vmuTextureId[vmu_screen_number] == 0) + UpdateVmuTexture(vmu_screen_number); - switch ( vmu_screen_params[vmu_screen_number].vmu_screen_position ) + switch (vmu_screen_params[vmu_screen_number].vmu_screen_position) { - case UPPER_LEFT : - { - x = 0 ; - y = 0 ; - break ; - } - case UPPER_RIGHT : - { - x = 640-w ; - y = 0 ; - break ; - } - case LOWER_LEFT : - { - x = 0 ; - y = 480-h ; - break ; - } - case LOWER_RIGHT : - { - x = 640-w ; - y = 480-h ; - break ; - } + case UPPER_LEFT: + break; + case UPPER_RIGHT: + x = 640 - x - w; + break; + case LOWER_LEFT: + y = 480 - y - h; + break; + case LOWER_RIGHT: + x = 640 - x - w; + y = 480 - y - h; + break; } glcache.BindTexture(GL_TEXTURE_2D, vmuTextureId[vmu_screen_number]); @@ -930,15 +878,15 @@ void DrawGunCrosshair(u8 port) glActiveTexture(GL_TEXTURE0); - float x=0; - float y=0; - float w=LIGHTGUN_CROSSHAIR_SIZE; - float h=LIGHTGUN_CROSSHAIR_SIZE; + float x = lightgun_params[port].x; + float y = lightgun_params[port].y; - x = lightgun_params[port].x - ( LIGHTGUN_CROSSHAIR_SIZE / 2 ); - y = lightgun_params[port].y - ( LIGHTGUN_CROSSHAIR_SIZE / 2 ); + float w = LIGHTGUN_CROSSHAIR_SIZE; + float h = LIGHTGUN_CROSSHAIR_SIZE; + x -= w / 2; + y -= h / 2; - if ( lightgun_params[port].dirty || lightgunTextureId[port] == 0) + if (lightgun_params[port].dirty || lightgunTextureId[port] == 0) UpdateLightGunTexture(port); glcache.BindTexture(GL_TEXTURE_2D, lightgunTextureId[port]); diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index 27413e128..4bdd53dec 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -948,12 +948,12 @@ void OSD_DRAW(bool clear_screen) if (settings.platform.system == DC_PLATFORM_DREAMCAST) { for (int vmu_screen_number = 0 ; vmu_screen_number < 4 ; vmu_screen_number++) - if (vmu_lcd_status[vmu_screen_number]) + if (vmu_lcd_status[vmu_screen_number * 2]) DrawVmuTexture(vmu_screen_number); } -// for (int lightgun_port = 0 ; lightgun_port < 4 ; lightgun_port++) -// DrawGunCrosshair(lightgun_port); + for (int lightgun_port = 0 ; lightgun_port < 4 ; lightgun_port++) + DrawGunCrosshair(lightgun_port); #else gui_display_osd(); diff --git a/core/rend/osd.cpp b/core/rend/osd.cpp index 62ffb2b0c..ecc65e640 100644 --- a/core/rend/osd.cpp +++ b/core/rend/osd.cpp @@ -20,6 +20,9 @@ #include "input/gamepad_device.h" #include "TexCache.h" #include "hw/maple/maple_devs.h" +#ifdef LIBRETRO +#include "vmu_xhair.h" +#endif #include @@ -179,7 +182,14 @@ void push_vmu_screen(int bus_id, int bus_port, u8* buffer) return; u32 *p = &vmu_lcd_data[vmu_id][0]; for (int i = 0; i < (int)ARRAY_SIZE(vmu_lcd_data[vmu_id]); i++, buffer++) +#ifdef LIBRETRO + *p++ = (*buffer != 0 + ? vmu_screen_params[bus_id].vmu_pixel_on_R | (vmu_screen_params[bus_id].vmu_pixel_on_G << 8) | (vmu_screen_params[bus_id].vmu_pixel_on_B << 16) + : vmu_screen_params[bus_id].vmu_pixel_off_R | (vmu_screen_params[bus_id].vmu_pixel_off_G << 8) | (vmu_screen_params[bus_id].vmu_pixel_off_B << 16)) + | (vmu_screen_params[bus_id].vmu_screen_opacity << 24); +#else *p++ = *buffer != 0 ? 0xFFFFFFFFu : 0xFF000000u; +#endif #ifndef LIBRETRO vmu_lcd_status[vmu_id] = true; #endif diff --git a/core/rend/vulkan/overlay.cpp b/core/rend/vulkan/overlay.cpp index bbd529740..44c724c20 100644 --- a/core/rend/vulkan/overlay.cpp +++ b/core/rend/vulkan/overlay.cpp @@ -23,6 +23,9 @@ #include "overlay.h" #include "cfg/option.h" #include "rend/osd.h" +#ifdef LIBRETRO +#include "vmu_xhair.h" +#endif VulkanOverlay::~VulkanOverlay() = default; @@ -93,38 +96,70 @@ void VulkanOverlay::Draw(vk::CommandBuffer commandBuffer, vk::Extent2D viewport, if (vmu) { f32 vmu_padding = 8.f * scaling; - f32 vmu_height = 70.f * scaling; - f32 vmu_width = 48.f / 32.f * vmu_height; + f32 vmu_height = 32.f * scaling; + f32 vmu_width = 48.f * scaling; pipeline->BindPipeline(commandBuffer); +#ifndef LIBRETRO + vmu_height *= 2.f; + vmu_width *= 2.f; float blendConstants[4] = { 0.75f, 0.75f, 0.75f, 0.75f }; commandBuffer.setBlendConstants(blendConstants); +#endif for (size_t i = 0; i < vmuTextures.size(); i++) { if (!vmuTextures[i]) continue; - f32 x; + float x; + float y; + float w = vmu_width; + float h = vmu_height; +#ifdef LIBRETRO + if (i & 1) + continue; + w *= vmu_screen_params[i / 2].vmu_screen_size_mult; + h *= vmu_screen_params[i / 2].vmu_screen_size_mult; + switch (vmu_screen_params[i / 2].vmu_screen_position) + { + case UPPER_LEFT: + x = vmu_padding; + y = vmu_padding; + break; + case UPPER_RIGHT: + x = viewport.width - vmu_padding - w; + y = vmu_padding; + break; + case LOWER_LEFT: + x = vmu_padding; + y = viewport.height - vmu_padding - h; + break; + case LOWER_RIGHT: + x = viewport.width - vmu_padding - w; + y = viewport.height - vmu_padding - h; + break; + } +#else if (i & 2) - x = viewport.width - vmu_padding - vmu_width; + x = viewport.width - vmu_padding - w; else x = vmu_padding; - f32 y; if (i & 4) { - y = viewport.height - vmu_padding - vmu_height; + y = viewport.height - vmu_padding - h; if (i & 1) - y -= vmu_padding + vmu_height; + y -= vmu_padding + h; } else { y = vmu_padding; if (i & 1) - y += vmu_padding + vmu_height; + y += vmu_padding + h; } - vk::Viewport viewport(x, y, vmu_width, vmu_height); +#endif + vk::Viewport viewport(x, y, w, h); commandBuffer.setViewport(0, 1, &viewport); - commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(x, y), vk::Extent2D(vmu_width, vmu_height))); + commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(x, y), vk::Extent2D(w, h))); drawers[i]->Draw(commandBuffer, vmuTextures[i]->GetImageView(), vtx, true); } @@ -141,8 +176,14 @@ void VulkanOverlay::Draw(vk::CommandBuffer commandBuffer, vk::Extent2D viewport, float x, y; std::tie(x, y) = getCrosshairPosition(i); + +#ifdef LIBRETRO + float w = LIGHTGUN_CROSSHAIR_SIZE * scaling; + float h = LIGHTGUN_CROSSHAIR_SIZE * scaling; +#else float w = XHAIR_WIDTH * scaling; float h = XHAIR_HEIGHT * scaling; +#endif x -= w / 2; y -= h / 2; vk::Viewport viewport(x, y, w, h); diff --git a/core/rend/vulkan/vulkan_renderer.h b/core/rend/vulkan/vulkan_renderer.h index d22554dfd..dadbb9b0b 100644 --- a/core/rend/vulkan/vulkan_renderer.h +++ b/core/rend/vulkan/vulkan_renderer.h @@ -66,7 +66,7 @@ protected: } #endif #ifdef LIBRETRO - quadPipeline = std::unique_ptr(new QuadPipeline()); + quadPipeline = std::unique_ptr(new QuadPipeline(true)); quadPipeline->Init(&shaderManager, renderPass); overlay = std::unique_ptr(new VulkanOverlay()); overlay->Init(quadPipeline.get()); diff --git a/shell/libretro/libretro.cpp b/shell/libretro/libretro.cpp index 37580e261..b26ab0104 100644 --- a/shell/libretro/libretro.cpp +++ b/shell/libretro/libretro.cpp @@ -147,6 +147,8 @@ unsigned per_content_vmus = 0; static bool first_run = true; static bool mute_messages; static bool rotate_screen; +static int framebufferWidth; +static int framebufferHeight; static retro_perf_callback perf_cb; static retro_get_cpu_features_t perf_get_cpu_features_cb; @@ -638,27 +640,31 @@ static void update_variables(bool first_startup) else if (!strcmp("Blue", var.value)) lightgun_params[i].colour = LIGHTGUN_COLOR_BLUE; } + config::CrosshairColor[i] = lightgun_palette[lightgun_params[i].colour * 3] + | (lightgun_palette[lightgun_params[i].colour * 3 + 1] << 8) + | (lightgun_palette[lightgun_params[i].colour * 3 + 2] << 16) + | 0xff000000; vmu_lcd_status[i] = false; vmu_lcd_changed[i] = true; - vmu_screen_params[i].vmu_screen_position = UPPER_LEFT ; - vmu_screen_params[i].vmu_screen_size_mult = 1 ; - vmu_screen_params[i].vmu_pixel_on_R = VMU_SCREEN_COLOR_MAP[VMU_DEFAULT_ON].r ; - vmu_screen_params[i].vmu_pixel_on_G = VMU_SCREEN_COLOR_MAP[VMU_DEFAULT_ON].g ; - vmu_screen_params[i].vmu_pixel_on_B = VMU_SCREEN_COLOR_MAP[VMU_DEFAULT_ON].b ; - vmu_screen_params[i].vmu_pixel_off_R = VMU_SCREEN_COLOR_MAP[VMU_DEFAULT_OFF].r ; - vmu_screen_params[i].vmu_pixel_off_G = VMU_SCREEN_COLOR_MAP[VMU_DEFAULT_OFF].g ; - vmu_screen_params[i].vmu_pixel_off_B = VMU_SCREEN_COLOR_MAP[VMU_DEFAULT_OFF].b ; - vmu_screen_params[i].vmu_screen_opacity = 0xFF ; + vmu_screen_params[i].vmu_screen_position = UPPER_LEFT; + vmu_screen_params[i].vmu_screen_size_mult = 1; + vmu_screen_params[i].vmu_pixel_on_R = VMU_SCREEN_COLOR_MAP[VMU_DEFAULT_ON].r; + vmu_screen_params[i].vmu_pixel_on_G = VMU_SCREEN_COLOR_MAP[VMU_DEFAULT_ON].g; + vmu_screen_params[i].vmu_pixel_on_B = VMU_SCREEN_COLOR_MAP[VMU_DEFAULT_ON].b; + vmu_screen_params[i].vmu_pixel_off_R = VMU_SCREEN_COLOR_MAP[VMU_DEFAULT_OFF].r; + vmu_screen_params[i].vmu_pixel_off_G = VMU_SCREEN_COLOR_MAP[VMU_DEFAULT_OFF].g; + vmu_screen_params[i].vmu_pixel_off_B = VMU_SCREEN_COLOR_MAP[VMU_DEFAULT_OFF].b; + vmu_screen_params[i].vmu_screen_opacity = 0xFF; - snprintf(key, sizeof(key), CORE_OPTION_NAME "_vmu%d_screen_display", i+1) ; + snprintf(key, sizeof(key), CORE_OPTION_NAME "_vmu%d_screen_display", i+1); if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && !strcmp("enabled", var.value) ) vmu_lcd_status[i] = true; - snprintf(key, sizeof(key), CORE_OPTION_NAME "_vmu%d_screen_position", i+1) ; + snprintf(key, sizeof(key), CORE_OPTION_NAME "_vmu%d_screen_position", i+1); - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value ) + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp("Upper Left", var.value)) vmu_screen_params[i].vmu_screen_position = UPPER_LEFT; @@ -670,9 +676,9 @@ static void update_variables(bool first_startup) vmu_screen_params[i].vmu_screen_position = LOWER_RIGHT; } - snprintf(key, sizeof(key), CORE_OPTION_NAME "_vmu%d_screen_size_mult", i+1) ; + snprintf(key, sizeof(key), CORE_OPTION_NAME "_vmu%d_screen_size_mult", i+1); - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value ) + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp("1x", var.value)) vmu_screen_params[i].vmu_screen_size_mult = 1; @@ -686,9 +692,9 @@ static void update_variables(bool first_startup) vmu_screen_params[i].vmu_screen_size_mult = 5; } - snprintf(key, sizeof(key), CORE_OPTION_NAME "_vmu%d_screen_opacity", i+1) ; + snprintf(key, sizeof(key), CORE_OPTION_NAME "_vmu%d_screen_opacity", i + 1); - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value ) + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp("100%", var.value)) vmu_screen_params[i].vmu_screen_opacity = 255; @@ -712,24 +718,24 @@ static void update_variables(bool first_startup) vmu_screen_params[i].vmu_screen_opacity = 1*25.5; } - snprintf(key, sizeof(key), CORE_OPTION_NAME "_vmu%d_pixel_on_color", i+1) ; + snprintf(key, sizeof(key), CORE_OPTION_NAME "_vmu%d_pixel_on_color", i + 1); - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && strlen(var.value)>1 ) + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && strlen(var.value)>1) { - int color_idx = atoi(var.value+(strlen(var.value)-2)) ; - vmu_screen_params[i].vmu_pixel_on_R = VMU_SCREEN_COLOR_MAP[color_idx].r ; - vmu_screen_params[i].vmu_pixel_on_G = VMU_SCREEN_COLOR_MAP[color_idx].g ; - vmu_screen_params[i].vmu_pixel_on_B = VMU_SCREEN_COLOR_MAP[color_idx].b ; + int color_idx = atoi(var.value+(strlen(var.value)-2)); + vmu_screen_params[i].vmu_pixel_on_R = VMU_SCREEN_COLOR_MAP[color_idx].r; + vmu_screen_params[i].vmu_pixel_on_G = VMU_SCREEN_COLOR_MAP[color_idx].g; + vmu_screen_params[i].vmu_pixel_on_B = VMU_SCREEN_COLOR_MAP[color_idx].b; } - snprintf(key, sizeof(key), CORE_OPTION_NAME "_vmu%d_pixel_off_color", i+1) ; + snprintf(key, sizeof(key), CORE_OPTION_NAME "_vmu%d_pixel_off_color", i+1); - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && strlen(var.value)>1 ) + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && strlen(var.value)>1) { - int color_idx = atoi(var.value+(strlen(var.value)-2)) ; - vmu_screen_params[i].vmu_pixel_off_R = VMU_SCREEN_COLOR_MAP[color_idx].r ; - vmu_screen_params[i].vmu_pixel_off_G = VMU_SCREEN_COLOR_MAP[color_idx].g ; - vmu_screen_params[i].vmu_pixel_off_B = VMU_SCREEN_COLOR_MAP[color_idx].b ; + int color_idx = atoi(var.value+(strlen(var.value)-2)); + vmu_screen_params[i].vmu_pixel_off_R = VMU_SCREEN_COLOR_MAP[color_idx].r; + vmu_screen_params[i].vmu_pixel_off_G = VMU_SCREEN_COLOR_MAP[color_idx].g; + vmu_screen_params[i].vmu_pixel_off_B = VMU_SCREEN_COLOR_MAP[color_idx].b; } } @@ -774,11 +780,8 @@ void retro_run() startTime = sh4_sched_now64(); dc_run(nullptr); } - int width = config::RenderResolution * 4 / 3; - if (config::Widescreen && !rotate_screen) - width = width * 4 / 3; #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) || defined(HAVE_VULKAN) - video_cb(is_dupe ? 0 : RETRO_HW_FRAME_BUFFER_VALID, width, config::RenderResolution, 0); + video_cb(is_dupe ? 0 : RETRO_HW_FRAME_BUFFER_VALID, framebufferWidth, framebufferHeight, 0); #endif if (!config::ThreadedRendering) is_dupe = true; @@ -1255,10 +1258,7 @@ static void retro_vk_context_reset() ERROR_LOG(RENDERER, "Get Vulkan HW interface failed"); return; } - int width = config::RenderResolution * 4 / 3; - if (config::Widescreen && !rotate_screen) - width = width * 4 / 3; - theVulkanContext.SetWindowSize(width, config::RenderResolution); + theVulkanContext.SetWindowSize(framebufferWidth, framebufferHeight); theVulkanContext.Init((retro_hw_render_interface_vulkan *)vulkan); rend_term_renderer(); rend_init_renderer(); @@ -1579,6 +1579,13 @@ bool retro_load_game(const struct retro_game_info *game) config::Rotate90 = false; // actual framebuffer rotation is done by frontend if (rotate_screen) config::Widescreen.override(false); + framebufferHeight = config::RenderResolution; + if (config::Widescreen) + framebufferWidth = config::RenderResolution * 16.f / 9.f; + else if (!rotate_screen) + framebufferWidth = config::RenderResolution * 4.f * config::ScreenStretching / 3.f / 100.f; + else + framebufferWidth = config::RenderResolution * 4.f / 3.f; if (devices_need_refresh) refresh_devices(true); @@ -1733,31 +1740,19 @@ void retro_get_system_av_info(struct retro_system_av_info *info) const int spg_clks[4] = { 26944080, 13458568, 13462800, 26944080 }; u32 pixel_clock= spg_clks[(SPG_CONTROL.full >> 6) & 3]; - int width = config::RenderResolution * 4 / 3; - cheatManager.reset(config::Settings::instance().getGameId()); if (cheatManager.isWidescreen()) { - info->geometry.aspect_ratio = 16.0 / 9.0; struct retro_message msg; msg.msg = "Widescreen cheat activated"; msg.frames = 120; environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, &msg); } - else - { - if (config::Widescreen) - { - width = (int)lround(width * 4.0 / 3.0); - info->geometry.aspect_ratio = 16.0 / 9.0; - } - else - info->geometry.aspect_ratio = 4.0 / 3.0; - } + info->geometry.aspect_ratio = (float)framebufferWidth / framebufferHeight; if (rotate_screen) info->geometry.aspect_ratio = 1 / info->geometry.aspect_ratio; - int maximum = width > config::RenderResolution ? width : config::RenderResolution; - info->geometry.base_width = width; - info->geometry.base_height = config::RenderResolution; + info->geometry.base_width = framebufferWidth; + info->geometry.base_height = framebufferHeight; + int maximum = std::max(framebufferWidth, framebufferHeight); info->geometry.max_width = maximum; info->geometry.max_height = maximum; @@ -2065,6 +2060,21 @@ static void updateMouseState(u32 port) mo_wheel_delta[port] += 10; } +static void updateLightgunCoordinates(u32 port) +{ + int x = input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X); + int y = input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y); + if (config::Widescreen && config::ScreenStretching == 100) + mo_x_abs[port] = 640.f * ((x + 0x8000) * 4.f / 3.f / 0x10000 - (4.f / 3.f - 1.f) / 2.f); + else + mo_x_abs[port] = (x + 0x8000) * 640.f / 0x10000; + mo_y_abs[port] = (y + 0x8000) * 480.f / 0x10000; + + lightgun_params[port].offscreen = false; + lightgun_params[port].x = mo_x_abs[port]; + lightgun_params[port].y = mo_y_abs[port]; +} + static void UpdateInputStateNaomi(u32 port) { switch (config::MapleMainDevices[port]) @@ -2109,14 +2119,7 @@ static void UpdateInputStateNaomi(u32 port) } else { - int x = input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X); - int y = input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y); - mo_x_abs[port] = (x + 0x8000) * 640.f / 0x10000; - mo_y_abs[port] = (y + 0x8000) * 480.f / 0x10000; - - lightgun_params[port].offscreen = false; - lightgun_params[port].x = mo_x_abs[port]; - lightgun_params[port].y = mo_y_abs[port]; + updateLightgunCoordinates(port); } } break; @@ -2521,12 +2524,7 @@ static void UpdateInputState(u32 port) } else { - mo_x_abs[port] = (input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) + 0x8000) * 640.f / 0x10000; - mo_y_abs[port] = (input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y) + 0x8000) * 480.f / 0x10000; - - lightgun_params[port].offscreen = false; - lightgun_params[port].x = mo_x_abs[port]; - lightgun_params[port].y = mo_y_abs[port]; + updateLightgunCoordinates(port); } } break; diff --git a/shell/libretro/vmu_xhair.cpp b/shell/libretro/vmu_xhair.cpp index a35f636a1..3e32206a3 100644 --- a/shell/libretro/vmu_xhair.cpp +++ b/shell/libretro/vmu_xhair.cpp @@ -15,6 +15,7 @@ along with Flycast. If not, see . */ #include "vmu_xhair.h" +#include "cfg/option.h" const char* VMU_SCREEN_COLOR_NAMES[VMU_NUM_COLORS] = { "DEFAULT_ON", @@ -114,5 +115,10 @@ lightgun_params_t lightgun_params[4]; std::pair getCrosshairPosition(int playerNum) { - return std::make_pair(lightgun_params[playerNum].x, lightgun_params[playerNum].y); + float fx = lightgun_params[playerNum].x * config::RenderResolution * config::ScreenStretching / 480.f / 100.f; + float fy = lightgun_params[playerNum].y * config::RenderResolution / 480.f; + if (config::Widescreen && config::ScreenStretching == 100) + fx += (480.f * 16.f / 9.f - 640.f) / 2.f * config::RenderResolution / 480.f; + + return std::make_pair(fx, fy); }