summaryrefslogtreecommitdiff
path: root/src/yuzu_cmd
diff options
context:
space:
mode:
authorGravatar James Rowe2018-01-11 19:21:20 -0700
committerGravatar James Rowe2018-01-12 19:11:03 -0700
commitebf9a784a9f7f4148a669dbb39e7cd50df779a14 (patch)
treed585685a1c0a34b903af1d086d62560bf56bb29f /src/yuzu_cmd
parentconfig: Default CPU core to Unicorn. (diff)
downloadyuzu-ebf9a784a9f7f4148a669dbb39e7cd50df779a14.tar.gz
yuzu-ebf9a784a9f7f4148a669dbb39e7cd50df779a14.tar.xz
yuzu-ebf9a784a9f7f4148a669dbb39e7cd50df779a14.zip
Massive removal of unused modules
Diffstat (limited to 'src/yuzu_cmd')
-rw-r--r--src/yuzu_cmd/CMakeLists.txt35
-rw-r--r--src/yuzu_cmd/citra.cpp175
-rw-r--r--src/yuzu_cmd/citra.rc17
-rw-r--r--src/yuzu_cmd/config.cpp160
-rw-r--r--src/yuzu_cmd/config.h24
-rw-r--r--src/yuzu_cmd/default_ini.h179
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.cpp177
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.h59
-rw-r--r--src/yuzu_cmd/resource.h16
9 files changed, 842 insertions, 0 deletions
diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt
new file mode 100644
index 000000000..c6c527eb6
--- /dev/null
+++ b/src/yuzu_cmd/CMakeLists.txt
@@ -0,0 +1,35 @@
1set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules)
2
3set(SRCS
4 emu_window/emu_window_sdl2.cpp
5 citra.cpp
6 config.cpp
7 citra.rc
8 )
9set(HEADERS
10 emu_window/emu_window_sdl2.h
11 config.h
12 default_ini.h
13 resource.h
14 )
15
16create_directory_groups(${SRCS} ${HEADERS})
17
18add_executable(yuzu-cmd ${SRCS} ${HEADERS})
19target_link_libraries(yuzu-cmd PRIVATE common core input_common)
20target_link_libraries(yuzu-cmd PRIVATE inih glad)
21if (MSVC)
22 target_link_libraries(yuzu-cmd PRIVATE getopt)
23endif()
24target_link_libraries(yuzu-cmd PRIVATE ${PLATFORM_LIBRARIES} SDL2 Threads::Threads)
25
26if(UNIX AND NOT APPLE)
27 install(TARGETS yuzu-cmd RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
28endif()
29
30if (MSVC)
31 include(CopyCitraSDLDeps)
32 include(CopyYuzuUnicornDeps)
33 copy_citra_SDL_deps(yuzu-cmd)
34 copy_yuzu_unicorn_deps(yuzu-cmd)
35endif()
diff --git a/src/yuzu_cmd/citra.cpp b/src/yuzu_cmd/citra.cpp
new file mode 100644
index 000000000..e524c5535
--- /dev/null
+++ b/src/yuzu_cmd/citra.cpp
@@ -0,0 +1,175 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <iostream>
6#include <memory>
7#include <string>
8#include <thread>
9
10// This needs to be included before getopt.h because the latter #defines symbols used by it
11#include "common/microprofile.h"
12
13#ifdef _MSC_VER
14#include <getopt.h>
15#else
16#include <getopt.h>
17#include <unistd.h>
18#endif
19
20#ifdef _WIN32
21// windows.h needs to be included before shellapi.h
22#include <windows.h>
23
24#include <shellapi.h>
25#endif
26
27#include "citra/config.h"
28#include "citra/emu_window/emu_window_sdl2.h"
29#include "common/logging/backend.h"
30#include "common/logging/filter.h"
31#include "common/logging/log.h"
32#include "common/scm_rev.h"
33#include "common/scope_exit.h"
34#include "common/string_util.h"
35#include "core/core.h"
36#include "core/gdbstub/gdbstub.h"
37#include "core/loader/loader.h"
38#include "core/settings.h"
39
40static void PrintHelp(const char* argv0) {
41 std::cout << "Usage: " << argv0
42 << " [options] <filename>\n"
43 "-g, --gdbport=NUMBER Enable gdb stub on port NUMBER\n"
44 "-h, --help Display this help and exit\n"
45 "-v, --version Output version information and exit\n";
46}
47
48static void PrintVersion() {
49 std::cout << "Citra " << Common::g_scm_branch << " " << Common::g_scm_desc << std::endl;
50}
51
52/// Application entry point
53int main(int argc, char** argv) {
54 Config config;
55 int option_index = 0;
56 bool use_gdbstub = Settings::values.use_gdbstub;
57 u32 gdb_port = static_cast<u32>(Settings::values.gdbstub_port);
58 char* endarg;
59#ifdef _WIN32
60 int argc_w;
61 auto argv_w = CommandLineToArgvW(GetCommandLineW(), &argc_w);
62
63 if (argv_w == nullptr) {
64 LOG_CRITICAL(Frontend, "Failed to get command line arguments");
65 return -1;
66 }
67#endif
68 std::string filepath;
69
70 static struct option long_options[] = {
71 {"gdbport", required_argument, 0, 'g'},
72 {"help", no_argument, 0, 'h'},
73 {"version", no_argument, 0, 'v'},
74 {0, 0, 0, 0},
75 };
76
77 while (optind < argc) {
78 char arg = getopt_long(argc, argv, "g:hv", long_options, &option_index);
79 if (arg != -1) {
80 switch (arg) {
81 case 'g':
82 errno = 0;
83 gdb_port = strtoul(optarg, &endarg, 0);
84 use_gdbstub = true;
85 if (endarg == optarg)
86 errno = EINVAL;
87 if (errno != 0) {
88 perror("--gdbport");
89 exit(1);
90 }
91 break;
92 case 'h':
93 PrintHelp(argv[0]);
94 return 0;
95 case 'v':
96 PrintVersion();
97 return 0;
98 }
99 } else {
100#ifdef _WIN32
101 filepath = Common::UTF16ToUTF8(argv_w[optind]);
102#else
103 filepath = argv[optind];
104#endif
105 optind++;
106 }
107 }
108
109#ifdef _WIN32
110 LocalFree(argv_w);
111#endif
112
113 Log::Filter log_filter(Log::Level::Debug);
114 Log::SetFilter(&log_filter);
115
116 MicroProfileOnThreadCreate("EmuThread");
117 SCOPE_EXIT({ MicroProfileShutdown(); });
118
119 if (filepath.empty()) {
120 LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified");
121 return -1;
122 }
123
124 log_filter.ParseFilterString(Settings::values.log_filter);
125
126 // Apply the command line arguments
127 Settings::values.gdbstub_port = gdb_port;
128 Settings::values.use_gdbstub = use_gdbstub;
129 Settings::Apply();
130
131 std::unique_ptr<EmuWindow_SDL2> emu_window{std::make_unique<EmuWindow_SDL2>()};
132
133 Core::System& system{Core::System::GetInstance()};
134
135 SCOPE_EXIT({ system.Shutdown(); });
136
137 const Core::System::ResultStatus load_result{system.Load(emu_window.get(), filepath)};
138
139 switch (load_result) {
140 case Core::System::ResultStatus::ErrorGetLoader:
141 LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filepath.c_str());
142 return -1;
143 case Core::System::ResultStatus::ErrorLoader:
144 LOG_CRITICAL(Frontend, "Failed to load ROM!");
145 return -1;
146 case Core::System::ResultStatus::ErrorLoader_ErrorEncrypted:
147 LOG_CRITICAL(Frontend, "The game that you are trying to load must be decrypted before "
148 "being used with Citra. \n\n For more information on dumping and "
149 "decrypting games, please refer to: "
150 "https://citra-emu.org/wiki/dumping-game-cartridges/");
151 return -1;
152 case Core::System::ResultStatus::ErrorLoader_ErrorInvalidFormat:
153 LOG_CRITICAL(Frontend, "Error while loading ROM: The ROM format is not supported.");
154 return -1;
155 case Core::System::ResultStatus::ErrorNotInitialized:
156 LOG_CRITICAL(Frontend, "CPUCore not initialized");
157 return -1;
158 case Core::System::ResultStatus::ErrorSystemMode:
159 LOG_CRITICAL(Frontend, "Failed to determine system mode!");
160 return -1;
161 case Core::System::ResultStatus::ErrorVideoCore:
162 LOG_CRITICAL(Frontend, "VideoCore not initialized");
163 return -1;
164 case Core::System::ResultStatus::Success:
165 break; // Expected case
166 }
167
168 Core::Telemetry().AddField(Telemetry::FieldType::App, "Frontend", "SDL");
169
170 while (emu_window->IsOpen()) {
171 system.RunLoop();
172 }
173
174 return 0;
175}
diff --git a/src/yuzu_cmd/citra.rc b/src/yuzu_cmd/citra.rc
new file mode 100644
index 000000000..c490ef302
--- /dev/null
+++ b/src/yuzu_cmd/citra.rc
@@ -0,0 +1,17 @@
1#include "winresrc.h"
2/////////////////////////////////////////////////////////////////////////////
3//
4// Icon
5//
6
7// Icon with lowest ID value placed first to ensure application icon
8// remains consistent on all systems.
9CITRA_ICON ICON "../../dist/citra.ico"
10
11
12/////////////////////////////////////////////////////////////////////////////
13//
14// RT_MANIFEST
15//
16
171 RT_MANIFEST "../../dist/citra.manifest"
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
new file mode 100644
index 000000000..94d1a9f1c
--- /dev/null
+++ b/src/yuzu_cmd/config.cpp
@@ -0,0 +1,160 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <memory>
6#include <SDL.h>
7#include <inih/cpp/INIReader.h>
8#include "citra/config.h"
9#include "citra/default_ini.h"
10#include "common/file_util.h"
11#include "common/logging/log.h"
12#include "common/param_package.h"
13#include "core/settings.h"
14#include "input_common/main.h"
15
16Config::Config() {
17 // TODO: Don't hardcode the path; let the frontend decide where to put the config files.
18 sdl2_config_loc = FileUtil::GetUserPath(D_CONFIG_IDX) + "sdl2-config.ini";
19 sdl2_config = std::make_unique<INIReader>(sdl2_config_loc);
20
21 Reload();
22}
23
24Config::~Config() = default;
25
26bool Config::LoadINI(const std::string& default_contents, bool retry) {
27 const char* location = this->sdl2_config_loc.c_str();
28 if (sdl2_config->ParseError() < 0) {
29 if (retry) {
30 LOG_WARNING(Config, "Failed to load %s. Creating file from defaults...", location);
31 FileUtil::CreateFullPath(location);
32 FileUtil::WriteStringToFile(true, default_contents, location);
33 sdl2_config = std::make_unique<INIReader>(location); // Reopen file
34
35 return LoadINI(default_contents, false);
36 }
37 LOG_ERROR(Config, "Failed.");
38 return false;
39 }
40 LOG_INFO(Config, "Successfully loaded %s", location);
41 return true;
42}
43
44static const std::array<int, Settings::NativeButton::NumButtons> default_buttons = {
45 SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_T,
46 SDL_SCANCODE_G, SDL_SCANCODE_F, SDL_SCANCODE_H, SDL_SCANCODE_Q, SDL_SCANCODE_W,
47 SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_B,
48};
49
50static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs{{
51 {
52 SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_D,
53 },
54 {
55 SDL_SCANCODE_I, SDL_SCANCODE_K, SDL_SCANCODE_J, SDL_SCANCODE_L, SDL_SCANCODE_D,
56 },
57}};
58
59void Config::ReadValues() {
60 // Controls
61 for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
62 std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
63 Settings::values.buttons[i] =
64 sdl2_config->Get("Controls", Settings::NativeButton::mapping[i], default_param);
65 if (Settings::values.buttons[i].empty())
66 Settings::values.buttons[i] = default_param;
67 }
68
69 for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
70 std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
71 default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
72 default_analogs[i][3], default_analogs[i][4], 0.5f);
73 Settings::values.analogs[i] =
74 sdl2_config->Get("Controls", Settings::NativeAnalog::mapping[i], default_param);
75 if (Settings::values.analogs[i].empty())
76 Settings::values.analogs[i] = default_param;
77 }
78
79 Settings::values.motion_device = sdl2_config->Get(
80 "Controls", "motion_device", "engine:motion_emu,update_period:100,sensitivity:0.01");
81 Settings::values.touch_device =
82 sdl2_config->Get("Controls", "touch_device", "engine:emu_window");
83
84 // Core
85 Settings::values.cpu_core =
86 static_cast<Settings::CpuCore>(sdl2_config->GetInteger("Core", "cpu_core", 0));
87
88 // Renderer
89 Settings::values.use_hw_renderer = sdl2_config->GetBoolean("Renderer", "use_hw_renderer", true);
90 Settings::values.use_shader_jit = sdl2_config->GetBoolean("Renderer", "use_shader_jit", true);
91 Settings::values.resolution_factor =
92 (float)sdl2_config->GetReal("Renderer", "resolution_factor", 1.0);
93 Settings::values.use_vsync = sdl2_config->GetBoolean("Renderer", "use_vsync", false);
94 Settings::values.toggle_framelimit =
95 sdl2_config->GetBoolean("Renderer", "toggle_framelimit", true);
96
97 Settings::values.bg_red = (float)sdl2_config->GetReal("Renderer", "bg_red", 0.0);
98 Settings::values.bg_green = (float)sdl2_config->GetReal("Renderer", "bg_green", 0.0);
99 Settings::values.bg_blue = (float)sdl2_config->GetReal("Renderer", "bg_blue", 0.0);
100
101 // Layout
102 Settings::values.layout_option =
103 static_cast<Settings::LayoutOption>(sdl2_config->GetInteger("Layout", "layout_option", 0));
104 Settings::values.swap_screen = sdl2_config->GetBoolean("Layout", "swap_screen", false);
105 Settings::values.custom_layout = sdl2_config->GetBoolean("Layout", "custom_layout", false);
106 Settings::values.custom_top_left =
107 static_cast<u16>(sdl2_config->GetInteger("Layout", "custom_top_left", 0));
108 Settings::values.custom_top_top =
109 static_cast<u16>(sdl2_config->GetInteger("Layout", "custom_top_top", 0));
110 Settings::values.custom_top_right =
111 static_cast<u16>(sdl2_config->GetInteger("Layout", "custom_top_right", 400));
112 Settings::values.custom_top_bottom =
113 static_cast<u16>(sdl2_config->GetInteger("Layout", "custom_top_bottom", 240));
114 Settings::values.custom_bottom_left =
115 static_cast<u16>(sdl2_config->GetInteger("Layout", "custom_bottom_left", 40));
116 Settings::values.custom_bottom_top =
117 static_cast<u16>(sdl2_config->GetInteger("Layout", "custom_bottom_top", 240));
118 Settings::values.custom_bottom_right =
119 static_cast<u16>(sdl2_config->GetInteger("Layout", "custom_bottom_right", 360));
120 Settings::values.custom_bottom_bottom =
121 static_cast<u16>(sdl2_config->GetInteger("Layout", "custom_bottom_bottom", 480));
122
123 // Audio
124 Settings::values.sink_id = sdl2_config->Get("Audio", "output_engine", "auto");
125 Settings::values.enable_audio_stretching =
126 sdl2_config->GetBoolean("Audio", "enable_audio_stretching", true);
127 Settings::values.audio_device_id = sdl2_config->Get("Audio", "output_device", "auto");
128
129 // Data Storage
130 Settings::values.use_virtual_sd =
131 sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true);
132
133 // System
134 Settings::values.is_new_3ds = sdl2_config->GetBoolean("System", "is_new_3ds", false);
135 Settings::values.region_value =
136 sdl2_config->GetInteger("System", "region_value", Settings::REGION_VALUE_AUTO_SELECT);
137
138 // Miscellaneous
139 Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Info");
140
141 // Debugging
142 Settings::values.use_gdbstub = sdl2_config->GetBoolean("Debugging", "use_gdbstub", false);
143 Settings::values.gdbstub_port =
144 static_cast<u16>(sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689));
145
146 // Web Service
147 Settings::values.enable_telemetry =
148 sdl2_config->GetBoolean("WebService", "enable_telemetry", true);
149 Settings::values.telemetry_endpoint_url = sdl2_config->Get(
150 "WebService", "telemetry_endpoint_url", "https://services.citra-emu.org/api/telemetry");
151 Settings::values.verify_endpoint_url = sdl2_config->Get(
152 "WebService", "verify_endpoint_url", "https://services.citra-emu.org/api/profile");
153 Settings::values.citra_username = sdl2_config->Get("WebService", "citra_username", "");
154 Settings::values.citra_token = sdl2_config->Get("WebService", "citra_token", "");
155}
156
157void Config::Reload() {
158 LoadINI(DefaultINI::sdl2_config_file);
159 ReadValues();
160}
diff --git a/src/yuzu_cmd/config.h b/src/yuzu_cmd/config.h
new file mode 100644
index 000000000..abc90f642
--- /dev/null
+++ b/src/yuzu_cmd/config.h
@@ -0,0 +1,24 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <string>
9
10class INIReader;
11
12class Config {
13 std::unique_ptr<INIReader> sdl2_config;
14 std::string sdl2_config_loc;
15
16 bool LoadINI(const std::string& default_contents = "", bool retry = true);
17 void ReadValues();
18
19public:
20 Config();
21 ~Config();
22
23 void Reload();
24};
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
new file mode 100644
index 000000000..b7b8abe1e
--- /dev/null
+++ b/src/yuzu_cmd/default_ini.h
@@ -0,0 +1,179 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7namespace DefaultINI {
8
9const char* sdl2_config_file = R"(
10[Controls]
11# The input devices and parameters for each 3DS native input
12# It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..."
13# Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values
14
15# for button input, the following devices are available:
16# - "keyboard" (default) for keyboard input. Required parameters:
17# - "code": the code of the key to bind
18# - "sdl" for joystick input using SDL. Required parameters:
19# - "joystick": the index of the joystick to bind
20# - "button"(optional): the index of the button to bind
21# - "hat"(optional): the index of the hat to bind as direction buttons
22# - "axis"(optional): the index of the axis to bind
23# - "direction"(only used for hat): the direction name of the hat to bind. Can be "up", "down", "left" or "right"
24# - "threshold"(only used for axis): a float value in (-1.0, 1.0) which the button is
25# triggered if the axis value crosses
26# - "direction"(only used for axis): "+" means the button is triggered when the axis value
27# is greater than the threshold; "-" means the button is triggered when the axis value
28# is smaller than the threshold
29button_a=
30button_b=
31button_x=
32button_y=
33button_up=
34button_down=
35button_left=
36button_right=
37button_l=
38button_r=
39button_start=
40button_select=
41button_zl=
42button_zr=
43button_home=
44
45# for analog input, the following devices are available:
46# - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters:
47# - "up", "down", "left", "right": sub-devices for each direction.
48# Should be in the format as a button input devices using escape characters, for example, "engine$0keyboard$1code$00"
49# - "modifier": sub-devices as a modifier.
50# - "modifier_scale": a float number representing the applied modifier scale to the analog input.
51# Must be in range of 0.0-1.0. Defaults to 0.5
52# - "sdl" for joystick input using SDL. Required parameters:
53# - "joystick": the index of the joystick to bind
54# - "axis_x": the index of the axis to bind as x-axis (default to 0)
55# - "axis_y": the index of the axis to bind as y-axis (default to 1)
56circle_pad=
57c_stick=
58
59# for motion input, the following devices are available:
60# - "motion_emu" (default) for emulating motion input from mouse input. Required parameters:
61# - "update_period": update period in milliseconds (default to 100)
62# - "sensitivity": the coefficient converting mouse movement to tilting angle (default to 0.01)
63motion_device=
64
65# for touch input, the following devices are available:
66# - "emu_window" (default) for emulating touch input from mouse input to the emulation window. No parameters required
67touch_device=
68
69[Core]
70# Which CPU core to use for CPU emulation
71# 0 (default): Unicorn (slow), 1: Dynarmic (faster)
72cpu_core =
73
74[Renderer]
75# Whether to use software or hardware rendering.
76# 0: Software, 1 (default): Hardware
77use_hw_renderer =
78
79# Whether to use the Just-In-Time (JIT) compiler for shader emulation
80# 0: Interpreter (slow), 1 (default): JIT (fast)
81use_shader_jit =
82
83# Resolution scale factor
84# 0: Auto (scales resolution to window size), 1: Native 3DS screen resolution, Otherwise a scale
85# factor for the 3DS resolution
86resolution_factor =
87
88# Whether to enable V-Sync (caps the framerate at 60FPS) or not.
89# 0 (default): Off, 1: On
90use_vsync =
91
92# The clear color for the renderer. What shows up on the sides of the bottom screen.
93# Must be in range of 0.0-1.0. Defaults to 1.0 for all.
94bg_red =
95bg_blue =
96bg_green =
97
98[Layout]
99# Layout for the screen inside the render window.
100# 0 (default): Default Top Bottom Screen, 1: Single Screen Only, 2: Large Screen Small Screen
101layout_option =
102
103# Toggle custom layout (using the settings below) on or off.
104# 0 (default): Off , 1: On
105custom_layout =
106
107# Screen placement when using Custom layout option
108# 0x, 0y is the top left corner of the render window.
109custom_top_left =
110custom_top_top =
111custom_top_right =
112custom_top_bottom =
113custom_bottom_left =
114custom_bottom_top =
115custom_bottom_right =
116custom_bottom_bottom =
117
118#Whether to toggle frame limiter on or off.
119# 0: Off , 1 (default): On
120toggle_framelimit =
121
122# Swaps the prominent screen with the other screen.
123# For example, if Single Screen is chosen, setting this to 1 will display the bottom screen instead of the top screen.
124# 0 (default): Top Screen is prominent, 1: Bottom Screen is prominent
125swap_screen =
126
127[Audio]
128# Which audio output engine to use.
129# auto (default): Auto-select, null: No audio output, sdl2: SDL2 (if available)
130output_engine =
131
132# Whether or not to enable the audio-stretching post-processing effect.
133# This effect adjusts audio speed to match emulation speed and helps prevent audio stutter,
134# at the cost of increasing audio latency.
135# 0: No, 1 (default): Yes
136enable_audio_stretching =
137
138# Which audio device to use.
139# auto (default): Auto-select
140output_device =
141
142[Data Storage]
143# Whether to create a virtual SD card.
144# 1 (default): Yes, 0: No
145use_virtual_sd =
146
147[System]
148# The system model that Citra will try to emulate
149# 0: Old 3DS (default), 1: New 3DS
150is_new_3ds =
151
152# The system region that Citra will use during emulation
153# -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan
154region_value =
155
156[Miscellaneous]
157# A filter which removes logs below a certain logging level.
158# Examples: *:Debug Kernel.SVC:Trace Service.*:Critical
159log_filter = *:Info
160
161[Debugging]
162# Port for listening to GDB connections.
163use_gdbstub=false
164gdbstub_port=24689
165
166[WebService]
167# Whether or not to enable telemetry
168# 0: No, 1 (default): Yes
169enable_telemetry =
170# Endpoint URL for submitting telemetry data
171telemetry_endpoint_url = https://services.citra-emu.org/api/telemetry
172# Endpoint URL to verify the username and token
173verify_endpoint_url = https://services.citra-emu.org/api/profile
174# Username and token for Citra Web Service
175# See https://services.citra-emu.org/ for more info
176citra_username =
177citra_token =
178)";
179}
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
new file mode 100644
index 000000000..e65b04e4b
--- /dev/null
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
@@ -0,0 +1,177 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <cstdlib>
7#include <string>
8#define SDL_MAIN_HANDLED
9#include <SDL.h>
10#include <glad/glad.h>
11#include "citra/emu_window/emu_window_sdl2.h"
12#include "common/logging/log.h"
13#include "common/scm_rev.h"
14#include "common/string_util.h"
15#include "core/settings.h"
16#include "input_common/keyboard.h"
17#include "input_common/main.h"
18#include "input_common/motion_emu.h"
19#include "network/network.h"
20
21void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
22 TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0));
23 InputCommon::GetMotionEmu()->Tilt(x, y);
24}
25
26void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
27 if (button == SDL_BUTTON_LEFT) {
28 if (state == SDL_PRESSED) {
29 TouchPressed((unsigned)std::max(x, 0), (unsigned)std::max(y, 0));
30 } else {
31 TouchReleased();
32 }
33 } else if (button == SDL_BUTTON_RIGHT) {
34 if (state == SDL_PRESSED) {
35 InputCommon::GetMotionEmu()->BeginTilt(x, y);
36 } else {
37 InputCommon::GetMotionEmu()->EndTilt();
38 }
39 }
40}
41
42void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) {
43 if (state == SDL_PRESSED) {
44 InputCommon::GetKeyboard()->PressKey(key);
45 } else if (state == SDL_RELEASED) {
46 InputCommon::GetKeyboard()->ReleaseKey(key);
47 }
48}
49
50bool EmuWindow_SDL2::IsOpen() const {
51 return is_open;
52}
53
54void EmuWindow_SDL2::OnResize() {
55 int width, height;
56 SDL_GetWindowSize(render_window, &width, &height);
57 UpdateCurrentFramebufferLayout(width, height);
58}
59
60EmuWindow_SDL2::EmuWindow_SDL2() {
61 InputCommon::Init();
62 Network::Init();
63
64 SDL_SetMainReady();
65
66 // Initialize the window
67 if (SDL_Init(SDL_INIT_VIDEO) < 0) {
68 LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting...");
69 exit(1);
70 }
71
72 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
73 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
74 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
75 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
76 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
77 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
78 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
79 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
80
81 std::string window_title = Common::StringFromFormat("yuzu %s| %s-%s ", Common::g_build_name,
82 Common::g_scm_branch, Common::g_scm_desc);
83 render_window =
84 SDL_CreateWindow(window_title.c_str(),
85 SDL_WINDOWPOS_UNDEFINED, // x position
86 SDL_WINDOWPOS_UNDEFINED, // y position
87 Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height,
88 SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
89
90 if (render_window == nullptr) {
91 LOG_CRITICAL(Frontend, "Failed to create SDL2 window! Exiting...");
92 exit(1);
93 }
94
95 gl_context = SDL_GL_CreateContext(render_window);
96
97 if (gl_context == nullptr) {
98 LOG_CRITICAL(Frontend, "Failed to create SDL2 GL context! Exiting...");
99 exit(1);
100 }
101
102 if (!gladLoadGLLoader(static_cast<GLADloadproc>(SDL_GL_GetProcAddress))) {
103 LOG_CRITICAL(Frontend, "Failed to initialize GL functions! Exiting...");
104 exit(1);
105 }
106
107 OnResize();
108 OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size);
109 SDL_PumpEvents();
110 SDL_GL_SetSwapInterval(Settings::values.use_vsync);
111
112 DoneCurrent();
113}
114
115EmuWindow_SDL2::~EmuWindow_SDL2() {
116 SDL_GL_DeleteContext(gl_context);
117 SDL_Quit();
118
119 Network::Shutdown();
120 InputCommon::Shutdown();
121}
122
123void EmuWindow_SDL2::SwapBuffers() {
124 SDL_GL_SwapWindow(render_window);
125}
126
127void EmuWindow_SDL2::PollEvents() {
128 SDL_Event event;
129
130 // SDL_PollEvent returns 0 when there are no more events in the event queue
131 while (SDL_PollEvent(&event)) {
132 switch (event.type) {
133 case SDL_WINDOWEVENT:
134 switch (event.window.event) {
135 case SDL_WINDOWEVENT_SIZE_CHANGED:
136 case SDL_WINDOWEVENT_RESIZED:
137 case SDL_WINDOWEVENT_MAXIMIZED:
138 case SDL_WINDOWEVENT_RESTORED:
139 case SDL_WINDOWEVENT_MINIMIZED:
140 OnResize();
141 break;
142 case SDL_WINDOWEVENT_CLOSE:
143 is_open = false;
144 break;
145 }
146 break;
147 case SDL_KEYDOWN:
148 case SDL_KEYUP:
149 OnKeyEvent(static_cast<int>(event.key.keysym.scancode), event.key.state);
150 break;
151 case SDL_MOUSEMOTION:
152 OnMouseMotion(event.motion.x, event.motion.y);
153 break;
154 case SDL_MOUSEBUTTONDOWN:
155 case SDL_MOUSEBUTTONUP:
156 OnMouseButton(event.button.button, event.button.state, event.button.x, event.button.y);
157 break;
158 case SDL_QUIT:
159 is_open = false;
160 break;
161 }
162 }
163}
164
165void EmuWindow_SDL2::MakeCurrent() {
166 SDL_GL_MakeCurrent(render_window, gl_context);
167}
168
169void EmuWindow_SDL2::DoneCurrent() {
170 SDL_GL_MakeCurrent(render_window, nullptr);
171}
172
173void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(
174 const std::pair<unsigned, unsigned>& minimal_size) {
175
176 SDL_SetWindowMinimumSize(render_window, minimal_size.first, minimal_size.second);
177}
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
new file mode 100644
index 000000000..3664d2fbe
--- /dev/null
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
@@ -0,0 +1,59 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <utility>
9#include "core/frontend/emu_window.h"
10
11struct SDL_Window;
12
13class EmuWindow_SDL2 : public EmuWindow {
14public:
15 EmuWindow_SDL2();
16 ~EmuWindow_SDL2();
17
18 /// Swap buffers to display the next frame
19 void SwapBuffers() override;
20
21 /// Polls window events
22 void PollEvents() override;
23
24 /// Makes the graphics context current for the caller thread
25 void MakeCurrent() override;
26
27 /// Releases the GL context from the caller thread
28 void DoneCurrent() override;
29
30 /// Whether the window is still open, and a close request hasn't yet been sent
31 bool IsOpen() const;
32
33private:
34 /// Called by PollEvents when a key is pressed or released.
35 void OnKeyEvent(int key, u8 state);
36
37 /// Called by PollEvents when the mouse moves.
38 void OnMouseMotion(s32 x, s32 y);
39
40 /// Called by PollEvents when a mouse button is pressed or released
41 void OnMouseButton(u32 button, u8 state, s32 x, s32 y);
42
43 /// Called by PollEvents when any event that may cause the window to be resized occurs
44 void OnResize();
45
46 /// Called when a configuration change affects the minimal size of the window
47 void OnMinimalClientAreaChangeRequest(
48 const std::pair<unsigned, unsigned>& minimal_size) override;
49
50 /// Is the window still open?
51 bool is_open = true;
52
53 /// Internal SDL2 render window
54 SDL_Window* render_window;
55
56 using SDL_GLContext = void*;
57 /// The OpenGL context associated with the window
58 SDL_GLContext gl_context;
59};
diff --git a/src/yuzu_cmd/resource.h b/src/yuzu_cmd/resource.h
new file mode 100644
index 000000000..df8e459e4
--- /dev/null
+++ b/src/yuzu_cmd/resource.h
@@ -0,0 +1,16 @@
1//{{NO_DEPENDENCIES}}
2// Microsoft Visual C++ generated include file.
3// Used by pcafe.rc
4//
5#define IDI_ICON3 103
6
7// Next default values for new objects
8//
9#ifdef APSTUDIO_INVOKED
10#ifndef APSTUDIO_READONLY_SYMBOLS
11#define _APS_NEXT_RESOURCE_VALUE 105
12#define _APS_NEXT_COMMAND_VALUE 40001
13#define _APS_NEXT_CONTROL_VALUE 1001
14#define _APS_NEXT_SYMED_VALUE 101
15#endif
16#endif