diff --git a/CMakeLists.txt b/CMakeLists.txt index 82bf44e705..543d102f2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -229,6 +229,11 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE $<$:NOCRYPT> $<$,$>:_USE_MATH_DEFINES>) +if(UNIX AND NOT ANDROID AND NOT APPLE) + execute_process(COMMAND getconf PAGESIZE OUTPUT_VARIABLE PAGE_SIZE OUTPUT_STRIP_TRAILING_WHITESPACE) + target_compile_definitions(${PROJECT_NAME} PRIVATE PAGE_SIZE=${PAGE_SIZE}) +endif() + if(NOT "${SENTRY_UPLOAD_URL}" STREQUAL "") target_compile_definitions(${PROJECT_NAME} PRIVATE SENTRY_UPLOAD="${SENTRY_UPLOAD_URL}") endif() @@ -960,7 +965,8 @@ cmrc_add_resources(flycast-resources resources/flash/dirtypig.nvmem2.zip resources/flash/vf4.nvmem.zip # card all day, stage select resources/flash/vf4evob.nvmem.zip # card all day, stage select - resources/flash/vf4tuned.nvmem.zip) # card all day, stage select, 45 sec time limit, 3 match + resources/flash/vf4tuned.nvmem.zip # card all day, stage select, 45 sec time limit, 3 match + resources/picture/f355_print_template.png) cmrc_add_resources(flycast-resources fonts/printer_ascii8x16.bin diff --git a/core/cfg/option.cpp b/core/cfg/option.cpp index 474973bc5f..48e98f3327 100644 --- a/core/cfg/option.cpp +++ b/core/cfg/option.cpp @@ -94,6 +94,7 @@ std::array, 4> CrosshairColor { Option("rend.CrossHairColor3"), Option("rend.CrossHairColor4"), }; +Option CrosshairSize("rend.CrosshairSize", 40); Option SkipFrame("ta.skip"); Option MaxThreads("pvr.MaxThreads", 3); Option AutoSkipFrame("pvr.AutoSkipFrame", 0); @@ -108,9 +109,9 @@ Option PerPixelLayers("rend.PerPixelLayers", 32); Option NativeDepthInterpolation("rend.NativeDepthInterpolation", false); Option EmulateFramebuffer("rend.EmulateFramebuffer", false); #ifdef VIDEO_ROUTING -Option VideoRouting("rend.VideoRouting", false); -Option VideoRoutingScale("rend.VideoRoutingScale", false); -Option VideoRoutingVRes("rend.VideoRoutingVRes", 720); +Option VideoRouting("rend.VideoRouting", false); +Option VideoRoutingScale("rend.VideoRoutingScale", false); +Option VideoRoutingVRes("rend.VideoRoutingVRes", 720); #endif // Misc diff --git a/core/cfg/option.h b/core/cfg/option.h index 02ef6cc341..8b382c3087 100644 --- a/core/cfg/option.h +++ b/core/cfg/option.h @@ -461,6 +461,7 @@ extern Option PerStripSorting; extern Option DelayFrameSwapping; // Delay swapping frame until FB_R_SOF matches FB_W_SOF extern Option WidescreenGameHacks; extern std::array, 4> CrosshairColor; +extern Option CrosshairSize; extern Option SkipFrame; extern Option MaxThreads; extern Option AutoSkipFrame; // 0: none, 1: some, 2: more @@ -474,9 +475,9 @@ extern Option DupeFrames; extern Option NativeDepthInterpolation; extern Option EmulateFramebuffer; #ifdef VIDEO_ROUTING -extern Option VideoRouting; -extern Option VideoRoutingScale; -extern Option VideoRoutingVRes; +extern Option VideoRouting; +extern Option VideoRoutingScale; +extern Option VideoRoutingVRes; #endif // Misc diff --git a/core/hw/naomi/naomi_cart.cpp b/core/hw/naomi/naomi_cart.cpp index 8fa96f88f5..4c1ac5e20e 100644 --- a/core/hw/naomi/naomi_cart.cpp +++ b/core/hw/naomi/naomi_cart.cpp @@ -684,7 +684,7 @@ void naomi_cart_LoadRom(const std::string& path, const std::string& fileName, Lo } if (gameId == " TOUCH DE UNOH -------------" || gameId == " TOUCH DE UNOH 2 -----------" - || (gameId == "F355 CHALLENGE JAPAN" && config::MultiboardSlaves == 2)) + || (gameId == "F355 CHALLENGE JAPAN" && (config::MultiboardSlaves == 2 || romName == "f355"))) { printer::init(); } diff --git a/core/hw/naomi/naomi_flashrom.cpp b/core/hw/naomi/naomi_flashrom.cpp index 1d9a7cea55..5732871616 100644 --- a/core/hw/naomi/naomi_flashrom.cpp +++ b/core/hw/naomi/naomi_flashrom.cpp @@ -136,7 +136,7 @@ void write_naomi_eeprom(u32 offset, u8 value) WARN_LOG(NAOMI, "EEPROM record doesn't exist or is too short"); } -static u8 readEeprom(u32 offset) +u8 read_naomi_eeprom(u32 offset) { return EEPROM[offset & 127]; } @@ -164,7 +164,7 @@ static bool initEeprom(const RomBootID *bootId) // ROM-specific defaults write_naomi_eeprom(2, bootId->coinFlag[0][1] | (((bootId->coinFlag[0][1] & 2) ^ 2) << 3)); if (bootId->coinFlag[0][2] == 1) // individual coin chute - write_naomi_eeprom(8, readEeprom(8) | 1); + write_naomi_eeprom(8, read_naomi_eeprom(8) | 1); write_naomi_eeprom(9, bootId->coinFlag[0][3] - 1); write_naomi_eeprom(10, std::max(bootId->coinFlag[0][6], (u8)1)); write_naomi_eeprom(11, std::max(bootId->coinFlag[0][4], (u8)1)); @@ -199,21 +199,21 @@ void configure_naomi_eeprom(const RomBootID *bootId) if (bootId->vertical == 2) { NOTICE_LOG(NAOMI, "EEPROM: vertical monitor orientation"); - write_naomi_eeprom(2, readEeprom(2) | 1); + write_naomi_eeprom(2, read_naomi_eeprom(2) | 1); config::Rotate90.override(true); } else if (bootId->vertical == 1) { NOTICE_LOG(NAOMI, "EEPROM: horizontal monitor orientation"); - write_naomi_eeprom(2, readEeprom(2) & ~1); + write_naomi_eeprom(2, read_naomi_eeprom(2) & ~1); } // Number of players if (bootId->cabinet != 0 && bootId->cabinet < 0x10) { - int nPlayers = readEeprom(8) >> 4; // 0 to 3 + int nPlayers = read_naomi_eeprom(8) >> 4; // 0 to 3 if (!(bootId->cabinet & (1 << nPlayers))) { - u8 coinChute = readEeprom(8) & 1; + u8 coinChute = read_naomi_eeprom(8) & 1; if (bootId->cabinet & 8) { NOTICE_LOG(NAOMI, "EEPROM: 4-player cabinet"); diff --git a/core/hw/naomi/naomi_flashrom.h b/core/hw/naomi/naomi_flashrom.h index e914a7b0ac..e5e26180c1 100644 --- a/core/hw/naomi/naomi_flashrom.h +++ b/core/hw/naomi/naomi_flashrom.h @@ -23,6 +23,7 @@ #include "naomi_cart.h" void write_naomi_flash(u32 addr, u8 value); +u8 read_naomi_eeprom(u32 offset); void write_naomi_eeprom(u32 offset, u8 value); void configure_naomi_eeprom(const RomBootID *bootId); void configure_maxspeed_flash(bool enableNetwork, bool master); diff --git a/core/hw/naomi/printer.cpp b/core/hw/naomi/printer.cpp index 2b98a26c37..b7b31cf296 100644 --- a/core/hw/naomi/printer.cpp +++ b/core/hw/naomi/printer.cpp @@ -25,13 +25,19 @@ #include #include #ifdef STANDALONE_TEST +#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION #undef INFO_LOG #define INFO_LOG(t, s, ...) printf(s "\n", __VA_ARGS__) +#undef NOTICE_LOG +#define NOTICE_LOG INFO_LOG +#undef ERROR_LOG +#define ERROR_LOG INFO_LOG #else #include CMRC_DECLARE(flycast); #endif +#include #include namespace printer @@ -311,6 +317,59 @@ class BitmapWriter { if (page.empty()) return false; + if (settings.content.gameId.substr(0, 4) == "F355") + { + u8 *data = nullptr; + int x, y, comp; +#ifndef STANDALONE_TEST + try { + cmrc::embedded_filesystem fs = cmrc::flycast::get_filesystem(); + cmrc::file templateFile = fs.open("picture/f355_print_template.png"); + const u8 *fileData = (const u8 *)templateFile.begin(); + data = stbi_load_from_memory(fileData, templateFile.size(), &x, &y, &comp, STBI_rgb_alpha); + } catch (const std::system_error& e) { + ERROR_LOG(NAOMI, "Failed to load the printer template: %s", e.what()); + } +#else + FILE *f = fopen("f355_print_template.png", "rb"); + if (f != nullptr) + { + data = stbi_load_from_file(f, &x, &y, &comp, STBI_rgb_alpha); + fclose(f); + } + else + fprintf(stderr, "Can't open template file %d\n", errno); +#endif + if (data != nullptr && (x != printerWidth || comp != STBI_rgb_alpha)) + { + ERROR_LOG(NAOMI, "Invalid printer template: width %d comp %d", x, comp); + stbi_image_free(data); + data = nullptr; + } + if (data != nullptr) + { + if (lines > y) + { + u8 *newData = (u8 *)malloc(printerWidth * 4 * lines); + const u8 *end = newData + printerWidth * 4 * lines; + for (u8 *p = newData; p < end; p += printerWidth * 4 * y) + memcpy(p, data, std::min(printerWidth * 4 * y, (int)(end - p))); + stbi_image_free(data); + data = newData; + } + u32 *p = (u32 *)data; + for (u8 b : page) + { + if (b == 0xff) + *p = 0xff000000; + p++; + } + stbi_write_png(filename.c_str(), printerWidth, lines, 4, data, printerWidth * 4); + stbi_image_free(data); + + return true; + } + } for (u8& b : page) b = 0xff - b; stbi_write_png(filename.c_str(), printerWidth, lines, 1, &page[0], printerWidth); @@ -744,6 +803,7 @@ class ThermalPrinter bitmapWriter.reset(); s = "Print out saved to " + s; gui_display_notification(s.c_str(), 5000); + NOTICE_LOG(NAOMI, "%s", s.c_str()); } break; case 'K': // Set Kanji mode @@ -1084,6 +1144,14 @@ void deserialize(Deserializer& deser) #ifdef STANDALONE_TEST settings_t settings; +std::string get_writable_data_path(const std::string& s) +{ + return "./" + s; +} + +void gui_display_notification(char const*, int) { +} + int main(int argc, char *argv[]) { if (argc < 2) @@ -1093,7 +1161,7 @@ int main(int argc, char *argv[]) perror(argv[1]); return 1; } - settings.content.gameId = "somegame"; + settings.content.gameId = "F355 CHALLENGE"; printer::ThermalPrinter printer; for (;;) { diff --git a/core/network/naomi_network.cpp b/core/network/naomi_network.cpp index 0b89cd9911..758cea4377 100644 --- a/core/network/naomi_network.cpp +++ b/core/network/naomi_network.cpp @@ -350,7 +350,7 @@ void SetNaomiNetworkConfig(int node) write_naomi_flash(0x224, node == -1 ? 0 : 1); // network on write_naomi_flash(0x220, node == 0 ? 0 : 1); // node id } - else if (gameId == "CLUB KART IN JAPAN") + else if (gameId == "CLUB KART IN JAPAN" && settings.content.fileName.substr(0, 6) != "clubkp") { write_naomi_eeprom(0x34, node + 1); // also 03 = satellite } @@ -358,19 +358,20 @@ void SetNaomiNetworkConfig(int node) || gameId == "INITIAL D Ver.2" || gameId == "INITIAL D Ver.3") { - write_naomi_eeprom(0x34, node == -1 ? 0x02 : node == 0 ? 0x12 : 0x22); + u8 b = read_naomi_eeprom(0x34) & 0xcf; + write_naomi_eeprom(0x34, (node == -1 ? 0x00 : node == 0 ? 0x10 : 0x20) | b); } else if (gameId == "THE KING OF ROUTE66") { - write_naomi_eeprom(0x3d, node == -1 ? 0x44 : node == 0 ? 0x54 : 0x64); + u8 b = read_naomi_eeprom(0x3d) & 0xf; + write_naomi_eeprom(0x3d, (node == -1 ? 0x40 : node == 0 ? 0x50 : 0x60) | b); } else if (gameId == "MAXIMUM SPEED") { configure_maxspeed_flash(node != -1, node == 0); } - else if (gameId == "F355 CHALLENGE JAPAN") + else if (gameId == "F355 CHALLENGE JAPAN" && settings.content.fileName != "f355") { - // FIXME need default flash write_naomi_flash(0x230, node == -1 ? 0 : node == 0 ? 1 : 2); if (node != -1) // car number (0 to 7) @@ -393,6 +394,9 @@ bool NaomiNetworkSupported() }; if (!config::NetworkEnable) return false; + if (settings.content.fileName.substr(0, 6) == "clubkp" || settings.content.fileName == "f355") + // Club Kart Prize and F355 (vanilla) don't support networking + return false; for (auto game : games) if (settings.content.gameId == game) return true; diff --git a/core/rend/dx11/dx11_overlay.cpp b/core/rend/dx11/dx11_overlay.cpp index 7f171656e1..741cc560fd 100644 --- a/core/rend/dx11/dx11_overlay.cpp +++ b/core/rend/dx11/dx11_overlay.cpp @@ -28,14 +28,17 @@ void DX11Overlay::draw(u32 width, u32 height, bool vmu, bool crosshair) deviceContext->RSSetScissorRects(1, &rect); if (vmu) { +#ifndef LIBRETRO float vmu_padding = 8.f * settings.display.uiScale; float vmu_height = 70.f * settings.display.uiScale; float vmu_width = 48.f / 32.f * vmu_height; -#ifndef LIBRETRO const float blend_factor[4] = { 0.75f, 0.75f, 0.75f, 0.75f }; deviceContext->OMSetBlendState(blendStates.getState(true, 8, 8), blend_factor, 0xffffffff); #else + float vmu_padding = 8.f * config::RenderResolution / 480.f; + float vmu_height = 32.f * config::RenderResolution / 480.f; + float vmu_width = 48.f * config::RenderResolution / 480.f; deviceContext->OMSetBlendState(blendStates.getState(true, 4, 5), nullptr, 0xffffffff); #endif @@ -169,11 +172,11 @@ void DX11Overlay::draw(u32 width, u32 height, bool vmu, bool crosshair) auto [x, y] = getCrosshairPosition(i); #ifdef LIBRETRO - float halfWidth = LIGHTGUN_CROSSHAIR_SIZE / 2.f / config::ScreenStretching * 100.f; - float halfHeight = LIGHTGUN_CROSSHAIR_SIZE / 2.f; + float halfWidth = lightgun_crosshair_size / 2.f / config::ScreenStretching * 100.f * config::RenderResolution / 480.f; + float halfHeight = lightgun_crosshair_size / 2.f * config::RenderResolution / 480.f; x /= config::ScreenStretching / 100.f; #else - float halfWidth = XHAIR_WIDTH * settings.display.uiScale / 2.f; + float halfWidth = config::CrosshairSize * settings.display.uiScale / 2.f; float halfHeight = halfWidth; #endif D3D11_VIEWPORT vp{}; diff --git a/core/rend/dx9/d3d_overlay.cpp b/core/rend/dx9/d3d_overlay.cpp index 271f555f24..fda6e2d5d4 100644 --- a/core/rend/dx9/d3d_overlay.cpp +++ b/core/rend/dx9/d3d_overlay.cpp @@ -118,7 +118,7 @@ void D3DOverlay::draw(u32 width, u32 height, bool vmu, bool crosshair) continue; auto [x, y] = getCrosshairPosition(i); - float halfWidth = XHAIR_WIDTH * settings.display.uiScale / 2.f; + float halfWidth = config::CrosshairSize * settings.display.uiScale / 2.f; RECT rect { (long) (x - halfWidth), (long) (y - halfWidth), (long) (x + halfWidth), (long) (y + halfWidth) }; D3DCOLOR color = (config::CrosshairColor[i] & 0xFF00FF00) | ((config::CrosshairColor[i] >> 16) & 0xFF) diff --git a/core/rend/dx9/d3d_renderer.cpp b/core/rend/dx9/d3d_renderer.cpp index d42d22e25f..4397c5f430 100644 --- a/core/rend/dx9/d3d_renderer.cpp +++ b/core/rend/dx9/d3d_renderer.cpp @@ -876,7 +876,7 @@ void D3DRenderer::setBaseScissor() } } -void D3DRenderer::prepareRttRenderTarget(u32 texAddress) +void D3DRenderer::prepareRttRenderTarget(u32 texAddress, int& vpWidth, int& vpHeight) { u32 fbw = pvrrc.getFramebufferWidth(); u32 fbh = pvrrc.getFramebufferHeight(); @@ -916,6 +916,8 @@ void D3DRenderer::prepareRttRenderTarget(u32 texAddress) viewport.MinZ = 0; viewport.MaxZ = 1; device->SetViewport(&viewport); + vpWidth = fbw; + vpHeight = fbh; } void D3DRenderer::readRttRenderTarget(u32 texAddress) @@ -982,9 +984,10 @@ bool D3DRenderer::Render() bool rc = SUCCEEDED(device->GetRenderTarget(0, &backbuffer.get())); verify(rc); u32 texAddress = pvrrc.fb_W_SOF1 & VRAM_MASK; + int vpWidth, vpHeight; if (is_rtt) { - prepareRttRenderTarget(texAddress); + prepareRttRenderTarget(texAddress, vpWidth, vpHeight); } else { @@ -1001,13 +1004,15 @@ bool D3DRenderer::Render() viewport.MaxZ = 1; rc = SUCCEEDED(device->SetViewport(&viewport)); verify(rc); + vpWidth = width; + vpHeight = height; } rc = SUCCEEDED(device->SetDepthStencilSurface(depthSurface)); verify(rc); matrices.CalcMatrices(&pvrrc, width, height); // infamous DX9 half-pixel viewport shift // https://docs.microsoft.com/en-us/windows/win32/direct3d9/directly-mapping-texels-to-pixels - glm::mat4 normalMat = glm::translate(glm::vec3(-1.f / width, 1.f / height, 0)) * matrices.GetNormalMatrix(); + glm::mat4 normalMat = glm::translate(glm::vec3(1.f / vpWidth, 1.f / vpHeight, 0)) * matrices.GetNormalMatrix(); rc = SUCCEEDED(device->SetVertexShaderConstantF(0, &normalMat[0][0], 4)); verify(rc); @@ -1124,6 +1129,7 @@ bool D3DRenderer::Render() devCache.SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); devCache.SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + devCache.SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); devCache.SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); devCache.SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); devCache.SetRenderState(D3DRS_CLIPPING, FALSE); diff --git a/core/rend/dx9/d3d_renderer.h b/core/rend/dx9/d3d_renderer.h index aba95d5525..36e360cd19 100644 --- a/core/rend/dx9/d3d_renderer.h +++ b/core/rend/dx9/d3d_renderer.h @@ -136,7 +136,7 @@ struct D3DRenderer : public Renderer void drawModVols(int first, int count); void setTexMode(D3DSAMPLERSTATETYPE state, u32 clamp, u32 mirror); void setBaseScissor(); - void prepareRttRenderTarget(u32 texAddress); + void prepareRttRenderTarget(u32 texAddress, int& vpWidth, int& vpHeight); void readRttRenderTarget(u32 texAddress); void writeFramebufferToVRAM(); diff --git a/core/rend/gles/gldraw.cpp b/core/rend/gles/gldraw.cpp index f8ae96a336..529bcc9b43 100644 --- a/core/rend/gles/gldraw.cpp +++ b/core/rend/gles/gldraw.cpp @@ -828,11 +828,11 @@ static void updateVmuTexture(int vmu_screen_number) void DrawVmuTexture(u8 vmu_screen_number, int width, int height) { - constexpr float vmu_padding = 8.f; + float vmu_padding = 8.f * config::RenderResolution / 480.f; float x = vmu_padding; float y = vmu_padding; - float w = (float)VMU_SCREEN_WIDTH * vmu_screen_params[vmu_screen_number].vmu_screen_size_mult * 4.f / 3.f / gl.ofbo.aspectRatio; - float h = (float)VMU_SCREEN_HEIGHT * vmu_screen_params[vmu_screen_number].vmu_screen_size_mult; + float w = (float)VMU_SCREEN_WIDTH * vmu_screen_params[vmu_screen_number].vmu_screen_size_mult * 4.f / 3.f / gl.ofbo.aspectRatio * config::RenderResolution / 480.f; + float h = (float)VMU_SCREEN_HEIGHT * vmu_screen_params[vmu_screen_number].vmu_screen_size_mult * config::RenderResolution / 480.f; if (vmu_lcd_changed[vmu_screen_number * 2] || vmuTextureId[vmu_screen_number] == 0) updateVmuTexture(vmu_screen_number); @@ -919,8 +919,8 @@ void DrawGunCrosshair(u8 port, int width, int height) if (lightgun_params[port].offscreen || lightgun_params[port].colour == 0) return; - float w = (float)LIGHTGUN_CROSSHAIR_SIZE * 4.f / 3.f / gl.ofbo.aspectRatio; - float h = (float)LIGHTGUN_CROSSHAIR_SIZE; + float w = lightgun_crosshair_size * 4.f / 3.f / gl.ofbo.aspectRatio * config::RenderResolution / 480.f; + float h = lightgun_crosshair_size * config::RenderResolution / 480.f; auto [x, y] = getCrosshairPosition(port); x -= w / 2; y -= h / 2; @@ -939,10 +939,8 @@ void DrawGunCrosshair(u8 port, int width, int height) x1, y, 1.f, 1.f, 1.f, }; glcache.Enable(GL_BLEND); - glcache.BlendFunc(GL_SRC_ALPHA, GL_ONE); - drawQuad(lightgunTextureId[port], false, false, vertices); - glcache.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + drawQuad(lightgunTextureId[port], false, false, vertices); } void termVmuLightgun() diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index 68eb0f9653..b6ce618c56 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -1401,13 +1401,13 @@ bool OpenGLRenderer::renderFrame(int width, int height) ReadRTTBuffer(); else if (config::EmulateFramebuffer) writeFramebufferToVRAM(); -#ifndef LIBRETRO else { gl.ofbo.aspectRatio = getOutputFramebufferAspectRatio(); +#ifndef LIBRETRO gl.ofbo2.ready = false; renderLastFrame(); - } #endif + } GlVertexArray::unbind(); return !is_rtt; diff --git a/core/rend/gles/opengl_driver.cpp b/core/rend/gles/opengl_driver.cpp index 8705b661f2..c0ef1f2453 100644 --- a/core/rend/gles/opengl_driver.cpp +++ b/core/rend/gles/opengl_driver.cpp @@ -144,9 +144,9 @@ void OpenGLDriver::displayCrosshairs() ImVec2 pos; std::tie(pos.x, pos.y) = getCrosshairPosition(i); - pos.x -= (XHAIR_WIDTH * settings.display.uiScale) / 2.f; - pos.y += (XHAIR_WIDTH * settings.display.uiScale) / 2.f; - ImVec2 pos_b(pos.x + XHAIR_WIDTH * settings.display.uiScale, pos.y - XHAIR_HEIGHT * settings.display.uiScale); + pos.x -= (config::CrosshairSize * settings.display.uiScale) / 2.f; + pos.y += (config::CrosshairSize * settings.display.uiScale) / 2.f; + ImVec2 pos_b(pos.x + config::CrosshairSize * settings.display.uiScale, pos.y - config::CrosshairSize * settings.display.uiScale); ImGui::GetWindowDrawList()->AddImage(crosshairTexId, pos, pos_b, ImVec2(0, 1), ImVec2(1, 0), config::CrosshairColor[i]); } diff --git a/core/rend/gui.cpp b/core/rend/gui.cpp index 9f4753ee18..eed7d79b9f 100644 --- a/core/rend/gui.cpp +++ b/core/rend/gui.cpp @@ -1729,6 +1729,7 @@ static void gui_display_settings() ImGui::Spacing(); header("Dreamcast Devices"); { + bool is_there_any_xhair = false; for (int bus = 0; bus < MAPLE_PORTS; bus++) { ImGui::Text("Device %c", bus + 'A'); @@ -1819,10 +1820,15 @@ static void gui_display_settings() config::CrosshairColor[bus] = 0; } } + is_there_any_xhair |= enabled; ImGui::PopID(); } ImGui::PopItemWidth(); } + { + DisabledScope scope(!is_there_any_xhair); + OptionSlider("Crosshair Size", config::CrosshairSize, 10, 100); + } OptionCheckbox("Per Game VMU A1", config::PerGameVmu, "When enabled, each game has its own VMU on port 1 of controller A."); } diff --git a/core/rend/osd.h b/core/rend/osd.h index 63ed099db5..52d65fa5a6 100644 --- a/core/rend/osd.h +++ b/core/rend/osd.h @@ -48,9 +48,6 @@ void push_vmu_screen(int bus_id, int bus_port, u8* buffer); const u32 *getCrosshairTextureData(); std::pair getCrosshairPosition(int playerNum); -constexpr int XHAIR_WIDTH = 40; -constexpr int XHAIR_HEIGHT = 40; - static inline bool crosshairsNeeded() { if (config::CrosshairColor[0] == 0 && config::CrosshairColor[1] == 0 diff --git a/core/rend/vulkan/overlay.cpp b/core/rend/vulkan/overlay.cpp index 99101d385f..ea8d68a525 100644 --- a/core/rend/vulkan/overlay.cpp +++ b/core/rend/vulkan/overlay.cpp @@ -210,12 +210,12 @@ void VulkanOverlay::Draw(vk::CommandBuffer commandBuffer, vk::Extent2D viewport, auto [x, y] = getCrosshairPosition(i); #ifdef LIBRETRO - float w = LIGHTGUN_CROSSHAIR_SIZE * scaling / config::ScreenStretching * 100.f; - float h = LIGHTGUN_CROSSHAIR_SIZE * scaling; + float w = lightgun_crosshair_size * scaling / config::ScreenStretching * 100.f; + float h = lightgun_crosshair_size * scaling; x /= config::ScreenStretching / 100.f; #else - float w = XHAIR_WIDTH * scaling; - float h = XHAIR_HEIGHT * scaling; + float w = config::CrosshairSize * scaling; + float h = config::CrosshairSize * scaling; #endif x -= w / 2; y -= h / 2; diff --git a/core/stdclass.h b/core/stdclass.h index d67901efe4..d2e83a78a6 100644 --- a/core/stdclass.h +++ b/core/stdclass.h @@ -15,7 +15,7 @@ #undef PAGE_MASK #elif defined(__APPLE__) && defined(__aarch64__) #define PAGE_SIZE 16384 -#else +#elif !defined(PAGE_SIZE) #define PAGE_SIZE 4096 #endif #ifndef PAGE_MASK diff --git a/resources/picture/f355_print_template.png b/resources/picture/f355_print_template.png new file mode 100644 index 0000000000..39189edef6 Binary files /dev/null and b/resources/picture/f355_print_template.png differ diff --git a/shell/libretro/libretro.cpp b/shell/libretro/libretro.cpp index 8b714241d9..ebb26d6eae 100644 --- a/shell/libretro/libretro.cpp +++ b/shell/libretro/libretro.cpp @@ -609,6 +609,9 @@ static bool set_variable_visibility(void) { option_display.visible = lightgunSettingsShown; + option_display.key = CORE_OPTION_NAME "_lightgun_crosshair_size_scaling"; + environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display); + for (unsigned i = 0; i < 4; i++) { char key[256]; @@ -911,6 +914,12 @@ static void update_variables(bool first_startup) else allow_service_buttons = false; + var.key = CORE_OPTION_NAME "_lightgun_crosshair_size_scaling"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + lightgun_crosshair_size = (float)LIGHTGUN_CROSSHAIR_SIZE * std::stof(var.value) / 100.f; + else + lightgun_crosshair_size = (float)LIGHTGUN_CROSSHAIR_SIZE; + char key[256]; key[0] = '\0'; diff --git a/shell/libretro/libretro_core_options.h b/shell/libretro/libretro_core_options.h index 33440768c4..f45f1f8e83 100644 --- a/shell/libretro/libretro_core_options.h +++ b/shell/libretro/libretro_core_options.h @@ -878,6 +878,44 @@ struct retro_core_option_v2_definition option_defs_us[] = { }, "disabled" }, + { + CORE_OPTION_NAME "_lightgun_crosshair_size_scaling", + "Gun Crosshair Size Scaling", + NULL, + "", + NULL, + "input", + { + { "50%", NULL }, + { "60%", NULL }, + { "70%", NULL }, + { "80%", NULL }, + { "90%", NULL }, + { "100%", NULL }, + { "110%", NULL }, + { "120%", NULL }, + { "130%", NULL }, + { "140%", NULL }, + { "150%", NULL }, + { "160%", NULL }, + { "170%", NULL }, + { "180%", NULL }, + { "190%", NULL }, + { "200%", NULL }, + { "210%", NULL }, + { "220%", NULL }, + { "230%", NULL }, + { "240%", NULL }, + { "250%", NULL }, + { "260%", NULL }, + { "270%", NULL }, + { "280%", NULL }, + { "290%", NULL }, + { "300%", NULL }, + { NULL, NULL }, + }, + "100%", + }, { CORE_OPTION_NAME "_lightgun1_crosshair", "Gun Crosshair 1 Display", diff --git a/shell/libretro/libretro_core_options_intl.h b/shell/libretro/libretro_core_options_intl.h index 2075f21b05..b4429c9b2b 100644 --- a/shell/libretro/libretro_core_options_intl.h +++ b/shell/libretro/libretro_core_options_intl.h @@ -11085,7 +11085,7 @@ struct retro_core_options_v2 options_cht = { #define CORE_OPTION_NAME_GDROM_FAST_LOADING_LABEL_CS "Rychlé Načítání GD-ROM (nepřesné)" #define CORE_OPTION_NAME_GDROM_FAST_LOADING_INFO_0_CS "Zrychluje načítání GD-ROM." #define CORE_OPTION_NAME_DC_32MB_MOD_LABEL_CS NULL -#define CORE_OPTION_NAME_DC_32MB_MOD_INFO_0_CS NULL +#define CORE_OPTION_NAME_DC_32MB_MOD_INFO_0_CS "Povoluje 32MB RAM Mod pro Dreamcast. Může ovlivnit kompatibilitu" #define CORE_OPTION_NAME_SH4CLOCK_LABEL_CS "Podtaktování/přetaktování procesoru SH4" #define CORE_OPTION_NAME_SH4CLOCK_INFO_0_CS "Změňte takt hlavního procesoru SH4 z výchozích 200 MHz. Podtaktování může pomoci pomalým platformám. Přetaktování může u některých her zvýšit snímkovou frekvenci. Používejte s opatrností." #define OPTION_VAL_100_CS NULL @@ -16592,14 +16592,14 @@ struct retro_core_options_v2 options_da = { #define CORE_OPTION_NAME_NETWORK_OUTPUT_INFO_0_DE "Digitale Ausgänge und Force-Feedback-Status auf TCP-Port 8000 übertragen. Kompatibel mit der MAME-Option „-output network“." #define CORE_OPTION_NAME_SHOW_LIGHTGUN_SETTINGS_LABEL_DE "Lightgun-Einstellungen anzeigen" #define CORE_OPTION_NAME_SHOW_LIGHTGUN_SETTINGS_INFO_0_DE "Aktiviert die Konfiguration der Lightgun-Fadenkreuz-Anzeigeoptionen. HINWEIS: Schnellmenü muss eingeschaltet sein, damit diese Einstellung wirksam wird." -#define CORE_OPTION_NAME_LIGHTGUN1_CROSSHAIR_LABEL_DE "Pistolen Fadenkreuz 1 anzeigen" +#define CORE_OPTION_NAME_LIGHTGUN1_CROSSHAIR_LABEL_DE "Anzeige Pistolen-Fadenkreuz 1" #define OPTION_VAL_WHITE_DE "Weiß" #define OPTION_VAL_RED_DE "Rot" #define OPTION_VAL_GREEN_DE "Grün" #define OPTION_VAL_BLUE_DE "Blau" -#define CORE_OPTION_NAME_LIGHTGUN2_CROSSHAIR_LABEL_DE "Pistolen Fadenkreuz 2 anzeigen" -#define CORE_OPTION_NAME_LIGHTGUN3_CROSSHAIR_LABEL_DE "Pistolen Fadenkreuz 3 anzeigen" -#define CORE_OPTION_NAME_LIGHTGUN4_CROSSHAIR_LABEL_DE "Pistolen Fadenkreuz 4 anzeigen" +#define CORE_OPTION_NAME_LIGHTGUN2_CROSSHAIR_LABEL_DE "Anzeige Pistolen-Fadenkreuz 2" +#define CORE_OPTION_NAME_LIGHTGUN3_CROSSHAIR_LABEL_DE "Anzeige Pistolen-Fadenkreuz 3" +#define CORE_OPTION_NAME_LIGHTGUN4_CROSSHAIR_LABEL_DE "Anzeige Pistolen-Fadenkreuz 4" #define CORE_OPTION_NAME_PER_CONTENT_VMUS_LABEL_DE "Visual Memory Units/Systeme (VMU) pro Spiel" #define CORE_OPTION_NAME_PER_CONTENT_VMUS_LABEL_CAT_DE "VMUs pro Spiel" #define CORE_OPTION_NAME_PER_CONTENT_VMUS_INFO_0_DE "Wenn deaktiviert, teilen alle Spiele 4 VMU-Speicherdateien (A1, B1, C1, D1) im Systemverzeichnis von RetroArch. Die Einstellung „VMU A1“ erzeugt für jedes Spiel, das gestartet wird, eine einzigartige VMU-„A1“-Datei im Speicherverzeichnis von RetroArch. Die Einstellung „Alle VMUs“ erzeugt 4 einzigartige VMU-Dateien (A1, B1, C1, D1) für jedes Spiel, das gestartet wird." diff --git a/shell/libretro/vmu_xhair.cpp b/shell/libretro/vmu_xhair.cpp index 5a1cf7030f..d90729f283 100644 --- a/shell/libretro/vmu_xhair.cpp +++ b/shell/libretro/vmu_xhair.cpp @@ -112,6 +112,7 @@ u8 lightgun_palette[LIGHTGUN_COLORS_COUNT*3] = }; lightgun_params_t lightgun_params[4]; +float lightgun_crosshair_size = (float)LIGHTGUN_CROSSHAIR_SIZE; std::pair getCrosshairPosition(int playerNum) { diff --git a/shell/libretro/vmu_xhair.h b/shell/libretro/vmu_xhair.h index 208eed9f9f..4bf13709ff 100644 --- a/shell/libretro/vmu_xhair.h +++ b/shell/libretro/vmu_xhair.h @@ -111,3 +111,4 @@ struct lightgun_params_t { extern u8 lightgun_palette[LIGHTGUN_COLORS_COUNT*3]; extern u8 lightgun_img_crosshair[LIGHTGUN_CROSSHAIR_SIZE*LIGHTGUN_CROSSHAIR_SIZE]; extern lightgun_params_t lightgun_params[4] ; +extern float lightgun_crosshair_size;