summaryrefslogtreecommitdiffstats
path: root/src/frontend/mame/ui/utils.cpp
blob: 5ad21c6839cc5743f0e473ae41a0b68ab2c79173 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
// license:BSD-3-Clause
// copyright-holders:Maurizio Petrarota
/***************************************************************************

    ui/utils.cpp

    Internal UI user interface.

***************************************************************************/

#include "emu.h"
#include "ui/utils.h"

extern const char UI_VERSION_TAG[];
const char UI_VERSION_TAG[] = "# UI INFO ";

// Years index
UINT16 c_year::actual = 0;
std::vector<std::string> c_year::ui;

// Manufacturers index
UINT16 c_mnfct::actual = 0;
std::vector<std::string> c_mnfct::ui;
std::unordered_map<std::string, int> c_mnfct::uimap;

// Main filters
UINT16 main_filters::actual = 0;
const char *main_filters::text[] = { "All", "Available", "Unavailable", "Working", "Not Working", "Mechanical", "Not Mechanical",
	"Category", "Favorites", "BIOS", "Parents", "Clones", "Manufacturers", "Years", "Support Save",
	"Not Support Save", "CHD", "No CHD", "Vertical", "Horizontal", "Custom" };
size_t main_filters::length = ARRAY_LENGTH(main_filters::text);

// Software filters
UINT16 sw_filters::actual = 0;
const char *sw_filters::text[] = { "All", "Available", "Unavailable", "Parents", "Clones", "Years", "Publishers", "Supported",
	"Partial Supported", "Unsupported", "Region", "Device Type", "Software List", "Custom" };
size_t sw_filters::length = ARRAY_LENGTH(sw_filters::text);

// Globals
UINT8 ui_globals::rpanel = 0;
UINT8 ui_globals::curimage_view = 0;
UINT8 ui_globals::curdats_view = 0;
UINT8 ui_globals::cur_sw_dats_view = 0;
bool ui_globals::switch_image = false;
bool ui_globals::default_image = true;
bool ui_globals::reset = false;
bool ui_globals::redraw_icon = false;
int ui_globals::visible_main_lines = 0;
int ui_globals::visible_sw_lines = 0;
UINT16 ui_globals::panels_status = 0;
bool ui_globals::has_icons = false;

// Custom filter
UINT16 custfltr::main = 0;
UINT16 custfltr::numother = 0;
UINT16 custfltr::other[MAX_CUST_FILTER];
UINT16 custfltr::mnfct[MAX_CUST_FILTER];
UINT16 custfltr::year[MAX_CUST_FILTER];
UINT16 custfltr::screen[MAX_CUST_FILTER];

// Custom filter
UINT16 sw_custfltr::main = 0;
UINT16 sw_custfltr::numother = 0;
UINT16 sw_custfltr::other[MAX_CUST_FILTER];
UINT16 sw_custfltr::mnfct[MAX_CUST_FILTER];
UINT16 sw_custfltr::year[MAX_CUST_FILTER];
UINT16 sw_custfltr::region[MAX_CUST_FILTER];
UINT16 sw_custfltr::type[MAX_CUST_FILTER];
UINT16 sw_custfltr::list[MAX_CUST_FILTER];

char* chartrimcarriage(char str[])
{
	char *pstr = strrchr(str, '\n');
	if (pstr)
		str[pstr - str] = '\0';
	pstr = strrchr(str, '\r');
	if (pstr)
		str[pstr - str] = '\0';
	return str;
}

const char* strensure(const char* s)
{
	return s == nullptr ? "" : s;
}

int getprecisionchr(const char* s)
{
	int precision = 1;
	char *dp = const_cast<char *>(strchr(s, '.'));
	if (dp != nullptr)
		precision = strlen(s) - (dp - s) - 1;
	return precision;
}

std::vector<std::string> tokenize(const std::string &text, char sep)
{
	std::vector<std::string> tokens;
	tokens.reserve(64);
	std::size_t start = 0, end = 0;
	while ((end = text.find(sep, start)) != std::string::npos) 
	{
		std::string temp = text.substr(start, end - start);
		if (!temp.empty()) tokens.push_back(temp);
		start = end + 1;
	}
	std::string temp = text.substr(start);
	if (!temp.empty()) tokens.push_back(temp);
	return tokens;
}

//-------------------------------------------------
//  search a substring with even partial matching
//-------------------------------------------------

