more work

This commit is contained in:
Connor McLaughlin 2022-07-13 22:49:40 +10:00
parent 97ed8b2cb5
commit 266eaf0ee6
165 changed files with 7001 additions and 4308 deletions

View File

@ -41,8 +41,8 @@ void AnalogController::Reset()
{
if (g_settings.controller_disable_analog_mode_forcing)
{
g_host_interface->AddOSDMessage(
g_host_interface->TranslateStdString(
Host::AddOSDMessage(
Host::TranslateStdString(
"OSDMessage", "Analog mode forcing is disabled by game settings. Controller will start in digital mode."),
10.0f);
}
@ -89,11 +89,11 @@ bool AnalogController::DoState(StateWrapper& sw, bool apply_input_state)
if (old_analog_mode != m_analog_mode)
{
g_host_interface->AddFormattedOSDMessage(
Host::AddFormattedOSDMessage(
5.0f,
m_analog_mode ?
g_host_interface->TranslateString("AnalogController", "Controller %u switched to analog mode.") :
g_host_interface->TranslateString("AnalogController", "Controller %u switched to digital mode."),
Host::TranslateString("AnalogController", "Controller %u switched to analog mode.") :
Host::TranslateString("AnalogController", "Controller %u switched to digital mode."),
m_index + 1u);
}
}
@ -113,7 +113,7 @@ void AnalogController::SetBindState(u32 index, float value)
if (index == static_cast<s32>(Button::Analog))
{
// analog toggle
if (value > 0.0f)
if (value >= 0.5f)
{
if (m_command == Command::Idle)
ProcessAnalogModeToggle();
@ -172,7 +172,7 @@ void AnalogController::SetBindState(u32 index, float value)
const u16 bit = u16(1) << static_cast<u8>(index);
// todo: deadzone
if (value > 0.0f)
if (value >= 0.5f)
{
if (m_button_state & bit)
System::SetRunaheadReplayFlag();
@ -240,10 +240,10 @@ void AnalogController::SetAnalogMode(bool enabled)
return;
Log_InfoPrintf("Controller %u switched to %s mode.", m_index + 1u, enabled ? "analog" : "digital");
g_host_interface->AddFormattedOSDMessage(
Host::AddFormattedOSDMessage(
5.0f,
enabled ? g_host_interface->TranslateString("AnalogController", "Controller %u switched to analog mode.") :
g_host_interface->TranslateString("AnalogController", "Controller %u switched to digital mode."),
enabled ? Host::TranslateString("AnalogController", "Controller %u switched to analog mode.") :
Host::TranslateString("AnalogController", "Controller %u switched to digital mode."),
m_index + 1u);
m_analog_mode = enabled;
}
@ -252,11 +252,11 @@ void AnalogController::ProcessAnalogModeToggle()
{
if (m_analog_locked)
{
g_host_interface->AddFormattedOSDMessage(
Host::AddFormattedOSDMessage(
5.0f,
m_analog_mode ?
g_host_interface->TranslateString("AnalogController", "Controller %u is locked to analog mode by the game.") :
g_host_interface->TranslateString("AnalogController", "Controller %u is locked to digital mode by the game."),
Host::TranslateString("AnalogController", "Controller %u is locked to analog mode by the game.") :
Host::TranslateString("AnalogController", "Controller %u is locked to digital mode by the game."),
m_index + 1u);
}
else
@ -707,41 +707,42 @@ std::unique_ptr<AnalogController> AnalogController::Create(u32 index)
}
static const Controller::ControllerBindingInfo s_binding_info[] = {
#define BUTTON(name, display_name, genb) \
#define BUTTON(name, display_name, button, genb) \
{ \
name, display_name, Controller::ControllerBindingType::Button, genb \
name, display_name, static_cast<u32>(button), Controller::ControllerBindingType::Button, genb \
}
#define AXIS(name, display_name, genb) \
#define AXIS(name, display_name, halfaxis, genb) \
{ \
name, display_name, Controller::ControllerBindingType::HalfAxis, genb \
name, display_name, static_cast<u32>(AnalogController::Button::Count) + static_cast<u32>(halfaxis), \
Controller::ControllerBindingType::HalfAxis, genb \
}
BUTTON("Select", "Select", GenericInputBinding::Select),
BUTTON("L3", "Select", GenericInputBinding::L3),
BUTTON("R3", "Select", GenericInputBinding::R3),
BUTTON("Start", "Select", GenericInputBinding::Start),
BUTTON("Up", "D-Pad Up", GenericInputBinding::DPadUp),
BUTTON("Right", "D-Pad Right", GenericInputBinding::DPadRight),
BUTTON("Down", "D-Pad Down", GenericInputBinding::DPadDown),
BUTTON("Left", "D-Pad Left", GenericInputBinding::DPadLeft),
BUTTON("L2", "L2", GenericInputBinding::L2),
BUTTON("R2", "R2", GenericInputBinding::R2),
BUTTON("L1", "L1", GenericInputBinding::L1),
BUTTON("R1", "R1", GenericInputBinding::R1),
BUTTON("Triangle", "Triangle", GenericInputBinding::Triangle),
BUTTON("Circle", "Circle", GenericInputBinding::Circle),
BUTTON("Cross", "Cross", GenericInputBinding::Cross),
BUTTON("Square", "Square", GenericInputBinding::Square),
BUTTON("Analog", "Analog Toggle", GenericInputBinding::System),
BUTTON("Up", "D-Pad Up", AnalogController::Button::Up, GenericInputBinding::DPadUp),
BUTTON("Right", "D-Pad Right", AnalogController::Button::Down, GenericInputBinding::DPadRight),
BUTTON("Down", "D-Pad Down", AnalogController::Button::Down, GenericInputBinding::DPadDown),
BUTTON("Left", "D-Pad Left", AnalogController::Button::Left, GenericInputBinding::DPadLeft),
BUTTON("Triangle", "Triangle", AnalogController::Button::Triangle, GenericInputBinding::Triangle),
BUTTON("Circle", "Circle", AnalogController::Button::Circle, GenericInputBinding::Circle),
BUTTON("Cross", "Cross", AnalogController::Button::Cross, GenericInputBinding::Cross),
BUTTON("Square", "Square", AnalogController::Button::Square, GenericInputBinding::Square),
BUTTON("Select", "Select", AnalogController::Button::Select, GenericInputBinding::Select),
BUTTON("Start", "Start", AnalogController::Button::Start, GenericInputBinding::Start),
BUTTON("Analog", "Analog Toggle", AnalogController::Button::Analog, GenericInputBinding::System),
BUTTON("L1", "L1", AnalogController::Button::L1, GenericInputBinding::L1),
BUTTON("R1", "R1", AnalogController::Button::R1, GenericInputBinding::R1),
BUTTON("L2", "L2", AnalogController::Button::L2, GenericInputBinding::L2),
BUTTON("R2", "R2", AnalogController::Button::R2, GenericInputBinding::R2),
BUTTON("L3", "L3", AnalogController::Button::L3, GenericInputBinding::L3),
BUTTON("R3", "R3", AnalogController::Button::R3, GenericInputBinding::R3),
AXIS("LLeft", "Left Stick Left", GenericInputBinding::LeftStickLeft),
AXIS("LRight", "Left Stick Right", GenericInputBinding::LeftStickRight),
AXIS("LDown", "Left Stick Down", GenericInputBinding::LeftStickDown),
AXIS("LUp", "Left Stick Up", GenericInputBinding::LeftStickUp),
AXIS("RLeft", "Right Stick Left", GenericInputBinding::LeftStickLeft),
AXIS("RRight", "Right Stick Right", GenericInputBinding::LeftStickRight),
AXIS("RDown", "Right Stick Down", GenericInputBinding::LeftStickDown),
AXIS("RUp", "Right Stick Up", GenericInputBinding::LeftStickUp),
AXIS("LLeft", "Left Stick Left", AnalogController::HalfAxis::LLeft, GenericInputBinding::LeftStickLeft),
AXIS("LRight", "Left Stick Right", AnalogController::HalfAxis::LRight, GenericInputBinding::LeftStickRight),
AXIS("LDown", "Left Stick Down", AnalogController::HalfAxis::LDown, GenericInputBinding::LeftStickDown),
AXIS("LUp", "Left Stick Up", AnalogController::HalfAxis::LUp, GenericInputBinding::LeftStickUp),
AXIS("RLeft", "Right Stick Left", AnalogController::HalfAxis::RLeft, GenericInputBinding::LeftStickLeft),
AXIS("RRight", "Right Stick Right", AnalogController::HalfAxis::RRight, GenericInputBinding::LeftStickRight),
AXIS("RDown", "Right Stick Down", AnalogController::HalfAxis::RDown, GenericInputBinding::LeftStickDown),
AXIS("RUp", "Right Stick Up", AnalogController::HalfAxis::RUp, GenericInputBinding::LeftStickUp),
#undef AXIS
#undef BUTTON

View File

@ -39,6 +39,19 @@ public:
Count
};
enum class HalfAxis : u8
{
LLeft,
LRight,
LDown,
LUp,
RLeft,
RRight,
RDown,
RUp,
Count
};
static constexpr u8 NUM_MOTORS = 2;
static const Controller::ControllerInfo INFO;
@ -82,19 +95,6 @@ private:
GetSetRumble // 0x4D
};
enum class HalfAxis : u8
{
LLeft,
LRight,
LDown,
LUp,
RLeft,
RRight,
RDown,
RUp,
Count
};
Command m_command = Command::Idle;
int m_command_step = 0;

View File

@ -10,7 +10,7 @@
#include "cpu_disasm.h"
#include "dma.h"
#include "gpu.h"
#include "host_interface.h"
#include "host.h"
#include "interrupt_controller.h"
#include "mdec.h"
#include "pad.h"
@ -130,7 +130,7 @@ bool Initialize()
{
if (!AllocateMemory(g_settings.enable_8mb_ram))
{
g_host_interface->ReportError("Failed to allocate memory");
Host::ReportErrorAsync("Error", "Failed to allocate memory");
return false;
}

View File

@ -9,6 +9,7 @@
#include "controller.h"
#include "cpu_code_cache.h"
#include "cpu_core.h"
#include "host.h"
#include "host_interface.h"
#include "system.h"
#include <cctype>

35
src/core/cheevos.h Normal file
View File

@ -0,0 +1,35 @@
#pragma once
#include "common/types.h"
class StateWrapper;
namespace Cheevos {
#ifdef WITH_CHEEVOS
// Implemented in Host.
extern void Reset();
extern bool DoState(StateWrapper& sw);
/// Returns true if features such as save states should be disabled.
extern bool IsChallengeModeActive();
extern void DisplayBlockedByChallengeModeMessage();
#else
// Make noops when compiling without cheevos.
static inline void Reset() {}
static inline bool DoState(StateWrapper& sw)
{
return true;
}
static constexpr inline bool IsChallengeModeActive()
{
return false;
}
static inline void DisplayBlockedByChallengeModeMessage() {}
#endif
} // namespace Cheevos

View File

@ -217,3 +217,8 @@ bool Controller::PortAndSlotIsMultitap(u32 port, u32 slot)
{
return (slot != 0);
}
std::string Controller::GetSettingsSection(u32 pad)
{
return fmt::format("Pad{}", pad + 1u);
}

View File

@ -40,6 +40,7 @@ public:
{
const char* name;
const char* display_name;
u32 bind_index;
ControllerBindingType type;
GenericInputBinding generic_mapping;
};
@ -133,6 +134,9 @@ public:
static bool PadIsMultitapSlot(u32 index);
static bool PortAndSlotIsMultitap(u32 port, u32 slot);
/// Returns the configuration section for the specified gamepad.
static std::string GetSettingsSection(u32 pad);
protected:
u32 m_index;
};

View File

@ -46,6 +46,7 @@
<ClCompile Include="gpu.cpp" />
<ClCompile Include="gpu_hw.cpp" />
<ClCompile Include="gpu_hw_opengl.cpp" />
<ClCompile Include="host.cpp" />
<ClCompile Include="host_display.cpp" />
<ClCompile Include="host_interface.cpp" />
<ClCompile Include="host_interface_progress_callback.cpp" />
@ -80,6 +81,7 @@
<ClInclude Include="cdrom.h" />
<ClInclude Include="cdrom_async_reader.h" />
<ClInclude Include="cheats.h" />
<ClInclude Include="cheevos.h" />
<ClInclude Include="cpu_core.h" />
<ClInclude Include="cpu_core_private.h" />
<ClInclude Include="cpu_disasm.h" />

View File

@ -58,6 +58,7 @@
<ClCompile Include="texture_replacements.cpp" />
<ClCompile Include="multitap.cpp" />
<ClCompile Include="gpu_hw_d3d12.cpp" />
<ClCompile Include="host.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="types.h" />
@ -122,5 +123,6 @@
<ClInclude Include="gdb_protocol.h" />
<ClInclude Include="host.h" />
<ClInclude Include="host_settings.h" />
<ClInclude Include="cheevos.h" />
</ItemGroup>
</Project>

View File

@ -7,7 +7,7 @@
#include "cpu_disasm.h"
#include "cpu_recompiler_thunks.h"
#include "gte.h"
#include "host_interface.h"
#include "host.h"
#include "pgxp.h"
#include "settings.h"
#include "system.h"
@ -1691,8 +1691,8 @@ bool AddBreakpoint(VirtualMemoryAddress address, bool auto_clear, bool enabled)
if (!auto_clear)
{
g_host_interface->ReportFormattedDebuggerMessage(
g_host_interface->TranslateString("DebuggerMessage", "Added breakpoint at 0x%08X."), address);
Host::ReportFormattedDebuggerMessage(Host::TranslateString("DebuggerMessage", "Added breakpoint at 0x%08X."),
address);
}
return true;
@ -1718,8 +1718,8 @@ bool RemoveBreakpoint(VirtualMemoryAddress address)
if (it == s_breakpoints.end())
return false;
g_host_interface->ReportFormattedDebuggerMessage(
g_host_interface->TranslateString("DebuggerMessage", "Removed breakpoint at 0x%08X."), address);
Host::ReportFormattedDebuggerMessage(Host::TranslateString("DebuggerMessage", "Removed breakpoint at 0x%08X."),
address);
s_breakpoints.erase(it);
UpdateDebugDispatcherFlag();
@ -1750,8 +1750,8 @@ bool AddStepOverBreakpoint()
if (!IsCallInstruction(inst))
{
g_host_interface->ReportFormattedDebuggerMessage(
g_host_interface->TranslateString("DebuggerMessage", "0x%08X is not a call instruction."), g_state.regs.pc);
Host::ReportFormattedDebuggerMessage(Host::TranslateString("DebuggerMessage", "0x%08X is not a call instruction."),
g_state.regs.pc);
return false;
}
@ -1760,16 +1760,15 @@ bool AddStepOverBreakpoint()
if (IsBranchInstruction(inst))
{
g_host_interface->ReportFormattedDebuggerMessage(
g_host_interface->TranslateString("DebuggerMessage", "Can't step over double branch at 0x%08X"), g_state.regs.pc);
Host::ReportFormattedDebuggerMessage(
Host::TranslateString("DebuggerMessage", "Can't step over double branch at 0x%08X"), g_state.regs.pc);
return false;
}
// skip the delay slot
bp_pc += sizeof(Instruction);
g_host_interface->ReportFormattedDebuggerMessage(
g_host_interface->TranslateString("DebuggerMessage", "Stepping over to 0x%08X."), bp_pc);
Host::ReportFormattedDebuggerMessage(Host::TranslateString("DebuggerMessage", "Stepping over to 0x%08X."), bp_pc);
return AddBreakpoint(bp_pc, true);
}
@ -1785,25 +1784,22 @@ bool AddStepOutBreakpoint(u32 max_instructions_to_search)
Instruction inst;
if (!SafeReadInstruction(ret_pc, &inst.bits))
{
g_host_interface->ReportFormattedDebuggerMessage(
g_host_interface->TranslateString("DebuggerMessage",
"Instruction read failed at %08X while searching for function end."),
Host::ReportFormattedDebuggerMessage(
Host::TranslateString("DebuggerMessage", "Instruction read failed at %08X while searching for function end."),
ret_pc);
return false;
}
if (IsReturnInstruction(inst))
{
g_host_interface->ReportFormattedDebuggerMessage(
g_host_interface->TranslateString("DebuggerMessage", "Stepping out to 0x%08X."), ret_pc);
Host::ReportFormattedDebuggerMessage(Host::TranslateString("DebuggerMessage", "Stepping out to 0x%08X."), ret_pc);
return AddBreakpoint(ret_pc, true);
}
}
g_host_interface->ReportFormattedDebuggerMessage(
g_host_interface->TranslateString("DebuggerMessage",
"No return instruction found after %u instructions for step-out at %08X."),
Host::ReportFormattedDebuggerMessage(
Host::TranslateString("DebuggerMessage", "No return instruction found after %u instructions for step-out at %08X."),
max_instructions_to_search, g_state.regs.pc);
return false;
@ -1857,18 +1853,18 @@ ALWAYS_INLINE_RELEASE static bool BreakpointCheck()
}
else
{
g_host_interface->PauseSystem(true);
System::PauseSystem(true);
if (bp.auto_clear)
{
g_host_interface->ReportFormattedDebuggerMessage("Stopped execution at 0x%08X.", pc);
Host::ReportFormattedDebuggerMessage("Stopped execution at 0x%08X.", pc);
s_breakpoints.erase(s_breakpoints.begin() + i);
count--;
UpdateDebugDispatcherFlag();
}
else
{
g_host_interface->ReportFormattedDebuggerMessage("Hit breakpoint %u at 0x%08X.", bp.number, pc);
Host::ReportFormattedDebuggerMessage("Hit breakpoint %u at 0x%08X.", bp.number, pc);
i++;
}
}
@ -1979,7 +1975,7 @@ void SingleStep()
{
s_single_step = true;
ExecuteDebug();
g_host_interface->ReportFormattedDebuggerMessage("Stepped to 0x%08X.", g_state.regs.pc);
Host::ReportFormattedDebuggerMessage("Stepped to 0x%08X.", g_state.regs.pc);
}
namespace CodeCache {

View File

@ -38,7 +38,7 @@ void DigitalController::SetBindState(u32 index, float value)
if (index >= static_cast<u32>(Button::Count))
return;
const bool pressed = (value > 0.0f);
const bool pressed = (value >= 0.5f);
const u16 bit = u16(1) << static_cast<u8>(index);
if (pressed)
{
@ -130,27 +130,25 @@ std::unique_ptr<DigitalController> DigitalController::Create(u32 index)
}
static const Controller::ControllerBindingInfo s_binding_info[] = {
#define BUTTON(name, display_name, genb) \
#define BUTTON(name, display_name, button, genb) \
{ \
name, display_name, Controller::ControllerBindingType::Button, genb \
name, display_name, static_cast<u32>(button), Controller::ControllerBindingType::Button, genb \
}
BUTTON("Select", "Select", GenericInputBinding::Select),
BUTTON("L3", "Select", GenericInputBinding::L3),
BUTTON("R3", "Select", GenericInputBinding::R3),
BUTTON("Start", "Select", GenericInputBinding::Start),
BUTTON("Up", "D-Pad Up", GenericInputBinding::DPadUp),
BUTTON("Right", "D-Pad Right", GenericInputBinding::DPadRight),
BUTTON("Down", "D-Pad Down", GenericInputBinding::DPadDown),
BUTTON("Left", "D-Pad Left", GenericInputBinding::DPadLeft),
BUTTON("L2", "L2", GenericInputBinding::L2),
BUTTON("R2", "R2", GenericInputBinding::R2),
BUTTON("L1", "L1", GenericInputBinding::L1),
BUTTON("R1", "R1", GenericInputBinding::R1),
BUTTON("Triangle", "Triangle", GenericInputBinding::Triangle),
BUTTON("Circle", "Circle", GenericInputBinding::Circle),
BUTTON("Cross", "Cross", GenericInputBinding::Cross),
BUTTON("Square", "Square", GenericInputBinding::Square),
BUTTON("Up", "D-Pad Up", DigitalController::Button::Up, GenericInputBinding::DPadUp),
BUTTON("Right", "D-Pad Right", DigitalController::Button::Right, GenericInputBinding::DPadRight),
BUTTON("Down", "D-Pad Down", DigitalController::Button::Down, GenericInputBinding::DPadDown),
BUTTON("Left", "D-Pad Left", DigitalController::Button::Left, GenericInputBinding::DPadLeft),
BUTTON("Triangle", "Triangle", DigitalController::Button::Triangle, GenericInputBinding::Triangle),
BUTTON("Circle", "Circle", DigitalController::Button::Circle, GenericInputBinding::Circle),
BUTTON("Cross", "Cross", DigitalController::Button::Cross, GenericInputBinding::Cross),
BUTTON("Square", "Square", DigitalController::Button::Square, GenericInputBinding::Square),
BUTTON("Select", "Select", DigitalController::Button::Select, GenericInputBinding::Select),
BUTTON("Start", "Start", DigitalController::Button::Start, GenericInputBinding::Start),
BUTTON("L1", "L1", DigitalController::Button::L1, GenericInputBinding::L1),
BUTTON("R1", "R1", DigitalController::Button::R1, GenericInputBinding::R1),
BUTTON("L2", "L2", DigitalController::Button::L2, GenericInputBinding::L2),
BUTTON("R2", "R2", DigitalController::Button::R2, GenericInputBinding::R2),
#undef BUTTON
};

View File

@ -4,6 +4,7 @@
#include "common/log.h"
#include "cpu_core.h"
#include "gpu_sw_backend.h"
#include "host.h"
#include "imgui.h"
#include "pgxp.h"
#include "settings.h"
@ -61,29 +62,26 @@ bool GPU_HW::Initialize(HostDisplay* host_display)
if (m_multisamples != g_settings.gpu_multisamples)
{
g_host_interface->AddFormattedOSDMessage(
20.0f, g_host_interface->TranslateString("OSDMessage", "%ux MSAA is not supported, using %ux instead."),
g_settings.gpu_multisamples, m_multisamples);
Host::AddFormattedOSDMessage(20.0f,
Host::TranslateString("OSDMessage", "%ux MSAA is not supported, using %ux instead."),
g_settings.gpu_multisamples, m_multisamples);
}
if (!m_per_sample_shading && g_settings.gpu_per_sample_shading)
{
g_host_interface->AddOSDMessage(
g_host_interface->TranslateStdString("OSDMessage", "SSAA is not supported, using MSAA instead."), 20.0f);
Host::AddOSDMessage(Host::TranslateStdString("OSDMessage", "SSAA is not supported, using MSAA instead."), 20.0f);
}
if (!m_supports_dual_source_blend && TextureFilterRequiresDualSourceBlend(m_texture_filtering))
{
g_host_interface->AddFormattedOSDMessage(
20.0f,
g_host_interface->TranslateString("OSDMessage",
"Texture filter '%s' is not supported with the current renderer."),
Host::AddFormattedOSDMessage(
20.0f, Host::TranslateString("OSDMessage", "Texture filter '%s' is not supported with the current renderer."),
Settings::GetTextureFilterDisplayName(m_texture_filtering));
m_texture_filtering = GPUTextureFilter::Nearest;
}
if (!m_supports_adaptive_downsampling && g_settings.gpu_resolution_scale > 1 &&
g_settings.gpu_downsample_mode == GPUDownsampleMode::Adaptive)
{
g_host_interface->AddOSDMessage(
g_host_interface->TranslateStdString(
Host::AddOSDMessage(
Host::TranslateStdString(
"OSDMessage", "Adaptive downsampling is not supported with the current renderer, using box filter instead."),
20.0f);
}
@ -149,27 +147,26 @@ void GPU_HW::UpdateHWSettings(bool* framebuffer_changed, bool* shaders_changed)
if (m_resolution_scale != resolution_scale)
{
g_host_interface->AddKeyedFormattedOSDMessage(
Host::AddKeyedFormattedOSDMessage(
"ResolutionScale", 10.0f,
g_host_interface->TranslateString("OSDMessage", "Resolution scale set to %ux (display %ux%u, VRAM %ux%u)"),
resolution_scale, m_crtc_state.display_vram_width * resolution_scale,
resolution_scale * m_crtc_state.display_vram_height, VRAM_WIDTH * resolution_scale,
VRAM_HEIGHT * resolution_scale);
Host::TranslateString("OSDMessage", "Resolution scale set to %ux (display %ux%u, VRAM %ux%u)"), resolution_scale,
m_crtc_state.display_vram_width * resolution_scale, resolution_scale * m_crtc_state.display_vram_height,
VRAM_WIDTH * resolution_scale, VRAM_HEIGHT * resolution_scale);
}
if (m_multisamples != multisamples || m_per_sample_shading != per_sample_shading)
{
if (per_sample_shading)
{
g_host_interface->AddKeyedFormattedOSDMessage(
"Multisampling", 10.0f,
g_host_interface->TranslateString("OSDMessage", "Multisample anti-aliasing set to %ux (SSAA)."), multisamples);
Host::AddKeyedFormattedOSDMessage(
"Multisampling", 10.0f, Host::TranslateString("OSDMessage", "Multisample anti-aliasing set to %ux (SSAA)."),
multisamples);
}
else
{
g_host_interface->AddKeyedFormattedOSDMessage(
"Multisampling", 10.0f,
g_host_interface->TranslateString("OSDMessage", "Multisample anti-aliasing set to %ux."), multisamples);
Host::AddKeyedFormattedOSDMessage("Multisampling", 10.0f,
Host::TranslateString("OSDMessage", "Multisample anti-aliasing set to %ux."),
multisamples);
}
}
@ -229,10 +226,9 @@ u32 GPU_HW::CalculateResolutionScale() const
if (g_settings.gpu_resolution_scale != 0)
{
g_host_interface->AddFormattedOSDMessage(
Host::AddFormattedOSDMessage(
10.0f,
g_host_interface->TranslateString("OSDMessage",
"Resolution scale %ux not supported for adaptive smoothing, using %ux."),
Host::TranslateString("OSDMessage", "Resolution scale %ux not supported for adaptive smoothing, using %ux."),
scale, new_scale);
}

View File

@ -3,6 +3,7 @@
#include "common/log.h"
#include "common/timer.h"
#include "gpu_hw_shadergen.h"
#include "host.h"
#include "host_display.h"
#include "shader_cache_version.h"
#include "system.h"
@ -55,10 +56,10 @@ bool GPU_HW_OpenGL::Initialize(HostDisplay* host_display)
(host_display->GetRenderAPI() == HostDisplay::RenderAPI::OpenGLES && GLAD_GL_ES_VERSION_3_0));
if (!opengl_is_available)
{
g_host_interface->AddOSDMessage(
g_host_interface->TranslateStdString("OSDMessage", "OpenGL renderer unavailable, your driver or hardware is not "
"recent enough. OpenGL 3.1 or OpenGL ES 3.0 is required."),
20.0f);
Host::AddOSDMessage(Host::TranslateStdString("OSDMessage",
"OpenGL renderer unavailable, your driver or hardware is not "
"recent enough. OpenGL 3.1 or OpenGL ES 3.0 is required."),
20.0f);
return false;
}

View File

@ -188,7 +188,7 @@ void UpdateAspectRatio()
{
case DisplayAspectRatio::MatchWindow:
{
const HostDisplay* display = g_host_interface->GetDisplay();
const HostDisplay* display = Host::GetHostDisplay();
if (!display)
{
s_aspect_ratio = DisplayAspectRatio::R4_3;

32
src/core/host.cpp Normal file
View File

@ -0,0 +1,32 @@
#include "host.h"
#include "common/string_util.h"
#include <cstdarg>
void Host::ReportFormattedErrorAsync(const std::string_view& title, const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
std::string message(StringUtil::StdStringFromFormatV(format, ap));
va_end(ap);
ReportErrorAsync(title, message);
}
bool Host::ConfirmFormattedMessage(const std::string_view& title, const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
std::string message = StringUtil::StdStringFromFormatV(format, ap);
va_end(ap);
return ConfirmMessage(title, message);
}
void Host::ReportFormattedDebuggerMessage(const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
std::string message = StringUtil::StdStringFromFormatV(format, ap);
va_end(ap);
ReportDebuggerMessage(message);
}

View File

@ -1,12 +1,21 @@
#pragma once
#include "common/string.h"
#include "common/types.h"
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
struct WindowInfo;
enum class AudioBackend : u8;
class AudioStream;
/// Marks a core string as being translatable.
#define TRANSLATABLE(context, str) str
/// Generic input bindings. These roughly match a DualShock 4 or XBox One controller.
/// They are used for automatic binding to PS2 controller types, and for big picture mode navigation.
enum class GenericInputBinding : u8
@ -58,6 +67,12 @@ std::optional<std::vector<u8>> ReadResourceFile(const char* filename);
/// Reads a resource file file from the resources directory as a string.
std::optional<std::string> ReadResourceFileToString(const char* filename);
/// Translates a string to the current language.
TinyString TranslateString(const char* context, const char* str, const char* disambiguation = nullptr, int n = -1);
std::string TranslateStdString(const char* context, const char* str, const char* disambiguation = nullptr, int n = -1);
std::unique_ptr<AudioStream> CreateAudioStream(AudioBackend backend);
/// Adds OSD messages, duration is in seconds.
void AddOSDMessage(std::string message, float duration = 2.0f);
void AddKeyedOSDMessage(std::string key, std::string message, float duration = 2.0f);
@ -70,14 +85,15 @@ void ClearOSDMessages();
void ReportErrorAsync(const std::string_view& title, const std::string_view& message);
void ReportFormattedErrorAsync(const std::string_view& title, const char* format, ...);
/// Displays a synchronous confirmation on the UI thread, i.e. blocks the caller.
bool ConfirmMessage(const std::string_view& title, const std::string_view& message);
bool ConfirmFormattedMessage(const std::string_view& title, const char* format, ...);
/// Debugger feedback.
void ReportDebuggerMessage(const std::string_view& message);
void ReportFormattedDebuggerMessage(const char* format, ...) printflike(2, 3);
/// Internal method used by pads to dispatch vibration updates to input sources.
/// Intensity is normalized from 0 to 1.
void SetPadVibrationIntensity(u32 pad_index, float large_or_single_motor_intensity, float small_motor_intensity);
void OpenBackgroundProgressDialog(const char* str_id, std::string message, s32 min, s32 max, s32 value);
void UpdateBackgroundProgressDialog(const char* str_id, std::string message, s32 min, s32 max, s32 value);
void CloseBackgroundProgressDialog(const char* str_id);
void AddNotification(float duration, std::string title, std::string text, std::string image_path);
void ShowToast(std::string title, std::string message, float duration = 10.0f);
} // namespace Host

View File

@ -290,3 +290,32 @@ protected:
bool m_display_integer_scaling = false;
bool m_display_stretch = false;
};
namespace Host {
/// Creates the host display. This may create a new window. The API used depends on the current configuration.
HostDisplay* AcquireHostDisplay(/*HostDisplay::RenderAPI api*/);
/// Destroys the host display. This may close the display window.
void ReleaseHostDisplay();
/// Returns a pointer to the current host display abstraction. Assumes AcquireHostDisplay() has been caled.
HostDisplay* GetHostDisplay();
/// Returns false if the window was completely occluded. If frame_skip is set, the frame won't be
/// displayed, but the GPU command queue will still be flushed.
//bool BeginPresentFrame(bool frame_skip);
/// Presents the frame to the display, and renders OSD elements.
//void EndPresentFrame();
/// Called on the MTGS thread when a resize request is received.
//void ResizeHostDisplay(u32 new_window_width, u32 new_window_height, float new_window_scale);
/// Called on the MTGS thread when a request to update the display is received.
/// This could be a fullscreen transition, for example.
//void UpdateHostDisplay();
/// Provided by the host; renders the display.
void RenderDisplay();
void InvalidateDisplay();
} // namespace Host

View File

@ -16,6 +16,7 @@
#include "gte.h"
#include "host.h"
#include "host_display.h"
#include "host_settings.h"
#include "pgxp.h"
#include "save_state_version.h"
#include "spu.h"
@ -42,7 +43,6 @@ HostInterface::HostInterface()
HostInterface::~HostInterface()
{
// system should be shut down prior to the destructor
Assert(System::IsShutdown() && !m_audio_stream && !m_display);
Assert(g_host_interface == this);
g_host_interface = nullptr;
}
@ -54,222 +54,11 @@ bool HostInterface::Initialize()
void HostInterface::Shutdown()
{
if (!System::IsShutdown())
System::Shutdown();
}
void HostInterface::CreateAudioStream()
{
Log_InfoPrintf("Creating '%s' audio stream, sample rate = %u, channels = %u, buffer size = %u",
Settings::GetAudioBackendName(g_settings.audio_backend), AUDIO_SAMPLE_RATE, AUDIO_CHANNELS,
g_settings.audio_buffer_size);
m_audio_stream = CreateAudioStream(g_settings.audio_backend);
if (!m_audio_stream ||
!m_audio_stream->Reconfigure(AUDIO_SAMPLE_RATE, AUDIO_SAMPLE_RATE, AUDIO_CHANNELS, g_settings.audio_buffer_size))
{
ReportFormattedError("Failed to create or configure audio stream, falling back to null output.");
m_audio_stream.reset();
m_audio_stream = AudioStream::CreateNullAudioStream();
m_audio_stream->Reconfigure(AUDIO_SAMPLE_RATE, AUDIO_SAMPLE_RATE, AUDIO_CHANNELS, g_settings.audio_buffer_size);
}
m_audio_stream->SetOutputVolume(GetAudioOutputVolume());
if (System::IsValid())
g_spu.SetAudioStream(m_audio_stream.get());
}
s32 HostInterface::GetAudioOutputVolume() const
{
return g_settings.audio_output_muted ? 0 : g_settings.audio_output_volume;
}
bool HostInterface::BootSystem(std::shared_ptr<SystemBootParameters> parameters)
{
if (!parameters->state_stream)
{
if (parameters->filename.empty())
Log_InfoPrintf("Boot Filename: <BIOS/Shell>");
else
Log_InfoPrintf("Boot Filename: %s", parameters->filename.c_str());
}
if (!AcquireHostDisplay())
{
ReportError(g_host_interface->TranslateString("System", "Failed to acquire host display."));
OnSystemDestroyed();
return false;
}
// set host display settings
m_display->SetDisplayLinearFiltering(g_settings.display_linear_filtering);
m_display->SetDisplayIntegerScaling(g_settings.display_integer_scaling);
m_display->SetDisplayStretch(g_settings.display_stretch);
// create the audio stream. this will never fail, since we'll just fall back to null
CreateAudioStream();
if (!System::Boot(*parameters))
{
if (!System::IsStartupCancelled())
{
ReportError(
g_host_interface->TranslateString("System", "System failed to boot. The log may contain more information."));
}
OnSystemDestroyed();
m_audio_stream.reset();
ReleaseHostDisplay();
return false;
}
UpdateSoftwareCursor();
OnSystemCreated();
m_audio_stream->PauseOutput(false);
return true;
}
void HostInterface::ResetSystem()
{
System::Reset();
System::ResetPerformanceCounters();
System::ResetThrottler();
AddOSDMessage(TranslateStdString("OSDMessage", "System reset."));
}
void HostInterface::PauseSystem(bool paused)
{
if (paused == System::IsPaused() || System::IsShutdown())
return;
System::SetState(paused ? System::State::Paused : System::State::Running);
if (!paused)
m_audio_stream->EmptyBuffers();
m_audio_stream->PauseOutput(paused);
OnSystemPaused(paused);
if (!paused)
{
System::ResetPerformanceCounters();
System::ResetThrottler();
}
}
void HostInterface::DestroySystem()
{
if (System::IsShutdown())
return;
System::Shutdown();
m_audio_stream.reset();
UpdateSoftwareCursor();
ReleaseHostDisplay();
OnSystemDestroyed();
}
void HostInterface::ReportError(const char* message)
{
Log_ErrorPrint(message);
}
void HostInterface::ReportMessage(const char* message)
{
Log_InfoPrint(message);
}
void HostInterface::ReportDebuggerMessage(const char* message)
{
Log_InfoPrintf("(Debugger) %s", message);
}
bool HostInterface::ConfirmMessage(const char* message)
{
Log_WarningPrintf("ConfirmMessage(\"%s\") -> Yes", message);
return true;
}
void HostInterface::ReportFormattedError(const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
std::string message = StringUtil::StdStringFromFormatV(format, ap);
va_end(ap);
ReportError(message.c_str());
}
void HostInterface::ReportFormattedMessage(const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
std::string message = StringUtil::StdStringFromFormatV(format, ap);
va_end(ap);
ReportMessage(message.c_str());
}
void HostInterface::ReportFormattedDebuggerMessage(const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
std::string message = StringUtil::StdStringFromFormatV(format, ap);
va_end(ap);
ReportDebuggerMessage(message.c_str());
}
bool HostInterface::ConfirmFormattedMessage(const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
std::string message = StringUtil::StdStringFromFormatV(format, ap);
va_end(ap);
return ConfirmMessage(message.c_str());
}
void HostInterface::AddOSDMessage(std::string message, float duration /*= 2.0f*/)
{
Host::AddOSDMessage(std::move(message), duration);
}
void HostInterface::AddKeyedOSDMessage(std::string key, std::string message, float duration /*= 2.0f*/)
{
Host::AddKeyedOSDMessage(std::move(key), std::move(message), duration);
}
void HostInterface::RemoveKeyedOSDMessage(std::string key)
{
Host::RemoveKeyedOSDMessage(std::move(key));
}
void HostInterface::AddFormattedOSDMessage(float duration, const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
std::string message = StringUtil::StdStringFromFormatV(format, ap);
va_end(ap);
Host::AddOSDMessage(std::move(message), duration);
}
void HostInterface::AddKeyedFormattedOSDMessage(std::string key, float duration, const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
std::string message = StringUtil::StdStringFromFormatV(format, ap);
va_end(ap);
Host::AddKeyedOSDMessage(std::move(key), std::move(message), duration);
}
std::string HostInterface::GetBIOSDirectory()
{
std::string dir = GetStringSettingValue("BIOS", "SearchDirectory", "");
std::string dir = Host::GetStringSettingValue("BIOS", "SearchDirectory", "");
if (!dir.empty())
return dir;
@ -283,16 +72,16 @@ std::optional<std::vector<u8>> HostInterface::GetBIOSImage(ConsoleRegion region)
switch (region)
{
case ConsoleRegion::NTSC_J:
bios_name = GetStringSettingValue("BIOS", "PathNTSCJ", "");
bios_name = Host::GetStringSettingValue("BIOS", "PathNTSCJ", "");
break;
case ConsoleRegion::PAL:
bios_name = GetStringSettingValue("BIOS", "PathPAL", "");
bios_name = Host::GetStringSettingValue("BIOS", "PathPAL", "");
break;
case ConsoleRegion::NTSC_U:
default:
bios_name = GetStringSettingValue("BIOS", "PathNTSCU", "");
bios_name = Host::GetStringSettingValue("BIOS", "PathNTSCU", "");
break;
}
@ -307,9 +96,8 @@ std::optional<std::vector<u8>> HostInterface::GetBIOSImage(ConsoleRegion region)
StringUtil::StdStringFromFormat("%s" FS_OSPATH_SEPARATOR_STR "%s", bios_dir.c_str(), bios_name.c_str()).c_str());
if (!image.has_value())
{
g_host_interface->ReportFormattedError(
g_host_interface->TranslateString("HostInterface", "Failed to load configured BIOS file '%s'"),
bios_name.c_str());
Host::ReportFormattedErrorAsync(
"Error", Host::TranslateString("HostInterface", "Failed to load configured BIOS file '%s'"), bios_name.c_str());
return std::nullopt;
}
@ -371,9 +159,9 @@ std::optional<std::vector<u8>> HostInterface::FindBIOSImageInDirectory(ConsoleRe
if (!fallback_image.has_value())
{
g_host_interface->ReportFormattedError(
g_host_interface->TranslateString("HostInterface", "No BIOS image found for %s region"),
Settings::GetConsoleRegionDisplayName(region));
Host::ReportFormattedErrorAsync("Error",
Host::TranslateString("HostInterface", "No BIOS image found for %s region"),
Settings::GetConsoleRegionDisplayName(region));
return std::nullopt;
}
@ -425,488 +213,11 @@ bool HostInterface::HasAnyBIOSImages()
return (FindBIOSImageInDirectory(ConsoleRegion::Auto, dir.c_str()).has_value());
}
bool HostInterface::LoadState(const char* filename)
{
std::unique_ptr<ByteStream> stream = ByteStream::OpenFile(filename, BYTESTREAM_OPEN_READ | BYTESTREAM_OPEN_STREAMED);
if (!stream)
return false;
AddFormattedOSDMessage(5.0f, TranslateString("OSDMessage", "Loading state from '%s'..."), filename);
if (!System::IsShutdown())
{
if (!System::LoadState(stream.get()))
{
ReportFormattedError(TranslateString("OSDMessage", "Loading state from '%s' failed. Resetting."), filename);
ResetSystem();
return false;
}
}
else
{
auto boot_params = std::make_shared<SystemBootParameters>();
boot_params->state_stream = std::move(stream);
if (!BootSystem(std::move(boot_params)))
return false;
}
System::ResetPerformanceCounters();
System::ResetThrottler();
OnDisplayInvalidated();
return true;
}
bool HostInterface::SaveState(const char* filename)
{
std::unique_ptr<ByteStream> stream =
ByteStream::OpenFile(filename, BYTESTREAM_OPEN_CREATE | BYTESTREAM_OPEN_WRITE | BYTESTREAM_OPEN_TRUNCATE |
BYTESTREAM_OPEN_ATOMIC_UPDATE | BYTESTREAM_OPEN_STREAMED);
if (!stream)
return false;
const bool result = System::SaveState(stream.get());
if (!result)
{
ReportFormattedError(TranslateString("OSDMessage", "Saving state to '%s' failed."), filename);
stream->Discard();
}
else
{
AddFormattedOSDMessage(5.0f, TranslateString("OSDMessage", "State saved to '%s'."), filename);
stream->Commit();
}
return result;
}
std::string HostInterface::GetShaderCacheBasePath() const
{
return GetUserDirectoryRelativePath("cache/");
}
void HostInterface::SetDefaultSettings(SettingsInterface& si)
{
si.SetStringValue("Console", "Region", Settings::GetConsoleRegionName(Settings::DEFAULT_CONSOLE_REGION));
si.SetBoolValue("Console", "Enable8MBRAM", false);
si.SetFloatValue("Main", "EmulationSpeed", 1.0f);
si.SetFloatValue("Main", "FastForwardSpeed", 0.0f);
si.SetFloatValue("Main", "TurboSpeed", 0.0f);
si.SetBoolValue("Main", "SyncToHostRefreshRate", false);
si.SetBoolValue("Main", "IncreaseTimerResolution", true);
si.SetBoolValue("Main", "InhibitScreensaver", true);
si.SetBoolValue("Main", "StartPaused", false);
si.SetBoolValue("Main", "StartFullscreen", false);
si.SetBoolValue("Main", "PauseOnFocusLoss", false);
si.SetBoolValue("Main", "PauseOnMenu", true);
si.SetBoolValue("Main", "SaveStateOnExit", true);
si.SetBoolValue("Main", "ConfirmPowerOff", true);
si.SetBoolValue("Main", "LoadDevicesFromSaveStates", false);
si.SetBoolValue("Main", "ApplyGameSettings", true);
si.SetBoolValue("Main", "AutoLoadCheats", true);
si.SetBoolValue("Main", "DisableAllEnhancements", false);
si.SetBoolValue("Main", "RewindEnable", false);
si.SetFloatValue("Main", "RewindFrequency", 10.0f);
si.SetIntValue("Main", "RewindSaveSlots", 10);
si.SetFloatValue("Main", "RunaheadFrameCount", 0);
si.SetStringValue("CPU", "ExecutionMode", Settings::GetCPUExecutionModeName(Settings::DEFAULT_CPU_EXECUTION_MODE));
si.SetIntValue("CPU", "OverclockNumerator", 1);
si.SetIntValue("CPU", "OverclockDenominator", 1);
si.SetBoolValue("CPU", "OverclockEnable", false);
si.SetBoolValue("CPU", "RecompilerMemoryExceptions", false);
si.SetBoolValue("CPU", "RecompilerBlockLinking", true);
si.SetBoolValue("CPU", "ICache", false);
si.SetBoolValue("CPU", "FastmemMode", Settings::GetCPUFastmemModeName(Settings::DEFAULT_CPU_FASTMEM_MODE));
si.SetStringValue("GPU", "Renderer", Settings::GetRendererName(Settings::DEFAULT_GPU_RENDERER));
si.SetIntValue("GPU", "ResolutionScale", 1);
si.SetIntValue("GPU", "Multisamples", 1);
si.SetBoolValue("GPU", "UseDebugDevice", false);
si.SetBoolValue("GPU", "UseSoftwareRendererForReadbacks", false);
si.SetBoolValue("GPU", "PerSampleShading", false);
si.SetBoolValue("GPU", "UseThread", true);
si.SetBoolValue("GPU", "ThreadedPresentation", true);
si.SetBoolValue("GPU", "TrueColor", false);
si.SetBoolValue("GPU", "ScaledDithering", true);
si.SetStringValue("GPU", "TextureFilter", Settings::GetTextureFilterName(Settings::DEFAULT_GPU_TEXTURE_FILTER));
si.SetStringValue("GPU", "DownsampleMode", Settings::GetDownsampleModeName(Settings::DEFAULT_GPU_DOWNSAMPLE_MODE));
si.SetBoolValue("GPU", "DisableInterlacing", true);
si.SetBoolValue("GPU", "ForceNTSCTimings", false);
si.SetBoolValue("GPU", "WidescreenHack", false);
si.SetBoolValue("GPU", "ChromaSmoothing24Bit", false);
si.SetBoolValue("GPU", "PGXPEnable", false);
si.SetBoolValue("GPU", "PGXPCulling", true);
si.SetBoolValue("GPU", "PGXPTextureCorrection", true);
si.SetBoolValue("GPU", "PGXPVertexCache", false);
si.SetBoolValue("GPU", "PGXPCPU", false);
si.SetBoolValue("GPU", "PGXPPreserveProjFP", false);
si.SetFloatValue("GPU", "PGXPTolerance", -1.0f);
si.SetBoolValue("GPU", "PGXPDepthBuffer", false);
si.SetFloatValue("GPU", "PGXPDepthClearThreshold", Settings::DEFAULT_GPU_PGXP_DEPTH_THRESHOLD);
si.SetStringValue("Display", "CropMode", Settings::GetDisplayCropModeName(Settings::DEFAULT_DISPLAY_CROP_MODE));
si.SetIntValue("Display", "ActiveStartOffset", 0);
si.SetIntValue("Display", "ActiveEndOffset", 0);
si.SetIntValue("Display", "LineStartOffset", 0);
si.SetIntValue("Display", "LineEndOffset", 0);
si.SetStringValue("Display", "AspectRatio",
Settings::GetDisplayAspectRatioName(Settings::DEFAULT_DISPLAY_ASPECT_RATIO));
si.SetIntValue("Display", "CustomAspectRatioNumerator", 4);
si.GetIntValue("Display", "CustomAspectRatioDenominator", 3);
si.SetBoolValue("Display", "Force4_3For24Bit", false);
si.SetBoolValue("Display", "LinearFiltering", true);
si.SetBoolValue("Display", "IntegerScaling", false);
si.SetBoolValue("Display", "Stretch", false);
si.SetBoolValue("Display", "PostProcessing", false);
si.SetBoolValue("Display", "ShowOSDMessages", true);
si.SetBoolValue("Display", "ShowFPS", false);
si.SetBoolValue("Display", "ShowVPS", false);
si.SetBoolValue("Display", "ShowSpeed", false);
si.SetBoolValue("Display", "ShowResolution", false);
si.SetBoolValue("Display", "ShowStatusIndicators", true);
si.SetBoolValue("Display", "ShowEnhancements", false);
si.SetBoolValue("Display", "Fullscreen", false);
si.SetBoolValue("Display", "VSync", Settings::DEFAULT_VSYNC_VALUE);
si.SetBoolValue("Display", "DisplayAllFrames", false);
si.SetStringValue("Display", "PostProcessChain", "");
si.SetFloatValue("Display", "MaxFPS", Settings::DEFAULT_DISPLAY_MAX_FPS);
si.SetIntValue("CDROM", "ReadaheadSectors", Settings::DEFAULT_CDROM_READAHEAD_SECTORS);
si.SetBoolValue("CDROM", "RegionCheck", false);
si.SetBoolValue("CDROM", "LoadImageToRAM", false);
si.SetBoolValue("CDROM", "MuteCDAudio", false);
si.SetIntValue("CDROM", "ReadSpeedup", 1);
si.SetIntValue("CDROM", "SeekSpeedup", 1);
si.SetStringValue("Audio", "Backend", Settings::GetAudioBackendName(Settings::DEFAULT_AUDIO_BACKEND));
si.SetIntValue("Audio", "OutputVolume", 100);
si.SetIntValue("Audio", "FastForwardVolume", 100);
si.SetIntValue("Audio", "BufferSize", DEFAULT_AUDIO_BUFFER_SIZE);
si.SetBoolValue("Audio", "Resampling", true);
si.SetIntValue("Audio", "OutputMuted", false);
si.SetBoolValue("Audio", "Sync", true);
si.SetBoolValue("Audio", "DumpOnBoot", false);
si.SetStringValue("BIOS", "SearchDirectory", "");
si.SetStringValue("BIOS", "PathNTSCU", "");
si.SetStringValue("BIOS", "PathNTSCJ", "");
si.SetStringValue("BIOS", "PathPAL", "");
si.SetBoolValue("BIOS", "PatchTTYEnable", false);
si.SetBoolValue("BIOS", "PatchFastBoot", Settings::DEFAULT_FAST_BOOT_VALUE);
si.SetStringValue("Controller1", "Type", Settings::GetControllerTypeName(Settings::DEFAULT_CONTROLLER_1_TYPE));
for (u32 i = 1; i < NUM_CONTROLLER_AND_CARD_PORTS; i++)
{
si.SetStringValue(TinyString::FromFormat("Controller%u", i + 1u), "Type",
Settings::GetControllerTypeName(Settings::DEFAULT_CONTROLLER_2_TYPE));
}
si.SetStringValue("MemoryCards", "Card1Type", Settings::GetMemoryCardTypeName(Settings::DEFAULT_MEMORY_CARD_1_TYPE));
si.SetStringValue("MemoryCards", "Card2Type", Settings::GetMemoryCardTypeName(Settings::DEFAULT_MEMORY_CARD_2_TYPE));
si.DeleteValue("MemoryCards", "Card1Path");
si.DeleteValue("MemoryCards", "Card2Path");
si.DeleteValue("MemoryCards", "Directory");
si.SetBoolValue("MemoryCards", "UsePlaylistTitle", true);
si.SetStringValue("ControllerPorts", "MultitapMode", Settings::GetMultitapModeName(Settings::DEFAULT_MULTITAP_MODE));
si.SetStringValue("Logging", "LogLevel", Settings::GetLogLevelName(Settings::DEFAULT_LOG_LEVEL));
si.SetStringValue("Logging", "LogFilter", "");
si.SetBoolValue("Logging", "LogToConsole", Settings::DEFAULT_LOG_TO_CONSOLE);
si.SetBoolValue("Logging", "LogToDebug", false);
si.SetBoolValue("Logging", "LogToWindow", false);
si.SetBoolValue("Logging", "LogToFile", false);
si.SetBoolValue("Debug", "ShowVRAM", false);
si.SetBoolValue("Debug", "DumpCPUToVRAMCopies", false);
si.SetBoolValue("Debug", "DumpVRAMToCPUCopies", false);
si.SetBoolValue("Debug", "ShowGPUState", false);
si.SetBoolValue("Debug", "ShowCDROMState", false);
si.SetBoolValue("Debug", "ShowSPUState", false);
si.SetBoolValue("Debug", "ShowTimersState", false);
si.SetBoolValue("Debug", "ShowMDECState", false);
si.SetBoolValue("Debug", "ShowDMAState", false);
si.SetIntValue("Hacks", "DMAMaxSliceTicks", static_cast<int>(Settings::DEFAULT_DMA_MAX_SLICE_TICKS));
si.SetIntValue("Hacks", "DMAHaltTicks", static_cast<int>(Settings::DEFAULT_DMA_HALT_TICKS));
si.SetIntValue("Hacks", "GPUFIFOSize", static_cast<int>(Settings::DEFAULT_GPU_FIFO_SIZE));
si.SetIntValue("Hacks", "GPUMaxRunAhead", static_cast<int>(Settings::DEFAULT_GPU_MAX_RUN_AHEAD));
}
void HostInterface::LoadSettings(SettingsInterface& si)
{
g_settings.Load(si);
}
void HostInterface::FixIncompatibleSettings(bool display_osd_messages)
{
if (g_settings.disable_all_enhancements)
{
Log_WarningPrintf("All enhancements disabled by config setting.");
g_settings.cpu_overclock_enable = false;
g_settings.cpu_overclock_active = false;
g_settings.enable_8mb_ram = false;
g_settings.gpu_resolution_scale = 1;
g_settings.gpu_multisamples = 1;
g_settings.gpu_per_sample_shading = false;
g_settings.gpu_true_color = false;
g_settings.gpu_scaled_dithering = false;
g_settings.gpu_texture_filter = GPUTextureFilter::Nearest;
g_settings.gpu_disable_interlacing = false;
g_settings.gpu_force_ntsc_timings = false;
g_settings.gpu_widescreen_hack = false;
g_settings.gpu_pgxp_enable = false;
g_settings.gpu_24bit_chroma_smoothing = false;
g_settings.cdrom_read_speedup = 1;
g_settings.cdrom_seek_speedup = 1;
g_settings.cdrom_mute_cd_audio = false;
g_settings.texture_replacements.enable_vram_write_replacements = false;
g_settings.bios_patch_fast_boot = false;
g_settings.bios_patch_tty_enable = false;
}
if (g_settings.display_integer_scaling && g_settings.display_linear_filtering)
{
Log_WarningPrintf("Disabling linear filter due to integer upscaling.");
g_settings.display_linear_filtering = false;
}
if (g_settings.display_integer_scaling && g_settings.display_stretch)
{
Log_WarningPrintf("Disabling stretch due to integer upscaling.");
g_settings.display_stretch = false;
}
if (g_settings.gpu_pgxp_enable)
{
if (g_settings.gpu_renderer == GPURenderer::Software)
{
if (display_osd_messages)
{
AddOSDMessage(
TranslateStdString("OSDMessage", "PGXP is incompatible with the software renderer, disabling PGXP."), 10.0f);
}
g_settings.gpu_pgxp_enable = false;
}
}
#ifndef WITH_MMAP_FASTMEM
if (g_settings.cpu_fastmem_mode == CPUFastmemMode::MMap)
{
Log_WarningPrintf("mmap fastmem is not available on this platform, using LUT instead.");
g_settings.cpu_fastmem_mode = CPUFastmemMode::LUT;
}
#endif
#if defined(__ANDROID__) && defined(__arm__) && !defined(__aarch64__) && !defined(_M_ARM64)
if (g_settings.rewind_enable)
{
AddOSDMessage(TranslateStdString("OSDMessage", "Rewind is not supported on 32-bit ARM for Android."), 30.0f);
g_settings.rewind_enable = false;
}
#endif
}
void HostInterface::SaveSettings(SettingsInterface& si)
{
g_settings.Save(si);
}
void HostInterface::CheckForSettingsChanges(const Settings& old_settings)
{
if (System::IsValid() && (g_settings.gpu_renderer != old_settings.gpu_renderer ||
g_settings.gpu_use_debug_device != old_settings.gpu_use_debug_device ||
g_settings.gpu_threaded_presentation != old_settings.gpu_threaded_presentation))
{
AddFormattedOSDMessage(5.0f, TranslateString("OSDMessage", "Switching to %s%s GPU renderer."),
Settings::GetRendererName(g_settings.gpu_renderer),
g_settings.gpu_use_debug_device ? " (debug)" : "");
RecreateSystem();
}
if (System::IsValid())
{
System::ClearMemorySaveStates();
if (g_settings.cpu_overclock_active != old_settings.cpu_overclock_active ||
(g_settings.cpu_overclock_active &&
(g_settings.cpu_overclock_numerator != old_settings.cpu_overclock_numerator ||
g_settings.cpu_overclock_denominator != old_settings.cpu_overclock_denominator)))
{
System::UpdateOverclock();
}
if (g_settings.audio_backend != old_settings.audio_backend ||
g_settings.audio_buffer_size != old_settings.audio_buffer_size)
{
if (g_settings.audio_backend != old_settings.audio_backend)
{
AddFormattedOSDMessage(5.0f, TranslateString("OSDMessage", "Switching to %s audio backend."),
Settings::GetAudioBackendName(g_settings.audio_backend));
}
DebugAssert(m_audio_stream);
m_audio_stream.reset();
CreateAudioStream();
m_audio_stream->PauseOutput(System::IsPaused());
}
if (g_settings.emulation_speed != old_settings.emulation_speed)
System::UpdateThrottlePeriod();
if (g_settings.cpu_execution_mode != old_settings.cpu_execution_mode ||
g_settings.cpu_fastmem_mode != old_settings.cpu_fastmem_mode)
{
AddFormattedOSDMessage(
5.0f, TranslateString("OSDMessage", "Switching to %s CPU execution mode."),
TranslateString("CPUExecutionMode", Settings::GetCPUExecutionModeDisplayName(g_settings.cpu_execution_mode))
.GetCharArray());
CPU::CodeCache::Reinitialize();
CPU::ClearICache();
}
if (g_settings.cpu_execution_mode == CPUExecutionMode::Recompiler &&
(g_settings.cpu_recompiler_memory_exceptions != old_settings.cpu_recompiler_memory_exceptions ||
g_settings.cpu_recompiler_block_linking != old_settings.cpu_recompiler_block_linking ||
g_settings.cpu_recompiler_icache != old_settings.cpu_recompiler_icache))
{
AddOSDMessage(TranslateStdString("OSDMessage", "Recompiler options changed, flushing all blocks."), 5.0f);
CPU::CodeCache::Flush();
if (g_settings.cpu_recompiler_icache != old_settings.cpu_recompiler_icache)
CPU::ClearICache();
}
m_audio_stream->SetOutputVolume(GetAudioOutputVolume());
if (g_settings.gpu_resolution_scale != old_settings.gpu_resolution_scale ||
g_settings.gpu_multisamples != old_settings.gpu_multisamples ||
g_settings.gpu_per_sample_shading != old_settings.gpu_per_sample_shading ||
g_settings.gpu_use_thread != old_settings.gpu_use_thread ||
g_settings.gpu_use_software_renderer_for_readbacks != old_settings.gpu_use_software_renderer_for_readbacks ||
g_settings.gpu_fifo_size != old_settings.gpu_fifo_size ||
g_settings.gpu_max_run_ahead != old_settings.gpu_max_run_ahead ||
g_settings.gpu_true_color != old_settings.gpu_true_color ||
g_settings.gpu_scaled_dithering != old_settings.gpu_scaled_dithering ||
g_settings.gpu_texture_filter != old_settings.gpu_texture_filter ||
g_settings.gpu_disable_interlacing != old_settings.gpu_disable_interlacing ||
g_settings.gpu_force_ntsc_timings != old_settings.gpu_force_ntsc_timings ||
g_settings.gpu_24bit_chroma_smoothing != old_settings.gpu_24bit_chroma_smoothing ||
g_settings.gpu_downsample_mode != old_settings.gpu_downsample_mode ||
g_settings.display_crop_mode != old_settings.display_crop_mode ||
g_settings.display_aspect_ratio != old_settings.display_aspect_ratio ||
g_settings.gpu_pgxp_enable != old_settings.gpu_pgxp_enable ||
g_settings.gpu_pgxp_depth_buffer != old_settings.gpu_pgxp_depth_buffer ||
g_settings.display_active_start_offset != old_settings.display_active_start_offset ||
g_settings.display_active_end_offset != old_settings.display_active_end_offset ||
g_settings.display_line_start_offset != old_settings.display_line_start_offset ||
g_settings.display_line_end_offset != old_settings.display_line_end_offset ||
g_settings.rewind_enable != old_settings.rewind_enable ||
g_settings.runahead_frames != old_settings.runahead_frames)
{
g_gpu->UpdateSettings();
OnDisplayInvalidated();
}
if (g_settings.gpu_widescreen_hack != old_settings.gpu_widescreen_hack ||
g_settings.display_aspect_ratio != old_settings.display_aspect_ratio ||
(g_settings.display_aspect_ratio == DisplayAspectRatio::Custom &&
(g_settings.display_aspect_ratio_custom_numerator != old_settings.display_aspect_ratio_custom_numerator ||
g_settings.display_aspect_ratio_custom_denominator != old_settings.display_aspect_ratio_custom_denominator)))
{
GTE::UpdateAspectRatio();
}
if (g_settings.gpu_pgxp_enable != old_settings.gpu_pgxp_enable ||
(g_settings.gpu_pgxp_enable && (g_settings.gpu_pgxp_culling != old_settings.gpu_pgxp_culling ||
g_settings.gpu_pgxp_vertex_cache != old_settings.gpu_pgxp_vertex_cache ||
g_settings.gpu_pgxp_cpu != old_settings.gpu_pgxp_cpu)))
{
if (g_settings.IsUsingCodeCache())
{
AddOSDMessage(g_settings.gpu_pgxp_enable ?
TranslateStdString("OSDMessage", "PGXP enabled, recompiling all blocks.") :
TranslateStdString("OSDMessage", "PGXP disabled, recompiling all blocks."),
5.0f);
CPU::CodeCache::Flush();
}
if (old_settings.gpu_pgxp_enable)
PGXP::Shutdown();
if (g_settings.gpu_pgxp_enable)
PGXP::Initialize();
}
if (g_settings.cdrom_readahead_sectors != old_settings.cdrom_readahead_sectors)
g_cdrom.SetReadaheadSectors(g_settings.cdrom_readahead_sectors);
if (g_settings.memory_card_types != old_settings.memory_card_types ||
g_settings.memory_card_paths != old_settings.memory_card_paths ||
(g_settings.memory_card_use_playlist_title != old_settings.memory_card_use_playlist_title &&
System::HasMediaSubImages()) ||
g_settings.memory_card_directory != old_settings.memory_card_directory)
{
System::UpdateMemoryCardTypes();
}
if (g_settings.rewind_enable != old_settings.rewind_enable ||
g_settings.rewind_save_frequency != old_settings.rewind_save_frequency ||
g_settings.rewind_save_slots != old_settings.rewind_save_slots ||
g_settings.runahead_frames != old_settings.runahead_frames)
{
System::UpdateMemorySaveStateSettings();
}
if (g_settings.texture_replacements.enable_vram_write_replacements !=
old_settings.texture_replacements.enable_vram_write_replacements ||
g_settings.texture_replacements.preload_textures != old_settings.texture_replacements.preload_textures)
{
g_texture_replacements.Reload();
}
g_dma.SetMaxSliceTicks(g_settings.dma_max_slice_ticks);
g_dma.SetHaltTicks(g_settings.dma_halt_ticks);
}
bool controllers_updated = false;
for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++)
{
if (g_settings.controller_types[i] != old_settings.controller_types[i])
{
if (!System::IsShutdown() && !controllers_updated)
{
System::UpdateControllers();
System::ResetControllers();
UpdateSoftwareCursor();
controllers_updated = true;
}
OnControllerTypeChanged(i);
}
if (!System::IsShutdown() && !controllers_updated)
{
System::UpdateControllerSettings();
UpdateSoftwareCursor();
}
}
if (g_settings.multitap_mode != old_settings.multitap_mode)
System::UpdateMultitaps();
if (m_display && (g_settings.display_linear_filtering != old_settings.display_linear_filtering ||
g_settings.display_integer_scaling != old_settings.display_integer_scaling ||
g_settings.display_stretch != old_settings.display_stretch))
{
m_display->SetDisplayLinearFiltering(g_settings.display_linear_filtering);
m_display->SetDisplayIntegerScaling(g_settings.display_integer_scaling);
m_display->SetDisplayStretch(g_settings.display_stretch);
OnDisplayInvalidated();
}
}
void HostInterface::SetUserDirectoryToProgramDirectory()
{
std::string program_path(FileSystem::GetProgramPath());
@ -1004,83 +315,6 @@ std::string HostInterface::GetGameMemoryCardPath(const char* game_code, u32 slot
}
}
bool HostInterface::GetBoolSettingValue(const char* section, const char* key, bool default_value /*= false*/)
{
std::string value = GetStringSettingValue(section, key, "");
if (value.empty())
return default_value;
std::optional<bool> bool_value = StringUtil::FromChars<bool>(value);
return bool_value.value_or(default_value);
}
int HostInterface::GetIntSettingValue(const char* section, const char* key, int default_value /*= 0*/)
{
std::string value = GetStringSettingValue(section, key, "");
if (value.empty())
return default_value;
std::optional<int> int_value = StringUtil::FromChars<int>(value);
return int_value.value_or(default_value);
}
float HostInterface::GetFloatSettingValue(const char* section, const char* key, float default_value /*= 0.0f*/)
{
std::string value = GetStringSettingValue(section, key, "");
if (value.empty())
return default_value;
std::optional<float> float_value = StringUtil::FromChars<float>(value);
return float_value.value_or(default_value);
}
TinyString HostInterface::TranslateString(const char* context, const char* str,
const char* disambiguation /*= nullptr*/, int n /*= -1*/) const
{
TinyString result(str);
if (n >= 0)
{
const std::string number = std::to_string(n);
result.Replace("%n", number.c_str());
result.Replace("%Ln", number.c_str());
}
return result;
}
std::string HostInterface::TranslateStdString(const char* context, const char* str,
const char* disambiguation /*= nullptr*/, int n /*= -1*/) const
{
std::string result(str);
if (n >= 0)
{
const std::string number = std::to_string(n);
// Made to mimick Qt's behaviour
// https://github.com/qt/qtbase/blob/255459250d450286a8c5c492dab3f6d3652171c9/src/corelib/kernel/qcoreapplication.cpp#L2099
size_t percent_pos = 0;
size_t len = 0;
while ((percent_pos = result.find('%', percent_pos + len)) != std::string::npos)
{
len = 1;
if (percent_pos + len == result.length())
break;
if (result[percent_pos + len] == 'L')
{
++len;
if (percent_pos + len == result.length())
break;
}
if (result[percent_pos + len] == 'n')
{
++len;
result.replace(percent_pos, len, number);
len = number.length();
}
}
}
return result;
}
void HostInterface::ToggleSoftwareRendering()
{
if (System::IsShutdown() || g_settings.gpu_renderer == GPURenderer::Software)
@ -1088,10 +322,11 @@ void HostInterface::ToggleSoftwareRendering()
const GPURenderer new_renderer = g_gpu->IsHardwareRenderer() ? GPURenderer::Software : g_settings.gpu_renderer;
AddKeyedFormattedOSDMessage("SoftwareRendering", 5.0f, TranslateString("OSDMessage", "Switching to %s renderer..."),
Settings::GetRendererDisplayName(new_renderer));
Host::AddKeyedFormattedOSDMessage("SoftwareRendering", 5.0f,
Host::TranslateString("OSDMessage", "Switching to %s renderer..."),
Settings::GetRendererDisplayName(new_renderer));
System::RecreateGPU(new_renderer);
OnDisplayInvalidated();
Host::InvalidateDisplay();
}
void HostInterface::ModifyResolutionScale(s32 increment)
@ -1109,7 +344,7 @@ void HostInterface::ModifyResolutionScale(s32 increment)
g_gpu->UpdateSettings();
g_gpu->ResetGraphicsAPIState();
System::ClearMemorySaveStates();
OnDisplayInvalidated();
Host::InvalidateDisplay();
}
}
@ -1118,7 +353,7 @@ void HostInterface::UpdateSoftwareCursor()
if (System::IsShutdown())
{
SetMouseMode(false, false);
m_display->ClearSoftwareCursor();
Host::GetHostDisplay()->ClearSoftwareCursor();
return;
}
@ -1141,38 +376,12 @@ void HostInterface::UpdateSoftwareCursor()
if (image && image->IsValid())
{
m_display->SetSoftwareCursor(image->GetPixels(), image->GetWidth(), image->GetHeight(), image->GetByteStride(),
Host::GetHostDisplay()->SetSoftwareCursor(image->GetPixels(), image->GetWidth(), image->GetHeight(), image->GetByteStride(),
image_scale);
}
else
{
m_display->ClearSoftwareCursor();
Host::GetHostDisplay()->ClearSoftwareCursor();
}
}
void HostInterface::RecreateSystem()
{
Assert(!System::IsShutdown());
std::unique_ptr<ByteStream> stream = ByteStream::CreateGrowableMemoryStream(nullptr, 8 * 1024);
if (!System::SaveState(stream.get(), 0) || !stream->SeekAbsolute(0))
{
ReportError("Failed to save state before system recreation. Shutting down.");
DestroySystem();
return;
}
DestroySystem();
auto boot_params = std::make_shared<SystemBootParameters>();
boot_params->state_stream = std::move(stream);
if (!BootSystem(std::move(boot_params)))
{
ReportError("Failed to boot system after recreation.");
return;
}
System::ResetPerformanceCounters();
System::ResetThrottler();
OnDisplayInvalidated();
}

View File

@ -14,7 +14,6 @@
enum LOGLEVEL;
class AudioStream;
class ByteStream;
class CDImage;
class HostDisplay;
@ -29,54 +28,15 @@ struct ImageInfo;
class HostInterface
{
public:
enum : u32
{
AUDIO_SAMPLE_RATE = 44100,
AUDIO_CHANNELS = 2,
DEFAULT_AUDIO_BUFFER_SIZE = 2048
};
HostInterface();
virtual ~HostInterface();
/// Access to host display.
ALWAYS_INLINE HostDisplay* GetDisplay() const { return m_display.get(); }
ALWAYS_INLINE bool HasDisplay() const { return static_cast<bool>(m_display.get()); }
/// Access to host audio stream.
ALWAYS_INLINE AudioStream* GetAudioStream() const { return m_audio_stream.get(); }
/// Initializes the emulator frontend.
virtual bool Initialize();
/// Shuts down the emulator frontend.
virtual void Shutdown();
virtual bool BootSystem(std::shared_ptr<SystemBootParameters> parameters);
virtual void PauseSystem(bool paused);
virtual void ResetSystem();
virtual void DestroySystem();
/// Loads state from the specified filename.
bool LoadState(const char* filename);
virtual void ReportError(const char* message);
virtual void ReportMessage(const char* message);
virtual void ReportDebuggerMessage(const char* message);
virtual bool ConfirmMessage(const char* message);
void ReportFormattedError(const char* format, ...) printflike(2, 3);
void ReportFormattedMessage(const char* format, ...) printflike(2, 3);
void ReportFormattedDebuggerMessage(const char* format, ...) printflike(2, 3);
bool ConfirmFormattedMessage(const char* format, ...) printflike(2, 3);
/// Adds OSD messages, duration is in seconds.
void AddOSDMessage(std::string message, float duration = 2.0f);
void AddKeyedOSDMessage(std::string key, std::string message, float duration = 2.0f);
void RemoveKeyedOSDMessage(std::string key);
void AddFormattedOSDMessage(float duration, const char* format, ...) printflike(3, 4);
void AddKeyedFormattedOSDMessage(std::string key, float duration, const char* format, ...) printflike(4, 5);
/// Returns the base user directory path.
ALWAYS_INLINE const std::string& GetUserDirectory() const { return m_user_directory; }
@ -109,27 +69,6 @@ public:
/// Returns the path to the shader cache directory.
virtual std::string GetShaderCacheBasePath() const;
/// Returns a setting value from the configuration.
virtual std::string GetStringSettingValue(const char* section, const char* key, const char* default_value = "") = 0;
/// Returns a boolean setting from the configuration.
virtual bool GetBoolSettingValue(const char* section, const char* key, bool default_value = false);
/// Returns an integer setting from the configuration.
virtual int GetIntSettingValue(const char* section, const char* key, int default_value = 0);
/// Returns a float setting from the configuration.
virtual float GetFloatSettingValue(const char* section, const char* key, float default_value = 0.0f);
/// Returns a string list from the configuration.
virtual std::vector<std::string> GetSettingStringList(const char* section, const char* key) = 0;
/// Translates a string to the current language.
virtual TinyString TranslateString(const char* context, const char* str, const char* disambiguation = nullptr,
int n = -1) const;
virtual std::string TranslateStdString(const char* context, const char* str, const char* disambiguation = nullptr,
int n = -1) const;
/// Returns the path to the directory to search for BIOS images.
virtual std::string GetBIOSDirectory();
@ -150,45 +89,9 @@ public:
/// This is the APK for Android builds, or the program directory for standalone builds.
virtual std::unique_ptr<ByteStream> OpenPackageFile(const char* path, u32 flags) = 0;
virtual void OnRunningGameChanged(const std::string& path, CDImage* image, const std::string& game_code,
const std::string& game_title) = 0;
virtual void OnSystemPerformanceCountersUpdated() = 0;
/// Called when the display is invalidated (e.g. a state is loaded).
virtual void OnDisplayInvalidated() = 0;
/// Called when achievements data is loaded.
virtual void OnAchievementsRefreshed() = 0;
protected:
virtual bool AcquireHostDisplay() = 0;
virtual void ReleaseHostDisplay() = 0;
virtual std::unique_ptr<AudioStream> CreateAudioStream(AudioBackend backend) = 0;
virtual s32 GetAudioOutputVolume() const;
virtual void OnSystemCreated() = 0;
virtual void OnSystemPaused(bool paused) = 0;
virtual void OnSystemDestroyed() = 0;
virtual void OnControllerTypeChanged(u32 slot) = 0;
/// Restores all settings to defaults.
virtual void SetDefaultSettings(SettingsInterface& si);
/// Loads settings to m_settings and any frontend-specific parameters.
virtual void LoadSettings(SettingsInterface& si);
/// Saves current settings variables to ini.
virtual void SaveSettings(SettingsInterface& si);
/// Checks and fixes up any incompatible settings.
virtual void FixIncompatibleSettings(bool display_osd_messages);
/// Checks for settings changes, std::move() the old settings away for comparing beforehand.
virtual void CheckForSettingsChanges(const Settings& old_settings);
/// Switches the GPU renderer by saving state, recreating the display window, and restoring state (if needed).
virtual void RecreateSystem();
/// Enables "relative" mouse mode, locking the cursor position and returning relative coordinates.
virtual void SetMouseMode(bool relative, bool hide_cursor) = 0;
@ -207,15 +110,8 @@ protected:
/// Updates software cursor state, based on controllers.
void UpdateSoftwareCursor();
bool SaveState(const char* filename);
void CreateAudioStream();
std::unique_ptr<HostDisplay> m_display;
std::unique_ptr<AudioStream> m_audio_stream;
std::string m_program_directory;
std::string m_user_directory;
};
#define TRANSLATABLE(context, str) str
extern HostInterface* g_host_interface;

View File

@ -1,4 +1,5 @@
#include "host_interface_progress_callback.h"
#include "host.h"
#include "common/log.h"
Log_SetChannel(HostInterfaceProgressCallback);
@ -72,17 +73,16 @@ void HostInterfaceProgressCallback::DisplayDebugMessage(const char* message) { L
void HostInterfaceProgressCallback::ModalError(const char* message)
{
Log_ErrorPrint(message);
g_host_interface->ReportError(message);
Host::ReportErrorAsync("Error", message);
}
bool HostInterfaceProgressCallback::ModalConfirmation(const char* message)
{
Log_InfoPrint(message);
return g_host_interface->ConfirmMessage(message);
return Host::ConfirmMessage("Confirm", message);
}
void HostInterfaceProgressCallback::ModalInformation(const char* message)
{
Log_InfoPrint(message);
g_host_interface->ReportMessage(message);
}

View File

@ -18,13 +18,16 @@ double GetBaseDoubleSettingValue(const char* section, const char* key, double de
std::vector<std::string> GetBaseStringListSetting(const char* section, const char* key);
// Allows the emucore to write settings back to the frontend. Use with care.
// You should call CommitBaseSettingChanges() after finishing writing, or it may not be written to disk.
// You should call CommitBaseSettingChanges() if you directly write to the layer (i.e. not these functions), or it may
// not be written to disk.
void SetBaseBoolSettingValue(const char* section, const char* key, bool value);
void SetBaseIntSettingValue(const char* section, const char* key, s32 value);
void SetBaseUIntSettingValue(const char* section, const char* key, u32 value);
void SetBaseFloatSettingValue(const char* section, const char* key, float value);
void SetBaseStringSettingValue(const char* section, const char* key, const char* value);
void SetBaseStringListSettingValue(const char* section, const char* key, const std::vector<std::string>& values);
bool AddValueToBaseStringListSetting(const char* section, const char* key, const char* value);
bool RemoveValueFromBaseStringListSetting(const char* section, const char* key, const char* value);
void DeleteBaseSettingValue(const char* section, const char* key);
void CommitBaseSettingChanges();

View File

@ -3,6 +3,7 @@
#include "common/file_system.h"
#include "common/log.h"
#include "common/string_util.h"
#include "host.h"
#include "host_interface.h"
#include "system.h"
#include "util/state_wrapper.h"
@ -273,8 +274,8 @@ std::unique_ptr<MemoryCard> MemoryCard::Open(std::string_view filename)
if (!mc->LoadFromFile())
{
Log_InfoPrintf("Memory card at '%s' could not be read, formatting.", mc->m_filename.c_str());
g_host_interface->AddFormattedOSDMessage(
5.0f, g_host_interface->TranslateString("OSDMessage", "Memory card at '%s' could not be read, formatting."),
Host::AddFormattedOSDMessage(
5.0f, Host::TranslateString("OSDMessage", "Memory card at '%s' could not be read, formatting."),
mc->m_filename.c_str());
mc->Format();
}
@ -309,8 +310,8 @@ bool MemoryCard::SaveIfChanged(bool display_osd_message)
{
if (display_osd_message)
{
g_host_interface->AddFormattedOSDMessage(
20.0f, g_host_interface->TranslateString("OSDMessage", "Failed to save memory card to '%s'"),
Host::AddFormattedOSDMessage(
20.0f, Host::TranslateString("OSDMessage", "Failed to save memory card to '%s'"),
m_filename.c_str());
}
@ -318,8 +319,10 @@ bool MemoryCard::SaveIfChanged(bool display_osd_message)
}
if (display_osd_message)
g_host_interface->AddFormattedOSDMessage(
2.0f, g_host_interface->TranslateString("OSDMessage", "Saved memory card to '%s'"), m_filename.c_str());
{
Host::AddFormattedOSDMessage(
2.0f, Host::TranslateString("OSDMessage", "Saved memory card to '%s'"), m_filename.c_str());
}
return true;
}

View File

@ -1,7 +1,7 @@
#include "pad.h"
#include "common/log.h"
#include "controller.h"
#include "host_interface.h"
#include "host.h"
#include "interrupt_controller.h"
#include "memory_card.h"
#include "multitap.h"
@ -66,17 +66,17 @@ bool Pad::DoStateController(StateWrapper& sw, u32 i)
// UI notification portion is separated from emulation portion (intentional condition check redundancy)
if (g_settings.load_devices_from_save_states)
{
g_host_interface->AddFormattedOSDMessage(
Host::AddFormattedOSDMessage(
10.0f,
g_host_interface->TranslateString(
"OSDMessage", "Save state contains controller type %s in port %u, but %s is used. Switching."),
Host::TranslateString("OSDMessage",
"Save state contains controller type %s in port %u, but %s is used. Switching."),
Settings::GetControllerTypeName(state_controller_type), i + 1u,
Settings::GetControllerTypeName(controller_type));
}
else
{
g_host_interface->AddFormattedOSDMessage(
10.0f, g_host_interface->TranslateString("OSDMessage", "Ignoring mismatched controller type %s in port %u."),
Host::AddFormattedOSDMessage(
10.0f, Host::TranslateString("OSDMessage", "Ignoring mismatched controller type %s in port %u."),
Settings::GetControllerTypeName(state_controller_type), i + 1u);
}
@ -129,10 +129,10 @@ bool Pad::DoStateMemcard(StateWrapper& sw, u32 i)
if (card_present_in_state && !m_memory_cards[i] && g_settings.load_devices_from_save_states)
{
g_host_interface->AddFormattedOSDMessage(
Host::AddFormattedOSDMessage(
20.0f,
g_host_interface->TranslateString(
"OSDMessage", "Memory card %u present in save state but not in system. Creating temporary card."),
Host::TranslateString("OSDMessage",
"Memory card %u present in save state but not in system. Creating temporary card."),
i + 1u);
m_memory_cards[i] = MemoryCard::Create();
}
@ -170,10 +170,10 @@ bool Pad::DoStateMemcard(StateWrapper& sw, u32 i)
}
else
{
g_host_interface->AddFormattedOSDMessage(
Host::AddFormattedOSDMessage(
20.0f,
g_host_interface->TranslateString(
"OSDMessage", "Memory card %u from save state does match current card data. Simulating replugging."),
Host::TranslateString("OSDMessage",
"Memory card %u from save state does match current card data. Simulating replugging."),
i + 1u);
// this is a potentially serious issue - some games cache info from memcards and jumping around
@ -188,10 +188,9 @@ bool Pad::DoStateMemcard(StateWrapper& sw, u32 i)
}
else
{
g_host_interface->AddFormattedOSDMessage(
Host::AddFormattedOSDMessage(
20.0f,
g_host_interface->TranslateString("OSDMessage",
"Memory card %u present in save state but not in system. Ignoring card."),
Host::TranslateString("OSDMessage", "Memory card %u present in save state but not in system. Ignoring card."),
i + 1u);
}
@ -202,19 +201,17 @@ bool Pad::DoStateMemcard(StateWrapper& sw, u32 i)
{
if (g_settings.load_devices_from_save_states)
{
g_host_interface->AddFormattedOSDMessage(
Host::AddFormattedOSDMessage(
20.0f,
g_host_interface->TranslateString("OSDMessage",
"Memory card %u present in system but not in save state. Removing card."),
Host::TranslateString("OSDMessage", "Memory card %u present in system but not in save state. Removing card."),
i + 1u);
m_memory_cards[i].reset();
}
else
{
g_host_interface->AddFormattedOSDMessage(
Host::AddFormattedOSDMessage(
20.0f,
g_host_interface->TranslateString("OSDMessage",
"Memory card %u present in system but not in save state. Replugging card."),
Host::TranslateString("OSDMessage", "Memory card %u present in system but not in save state. Replugging card."),
i + 1u);
m_memory_cards[i]->Reset();
}

View File

@ -1,14 +1,18 @@
#include "settings.h"
#include "cheevos.h"
#include "common/assert.h"
#include "common/file_system.h"
#include "common/log.h"
#include "common/make_array.h"
#include "common/string_util.h"
#include "host.h"
#include "host_display.h"
#include "host_interface.h"
#include <algorithm>
#include <array>
#include <cctype>
#include <numeric>
Log_SetChannel(Settings);
Settings g_settings;
@ -68,7 +72,16 @@ float SettingInfo::FloatStepValue() const
return step_value ? StringUtil::FromChars<float>(step_value).value_or(fallback_value) : fallback_value;
}
Settings::Settings() = default;
Settings::Settings()
{
controller_types[0] = DEFAULT_CONTROLLER_1_TYPE;
memory_card_types[0] = DEFAULT_MEMORY_CARD_1_TYPE;
for (u32 i = 1; i < NUM_CONTROLLER_AND_CARD_PORTS; i++)
{
controller_types[i] = DEFAULT_CONTROLLER_2_TYPE;
memory_card_types[i] = DEFAULT_MEMORY_CARD_2_TYPE;
}
}
bool Settings::HasAnyPerGameMemoryCards() const
{
@ -239,11 +252,13 @@ void Settings::Load(SettingsInterface& si)
display_show_status_indicators = si.GetBoolValue("Display", "ShowStatusIndicators", true);
display_show_enhancements = si.GetBoolValue("Display", "ShowEnhancements", false);
display_all_frames = si.GetBoolValue("Display", "DisplayAllFrames", false);
display_internal_resolution_screenshots = si.GetBoolValue("Display", "InternalResolutionScreenshots", false);
video_sync_enabled = si.GetBoolValue("Display", "VSync", DEFAULT_VSYNC_VALUE);
display_post_process_chain = si.GetStringValue("Display", "PostProcessChain", "");
display_max_fps = si.GetFloatValue("Display", "MaxFPS", DEFAULT_DISPLAY_MAX_FPS);
cdrom_readahead_sectors = static_cast<u8>(si.GetIntValue("CDROM", "ReadaheadSectors", DEFAULT_CDROM_READAHEAD_SECTORS));
cdrom_readahead_sectors =
static_cast<u8>(si.GetIntValue("CDROM", "ReadaheadSectors", DEFAULT_CDROM_READAHEAD_SECTORS));
cdrom_region_check = si.GetBoolValue("CDROM", "RegionCheck", false);
cdrom_load_image_to_ram = si.GetBoolValue("CDROM", "LoadImageToRAM", false);
cdrom_mute_cd_audio = si.GetBoolValue("CDROM", "MuteCDAudio", false);
@ -255,7 +270,7 @@ void Settings::Load(SettingsInterface& si)
.value_or(DEFAULT_AUDIO_BACKEND);
audio_output_volume = si.GetIntValue("Audio", "OutputVolume", 100);
audio_fast_forward_volume = si.GetIntValue("Audio", "FastForwardVolume", 100);
audio_buffer_size = si.GetIntValue("Audio", "BufferSize", HostInterface::DEFAULT_AUDIO_BUFFER_SIZE);
audio_buffer_size = si.GetIntValue("Audio", "BufferSize", DEFAULT_AUDIO_BUFFER_SIZE);
audio_resampling = si.GetBoolValue("Audio", "Resampling", true);
audio_output_muted = si.GetBoolValue("Audio", "OutputMuted", false);
audio_sync_enabled = si.GetBoolValue("Audio", "Sync", true);
@ -416,6 +431,7 @@ void Settings::Save(SettingsInterface& si) const
si.SetBoolValue("Display", "ShowStatusIndicators", display_show_status_indicators);
si.SetBoolValue("Display", "ShowEnhancements", display_show_enhancements);
si.SetBoolValue("Display", "DisplayAllFrames", display_all_frames);
si.SetBoolValue("Display", "InternalResolutionScreenshots", display_internal_resolution_screenshots);
si.SetBoolValue("Display", "VSync", video_sync_enabled);
if (display_post_process_chain.empty())
si.DeleteValue("Display", "PostProcessChain");
@ -502,6 +518,104 @@ void Settings::Save(SettingsInterface& si) const
texture_replacements.dump_vram_write_height_threshold);
}
void Settings::FixIncompatibleSettings(bool display_osd_messages)
{
if (g_settings.disable_all_enhancements)
{
Log_WarningPrintf("All enhancements disabled by config setting.");
g_settings.cpu_overclock_enable = false;
g_settings.cpu_overclock_active = false;
g_settings.enable_8mb_ram = false;
g_settings.gpu_resolution_scale = 1;
g_settings.gpu_multisamples = 1;
g_settings.gpu_per_sample_shading = false;
g_settings.gpu_true_color = false;
g_settings.gpu_scaled_dithering = false;
g_settings.gpu_texture_filter = GPUTextureFilter::Nearest;
g_settings.gpu_disable_interlacing = false;
g_settings.gpu_force_ntsc_timings = false;
g_settings.gpu_widescreen_hack = false;
g_settings.gpu_pgxp_enable = false;
g_settings.gpu_24bit_chroma_smoothing = false;
g_settings.cdrom_read_speedup = 1;
g_settings.cdrom_seek_speedup = 1;
g_settings.cdrom_mute_cd_audio = false;
g_settings.texture_replacements.enable_vram_write_replacements = false;
g_settings.bios_patch_fast_boot = false;
g_settings.bios_patch_tty_enable = false;
}
if (g_settings.display_integer_scaling && g_settings.display_linear_filtering)
{
Log_WarningPrintf("Disabling linear filter due to integer upscaling.");
g_settings.display_linear_filtering = false;
}
if (g_settings.display_integer_scaling && g_settings.display_stretch)
{
Log_WarningPrintf("Disabling stretch due to integer upscaling.");
g_settings.display_stretch = false;
}
if (g_settings.gpu_pgxp_enable)
{
if (g_settings.gpu_renderer == GPURenderer::Software)
{
if (display_osd_messages)
{
Host::AddOSDMessage(
Host::TranslateStdString("OSDMessage", "PGXP is incompatible with the software renderer, disabling PGXP."),
10.0f);
}
g_settings.gpu_pgxp_enable = false;
}
}
#ifndef WITH_MMAP_FASTMEM
if (g_settings.cpu_fastmem_mode == CPUFastmemMode::MMap)
{
Log_WarningPrintf("mmap fastmem is not available on this platform, using LUT instead.");
g_settings.cpu_fastmem_mode = CPUFastmemMode::LUT;
}
#endif
#if defined(__ANDROID__) && defined(__arm__) && !defined(__aarch64__) && !defined(_M_ARM64)
if (g_settings.rewind_enable)
{
Host::AddOSDMessage(Host::TranslateStdString("OSDMessage", "Rewind is not supported on 32-bit ARM for Android."),
30.0f);
g_settings.rewind_enable = false;
}
#endif
// if challenge mode is enabled, disable things like rewind since they use save states
if (Cheevos::IsChallengeModeActive())
{
g_settings.emulation_speed =
(g_settings.emulation_speed != 0.0f) ? std::max(g_settings.emulation_speed, 1.0f) : 0.0f;
g_settings.fast_forward_speed =
(g_settings.fast_forward_speed != 0.0f) ? std::max(g_settings.fast_forward_speed, 1.0f) : 0.0f;
g_settings.turbo_speed = (g_settings.turbo_speed != 0.0f) ? std::max(g_settings.turbo_speed, 1.0f) : 0.0f;
g_settings.rewind_enable = false;
g_settings.auto_load_cheats = false;
if (g_settings.cpu_overclock_enable && g_settings.GetCPUOverclockPercent() < 100)
{
g_settings.cpu_overclock_enable = false;
g_settings.UpdateOverclockActive();
}
g_settings.debugging.enable_gdb_server = false;
g_settings.debugging.show_vram = false;
g_settings.debugging.show_gpu_state = false;
g_settings.debugging.show_cdrom_state = false;
g_settings.debugging.show_spu_state = false;
g_settings.debugging.show_timers_state = false;
g_settings.debugging.show_mdec_state = false;
g_settings.debugging.show_dma_state = false;
g_settings.debugging.dump_cpu_to_vram_copies = false;
g_settings.debugging.dump_vram_to_cpu_copies = false;
}
}
static std::array<const char*, LOGLEVEL_COUNT> s_log_level_names = {
{"None", "Error", "Warning", "Perf", "Info", "Verbose", "Dev", "Profile", "Debug", "Trace"}};
static std::array<const char*, LOGLEVEL_COUNT> s_log_level_display_names = {
@ -655,14 +769,12 @@ const char* Settings::GetCPUFastmemModeDisplayName(CPUFastmemMode mode)
static constexpr auto s_gpu_renderer_names = make_array(
#ifdef _WIN32
"D3D11",
"D3D12",
"D3D11", "D3D12",
#endif
"Vulkan", "OpenGL", "Software");
static constexpr auto s_gpu_renderer_display_names = make_array(
#ifdef _WIN32
TRANSLATABLE("GPURenderer", "Hardware (D3D11)"),
TRANSLATABLE("GPURenderer", "Hardware (D3D12)"),
TRANSLATABLE("GPURenderer", "Hardware (D3D11)"), TRANSLATABLE("GPURenderer", "Hardware (D3D12)"),
#endif
TRANSLATABLE("GPURenderer", "Hardware (Vulkan)"), TRANSLATABLE("GPURenderer", "Hardware (OpenGL)"),
TRANSLATABLE("GPURenderer", "Software"));
@ -812,7 +924,7 @@ float Settings::GetDisplayAspectRatioValue() const
{
case DisplayAspectRatio::MatchWindow:
{
const HostDisplay* display = g_host_interface->GetDisplay();
const HostDisplay* display = Host::GetHostDisplay();
if (!display)
return s_display_aspect_ratio_values[static_cast<int>(DEFAULT_DISPLAY_ASPECT_RATIO)];

View File

@ -44,9 +44,9 @@ struct Settings
{
Settings();
ConsoleRegion region = ConsoleRegion::Auto;
ConsoleRegion region = DEFAULT_CONSOLE_REGION;
CPUExecutionMode cpu_execution_mode = CPUExecutionMode::Interpreter;
CPUExecutionMode cpu_execution_mode = DEFAULT_CPU_EXECUTION_MODE;
u32 cpu_overclock_numerator = 1;
u32 cpu_overclock_denominator = 1;
bool cpu_overclock_enable = false;
@ -54,14 +54,14 @@ struct Settings
bool cpu_recompiler_memory_exceptions = false;
bool cpu_recompiler_block_linking = true;
bool cpu_recompiler_icache = false;
CPUFastmemMode cpu_fastmem_mode = CPUFastmemMode::Disabled;
CPUFastmemMode cpu_fastmem_mode = DEFAULT_CPU_FASTMEM_MODE;
float emulation_speed = 1.0f;
float fast_forward_speed = 0.0f;
float turbo_speed = 0.0f;
bool sync_to_host_refresh_rate = true;
bool sync_to_host_refresh_rate = false;
bool increase_timer_resolution = true;
bool inhibit_screensaver = false;
bool inhibit_screensaver = true;
bool start_paused = false;
bool start_fullscreen = false;
bool pause_on_focus_loss = false;
@ -70,7 +70,7 @@ struct Settings
bool confim_power_off = true;
bool load_devices_from_save_states = false;
bool apply_game_settings = true;
bool auto_load_cheats = false;
bool auto_load_cheats = true;
bool disable_all_enhancements = false;
bool rewind_enable = false;
@ -78,7 +78,7 @@ struct Settings
u32 rewind_save_slots = 10;
u32 runahead_frames = 0;
GPURenderer gpu_renderer = GPURenderer::Software;
GPURenderer gpu_renderer = DEFAULT_GPU_RENDERER;
std::string gpu_adapter;
std::string display_post_process_chain;
u32 gpu_resolution_scale = 1;
@ -88,10 +88,10 @@ struct Settings
bool gpu_threaded_presentation = true;
bool gpu_use_debug_device = false;
bool gpu_per_sample_shading = false;
bool gpu_true_color = false;
bool gpu_scaled_dithering = false;
GPUTextureFilter gpu_texture_filter = GPUTextureFilter::Nearest;
GPUDownsampleMode gpu_downsample_mode = GPUDownsampleMode::Disabled;
bool gpu_true_color = true;
bool gpu_scaled_dithering = true;
GPUTextureFilter gpu_texture_filter = DEFAULT_GPU_TEXTURE_FILTER;
GPUDownsampleMode gpu_downsample_mode = DEFAULT_GPU_DOWNSAMPLE_MODE;
bool gpu_disable_interlacing = true;
bool gpu_force_ntsc_timings = false;
bool gpu_widescreen_hack = false;
@ -102,8 +102,8 @@ struct Settings
bool gpu_pgxp_cpu = false;
bool gpu_pgxp_preserve_proj_fp = false;
bool gpu_pgxp_depth_buffer = false;
DisplayCropMode display_crop_mode = DisplayCropMode::None;
DisplayAspectRatio display_aspect_ratio = DisplayAspectRatio::Auto;
DisplayCropMode display_crop_mode = DEFAULT_DISPLAY_CROP_MODE;
DisplayAspectRatio display_aspect_ratio = DEFAULT_DISPLAY_ASPECT_RATIO;
u16 display_aspect_ratio_custom_numerator = 0;
u16 display_aspect_ratio_custom_denominator = 0;
s16 display_active_start_offset = 0;
@ -124,10 +124,11 @@ struct Settings
bool display_show_status_indicators = true;
bool display_show_enhancements = false;
bool display_all_frames = false;
bool display_internal_resolution_screenshots = false;
bool video_sync_enabled = DEFAULT_VSYNC_VALUE;
float display_max_fps = DEFAULT_DISPLAY_MAX_FPS;
float gpu_pgxp_tolerance = -1.0f;
float gpu_pgxp_depth_clear_threshold = 300.0f / 4096.0f;
float gpu_pgxp_depth_clear_threshold = DEFAULT_GPU_PGXP_DEPTH_THRESHOLD;
u8 cdrom_readahead_sectors = DEFAULT_CDROM_READAHEAD_SECTORS;
bool cdrom_region_check = false;
@ -136,20 +137,20 @@ struct Settings
u32 cdrom_read_speedup = 1;
u32 cdrom_seek_speedup = 1;
AudioBackend audio_backend = AudioBackend::Cubeb;
AudioBackend audio_backend = DEFAULT_AUDIO_BACKEND;
s32 audio_output_volume = 100;
s32 audio_fast_forward_volume = 100;
u32 audio_buffer_size = 2048;
bool audio_resampling = false;
u32 audio_buffer_size = DEFAULT_AUDIO_BUFFER_SIZE;
bool audio_resampling = true;
bool audio_output_muted = false;
bool audio_sync_enabled = true;
bool audio_dump_on_boot = true;
bool audio_dump_on_boot = false;
// timing hacks section
TickCount dma_max_slice_ticks = 1000;
TickCount dma_halt_ticks = 100;
u32 gpu_fifo_size = 128;
TickCount gpu_max_run_ahead = 128;
TickCount dma_max_slice_ticks = DEFAULT_DMA_MAX_SLICE_TICKS;
TickCount dma_halt_ticks = DEFAULT_DMA_HALT_TICKS;
u32 gpu_fifo_size = DEFAULT_GPU_FIFO_SIZE;
TickCount gpu_max_run_ahead = DEFAULT_GPU_MAX_RUN_AHEAD;
struct DebugSettings
{
@ -191,7 +192,7 @@ struct Settings
// TODO: Controllers, memory cards, etc.
bool bios_patch_tty_enable = false;
bool bios_patch_fast_boot = false;
bool bios_patch_fast_boot = DEFAULT_FAST_BOOT_VALUE;
bool enable_8mb_ram = false;
std::array<ControllerType, NUM_CONTROLLER_AND_CARD_PORTS> controller_types{};
@ -202,13 +203,13 @@ struct Settings
std::string memory_card_directory;
bool memory_card_use_playlist_title = true;
MultitapMode multitap_mode = MultitapMode::Disabled;
MultitapMode multitap_mode = DEFAULT_MULTITAP_MODE;
std::array<TinyString, NUM_CONTROLLER_AND_CARD_PORTS> GeneratePortLabels() const;
LOGLEVEL log_level = LOGLEVEL_INFO;
LOGLEVEL log_level = DEFAULT_LOG_LEVEL;
std::string log_filter;
bool log_to_console = false;
bool log_to_console = DEFAULT_LOG_TO_CONSOLE;
bool log_to_debug = false;
bool log_to_window = false;
bool log_to_file = false;
@ -268,6 +269,8 @@ struct Settings
void Load(SettingsInterface& si);
void Save(SettingsInterface& si) const;
void FixIncompatibleSettings(bool display_osd_messages);
static std::optional<LOGLEVEL> ParseLogLevelName(const char* str);
static const char* GetLogLevelName(LOGLEVEL level);
static const char* GetLogLevelDisplayName(LOGLEVEL level);
@ -367,6 +370,8 @@ struct Settings
static constexpr LOGLEVEL DEFAULT_LOG_LEVEL = LOGLEVEL_INFO;
static constexpr u32 DEFAULT_AUDIO_BUFFER_SIZE = 2048;
// Enable console logging by default on Linux platforms.
#if defined(__linux__) && !defined(__ANDROID__)
static constexpr bool DEFAULT_LOG_TO_CONSOLE = true;

View File

@ -3,6 +3,7 @@
#include "common/file_system.h"
#include "common/log.h"
#include "dma.h"
#include "host.h"
#include "host_interface.h"
#include "imgui.h"
#include "interrupt_controller.h"
@ -30,11 +31,37 @@ void SPU::Initialize()
"SPU Transfer", TRANSFER_TICKS_PER_HALFWORD, TRANSFER_TICKS_PER_HALFWORD,
[](void* param, TickCount ticks, TickCount ticks_late) { static_cast<SPU*>(param)->ExecuteTransfer(ticks); }, this,
false);
m_audio_stream = g_host_interface->GetAudioStream();
CreateOutputStream();
Reset();
}
void SPU::CreateOutputStream()
{
Log_InfoPrintf("Creating '%s' audio stream, sample rate = %u, channels = %u, buffer size = %u",
Settings::GetAudioBackendName(g_settings.audio_backend), SAMPLE_RATE, NUM_CHANNELS,
g_settings.audio_buffer_size);
m_audio_stream = Host::CreateAudioStream(g_settings.audio_backend);
if (!m_audio_stream ||
!m_audio_stream->Reconfigure(SAMPLE_RATE, SAMPLE_RATE, NUM_CHANNELS, g_settings.audio_buffer_size))
{
Host::ReportErrorAsync("Error", "Failed to create or configure audio stream, falling back to null output.");
m_audio_stream.reset();
m_audio_stream = AudioStream::CreateNullAudioStream();
m_audio_stream->Reconfigure(SAMPLE_RATE, SAMPLE_RATE, NUM_CHANNELS, g_settings.audio_buffer_size);
}
m_audio_stream->SetOutputVolume(System::GetAudioOutputVolume());
}
void SPU::RecreateOutputStream()
{
m_audio_stream.reset();
CreateOutputStream();
}
void SPU::CPUClockChanged()
{
// (X * D) / N / 768 -> (X * D) / (N * 768)
@ -1781,11 +1808,13 @@ void SPU::Execute(TickCount ticks)
m_ticks_carry = (ticks + m_ticks_carry) % SYSCLK_TICKS_PER_SPU_TICK;
}
AudioStream* output_stream = m_audio_output_muted ? m_null_audio_stream.get() : m_audio_stream.get();
while (remaining_frames > 0)
{
s16* output_frame_start;
u32 output_frame_space = remaining_frames;
m_audio_stream->BeginWrite(&output_frame_start, &output_frame_space);
output_stream->BeginWrite(&output_frame_start, &output_frame_space);
s16* output_frame = output_frame_start;
const u32 frames_in_this_batch = std::min(remaining_frames, output_frame_space);
@ -1888,7 +1917,7 @@ void SPU::Execute(TickCount ticks)
if (m_dump_writer)
m_dump_writer->WriteFrames(output_frame_start, frames_in_this_batch);
m_audio_stream->EndWrite(frames_in_this_batch);
output_stream->EndWrite(frames_in_this_batch);
remaining_frames -= frames_in_this_batch;
}
}
@ -1898,7 +1927,7 @@ void SPU::UpdateEventInterval()
// Don't generate more than the audio buffer since in a single slice, otherwise we'll both overflow the buffers when
// we do write it, and the audio thread will underflow since it won't have enough data it the game isn't messing with
// the SPU state.
const u32 max_slice_frames = g_host_interface->GetAudioStream()->GetBufferSize();
const u32 max_slice_frames = m_audio_stream->GetBufferSize();
// TODO: Make this predict how long until the interrupt will be hit instead...
const u32 interval = (m_SPUCNT.enable && m_SPUCNT.irq9_enable) ? 1 : max_slice_frames;

View File

@ -11,6 +11,8 @@
class StateWrapper;
class AudioStream;
namespace Common {
class WAVWriter;
}
@ -24,6 +26,7 @@ public:
{
RAM_SIZE = 512 * 1024,
RAM_MASK = RAM_SIZE - 1,
SAMPLE_RATE = 44100,
};
SPU();
@ -61,16 +64,21 @@ public:
std::array<u8, RAM_SIZE>& GetRAM() { return m_ram; }
/// Change output stream - used for runahead.
ALWAYS_INLINE void SetAudioStream(AudioStream* stream) { m_audio_stream = stream; }
// TODO: Make it use system "running ahead" flag
ALWAYS_INLINE bool IsAudioOutputMuted() const { return m_audio_output_muted; }
void SetAudioOutputMuted(bool muted) { m_audio_output_muted = muted; }
ALWAYS_INLINE AudioStream* GetOutputStream() const { return m_audio_stream.get(); }
void RecreateOutputStream();
private:
static constexpr u32 SPU_BASE = 0x1F801C00;
static constexpr u32 NUM_CHANNELS = 2;
static constexpr u32 NUM_VOICES = 24;
static constexpr u32 NUM_VOICE_REGISTERS = 8;
static constexpr u32 VOICE_ADDRESS_SHIFT = 3;
static constexpr u32 NUM_SAMPLES_PER_ADPCM_BLOCK = 28;
static constexpr u32 NUM_SAMPLES_FROM_LAST_ADPCM_BLOCK = 3;
static constexpr u32 SAMPLE_RATE = 44100;
static constexpr u32 SYSCLK_TICKS_PER_SPU_TICK = System::MASTER_CLOCK / SAMPLE_RATE; // 0x300
static constexpr s16 ENVELOPE_MIN_VOLUME = 0;
static constexpr s16 ENVELOPE_MAX_VOLUME = 0x7FFF;
@ -376,10 +384,15 @@ private:
void UpdateTransferEvent();
void UpdateDMARequest();
void CreateOutputStream();
std::unique_ptr<TimingEvent> m_tick_event;
std::unique_ptr<TimingEvent> m_transfer_event;
std::unique_ptr<Common::WAVWriter> m_dump_writer;
AudioStream* m_audio_stream = nullptr;
std::unique_ptr<AudioStream> m_audio_stream;
std::unique_ptr<AudioStream> m_null_audio_stream;
bool m_audio_output_muted = false;
TickCount m_ticks_carry = 0;
TickCount m_cpu_ticks_per_spu_tick = 0;
TickCount m_cpu_tick_divider = 0;

File diff suppressed because it is too large Load Diff

View File

@ -34,12 +34,38 @@ struct SystemBootParameters
bool force_software_renderer = false;
};
struct SaveStateInfo
{
std::string path;
std::time_t timestamp;
s32 slot;
bool global;
};
struct ExtendedSaveStateInfo
{
std::string path;
std::string title;
std::string game_code;
std::string media_path;
std::time_t timestamp;
s32 slot;
bool global;
u32 screenshot_width;
u32 screenshot_height;
std::vector<u32> screenshot_data;
};
namespace System {
enum : u32
{
// 5 megabytes is sufficient for now, at the moment they're around 4.3MB, or 10.3MB with 8MB RAM enabled.
MAX_SAVE_STATE_SIZE = 11 * 1024 * 1024
MAX_SAVE_STATE_SIZE = 11 * 1024 * 1024,
PER_GAME_SAVE_STATE_SLOTS = 10,
GLOBAL_SAVE_STATE_SLOTS = 10
};
enum : TickCount
@ -82,6 +108,9 @@ DiscRegion GetRegionForExe(const char* path);
DiscRegion GetRegionForPsf(const char* path);
std::optional<DiscRegion> GetRegionForPath(const char* image_path);
/// Returns the path for the game settings ini file for the specified serial.
std::string GetGameSettingsPath(const std::string_view& game_serial);
State GetState();
void SetState(State new_state);
bool IsRunning();
@ -147,12 +176,36 @@ float GetThrottleFrequency();
float GetCPUThreadUsage();
float GetCPUThreadAverageTime();
bool Boot(const SystemBootParameters& params);
void Reset();
void Shutdown();
/// Loads global settings (i.e. EmuConfig).
void LoadSettings(bool display_osd_messages);
void SetDefaultSettings(SettingsInterface& si);
bool LoadState(ByteStream* state, bool update_display = true);
bool SaveState(ByteStream* state, u32 screenshot_size = 256);
/// Reloads settings, and applies any changes present.
void ApplySettings(bool display_osd_messages);
/// Reloads game specific settings, and applys any changes present.
bool ReloadGameSettings(bool display_osd_messages);
bool BootSystem(std::shared_ptr<SystemBootParameters> parameters);
void PauseSystem(bool paused);
void ResetSystem();
void DestroySystem();
/// Loads state from the specified filename.
bool LoadState(const char* filename);
bool SaveState(const char* filename);
/// Loads the current emulation state from file. Specifying a slot of -1 loads the "resume" game state.
bool LoadStateFromSlot(bool global, s32 slot);
/// Saves the current emulation state to a file. Specifying a slot of -1 saves the "resume" save state.
bool SaveStateToSlot(bool global, s32 slot);
/// Runs the VM until the CPU execution is canceled.
void Execute();
/// Switches the GPU renderer by saving state, recreating the display window, and restoring state (if needed).
void RecreateSystem();
/// Recreates the GPU component, saving/loading the state so it is preserved. Call when the GPU renderer changes.
bool RecreateGPU(GPURenderer renderer, bool update_display = true);
@ -163,7 +216,6 @@ void RunFrames();
/// Sets target emulation speed.
float GetTargetSpeed();
void SetTargetSpeed(float speed);
/// Adjusts the throttle frequency, i.e. how many times we should sleep per second.
void SetThrottleFrequency(float frequency);
@ -186,7 +238,10 @@ void ResetControllers();
void UpdateMemoryCardTypes();
void UpdatePerGameMemoryCards();
bool HasMemoryCard(u32 slot);
/// Swaps memory cards in slot 1/2.
void SwapMemoryCards();
void UpdateMultitaps();
/// Dumps RAM to a file.
@ -233,6 +288,140 @@ void ApplyCheatCode(const CheatCode& code);
/// Sets or clears the provided cheat list, applying every frame.
void SetCheatList(std::unique_ptr<CheatList> cheats);
/// Checks for settings changes, std::move() the old settings away for comparing beforehand.
void CheckForSettingsChanges(const Settings& old_settings);
/// Updates throttler.
void UpdateSpeedLimiterState();
/// Toggles fast forward state.
bool IsFastForwardEnabled();
void SetFastForwardEnabled(bool enabled);
/// Toggles turbo state.
bool IsTurboEnabled();
void SetTurboEnabled(bool enabled);
/// Toggles rewind state.
bool IsRewinding();
void SetRewindState(bool enabled);
void DoFrameStep();
void DoToggleCheats();
/// Returns the path to a save state file. Specifying an index of -1 is the "resume" save state.
std::string GetGameSaveStateFileName(const char* game_code, s32 slot);
/// Returns the path to a save state file. Specifying an index of -1 is the "resume" save state.
std::string GetGlobalSaveStateFileName(s32 slot);
/// Moves the current save state file to a backup name, if it exists.
void RenameCurrentSaveStateToBackup(const char* filename);
/// Returns the most recent resume save state.
std::string GetMostRecentResumeSaveStatePath();
/// Returns the path to the cheat file for the specified game title.
std::string GetCheatFileName();
/// Powers off the system, optionally saving the resume state.
void PowerOffSystem(bool save_resume_state);
/// Returns true if an undo load state exists.
bool CanUndoLoadState();
/// Returns save state info for the undo slot, if present.
std::optional<ExtendedSaveStateInfo> GetUndoSaveStateInfo();
/// Undoes a load state, i.e. restores the state prior to the load.
bool UndoLoadState();
/// Returns true if the specified file/disc image is resumable.
bool CanResumeSystemFromFile(const char* filename);
/// Loads the resume save state for the given game. Optionally boots the game anyway if loading fails.
bool ResumeSystemFromState(const char* filename, bool boot_on_failure);
/// Loads the most recent resume save state. This may be global or per-game.
bool ResumeSystemFromMostRecentState();
/// Saves the resume save state, call when shutting down.
bool SaveResumeSaveState();
/// Returns a list of save states for the specified game code.
std::vector<SaveStateInfo> GetAvailableSaveStates(const char* game_code);
/// Returns save state info if present. If game_code is null or empty, assumes global state.
std::optional<SaveStateInfo> GetSaveStateInfo(const char* game_code, s32 slot);
/// Returns save state info from opened save state stream.
std::optional<ExtendedSaveStateInfo> GetExtendedSaveStateInfo(ByteStream* stream);
/// Returns save state info if present. If game_code is null or empty, assumes global state.
std::optional<ExtendedSaveStateInfo> GetExtendedSaveStateInfo(const char* game_code, s32 slot);
/// Deletes save states for the specified game code. If resume is set, the resume state is deleted too.
void DeleteSaveStates(const char* game_code, bool resume);
/// Returns intended output volume considering fast forwarding.
s32 GetAudioOutputVolume();
void UpdateVolume();
/// Returns true if currently dumping audio.
bool IsDumpingAudio();
/// Starts dumping audio to a file. If no file name is provided, one will be generated automatically.
bool StartDumpingAudio(const char* filename = nullptr);
/// Stops dumping audio to file if it has been started.
void StopDumpingAudio();
/// Saves a screenshot to the specified file. IF no file name is provided, one will be generated automatically.
bool SaveScreenshot(const char* filename = nullptr, bool full_resolution = true, bool apply_aspect_ratio = true,
bool compress_on_thread = true);
/// Loads the cheat list from the specified file.
bool LoadCheatList(const char* filename);
/// Loads the cheat list for the current game title from the user directory.
bool LoadCheatListFromGameTitle();
/// Loads the cheat list for the current game code from the built-in code database.
bool LoadCheatListFromDatabase();
/// Saves the current cheat list to the game title's file.
bool SaveCheatList();
/// Saves the current cheat list to the specified file.
bool SaveCheatList(const char* filename);
/// Deletes the cheat list, if present.
bool DeleteCheatList();
/// Removes all cheats from the cheat list.
void ClearCheatList(bool save_to_file);
/// Enables/disabled the specified cheat code.
void SetCheatCodeState(u32 index, bool enabled, bool save_to_file);
/// Immediately applies the specified cheat code.
void ApplyCheatCode(u32 index);
/// Temporarily toggles post-processing on/off.
void TogglePostProcessing();
/// Reloads post processing shaders with the current configuration.
void ReloadPostProcessingShaders();
/// Toggle Widescreen Hack and Aspect Ratio
void ToggleWidescreen();
/// Returns true if the state should be saved on shutdown.
bool ShouldSaveResumeState();
/// Returns true if fast forwarding or slow motion is currently active.
bool IsRunningAtNonStandardSpeed();
//////////////////////////////////////////////////////////////////////////
// Memory Save States (Rewind and Runahead)
//////////////////////////////////////////////////////////////////////////
@ -240,8 +429,76 @@ void CalculateRewindMemoryUsage(u32 num_saves, u64* ram_usage, u64* vram_usage);
void ClearMemorySaveStates();
void UpdateMemorySaveStateSettings();
bool LoadRewindState(u32 skip_saves = 0, bool consume_state = true);
bool IsRewinding();
void SetRewinding(bool enabled);
void SetRunaheadReplayFlag();
} // namespace System
namespace Host {
/// Called with the settings lock held, when system settings are being loaded (should load input sources, etc).
void LoadSettings(SettingsInterface& si, std::unique_lock<std::mutex>& lock);
/// Called after settings are updated.
void CheckForSettingsChanges(const Settings& old_settings);
/// Called when the VM is starting initialization, but has not been completed yet.
void OnSystemStarting();
/// Called when the VM is created.
void OnSystemStarted();
/// Called when the VM is shut down or destroyed.
void OnSystemDestroyed();
/// Called when the VM is paused.
void OnSystemPaused();
/// Called when the VM is resumed after being paused.
void OnSystemResumed();
/// Called when performance metrics are updated, approximately once a second.
void OnPerformanceMetricsUpdated();
/// Called when a save state is loading, before the file is processed.
// void OnSaveStateLoading(const std::string_view& filename);
/// Called after a save state is successfully loaded. If the save state was invalid, was_successful will be false.
// void OnSaveStateLoaded(const std::string_view& filename, bool was_successful);
/// Called when a save state is being created/saved. The compression/write to disk is asynchronous, so this callback
/// just signifies that the save has started, not necessarily completed.
// void OnSaveStateSaved(const std::string_view& filename);
/// Provided by the host; called when the running executable changes.
void OnGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name);
/// Provided by the host; called once per frame at guest vsync.
void PumpMessagesOnCPUThread();
/// Provided by the host; called when a state is saved, and the frontend should invalidate its save state cache.
// void InvalidateSaveStateCache();
/// Requests a specific display window size.
// void RequestResizeHostDisplay(s32 width, s32 height);
/// Safely executes a function on the VM thread.
// void RunOnCPUThread(std::function<void()> function, bool block = false);
/// Asynchronously starts refreshing the game list.
// void RefreshGameListAsync(bool invalidate_cache);
/// Cancels game list refresh, if there is one in progress.
// void CancelGameListRefresh();
/// Requests shut down and exit of the hosting application. This may not actually exit,
/// if the user cancels the shutdown confirmation.
// void RequestExit(bool save_state_if_running);
/// Requests shut down of the current virtual machine.
// void RequestVMShutdown(bool save_state);
/// Returns true if the hosting application is currently fullscreen.
// bool IsFullscreen();
/// Alters fullscreen state of hosting application.
// void SetFullscreen(bool enabled);
} // namespace Host

View File

@ -155,17 +155,17 @@ static void addMSAATweakOption(SettingsDialog* dialog, QTableWidget* table, cons
QComboBox* msaa = new QComboBox(table);
QtUtils::FillComboBoxWithMSAAModes(msaa);
const QVariant current_msaa_mode(QtUtils::GetMSAAModeValue(
static_cast<uint>(QtHostInterface::GetInstance()->GetIntSettingValue("GPU", "Multisamples", 1)),
QtHostInterface::GetInstance()->GetBoolSettingValue("GPU", "PerSampleShading", false)));
static_cast<uint>(dialog->getEffectiveIntValue("GPU", "Multisamples", 1)),
dialog->getEffectiveBoolValue("GPU", "PerSampleShading", false)));
const int current_msaa_index = msaa->findData(current_msaa_mode);
if (current_msaa_index >= 0)
msaa->setCurrentIndex(current_msaa_index);
msaa->connect(msaa, QOverload<int>::of(&QComboBox::currentIndexChanged), [msaa](int index) {
msaa->connect(msaa, QOverload<int>::of(&QComboBox::currentIndexChanged), [dialog, msaa](int index) {
uint multisamples;
bool ssaa;
QtUtils::DecodeMSAAModeValue(msaa->itemData(index), &multisamples, &ssaa);
QtHostInterface::GetInstance()->SetIntSettingValue("GPU", "Multisamples", static_cast<int>(multisamples));
QtHostInterface::GetInstance()->SetBoolSettingValue("GPU", "PerSampleShading", ssaa);
dialog->setIntSettingValue("GPU", "Multisamples", static_cast<int>(multisamples));
dialog->setBoolSettingValue("GPU", "PerSampleShading", ssaa);
QtHostInterface::GetInstance()->applySettings(false);
});

View File

@ -1,11 +1,11 @@
#include "audiosettingswidget.h"
#include "core/spu.h"
#include "settingsdialog.h"
#include "settingwidgetbinder.h"
#include "util/audio_stream.h"
#include <cmath>
AudioSettingsWidget::AudioSettingsWidget(SettingsDialog* dialog, QWidget* parent)
: QWidget(parent), m_dialog(dialog)
AudioSettingsWidget::AudioSettingsWidget(SettingsDialog* dialog, QWidget* parent) : QWidget(parent), m_dialog(dialog)
{
SettingsInterface* sif = dialog->getSettingsInterface();
@ -17,11 +17,11 @@ AudioSettingsWidget::AudioSettingsWidget(SettingsDialog* dialog, QWidget* parent
qApp->translate("AudioBackend", Settings::GetAudioBackendDisplayName(static_cast<AudioBackend>(i))));
}
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.audioBackend, "Audio", "Backend",
&Settings::ParseAudioBackend, &Settings::GetAudioBackendName,
Settings::DEFAULT_AUDIO_BACKEND);
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.audioBackend, "Audio", "Backend", &Settings::ParseAudioBackend,
&Settings::GetAudioBackendName, Settings::DEFAULT_AUDIO_BACKEND);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.syncToOutput, "Audio", "Sync", true);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.bufferSize, "Audio", "BufferSize", HostInterface::DEFAULT_AUDIO_BUFFER_SIZE);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.bufferSize, "Audio", "BufferSize",
Settings::DEFAULT_AUDIO_BUFFER_SIZE);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.startDumpingOnBoot, "Audio", "DumpOnBoot", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.muteCDAudio, "CDROM", "MuteCDAudio", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.resampling, "Audio", "Resampling", true);
@ -84,7 +84,7 @@ void AudioSettingsWidget::updateBufferingLabel()
return;
}
const float max_latency = AudioStream::GetMaxLatency(HostInterface::AUDIO_SAMPLE_RATE, actual_buffer_size);
const float max_latency = AudioStream::GetMaxLatency(SPU::SAMPLE_RATE, actual_buffer_size);
m_ui.bufferingLabel->setText(tr("Maximum Latency: %n frames (%1ms)", "", actual_buffer_size)
.arg(static_cast<double>(max_latency) * 1000.0, 0, 'f', 2));
}

View File

@ -418,7 +418,7 @@ void AutoUpdaterDialog::downloadUpdateClicked()
bool AutoUpdaterDialog::updateNeeded() const
{
QString last_checked_sha =
QString::fromStdString(m_host_interface->GetStringSettingValue("AutoUpdater", "LastVersion"));
QString::fromStdString(Host::GetBaseStringSettingValue("AutoUpdater", "LastVersion"));
Log_InfoPrintf("Current SHA: %s", g_scm_hash_str);
Log_InfoPrintf("Latest SHA: %s", m_latest_sha.toUtf8().constData());
@ -435,7 +435,7 @@ bool AutoUpdaterDialog::updateNeeded() const
void AutoUpdaterDialog::skipThisUpdateClicked()
{
m_host_interface->SetStringSettingValue("AutoUpdater", "LastVersion", m_latest_sha.toUtf8().constData());
Host::SetBaseStringSettingValue("AutoUpdater", "LastVersion", m_latest_sha.toUtf8().constData());
done(0);
}

View File

@ -4,6 +4,7 @@
#include "common/string_util.h"
#include "core/bus.h"
#include "core/cpu_core.h"
#include "core/host.h"
#include "core/system.h"
#include "qthostinterface.h"
#include "qtutils.h"
@ -45,26 +46,33 @@ static QString formatHexAndDecValue(u32 value, u8 size, bool is_signed)
return QStringLiteral("0x%1 (%2)").arg(static_cast<u32>(value), size, 16, QChar('0')).arg(static_cast<uint>(value));
}
static QString formatCheatCode(u32 address, u32 value, const MemoryAccessSize size)
{
if (size == MemoryAccessSize::Byte && address <= 0x00200000)
return QStringLiteral("CHEAT CODE: %1 %2")
.arg(static_cast<u32>(address) + 0x30000000, 8, 16, QChar('0')).toUpper()
.arg(static_cast<u16>(value), 4, 16, QChar('0')).toUpper();
else if (size == MemoryAccessSize::HalfWord && address <= 0x001FFFFE)
return QStringLiteral("CHEAT CODE: %1 %2")
.arg(static_cast<u32>(address) + 0x80000000, 8, 16, QChar('0')).toUpper()
.arg(static_cast<u16>(value), 4, 16, QChar('0')).toUpper();
else if (size == MemoryAccessSize::Word && address <= 0x001FFFFC)
return QStringLiteral("CHEAT CODE: %1 %2")
.arg(static_cast<u32>(address) + 0x90000000, 8, 16, QChar('0')).toUpper()
.arg(static_cast<u32>(value), 8, 16, QChar('0')).toUpper();
else
return QStringLiteral("OUTSIDE RAM RANGE. POKE %1 with %2")
.arg(static_cast<u32>(address), 8, 16, QChar('0')).toUpper()
.arg(static_cast<u16>(value), 8, 16, QChar('0')).toUpper();
if (size == MemoryAccessSize::Byte && address <= 0x00200000)
return QStringLiteral("CHEAT CODE: %1 %2")
.arg(static_cast<u32>(address) + 0x30000000, 8, 16, QChar('0'))
.toUpper()
.arg(static_cast<u16>(value), 4, 16, QChar('0'))
.toUpper();
else if (size == MemoryAccessSize::HalfWord && address <= 0x001FFFFE)
return QStringLiteral("CHEAT CODE: %1 %2")
.arg(static_cast<u32>(address) + 0x80000000, 8, 16, QChar('0'))
.toUpper()
.arg(static_cast<u16>(value), 4, 16, QChar('0'))
.toUpper();
else if (size == MemoryAccessSize::Word && address <= 0x001FFFFC)
return QStringLiteral("CHEAT CODE: %1 %2")
.arg(static_cast<u32>(address) + 0x90000000, 8, 16, QChar('0'))
.toUpper()
.arg(static_cast<u32>(value), 8, 16, QChar('0'))
.toUpper();
else
return QStringLiteral("OUTSIDE RAM RANGE. POKE %1 with %2")
.arg(static_cast<u32>(address), 8, 16, QChar('0'))
.toUpper()
.arg(static_cast<u16>(value), 8, 16, QChar('0'))
.toUpper();
}
static QString formatValue(u32 value, bool is_signed)
@ -180,7 +188,8 @@ void CheatManagerDialog::connectUi()
connect(m_ui.scanTable, &QTableWidget::itemChanged, this, &CheatManagerDialog::scanItemChanged);
connect(m_ui.watchTable, &QTableWidget::itemChanged, this, &CheatManagerDialog::watchItemChanged);
connect(QtHostInterface::GetInstance(), &QtHostInterface::cheatEnabled, this, &CheatManagerDialog::setCheatCheckState);
connect(QtHostInterface::GetInstance(), &QtHostInterface::cheatEnabled, this,
&CheatManagerDialog::setCheatCheckState);
}
void CheatManagerDialog::showEvent(QShowEvent* event)
@ -332,12 +341,12 @@ CheatList* CheatManagerDialog::getCheatList() const
CheatList* list = System::GetCheatList();
if (!list)
{
QtHostInterface::GetInstance()->LoadCheatListFromGameTitle();
System::LoadCheatListFromGameTitle();
list = System::GetCheatList();
}
if (!list)
{
QtHostInterface::GetInstance()->LoadCheatListFromDatabase();
System::LoadCheatListFromDatabase();
list = System::GetCheatList();
}
if (!list)
@ -408,7 +417,7 @@ void CheatManagerDialog::fillItemForCheatCode(QTreeWidgetItem* item, u32 index,
void CheatManagerDialog::saveCheatList()
{
QtHostInterface::GetInstance()->executeOnEmulationThread([]() { QtHostInterface::GetInstance()->SaveCheatList(); });
QtHostInterface::GetInstance()->executeOnEmulationThread([]() { System::SaveCheatList(); });
}
void CheatManagerDialog::cheatListCurrentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous)
@ -472,7 +481,7 @@ void CheatManagerDialog::cheatListItemChanged(QTreeWidgetItem* item, int column)
QtHostInterface::GetInstance()->executeOnEmulationThread([index, new_enabled]() {
System::GetCheatList()->SetCodeEnabled(static_cast<u32>(index), new_enabled);
QtHostInterface::GetInstance()->SaveCheatList();
System::SaveCheatList();
});
}
@ -494,7 +503,7 @@ void CheatManagerDialog::activateCheat(u32 index)
QtHostInterface::GetInstance()->executeOnEmulationThread([index, new_enabled]() {
System::GetCheatList()->SetCodeEnabled(index, new_enabled);
QtHostInterface::GetInstance()->SaveCheatList();
System::SaveCheatList();
});
}
@ -545,7 +554,7 @@ void CheatManagerDialog::addCodeClicked()
QtHostInterface::GetInstance()->executeOnEmulationThread(
[this, &new_code]() {
System::GetCheatList()->AddCode(std::move(new_code));
QtHostInterface::GetInstance()->SaveCheatList();
System::SaveCheatList();
},
true);
}
@ -591,7 +600,7 @@ void CheatManagerDialog::editCodeClicked()
QtHostInterface::GetInstance()->executeOnEmulationThread(
[index, &new_code]() {
System::GetCheatList()->SetCode(static_cast<u32>(index), std::move(new_code));
QtHostInterface::GetInstance()->SaveCheatList();
System::SaveCheatList();
},
true);
}
@ -617,7 +626,7 @@ void CheatManagerDialog::deleteCodeClicked()
QtHostInterface::GetInstance()->executeOnEmulationThread(
[index]() {
System::GetCheatList()->RemoveCode(static_cast<u32>(index));
QtHostInterface::GetInstance()->SaveCheatList();
System::SaveCheatList();
},
true);
updateCheatList();
@ -658,7 +667,7 @@ void CheatManagerDialog::importFromFileTriggered()
[&new_cheats]() {
DebugAssert(System::HasCheatList());
System::GetCheatList()->MergeList(new_cheats);
QtHostInterface::GetInstance()->SaveCheatList();
System::SaveCheatList();
},
true);
updateCheatList();
@ -681,7 +690,7 @@ void CheatManagerDialog::importFromTextTriggered()
[&new_cheats]() {
DebugAssert(System::HasCheatList());
System::GetCheatList()->MergeList(new_cheats);
QtHostInterface::GetInstance()->SaveCheatList();
System::SaveCheatList();
},
true);
updateCheatList();
@ -707,8 +716,7 @@ void CheatManagerDialog::clearClicked()
return;
}
QtHostInterface::GetInstance()->executeOnEmulationThread([] { QtHostInterface::GetInstance()->ClearCheatList(true); },
true);
QtHostInterface::GetInstance()->executeOnEmulationThread([] { System::ClearCheatList(true); }, true);
updateCheatList();
}
@ -723,8 +731,7 @@ void CheatManagerDialog::resetClicked()
return;
}
QtHostInterface::GetInstance()->executeOnEmulationThread([] { QtHostInterface::GetInstance()->DeleteCheatList(); },
true);
QtHostInterface::GetInstance()->executeOnEmulationThread([] { System::DeleteCheatList(); }, true);
updateCheatList();
}
@ -737,11 +744,11 @@ void CheatManagerDialog::addToWatchClicked()
for (int index = indexFirst; index <= indexLast; index++)
{
const MemoryScan::Result& res = m_scanner.GetResults()[static_cast<u32>(index)];
m_watch.AddEntry(StringUtil::StdStringFromFormat("0x%08x", res.address), res.address, m_scanner.GetSize(), m_scanner.GetValueSigned(), false);
updateWatch();
}
const MemoryScan::Result& res = m_scanner.GetResults()[static_cast<u32>(index)];
m_watch.AddEntry(StringUtil::StdStringFromFormat("0x%08x", res.address), res.address, m_scanner.GetSize(),
m_scanner.GetValueSigned(), false);
updateWatch();
}
}
void CheatManagerDialog::addManualWatchAddressClicked()
@ -779,9 +786,9 @@ void CheatManagerDialog::removeWatchClicked()
for (int index = indexLast; index >= indexFirst; index--)
{
m_watch.RemoveEntry(static_cast<u32>(index));
updateWatch();
}
m_watch.RemoveEntry(static_cast<u32>(index));
updateWatch();
}
}
void CheatManagerDialog::scanCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous)
@ -856,9 +863,9 @@ void CheatManagerDialog::watchItemChanged(QTableWidgetItem* item)
{
uint value;
if (item->text()[1] == 'x' || item->text()[1] == 'X')
value = item->text().toUInt(&value_ok, 16);
value = item->text().toUInt(&value_ok, 16);
else
value = item->text().toUInt(&value_ok);
value = item->text().toUInt(&value_ok);
if (value_ok)
m_watch.SetEntryValue(index, static_cast<u32>(value));
}
@ -930,7 +937,6 @@ void CheatManagerDialog::updateResults()
row++;
}
m_ui.scanResultsCount->setText(QString::number(m_scanner.GetResultCount()));
}
else
m_ui.scanResultsCount->setText("0");
@ -1003,12 +1009,12 @@ void CheatManagerDialog::updateWatch()
value_item = new QTableWidgetItem(formatHexAndDecValue(res.value, 8, res.is_signed));
m_ui.watchTable->setItem(row, 3, value_item);
QTableWidgetItem* freeze_item = new QTableWidgetItem();
freeze_item->setFlags(freeze_item->flags() | (Qt::ItemIsEditable | Qt::ItemIsUserCheckable));
freeze_item->setCheckState(res.freeze ? Qt::Checked : Qt::Unchecked);
m_ui.watchTable->setItem(row, 4, freeze_item);
row++;
}
}

View File

@ -140,7 +140,7 @@ void ConsoleSettingsWidget::onEnableCPUClockSpeedControlChecked(int state)
return;
}
QtHost::SetBaseBoolSettingValue("UI", "CPUOverclockingWarningShown", true);
Host::SetBaseBoolSettingValue("UI", "CPUOverclockingWarningShown", true);
}
m_ui.cpuClockSpeed->setEnabled(state == Qt::Checked);

View File

@ -624,13 +624,6 @@
</layout>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QGroupBox" name="groupBox_34">
<property name="title">
<string>UNUSED</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QGroupBox" name="groupBox_24">
<property name="title">
@ -1108,7 +1101,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="../resources/resources.qrc">:/images/dualshock-2.png</pixmap>
<pixmap resource="resources/resources.qrc">:/controllers/analog_controller.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
@ -1316,6 +1309,7 @@
</customwidget>
</customwidgets>
<resources>
<include location="resources/resources.qrc"/>
<include location="../resources/resources.qrc"/>
</resources>
<connections/>

View File

@ -0,0 +1,737 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ControllerBindingWidget_DigitalController</class>
<widget class="QWidget" name="ControllerBindingWidget_DigitalController">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1100</width>
<height>500</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>1100</width>
<height>500</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="1">
<layout class="QGridLayout" name="gridLayout_27">
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_22">
<property name="title">
<string>L1</string>
</property>
<layout class="QGridLayout" name="gridLayout_22">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="L1">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_21">
<property name="title">
<string>L2</string>
</property>
<layout class="QGridLayout" name="gridLayout_21">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="L2">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="groupBox_23">
<property name="title">
<string>R2</string>
</property>
<layout class="QGridLayout" name="gridLayout_23">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="R2">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="1">
<widget class="QGroupBox" name="groupBox_24">
<property name="title">
<string>R1</string>
</property>
<layout class="QGridLayout" name="gridLayout_24">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="R1">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item row="0" column="2" rowspan="4">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="groupBox_16">
<property name="title">
<string>Face Buttons</string>
</property>
<layout class="QGridLayout" name="gridLayout_16">
<item row="3" column="1" colspan="2">
<widget class="QGroupBox" name="groupBox_17">
<property name="title">
<string>Cross</string>
</property>
<layout class="QGridLayout" name="gridLayout_17">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="Cross">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_18">
<property name="title">
<string>Square</string>
</property>
<layout class="QGridLayout" name="gridLayout_18">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="Square">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QGroupBox" name="groupBox_19">
<property name="title">
<string>Triangle</string>
</property>
<layout class="QGridLayout" name="gridLayout_19">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="Triangle">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="QGroupBox" name="groupBox_20">
<property name="title">
<string>Circle</string>
</property>
<layout class="QGridLayout" name="gridLayout_20">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="Circle">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>400</width>
<height>266</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="resources/resources.qrc">:/controllers/digital_controller.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="3" column="1">
<layout class="QGridLayout" name="gridLayout_32">
<item row="1" column="0" colspan="4">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="0" column="0" rowspan="4">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>D-Pad</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="3" column="1" colspan="2">
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
<string>Down</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="Down">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Left</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="Left">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Up</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="Up">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Right</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="Right">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="2" column="1">
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="1">
<widget class="QGroupBox" name="groupBox_25">
<property name="title">
<string>Select</string>
</property>
<layout class="QGridLayout" name="gridLayout_25">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="Select">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="2">
<widget class="QGroupBox" name="groupBox_26">
<property name="title">
<string>Start</string>
</property>
<layout class="QGridLayout" name="gridLayout_26">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="Start">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>InputBindingWidget</class>
<extends>QPushButton</extends>
<header>inputbindingwidgets.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="resources/resources.qrc"/>
<include location="resources/resources.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -23,10 +23,6 @@ ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSett
populateControllerTypes();
onTypeChanged();
ControllerSettingWidgetBinder::BindWidgetToInputProfileString(m_dialog->getProfileSettingsInterface(),
m_ui.controllerType, m_config_section, "Type",
Controller::GetDefaultPadType(port));
connect(m_ui.controllerType, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&ControllerBindingWidget::onTypeChanged);
connect(m_ui.automaticBinding, &QPushButton::clicked, this, &ControllerBindingWidget::doAutomaticBinding);
@ -51,30 +47,32 @@ void ControllerBindingWidget::populateControllerTypes()
m_ui.controllerType->addItem(qApp->translate("ControllerType", cinfo->display_name), QVariant(static_cast<int>(i)));
}
}
void ControllerBindingWidget::onTypeChanged()
{
const bool is_initializing = (m_current_widget == nullptr);
const std::string controller_type_name(
m_dialog->getStringValue(m_config_section.c_str(), "Type", Controller::GetDefaultPadType(m_port_number)));
m_controller_type = Settings::ParseControllerTypeName(controller_type_name.c_str()).value_or(ControllerType::None);
if (!is_initializing)
{
m_ui.verticalLayout->removeWidget(m_current_widget);
delete m_current_widget;
m_current_widget = nullptr;
}
const int index = m_ui.controllerType->findData(QVariant(static_cast<int>(m_controller_type)));
if (index >= 0 && index != m_ui.controllerType->currentIndex())
{
QSignalBlocker sb(m_ui.controllerType);
m_ui.controllerType->setCurrentIndex(index);
}
}
if (m_controller_type == ControllerType::AnalogController)
void ControllerBindingWidget::populateBindingWidget()
{
const bool is_initializing = (m_current_widget == nullptr);
if (!is_initializing)
{
m_ui.verticalLayout->removeWidget(m_current_widget);
delete m_current_widget;
m_current_widget = nullptr;
}
if (m_controller_type == ControllerType::DigitalController)
m_current_widget = ControllerBindingWidget_DigitalController::createInstance(this);
else if (m_controller_type == ControllerType::AnalogController)
m_current_widget = ControllerBindingWidget_AnalogController::createInstance(this);
else
m_current_widget = new ControllerBindingWidget_Base(this);
@ -86,6 +84,27 @@ void ControllerBindingWidget::onTypeChanged()
m_dialog->updateListDescription(m_port_number, this);
}
void ControllerBindingWidget::onTypeChanged()
{
bool ok;
const int index = m_ui.controllerType->currentData().toInt(&ok);
if (!ok || index < 0 || index >= static_cast<int>(ControllerType::Count))
return;
m_controller_type = static_cast<ControllerType>(index);
SettingsInterface* sif = m_dialog->getProfileSettingsInterface();
if (sif)
sif->SetStringValue(m_config_section.c_str(), "Type", Settings::GetControllerTypeName(m_controller_type));
else
Host::SetBaseStringSettingValue(m_config_section.c_str(), "Type", Settings::GetControllerTypeName(m_controller_type));
// TODO: reloadInputProfile() ?
QtHostInterface::GetInstance()->applySettings();
populateBindingWidget();
}
void ControllerBindingWidget::doAutomaticBinding()
{
QMenu menu(this);
@ -271,6 +290,29 @@ void ControllerBindingWidget_Base::initBindingWidgets()
Controller::DEFAULT_MOTOR_SCALE);
}
//////////////////////////////////////////////////////////////////////////
ControllerBindingWidget_DigitalController::ControllerBindingWidget_DigitalController(ControllerBindingWidget* parent)
: ControllerBindingWidget_Base(parent)
{
m_ui.setupUi(this);
initBindingWidgets();
}
ControllerBindingWidget_DigitalController::~ControllerBindingWidget_DigitalController() {}
QIcon ControllerBindingWidget_DigitalController::getIcon() const
{
return QIcon::fromTheme("gamepad-line");
}
ControllerBindingWidget_Base* ControllerBindingWidget_DigitalController::createInstance(ControllerBindingWidget* parent)
{
return new ControllerBindingWidget_DigitalController(parent);
}
//////////////////////////////////////////////////////////////////////////
ControllerBindingWidget_AnalogController::ControllerBindingWidget_AnalogController(ControllerBindingWidget* parent)
: ControllerBindingWidget_Base(parent)
{

View File

@ -5,6 +5,7 @@
#include "ui_controllerbindingwidget.h"
#include "ui_controllerbindingwidget_analog_controller.h"
#include "ui_controllerbindingwidget_digital_controller.h"
class InputBindingWidget;
class ControllerSettingsDialog;
@ -32,6 +33,7 @@ private Q_SLOTS:
private:
void populateControllerTypes();
void populateBindingWidget();
void doDeviceAutomaticBinding(const QString& device);
void saveAndRefresh();
@ -74,6 +76,22 @@ protected:
void initBindingWidgets();
};
class ControllerBindingWidget_DigitalController final : public ControllerBindingWidget_Base
{
Q_OBJECT
public:
ControllerBindingWidget_DigitalController(ControllerBindingWidget* parent);
~ControllerBindingWidget_DigitalController();
QIcon getIcon() const override;
static ControllerBindingWidget_Base* createInstance(ControllerBindingWidget* parent);
private:
Ui::ControllerBindingWidget_DigitalController m_ui;
};
class ControllerBindingWidget_AnalogController final : public ControllerBindingWidget_Base
{
Q_OBJECT

View File

@ -5,7 +5,7 @@
#include "controllerglobalsettingswidget.h"
#include "core/controller.h"
#include "core/host_settings.h"
#include "frontend-common/ini_settings_interface.h"
#include "util/ini_settings_interface.h"
#include "frontend-common/input_manager.h"
#include "hotkeysettingswidget.h"
#include "qthostinterface.h"
@ -37,16 +37,18 @@ ControllerSettingsDialog::ControllerSettingsDialog(QWidget* parent /* = nullptr
connect(m_ui.deleteProfile, &QPushButton::clicked, this, &ControllerSettingsDialog::onDeleteProfileClicked);
connect(m_ui.restoreDefaults, &QPushButton::clicked, this, &ControllerSettingsDialog::onRestoreDefaultsClicked);
// connect(g_emu_thread, &EmuThread::onInputDevicesEnumerated, this,
// &ControllerSettingsDialog::onInputDevicesEnumerated); connect(g_emu_thread, &EmuThread::onInputDeviceConnected,
// this, &ControllerSettingsDialog::onInputDeviceConnected); connect(g_emu_thread,
// &EmuThread::onInputDeviceDisconnected, this, &ControllerSettingsDialog::onInputDeviceDisconnected);
// connect(g_emu_thread, &EmuThread::onVibrationMotorsEnumerated, this,
// &ControllerSettingsDialog::onVibrationMotorsEnumerated);
connect(QtHostInterface::GetInstance(), &QtHostInterface::onInputDevicesEnumerated, this,
&ControllerSettingsDialog::onInputDevicesEnumerated);
connect(QtHostInterface::GetInstance(), &QtHostInterface::onInputDeviceConnected, this,
&ControllerSettingsDialog::onInputDeviceConnected);
connect(QtHostInterface::GetInstance(), &QtHostInterface::onInputDeviceDisconnected, this,
&ControllerSettingsDialog::onInputDeviceDisconnected);
connect(QtHostInterface::GetInstance(), &QtHostInterface::onVibrationMotorsEnumerated, this,
&ControllerSettingsDialog::onVibrationMotorsEnumerated);
// trigger a device enumeration to populate the device list
// g_emu_thread->enumerateInputDevices();
// g_emu_thread->enumerateVibrationMotors();
QtHostInterface::GetInstance()->enumerateInputDevices();
QtHostInterface::GetInstance()->enumerateVibrationMotors();
}
ControllerSettingsDialog::~ControllerSettingsDialog() = default;
@ -212,9 +214,7 @@ void ControllerSettingsDialog::onInputDeviceConnected(const QString& identifier,
{
m_device_list.emplace_back(identifier, device_name);
m_global_settings->addDeviceToList(identifier, device_name);
#if 0
g_emu_thread->enumerateVibrationMotors();
#endif
QtHostInterface::GetInstance()->enumerateVibrationMotors();
}
void ControllerSettingsDialog::onInputDeviceDisconnected(const QString& identifier)
@ -229,9 +229,7 @@ void ControllerSettingsDialog::onInputDeviceDisconnected(const QString& identifi
}
m_global_settings->removeDeviceFromList(identifier);
#if 0
g_emu_thread->enumerateVibrationMotors();
#endif
QtHostInterface::GetInstance()->enumerateVibrationMotors();
}
void ControllerSettingsDialog::onVibrationMotorsEnumerated(const QList<InputBindingKey>& motors)
@ -276,7 +274,7 @@ void ControllerSettingsDialog::setBoolValue(const char* section, const char* key
}
else
{
QtHost::SetBaseBoolSettingValue(section, key, value);
Host::SetBaseBoolSettingValue(section, key, value);
QtHostInterface::GetInstance()->applySettings();
}
}
@ -291,7 +289,7 @@ void ControllerSettingsDialog::setStringValue(const char* section, const char* k
}
else
{
QtHost::SetBaseStringSettingValue(key, section, value);
Host::SetBaseStringSettingValue(key, section, value);
QtHostInterface::GetInstance()->applySettings();
}
}
@ -306,7 +304,7 @@ void ControllerSettingsDialog::clearSettingValue(const char* section, const char
}
else
{
QtHost::RemoveBaseSettingValue(section, key);
Host::DeleteBaseSettingValue(section, key);
QtHostInterface::GetInstance()->applySettings();
}
}
@ -395,11 +393,11 @@ void ControllerSettingsDialog::updateListDescription(u32 global_slot, Controller
for (int i = 0; i < m_ui.settingsCategory->count(); i++)
{
QListWidgetItem* item = m_ui.settingsCategory->item(i);
const QVariant data(item->data(Qt::UserRole));
const QVariant item_data(item->data(Qt::UserRole));
bool is_ok;
if (data.toUInt(&is_ok) == global_slot && is_ok)
if (item_data.toUInt(&is_ok) == global_slot && is_ok)
{
const bool is_mtap_port = Controller::PadIsMultitapSlot(global_slot);
//const bool is_mtap_port = Controller::PadIsMultitapSlot(global_slot);
const auto [port, slot] = Controller::ConvertPadToPortAndSlot(global_slot);
const bool mtap_enabled = getBoolValue("Pad", (port == 0) ? "MultitapPort1" : "MultitapPort2", false);

View File

@ -45,7 +45,7 @@ static void BindWidgetToInputProfileBool(SettingsInterface* sif, WidgetType* wid
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const bool new_value = Accessor::getBoolValue(widget);
QtHost::SetBaseBoolSettingValue(section.c_str(), key.c_str(), new_value);
Host::SetBaseBoolSettingValue(section.c_str(), key.c_str(), new_value);
QtHostInterface::GetInstance()->applySettings();
});
}
@ -77,7 +77,7 @@ static void BindWidgetToInputProfileFloat(SettingsInterface* sif, WidgetType* wi
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const float new_value = Accessor::getFloatValue(widget);
QtHost::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value);
Host::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value);
QtHostInterface::GetInstance()->applySettings();
});
}
@ -109,7 +109,7 @@ static void BindWidgetToInputProfileNormalized(SettingsInterface* sif, WidgetTyp
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), range]() {
const float new_value = (static_cast<float>(Accessor::getIntValue(widget)) / range);
QtHost::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value);
Host::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value);
QtHostInterface::GetInstance()->applySettings();
});
}
@ -150,9 +150,9 @@ static void BindWidgetToInputProfileString(SettingsInterface* sif, WidgetType* w
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const QString new_value = Accessor::getStringValue(widget);
if (!new_value.isEmpty())
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), new_value.toUtf8().constData());
Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), new_value.toUtf8().constData());
else
QtHost::RemoveBaseSettingValue(section.c_str(), key.c_str());
Host::DeleteBaseSettingValue(section.c_str(), key.c_str());
QtHostInterface::GetInstance()->applySettings();
});

View File

@ -170,6 +170,9 @@
<QtUi Include="controllerbindingwidget_analog_controller.ui">
<FileType>Document</FileType>
</QtUi>
<QtUi Include="controllerbindingwidget_digital_controller.ui">
<FileType>Document</FileType>
</QtUi>
<QtUi Include="controllerglobalsettingswidget.ui">
<FileType>Document</FileType>
</QtUi>

View File

@ -144,11 +144,11 @@ void GameListSearchDirectoriesModel::openEntryInExplorer(QWidget* parent, int ro
void GameListSearchDirectoriesModel::loadFromSettings()
{
std::vector<std::string> path_list = m_host_interface->GetSettingStringList("GameList", "Paths");
std::vector<std::string> path_list = Host::GetBaseStringListSetting("GameList", "Paths");
for (std::string& entry : path_list)
m_entries.push_back({QString::fromStdString(entry), false});
path_list = m_host_interface->GetSettingStringList("GameList", "RecursivePaths");
path_list = Host::GetBaseStringListSetting("GameList", "RecursivePaths");
for (std::string& entry : path_list)
m_entries.push_back({QString::fromStdString(entry), true});
}
@ -167,12 +167,12 @@ void GameListSearchDirectoriesModel::saveToSettings()
}
if (paths.empty())
m_host_interface->RemoveSettingValue("GameList", "Paths");
Host::DeleteBaseSettingValue("GameList", "Paths");
else
m_host_interface->SetStringListSettingValue("GameList", "Paths", paths);
Host::SetBaseStringListSettingValue("GameList", "Paths", paths);
if (recursive_paths.empty())
m_host_interface->RemoveSettingValue("GameList", "RecursivePaths");
Host::DeleteBaseSettingValue("GameList", "RecursivePaths");
else
m_host_interface->SetStringListSettingValue("GameList", "RecursivePaths", recursive_paths);
Host::SetBaseStringListSettingValue("GameList", "RecursivePaths", recursive_paths);
}

View File

@ -52,7 +52,7 @@ GameListSettingsWidget::~GameListSettingsWidget() = default;
bool GameListSettingsWidget::addExcludedPath(const std::string& path)
{
if (!QtHostInterface::GetInstance()->AddValueToStringList("GameList", "ExcludedPaths", path.c_str()))
if (!Host::AddValueToBaseStringListSetting("GameList", "ExcludedPaths", path.c_str()))
return false;
m_ui.excludedPaths->addItem(QString::fromStdString(path));
@ -64,7 +64,7 @@ void GameListSettingsWidget::refreshExclusionList()
{
m_ui.excludedPaths->clear();
const std::vector<std::string> paths(QtHostInterface::GetInstance()->GetSettingStringList("GameList", "ExcludedPaths"));
const std::vector<std::string> paths(Host::GetBaseStringListSetting("GameList", "ExcludedPaths"));
for (const std::string& path : paths)
m_ui.excludedPaths->addItem(QString::fromStdString(path));
}
@ -158,7 +158,7 @@ void GameListSettingsWidget::onRemoveExcludedPathButtonClicked()
if (!item)
return;
QtHostInterface::GetInstance()->RemoveValueFromStringList("GameList", "ExcludedPaths", item->text().toUtf8().constData());
Host::RemoveValueFromBaseStringListSetting("GameList", "ExcludedPaths", item->text().toUtf8().constData());
delete item;
QtHostInterface::GetInstance()->refreshGameList();

View File

@ -1,5 +1,6 @@
#include "gamelistwidget.h"
#include "common/string_util.h"
#include "core/host_settings.h"
#include "core/settings.h"
#include "frontend-common/game_list.h"
#include "gamelistmodel.h"
@ -43,8 +44,8 @@ void GameListWidget::initialize(QtHostInterface* host_interface)
connect(m_host_interface, &QtHostInterface::gameListRefreshed, this, &GameListWidget::onGameListRefreshed);
m_model = new GameListModel(m_game_list, this);
m_model->setCoverScale(host_interface->GetFloatSettingValue("UI", "GameListCoverArtScale", 0.45f));
m_model->setShowCoverTitles(host_interface->GetBoolSettingValue("UI", "GameListShowCoverTitles", true));
m_model->setCoverScale(Host::GetBaseFloatSettingValue("UI", "GameListCoverArtScale", 0.45f));
m_model->setShowCoverTitles(Host::GetBaseBoolSettingValue("UI", "GameListShowCoverTitles", true));
m_sort_model = new GameListSortModel(m_model);
m_sort_model->setSourceModel(m_model);
@ -98,7 +99,7 @@ void GameListWidget::initialize(QtHostInterface* host_interface)
insertWidget(1, m_list_view);
if (m_host_interface->GetBoolSettingValue("UI", "GameListGridView", false))
if (Host::GetBaseBoolSettingValue("UI", "GameListGridView", false))
setCurrentIndex(1);
else
setCurrentIndex(0);
@ -210,7 +211,7 @@ void GameListWidget::listZoom(float delta)
static constexpr float MAX_SCALE = 2.0f;
const float new_scale = std::clamp(m_model->getCoverScale() + delta, MIN_SCALE, MAX_SCALE);
m_host_interface->SetFloatSettingValue("UI", "GameListCoverArtScale", new_scale);
Host::SetBaseFloatSettingValue("UI", "GameListCoverArtScale", new_scale);
m_model->setCoverScale(new_scale);
updateListFont();
@ -237,7 +238,7 @@ void GameListWidget::showGameList()
if (currentIndex() == 0)
return;
m_host_interface->SetBoolSettingValue("UI", "GameListGridView", false);
Host::SetBaseBoolSettingValue("UI", "GameListGridView", false);
setCurrentIndex(0);
resizeTableViewColumnsToFit();
}
@ -247,7 +248,7 @@ void GameListWidget::showGameGrid()
if (currentIndex() == 1)
return;
m_host_interface->SetBoolSettingValue("UI", "GameListGridView", true);
Host::SetBaseBoolSettingValue("UI", "GameListGridView", true);
setCurrentIndex(1);
}
@ -256,7 +257,7 @@ void GameListWidget::setShowCoverTitles(bool enabled)
if (m_model->getShowCoverTitles() == enabled)
return;
m_host_interface->SetBoolSettingValue("UI", "GameListShowCoverTitles", enabled);
Host::SetBaseBoolSettingValue("UI", "GameListShowCoverTitles", enabled);
m_model->setShowCoverTitles(enabled);
if (isShowingGameGrid())
m_model->refresh();
@ -287,7 +288,7 @@ void GameListWidget::resizeTableViewColumnsToFit()
200, // genre
50, // year
100, // players
80, // size
80, // size
50, // region
100 // compatibility
});
@ -317,8 +318,8 @@ void GameListWidget::loadTableViewColumnVisibilitySettings()
for (int column = 0; column < GameListModel::Column_Count; column++)
{
const bool visible = m_host_interface->GetBoolSettingValue(
"GameListTableView", getColumnVisibilitySettingsKeyName(column), DEFAULT_VISIBILITY[column]);
const bool visible = Host::GetBaseBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column),
DEFAULT_VISIBILITY[column]);
m_table_view->setColumnHidden(column, !visible);
}
}
@ -328,14 +329,14 @@ void GameListWidget::saveTableViewColumnVisibilitySettings()
for (int column = 0; column < GameListModel::Column_Count; column++)
{
const bool visible = !m_table_view->isColumnHidden(column);
m_host_interface->SetBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column), visible);
Host::SetBaseBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column), visible);
}
}
void GameListWidget::saveTableViewColumnVisibilitySettings(int column)
{
const bool visible = !m_table_view->isColumnHidden(column);
m_host_interface->SetBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column), visible);
Host::SetBaseBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column), visible);
}
void GameListWidget::loadTableViewColumnSortSettings()
@ -344,10 +345,10 @@ void GameListWidget::loadTableViewColumnSortSettings()
const bool DEFAULT_SORT_DESCENDING = false;
const GameListModel::Column sort_column =
GameListModel::getColumnIdForName(m_host_interface->GetStringSettingValue("GameListTableView", "SortColumn"))
GameListModel::getColumnIdForName(Host::GetBaseStringSettingValue("GameListTableView", "SortColumn"))
.value_or(DEFAULT_SORT_COLUMN);
const bool sort_descending =
m_host_interface->GetBoolSettingValue("GameListTableView", "SortDescending", DEFAULT_SORT_DESCENDING);
Host::GetBaseBoolSettingValue("GameListTableView", "SortDescending", DEFAULT_SORT_DESCENDING);
m_sort_model->sort(sort_column, sort_descending ? Qt::DescendingOrder : Qt::AscendingOrder);
}
@ -358,11 +359,11 @@ void GameListWidget::saveTableViewColumnSortSettings()
if (sort_column >= 0 && sort_column < GameListModel::Column_Count)
{
m_host_interface->SetStringSettingValue(
"GameListTableView", "SortColumn", GameListModel::getColumnName(static_cast<GameListModel::Column>(sort_column)));
Host::SetBaseStringSettingValue("GameListTableView", "SortColumn",
GameListModel::getColumnName(static_cast<GameListModel::Column>(sort_column)));
}
m_host_interface->SetBoolSettingValue("GameListTableView", "SortDescending", sort_descending);
Host::SetBaseBoolSettingValue("GameListTableView", "SortDescending", sort_descending);
}
const GameListEntry* GameListWidget::getSelectedEntry() const

View File

@ -235,9 +235,9 @@ void InputBindingDialog::saveListToSettings()
else
{
if (!m_bindings.empty())
QtHost::SetBaseStringListSettingValue(m_section_name.c_str(), m_key_name.c_str(), m_bindings);
Host::SetBaseStringListSettingValue(m_section_name.c_str(), m_key_name.c_str(), m_bindings);
else
QtHost::RemoveBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
Host::DeleteBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
QtHostInterface::GetInstance()->reloadInputBindings();
}
}

View File

@ -214,7 +214,7 @@ void InputBindingWidget::setNewBinding()
}
else
{
QtHost::SetBaseStringSettingValue(m_section_name.c_str(), m_key_name.c_str(), new_binding.c_str());
Host::SetBaseStringSettingValue(m_section_name.c_str(), m_key_name.c_str(), new_binding.c_str());
QtHostInterface::GetInstance()->reloadInputBindings();
}
}
@ -234,7 +234,7 @@ void InputBindingWidget::clearBinding()
}
else
{
QtHost::RemoveBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
Host::DeleteBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
QtHostInterface::GetInstance()->reloadInputBindings();
}
reloadBinding();
@ -390,7 +390,7 @@ void InputVibrationBindingWidget::setKey(ControllerSettingsDialog* dialog, std::
void InputVibrationBindingWidget::clearBinding()
{
m_binding = {};
QtHost::RemoveBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
Host::DeleteBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
QtHostInterface::GetInstance()->reloadInputBindings();
setText(QString());
}
@ -427,7 +427,7 @@ void InputVibrationBindingWidget::onClicked()
const QString new_value(input_dialog.textValue());
m_binding = new_value.toStdString();
QtHost::SetBaseStringSettingValue(m_section_name.c_str(), m_key_name.c_str(), m_binding.c_str());
Host::SetBaseStringSettingValue(m_section_name.c_str(), m_key_name.c_str(), m_binding.c_str());
setText(new_value);
}

View File

@ -3,6 +3,7 @@
#include "autoupdaterdialog.h"
#include "cheatmanagerdialog.h"
#include "common/assert.h"
#include "core/host.h"
#include "core/host_display.h"
#include "core/settings.h"
#include "core/system.h"
@ -113,20 +114,15 @@ void MainWindow::initializeAndShow()
#endif
}
void MainWindow::reportError(const QString& message)
void MainWindow::reportError(const QString& title, const QString& message)
{
QMessageBox::critical(this, tr("DuckStation"), message, QMessageBox::Ok);
QMessageBox::critical(this, title, message, QMessageBox::Ok);
focusDisplayWidget();
}
void MainWindow::reportMessage(const QString& message)
bool MainWindow::confirmMessage(const QString& title, const QString& message)
{
m_ui.statusBar->showMessage(message, 2000);
}
bool MainWindow::confirmMessage(const QString& message)
{
const int result = QMessageBox::question(this, tr("DuckStation"), message);
const int result = QMessageBox::question(this, title, message);
focusDisplayWidget();
return (result == QMessageBox::Yes);
@ -134,7 +130,7 @@ bool MainWindow::confirmMessage(const QString& message)
bool MainWindow::shouldHideCursorInFullscreen() const
{
return g_host_interface->GetBoolSettingValue("Main", "HideCursorInFullscreen", true);
return Host::GetBoolSettingValue("Main", "HideCursorInFullscreen", true);
}
QtDisplayWidget* MainWindow::createDisplay(QThread* worker_thread, bool fullscreen, bool render_to_main)
@ -145,11 +141,11 @@ QtDisplayWidget* MainWindow::createDisplay(QThread* worker_thread, bool fullscre
m_host_display = m_host_interface->createHostDisplay();
if (!m_host_display)
{
reportError(tr("Failed to create host display."));
reportError(tr("Error"), tr("Failed to create host display."));
return nullptr;
}
const std::string fullscreen_mode = m_host_interface->GetStringSettingValue("GPU", "FullscreenMode", "");
const std::string fullscreen_mode = Host::GetStringSettingValue("GPU", "FullscreenMode", "");
const bool is_exclusive_fullscreen = (fullscreen && !fullscreen_mode.empty() && m_host_display->SupportsFullscreen());
QWidget* container;
@ -197,7 +193,7 @@ QtDisplayWidget* MainWindow::createDisplay(QThread* worker_thread, bool fullscre
std::optional<WindowInfo> wi = m_display_widget->getWindowInfo();
if (!wi.has_value())
{
reportError(QStringLiteral("Failed to get window info from widget"));
reportError(tr("Error"), QStringLiteral("Failed to get window info from widget"));
destroyDisplayWidget();
m_host_display = nullptr;
return nullptr;
@ -206,7 +202,7 @@ QtDisplayWidget* MainWindow::createDisplay(QThread* worker_thread, bool fullscre
if (!m_host_display->CreateRenderDevice(wi.value(), g_settings.gpu_adapter, g_settings.gpu_use_debug_device,
g_settings.gpu_threaded_presentation))
{
reportError(tr("Failed to create host display device context."));
reportError(tr("Error"), QStringLiteral("Failed to create host display device context."));
destroyDisplayWidget();
m_host_display = nullptr;
return nullptr;
@ -223,7 +219,7 @@ QtDisplayWidget* MainWindow::updateDisplay(QThread* worker_thread, bool fullscre
{
const bool is_fullscreen = m_display_widget->isFullScreen();
const bool is_rendering_to_main = (!is_fullscreen && m_display_widget->parent());
const std::string fullscreen_mode = m_host_interface->GetStringSettingValue("GPU", "FullscreenMode", "");
const std::string fullscreen_mode = Host::GetStringSettingValue("GPU", "FullscreenMode", "");
const bool is_exclusive_fullscreen = (fullscreen && !fullscreen_mode.empty() && m_host_display->SupportsFullscreen());
if (fullscreen == is_fullscreen && is_rendering_to_main == render_to_main)
return m_display_widget;
@ -301,7 +297,7 @@ QtDisplayWidget* MainWindow::updateDisplay(QThread* worker_thread, bool fullscre
std::optional<WindowInfo> wi = m_display_widget->getWindowInfo();
if (!wi.has_value())
{
reportError(QStringLiteral("Failed to get new window info from widget"));
reportError(tr("Error"), QStringLiteral("Failed to get new window info from widget"));
destroyDisplayWidget();
return nullptr;
}
@ -330,13 +326,13 @@ void MainWindow::setDisplayFullscreen(const std::string& fullscreen_mode)
result = m_host_display->SetFullscreen(true, width, height, refresh_rate);
if (result)
{
m_host_interface->AddOSDMessage(
m_host_interface->TranslateStdString("OSDMessage", "Acquired exclusive fullscreen."), 10.0f);
Host::AddOSDMessage(
Host::TranslateStdString("OSDMessage", "Acquired exclusive fullscreen."), 10.0f);
}
else
{
m_host_interface->AddOSDMessage(
m_host_interface->TranslateStdString("OSDMessage", "Failed to acquire exclusive fullscreen."), 10.0f);
Host::AddOSDMessage(
Host::TranslateStdString("OSDMessage", "Failed to acquire exclusive fullscreen."), 10.0f);
}
}
}
@ -431,7 +427,7 @@ void MainWindow::updateMouseMode(bool paused)
void MainWindow::onEmulationStarting()
{
m_emulation_running = true;
updateEmulationActions(true, false, m_host_interface->IsCheevosChallengeModeActive());
updateEmulationActions(true, false, Cheevos::IsChallengeModeActive());
// ensure it gets updated, since the boot can take a while
QGuiApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
@ -439,13 +435,13 @@ void MainWindow::onEmulationStarting()
void MainWindow::onEmulationStarted()
{
updateEmulationActions(false, true, m_host_interface->IsCheevosChallengeModeActive());
updateEmulationActions(false, true, Cheevos::IsChallengeModeActive());
}
void MainWindow::onEmulationStopped()
{
m_emulation_running = false;
updateEmulationActions(false, false, m_host_interface->IsCheevosChallengeModeActive());
updateEmulationActions(false, false, Cheevos::IsChallengeModeActive());
switchToGameListView();
if (m_cheat_manager_dialog)
@ -672,13 +668,13 @@ void MainWindow::onViewToolbarActionToggled(bool checked)
void MainWindow::onViewLockToolbarActionToggled(bool checked)
{
m_host_interface->SetBoolSettingValue("UI", "LockToolbar", checked);
Host::SetBaseBoolSettingValue("UI", "LockToolbar", checked);
m_ui.toolBar->setMovable(!checked);
}
void MainWindow::onViewStatusBarActionToggled(bool checked)
{
m_host_interface->SetBoolSettingValue("UI", "ShowStatusBar", checked);
Host::SetBaseBoolSettingValue("UI", "ShowStatusBar", checked);
m_ui.statusBar->setVisible(checked);
}
@ -808,7 +804,7 @@ void MainWindow::onGameListContextMenuRequested(const QPoint& point, const GameL
m_host_interface->bootSystem(std::move(boot_params));
});
if (m_ui.menuDebug->menuAction()->isVisible() && !m_host_interface->IsCheevosChallengeModeActive())
if (m_ui.menuDebug->menuAction()->isVisible() && !Cheevos::IsChallengeModeActive())
{
connect(menu.addAction(tr("Boot and Debug")), &QAction::triggered, [this, entry]() {
m_open_debugger_on_start = true;
@ -881,11 +877,11 @@ void MainWindow::setupAdditionalUi()
{
setWindowTitle(getWindowTitle(QString()));
const bool status_bar_visible = m_host_interface->GetBoolSettingValue("UI", "ShowStatusBar", true);
const bool status_bar_visible = Host::GetBaseBoolSettingValue("UI", "ShowStatusBar", true);
m_ui.actionViewStatusBar->setChecked(status_bar_visible);
m_ui.statusBar->setVisible(status_bar_visible);
const bool toolbars_locked = m_host_interface->GetBoolSettingValue("UI", "LockToolbar", false);
const bool toolbars_locked = Host::GetBaseBoolSettingValue("UI", "LockToolbar", false);
m_ui.actionViewLockToolbar->setChecked(toolbars_locked);
m_ui.toolBar->setMovable(!toolbars_locked);
m_ui.toolBar->setContextMenuPolicy(Qt::PreventContextMenu);
@ -931,7 +927,7 @@ void MainWindow::setupAdditionalUi()
qApp->translate("CPUExecutionMode", Settings::GetCPUExecutionModeDisplayName(mode)));
action->setCheckable(true);
connect(action, &QAction::triggered, [this, mode]() {
m_host_interface->SetStringSettingValue("CPU", "ExecutionMode", Settings::GetCPUExecutionModeName(mode));
Host::SetBaseBoolSettingValue("CPU", "ExecutionMode", Settings::GetCPUExecutionModeName(mode));
m_host_interface->applySettings();
updateDebugMenuCPUExecutionMode();
});
@ -945,7 +941,7 @@ void MainWindow::setupAdditionalUi()
m_ui.menuRenderer->addAction(qApp->translate("GPURenderer", Settings::GetRendererDisplayName(renderer)));
action->setCheckable(true);
connect(action, &QAction::triggered, [this, renderer]() {
m_host_interface->SetStringSettingValue("GPU", "Renderer", Settings::GetRendererName(renderer));
Host::SetBaseStringSettingValue("GPU", "Renderer", Settings::GetRendererName(renderer));
m_host_interface->applySettings();
updateDebugMenuGPURenderer();
});
@ -959,7 +955,7 @@ void MainWindow::setupAdditionalUi()
qApp->translate("DisplayCropMode", Settings::GetDisplayCropModeDisplayName(crop_mode)));
action->setCheckable(true);
connect(action, &QAction::triggered, [this, crop_mode]() {
m_host_interface->SetStringSettingValue("Display", "CropMode", Settings::GetDisplayCropModeName(crop_mode));
Host::SetBaseStringSettingValue("Display", "CropMode", Settings::GetDisplayCropModeName(crop_mode));
m_host_interface->applySettings();
updateDebugMenuCropMode();
});
@ -967,7 +963,7 @@ void MainWindow::setupAdditionalUi()
updateDebugMenuCropMode();
const QString current_language(
QString::fromStdString(m_host_interface->GetStringSettingValue("Main", "Language", "")));
QString::fromStdString(Host::GetBaseStringSettingValue("Main", "Language", "")));
QActionGroup* language_group = new QActionGroup(m_ui.menuSettingsLanguage);
for (const std::pair<QString, QString>& it : m_host_interface->getAvailableLanguageList())
{
@ -989,7 +985,7 @@ void MainWindow::setupAdditionalUi()
action->setData(it.second);
connect(action, &QAction::triggered, [this, action]() {
const QString new_language = action->data().toString();
m_host_interface->SetStringSettingValue("Main", "Language", new_language.toUtf8().constData());
Host::SetBaseStringSettingValue("Main", "Language", new_language.toUtf8().constData());
m_host_interface->reinstallTranslator();
recreate();
});
@ -1152,7 +1148,7 @@ void MainWindow::startGameOrChangeDiscs(const std::string& path)
// if we're not running, boot the system, otherwise swap discs
if (!m_emulation_running)
{
if (m_host_interface->CanResumeSystemFromFile(path.c_str()))
if (System::CanResumeSystemFromFile(path.c_str()))
m_host_interface->resumeSystemFromState(QString::fromStdString(path), true);
else
m_host_interface->bootSystem(std::make_shared<SystemBootParameters>(path));
@ -1167,7 +1163,7 @@ void MainWindow::startGameOrChangeDiscs(const std::string& path)
void MainWindow::connectSignals()
{
updateEmulationActions(false, false, m_host_interface->IsCheevosChallengeModeActive());
updateEmulationActions(false, false, Cheevos::IsChallengeModeActive());
onEmulationPaused(false);
connect(qApp, &QGuiApplication::applicationStateChanged, this, &MainWindow::onApplicationStateChanged);
@ -1267,7 +1263,6 @@ void MainWindow::connectSignals()
connect(m_host_interface, &QtHostInterface::settingsResetToDefault, this, &MainWindow::onSettingsResetToDefault);
connect(m_host_interface, &QtHostInterface::errorReported, this, &MainWindow::reportError,
Qt::BlockingQueuedConnection);
connect(m_host_interface, &QtHostInterface::messageReported, this, &MainWindow::reportMessage);
connect(m_host_interface, &QtHostInterface::messageConfirmed, this, &MainWindow::confirmMessage,
Qt::BlockingQueuedConnection);
connect(m_host_interface, &QtHostInterface::createDisplayRequested, this, &MainWindow::createDisplay,
@ -1362,7 +1357,7 @@ void MainWindow::addThemeToMenu(const QString& name, const QString& key)
void MainWindow::setTheme(const QString& theme)
{
m_host_interface->SetStringSettingValue("UI", "Theme", theme.toUtf8().constData());
Host::SetBaseStringSettingValue("UI", "Theme", theme.toUtf8().constData());
setStyleFromSettings();
setIconThemeFromSettings();
updateMenuSelectedTheme();
@ -1371,7 +1366,7 @@ void MainWindow::setTheme(const QString& theme)
void MainWindow::setStyleFromSettings()
{
const std::string theme(m_host_interface->GetStringSettingValue("UI", "Theme", DEFAULT_THEME_NAME));
const std::string theme(Host::GetBaseStringSettingValue("UI", "Theme", DEFAULT_THEME_NAME));
if (theme == "qdarkstyle")
{
@ -1469,7 +1464,7 @@ void MainWindow::setStyleFromSettings()
void MainWindow::setIconThemeFromSettings()
{
const std::string theme(m_host_interface->GetStringSettingValue("UI", "Theme", DEFAULT_THEME_NAME));
const std::string theme(Host::GetBaseStringSettingValue("UI", "Theme", DEFAULT_THEME_NAME));
QString icon_theme;
if (theme == "qdarkstyle" || theme == "darkfusion" || theme == "darkfusionblue")
@ -1508,31 +1503,31 @@ void MainWindow::saveStateToConfig()
{
const QByteArray geometry = saveGeometry();
const QByteArray geometry_b64 = geometry.toBase64();
const std::string old_geometry_b64 = m_host_interface->GetStringSettingValue("UI", "MainWindowGeometry");
const std::string old_geometry_b64 = Host::GetBaseStringSettingValue("UI", "MainWindowGeometry");
if (old_geometry_b64 != geometry_b64.constData())
m_host_interface->SetStringSettingValue("UI", "MainWindowGeometry", geometry_b64.constData());
Host::SetBaseStringSettingValue("UI", "MainWindowGeometry", geometry_b64.constData());
}
{
const QByteArray state = saveState();
const QByteArray state_b64 = state.toBase64();
const std::string old_state_b64 = m_host_interface->GetStringSettingValue("UI", "MainWindowState");
const std::string old_state_b64 = Host::GetBaseStringSettingValue("UI", "MainWindowState");
if (old_state_b64 != state_b64.constData())
m_host_interface->SetStringSettingValue("UI", "MainWindowState", state_b64.constData());
Host::SetBaseStringSettingValue("UI", "MainWindowState", state_b64.constData());
}
}
void MainWindow::restoreStateFromConfig()
{
{
const std::string geometry_b64 = m_host_interface->GetStringSettingValue("UI", "MainWindowGeometry");
const std::string geometry_b64 = Host::GetBaseStringSettingValue("UI", "MainWindowGeometry");
const QByteArray geometry = QByteArray::fromBase64(QByteArray::fromStdString(geometry_b64));
if (!geometry.isEmpty())
restoreGeometry(geometry);
}
{
const std::string state_b64 = m_host_interface->GetStringSettingValue("UI", "MainWindowState");
const std::string state_b64 = Host::GetBaseStringSettingValue("UI", "MainWindowState");
const QByteArray state = QByteArray::fromBase64(QByteArray::fromStdString(state_b64));
if (!state.isEmpty())
restoreState(state);
@ -1552,14 +1547,14 @@ void MainWindow::saveDisplayWindowGeometryToConfig()
{
const QByteArray geometry = getDisplayContainer()->saveGeometry();
const QByteArray geometry_b64 = geometry.toBase64();
const std::string old_geometry_b64 = m_host_interface->GetStringSettingValue("UI", "DisplayWindowGeometry");
const std::string old_geometry_b64 = Host::GetBaseStringSettingValue("UI", "DisplayWindowGeometry");
if (old_geometry_b64 != geometry_b64.constData())
m_host_interface->SetStringSettingValue("UI", "DisplayWindowGeometry", geometry_b64.constData());
Host::SetBaseStringSettingValue("UI", "DisplayWindowGeometry", geometry_b64.constData());
}
void MainWindow::restoreDisplayWindowGeometryFromConfig()
{
const std::string geometry_b64 = m_host_interface->GetStringSettingValue("UI", "DisplayWindowGeometry");
const std::string geometry_b64 = Host::GetBaseStringSettingValue("UI", "DisplayWindowGeometry");
const QByteArray geometry = QByteArray::fromBase64(QByteArray::fromStdString(geometry_b64));
QWidget* container = getDisplayContainer();
if (!geometry.isEmpty())
@ -1614,7 +1609,7 @@ void MainWindow::doControllerSettings(
void MainWindow::updateDebugMenuCPUExecutionMode()
{
std::optional<CPUExecutionMode> current_mode =
Settings::ParseCPUExecutionMode(m_host_interface->GetStringSettingValue("CPU", "ExecutionMode").c_str());
Settings::ParseCPUExecutionMode(Host::GetBaseStringSettingValue("CPU", "ExecutionMode").c_str());
if (!current_mode.has_value())
return;
@ -1632,7 +1627,7 @@ void MainWindow::updateDebugMenuGPURenderer()
{
// update the menu with the new selected renderer
std::optional<GPURenderer> current_renderer =
Settings::ParseRendererName(m_host_interface->GetStringSettingValue("GPU", "Renderer").c_str());
Settings::ParseRendererName(Host::GetBaseStringSettingValue("GPU", "Renderer").c_str());
if (!current_renderer.has_value())
return;
@ -1649,7 +1644,7 @@ void MainWindow::updateDebugMenuGPURenderer()
void MainWindow::updateDebugMenuCropMode()
{
std::optional<DisplayCropMode> current_crop_mode =
Settings::ParseDisplayCropMode(m_host_interface->GetStringSettingValue("Display", "CropMode").c_str());
Settings::ParseDisplayCropMode(Host::GetBaseStringSettingValue("Display", "CropMode").c_str());
if (!current_crop_mode.has_value())
return;
@ -1665,7 +1660,7 @@ void MainWindow::updateDebugMenuCropMode()
void MainWindow::updateMenuSelectedTheme()
{
QString theme = QString::fromStdString(m_host_interface->GetStringSettingValue("UI", "Theme", DEFAULT_THEME_NAME));
QString theme = QString::fromStdString(Host::GetBaseStringSettingValue("UI", "Theme", DEFAULT_THEME_NAME));
for (QObject* obj : m_ui.menuSettingsTheme->children())
{
@ -1751,7 +1746,7 @@ void MainWindow::dropEvent(QDropEvent* event)
void MainWindow::startupUpdateCheck()
{
if (!m_host_interface->GetBoolSettingValue("AutoUpdater", "CheckAtStartup", true))
if (!Host::GetBaseBoolSettingValue("AutoUpdater", "CheckAtStartup", true))
return;
checkForUpdates(false);
@ -1759,14 +1754,14 @@ void MainWindow::startupUpdateCheck()
void MainWindow::updateDebugMenuVisibility()
{
const bool visible = m_host_interface->GetBoolSettingValue("Main", "ShowDebugMenu", false);
const bool visible = Host::GetBaseBoolSettingValue("Main", "ShowDebugMenu", false);
m_ui.menuDebug->menuAction()->setVisible(visible);
}
void MainWindow::onCheckForUpdatesActionTriggered()
{
// Wipe out the last version, that way it displays the update if we've previously skipped it.
m_host_interface->RemoveSettingValue("AutoUpdater", "LastVersion");
Host::DeleteBaseSettingValue("AutoUpdater", "LastVersion");
checkForUpdates(true);
}
@ -1848,7 +1843,7 @@ void MainWindow::onToolsCheatManagerTriggered()
{
if (!m_cheat_manager_dialog)
{
if (m_host_interface->GetBoolSettingValue("UI", "DisplayCheatWarning", true))
if (Host::GetBaseBoolSettingValue("UI", "DisplayCheatWarning", true))
{
QCheckBox* cb = new QCheckBox(tr("Do not show again"));
QMessageBox mb(this);
@ -1866,8 +1861,7 @@ void MainWindow::onToolsCheatManagerTriggered()
mb.setCheckBox(cb);
connect(cb, &QCheckBox::stateChanged, [](int state) {
QtHostInterface::GetInstance()->SetBoolSettingValue("UI", "DisplayCheatWarning",
(state != Qt::CheckState::Checked));
Host::SetBaseBoolSettingValue("UI", "DisplayCheatWarning", (state != Qt::CheckState::Checked));
});
if (mb.exec() == QMessageBox::No)

View File

@ -53,9 +53,8 @@ public Q_SLOTS:
void checkForUpdates(bool display_message);
private Q_SLOTS:
void reportError(const QString& message);
void reportMessage(const QString& message);
bool confirmMessage(const QString& message);
void reportError(const QString& title, const QString& message);
bool confirmMessage(const QString& title, const QString& message);
QtDisplayWidget* createDisplay(QThread* worker_thread, bool fullscreen, bool render_to_main);
QtDisplayWidget* updateDisplay(QThread* worker_thread, bool fullscreen, bool render_to_main);
void displaySizeRequested(qint32 width, qint32 height);

View File

@ -1,6 +1,7 @@
#include "memorycardeditordialog.h"
#include "common/file_system.h"
#include "common/string_util.h"
#include "core/host.h"
#include "core/host_interface.h"
#include "qtutils.h"
#include <QtCore/QFileInfo>

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,11 @@
#pragma once
#include "common/event.h"
#include "core/host_interface.h"
#include "core/host_settings.h"
#include "core/system.h"
#include "frontend-common/common_host_interface.h"
#include "frontend-common/game_list.h"
#include "frontend-common/input_manager.h"
#include "qtutils.h"
#include <QtCore/QByteArray>
#include <QtCore/QObject>
@ -53,28 +55,7 @@ public:
void RunLater(std::function<void()> func) override;
public Q_SLOTS:
void ReportError(const char* message) override;
void ReportMessage(const char* message) override;
void ReportDebuggerMessage(const char* message) override;
bool ConfirmMessage(const char* message) override;
public:
/// Thread-safe settings access.
void SetBoolSettingValue(const char* section, const char* key, bool value);
void SetIntSettingValue(const char* section, const char* key, int value);
void SetFloatSettingValue(const char* section, const char* key, float value);
void SetStringSettingValue(const char* section, const char* key, const char* value);
void SetStringListSettingValue(const char* section, const char* key, const std::vector<std::string>& values);
bool AddValueToStringList(const char* section, const char* key, const char* value);
bool RemoveValueFromStringList(const char* section, const char* key, const char* value);
void RemoveSettingValue(const char* section, const char* key);
TinyString TranslateString(const char* context, const char* str, const char* disambiguation = nullptr,
int n = -1) const override;
std::string TranslateStdString(const char* context, const char* str, const char* disambiguation = nullptr,
int n = -1) const override;
bool RequestRenderWindowSize(s32 new_window_width, s32 new_window_height) override;
void* GetTopLevelWindowHandle() const override;
@ -89,8 +70,10 @@ public:
ALWAYS_INLINE MainWindow* getMainWindow() const { return m_main_window; }
void setMainWindow(MainWindow* window);
HostDisplay* createHostDisplay();
void connectDisplaySignals(QtDisplayWidget* widget);
ALWAYS_INLINE QEventLoop* getEventLoop() const { return m_worker_thread_event_loop; }
void reinstallTranslator();
void populateLoadStateMenu(const char* game_code, QMenu* menu);
@ -119,12 +102,28 @@ public:
/// Returns program directory as a QString.
QString getProgramDirectory() const;
/// Called back from the GS thread when the display state changes (e.g. fullscreen, render to main).
static HostDisplay* createHostDisplay();
HostDisplay* acquireHostDisplay();
void connectDisplaySignals(QtDisplayWidget* widget);
void releaseHostDisplay();
void updateDisplay();
void renderDisplay();
void onSystemStarted();
void onSystemPaused();
void onSystemResumed();
void onSystemDestroyed();
Q_SIGNALS:
void errorReported(const QString& message);
void messageReported(const QString& message);
void errorReported(const QString& title, const QString& message);
bool messageConfirmed(const QString& title, const QString& message);
void debuggerMessageReported(const QString& message);
bool messageConfirmed(const QString& message);
void settingsResetToDefault();
void onInputDevicesEnumerated(const QList<QPair<QString, QString>>& devices);
void onInputDeviceConnected(const QString& identifier, const QString& device_name);
void onInputDeviceDisconnected(const QString& identifier);
void onVibrationMotorsEnumerated(const QList<InputBindingKey>& motors);
void emulationStarting();
void emulationStarted();
void emulationStopped();
@ -149,8 +148,11 @@ public Q_SLOTS:
void setDefaultSettings();
void applySettings(bool display_osd_messages = false);
void reloadGameSettings();
void reloadInputBindings();
void applyInputProfile(const QString& profile_path);
void reloadInputSources();
void reloadInputBindings();
void enumerateInputDevices();
void enumerateVibrationMotors();
void bootSystem(std::shared_ptr<SystemBootParameters> params);
void resumeSystemFromState(const QString& filename, bool boot_on_failure);
void resumeSystemFromMostRecentState();
@ -184,7 +186,6 @@ public Q_SLOTS:
void requestRenderWindowScale(qreal scale);
void executeOnEmulationThread(std::function<void()> callback, bool wait = false);
void OnAchievementsRefreshed() override;
void OnDisplayInvalidated() override;
private Q_SLOTS:
void doStopThread();
@ -197,24 +198,11 @@ private Q_SLOTS:
void doBackgroundControllerPoll();
protected:
bool AcquireHostDisplay() override;
void ReleaseHostDisplay() override;
bool IsFullscreen() const override;
bool SetFullscreen(bool enabled) override;
void RequestExit() override;
void OnSystemCreated() override;
void OnSystemPaused(bool paused) override;
void OnSystemDestroyed() override;
void OnSystemPerformanceCountersUpdated() override;
void OnRunningGameChanged(const std::string& path, CDImage* image, const std::string& game_code,
const std::string& game_title) override;
void SetDefaultSettings(SettingsInterface& si) override;
void SetDefaultSettings() override;
void ApplySettings(bool display_osd_messages) override;
void SetMouseMode(bool relative, bool hide_cursor) override;
private:
@ -258,7 +246,6 @@ private:
bool initializeOnThread();
void shutdownOnThread();
void installTranslator();
void renderDisplay();
void checkRenderToMainState();
void updateDisplayState();
void queueSettingsSave();
@ -281,31 +268,25 @@ private:
bool m_lost_exclusive_fullscreen = false;
};
extern QtHostInterface* g_emu_thread;
namespace QtHost {
/// Sets batch mode (exit after game shutdown).
//bool InBatchMode();
//void SetBatchMode(bool enabled);
// bool InBatchMode();
// void SetBatchMode(bool enabled);
/// Executes a function on the UI thread.
void RunOnUIThread(const std::function<void()>& func, bool block = false);
/// Returns the application name and version, optionally including debug/devel config indicator.
//QString GetAppNameAndVersion();
// QString GetAppNameAndVersion();
/// Returns the debug/devel config indicator.
//QString GetAppConfigSuffix();
// QString GetAppConfigSuffix();
/// Returns the base path for resources. This may be : prefixed, if we're using embedded resources.
//QString GetResourcesBasePath();
// QString GetResourcesBasePath();
/// Thread-safe settings access.
void SetBaseBoolSettingValue(const char* section, const char* key, bool value);
void SetBaseIntSettingValue(const char* section, const char* key, int value);
void SetBaseFloatSettingValue(const char* section, const char* key, float value);
void SetBaseStringSettingValue(const char* section, const char* key, const char* value);
void SetBaseStringListSettingValue(const char* section, const char* key, const std::vector<std::string>& values);
bool AddBaseValueToStringList(const char* section, const char* key, const char* value);
bool RemoveBaseValueFromStringList(const char* section, const char* key, const char* value);
void RemoveBaseSettingValue(const char* section, const char* key);
void QueueSettingsSave();
} // namespace QtHost

View File

@ -0,0 +1,422 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="100%"
height="100%"
viewBox="0 0 14044 9934"
version="1.1"
xml:space="preserve"
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;"
id="svg243"
sodipodi:docname="Dualshock.svg"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:serif="http://www.serif.com/"><defs
id="defs247" /><sodipodi:namedview
id="namedview245"
pagecolor="#ffffff"
bordercolor="#999999"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="0.063317898"
inkscape:cx="7028.0286"
inkscape:cy="4967"
inkscape:window-width="1920"
inkscape:window-height="1057"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg243" /><g
id="g381"><path
d="M10753.3,8451c-389.372,-507.74 -389.331,-507.607 -934.976,-1289c-75.558,560.925 -556.692,994 -1138.18,994c-633.875,0 -1148.5,-514.626 -1148.5,-1148.5c-0,-41.211 2.175,-81.918 6.417,-122.013c0.017,-0.161 0.034,-0.323 0.052,-0.487l-1032.94,0c4.276,40.252 6.469,81.122 6.469,122.5c-0,633.874 -514.626,1148.5 -1148.5,1148.5c-581.486,0 -1062.62,-433.075 -1138.18,-994c-535.503,767.622 -535.459,768.031 -934.976,1289c-546.654,712.835 -1177.32,754.202 -1824,323c-646.678,-431.202 -497.114,-1201.6 -456,-1508c41.114,-306.398 188.618,-1499.22 238,-1781c49.382,-281.782 100.637,-1065.49 193,-1437c92.363,-371.511 158.273,-1152.75 553,-1607c394.727,-454.247 473.66,-678.27 584,-954c110.34,-275.73 33.857,-605 1146,-605c1112.14,0 831.23,848.344 1012,1019c346.272,166.412 398,417 398,417l3775.31,0c0,0 51.728,-250.588 398,-417c180.77,-170.656 -100.142,-1019 1012,-1019c1112.14,0 1035.66,329.27 1146,605c110.34,275.73 189.273,499.753 584,954c394.727,454.247 460.638,1235.49 553,1607c92.363,371.511 143.618,1155.22 193,1437c49.382,281.782 196.886,1474.6 238,1781c41.114,306.398 190.678,1076.8 -456,1508c-646.678,431.202 -1277.35,389.835 -1824,-323Z"
style="fill:#b3b3b3;stroke:#000;stroke-width:62.5px;"
id="path2" /><g
id="Controle"><g
id="Camada1"><g
id="D-Pad"><g
id="Botões"><path
d="M3770.66,5295.54c22.468,25.431 54.769,39.995 88.703,39.995c96.047,0 300.757,0 437.818,0c36.02,0 70.565,-14.309 96.035,-39.779c25.47,-25.47 39.779,-60.015 39.779,-96.035l0,-466.371c0,-36.02 -14.309,-70.565 -39.779,-96.035c-25.47,-25.471 -60.015,-39.78 -96.035,-39.78l-437.818,0c-33.934,0 -66.235,14.565 -88.703,39.996c-60.337,68.296 -183.002,207.14 -248.009,280.722c-24.364,27.578 -24.364,68.987 -0,96.565c65.007,73.582 187.672,212.426 248.009,280.722Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="path4" /><path
d="M3021.99,5386.2c-25.43,22.467 -39.995,54.769 -39.995,88.702c0,96.048 0,300.758 0,437.818c-0,36.02 14.309,70.565 39.779,96.035c25.47,25.47 60.015,39.779 96.035,39.779l466.372,0c36.02,0 70.565,-14.309 96.035,-39.779c25.47,-25.47 39.779,-60.015 39.779,-96.035l0,-437.818c0,-33.933 -14.565,-66.235 -39.995,-88.702c-68.297,-60.338 -207.141,-183.002 -280.723,-248.01c-27.578,-24.364 -68.986,-24.364 -96.564,0c-73.582,65.008 -212.426,187.672 -280.723,248.01Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="path6" /><path
d="M2931.34,5295.54c-22.468,25.431 -54.769,39.995 -88.703,39.995c-96.047,0 -300.757,0 -437.818,0c-36.02,0 -70.565,-14.309 -96.035,-39.779c-25.47,-25.47 -39.779,-60.015 -39.779,-96.035l-0,-466.371c-0,-36.02 14.309,-70.565 39.779,-96.035c25.47,-25.471 60.015,-39.78 96.035,-39.78l437.818,0c33.934,0 66.235,14.565 88.703,39.996c60.337,68.296 183.002,207.14 248.009,280.722c24.364,27.578 24.364,68.987 0,96.565c-65.007,73.582 -187.672,212.426 -248.009,280.722Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="path8" /><path
d="M3021.99,4546.87c-25.43,-22.467 -39.995,-54.769 -39.995,-88.703c0,-96.047 0,-300.757 0,-437.817c-0,-36.02 14.309,-70.565 39.779,-96.035c25.47,-25.471 60.015,-39.78 96.035,-39.78l466.372,0c36.02,0 70.565,14.309 96.035,39.78c25.47,25.47 39.779,60.015 39.779,96.035l0,437.817c0,33.934 -14.565,66.236 -39.995,88.703c-68.297,60.338 -207.141,183.002 -280.723,248.01c-27.578,24.364 -68.986,24.364 -96.564,-0c-73.582,-65.008 -212.426,-187.672 -280.723,-248.01Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="path10" /></g><path
d="M4810,4966.53l-232,262l0,-524l232,262Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path13" /><path
d="M1892,4966.53l232,262l-0,-524l-232,262Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path15" /><path
d="M3351,6425.53l-262,-232l524,0l-262,232Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path17" /><path
d="M3351,3507.53l-262,232l524,0l-262,-232Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path19" /></g></g><g
id="Base"><g
id="Base1"
serif:id="Base"><path
d="M1875,3636c0,0 205.726,-169.78 295,-296.752c52.938,-105.72 53.86,-485.219 88,-583.248c34.14,-98.029 124.145,-452 988,-452c863.855,0 933.091,200.612 1047,584c113.909,383.388 82.114,526 816,526l1912.65,0"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path23" /><path
d="M2135,3211l251,-1086c0,0 80.109,-386 1069,-386c988.891,0 1053,678.558 1053,806c0,127.442 -14.804,222 214,222l2299.65,0"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path25" /><path
d="M4470,3240l254,-1257"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path27" /><path
d="M4679,2679l404,-311"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path29" /><path
d="M4616,2888l154,445"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path31" /><path
d="M2257,2711c0,0 -530.357,346.988 -727,968"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path33" /><path
d="M2388,2118l67,-345"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path35" /><path
d="M3195,8453l970,-1409"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path37" /><path
d="M6604,6800l417.654,0"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path39" /><path
d="M4283.05,6645.21c-5.207,2.9 -10.43,5.776 -15.667,8.629c-272.398,148.372 -584.621,232.699 -916.384,232.699c-1059.68,0 -1920,-860.323 -1920,-1920c0,-1059.68 860.323,-1920 1920,-1920c1059.68,0 1920,860.324 1920,1920c0,338.339 -87.704,656.354 -241.597,932.534"
style="fill:none;stroke:#000;stroke-width:41.67px;"
id="path41" /><path
d="M3895,4422.53l0,-986.947c-0,-53.207 -43.133,-96.34 -96.34,-96.34l-895.32,0c-53.207,0 -96.34,43.133 -96.34,96.34l0,986.947l-987.66,0c-25.551,0 -50.055,10.151 -68.123,28.218c-18.067,18.067 -28.217,42.572 -28.217,68.123l0,895.319c-0,25.551 10.15,50.056 28.217,68.123c18.068,18.067 42.572,28.217 68.123,28.217l987.66,0l0,988.373c0,25.551 10.15,50.055 28.217,68.123c18.068,18.067 42.572,28.217 68.123,28.217l895.32,0c25.551,0 50.055,-10.15 68.123,-28.217c18.067,-18.068 28.217,-42.572 28.217,-68.123l0,-988.373l987.66,0c25.551,0 50.055,-10.15 68.123,-28.217c18.067,-18.067 28.217,-42.572 28.217,-68.123l0,-895.319c0,-25.551 -10.15,-50.056 -28.217,-68.123c-18.068,-18.067 -42.572,-28.218 -68.123,-28.218l-987.66,0Z"
style="fill:none;stroke:#000;stroke-width:41.67px;"
id="path43" /></g><g
id="Base2"
serif:id="Base"><path
d="M12168.3,3636c0,0 -205.726,-169.78 -295,-296.752c-52.938,-105.72 -53.86,-485.219 -88,-583.248c-34.14,-98.029 -124.145,-452 -988,-452c-863.855,0 -933.091,200.612 -1047,584c-113.909,383.388 -82.114,526 -816,526l-1912.65,0"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path46" /><path
d="M11908.3,3211l-251,-1086c0,0 -80.109,-386 -1069,-386c-988.89,0 -1053,678.558 -1053,806c0,127.442 14.804,222 -214,222l-2299.65,0"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path48" /><path
d="M9573.31,3240l-254,-1257"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path50" /><path
d="M9364.31,2679l-404,-311"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path52" /><path
d="M9427.31,2888l-154,445"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path54" /><path
d="M11786.3,2711c0,0 530.357,346.988 727,968"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path56" /><path
d="M11655.3,2118l-67,-345"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path58" /><path
d="M10848.3,8453l-970,-1409"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path60" /><path
d="M7439.31,6800l-417.653,0"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path62" /><path
d="M9787.41,6660.04c269.674,144.515 577.786,226.492 904.894,226.492c1059.68,0 1920,-860.323 1920,-1920c0,-1059.68 -860.323,-1920 -1920,-1920c-1059.68,0 -1920,860.324 -1920,1920c0,335.752 86.368,651.49 238.079,926.191"
style="fill:none;stroke:#000;stroke-width:41.67px;"
id="path64" /><path
d="M10148.3,4422.53l0,-986.947c0,-53.207 43.133,-96.34 96.34,-96.34l895.32,0c53.207,0 96.34,43.133 96.34,96.34l0,986.947l987.66,0c25.551,0 50.055,10.151 68.123,28.218c18.067,18.067 28.217,42.572 28.217,68.123c0,206.346 0,688.973 0,895.319c0,25.551 -10.15,50.056 -28.217,68.123c-18.068,18.067 -42.572,28.217 -68.123,28.217l-987.66,0l0,988.373c0,25.551 -10.15,50.055 -28.217,68.123c-18.068,18.067 -42.572,28.217 -68.123,28.217l-895.32,0c-25.551,0 -50.055,-10.15 -68.123,-28.217c-18.067,-18.068 -28.217,-42.572 -28.217,-68.123l0,-988.373l-987.66,0c-25.551,0 -50.055,-10.15 -68.123,-28.217c-18.067,-18.067 -28.217,-42.572 -28.217,-68.123c0,-206.346 0,-688.973 0,-895.319c0,-25.551 10.15,-50.056 28.217,-68.123c18.068,-18.067 42.572,-28.218 68.123,-28.218l987.66,0Z"
style="fill:none;stroke:#000;stroke-width:41.67px;"
id="path66" /></g></g><g
id="Botões1"
serif:id="Botões"><path
d="M3511.78,1591c-224.789,-5.298 -789,-13 -874,310c-131.822,500.924 -48.891,239 708,239c756.891,0 803.274,397.046 917,-90c92,-394 -454,-452 -751,-459Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="path70" /><path
d="M10531.5,1591c224.789,-5.298 789,-13 874,310c131.822,500.924 48.891,239 -708,239c-756.891,0 -803.273,397.046 -917,-90c-92,-394 454,-452 751,-459Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="path72" /><path
d="M3692.24,796.638c-224.79,-5.953 -789,-14.609 -874,348.364c-131.822,562.916 -48.891,268.578 708,268.578c756.89,-0 803.273,446.182 917,-101.138c92,-442.76 -454,-507.937 -751,-515.804Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="path74" /><path
d="M10351.1,796.638c224.789,-5.953 789,-14.609 874,348.364c131.822,562.916 48.89,268.578 -708,268.578c-756.891,-0 -803.274,446.182 -917,-101.138c-92,-442.76 454,-507.937 751,-515.804Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="path76" /><g
transform="matrix(-0.984917,-0.173029,0.173029,-0.984917,12155.2,9433.92)"
id="g80"><text
x="9839.79px"
y="6093.16px"
style="font-family:'Arial-BoldMT', 'Arial', sans-serif;font-weight:700;font-size:261.061px;fill:#e0e0e0;"
id="text78">1</text></g><g
transform="matrix(-0.984808,0.173648,-0.173648,-0.984808,28878.8,3509.63)"
id="g84"><text
x="17636.9px"
y="4924.1px"
style="font-family:'Arial-BoldMT', 'Arial', sans-serif;font-weight:700;font-size:261.061px;fill:#e0e0e0;"
id="text82">1</text></g><g
transform="matrix(-0.992546,-0.121869,0.121869,-0.992546,13104,7378.99)"
id="g88"><text
x="10128.7px"
y="5194.76px"
style="font-family:'Arial-BoldMT', 'Arial', sans-serif;font-weight:700;font-size:261.061px;fill:#e0e0e0;"
id="text86">2</text></g><g
transform="matrix(-0.992546,0.121869,-0.121869,-0.992546,28316.7,3208.88)"
id="g92"><text
x="17411.2px"
y="4376.4px"
style="font-family:'Arial-BoldMT', 'Arial', sans-serif;font-weight:700;font-size:261.061px;fill:#e0e0e0;"
id="text90">2</text></g></g><g
id="Duckstation--Logo-"
serif:id="Duckstation (Logo)"><path
d="M6547.88,5012.41c-0,14.441 -2.931,25.74 -8.793,33.895c-5.861,8.156 -15.673,12.234 -29.436,12.234l-70.34,-0l0,-178.655l70.34,0c13.763,0 23.575,4.12 29.436,12.361c5.862,8.24 8.793,19.921 8.793,35.043l-0,85.122Zm-26.76,-85.122c-0,-12.403 -1.529,-20.856 -4.587,-25.359c-3.059,-4.502 -8.071,-6.753 -15.037,-6.753l-35.425,-0l-0,148.071l35.425,0c6.966,0 11.978,-2.548 15.037,-7.646c3.058,-5.097 4.587,-12.827 4.587,-23.191l-0,-85.122Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path95" /><path
d="M6651.35,5043.25l0,-126.154l25.996,0l-0,141.446l-68.557,-0c-7.645,-0 -13.932,-0.765 -18.859,-2.294c-4.927,-1.529 -8.877,-4.035 -11.851,-7.518c-2.973,-3.483 -5.012,-7.943 -6.116,-13.38c-1.105,-5.437 -1.657,-12.149 -1.657,-20.134l0,-98.12l25.996,0l-0,99.139c-0,5.607 0.297,10.195 0.892,13.763c0.594,3.568 1.656,6.329 3.185,8.282c1.529,1.954 3.696,3.271 6.499,3.951c2.803,0.679 6.499,1.019 11.086,1.019l33.386,0Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path97" /><path
d="M6726.78,5016.23c-0,5.607 0.297,10.195 0.892,13.763c0.595,3.568 1.656,6.329 3.186,8.282c1.529,1.954 3.695,3.271 6.498,3.951c2.804,0.679 6.499,1.019 11.087,1.019l40.267,0l-0,15.292l-49.442,-0c-7.646,-0 -13.932,-0.765 -18.86,-2.294c-4.927,-1.529 -8.877,-4.035 -11.85,-7.518c-2.974,-3.483 -5.012,-7.943 -6.117,-13.38c-1.104,-5.437 -1.656,-12.149 -1.656,-20.134l-0,-54.794c-0,-7.816 0.552,-14.484 1.656,-20.006c1.105,-5.522 3.143,-10.025 6.117,-13.508c2.973,-3.483 6.923,-5.989 11.85,-7.518c4.928,-1.529 11.214,-2.294 18.86,-2.294l49.442,0l-0,15.292l-40.267,-0c-4.588,-0 -8.283,0.34 -11.087,1.019c-2.803,0.68 -4.969,1.996 -6.498,3.95c-1.53,1.954 -2.591,4.715 -3.186,8.283c-0.595,3.568 -0.892,8.156 -0.892,13.762l-0,56.833Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path99" /><path
d="M6909.01,5058.54l-30.838,-0l-44.09,-78.751l0,78.751l-25.995,-0l0,-183.752l25.995,0l0,97.61l48.933,-55.304l19.879,0l-45.11,51.481l51.226,89.965Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path101" /><path
d="M7020.12,5004.76c0,18.519 -3.143,32.112 -9.429,40.777c-6.287,8.665 -16.991,12.998 -32.112,12.998l-57.088,-0l0,-15.292l51.991,0c3.568,0 6.753,-0.425 9.557,-1.274c2.803,-0.85 5.097,-2.549 6.881,-5.097c1.784,-2.549 3.143,-6.074 4.078,-10.577c0.934,-4.502 1.401,-10.406 1.401,-17.712c0,-6.287 -0.339,-11.426 -1.019,-15.419c-0.68,-3.993 -1.911,-7.051 -3.695,-9.175c-1.784,-2.124 -4.248,-3.568 -7.391,-4.332c-3.144,-0.765 -7.264,-1.147 -12.361,-1.147l-19.369,-0c-6.456,-0 -11.893,-0.85 -16.311,-2.549c-4.417,-1.699 -7.985,-4.46 -10.704,-8.283c-2.718,-3.823 -4.672,-8.835 -5.861,-15.036c-1.19,-6.202 -1.784,-13.89 -1.784,-23.065c-0,-15.631 2.93,-27.822 8.792,-36.572c5.862,-8.75 16.014,-13.125 30.455,-13.125l49.697,0l0,15.292l-43.325,-0c-3.568,-0 -6.626,0.467 -9.175,1.401c-2.548,0.935 -4.715,2.549 -6.499,4.843c-1.784,2.293 -3.101,5.437 -3.95,9.429c-0.85,3.993 -1.274,9.048 -1.274,15.164c-0,5.947 0.255,10.832 0.764,14.655c0.51,3.822 1.487,6.796 2.931,8.919c1.444,2.124 3.526,3.611 6.244,4.46c2.719,0.85 6.371,1.275 10.959,1.275l18.095,-0c6.796,-0 12.7,0.679 17.712,2.039c5.012,1.359 9.133,3.822 12.361,7.39c3.228,3.568 5.607,8.581 7.136,15.037c1.529,6.456 2.293,14.782 2.293,24.976Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path103" /><path
d="M7100.15,4932.39l-35.425,-0l0,90.219c0,8.155 1.147,13.635 3.441,16.438c2.294,2.803 6.753,4.205 13.38,4.205l11.468,0l0,15.292l-21.917,-0c-6.117,-0 -11.256,-0.85 -15.419,-2.549c-4.163,-1.699 -7.476,-4.078 -9.94,-7.136c-2.463,-3.058 -4.247,-6.669 -5.352,-10.831c-1.104,-4.163 -1.656,-8.708 -1.656,-13.635l-0,-144.504l25.995,0l0,37.209l35.425,0l0,15.292Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path105" /><path
d="M7166.16,4973.67l0,14.782l-10.959,0c-4.587,0 -8.283,0.34 -11.086,1.019c-2.803,0.68 -4.97,1.742 -6.499,3.186c-1.529,1.444 -2.591,3.356 -3.186,5.734c-0.594,2.379 -0.892,5.352 -0.892,8.92l0,16.311c0,3.908 0.298,7.094 0.892,9.557c0.595,2.464 1.657,4.46 3.186,5.989c1.529,1.53 3.696,2.591 6.499,3.186c2.803,0.595 6.499,0.892 11.086,0.892l28.799,0l-0,-83.848c-0,-5.606 -0.297,-10.194 -0.892,-13.762c-0.595,-3.568 -1.657,-6.329 -3.186,-8.283c-1.529,-1.954 -3.695,-3.27 -6.499,-3.95c-2.803,-0.679 -6.498,-1.019 -11.086,-1.019l-36.699,-0l-0,-15.292l45.874,0c7.646,0 13.932,0.765 18.859,2.294c4.928,1.529 8.878,4.035 11.851,7.518c2.973,3.483 5.012,7.986 6.117,13.508c1.104,5.522 1.656,12.19 1.656,20.006l0,98.12l-63.969,-0c-7.645,-0 -13.932,-0.723 -18.859,-2.167c-4.927,-1.444 -8.877,-3.568 -11.851,-6.371c-2.973,-2.804 -5.012,-6.287 -6.116,-10.449c-1.105,-4.163 -1.657,-8.963 -1.657,-14.4l0,-18.094c0,-5.437 0.552,-10.237 1.657,-14.4c1.104,-4.162 3.143,-7.645 6.116,-10.449c2.974,-2.803 6.924,-4.927 11.851,-6.371c4.927,-1.445 11.214,-2.167 18.859,-2.167l20.134,0Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path107" /><path
d="M7294.86,4932.39l-35.425,-0l0,90.219c0,8.155 1.147,13.635 3.441,16.438c2.294,2.803 6.754,4.205 13.38,4.205l11.468,0l0,15.292l-21.917,-0c-6.117,-0 -11.256,-0.85 -15.419,-2.549c-4.163,-1.699 -7.476,-4.078 -9.939,-7.136c-2.464,-3.058 -4.248,-6.669 -5.352,-10.831c-1.105,-4.163 -1.657,-8.708 -1.657,-13.635l0,-144.504l25.995,0l0,37.209l35.425,0l0,15.292Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path109" /><path
d="M7337.17,5058.54l-25.996,-0l0,-141.446l25.996,0l-0,141.446Zm-0,-159.54l-25.996,-0l0,-24.467l25.996,0l-0,24.467Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path111" /><path
d="M7433.76,4917.09c7.646,0 13.932,0.765 18.859,2.294c4.928,1.529 8.878,4.035 11.851,7.518c2.974,3.483 5.012,7.986 6.117,13.508c1.104,5.522 1.656,12.19 1.656,20.006l0,54.794c0,7.985 -0.552,14.697 -1.656,20.134c-1.105,5.437 -3.143,9.897 -6.117,13.38c-2.973,3.483 -6.923,5.989 -11.851,7.518c-4.927,1.529 -11.213,2.294 -18.859,2.294l-34.151,-0c-7.645,-0 -13.932,-0.765 -18.859,-2.294c-4.927,-1.529 -8.878,-4.035 -11.851,-7.518c-2.973,-3.483 -5.012,-7.943 -6.116,-13.38c-1.105,-5.437 -1.657,-12.149 -1.657,-20.134l0,-54.794c0,-7.816 0.552,-14.484 1.657,-20.006c1.104,-5.522 3.143,-10.025 6.116,-13.508c2.973,-3.483 6.924,-5.989 11.851,-7.518c4.927,-1.529 11.214,-2.294 18.859,-2.294l34.151,0Zm-46.639,99.139c0,5.607 0.298,10.195 0.892,13.763c0.595,3.568 1.657,6.329 3.186,8.282c1.529,1.954 3.695,3.271 6.499,3.951c2.803,0.679 6.499,1.019 11.086,1.019l15.801,0c4.588,0 8.283,-0.34 11.086,-1.019c2.804,-0.68 4.97,-1.997 6.499,-3.951c1.529,-1.953 2.591,-4.714 3.186,-8.282c0.595,-3.568 0.892,-8.156 0.892,-13.763l0,-56.833c0,-5.606 -0.297,-10.194 -0.892,-13.762c-0.595,-3.568 -1.657,-6.329 -3.186,-8.283c-1.529,-1.954 -3.695,-3.27 -6.499,-3.95c-2.803,-0.679 -6.498,-1.019 -11.086,-1.019l-15.801,-0c-4.587,-0 -8.283,0.34 -11.086,1.019c-2.804,0.68 -4.97,1.996 -6.499,3.95c-1.529,1.954 -2.591,4.715 -3.186,8.283c-0.594,3.568 -0.892,8.156 -0.892,13.762l0,56.833Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path113" /><path
d="M7521.68,4932.39l0,126.154l-25.995,-0l0,-141.446l69.831,0c7.645,0 13.932,0.765 18.859,2.294c4.927,1.529 8.878,4.035 11.851,7.518c2.973,3.483 5.012,7.986 6.116,13.508c1.105,5.522 1.657,12.19 1.657,20.006l-0,98.12l-25.995,-0l-0,-99.14c-0,-5.606 -0.298,-10.194 -0.892,-13.762c-0.595,-3.568 -1.657,-6.329 -3.186,-8.283c-1.529,-1.954 -3.695,-3.27 -6.499,-3.95c-2.803,-0.679 -6.499,-1.019 -11.086,-1.019l-34.661,-0Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path115" /><g
id="Duck"><path
d="M7003.84,4643.95l-58.35,35.385"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path117" /><path
d="M6945.49,4563.11l-0,48.976l58.35,31.87l-0,70.067l-58.35,33.979"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path119" /><path
d="M7123.82,4457.89l-0,48.976l57.764,31.987"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path121" /><path
d="M7003.84,4530.07l-0,46.516l118.809,67.372l58.936,-33.041l-0,-69.598l-59.639,35.267l-61.162,-36.673l-0,-44.29"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path123" /><path
d="M6826.45,4523.04l-0,154.663l119.043,70.301l-0,-68.895l-61.162,-35.854l-0,-85.064"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path125" /><path
d="M6703.31,3825.65l93.97,-54.484"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path127" /><path
d="M6613.32,3771.16l89.985,-51.671l93.97,51.671l-0,103.46"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path129" /><path
d="M6703.31,3929.11l0,-104.398l-89.985,-53.546l-0,109.319l83.658,53.077"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path131" /><path
d="M7094.88,4279.44l82.252,-49.328"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path133" /><path
d="M7154.29,4159.23l0,56.552l146.461,85.222l0,-56.71"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path135" /><path
d="M7301.8,4074.16l-147.516,85.885l147.164,84.244l145.758,-84.596l-145.406,-85.533Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path137" /><path
d="M6920.19,4576.58l324.088,-190.164l-0,-117.755"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path139" /><path
d="M6596.1,3994.25l248.632,-145.875"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path141" /><path
d="M6920.19,4180.12l-0,396.458l-324.089,-188.201l0,-394.127l324.089,185.87Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path143" /><path
d="M7094.88,3973.98l250.155,-146.695"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path145" /><g
id="Camada2"><path
d="M6844.73,4135.68l-0,-308.857l250.155,-144.82l250.155,145.641l-0,271.714"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path147" /><path
d="M6844.73,4135.68l250.155,143.766l-0,-304.053l-250.155,-148.101"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path149" /></g><path
d="M7300.75,4301l146.461,-85.222l-0,-56.552"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path152" /><path
d="M7123.82,4576.23l-0,67.723"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path154" /><path
d="M6885.97,4643.95l59.522,-33.861"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path156" /><path
d="M7062.08,4539.44l61.748,-33.159"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path158" /><path
d="M7130.74,4075.22l-0,59.639l50.851,-28.707l-0,-60.107l-50.851,29.175Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path160" /><path
d="M7258.45,4003.63l0,59.639l50.851,-28.707l0,-60.107l-50.851,29.175Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path162" /></g></g><g
id="Botões2"
serif:id="Botões"><circle
cx="9642.81"
cy="4966.53"
r="461.5"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="circle166" /><path
d="M11153.8,3917.03c0,254.709 -206.791,461.5 -461.5,461.5c-254.709,0 -461.5,-206.791 -461.5,-461.5c0,-254.708 206.791,-461.5 461.5,-461.5c254.709,0 461.5,206.792 461.5,461.5Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="path168" /><circle
cx="11741.8"
cy="4966.53"
r="461.5"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="circle170" /><path
d="M11153.8,6016.03c0,254.709 -206.791,461.5 -461.5,461.5c-254.709,0 -461.5,-206.791 -461.5,-461.5c0,-254.708 206.791,-461.5 461.5,-461.5c254.709,0 461.5,206.792 461.5,461.5Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="path172" /><g
id="X"><path
d="M10915,5793.34l-445.386,445.385"
style="fill:none;stroke:#6f97e3;stroke-width:83.33px;"
id="path174" /><path
d="M10469.6,5793.34l445.386,445.385"
style="fill:none;stroke:#6f97e3;stroke-width:83.33px;"
id="path176" /></g><path
d="M10692.3,3603l252,504l-504,0l252,-504Z"
style="fill:none;stroke:#7ae0c4;stroke-width:83.33px;"
id="path179" /><circle
cx="11741.8"
cy="4952.87"
r="305.126"
style="fill:none;stroke:#ee676b;stroke-width:83.33px;"
id="circle181" /><rect
x="9400.27"
y="4724"
width="485.071"
height="485.071"
style="fill:none;stroke:#f37caa;stroke-width:83.33px;"
id="rect183" /></g><g
id="Botões-Centrais"
serif:id="Botões Centrais"><path
id="Analógico"
d="M7353.15,6081.73c-0,-62.812 -50.92,-113.731 -113.732,-113.731l-435.537,0c-62.812,0 -113.731,50.919 -113.731,113.731l-0,173.538c-0,62.812 50.919,113.731 113.731,113.731l435.537,0c62.812,-0 113.732,-50.919 113.732,-113.731l-0,-173.538Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;" /><path
id="Select"
d="M6176,4817.73c-0,-62.812 -50.919,-113.731 -113.731,-113.731c-121.75,0 -313.788,-0 -435.538,0c-62.812,0 -113.731,50.919 -113.731,113.731l0,173.538c0,62.812 50.919,113.731 113.731,113.731l435.538,0c62.812,-0 113.731,-50.919 113.731,-113.731c0,-54.335 0,-119.203 0,-173.538Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;" /><rect
id="Led-Analógico"
serif:id="Led Analógico"
x="6832.15"
y="6516"
width="379"
height="124"
style="fill:#a7de74;stroke:#404040;stroke-width:20.83px;stroke-linecap:square;" /><path
id="Start"
d="M8466.86,4889.43c18.696,6.583 31.202,24.247 31.202,44.068c0,19.821 -12.506,37.485 -31.202,44.068c-150.687,53.064 -397.808,140.086 -512.618,180.515c-14.296,5.034 -30.146,2.821 -42.516,-5.938c-12.37,-8.758 -19.723,-22.973 -19.723,-38.13l0,-361.03c-0,-15.157 7.353,-29.372 19.723,-38.13c12.37,-8.759 28.22,-10.972 42.516,-5.938c114.81,40.429 361.931,127.451 512.618,180.515Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;" /></g><g
id="Textos"><g
id="ANALOG"><path
d="M6511.96,5844.83l68.235,-177.676l25.33,0l72.719,177.676l-26.785,0l-20.725,-53.812l-74.294,0l-19.513,53.812l-24.967,0Zm51.267,-72.961l60.235,-0l-18.543,-49.206c-5.656,-14.948 -9.857,-27.229 -12.604,-36.844c-2.263,11.392 -5.454,22.704 -9.575,33.935l-19.513,52.115Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path191" /><path
d="M6696.78,5844.83l0,-177.676l24.118,0l93.323,139.499l-0,-139.499l22.542,0l0,177.676l-24.118,0l-93.322,-139.62l-0,139.62l-22.543,0Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path193" /><path
d="M6856.76,5844.83l68.234,-177.676l25.331,0l72.718,177.676l-26.784,0l-20.725,-53.812l-74.294,0l-19.513,53.812l-24.967,0Zm51.267,-72.961l60.235,-0l-18.543,-49.206c-5.656,-14.948 -9.858,-27.229 -12.605,-36.844c-2.262,11.392 -5.454,22.704 -9.574,33.935l-19.513,52.115Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path195" /><path
d="M7040.86,5844.83l0,-177.676l23.513,0l-0,156.709l87.505,-0l-0,20.967l-111.018,0Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path197" /><path
d="M7172.73,5758.29c-0,-29.492 7.918,-52.58 23.754,-69.265c15.837,-16.685 36.279,-25.027 61.326,-25.027c16.402,0 31.189,3.919 44.359,11.756c13.17,7.838 23.209,18.766 30.117,32.784c6.909,14.019 10.363,29.916 10.363,47.691c-0,18.019 -3.636,34.138 -10.908,48.358c-7.272,14.221 -17.574,24.987 -30.905,32.3c-13.332,7.312 -27.714,10.968 -43.147,10.968c-16.725,-0 -31.673,-4.04 -44.843,-12.12c-13.17,-8.08 -23.149,-19.109 -29.936,-33.087c-6.787,-13.978 -10.18,-28.764 -10.18,-44.358Zm24.239,0.363c0,21.412 5.757,38.279 17.271,50.6c11.514,12.322 25.956,18.483 43.328,18.483c17.695,0 32.259,-6.221 43.692,-18.664c11.433,-12.443 17.149,-30.098 17.149,-52.964c0,-14.463 -2.444,-27.087 -7.332,-37.874c-4.889,-10.787 -12.039,-19.149 -21.452,-25.088c-9.413,-5.939 -19.978,-8.908 -31.693,-8.908c-16.645,0 -30.966,5.717 -42.965,17.15c-11.999,11.432 -17.998,30.521 -17.998,57.265Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path199" /><path
d="M7456.09,5775.14l-0,-20.846l75.264,-0.121l-0,65.932c-11.555,9.211 -23.472,16.139 -35.754,20.785c-12.281,4.646 -24.886,6.969 -37.813,6.969c-17.453,-0 -33.31,-3.737 -47.571,-11.211c-14.26,-7.474 -25.027,-18.28 -32.299,-32.42c-7.272,-14.14 -10.908,-29.936 -10.908,-47.389c0,-17.29 3.616,-33.43 10.848,-48.418c7.231,-14.988 17.634,-26.118 31.208,-33.39c13.574,-7.272 29.209,-10.908 46.904,-10.908c12.847,0 24.461,2.081 34.844,6.242c10.383,4.161 18.523,9.958 24.421,17.392c5.899,7.433 10.383,17.129 13.453,29.087l-21.209,5.818c-2.667,-9.05 -5.979,-16.16 -9.939,-21.331c-3.959,-5.171 -9.615,-9.312 -16.967,-12.423c-7.353,-3.111 -15.514,-4.666 -24.482,-4.666c-10.746,0 -20.038,1.636 -27.876,4.909c-7.837,3.272 -14.16,7.574 -18.967,12.907c-4.808,5.333 -8.545,11.191 -11.211,17.574c-4.525,10.988 -6.787,22.906 -6.787,35.753c0,15.837 2.727,29.088 8.181,39.753c5.454,10.665 13.392,18.584 23.815,23.755c10.423,5.171 21.493,7.756 33.208,7.756c10.181,0 20.119,-1.959 29.815,-5.878c9.696,-3.918 17.049,-8.1 22.058,-12.544l0,-33.087l-52.236,0Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path201" /></g><g
id="SELECT"><path
d="M5369.77,5385.62l22.18,-1.939c1.05,8.887 3.494,16.179 7.332,21.876c3.838,5.696 9.797,10.302 17.877,13.816c8.08,3.515 17.169,5.272 27.269,5.272c8.969,0 16.887,-1.333 23.755,-3.999c6.868,-2.667 11.978,-6.323 15.332,-10.969c3.353,-4.645 5.029,-9.716 5.029,-15.21c0,-5.575 -1.616,-10.443 -4.848,-14.604c-3.232,-4.161 -8.564,-7.656 -15.998,-10.484c-4.767,-1.858 -15.311,-4.747 -31.632,-8.665c-16.322,-3.919 -27.755,-7.616 -34.299,-11.09c-8.484,-4.444 -14.807,-9.958 -18.968,-16.544c-4.161,-6.585 -6.241,-13.957 -6.241,-22.118c-0,-8.969 2.545,-17.352 7.635,-25.149c5.09,-7.797 12.524,-13.715 22.3,-17.755c9.777,-4.04 20.644,-6.06 32.603,-6.06c13.17,0 24.785,2.121 34.844,6.363c10.059,4.242 17.796,10.483 23.209,18.725c5.414,8.241 8.323,17.574 8.727,27.997l-22.543,1.696c-1.212,-11.231 -5.313,-19.714 -12.302,-25.451c-6.989,-5.737 -17.311,-8.605 -30.966,-8.605c-14.22,-0 -24.583,2.606 -31.087,7.817c-6.504,5.212 -9.756,11.494 -9.756,18.846c-0,6.383 2.302,11.635 6.908,15.756c4.525,4.121 16.341,8.342 35.45,12.665c19.109,4.323 32.219,8.1 39.329,11.332c10.342,4.767 17.977,10.807 22.906,18.119c4.929,7.312 7.393,15.736 7.393,25.27c0,9.453 -2.707,18.361 -8.12,26.724c-5.414,8.363 -13.19,14.867 -23.331,19.513c-10.14,4.646 -21.553,6.969 -34.238,6.969c-16.079,-0 -29.552,-2.343 -40.419,-7.03c-10.868,-4.686 -19.392,-11.736 -25.573,-21.149c-6.181,-9.413 -9.433,-20.058 -9.757,-31.935Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path204" /><path
d="M5543.81,5442.71l0,-177.676l128.47,-0l0,20.967l-104.957,0l-0,54.418l98.291,-0l0,20.846l-98.291,-0l-0,60.478l109.078,-0l-0,20.967l-132.591,-0Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path206" /><path
d="M5707.91,5442.71l0,-177.676l23.513,-0l-0,156.709l87.504,-0l0,20.967l-111.017,-0Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path208" /><path
d="M5847.41,5442.71l-0,-177.676l128.469,-0l0,20.967l-104.957,0l0,54.418l98.291,-0l0,20.846l-98.291,-0l0,60.478l109.078,-0l0,20.967l-132.59,-0Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path210" /><path
d="M6139.25,5380.41l23.512,5.939c-4.928,19.311 -13.796,34.036 -26.603,44.176c-12.806,10.141 -28.461,15.211 -46.964,15.211c-19.149,-0 -34.723,-3.899 -46.722,-11.696c-11.998,-7.797 -21.128,-19.088 -27.39,-33.875c-6.262,-14.786 -9.393,-30.663 -9.393,-47.63c-0,-18.503 3.535,-34.643 10.605,-48.419c7.07,-13.776 17.129,-24.239 30.178,-31.39c13.049,-7.151 27.411,-10.726 43.086,-10.726c17.775,0 32.723,4.525 44.843,13.574c12.12,9.05 20.563,21.775 25.33,38.177l-23.148,5.454c-4.121,-12.927 -10.1,-22.34 -17.938,-28.239c-7.837,-5.898 -17.695,-8.847 -29.572,-8.847c-13.655,-0 -25.068,3.272 -34.238,9.817c-9.171,6.545 -15.615,15.331 -19.331,26.36c-3.717,11.029 -5.575,22.402 -5.575,34.118c-0,15.109 2.201,28.299 6.605,39.571c4.403,11.271 11.251,19.694 20.543,25.269c9.292,5.575 19.351,8.363 30.178,8.363c13.17,-0 24.32,-3.798 33.451,-11.393c9.13,-7.595 15.311,-18.866 18.543,-33.814Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path212" /><path
d="M6236.94,5442.71l0,-156.709l-58.538,0l-0,-20.967l140.832,-0l-0,20.967l-58.781,0l-0,156.709l-23.513,-0Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path214" /></g><g
id="START"><path
d="M7807.74,5385.62l22.179,-1.939c1.051,8.887 3.495,16.179 7.333,21.876c3.838,5.696 9.797,10.302 17.877,13.816c8.079,3.515 17.169,5.272 27.269,5.272c8.969,0 16.887,-1.333 23.755,-3.999c6.868,-2.667 11.978,-6.323 15.331,-10.969c3.354,-4.645 5.03,-9.716 5.03,-15.21c0,-5.575 -1.616,-10.443 -4.848,-14.604c-3.232,-4.161 -8.564,-7.656 -15.998,-10.484c-4.767,-1.858 -15.311,-4.747 -31.633,-8.665c-16.321,-3.919 -27.754,-7.616 -34.298,-11.09c-8.484,-4.444 -14.807,-9.958 -18.968,-16.544c-4.161,-6.585 -6.242,-13.957 -6.242,-22.118c0,-8.969 2.546,-17.352 7.636,-25.149c5.09,-7.797 12.524,-13.715 22.3,-17.755c9.777,-4.04 20.644,-6.06 32.602,-6.06c13.171,0 24.785,2.121 34.845,6.363c10.059,4.242 17.796,10.483 23.209,18.725c5.414,8.241 8.322,17.574 8.726,27.997l-22.542,1.696c-1.212,-11.231 -5.313,-19.714 -12.302,-25.451c-6.989,-5.737 -17.311,-8.605 -30.966,-8.605c-14.221,-0 -24.583,2.606 -31.087,7.817c-6.504,5.212 -9.757,11.494 -9.757,18.846c0,6.383 2.303,11.635 6.909,15.756c4.524,4.121 16.341,8.342 35.45,12.665c19.109,4.323 32.218,8.1 39.329,11.332c10.342,4.767 17.977,10.807 22.906,18.119c4.929,7.312 7.393,15.736 7.393,25.27c0,9.453 -2.707,18.361 -8.12,26.724c-5.414,8.363 -13.191,14.867 -23.331,19.513c-10.14,4.646 -21.553,6.969 -34.238,6.969c-16.079,-0 -29.552,-2.343 -40.42,-7.03c-10.867,-4.686 -19.391,-11.736 -25.572,-21.149c-6.181,-9.413 -9.433,-20.058 -9.757,-31.935Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path217" /><path
d="M8026.5,5442.71l0,-156.709l-58.538,0l-0,-20.967l140.831,-0l0,20.967l-58.78,0l-0,156.709l-23.513,-0Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path219" /><path
d="M8094.98,5442.71l68.234,-177.676l25.331,-0l72.718,177.676l-26.784,-0l-20.725,-53.812l-74.294,0l-19.513,53.812l-24.967,-0Zm51.267,-72.961l60.235,-0l-18.543,-49.206c-5.656,-14.948 -9.858,-27.23 -12.605,-36.845c-2.262,11.393 -5.454,22.705 -9.575,33.936l-19.512,52.115Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path221" /><path
d="M8280.41,5442.71l0,-177.676l78.779,-0c15.837,-0 27.875,1.596 36.117,4.787c8.241,3.192 14.826,8.827 19.755,16.907c4.929,8.08 7.393,17.008 7.393,26.785c0,12.605 -4.08,23.23 -12.241,31.875c-8.16,8.645 -20.765,14.14 -37.813,16.483c6.221,2.989 10.948,5.939 14.18,8.847c6.868,6.303 13.372,14.181 19.513,23.634l30.905,48.358l-29.572,-0l-23.513,-36.965c-6.868,-10.666 -12.523,-18.827 -16.967,-24.482c-4.444,-5.656 -8.424,-9.615 -11.938,-11.878c-3.515,-2.262 -7.09,-3.838 -10.726,-4.727c-2.667,-0.565 -7.03,-0.848 -13.09,-0.848l-27.269,0l-0,78.9l-23.513,-0Zm23.513,-99.261l50.539,-0c10.746,-0 19.15,-1.111 25.209,-3.333c6.06,-2.222 10.666,-5.777 13.817,-10.665c3.151,-4.889 4.727,-10.201 4.727,-15.938c-0,-8.403 -3.05,-15.311 -9.151,-20.725c-6.1,-5.413 -15.735,-8.12 -28.905,-8.12l-56.236,-0l-0,58.781Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path223" /><path
d="M8500.02,5442.71l-0,-156.709l-58.539,0l0,-20.967l140.832,-0l0,20.967l-58.781,0l0,156.709l-23.512,-0Z"
style="fill-rule:nonzero;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path225" /></g></g><g
id="Analógicos"><circle
cx="5363.15"
cy="7007.5"
r="1148.5"
style="fill:none;stroke:#000;stroke-width:62.5px;stroke-linecap:square;"
id="circle229" /><circle
cx="8680.15"
cy="7007.5"
r="1148.5"
style="fill:none;stroke:#000;stroke-width:62.5px;stroke-linecap:square;"
id="circle231" /><circle
cx="5363.15"
cy="7007.5"
r="867.5"
style="fill:#4d4d4d;stroke:#404040;stroke-width:62.5px;stroke-linecap:square;"
id="circle233" /><circle
cx="8680.15"
cy="7007.5"
r="867.5"
style="fill:#4d4d4d;stroke:#404040;stroke-width:62.5px;stroke-linecap:square;"
id="circle235" /></g><text
x="3265.86px"
y="2699.28px"
style="font-family:'ArialMT', 'Arial', sans-serif;font-size:286.779px;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="text238">L</text><text
x="10579.3px"
y="2699.28px"
style="font-family:'ArialMT', 'Arial', sans-serif;font-size:286.779px;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="text240">R</text></g></g></svg>

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -0,0 +1,372 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="100%"
height="100%"
viewBox="0 0 14044 9934"
version="1.1"
xml:space="preserve"
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;"
id="svg207"
sodipodi:docname="Digital.svg"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:serif="http://www.serif.com/"><defs
id="defs211" /><sodipodi:namedview
id="namedview209"
pagecolor="#ffffff"
bordercolor="#999999"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="0.063317898"
inkscape:cx="7028.0286"
inkscape:cy="4967"
inkscape:window-width="1920"
inkscape:window-height="1057"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg207" /><g
id="g327"><path
id="Base--Background-"
serif:id="Base (Background)"
d="M5465.29,6534c-405.109,0 -443.787,14.871 -511.634,86.341c-126.362,133.108 -912.097,1142.92 -1458.75,1855.75c-546.654,712.834 -1177.32,754.202 -1824,323c-646.677,-431.203 -497.113,-1201.6 -456,-1508c41.114,-306.399 188.619,-1499.22 238,-1781c49.382,-281.783 100.638,-1065.49 193,-1437c92.363,-371.512 158.273,-1152.75 553,-1607c394.728,-454.247 473.661,-678.27 584,-954c110.34,-275.731 33.858,-605 1146,-605c1112.14,-0 831.23,848.344 1012,1019c346.272,166.412 398,417 398,417l3436.41,-0c-0,-0 51.728,-250.588 398,-417c180.77,-170.656 -100.143,-1019 1012,-1019c1112.14,-0 1035.66,329.269 1146,605c110.34,275.73 189.273,499.753 584,954c394.727,454.246 460.637,1235.49 553,1607c92.363,371.511 143.618,1155.22 193,1437c49.382,281.782 196.886,1474.6 238,1781c41.114,306.398 190.678,1076.8 -456,1508c-646.678,431.202 -1277.35,389.834 -1824,-323c-487.936,-636.268 -1166.35,-1509.14 -1396.32,-1783.97c-27.675,-33.073 -48.855,-57.486 -62.428,-71.783c-60.507,-63.738 -98.797,-86.341 -392.561,-86.341l-3302.71,0Z"
style="fill:#b3b3b3;stroke:#000;stroke-width:62.5px;" /><g
id="Base"><path
d="M2079.91,3661.09c0,-0 205.726,-169.78 295,-296.752c52.939,-105.72 53.861,-485.219 88,-583.248c34.14,-98.03 124.145,-452 988,-452c863.856,-0 933.092,200.612 1047,584c113.909,383.387 82.114,526 816,526l1912.65,-0"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path3" /><path
d="M12034.3,3661.09c-0,-0 -205.726,-169.78 -295,-296.752c-52.938,-105.72 -53.86,-485.219 -88,-583.248c-34.14,-98.03 -124.145,-452 -988,-452c-863.855,-0 -933.091,200.612 -1047,584c-113.909,383.387 -82.114,526 -816,526l-1912.65,-0"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path5" /><path
d="M2339.91,3236.09l251,-1086c0,-0 80.11,-386 1069,-386c988.891,-0 1053,678.557 1053,806c0,127.442 -14.803,222 214,222l2299.65,-0"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path7" /><path
d="M11774.3,3236.09l-251,-1086c-0,-0 -80.109,-386 -1069,-386c-988.891,-0 -1053,678.557 -1053,806c-0,127.442 14.804,222 -214,222l-2299.65,-0"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path9" /><path
d="M4674.91,3265.09l254,-1257"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path11" /><path
d="M9439.31,3265.09l-254,-1257"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path13" /><path
d="M4883.91,2704.09l404,-311"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path15" /><path
d="M9230.31,2704.09l-404,-311"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path17" /><path
d="M4820.91,2913.09l154,445"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path19" /><path
d="M9293.31,2913.09l-154,445"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path21" /><path
d="M2461.91,2736.09c0,-0 -530.356,346.987 -727,968"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path23" /><path
d="M11652.3,2736.09c-0,-0 530.357,346.987 727,968"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path25" /><path
d="M2592.91,2143.09l67,-345"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path27" /><path
d="M11521.3,2143.09l-67,-345"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path29" /><path
d="M3629.91,8163.09l970,-1409"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path31" /><path
d="M10484.3,8163.09l-970,-1409"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path33" /><path
d="M5159.65,6442l3724,0"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path35" /><circle
cx="3556.91"
cy="4991.63"
r="1920"
style="fill:none;stroke:#000;stroke-width:41.67px;"
id="circle37" /><circle
cx="10557.3"
cy="4991.63"
r="1920"
style="fill:none;stroke:#000;stroke-width:41.67px;"
id="circle39" /><path
d="M4069.02,4447.63l-0,-986.947c-0,-53.208 -43.133,-96.34 -96.34,-96.34l-895.32,-0c-53.207,-0 -96.34,43.132 -96.34,96.34l-0,986.947l-987.66,-0c-25.551,-0 -50.055,10.15 -68.123,28.217c-18.067,18.068 -28.217,42.572 -28.217,68.123l-0,895.32c-0,25.551 10.15,50.055 28.217,68.123c18.068,18.067 42.572,28.217 68.123,28.217l987.66,-0l-0,988.372c-0,25.551 10.15,50.056 28.217,68.123c18.068,18.067 42.572,28.218 68.123,28.218l895.32,-0c25.551,-0 50.055,-10.151 68.123,-28.218c18.067,-18.067 28.217,-42.572 28.217,-68.123l-0,-988.372l987.66,-0c25.551,-0 50.055,-10.15 68.123,-28.217c18.067,-18.068 28.217,-42.572 28.217,-68.123l-0,-895.32c-0,-25.551 -10.15,-50.055 -28.217,-68.123c-18.068,-18.067 -42.572,-28.217 -68.123,-28.217l-987.66,-0Z"
style="fill:none;stroke:#000;stroke-width:41.67px;"
id="path41" /><path
d="M10045.2,4447.63c0,-0 0,-721.659 0,-986.947c0,-53.208 43.133,-96.34 96.341,-96.34c206.346,-0 688.973,-0 895.319,-0c53.208,-0 96.34,43.132 96.34,96.34l0,986.947l987.66,-0c25.551,-0 50.056,10.15 68.123,28.217c18.067,18.068 28.217,42.572 28.217,68.123c0,206.347 0,688.973 0,895.32c0,25.551 -10.15,50.055 -28.217,68.123c-18.067,18.067 -42.572,28.217 -68.123,28.217c-265.411,-0 -987.66,-0 -987.66,-0c0,-0 0,722.838 0,988.372c0,25.551 -10.15,50.056 -28.217,68.123c-18.067,18.067 -42.572,28.218 -68.123,28.218l-895.319,-0c-25.551,-0 -50.056,-10.151 -68.123,-28.218c-18.067,-18.067 -28.218,-42.572 -28.218,-68.123l0,-988.372l-987.659,-0c-25.551,-0 -50.056,-10.15 -68.123,-28.217c-18.067,-18.068 -28.218,-42.572 -28.218,-68.123l0,-895.32c0,-25.551 10.151,-50.055 28.218,-68.123c18.067,-18.067 42.572,-28.217 68.123,-28.217l987.659,-0Z"
style="fill:none;stroke:#000;stroke-width:41.67px;"
id="path43" /></g><g
id="Duckstation-Logo"
serif:id="Duckstation Logo"><path
d="M6547.88,5164.41c-0,14.441 -2.931,25.74 -8.793,33.895c-5.861,8.156 -15.673,12.234 -29.436,12.234l-70.34,-0l0,-178.655l70.34,0c13.763,0 23.575,4.12 29.436,12.361c5.862,8.24 8.793,19.921 8.793,35.043l-0,85.122Zm-26.76,-85.122c-0,-12.403 -1.529,-20.856 -4.587,-25.359c-3.059,-4.502 -8.071,-6.753 -15.037,-6.753l-35.425,-0l-0,148.071l35.425,0c6.966,0 11.978,-2.548 15.037,-7.646c3.058,-5.097 4.587,-12.827 4.587,-23.191l-0,-85.122Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path46" /><path
d="M6651.35,5195.25l0,-126.154l25.996,0l-0,141.446l-68.557,-0c-7.645,-0 -13.932,-0.765 -18.859,-2.294c-4.927,-1.529 -8.877,-4.035 -11.851,-7.518c-2.973,-3.483 -5.012,-7.943 -6.116,-13.38c-1.105,-5.437 -1.657,-12.149 -1.657,-20.134l0,-98.12l25.996,0l-0,99.139c-0,5.607 0.297,10.195 0.892,13.763c0.594,3.568 1.656,6.329 3.185,8.282c1.529,1.954 3.696,3.271 6.499,3.951c2.803,0.679 6.499,1.019 11.086,1.019l33.386,0Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path48" /><path
d="M6726.78,5168.23c-0,5.607 0.297,10.195 0.892,13.763c0.595,3.568 1.656,6.329 3.186,8.282c1.529,1.954 3.695,3.271 6.498,3.951c2.804,0.679 6.499,1.019 11.087,1.019l40.267,0l-0,15.292l-49.442,-0c-7.646,-0 -13.932,-0.765 -18.86,-2.294c-4.927,-1.529 -8.877,-4.035 -11.85,-7.518c-2.974,-3.483 -5.012,-7.943 -6.117,-13.38c-1.104,-5.437 -1.656,-12.149 -1.656,-20.134l-0,-54.794c-0,-7.816 0.552,-14.484 1.656,-20.006c1.105,-5.522 3.143,-10.025 6.117,-13.508c2.973,-3.483 6.923,-5.989 11.85,-7.518c4.928,-1.529 11.214,-2.294 18.86,-2.294l49.442,0l-0,15.292l-40.267,-0c-4.588,-0 -8.283,0.34 -11.087,1.019c-2.803,0.68 -4.969,1.996 -6.498,3.95c-1.53,1.954 -2.591,4.715 -3.186,8.283c-0.595,3.568 -0.892,8.156 -0.892,13.762l-0,56.833Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path50" /><path
d="M6909.01,5210.54l-30.838,-0l-44.09,-78.751l0,78.751l-25.995,-0l0,-183.752l25.995,0l0,97.61l48.933,-55.304l19.879,0l-45.11,51.481l51.226,89.965Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path52" /><path
d="M7020.12,5156.76c0,18.519 -3.143,32.112 -9.429,40.777c-6.287,8.665 -16.991,12.998 -32.112,12.998l-57.088,-0l0,-15.292l51.991,0c3.568,0 6.753,-0.425 9.557,-1.274c2.803,-0.85 5.097,-2.549 6.881,-5.097c1.784,-2.549 3.143,-6.074 4.078,-10.577c0.934,-4.502 1.401,-10.406 1.401,-17.712c0,-6.287 -0.339,-11.426 -1.019,-15.419c-0.68,-3.993 -1.911,-7.051 -3.695,-9.175c-1.784,-2.124 -4.248,-3.568 -7.391,-4.332c-3.144,-0.765 -7.264,-1.147 -12.361,-1.147l-19.369,-0c-6.456,-0 -11.893,-0.85 -16.311,-2.549c-4.417,-1.699 -7.985,-4.46 -10.704,-8.283c-2.718,-3.823 -4.672,-8.835 -5.861,-15.036c-1.19,-6.202 -1.784,-13.89 -1.784,-23.065c-0,-15.631 2.93,-27.822 8.792,-36.572c5.862,-8.75 16.014,-13.125 30.455,-13.125l49.697,0l0,15.292l-43.325,-0c-3.568,-0 -6.626,0.467 -9.175,1.401c-2.548,0.935 -4.715,2.549 -6.499,4.843c-1.784,2.293 -3.101,5.437 -3.95,9.429c-0.85,3.993 -1.274,9.048 -1.274,15.164c-0,5.947 0.255,10.832 0.764,14.655c0.51,3.822 1.487,6.796 2.931,8.919c1.444,2.124 3.526,3.611 6.244,4.46c2.719,0.85 6.371,1.275 10.959,1.275l18.095,-0c6.796,-0 12.7,0.679 17.712,2.039c5.012,1.359 9.133,3.822 12.361,7.39c3.228,3.568 5.607,8.581 7.136,15.037c1.529,6.456 2.293,14.782 2.293,24.976Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path54" /><path
d="M7100.15,5084.39l-35.425,-0l0,90.219c0,8.155 1.147,13.635 3.441,16.438c2.294,2.803 6.753,4.205 13.38,4.205l11.468,0l0,15.292l-21.917,-0c-6.117,-0 -11.256,-0.85 -15.419,-2.549c-4.163,-1.699 -7.476,-4.078 -9.94,-7.136c-2.463,-3.058 -4.247,-6.669 -5.352,-10.831c-1.104,-4.163 -1.656,-8.708 -1.656,-13.635l-0,-144.504l25.995,0l0,37.209l35.425,0l0,15.292Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path56" /><path
d="M7166.16,5125.67l0,14.782l-10.959,0c-4.587,0 -8.283,0.34 -11.086,1.019c-2.803,0.68 -4.97,1.742 -6.499,3.186c-1.529,1.444 -2.591,3.356 -3.186,5.734c-0.594,2.379 -0.892,5.352 -0.892,8.92l0,16.311c0,3.908 0.298,7.094 0.892,9.557c0.595,2.464 1.657,4.46 3.186,5.989c1.529,1.53 3.696,2.591 6.499,3.186c2.803,0.595 6.499,0.892 11.086,0.892l28.799,0l-0,-83.848c-0,-5.606 -0.297,-10.194 -0.892,-13.762c-0.595,-3.568 -1.657,-6.329 -3.186,-8.283c-1.529,-1.954 -3.695,-3.27 -6.499,-3.95c-2.803,-0.679 -6.498,-1.019 -11.086,-1.019l-36.699,-0l-0,-15.292l45.874,0c7.646,0 13.932,0.765 18.859,2.294c4.928,1.529 8.878,4.035 11.851,7.518c2.973,3.483 5.012,7.986 6.117,13.508c1.104,5.522 1.656,12.19 1.656,20.006l0,98.12l-63.969,-0c-7.645,-0 -13.932,-0.723 -18.859,-2.167c-4.927,-1.444 -8.877,-3.568 -11.851,-6.371c-2.973,-2.804 -5.012,-6.287 -6.116,-10.449c-1.105,-4.163 -1.657,-8.963 -1.657,-14.4l0,-18.094c0,-5.437 0.552,-10.237 1.657,-14.4c1.104,-4.162 3.143,-7.645 6.116,-10.449c2.974,-2.803 6.924,-4.927 11.851,-6.371c4.927,-1.445 11.214,-2.167 18.859,-2.167l20.134,0Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path58" /><path
d="M7294.86,5084.39l-35.425,-0l0,90.219c0,8.155 1.147,13.635 3.441,16.438c2.294,2.803 6.754,4.205 13.38,4.205l11.468,0l0,15.292l-21.917,-0c-6.117,-0 -11.256,-0.85 -15.419,-2.549c-4.163,-1.699 -7.476,-4.078 -9.939,-7.136c-2.464,-3.058 -4.248,-6.669 -5.352,-10.831c-1.105,-4.163 -1.657,-8.708 -1.657,-13.635l0,-144.504l25.995,0l0,37.209l35.425,0l0,15.292Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path60" /><path
d="M7337.17,5210.54l-25.996,-0l0,-141.446l25.996,0l-0,141.446Zm-0,-159.54l-25.996,-0l0,-24.467l25.996,0l-0,24.467Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path62" /><path
d="M7433.76,5069.09c7.646,0 13.932,0.765 18.859,2.294c4.928,1.529 8.878,4.035 11.851,7.518c2.974,3.483 5.012,7.986 6.117,13.508c1.104,5.522 1.656,12.19 1.656,20.006l0,54.794c0,7.985 -0.552,14.697 -1.656,20.134c-1.105,5.437 -3.143,9.897 -6.117,13.38c-2.973,3.483 -6.923,5.989 -11.851,7.518c-4.927,1.529 -11.213,2.294 -18.859,2.294l-34.151,-0c-7.645,-0 -13.932,-0.765 -18.859,-2.294c-4.927,-1.529 -8.878,-4.035 -11.851,-7.518c-2.973,-3.483 -5.012,-7.943 -6.116,-13.38c-1.105,-5.437 -1.657,-12.149 -1.657,-20.134l0,-54.794c0,-7.816 0.552,-14.484 1.657,-20.006c1.104,-5.522 3.143,-10.025 6.116,-13.508c2.973,-3.483 6.924,-5.989 11.851,-7.518c4.927,-1.529 11.214,-2.294 18.859,-2.294l34.151,0Zm-46.639,99.139c0,5.607 0.298,10.195 0.892,13.763c0.595,3.568 1.657,6.329 3.186,8.282c1.529,1.954 3.695,3.271 6.499,3.951c2.803,0.679 6.499,1.019 11.086,1.019l15.801,0c4.588,0 8.283,-0.34 11.086,-1.019c2.804,-0.68 4.97,-1.997 6.499,-3.951c1.529,-1.953 2.591,-4.714 3.186,-8.282c0.595,-3.568 0.892,-8.156 0.892,-13.763l0,-56.833c0,-5.606 -0.297,-10.194 -0.892,-13.762c-0.595,-3.568 -1.657,-6.329 -3.186,-8.283c-1.529,-1.954 -3.695,-3.27 -6.499,-3.95c-2.803,-0.679 -6.498,-1.019 -11.086,-1.019l-15.801,-0c-4.587,-0 -8.283,0.34 -11.086,1.019c-2.804,0.68 -4.97,1.996 -6.499,3.95c-1.529,1.954 -2.591,4.715 -3.186,8.283c-0.594,3.568 -0.892,8.156 -0.892,13.762l0,56.833Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path64" /><path
d="M7521.68,5084.39l0,126.154l-25.995,-0l0,-141.446l69.831,0c7.645,0 13.932,0.765 18.859,2.294c4.927,1.529 8.878,4.035 11.851,7.518c2.973,3.483 5.012,7.986 6.116,13.508c1.105,5.522 1.657,12.19 1.657,20.006l-0,98.12l-25.995,-0l-0,-99.14c-0,-5.606 -0.298,-10.194 -0.892,-13.762c-0.595,-3.568 -1.657,-6.329 -3.186,-8.283c-1.529,-1.954 -3.695,-3.27 -6.499,-3.95c-2.803,-0.679 -6.499,-1.019 -11.086,-1.019l-34.661,-0Z"
style="fill-rule:nonzero;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path66" /><g
id="Duck"><path
d="M7003.84,4795.95l-58.35,35.385"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path68" /><path
d="M6945.49,4715.11l-0,48.976l58.35,31.87l-0,70.067l-58.35,33.979"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path70" /><path
d="M7123.82,4609.89l-0,48.976l57.764,31.987"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path72" /><path
d="M7003.84,4682.07l-0,46.516l118.809,67.372l58.936,-33.041l-0,-69.598l-59.639,35.267l-61.162,-36.673l-0,-44.29"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path74" /><path
d="M6826.45,4675.04l-0,154.663l119.043,70.301l-0,-68.895l-61.162,-35.854l-0,-85.064"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path76" /><path
d="M6703.31,3977.65l93.97,-54.484"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path78" /><path
d="M6613.32,3923.16l89.985,-51.671l93.97,51.671l-0,103.46"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path80" /><path
d="M6703.31,4081.11l0,-104.398l-89.985,-53.546l-0,109.319l83.658,53.077"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path82" /><path
d="M7094.88,4431.44l82.252,-49.328"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path84" /><path
d="M7154.29,4311.23l0,56.552l146.461,85.222l0,-56.71"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path86" /><path
d="M7301.8,4226.16l-147.516,85.885l147.164,84.244l145.758,-84.596l-145.406,-85.533Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path88" /><path
d="M6920.19,4728.58l324.088,-190.164l-0,-117.755"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path90" /><path
d="M6596.1,4146.25l248.632,-145.875"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path92" /><path
d="M6920.19,4332.12l-0,396.458l-324.089,-188.201l0,-394.127l324.089,185.87Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path94" /><path
d="M7094.88,4125.98l250.155,-146.695"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path96" /><g
id="Camada2"><path
d="M6844.73,4287.68l-0,-308.857l250.155,-144.82l250.155,145.641l-0,271.714"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path98" /><path
d="M6844.73,4287.68l250.155,143.766l-0,-304.053l-250.155,-148.101"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path100" /></g><path
d="M7300.75,4453l146.461,-85.222l-0,-56.552"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path103" /><path
d="M7123.82,4728.23l-0,67.723"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path105" /><path
d="M6885.97,4795.95l59.522,-33.861"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path107" /><path
d="M7062.08,4691.44l61.748,-33.159"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path109" /><path
d="M7130.74,4227.22l-0,59.639l50.851,-28.707l-0,-60.107l-50.851,29.175Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path111" /><path
d="M7258.45,4155.63l0,59.639l50.851,-28.707l0,-60.107l-50.851,29.175Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path113" /></g></g><g
id="Controle"><g
id="D-Pad"><g
id="D-Pad1"
serif:id="D-Pad"><g
id="Botões"><path
d="M3931.66,5295.54c22.468,25.431 54.769,39.995 88.703,39.995c96.047,0 300.757,0 437.818,0c36.02,0 70.565,-14.309 96.035,-39.779c25.47,-25.47 39.779,-60.015 39.779,-96.035l0,-466.371c0,-36.02 -14.309,-70.565 -39.779,-96.035c-25.47,-25.471 -60.015,-39.78 -96.035,-39.78l-437.818,0c-33.934,0 -66.235,14.565 -88.703,39.996c-60.337,68.296 -183.002,207.14 -248.009,280.722c-24.364,27.578 -24.364,68.987 -0,96.565c65.007,73.582 187.672,212.426 248.009,280.722Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="path117" /><path
d="M3182.99,5386.2c-25.43,22.467 -39.995,54.769 -39.995,88.702c0,96.048 0,300.758 0,437.818c-0,36.02 14.309,70.565 39.779,96.035c25.47,25.47 60.015,39.779 96.035,39.779l466.372,0c36.02,0 70.565,-14.309 96.035,-39.779c25.47,-25.47 39.779,-60.015 39.779,-96.035l0,-437.818c0,-33.933 -14.565,-66.235 -39.995,-88.702c-68.297,-60.338 -207.141,-183.002 -280.723,-248.01c-27.578,-24.364 -68.986,-24.364 -96.564,0c-73.582,65.008 -212.426,187.672 -280.723,248.01Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="path119" /><path
d="M3092.34,5295.54c-22.468,25.431 -54.769,39.995 -88.703,39.995c-96.047,0 -300.757,0 -437.818,0c-36.02,0 -70.565,-14.309 -96.035,-39.779c-25.47,-25.47 -39.779,-60.015 -39.779,-96.035l-0,-466.371c-0,-36.02 14.309,-70.565 39.779,-96.035c25.47,-25.471 60.015,-39.78 96.035,-39.78l437.818,0c33.934,0 66.235,14.565 88.703,39.996c60.337,68.296 183.002,207.14 248.009,280.722c24.364,27.578 24.364,68.987 0,96.565c-65.007,73.582 -187.672,212.426 -248.009,280.722Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="path121" /><path
d="M3182.99,4546.87c-25.43,-22.467 -39.995,-54.769 -39.995,-88.703l0,-437.817c-0,-36.02 14.309,-70.565 39.779,-96.035c25.47,-25.471 60.015,-39.78 96.035,-39.78l466.372,0c36.02,0 70.565,14.309 96.035,39.78c25.47,25.47 39.779,60.015 39.779,96.035l0,437.817c0,33.934 -14.565,66.236 -39.995,88.703c-68.297,60.338 -207.141,183.002 -280.723,248.01c-27.578,24.364 -68.986,24.364 -96.564,-0c-73.582,-65.008 -212.426,-187.672 -280.723,-248.01Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="path123" /></g><path
d="M4971,4992.34l-232,262l0,-524l232,262Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path126" /><path
d="M2053,4992.34l232,262l-0,-524l-232,262Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path128" /><path
d="M3512,6451.34l-262,-232l524,-0l-262,232Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path130" /><path
d="M3512,3533.34l-262,232l524,-0l-262,-232Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path132" /></g></g><g
id="Botões1"
serif:id="Botões"><path
id="L1"
d="M3716.46,1657.09c-224.79,-5.299 -789,-13 -874,310c-131.822,500.923 -48.891,239 708,239c756.89,-0 803.273,397.046 917,-90c92,-394 -454,-452 -751,-459Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;" /><g
transform="matrix(-0.984917,-0.173029,0.173029,-0.984917,12490.4,9545.14)"
id="g139"><text
x="10012.2px"
y="6134.16px"
style="font-family:'Arial-BoldMT', 'Arial', sans-serif;font-weight:700;font-size:261.061px;fill:#e0e0e0;"
id="text137">1</text></g><path
id="R1"
d="M10397.8,1657.09c224.789,-5.299 789,-13 874,310c131.822,500.923 48.891,239 -708,239c-756.891,-0 -803.274,397.046 -917,-90c-92,-394 454,-452 751,-459Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;" /><g
transform="matrix(-0.984808,0.173648,-0.173648,-0.984808,28543,3539.01)"
id="g144"><text
x="17467.7px"
y="4924.1px"
style="font-family:'Arial-BoldMT', 'Arial', sans-serif;font-weight:700;font-size:261.061px;fill:#e0e0e0;"
id="text142">1</text></g><path
id="L2"
d="M3896.92,989.163c-224.789,-4.999 -789,-12.266 -874,292.496c-131.822,472.639 -48.891,225.505 708,225.505c756.891,-0 803.274,374.627 917,-84.919c92,-371.753 -454,-426.478 -751,-433.082Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;" /><g
transform="matrix(-0.992546,-0.121869,0.121869,-0.992546,13429,7704.48)"
id="g149"><text
x="10301.1px"
y="5347.56px"
style="font-family:'Arial-BoldMT', 'Arial', sans-serif;font-weight:700;font-size:261.061px;fill:#e0e0e0;"
id="text147">2</text></g><path
id="R2"
d="M10217.3,989.163c224.79,-4.999 789,-12.266 874,292.496c131.822,472.639 48.891,225.505 -708,225.505c-756.891,-0 -803.273,374.627 -917,-84.919c-92,-371.753 454,-426.478 751,-433.082Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;" /><g
transform="matrix(-0.992546,0.121869,-0.121869,-0.992546,27993.2,3452.28)"
id="g154"><text
x="17242px"
y="4488.21px"
style="font-family:'Arial-BoldMT', 'Arial', sans-serif;font-weight:700;font-size:261.061px;fill:#e0e0e0;"
id="text152">2</text></g></g><g
id="Botões2"
serif:id="Botões"><circle
cx="9539.7"
cy="4992.34"
r="461.5"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="circle157" /><path
d="M11050.7,3942.84c0,254.708 -206.791,461.5 -461.5,461.5c-254.708,-0 -461.5,-206.792 -461.5,-461.5c0,-254.709 206.792,-461.5 461.5,-461.5c254.709,-0 461.5,206.791 461.5,461.5Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="path159" /><circle
cx="11638.7"
cy="4992.34"
r="461.5"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="circle161" /><path
d="M11050.7,6041.84c0,254.708 -206.791,461.5 -461.5,461.5c-254.708,-0 -461.5,-206.792 -461.5,-461.5c0,-254.709 206.792,-461.5 461.5,-461.5c254.709,-0 461.5,206.791 461.5,461.5Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;"
id="path163" /><g
id="X"><path
d="M10811.9,5819.15l-445.385,445.385"
style="fill:none;stroke:#6f97e3;stroke-width:83.33px;"
id="path165" /><path
d="M10366.5,5819.15l445.385,445.385"
style="fill:none;stroke:#6f97e3;stroke-width:83.33px;"
id="path167" /></g><path
d="M10589.2,3628.81l252,504l-504,0l252,-504Z"
style="fill:none;stroke:#7ae0c4;stroke-width:83.33px;"
id="path170" /><circle
cx="11638.7"
cy="4978.68"
r="305.126"
style="fill:none;stroke:#ee676b;stroke-width:83.33px;"
id="circle172" /><rect
x="9297.17"
y="4749.81"
width="485.071"
height="485.071"
style="fill:none;stroke:#f37caa;stroke-width:83.33px;"
id="rect174" /></g><g
id="Botões-Centrais"
serif:id="Botões Centrais"><path
id="Select"
d="M6604,5599.73c-0,-62.812 -50.919,-113.731 -113.731,-113.731c-121.75,0 -313.788,0 -435.538,0c-62.812,0 -113.731,50.919 -113.731,113.731l-0,173.538c0,62.812 50.919,113.731 113.731,113.731l435.538,0c62.812,-0 113.731,-50.919 113.731,-113.731l-0,-173.538Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;" /><path
id="Start"
d="M8078.86,5671.43c18.696,6.583 31.202,24.247 31.202,44.068c0,19.821 -12.506,37.485 -31.202,44.068c-150.687,53.064 -397.808,140.086 -512.618,180.515c-14.296,5.034 -30.146,2.821 -42.516,-5.938c-12.37,-8.758 -19.723,-22.973 -19.723,-38.13c0,-94.325 0,-266.705 0,-361.03c-0,-15.157 7.353,-29.372 19.723,-38.13c12.37,-8.759 28.22,-10.972 42.516,-5.938c114.81,40.429 361.931,127.451 512.618,180.515Z"
style="fill:#595959;stroke:#404040;stroke-width:41.67px;" /></g><text
id="L"
x="3394.97px"
y="2739.28px"
style="font-family:'ArialMT', 'Arial', sans-serif;font-size:286.779px;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;">L</text><text
id="R"
x="10437.5px"
y="2739.28px"
style="font-family:'ArialMT', 'Arial', sans-serif;font-size:286.779px;stroke:#63112e;stroke-width:1px;stroke-linecap:butt;stroke-miterlimit:2;">R</text><g
id="Select1"
serif:id="Select"><path
d="M5701.16,6158.8l39.778,-3.86c2.394,13.328 7.251,23.117 14.571,29.367c7.321,6.25 17.196,9.375 29.627,9.375c13.167,-0 23.089,-2.78 29.765,-8.341c6.676,-5.561 10.013,-12.064 10.013,-19.509c0,-4.78 -1.404,-8.847 -4.212,-12.202c-2.809,-3.355 -7.712,-6.273 -14.71,-8.755c-4.788,-1.654 -15.699,-4.595 -32.734,-8.823c-21.915,-5.423 -37.292,-12.087 -46.132,-19.992c-12.431,-11.121 -18.646,-24.679 -18.646,-40.672c-0,-10.294 2.923,-19.922 8.77,-28.884c5.847,-8.961 14.273,-15.786 25.276,-20.474c11.004,-4.687 24.286,-7.031 39.848,-7.031c25.414,0 44.543,5.561 57.388,16.682c12.845,11.122 19.59,25.966 20.235,44.533l-40.884,1.792c-1.749,-10.386 -5.501,-17.854 -11.256,-22.404c-5.755,-4.55 -14.388,-6.825 -25.898,-6.825c-11.878,0 -21.178,2.436 -27.9,7.308c-4.327,3.125 -6.491,7.307 -6.491,12.546c-0,4.779 2.025,8.87 6.077,12.27c5.156,4.32 17.679,8.824 37.568,13.512c19.89,4.687 34.599,9.536 44.129,14.545c9.531,5.01 16.989,11.857 22.376,20.543c5.386,8.686 8.08,19.417 8.08,32.193c-0,11.581 -3.223,22.427 -9.669,32.538c-6.445,10.11 -15.561,17.624 -27.347,22.542c-11.786,4.917 -26.473,7.376 -44.06,7.376c-25.598,-0 -45.257,-5.906 -58.977,-17.717c-13.72,-11.811 -21.915,-29.022 -24.585,-51.633Z"
style="fill-rule:nonzero;"
id="path182" /><path
d="M5900.19,6224.57l-0,-202.119l150.135,-0l0,34.192l-109.252,-0l-0,44.808l101.656,0l-0,34.054l-101.656,0l-0,55.011l113.12,-0l-0,34.054l-154.003,0Z"
style="fill-rule:nonzero;"
id="path184" /><path
d="M6089.96,6224.57l-0,-200.465l40.883,0l-0,166.411l101.656,-0l-0,34.054l-142.539,0Z"
style="fill-rule:nonzero;"
id="path186" /><path
d="M6261.64,6224.57l-0,-202.119l150.136,-0l-0,34.192l-109.253,-0l0,44.808l101.656,0l0,34.054l-101.656,0l0,55.011l113.12,-0l-0,34.054l-154.003,0Z"
style="fill-rule:nonzero;"
id="path188" /><path
d="M6579.87,6150.25l39.64,12.547c-6.077,22.059 -16.183,38.443 -30.317,49.151c-14.134,10.708 -32.067,16.062 -53.798,16.062c-26.887,-0 -48.986,-9.169 -66.297,-27.505c-17.311,-18.337 -25.966,-43.407 -25.966,-75.209c-0,-33.641 8.701,-59.767 26.104,-78.38c17.403,-18.613 40.285,-27.919 68.646,-27.919c24.769,0 44.888,7.307 60.358,21.922c9.208,8.639 16.114,21.048 20.718,37.225l-40.469,9.651c-2.394,-10.478 -7.39,-18.751 -14.986,-24.817c-7.597,-6.066 -16.828,-9.1 -27.693,-9.1c-15.009,0 -27.187,5.377 -36.533,16.131c-9.346,10.754 -14.019,28.172 -14.019,52.254c0,25.552 4.604,43.751 13.812,54.597c9.208,10.846 21.178,16.268 35.911,16.268c10.866,0 20.212,-3.446 28.038,-10.34c7.827,-6.893 13.444,-17.739 16.851,-32.538Z"
style="fill-rule:nonzero;"
id="path190" /><path
d="M6700.17,6224.57l-0,-167.927l-60.082,-0l-0,-34.192l160.909,-0l0,34.192l-59.944,-0l0,167.927l-40.883,0Z"
style="fill-rule:nonzero;"
id="path192" /></g><g
id="Start1"
serif:id="Start"><path
d="M7354.14,6158.8l39.779,-3.86c2.394,13.328 7.251,23.117 14.571,29.367c7.321,6.25 17.196,9.375 29.627,9.375c13.167,-0 23.089,-2.78 29.765,-8.341c6.675,-5.561 10.013,-12.064 10.013,-19.509c0,-4.78 -1.404,-8.847 -4.212,-12.202c-2.809,-3.355 -7.712,-6.273 -14.71,-8.755c-4.788,-1.654 -15.7,-4.595 -32.734,-8.823c-21.915,-5.423 -37.293,-12.087 -46.132,-19.992c-12.431,-11.121 -18.646,-24.679 -18.646,-40.672c-0,-10.294 2.923,-19.922 8.77,-28.884c5.847,-8.961 14.273,-15.786 25.276,-20.474c11.004,-4.687 24.286,-7.031 39.847,-7.031c25.414,0 44.544,5.561 57.389,16.682c12.845,11.122 19.59,25.966 20.235,44.533l-40.884,1.792c-1.749,-10.386 -5.502,-17.854 -11.257,-22.404c-5.754,-4.55 -14.387,-6.825 -25.897,-6.825c-11.878,0 -21.178,2.436 -27.9,7.308c-4.328,3.125 -6.492,7.307 -6.492,12.546c0,4.779 2.026,8.87 6.078,12.27c5.156,4.32 17.679,8.824 37.568,13.512c19.889,4.687 34.599,9.536 44.129,14.545c9.53,5.01 16.989,11.857 22.376,20.543c5.386,8.686 8.08,19.417 8.08,32.193c-0,11.581 -3.223,22.427 -9.669,32.538c-6.445,10.11 -15.561,17.624 -27.347,22.542c-11.787,4.917 -26.473,7.376 -44.061,7.376c-25.598,-0 -45.257,-5.906 -58.976,-17.717c-13.72,-11.811 -21.915,-29.022 -24.586,-51.633Z"
style="fill-rule:nonzero;"
id="path195" /><path
d="M7598.75,6224.57l-0,-167.927l-60.082,-0l-0,-34.192l160.909,-0l-0,34.192l-59.944,-0l0,167.927l-40.883,0Z"
style="fill-rule:nonzero;"
id="path197" /><path
d="M7887.55,6224.57l-44.474,0l-17.679,-45.911l-80.938,-0l-16.713,45.911l-43.369,0l78.866,-202.119l43.231,-0l81.076,202.119Zm-75.275,-79.965l-27.9,-75.002l-27.348,75.002l55.248,-0Z"
style="fill-rule:nonzero;"
id="path199" /><path
d="M7909.38,6224.57l0,-202.119l86.048,-0c21.639,-0 37.362,1.815 47.168,5.446c9.807,3.63 17.657,10.087 23.55,19.371c5.893,9.283 8.839,19.899 8.839,31.848c0,15.166 -4.466,27.689 -13.397,37.57c-8.932,9.881 -22.284,16.108 -40.055,18.681c8.84,5.148 16.137,10.8 21.892,16.959c5.755,6.158 13.513,17.096 23.273,32.813l24.723,39.431l-48.894,0l-29.557,-43.981c-10.497,-15.717 -17.68,-25.621 -21.547,-29.711c-3.867,-4.09 -7.965,-6.894 -12.293,-8.41c-4.327,-1.517 -11.187,-2.275 -20.579,-2.275l-8.288,-0l0,84.377l-40.883,0Zm40.883,-116.639l30.249,-0c19.613,-0 31.859,-0.827 36.739,-2.482c4.881,-1.654 8.702,-4.503 11.464,-8.548c2.763,-4.044 4.144,-9.099 4.144,-15.166c-0,-6.801 -1.819,-12.293 -5.456,-16.475c-3.637,-4.182 -8.77,-6.825 -15.4,-7.928c-3.315,-0.459 -13.26,-0.689 -29.834,-0.689l-31.906,-0l0,51.288Z"
style="fill-rule:nonzero;"
id="path201" /><path
d="M8159.1,6224.57l-0,-167.927l-60.082,-0l0,-34.192l160.909,-0l0,34.192l-59.944,-0l0,167.927l-40.883,0Z"
style="fill-rule:nonzero;"
id="path203" /></g></g></g></svg>

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -0,0 +1,466 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="100%"
height="100%"
viewBox="0 0 14044 9934"
version="1.1"
xml:space="preserve"
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;"
id="svg281"
sodipodi:docname="NamcoGun - DuckStation.svg"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:serif="http://www.serif.com/"><defs
id="defs285" /><sodipodi:namedview
id="namedview283"
pagecolor="#ffffff"
bordercolor="#999999"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="0.063317898"
inkscape:cx="7028.0286"
inkscape:cy="4967"
inkscape:window-width="1920"
inkscape:window-height="1057"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg281" /><g
id="g439"><path
id="Background"
d="M2377,2184.1c-115.918,0 -384.008,-4.612 -418,0c-125.303,17 -619.626,1035.52 -467,1139.9c99.068,67.753 138.916,25.61 146,36c7.084,10.39 -167.476,270.784 -30,270c1285.19,-7.332 1014.64,1083.07 978,1154c-249.839,483.616 -654.595,697.598 -1066.55,1946c-288.331,873.757 -418.429,1688.57 117.329,1810.58c17.663,114.63 106.091,419.058 106.091,419.058l1448.14,26.523c-0,0 40.462,-79.966 58.967,-105.215c108.116,19.728 337.905,-136.275 420.469,-423.076c-56.491,-72.787 -76.221,-217.893 -78.937,-321.098c-2.716,-103.205 667.122,-2637.75 667.122,-2637.75c0,0 218.064,-237.27 304.973,-248.134c86.91,-10.864 135.797,-43.455 271.593,5.432c135.796,48.886 879.959,206.41 1333.52,89.625l1516.43,0c-0,0 -2.716,-460.306 27.159,-577.091c59.75,-173.819 95.057,-214.558 706.14,-214.558l-0,153.391l541.67,537.1l213.464,0l36.937,-38.971l356.329,-0l34.764,32.591l123.846,-0l34.764,-45.628l336.774,0l52.146,52.146l106.464,-0l49.973,-58.664l323.738,-0l56.491,58.664l178.164,-0l39.11,-54.319l97.773,0l27.706,48.486l845.331,-0l339.49,-383.624l0,-312.331l149.376,-3.395l64.503,-254.618l203.694,0l0,-1195.34l-246.262,-13.58l0,-350.354l38.023,-35.307l206.41,0l0,-1025.25l-225.877,-13.58c-0,-0 6.789,-278.382 -298.752,-298.751l-146.778,-0c-0,-0 -385.35,-278.924 -404.039,-2.073l-1577.9,0l0,127.598l-4592.07,-0l0,-110.696l-1481.87,-0l-134.02,-168.414l-510.332,-5.562l-73.699,-148.789l-186.334,-13.906l-76.48,326.78c-0,-0 -288.581,13.955 -543.962,826.198Zm4611.32,2319.16c-0,-330.707 -268.493,-599.2 -599.2,-599.2l-1018.47,0c-330.707,0 -599.2,268.493 -599.2,599.2c0,330.707 268.493,599.2 599.2,599.2l1018.47,-0c330.707,-0 599.2,-268.493 599.2,-599.2Z"
style="fill:#b3b3b3;" /><g
id="Gatilho"><g
id="Camada7"><path
d="M5674.9,3911.33c0,0 -187.103,264.439 -174.629,476.489c12.473,212.05 -29.937,324.312 192.092,623.677l-623.677,-0c0,-0 -162.155,-112.262 -189.597,-169.64c-27.442,-57.378 -114.757,-197.082 -109.767,-301.86c4.989,-104.777 27.442,-269.428 77.336,-341.774c49.894,-72.347 182.113,-239.492 379.195,-279.407c197.082,-39.916 449.047,-7.485 449.047,-7.485Z"
style="fill:#666;"
id="path3" /></g><path
d="M5684,3903c0,-0 -192,206.245 -192,556c0,349.755 206.772,558.685 207,559c0.228,0.315 -626,0 -626,0"
style="fill:#666;stroke:#404040;stroke-width:41.67px;"
id="path6" /><circle
cx="5152"
cy="4252"
r="130"
style="fill:none;stroke:#404040;stroke-width:23.61px;"
id="circle8" /><circle
cx="5152"
cy="4652"
r="166"
style="fill:none;stroke:#404040;stroke-width:23.61px;"
id="circle10" /></g><g
id="Pistola"><g
id="Camada1"><path
d="M2311,2721c136.932,-1352.35 625,-1358 625,-1358l2455,0c0,0 0.312,120.095 0,120c-0.312,-0.095 4583,0 4583,0l0,-122l2132,0c174.137,0 306,138.677 306,351c0,212.323 -6.672,1007.66 -6.672,1007.66c0,-0 -8715.57,1.339 -10094.3,1.339Z"
style="fill:none;stroke:#000;stroke-width:62.5px;"
id="path13" /><path
d="M4583.96,2851.45c5.052,-16.527 1.969,-34.47 -8.31,-48.362c-10.28,-13.891 -26.537,-22.086 -43.819,-22.086c-316.772,0 -1547.08,0 -1547.08,0c0,0 -272.042,889.81 -361.421,1182.15c-6.587,21.546 -2.567,44.939 10.834,63.05c13.402,18.111 34.598,28.795 57.128,28.795l1524.71,0c0,0 286.252,-936.288 367.963,-1203.55Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path15" /><path
d="M10730,1959.27c0,-34.816 -13.83,-68.205 -38.449,-92.823c-24.618,-24.619 -58.007,-38.449 -92.823,-38.449c-529.595,0 -2505.86,0 -3035.46,0c-34.816,-0 -68.205,13.83 -92.823,38.449c-24.619,24.618 -38.449,58.007 -38.449,92.823l0,362.456c-0,34.816 13.83,68.205 38.449,92.823c24.618,24.619 58.007,38.449 92.823,38.449c529.595,0 2505.86,0 3035.46,0c34.816,0 68.205,-13.83 92.823,-38.449c24.619,-24.618 38.449,-58.007 38.449,-92.823c0,-106.511 0,-255.945 0,-362.456Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path17" /><path
d="M5867,2992.5c-0,-51.639 -41.861,-93.5 -93.5,-93.5c-199.937,0 -667.063,0 -867,0c-51.639,0 -93.5,41.861 -93.5,93.5l0,0c0,51.639 41.861,93.5 93.5,93.5c199.937,0 667.063,0 867,0c51.639,-0 93.5,-41.861 93.5,-93.5c0,0 0,0 0,-0Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path19" /><path
d="M3876,2708.14l374,-1063.73"
style="fill:none;stroke:#000;stroke-width:33.33px;stroke-linecap:butt;"
id="path21" /><path
d="M5024,2708.14l374,-1063.73"
style="fill:none;stroke:#000;stroke-width:33.33px;stroke-linecap:butt;"
id="path23" /><path
d="M4256,2708.14l374,-1063.73"
style="fill:none;stroke:#000;stroke-width:33.33px;stroke-linecap:butt;"
id="path25" /><path
d="M5404,2708.14l374,-1063.73"
style="fill:none;stroke:#000;stroke-width:33.33px;stroke-linecap:butt;"
id="path27" /><path
d="M4641,2708.14l374,-1063.73"
style="fill:none;stroke:#000;stroke-width:33.33px;stroke-linecap:butt;"
id="path29" /><path
d="M5789,2708.14l374,-1063.73"
style="fill:none;stroke:#000;stroke-width:33.33px;stroke-linecap:butt;"
id="path31" /><path
d="M4066,2708.14l374,-1063.73"
style="fill:none;stroke:#000;stroke-width:33.33px;stroke-linecap:butt;"
id="path33" /><path
d="M5214,2708.14l374,-1063.73"
style="fill:none;stroke:#000;stroke-width:33.33px;stroke-linecap:butt;"
id="path35" /><path
d="M4446,2708.14l374,-1063.73"
style="fill:none;stroke:#000;stroke-width:33.33px;stroke-linecap:butt;"
id="path37" /><path
d="M5594,2708.14l374,-1063.73"
style="fill:none;stroke:#000;stroke-width:33.33px;stroke-linecap:butt;"
id="path39" /><path
d="M4831,2708.14l374,-1063.73"
style="fill:none;stroke:#000;stroke-width:33.33px;stroke-linecap:butt;"
id="path41" /><g
id="g48"><g
id="g344" /><g
id="g348" /><g
id="g352" /><path
d="M6990.65,4501.5c-0.001,-330.543 -267.958,-598.5 -598.5,-598.5c-317.689,0 -706.966,0 -1024.65,0c-330.542,0 -598.5,267.958 -598.5,598.5l0,0c0,330.543 267.958,598.5 598.5,598.5c317.688,0 706.965,0 1024.65,0c330.542,-0 598.499,-267.957 598.5,-598.5c-0,0 -0,0 -0,-0Z"
style="fill:none;stroke:#000;stroke-width:52.12px;"
id="path46" /></g><path
d="M4548.03,3601.27l1357,0l240,-752c-0,0 9.384,-52 -60,-52l-1121,0"
style="fill:none;stroke:#000;stroke-width:23.61px;"
id="path50" /><circle
cx="7209.65"
cy="2930"
r="183"
style="fill:none;stroke:#000;stroke-width:23.61px;"
id="circle52" /><circle
cx="7545.5"
cy="3267.5"
r="90.5"
style="fill:none;stroke:#000;stroke-width:23.61px;"
id="circle54" /><circle
cx="7328.5"
cy="3983.5"
r="106.5"
style="fill:none;stroke:#000;stroke-width:23.61px;"
id="circle56" /><path
d="M2620.22,1646l9791.78,0"
style="fill:none;stroke:#000;stroke-width:23.61px;"
id="path58" /><path
d="M6749,1646l0,1002c0,0 4.592,61 -137,61"
style="fill:none;stroke:#000;stroke-width:23.61px;"
id="path60" /><path
d="M4481.31,4655c140.745,37.052 224.931,181.4 187.879,322.144c-37.051,140.745 -181.399,224.931 -322.144,187.879"
style="fill:none;stroke:#000;stroke-width:33.33px;"
id="path62" /><path
d="M2735.59,4089.2c0,-0 158.497,131.158 158.497,474.451c0,343.293 -317.691,498.194 -486.852,766.13c-169.16,267.936 -505.604,808.636 -717.054,1567.44c-211.451,758.803 -184.633,1082.21 -184.633,1186.87c0,104.662 24.756,175.833 313.566,175.833l1050.61,-0c-0,-0 147.195,8.678 195.245,-120.876c52.613,-141.856 1125.71,-4044.26 1125.71,-4044.26c-0,0 6.077,-39.66 -41.242,-39.66l-1399.28,-0c0,-0 -46.44,3.282 -14.562,34.068Z"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path64" /><rect
x="2219.86"
y="2770.66"
width="491.942"
height="117.904"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="rect66" /><rect
x="2219.86"
y="2807.41"
width="491.951"
height="44.408"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="rect68" /><path
d="M2221.19,2892.55l-70.471,115.193c0,0 -5.421,13.552 13.552,25.749c18.973,12.197 218.19,116.548 218.19,116.548"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path70" /><path
d="M3435.8,8788.77c0,0 -406.96,-148.888 -241.529,-757.674c165.431,-608.786 1234.96,-4431.17 1234.96,-4431.17l122.19,-0l-86.247,314.086l167.138,-2.747"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path72" /><path
d="M5888.95,3602.37l446.714,-0c-0,-0 564.299,-41.754 848.423,571.666c6.184,13.428 19.617,22.031 34.4,22.031c162.938,0.017 396.445,0.017 465.485,0.017c11.014,-0 19.942,-8.929 19.942,-19.942l-0,-920.25l103.493,-0l149.099,-526.234"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path74" /><rect
x="7705.28"
y="3256.02"
width="733.733"
height="767.131"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="rect76" /><path
d="M6992.01,4531.09l1447.14,-0l0,-260.193l-1488.07,-0"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path78" /><path
d="M5482.06,3898.55l-998.67,0"
style="fill:none;stroke:#000;stroke-width:41.67px;"
id="path80" /><path
d="M8418.32,4531.16l0,181.494l525.344,525.809l241.364,-0l28.066,-37.421l362.982,-0l16.839,33.679l127.231,-0l26.195,-34.266l362.745,0l26.823,38.29l122.621,-0l24.907,-42.151l359.105,-0l26.344,43.367l201.175,-0l31.134,-38.319l-0,-1001.72"
style="fill:none;stroke:#000;stroke-width:62.5px;stroke-linecap:butt;"
id="path82" /><path
d="M10994.4,4200.17l-0,982.295l31.396,59.965l844.292,0l343.413,-375.165l-0,-879.213"
style="fill:none;stroke:#000;stroke-width:62.5px;stroke-linecap:butt;"
id="path84" /><path
d="M12237.3,3996.64l-899.348,-903.997"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path86" /><path
d="M12234.3,3993.38l-918.336,-0l253.781,106.76l539.641,-0l99.473,-106.76"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path88" /><path
d="M12113.5,4100.13l-0,696.525l-235.502,259.45l-862.174,0"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path90" /><path
d="M10886.2,5057.68l-1828.65,-0l-434.455,-424.886l-0,-1374.62l2882.14,-0"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path92" /><path
d="M9060.28,5058.7l-102.183,153.275"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path94" /><path
d="M8622.2,4631.87l-199.257,73.573"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path96" /><path
d="M11877.6,5057.96l-17.563,172.434"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path98" /><path
d="M12117,4790.68l80.469,72.806"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path100" /><path
d="M10910.5,5187.53l85.578,0"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path102" /><path
d="M11502.6,3249.48l902.089,-0"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path104" /><path
d="M12383.1,2733.37l0,526.536"
style="fill:none;stroke:#000;stroke-width:62.5px;stroke-linecap:butt;"
id="path106" /><path
d="M12395.5,3082.84l233.88,0l-0,1206.82l-221.406,-0"
style="fill:none;stroke:#000;stroke-width:62.5px;stroke-linecap:butt;"
id="path108" /><path
d="M12226.3,4025.18l180.866,0l0,277.537l-49.894,243.234l-121.617,0"
style="fill:none;stroke:#000;stroke-width:62.5px;stroke-linecap:butt;"
id="path110" /><path
d="M12231.4,4289.66l164.447,-0"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path112" /><path
d="M10048,3745.07c0,-26.995 -10.723,-52.884 -29.812,-71.972c-19.088,-19.088 -44.977,-29.812 -71.972,-29.812l-1031.81,-0c-26.995,-0 -52.884,10.724 -71.972,29.812c-19.089,19.088 -29.812,44.977 -29.812,71.972l-0,281.404c-0,26.995 10.723,52.884 29.812,71.972c19.088,19.088 44.977,29.812 71.972,29.812c232.326,-0 799.488,-0 1031.81,-0c26.995,-0 52.884,-10.724 71.972,-29.812c19.089,-19.088 29.812,-44.977 29.812,-71.972c0,-82.679 0,-198.725 0,-281.404Z"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path114" /><path
d="M9986.09,3831.88c0,-51.254 -41.549,-92.803 -92.803,-92.803l-922.045,-0c-51.254,-0 -92.804,41.549 -92.804,92.803l0,115.755c0,51.254 41.55,92.803 92.804,92.803l922.045,0c51.254,0 92.803,-41.549 92.803,-92.803l0,-115.755Z"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path116" /><path
d="M9000.18,4128.26l0,191.594l512.913,-0l107.772,-193.59"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path118" /><g
id="g134"><path
d="M7066.23,2880.26l287.02,-0"
style="fill:none;stroke:#000;stroke-width:16.67px;"
id="path120" /><path
d="M7066.23,2978.36l287.02,0"
style="fill:none;stroke:#000;stroke-width:16.67px;"
id="path122" /><path
d="M7095.65,2830.31l227.981,-0"
style="fill:none;stroke:#000;stroke-width:16.67px;"
id="path124" /><path
d="M7095.65,3028.32l227.981,0"
style="fill:none;stroke:#000;stroke-width:16.67px;"
id="path126" /><path
d="M7147.91,2785.8l124.436,-0"
style="fill:none;stroke:#000;stroke-width:16.67px;"
id="path128" /><path
d="M7059.16,2929.31l302.026,-0"
style="fill:none;stroke:#000;stroke-width:16.67px;"
id="path130" /><path
d="M7147.91,3072.82l124.436,-0"
style="fill:none;stroke:#000;stroke-width:16.67px;"
id="path132" /></g></g><g
id="Camada2"><path
d="M2920,1361c0,0 50.93,-331.074 87,-331c64.505,0.132 179,0 179,0l66,165l529,0l117,149"
style="fill:none;stroke:#000;stroke-width:62.5px;"
id="path137" /></g><path
d="M11552,1337.65c0,-0 -0.076,-263.706 427,23.353"
style="fill:none;stroke:#000;stroke-width:23.75px;"
id="path140" /><g
id="Camada3"><g
id="g148"><path
d="M6998.36,3297.01c-118.667,-52.609 -201.889,-174.622 -201.889,-316.592c0,-15.129 0.945,-30.032 2.778,-44.648"
style="fill:none;stroke:#000;stroke-width:23.75px;"
id="path142" /><path
d="M7093.08,3148.49c-74.499,-17.05 -130.294,-85.868 -130.294,-168.066c0,-14.515 1.74,-28.613 5.016,-42.082m-0,0l-167.881,-2.653"
style="fill:none;stroke:#000;stroke-width:23.75px;"
id="path144" /><path
d="M7093.4,3148.75l-94.036,147.465"
style="fill:none;stroke:#000;stroke-width:23.75px;"
id="path146" /></g></g><g
id="Camada4"><path
d="M2799,2729c126.231,515.191 -119,565 -119,565l-559,-233c0,0 -95.659,161.403 -473,303c-90.538,86.341 -75.394,251.58 -31,265c44.394,13.42 841.91,-53.165 1003,634c161.09,687.165 -468.928,911.797 -822,1747c-353.072,835.203 -847.557,2349.5 -228,2497c679.025,161.658 1744,377 1744,377c0,0 187.855,-49.398 340,-350c45.252,-111.483 -125.678,-176.749 -46,-507c79.365,-328.955 1028.37,-4112.63 1028.37,-4112.63"
style="fill:none;stroke:#000;stroke-width:62.5px;"
id="path151" /><path
d="M8594.26,3104l-157.139,-142.521l-0,-160.794l2835.81,0l0,226.573l78.264,78.264l-2756.93,-1.522Zm-157.139,-193.463l2835.81,-0"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path153" /><path
d="M8435.34,3253.29l160.91,-144.07"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path155" /><path
d="M8439.06,4014.95l0,284.398"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path157" /><path
d="M8508.13,2802.85l46.334,24.949l2636.79,0l37.562,-24.939l44.635,0l0,105.684l-80.366,-42.575l-2641.67,-0l-93.378,42.363l-20.665,0l-0,-105.624l70.76,0.142Z"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path159" /><path
d="M8553.74,2829.55l0,33.742"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path161" /><path
d="M11191.8,2828.65l-0,35.695"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path163" /></g><g
id="Camada10"><path
d="M7705.28,3274.32c49.082,85.668 80.722,220.044 80.722,371.007c-0,150.963 -31.64,285.339 -80.722,371.007"
style="fill:none;stroke:#000;stroke-width:20.83px;"
id="path166" /></g><g
id="Camada9" /><g
id="Camada5"><path
d="M1641,8531l95,432.596c0,0 1338.72,33.81 1437,22.46c55.242,-20.486 47.336,-75.49 70,-99.605"
style="fill:none;stroke:#000;stroke-width:62.5px;"
id="path170" /><path
d="M4216,5606c0,0 184.64,-448.481 592.431,-353.463c407.791,95.018 734.53,208.261 1357.12,91.602l1514.43,-0c0,-0 6.549,-176.096 13.94,-374.835c15.241,-409.821 98.842,-413.736 721.87,-413.736"
style="fill:none;stroke:#000;stroke-width:62.5px;"
id="path172" /><path
d="M12412,1669l210,0l0,1032l-210,0"
style="fill:none;stroke:#000;stroke-width:62.5px;"
id="path174" /></g><g
id="Camada6"><path
d="M2395,2185l-435,0c0,0 -42.966,-23.872 -162.116,174.441"
style="fill:none;stroke:#000;stroke-width:62.5px;"
id="path177" /><path
d="M1797.88,2359.44c-51.5,85.719 -117.234,212.948 -199.884,401.559c-66.001,150.618 -104.471,262.982 -123.254,346.889"
style="fill:none;stroke:#000;stroke-width:62.5px;stroke-linecap:butt;stroke-dasharray:62.5,62.5;"
id="path179" /><path
d="M1474.75,3107.89c-59.155,264.256 76.949,246.269 163.254,252.111"
style="fill:none;stroke:#000;stroke-width:62.5px;"
id="path181" /><path
d="M1797.88,2386c-84.884,146 -271.884,560 -304.884,702.845"
style="fill:none;stroke:#000;stroke-width:35.25px;"
id="path183" /></g><g
id="Logos"><g
id="NAMCO"><path
id="rect4393"
d="M10165.4,1931.18c-60.093,0 -110.236,50.95 -110.236,112.01l0,195.668c0,61.059 50.143,112.009 110.236,112.009l349.004,0c60.093,0 110.236,-50.95 110.236,-112.009l0,-195.668c0,-61.06 -50.143,-112.01 -110.236,-112.01l-349.004,0Zm24.974,118.981l296.469,0l0,181.725l-296.469,0l-0,-181.725Z"
style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:17.79px;stroke-linecap:butt;stroke-miterlimit:2;" /><path
id="rect4348"
d="M7537.28,1939.54l0,411.786l135.21,0l0,-292.805l255.262,0l0,292.805l132.622,0l0,-299.776c0,-61.06 -50.143,-112.01 -110.236,-112.01l-412.858,0Z"
style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:17.79px;stroke-linecap:butt;stroke-miterlimit:2;" /><path
id="path4359"
d="M8151.86,1939.54l0,108.291l367.301,0l-0,29.281l-286.797,-0c-60.092,-0 -110.235,51.415 -110.235,112.474l-0,49.731c-0,61.059 50.143,112.009 110.235,112.009l419.446,0l-0,-299.776c-0,-61.06 -50.143,-112.01 -110.236,-112.01l-389.714,0Zm108.406,247.258l258.895,-0l-0,58.561l-258.895,-0l0,-58.561Z"
style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:17.79px;stroke-linecap:butt;stroke-miterlimit:2;" /><path
id="path4384"
d="M8735.06,1939.54l-0,411.786l135.393,0l0,-292.805l139.053,0l-0,292.805l135.393,0l0,-292.805l141.798,0l-0,292.805l132.649,0l-0,-299.776c-0,-61.06 -50.144,-112.01 -110.236,-112.01l-574.05,0Z"
style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:17.79px;stroke-linecap:butt;stroke-miterlimit:2;" /><path
id="rect4389"
d="M9608.25,1931.18c-60.093,0 -110.236,50.95 -110.236,112.01l0,195.668c0,61.059 50.143,112.009 110.236,112.009l370.503,0l-0,-118.981l-342.942,0l0,-181.725l342.942,0l-0,-118.981l-370.503,0Z"
style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:17.79px;stroke-linecap:butt;stroke-miterlimit:2;" /></g><g
id="g264"><g
id="DuckStation-Logo"
serif:id="DuckStation Logo"><path
d="M2993.81,3728.12c0,14.99 -3.152,26.719 -9.457,35.184c-6.305,8.465 -16.859,12.698 -31.662,12.698l-75.659,-0l0,-185.445l75.659,0c14.803,0 25.357,4.277 31.662,12.831c6.305,8.553 9.457,20.678 9.457,36.374l0,88.358Zm-28.783,-88.358c-0,-12.874 -1.645,-21.648 -4.934,-26.322c-3.29,-4.673 -8.681,-7.01 -16.174,-7.01l-38.103,-0l-0,153.699l38.103,0c7.493,0 12.884,-2.645 16.174,-7.936c3.289,-5.291 4.934,-13.315 4.934,-24.073l-0,-88.358Z"
style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:9.06px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path192" /><path
d="M3105.11,3760.13l0,-130.948l27.961,-0l0,146.821l-73.74,-0c-8.224,-0 -14.985,-0.794 -20.285,-2.381c-5.3,-1.587 -9.549,-4.188 -12.747,-7.804c-3.198,-3.615 -5.391,-8.245 -6.579,-13.888c-1.188,-5.644 -1.782,-12.61 -1.782,-20.899l0,-101.849l27.961,-0l-0,102.907c-0,5.82 0.32,10.582 0.959,14.285c0.64,3.704 1.782,6.57 3.427,8.598c1.645,2.028 3.975,3.395 6.99,4.1c3.016,0.706 6.99,1.058 11.925,1.058l35.91,0Z"
style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:9.06px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path194" /><path
d="M3186.25,3732.09c0,5.82 0.32,10.582 0.96,14.285c0.639,3.704 1.782,6.57 3.426,8.598c1.645,2.028 3.975,3.395 6.991,4.1c3.015,0.706 6.99,1.058 11.924,1.058l43.312,0l-0,15.873l-53.18,-0c-8.224,-0 -14.986,-0.794 -20.286,-2.381c-5.299,-1.587 -9.548,-4.188 -12.747,-7.804c-3.198,-3.615 -5.391,-8.245 -6.579,-13.888c-1.187,-5.644 -1.781,-12.61 -1.781,-20.899l-0,-56.877c-0,-8.113 0.594,-15.035 1.781,-20.767c1.188,-5.731 3.381,-10.405 6.579,-14.02c3.199,-3.616 7.448,-6.217 12.747,-7.804c5.3,-1.588 12.062,-2.381 20.286,-2.381l53.18,-0l-0,15.872l-43.312,0c-4.934,0 -8.909,0.353 -11.924,1.058c-3.016,0.706 -5.346,2.073 -6.991,4.101c-1.644,2.028 -2.787,4.894 -3.426,8.597c-0.64,3.704 -0.96,8.466 -0.96,14.286l0,58.993Z"
style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:9.06px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path196" /><path
d="M3382.25,3776l-33.169,-0l-47.424,-81.744l0,81.744l-27.96,-0l-0,-190.735l27.96,-0l0,101.319l52.633,-57.405l21.381,-0l-48.52,53.437l55.099,93.384Z"
style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:9.06px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path198" /><path
d="M3501.77,3720.18c0,19.224 -3.381,33.333 -10.142,42.327c-6.762,8.995 -18.275,13.492 -34.54,13.492l-61.404,-0l-0,-15.873l55.921,0c3.838,0 7.265,-0.44 10.28,-1.322c3.015,-0.882 5.482,-2.646 7.401,-5.291c1.919,-2.646 3.381,-6.305 4.386,-10.979c1.005,-4.673 1.508,-10.802 1.508,-18.385c0,-6.526 -0.365,-11.861 -1.096,-16.005c-0.731,-4.145 -2.056,-7.319 -3.975,-9.524c-1.919,-2.204 -4.569,-3.703 -7.95,-4.497c-3.381,-0.794 -7.813,-1.19 -13.295,-1.19l-20.834,-0c-6.944,-0 -12.792,-0.882 -17.544,-2.646c-4.751,-1.764 -8.589,-4.629 -11.513,-8.598c-2.924,-3.968 -5.026,-9.17 -6.305,-15.608c-1.279,-6.437 -1.919,-14.417 -1.919,-23.941c0,-16.225 3.153,-28.879 9.458,-37.962c6.305,-9.082 17.224,-13.624 32.758,-13.624l53.454,0l0,15.873l-46.601,-0c-3.838,-0 -7.127,0.485 -9.869,1.455c-2.741,0.97 -5.071,2.645 -6.99,5.026c-1.919,2.381 -3.335,5.644 -4.249,9.788c-0.914,4.145 -1.371,9.392 -1.371,15.741c0,6.172 0.275,11.243 0.823,15.211c0.548,3.968 1.599,7.054 3.152,9.259c1.554,2.204 3.792,3.748 6.716,4.629c2.924,0.882 6.854,1.323 11.788,1.323l19.463,0c7.31,0 13.66,0.706 19.051,2.116c5.392,1.411 9.823,3.969 13.296,7.672c3.472,3.704 6.03,8.906 7.675,15.608c1.645,6.702 2.467,15.344 2.467,25.925Z"
style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:9.06px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path200" /><path
d="M3587.85,3645.05l-38.104,0l0,93.648c0,8.466 1.234,14.153 3.701,17.063c2.467,2.91 7.264,4.365 14.392,4.365l12.335,0l0,15.873l-23.575,-0c-6.579,-0 -12.107,-0.882 -16.584,-2.645c-4.478,-1.764 -8.041,-4.233 -10.691,-7.408c-2.65,-3.174 -4.569,-6.922 -5.757,-11.243c-1.188,-4.321 -1.782,-9.038 -1.782,-14.153l0,-149.996l27.961,0l0,38.624l38.104,-0l-0,15.872Z"
style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:9.06px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path202" /><path
d="M3658.84,3687.91l0,15.344l-11.787,-0c-4.934,-0 -8.909,0.352 -11.925,1.058c-3.015,0.705 -5.345,1.808 -6.99,3.307c-1.645,1.499 -2.787,3.483 -3.426,5.952c-0.64,2.469 -0.96,5.555 -0.96,9.259l0,16.931c0,4.056 0.32,7.363 0.96,9.92c0.639,2.557 1.781,4.629 3.426,6.217c1.645,1.587 3.975,2.689 6.99,3.307c3.016,0.617 6.991,0.925 11.925,0.925l30.976,0l0,-87.034c0,-5.82 -0.32,-10.582 -0.959,-14.286c-0.64,-3.703 -1.782,-6.569 -3.427,-8.597c-1.645,-2.028 -3.975,-3.395 -6.99,-4.101c-3.015,-0.705 -6.99,-1.058 -11.925,-1.058l-39.474,0l0,-15.872l49.343,-0c8.224,-0 14.986,0.793 20.285,2.381c5.3,1.587 9.549,4.188 12.747,7.804c3.198,3.615 5.391,8.289 6.579,14.02c1.188,5.732 1.782,12.654 1.782,20.767l-0,101.849l-68.806,-0c-8.223,-0 -14.985,-0.75 -20.285,-2.249c-5.3,-1.499 -9.549,-3.703 -12.747,-6.613c-3.198,-2.91 -5.391,-6.526 -6.579,-10.846c-1.188,-4.321 -1.782,-9.304 -1.782,-14.947l0,-18.783c0,-5.643 0.594,-10.625 1.782,-14.946c1.188,-4.321 3.381,-7.937 6.579,-10.847c3.198,-2.91 7.447,-5.114 12.747,-6.613c5.3,-1.499 12.062,-2.249 20.285,-2.249l21.656,0Z"
style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:9.06px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path204" /><path
d="M3797.28,3645.05l-38.104,0l0,93.648c0,8.466 1.234,14.153 3.701,17.063c2.467,2.91 7.264,4.365 14.392,4.365l12.335,0l0,15.873l-23.574,-0c-6.579,-0 -12.108,-0.882 -16.585,-2.645c-4.477,-1.764 -8.041,-4.233 -10.691,-7.408c-2.65,-3.174 -4.569,-6.922 -5.757,-11.243c-1.187,-4.321 -1.781,-9.038 -1.781,-14.153l-0,-149.996l27.96,0l0,38.624l38.104,-0l-0,15.872Z"
style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:9.06px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path206" /><path
d="M3842.78,3776l-27.961,-0l-0,-146.821l27.961,-0l-0,146.821Zm-0,-165.604l-27.961,0l-0,-25.396l27.961,-0l-0,25.396Z"
style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:9.06px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path208" /><path
d="M3946.68,3629.18c8.224,-0 14.986,0.793 20.286,2.381c5.3,1.587 9.549,4.188 12.747,7.804c3.198,3.615 5.391,8.289 6.579,14.02c1.188,5.732 1.781,12.654 1.781,20.767l0,56.877c0,8.289 -0.593,15.255 -1.781,20.899c-1.188,5.643 -3.381,10.273 -6.579,13.888c-3.198,3.616 -7.447,6.217 -12.747,7.804c-5.3,1.587 -12.062,2.381 -20.286,2.381l-36.732,-0c-8.224,-0 -14.986,-0.794 -20.286,-2.381c-5.299,-1.587 -9.548,-4.188 -12.747,-7.804c-3.198,-3.615 -5.391,-8.245 -6.579,-13.888c-1.187,-5.644 -1.781,-12.61 -1.781,-20.899l-0,-56.877c-0,-8.113 0.594,-15.035 1.781,-20.767c1.188,-5.731 3.381,-10.405 6.579,-14.02c3.199,-3.616 7.448,-6.217 12.747,-7.804c5.3,-1.588 12.062,-2.381 20.286,-2.381l36.732,-0Zm-50.165,102.907c0,5.82 0.32,10.582 0.96,14.285c0.64,3.704 1.782,6.57 3.426,8.598c1.645,2.028 3.975,3.395 6.991,4.1c3.015,0.706 6.99,1.058 11.924,1.058l16.996,0c4.934,0 8.909,-0.352 11.924,-1.058c3.016,-0.705 5.346,-2.072 6.991,-4.1c1.644,-2.028 2.787,-4.894 3.426,-8.598c0.64,-3.703 0.96,-8.465 0.96,-14.285l-0,-58.993c-0,-5.82 -0.32,-10.582 -0.96,-14.286c-0.639,-3.703 -1.782,-6.569 -3.426,-8.597c-1.645,-2.028 -3.975,-3.395 -6.991,-4.101c-3.015,-0.705 -6.99,-1.058 -11.924,-1.058l-16.996,0c-4.934,0 -8.909,0.353 -11.924,1.058c-3.016,0.706 -5.346,2.073 -6.991,4.101c-1.644,2.028 -2.786,4.894 -3.426,8.597c-0.64,3.704 -0.96,8.466 -0.96,14.286l0,58.993Z"
style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:9.06px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path210" /><path
d="M4041.25,3645.05l-0,130.949l-27.961,-0l0,-146.821l75.111,-0c8.223,-0 14.985,0.793 20.285,2.381c5.3,1.587 9.549,4.188 12.747,7.804c3.198,3.615 5.391,8.289 6.579,14.02c1.188,5.732 1.782,12.654 1.782,20.767l-0,101.849l-27.961,-0l-0,-102.907c-0,-5.82 -0.32,-10.582 -0.96,-14.286c-0.639,-3.703 -1.782,-6.569 -3.426,-8.597c-1.645,-2.028 -3.975,-3.395 -6.991,-4.101c-3.015,-0.705 -6.99,-1.058 -11.924,-1.058l-37.281,0Z"
style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:9.06px;stroke-linecap:butt;stroke-miterlimit:2;"
id="path212" /></g><g
id="g262"><path
d="M3593.98,3447.16l-30.47,18.478"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path215" /><path
d="M3563.51,3404.94l-0,25.575l30.47,16.643l0,36.588l-30.47,17.744"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path217" /><path
d="M3656.64,3350l-0,25.575l30.164,16.704"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path219" /><path
d="M3593.98,3387.69l0,24.29l62.042,35.182l30.776,-17.255l-0,-36.344l-31.143,18.417l-31.939,-19.151l0,-23.128"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path221" /><path
d="M3501.35,3384.02l-0,80.764l62.164,36.711l-0,-35.977l-31.939,-18.722l0,-44.421"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path223" /><path
d="M3437.04,3019.84l49.071,-28.451"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path225" /><path
d="M3390.05,2991.39l46.99,-26.983l49.071,26.983l-0,54.026"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path227" /><path
d="M3437.04,3073.87l0,-54.516l-46.99,-27.961l0,57.085l43.686,27.717"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path229" /><path
d="M3641.53,3256.81l42.952,-25.759"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path231" /><path
d="M3672.55,3194.04l-0,29.531l76.481,44.503l0,-29.614"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path233" /><path
d="M3749.58,3149.62l-77.032,44.849l76.848,43.992l76.115,-44.175l-75.931,-44.666Z"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path235" /><path
d="M3550.3,3411.98l169.238,-99.303l-0,-61.491"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path237" /><path
d="M3381.06,3107.89l129.835,-76.175"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path239" /><path
d="M3550.3,3204.95l-0,207.029l-169.238,-98.278l-0,-205.812l169.238,97.061Z"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path241" /><path
d="M3641.53,3097.3l130.63,-76.604"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path243" /><g
id="Camada21"
serif:id="Camada2"><path
d="M3510.89,3181.74l-0,-161.284l130.63,-75.625l130.63,76.053l0,141.888"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path245" /><path
d="M3510.89,3181.74l130.63,75.074l-0,-158.776l-130.63,-77.338"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path247" /></g><path
d="M3749.03,3268.07l76.482,-44.503l-0,-29.531"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path250" /><path
d="M3656.64,3411.8l-0,35.365"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path252" /><path
d="M3532.43,3447.16l31.082,-17.683"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path254" /><path
d="M3624.39,3392.58l32.245,-17.316"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path256" /><path
d="M3660.25,3150.17l-0,31.143l26.554,-14.99l-0,-31.388l-26.554,15.235Z"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path258" /><path
d="M3726.94,3112.78l0,31.143l26.555,-14.99l-0,-31.388l-26.555,15.235Z"
style="fill:none;stroke:#000;stroke-width:8.33px;"
id="path260" /></g></g></g><path
d="M10366.8,3256.76c-0.362,0.417 -0.723,0.833 -1.084,1.25c-112.023,129.467 -179.792,298.279 -179.792,482.92c-0,396.964 313.923,721.187 706.846,737.742"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path267" /><path
d="M11008.5,4474.59c241.356,-27.378 447.426,-171.112 560.759,-373.75"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path269" /><path
d="M10916,3258.27c-262.908,-0 -476.037,213.129 -476.037,476.036c0,262.732 213.305,476.037 476.037,476.037c5.389,0 10.758,-0.089 16.104,-0.267"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path271" /><path
d="M10963.8,4207.97c147.162,-14.675 274.589,-96.371 351.318,-214.124"
style="fill:none;stroke:#000;stroke-width:20.83px;stroke-linecap:butt;"
id="path273" /><g
id="Camada8"><path
d="M8441.95,3508.86l1586.23,0l98.419,-250.237l94.232,-150.771"
style="fill:none;stroke:#000;stroke-width:23.75px;"
id="path275" /></g></g><circle
cx="10925.2"
cy="3732.75"
r="363.156"
style="fill:#ba1b42;stroke:#63112e;stroke-width:20.83px;stroke-linecap:butt;"
id="circle279" /></g></svg>

After

Width:  |  Height:  |  Size: 36 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 36 KiB

View File

@ -0,0 +1,13 @@
#!/bin/sh
IFS="
"
printf "<RCC>\n"
printf "\t<qresource>\n"
for i in $(find . -not -iname '*.sh' -not -iname '*.qrc' -type f | cut -d'/' -f2-99); do
printf "\t\t<file>%s</file>\n" "$i"
done
printf "\t</qresource>\n"
printf "</RCC>\n"

View File

@ -13,3 +13,9 @@ Type=Fixed
[64]
Size=64
Type=Fixed
[svg]
Size=64
Type=Scalable
MinSize=64
MaxSize=1024

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M16.05 12.05L21 17l-4.95 4.95-1.414-1.414 2.536-2.537L4 18v-2h13.172l-2.536-2.536 1.414-1.414zm-8.1-10l1.414 1.414L6.828 6 20 6v2H6.828l2.536 2.536L7.95 11.95 3 7l4.95-4.95z" fill="#000000"/></svg>

After

Width:  |  Height:  |  Size: 326 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M8 8v8h8V8H8zM6 6h12v12H6V6zm0-4h2v3H6V2zm0 17h2v3H6v-3zM2 6h3v2H2V6zm0 10h3v2H2v-2zM19 6h3v2h-3V6zm0 10h3v2h-3v-2zM16 2h2v3h-2V2zm0 17h2v3h-2v-3z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 298 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M13 21v2h-2v-2H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h6a3.99 3.99 0 0 1 3 1.354A3.99 3.99 0 0 1 15 3h6a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1h-8zm7-2V5h-5a2 2 0 0 0-2 2v12h7zm-9 0V7a2 2 0 0 0-2-2H4v14h7z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 340 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M15.456 9.678l-.142-.142a5.475 5.475 0 0 0-2.39-1.349c-2.907-.778-5.699.869-6.492 3.83-.043.16-.066.34-.104.791-.154 1.87-.594 3.265-1.8 4.68 2.26.888 4.938 1.514 6.974 1.514a5.505 5.505 0 0 0 5.31-4.078 5.497 5.497 0 0 0-1.356-5.246zM13.29 6.216l4.939-3.841a1 1 0 0 1 1.32.082l2.995 2.994a1 1 0 0 1 .082 1.321l-3.84 4.938a7.505 7.505 0 0 1-7.283 9.292C8 21.002 3.5 19.5 1 18c3.98-3 3.047-4.81 3.5-6.5 1.058-3.95 4.842-6.257 8.789-5.284zm3.413 1.879c.065.063.13.128.193.194l1.135 1.134 2.475-3.182-1.746-1.746-3.182 2.475 1.125 1.125z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 686 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 280 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M13 21V11h8v10h-8zM3 13V3h8v10H3zm6-2V5H5v6h4zM3 21v-6h8v6H3zm2-2h4v-2H5v2zm10 0h4v-6h-4v6zM13 3h8v6h-8V3zm2 2v2h4V5h-4z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 272 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M15 4.582V12a3 3 0 1 1-2-2.83V2.05c5.053.501 9 4.765 9 9.95 0 5.523-4.477 10-10 10S2 17.523 2 12c0-5.185 3.947-9.449 9-9.95v2.012A8.001 8.001 0 0 0 12 20a8 8 0 0 0 3-15.418z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 325 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0H24V24H0z"/>
<path d="M2 21v-2h2V4.835c0-.484.346-.898.821-.984l9.472-1.722c.326-.06.638.157.697.483.007.035.01.07.01.107v1.28L19 4c.552 0 1 .448 1 1v14h2v2h-4V6h-3v15H2zM13 4.396L6 5.67V19h7V4.396zM12 11v2h-2v-2h2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 345 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M13 10h5l-6 6-6-6h5V3h2v7zm-9 9h16v-7h2v8a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1v-8h2v7z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 231 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm1-9h3l-5 7v-5H8l5-7v5z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 283 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M7.737 13h8.526L12 6.606 7.737 13zm4.679-9.376l7.066 10.599a.5.5 0 0 1-.416.777H4.934a.5.5 0 0 1-.416-.777l7.066-10.599a.5.5 0 0 1 .832 0zM5 17h14a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 329 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M15 4H5v16h14V8h-4V4zM3 2.992C3 2.444 3.447 2 3.999 2H16l5 5v13.993A1 1 0 0 1 20.007 22H3.993A1 1 0 0 1 3 21.008V2.992zM11 11V8h2v3h3v2h-3v3h-2v-3H8v-2h3z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 306 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M9 2.003V2h10.998C20.55 2 21 2.455 21 2.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 20.993V8l6-5.997zM5.83 8H9V4.83L5.83 8zM11 4v5a1 1 0 0 1-1 1H5v10h14V4h-8z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 319 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M20 22H4a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1zm-1-2V4H5v16h14zM8 7h8v2H8V7zm0 4h8v2H8v-2zm0 4h8v2H8v-2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 282 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M15 4H5v16h14V8h-4V4zM3 2.992C3 2.444 3.447 2 3.999 2H16l5 5v13.993A1 1 0 0 1 20.007 22H3.993A1 1 0 0 1 3 21.008V2.992zM16 11v2H8v-2h8z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 287 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M15 4H5v16h14V8h-4V4zM3 2.992C3 2.444 3.447 2 3.999 2H16l5 5v13.993A1 1 0 0 1 20.007 22H3.993A1 1 0 0 1 3 21.008V2.992zm10.529 11.454a4.002 4.002 0 0 1-4.86-6.274 4 4 0 0 1 6.274 4.86l2.21 2.21-1.414 1.415-2.21-2.21zm-.618-2.032a2 2 0 1 0-2.828-2.828 2 2 0 0 0 2.828 2.828z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 425 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path fill-rule="nonzero" d="M8.595 12.812a3.51 3.51 0 0 1 0-1.623l-.992-.573 1-1.732.992.573A3.496 3.496 0 0 1 11 8.645V7.5h2v1.145c.532.158 1.012.44 1.405.812l.992-.573 1 1.732-.992.573a3.51 3.51 0 0 1 0 1.622l.992.573-1 1.732-.992-.573a3.496 3.496 0 0 1-1.405.812V16.5h-2v-1.145a3.496 3.496 0 0 1-1.405-.812l-.992.573-1-1.732.992-.572zM12 13.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM15 4H5v16h14V8h-4V4zM3 2.992C3 2.444 3.447 2 3.999 2H16l5 5v13.993A1 1 0 0 1 20.007 22H3.993A1 1 0 0 1 3 21.008V2.992z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 645 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0H24V24H0z"/>
<path d="M16 2v2h-1v3.243c0 1.158.251 2.301.736 3.352l4.282 9.276c.347.753.018 1.644-.734 1.99-.197.092-.411.139-.628.139H5.344c-.828 0-1.5-.672-1.5-1.5 0-.217.047-.432.138-.629l4.282-9.276C8.749 9.545 9 8.401 9 7.243V4H8V2h8zm-2.612 8.001h-2.776c-.104.363-.23.721-.374 1.071l-.158.361L6.125 20h11.749l-3.954-8.567c-.214-.464-.392-.943-.532-1.432zM11 7.243c0 .253-.01.506-.029.758h2.058c-.01-.121-.016-.242-.021-.364L13 7.243V4h-2v3.243z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 580 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M12.414 5H21a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h7.414l2 2zM4 5v14h16V7h-8.414l-2-2H4zm7 7V9h2v3h3v2h-3v3h-2v-3H8v-2h3z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 298 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M3 21a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h7.414l2 2H20a1 1 0 0 1 1 1v3h-2V7h-7.414l-2-2H4v11.998L5.5 11h17l-2.31 9.243a1 1 0 0 1-.97.757H3zm16.938-8H7.062l-1.5 6h12.876l1.5-6z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 321 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M12.414 5H21a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h7.414l2 2zM4 5v14h16V7h-8.414l-2-2H4zm4 7h8v2H8v-2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 279 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M12.414 5H21a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h7.414l2 2zM4 5v14h16V7h-8.414l-2-2H4zm4.591 8.809a3.508 3.508 0 0 1 0-1.622l-.991-.572 1-1.732.991.573a3.495 3.495 0 0 1 1.404-.812V8.5h2v1.144c.532.159 1.01.44 1.403.812l.992-.573 1 1.731-.991.573a3.508 3.508 0 0 1 0 1.622l.991.572-1 1.731-.991-.572a3.495 3.495 0 0 1-1.404.811v1.145h-2V16.35a3.495 3.495 0 0 1-1.404-.811l-.991.572-1-1.73.991-.573zm3.404.688a1.5 1.5 0 1 0 0-2.998 1.5 1.5 0 0 0 0 2.998z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 632 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M20 3h2v6h-2V5h-4V3h4zM4 3h4v2H4v4H2V3h2zm16 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 234 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M3 3h8v8H3V3zm0 10h8v8H3v-8zM13 3h8v8h-8V3zm0 10h8v8h-8v-8zm2-8v4h4V5h-4zm0 10v4h4v-4h-4zM5 5v4h4V5H5zm0 10v4h4v-4H5z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 269 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path fill-rule="nonzero" d="M17 4a6 6 0 0 1 6 6v4a6 6 0 0 1-6 6H7a6 6 0 0 1-6-6v-4a6 6 0 0 1 6-6h10zm0 2H7a4 4 0 0 0-3.995 3.8L3 10v4a4 4 0 0 0 3.8 3.995L7 18h10a4 4 0 0 0 3.995-3.8L21 14v-4a4 4 0 0 0-3.8-3.995L17 6zm-7 3v2h2v2H9.999L10 15H8l-.001-2H6v-2h2V9h2zm8 4v2h-2v-2h2zm-2-4v2h-2V9h2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 435 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M5 14h14V4H5v10zm0 2v4h14v-4H5zM4 2h16a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1zm11 15h2v2h-2v-2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 271 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M3 17h18v2H3v-2zm0-6h3v3H3v-3zm5 0h3v3H8v-3zM3 5h3v3H3V5zm10 0h3v3h-3V5zm5 0h3v3h-3V5zm-5 6h3v3h-3v-3zm5 0h3v3h-3v-3zM8 5h3v3H8V5z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 282 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path fill-rule="nonzero" d="M21 3a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h18zM11 13H4v6h7v-6zm9 0h-7v6h7v-6zm-9-8H4v6h7V5zm9 0h-7v6h7V5z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 303 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M8 4h13v2H8V4zm-5-.5h3v3H3v-3zm0 7h3v3H3v-3zm0 7h3v3H3v-3zM8 11h13v2H8v-2zm0 7h13v2H8v-2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 241 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M6 5h2v14H6V5zm10 0h2v14h-2V5z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 182 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M16.394 12L10 7.737v8.526L16.394 12zm2.982.416L8.777 19.482A.5.5 0 0 1 8 19.066V4.934a.5.5 0 0 1 .777-.416l10.599 7.066a.5.5 0 0 1 0 .832z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 290 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M5.463 4.433A9.961 9.961 0 0 1 12 2c5.523 0 10 4.477 10 10 0 2.136-.67 4.116-1.81 5.74L17 12h3A8 8 0 0 0 6.46 6.228l-.997-1.795zm13.074 15.134A9.961 9.961 0 0 1 12 22C6.477 22 2 17.523 2 12c0-2.136.67-4.116 1.81-5.74L7 12H4a8 8 0 0 0 13.54 5.772l.997 1.795z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 409 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M18.537 19.567A9.961 9.961 0 0 1 12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10c0 2.136-.67 4.116-1.81 5.74L17 12h3a8 8 0 1 0-2.46 5.772l.997 1.795z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 310 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M18 19h1V6.828L17.172 5H16v4H7V5H5v14h1v-7h12v7zM4 3h14l2.707 2.707a1 1 0 0 1 .293.707V20a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm4 11v5h8v-5H8z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 303 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M3 3h2v2H3V3zm4 0h2v2H7V3zm4 0h2v2h-2V3zm4 0h2v2h-2V3zm4 0h2v2h-2V3zm0 4h2v2h-2V7zM3 19h2v2H3v-2zm0-4h2v2H3v-2zm0-4h2v2H3v-2zm0-4h2v2H3V7zm7.667 4l1.036-1.555A1 1 0 0 1 12.535 9h2.93a1 1 0 0 1 .832.445L17.333 11H20a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1v-8a1 1 0 0 1 1-1h2.667zM9 19h10v-6h-2.737l-1.333-2h-1.86l-1.333 2H9v6zm5-1a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 516 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M6 7.828V20h12V4H9.828L6 7.828zm-1.707-1.12L9 2h10a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7.414a1 1 0 0 1 .293-.707zM15 5h2v4h-2V5zm-3 0h2v4h-2V5zM9 6h2v3H9V6z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 319 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M3.34 17a10.018 10.018 0 0 1-.978-2.326 3 3 0 0 0 .002-5.347A9.99 9.99 0 0 1 4.865 4.99a3 3 0 0 0 4.631-2.674 9.99 9.99 0 0 1 5.007.002 3 3 0 0 0 4.632 2.672c.579.59 1.093 1.261 1.525 2.01.433.749.757 1.53.978 2.326a3 3 0 0 0-.002 5.347 9.99 9.99 0 0 1-2.501 4.337 3 3 0 0 0-4.631 2.674 9.99 9.99 0 0 1-5.007-.002 3 3 0 0 0-4.632-2.672A10.018 10.018 0 0 1 3.34 17zm5.66.196a4.993 4.993 0 0 1 2.25 2.77c.499.047 1 .048 1.499.001A4.993 4.993 0 0 1 15 17.197a4.993 4.993 0 0 1 3.525-.565c.29-.408.54-.843.748-1.298A4.993 4.993 0 0 1 18 12c0-1.26.47-2.437 1.273-3.334a8.126 8.126 0 0 0-.75-1.298A4.993 4.993 0 0 1 15 6.804a4.993 4.993 0 0 1-2.25-2.77c-.499-.047-1-.048-1.499-.001A4.993 4.993 0 0 1 9 6.803a4.993 4.993 0 0 1-3.525.565 7.99 7.99 0 0 0-.748 1.298A4.993 4.993 0 0 1 6 12c0 1.26-.47 2.437-1.273 3.334a8.126 8.126 0 0 0 .75 1.298A4.993 4.993 0 0 1 9 17.196zM12 15a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M6.265 3.807l1.147 1.639a8 8 0 1 0 9.176 0l1.147-1.639A9.988 9.988 0 0 1 22 12c0 5.523-4.477 10-10 10S2 17.523 2 12a9.988 9.988 0 0 1 4.265-8.193zM11 12V2h2v10h-2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 315 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M2 4c0-.552.455-1 .992-1h18.016c.548 0 .992.445.992 1v14c0 .552-.455 1-.992 1H2.992A.994.994 0 0 1 2 18V4zm2 1v12h16V5H4zm1 15h14v2H5v-2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 289 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M10 7.22L6.603 10H3v4h3.603L10 16.78V7.22zM5.889 16H2a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1h3.889l5.294-4.332a.5.5 0 0 1 .817.387v15.89a.5.5 0 0 1-.817.387L5.89 16zm13.517 4.134l-1.416-1.416A8.978 8.978 0 0 0 21 12a8.982 8.982 0 0 0-3.304-6.968l1.42-1.42A10.976 10.976 0 0 1 23 12c0 3.223-1.386 6.122-3.594 8.134zm-3.543-3.543l-1.422-1.422A3.993 3.993 0 0 0 16 12c0-1.43-.75-2.685-1.88-3.392l1.439-1.439A5.991 5.991 0 0 1 18 12c0 1.842-.83 3.49-2.137 4.591z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 601 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M3 3h18a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm17 8H4v8h16v-8zm0-2V5H4v4h16zm-5-3h4v2h-4V6z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 268 B

View File

@ -13,3 +13,9 @@ Type=Fixed
[64]
Size=64
Type=Fixed
[svg]
Size=64
Type=Scalable
MinSize=64
MaxSize=1024

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M16.05 12.05L21 17l-4.95 4.95-1.414-1.414 2.536-2.537L4 18v-2h13.172l-2.536-2.536 1.414-1.414zm-8.1-10l1.414 1.414L6.828 6 20 6v2H6.828l2.536 2.536L7.95 11.95 3 7l4.95-4.95z" fill="#ffffff"/></svg>

After

Width:  |  Height:  |  Size: 326 B

Some files were not shown because too many files have changed in this diff Show More