summaryrefslogtreecommitdiff
path: root/src/yuzu_cmd/citra.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuzu_cmd/citra.cpp')
-rw-r--r--src/yuzu_cmd/citra.cpp175
1 files changed, 175 insertions, 0 deletions
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}