int fuzzy_substring(std::string s_needle, std::string s_haystack)
{
	if (s_needle.empty())
		return s_haystack.size();
	if (s_haystack.empty())
		return s_needle.size();

	strmakelower(s_needle);
	strmakelower(s_haystack);

	if (s_needle == s_haystack)
		return 0;
	if (s_haystack.find(s_needle) != std::string::npos)
		return 0;

	auto *row1 = global_alloc_array_clear<int>(s_haystack.size() + 2);
	auto *row2 = global_alloc_array_clear<int>(s_haystack.size() + 2);

	for (int i = 0; i < s_needle.size(); ++i)
	{
		row2[0] = i + 1;
		for (int j = 0; j < s_haystack.size(); ++j)
		{
			int cost = (s_needle[i] == s_haystack[j]) ? 0 : 1;
			row2[j + 1] = MIN(row1[j + 1] + 1, MIN(row2[j] + 1, row1[j] + cost));
		}

		int *tmp = row1;
		row1 = row2;
		row2 = tmp;
	}

	int *first, *smallest;
	first = smallest = row1;
	int *last = row1 + s_haystack.size();

	while (++first != last)
		if (*first < *smallest)
			smallest = first;

	int rv = *smallest;
	global_free_array(row1);
	global_free_array(row2);

	return rv;
}

//-------------------------------------------------
//  set manufacturers
//-------------------------------------------------

void c_mnfct::set(const char *str)
{
	std::string name = getname(str);
	uimap[name] = 0;
}

std::string c_mnfct::getname(const char *str)
{
	std::string name(str);
	size_t found = name.find("(");

	if (found != std::string::npos)
		return (name.substr(0, found - 1));
	else
		return name;
}

//-------------------------------------------------
//  set years
//-------------------------------------------------

void c_year::set(const char *str)
{
	std::string name(str);
	if (std::find(ui.begin(), ui.end(), name) != ui.end())
		return;

	ui.push_back(name);
}
pan class="w"> SDLOPTION_KEYBINDEX "4", OSDOPTVAL_AUTO, OPTION_STRING, "name of keyboard mapped to keyboard #4" }, { SDLOPTION_KEYBINDEX "5", OSDOPTVAL_AUTO, OPTION_STRING, "name of keyboard mapped to keyboard #5" }, { SDLOPTION_KEYBINDEX "6", OSDOPTVAL_AUTO, OPTION_STRING, "name of keyboard mapped to keyboard #6" }, { SDLOPTION_KEYBINDEX "7", OSDOPTVAL_AUTO, OPTION_STRING, "name of keyboard mapped to keyboard #7" }, { SDLOPTION_KEYBINDEX "8", OSDOPTVAL_AUTO, OPTION_STRING, "name of keyboard mapped to keyboard #8" }, // SDL low level driver options { nullptr, nullptr, OPTION_HEADER, "SDL LOWLEVEL DRIVER OPTIONS" }, { SDLOPTION_VIDEODRIVER ";vd", OSDOPTVAL_AUTO, OPTION_STRING, "sdl video driver to use ('x11', 'directfb', ... or 'auto' for SDL default" }, { SDLOPTION_RENDERDRIVER ";rd", OSDOPTVAL_AUTO, OPTION_STRING, "sdl render driver to use ('software', 'opengl', 'directfb' ... or 'auto' for SDL default" }, { SDLOPTION_AUDIODRIVER ";ad", OSDOPTVAL_AUTO, OPTION_STRING, "sdl audio driver to use ('alsa', 'arts', ... or 'auto' for SDL default" }, #if USE_OPENGL { SDLOPTION_GL_LIB, SDLOPTVAL_GLLIB, OPTION_STRING, "alternative libGL.so to use; 'auto' for system default" }, #endif // End of list { nullptr } }; //============================================================ // sdl_options //============================================================ sdl_options::sdl_options() : osd_options() { std::string ini_path(INI_PATH); add_entries(sdl_options::s_option_entries); strreplace(ini_path,"APP_NAME", emulator_info::get_appname_lower()); set_default_value(SDLOPTION_INIPATH, ini_path.c_str()); } //============================================================ // main //============================================================ // we do some special sauce on Win32... #if defined(SDLMAME_WIN32) /* gee */ extern "C" DECLSPEC void SDLCALL SDL_SetModuleHandle(void *hInst); #endif // translated to utf8_main #if defined(SDLMAME_WIN32) int main(std::vector<std::string> &args) { #else int main(int argc, char** argv) { std::vector<std::string> args(argv, argv+argc); #endif int res = 0; // disable I/O buffering setvbuf(stdout, (char *) nullptr, _IONBF, 0); setvbuf(stderr, (char *) nullptr, _IONBF, 0); // Initialize crash diagnostics diagnostics_module::get_instance()->init_crash_diagnostics(); #if defined(SDLMAME_ANDROID) /* Enable standard application logging */ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_VERBOSE); #endif // FIXME: this should be done differently #ifdef SDLMAME_UNIX sdl_entered_debugger = 0; #if (!defined(SDLMAME_MACOSX)) && (!defined(SDLMAME_HAIKU)) && (!defined(SDLMAME_EMSCRIPTEN)) && (!defined(SDLMAME_ANDROID)) FcInit(); #endif #endif { sdl_options options; sdl_osd_interface osd(options); osd.register_options(); res = emulator_info::start_frontend(options, osd, args); } #ifdef SDLMAME_UNIX #if (!defined(SDLMAME_MACOSX)) && (!defined(SDLMAME_HAIKU)) && (!defined(SDLMAME_EMSCRIPTEN)) && (!defined(SDLMAME_ANDROID)) if (!sdl_entered_debugger) { FcFini(); } #endif #endif exit(res); } //============================================================ // constructor //============================================================ sdl_osd_interface::sdl_osd_interface(sdl_options &options) : osd_common_t(options), m_options(options) { } //============================================================ // destructor //============================================================ sdl_osd_interface::~sdl_osd_interface() { } //============================================================ // osd_exit //============================================================ void sdl_osd_interface::osd_exit() { osd_common_t::osd_exit(); SDL_QuitSubSystem(SDL_INIT_VIDEO); } //============================================================ // defines_verbose //============================================================ #define MAC_EXPAND_STR(_m) #_m #define MACRO_VERBOSE(_mac) \ do { \ if (strcmp(MAC_EXPAND_STR(_mac), #_mac) != 0) \ osd_printf_verbose("%s=%s ", #_mac, MAC_EXPAND_STR(_mac)); \ } while (0) #define _SDL_VER #SDL_MAJOR_VERSION "." #SDL_MINOR_VERSION "." #SDL_PATCHLEVEL static void defines_verbose(void) { osd_printf_verbose("Build version: %s\n", emulator_info::get_build_version()); osd_printf_verbose("Build architecure: "); MACRO_VERBOSE(SDLMAME_ARCH); osd_printf_verbose("\n"); osd_printf_verbose("Build defines 1: "); MACRO_VERBOSE(SDLMAME_UNIX); MACRO_VERBOSE(SDLMAME_X11); MACRO_VERBOSE(SDLMAME_WIN32); MACRO_VERBOSE(SDLMAME_MACOSX); MACRO_VERBOSE(SDLMAME_DARWIN); MACRO_VERBOSE(SDLMAME_LINUX); MACRO_VERBOSE(SDLMAME_SOLARIS); MACRO_VERBOSE(SDLMAME_IRIX); MACRO_VERBOSE(SDLMAME_BSD); osd_printf_verbose("\n"); osd_printf_verbose("Build defines 1: "); MACRO_VERBOSE(LSB_FIRST); MACRO_VERBOSE(PTR64); MACRO_VERBOSE(MAME_NOASM); MACRO_VERBOSE(MAME_DEBUG); MACRO_VERBOSE(BIGENDIAN); MACRO_VERBOSE(CPP_COMPILE); MACRO_VERBOSE(SYNC_IMPLEMENTATION); osd_printf_verbose("\n"); osd_printf_verbose("SDL/OpenGL defines: "); osd_printf_verbose("SDL_COMPILEDVERSION=%d ", SDL_COMPILEDVERSION); MACRO_VERBOSE(USE_OPENGL); MACRO_VERBOSE(USE_DISPATCH_GL); osd_printf_verbose("\n"); osd_printf_verbose("Compiler defines A: "); MACRO_VERBOSE(__GNUC__); MACRO_VERBOSE(__GNUC_MINOR__); MACRO_VERBOSE(__GNUC_PATCHLEVEL__); MACRO_VERBOSE(__VERSION__); osd_printf_verbose("\n"); osd_printf_verbose("Compiler defines B: "); MACRO_VERBOSE(__amd64__); MACRO_VERBOSE(__x86_64__); MACRO_VERBOSE(__unix__); MACRO_VERBOSE(__i386__); MACRO_VERBOSE(__ppc__); MACRO_VERBOSE(__ppc64__); osd_printf_verbose("\n"); osd_printf_verbose("Compiler defines C: "); MACRO_VERBOSE(_FORTIFY_SOURCE); MACRO_VERBOSE(__USE_FORTIFY_LEVEL); osd_printf_verbose("\n"); } //============================================================ // osd_sdl_info //============================================================ static void osd_sdl_info(void) { int i, num = SDL_GetNumVideoDrivers(); osd_printf_verbose("Available videodrivers: "); for (i=0;i<num;i++) { const char *name = SDL_GetVideoDriver(i); osd_printf_verbose("%s ", name); } osd_printf_verbose("\n"); osd_printf_verbose("Current Videodriver: %s\n", SDL_GetCurrentVideoDriver()); num = SDL_GetNumVideoDisplays(); for (i=0;i<num;i++) { SDL_DisplayMode mode; int j; osd_printf_verbose("\tDisplay #%d\n", i); if (SDL_GetDesktopDisplayMode(i, &mode)) osd_printf_verbose("\t\tDesktop Mode: %dx%d-%d@%d\n", mode.w, mode.h, SDL_BITSPERPIXEL(mode.format), mode.refresh_rate); if (SDL_GetCurrentDisplayMode(i, &mode)) osd_printf_verbose("\t\tCurrent Display Mode: %dx%d-%d@%d\n", mode.w, mode.h, SDL_BITSPERPIXEL(mode.format), mode.refresh_rate); osd_printf_verbose("\t\tRenderdrivers:\n"); for (j=0; j<SDL_GetNumRenderDrivers(); j++) { SDL_RendererInfo info; SDL_GetRenderDriverInfo(j, &info); osd_printf_verbose("\t\t\t%10s (%dx%d)\n", info.name, info.max_texture_width, info.max_texture_height); } } osd_printf_verbose("Available audio drivers: \n"); num = SDL_GetNumAudioDrivers(); for (i=0;i<num;i++) { osd_printf_verbose("\t%-20s\n", SDL_GetAudioDriver(i)); } } //============================================================ // video_register //============================================================ void sdl_osd_interface::video_register() { video_options_add("soft", nullptr); #if USE_OPENGL video_options_add("opengl", nullptr); #endif video_options_add("bgfx", nullptr); //video_options_add("auto", nullptr); // making d3d video default one } //============================================================ // output_oslog //============================================================ void sdl_osd_interface::output_oslog(const char *buffer) { fputs(buffer, stderr); } //============================================================ // init //============================================================ void sdl_osd_interface::init(running_machine &machine) { // call our parent osd_common_t::init(machine); const char *stemp; // determine if we are benchmarking, and adjust options appropriately int bench = options().bench(); if (bench > 0) { options().set_value(OPTION_THROTTLE, false, OPTION_PRIORITY_MAXIMUM); options().set_value(OSDOPTION_SOUND, "none", OPTION_PRIORITY_MAXIMUM); options().set_value(OSDOPTION_VIDEO, "none", OPTION_PRIORITY_MAXIMUM); options().set_value(OPTION_SECONDS_TO_RUN, bench, OPTION_PRIORITY_MAXIMUM); } // Some driver options - must be before audio init! stemp = options().audio_driver(); if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) != 0) { osd_printf_verbose("Setting SDL audiodriver '%s' ...\n", stemp); osd_setenv(SDLENV_AUDIODRIVER, stemp, 1); } stemp = options().video_driver(); if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) != 0) { osd_printf_verbose("Setting SDL videodriver '%s' ...\n", stemp); osd_setenv(SDLENV_VIDEODRIVER, stemp, 1); } stemp = options().render_driver(); if (stemp != nullptr) { if (strcmp(stemp, OSDOPTVAL_AUTO) != 0) { osd_printf_verbose("Setting SDL renderdriver '%s' ...\n", stemp); //osd_setenv(SDLENV_RENDERDRIVER, stemp, 1); SDL_SetHint(SDL_HINT_RENDER_DRIVER, stemp); } else { #if defined(SDLMAME_WIN32) // OpenGL renderer has less issues with mode switching on windows osd_printf_verbose("Setting SDL renderdriver '%s' ...\n", "opengl"); //osd_setenv(SDLENV_RENDERDRIVER, stemp, 1); SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"); #endif } } /* Set the SDL environment variable for drivers wanting to load the * lib at startup. */ #if USE_OPENGL /* FIXME: move lib loading code from drawogl.c here */ stemp = options().gl_lib(); if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) != 0) { osd_setenv("SDL_VIDEO_GL_DRIVER", stemp, 1); osd_printf_verbose("Setting SDL_VIDEO_GL_DRIVER = '%s' ...\n", stemp); } #endif /* get number of processors */ stemp = options().numprocessors(); osd_num_processors = 0; if (strcmp(stemp, "auto") != 0) { osd_num_processors = atoi(stemp); if (osd_num_processors < 1) { osd_printf_warning("numprocessors < 1 doesn't make much sense. Assuming auto ...\n"); osd_num_processors = 0; } } /* Initialize SDL */ if (SDL_InitSubSystem(SDL_INIT_VIDEO)) { osd_printf_error("Could not initialize SDL %s\n", SDL_GetError()); exit(-1); } osd_sdl_info(); defines_verbose(); osd_common_t::init_subsystems(); if (options().oslog()) { using namespace std::placeholders; machine.add_logerror_callback(std::bind(&sdl_osd_interface::output_oslog, this, _1)); } #ifdef SDLMAME_EMSCRIPTEN SDL_EventState(SDL_TEXTINPUT, SDL_FALSE); #else SDL_EventState(SDL_TEXTINPUT, SDL_TRUE); #endif }