1 #include "retro_common.h"
2 #include "retro_input.h"
3 
4 struct RomBiosInfo neogeo_bioses[] = {
5 	{"sp-s3.sp1",         0x91b64be3, 0x00, "MVS Asia/Europe ver. 6 (1 slot)", NEOGEO_MVS | NEOGEO_EUR, 0 },
6 	{"sp-s2.sp1",         0x9036d879, 0x01, "MVS Asia/Europe ver. 5 (1 slot)", NEOGEO_MVS | NEOGEO_EUR, 0 },
7 	{"sp-s.sp1",          0xc7f2fa45, 0x02, "MVS Asia/Europe ver. 3 (4 slot)", NEOGEO_MVS | NEOGEO_EUR, 0 },
8 	{"sp-45.sp1",         0x03cc9f6a, 0x0b, "NEO-MVH MV1C (Asia)"            , NEOGEO_MVS | NEOGEO_EUR, 0 },
9 	{"sp-u2.sp1",         0xe72943de, 0x03, "MVS USA ver. 5 (2 slot)"        , NEOGEO_MVS | NEOGEO_USA, 0 },
10 	{"sp1-u2",            0x62f021f4, 0x04, "MVS USA ver. 5 (4 slot)"        , NEOGEO_MVS | NEOGEO_USA, 0 },
11 	{"sp-e.sp1",          0x2723a5b5, 0x05, "MVS USA ver. 5 (6 slot)"        , NEOGEO_MVS | NEOGEO_USA, 0 },
12 	{"sp1-u4.bin",        0x1179a30f, 0x06, "MVS USA (U4)"                   , NEOGEO_MVS | NEOGEO_USA, 0 },
13 	{"sp1-u3.bin",        0x2025b7a2, 0x07, "MVS USA (U3)"                   , NEOGEO_MVS | NEOGEO_USA, 0 },
14 	{"vs-bios.rom",       0xf0e8f27d, 0x08, "MVS Japan ver. 6 (? slot)"      , NEOGEO_MVS | NEOGEO_JAP, 0 },
15 	{"sp-j2.sp1",         0xacede59C, 0x09, "MVS Japan ver. 5 (? slot)"      , NEOGEO_MVS | NEOGEO_JAP, 0 },
16 	{"sp1.jipan.1024",    0x9fb0abe4, 0x0a, "MVS Japan ver. 3 (4 slot)"      , NEOGEO_MVS | NEOGEO_JAP, 0 },
17 	{"sp-j3.sp1",         0x486cb450, 0x0c, "NEO-MVH MV1C (Japan)"           , NEOGEO_MVS | NEOGEO_JAP, 0 },
18 	{"japan-j3.bin",      0xdff6d41f, 0x0d, "MVS Japan (J3)"                 , NEOGEO_MVS | NEOGEO_JAP, 0 },
19 	{"sp1-j3.bin",        0xfbc6d469, 0x0e, "MVS Japan (J3, alt)"            , NEOGEO_MVS | NEOGEO_JAP, 0 },
20 	{"neo-epo.bin",       0xd27a71f1, 0x10, "AES Asia"                       , NEOGEO_AES | NEOGEO_EUR, 0 },
21 	{"neo-po.bin",        0x16d0c132, 0x0f, "AES Japan"                      , NEOGEO_AES | NEOGEO_JAP, 0 },
22 	{"uni-bios_4_0.rom",  0xa7aab458, 0x13, "Universe BIOS ver. 4.0"         , NEOGEO_UNI, 0 },
23 	{"uni-bios_3_3.rom",  0x24858466, 0x14, "Universe BIOS ver. 3.3"         , NEOGEO_UNI, 0 },
24 	{"uni-bios_3_2.rom",  0xa4e8b9b3, 0x15, "Universe BIOS ver. 3.2"         , NEOGEO_UNI, 0 },
25 	{"uni-bios_3_1.rom",  0x0c58093f, 0x16, "Universe BIOS ver. 3.1"         , NEOGEO_UNI, 0 },
26 	{"uni-bios_3_0.rom",  0xa97c89a9, 0x17, "Universe BIOS ver. 3.0"         , NEOGEO_UNI, 0 },
27 	{"uni-bios_2_3.rom",  0x27664eb5, 0x18, "Universe BIOS ver. 2.3"         , NEOGEO_UNI, 0 },
28 	{"uni-bios_2_3o.rom", 0x601720ae, 0x19, "Universe BIOS ver. 2.3 (alt)"   , NEOGEO_UNI, 0 },
29 	{"uni-bios_2_2.rom",  0x2d50996a, 0x1a, "Universe BIOS ver. 2.2"         , NEOGEO_UNI, 0 },
30 	{"uni-bios_2_1.rom",  0x8dabf76b, 0x1b, "Universe BIOS ver. 2.1"         , NEOGEO_UNI, 0 },
31 	{"uni-bios_2_0.rom",  0x0c12c2ad, 0x1c, "Universe BIOS ver. 2.0"         , NEOGEO_UNI, 0 },
32 	{"uni-bios_1_3.rom",  0xb24b44a0, 0x1d, "Universe BIOS ver. 1.3"         , NEOGEO_UNI, 0 },
33 	{"uni-bios_1_2.rom",  0x4fa698e9, 0x1e, "Universe BIOS ver. 1.2"         , NEOGEO_UNI, 0 },
34 	{"uni-bios_1_2o.rom", 0xe19d3ce9, 0x1f, "Universe BIOS ver. 1.2 (alt)"   , NEOGEO_UNI, 0 },
35 	{"uni-bios_1_1.rom",  0x5dda0d84, 0x20, "Universe BIOS ver. 1.1"         , NEOGEO_UNI, 0 },
36 	{"uni-bios_1_0.rom",  0x0ce453a0, 0x21, "Universe BIOS ver. 1.0"         , NEOGEO_UNI, 0 },
37 	{NULL, 0, 0, NULL, 0 }
38 };
39 
40 std::vector<dipswitch_core_option> dipswitch_core_options;
41 struct GameInp *pgi_reset;
42 struct GameInp *pgi_diag;
43 bool is_neogeo_game = false;
44 bool allow_neogeo_mode = true;
45 bool neogeo_use_specific_default_bios = false;
46 bool bAllowDepth32 = false;
47 bool bLightgunHideCrosshairEnabled = true;
48 bool bPatchedRomsetsEnabled = true;
49 bool bLibretroSupportsAudioBuffStatus = false;
50 bool bLowPassFilterEnabled = false;
51 UINT32 nVerticalMode = 0;
52 UINT32 nFrameskip = 1;
53 INT32 g_audio_samplerate = 48000;
54 UINT32 nMemcardMode = 0;
55 UINT8 *diag_input;
56 uint32_t g_opt_neo_geo_mode = 0;
57 
58 #ifdef USE_CYCLONE
59 // 0 - c68k, 1 - m68k
60 // we don't use cyclone by default because it breaks savestates cross-platform compatibility (including netplay)
61 int nSekCpuCore = 1;
62 static bool bCycloneEnabled = false;
63 #endif
64 
65 static UINT8 diag_input_start[] =       {RETRO_DEVICE_ID_JOYPAD_START,  RETRO_DEVICE_ID_JOYPAD_EMPTY };
66 static UINT8 diag_input_start_a_b[] =   {RETRO_DEVICE_ID_JOYPAD_START,  RETRO_DEVICE_ID_JOYPAD_A, RETRO_DEVICE_ID_JOYPAD_B, RETRO_DEVICE_ID_JOYPAD_EMPTY };
67 static UINT8 diag_input_start_l_r[] =   {RETRO_DEVICE_ID_JOYPAD_START,  RETRO_DEVICE_ID_JOYPAD_L, RETRO_DEVICE_ID_JOYPAD_R, RETRO_DEVICE_ID_JOYPAD_EMPTY };
68 static UINT8 diag_input_select[] =      {RETRO_DEVICE_ID_JOYPAD_SELECT, RETRO_DEVICE_ID_JOYPAD_EMPTY };
69 static UINT8 diag_input_select_a_b[] =  {RETRO_DEVICE_ID_JOYPAD_SELECT, RETRO_DEVICE_ID_JOYPAD_A, RETRO_DEVICE_ID_JOYPAD_B, RETRO_DEVICE_ID_JOYPAD_EMPTY };
70 static UINT8 diag_input_select_l_r[] =  {RETRO_DEVICE_ID_JOYPAD_SELECT, RETRO_DEVICE_ID_JOYPAD_L, RETRO_DEVICE_ID_JOYPAD_R, RETRO_DEVICE_ID_JOYPAD_EMPTY };
71 
72 // Global core options
73 static const struct retro_core_option_v2_definition var_empty = { NULL, NULL, NULL, NULL, NULL, NULL, {{0}}, NULL };
74 static const struct retro_core_option_v2_definition var_fbneo_allow_depth_32 = {
75 	"fbneo-allow-depth-32",
76 	"Use 32-bits color depth when available",
77 	NULL,
78 	"Change pixel format, some games require this to render properly, it could impact performances on some platforms",
79 	NULL,
80 	NULL,
81 	{
82 		{ "disabled", NULL },
83 		{ "enabled", NULL },
84 		{ NULL, NULL },
85 	},
86 	"enabled"
87 };
88 static const struct retro_core_option_v2_definition var_fbneo_vertical_mode = {
89 	"fbneo-vertical-mode",
90 	"Vertical mode",
91 	NULL,
92 	"Rotate display for vertical screens",
93 	NULL,
94 	NULL,
95 	{
96 		{ "disabled", NULL },
97 		{ "enabled", NULL },
98 		{ "alternate", NULL },
99 		{ NULL, NULL },
100 	},
101 	"disabled"
102 };
103 static const struct retro_core_option_v2_definition var_fbneo_fixed_frameskip = {
104 	"fbneo-fixed-frameskip",
105 	"Fixed Frameskip",
106 	NULL,
107 	"When 'Frameskip' is set to 'Fixed', or if the frontend doesn't support the alternative 'Frameskip' mode, skip rendering at a fixed rate of X frames out of X+1",
108 	NULL,
109 	"frameskip",
110 	{
111 		{ "0", "No skipping" },
112 		{ "1", "Skip rendering of 1 frames out of 2" },
113 		{ "2", "Skip rendering of 2 frames out of 3" },
114 		{ "3", "Skip rendering of 3 frames out of 4" },
115 		{ "4", "Skip rendering of 4 frames out of 5" },
116 		{ "5", "Skip rendering of 5 frames out of 6" },
117 		{ NULL, NULL },
118 	},
119 	"0"
120 };
121 static const struct retro_core_option_v2_definition var_fbneo_frameskip_type = {
122 	"fbneo-frameskip-type",
123 	"Frameskip",
124 	NULL,
125 	"Skip frames to avoid audio buffer under-run (crackling). Improves performance at the expense of visual smoothness. 'Auto' skips frames when advised by the frontend. 'Manual' uses the 'Frameskip Threshold (%)' setting. 'Fixed' uses the 'Fixed Frameskip' setting.",
126 	NULL,
127 	"frameskip",
128 	{
129 		{ "disabled", NULL },
130 		{ "Fixed", NULL },
131 		{ "Auto", NULL },
132 		{ "Manual", NULL },
133 		{ NULL, NULL },
134 	},
135 	"disabled"
136 };
137 static const struct retro_core_option_v2_definition var_fbneo_frameskip_manual_threshold = {
138 	"fbneo-frameskip-manual-threshold",
139 	"Frameskip Threshold (%)",
140 	NULL,
141 	"When 'Frameskip' is set to 'Manual', specifies the audio buffer occupancy threshold (percentage) below which frames will be skipped. Higher values reduce the risk of crackling by causing frames to be dropped more frequently.",
142 	NULL,
143 	"frameskip",
144 	{
145 		{ "15", NULL },
146 		{ "18", NULL },
147 		{ "21", NULL },
148 		{ "24", NULL },
149 		{ "27", NULL },
150 		{ "30", NULL },
151 		{ "33", NULL },
152 		{ "36", NULL },
153 		{ "39", NULL },
154 		{ "42", NULL },
155 		{ "45", NULL },
156 		{ "48", NULL },
157 		{ "51", NULL },
158 		{ "54", NULL },
159 		{ "57", NULL },
160 		{ "60", NULL },
161 		{ NULL, NULL },
162 	},
163 	"33"
164 };
165 static const struct retro_core_option_v2_definition var_fbneo_cpu_speed_adjust = {
166 	"fbneo-cpu-speed-adjust",
167 	"CPU clock",
168 	NULL,
169 	"Change emulated cpu frequency for various systems, by increasing you can fix native slowdowns in some games, by decreasing you can help performance on low-end devices",
170 	NULL,
171 	NULL,
172 	{
173 		PERCENT_VALUES
174 	},
175 	"100%"
176 };
177 static const struct retro_core_option_v2_definition var_fbneo_diagnostic_input = {
178 	"fbneo-diagnostic-input",
179 	"Diagnostic Input",
180 	NULL,
181 	"Configure button combination to enter cabinet service menu",
182 	NULL,
183 	NULL,
184 	{
185 		{ "None", NULL },
186 		{ "Hold Start", NULL },
187 		{ "Start + A + B", NULL },
188 		{ "Hold Start + A + B", NULL },
189 		{ "Start + L + R", NULL },
190 		{ "Hold Start + L + R", NULL },
191 		{ "Hold Select", NULL },
192 		{ "Select + A + B", NULL },
193 		{ "Hold Select + A + B", NULL },
194 		{ "Select + L + R", NULL },
195 		{ "Hold Select + L + R", NULL },
196 		{ NULL, NULL },
197 	},
198 	"Hold Start"
199 };
200 static const struct retro_core_option_v2_definition var_fbneo_hiscores = {
201 	"fbneo-hiscores",
202 	"Hiscores",
203 	NULL,
204 	"Enable high scores support, you also need the file hiscore.dat in your system/fbneo/ folder",
205 	NULL,
206 	NULL,
207 	{
208 		{ "disabled", NULL },
209 		{ "enabled", NULL },
210 		{ NULL, NULL },
211 	},
212 	"enabled"
213 };
214 static const struct retro_core_option_v2_definition var_fbneo_allow_patched_romsets = {
215 	"fbneo-allow-patched-romsets",
216 	"Allow patched romsets",
217 	NULL,
218 	"Allow romsets from your system/fbneo/patched/ folder to override your romsets, crcs will be ignored but sizes and names must still match, you need to close content for this setting to take effect",
219 	NULL,
220 	NULL,
221 	{
222 		{ "disabled", NULL },
223 		{ "enabled", NULL },
224 		{ NULL, NULL },
225 	},
226 	"enabled"
227 };
228 static const struct retro_core_option_v2_definition var_fbneo_samplerate = {
229 	"fbneo-samplerate",
230 	"Samplerate",
231 	NULL,
232 	"Configure samplerate, it could impact performances, closing & starting game again is required",
233 	NULL,
234 	"audio",
235 	{
236 		{ "44100", NULL },
237 		{ "48000", NULL },
238 		{ NULL, NULL },
239 	},
240 	"48000"
241 };
242 static const struct retro_core_option_v2_definition var_fbneo_sample_interpolation = {
243 	"fbneo-sample-interpolation",
244 	"Sample Interpolation",
245 	NULL,
246 	"Configure sample interpolation, it could impact performances",
247 	NULL,
248 	"audio",
249 	{
250 		{ "disabled", NULL },
251 		{ "2-point 1st order", NULL },
252 		{ "4-point 3rd order", NULL },
253 		{ NULL, NULL },
254 	},
255 	"4-point 3rd order"
256 };
257 static const struct retro_core_option_v2_definition var_fbneo_fm_interpolation = {
258 	"fbneo-fm-interpolation",
259 	"FM Interpolation",
260 	NULL,
261 	"Configure FM interpolation, it could impact performances",
262 	NULL,
263 	"audio",
264 	{
265 		{ "disabled", NULL },
266 		{ "4-point 3rd order", NULL },
267 		{ NULL, NULL },
268 	},
269 	"4-point 3rd order"
270 };
271 static const struct retro_core_option_v2_definition var_fbneo_lowpass_filter = {
272 	"fbneo-lowpass-filter",
273 	"LowPass Filter",
274 	NULL,
275 	"Enable LowPass Filter",
276 	NULL,
277 	"audio",
278 	{
279 		{ "disabled", NULL },
280 		{ "enabled", NULL },
281 		{ NULL, NULL },
282 	},
283 	"disabled"
284 };
285 static const struct retro_core_option_v2_definition var_fbneo_analog_speed = {
286 	"fbneo-analog-speed",
287 	"Analog Speed",
288 	NULL,
289 	"Mitigate analog controls speed, some games might require low values to be playable",
290 	NULL,
291 	NULL,
292 	{
293 		PERCENT_VALUES
294 	},
295 	"100%"
296 };
297 static const struct retro_core_option_v2_definition var_fbneo_lightgun_hide_crosshair = {
298 	"fbneo-lightgun-hide-crosshair",
299 	"No crosshair with lightgun device",
300 	NULL,
301 	"Hide crosshair if you play with a lightgun device",
302 	NULL,
303 	NULL,
304 	{
305 		{ "disabled", NULL },
306 		{ "enabled", NULL },
307 		{ NULL, NULL },
308 	},
309 	"enabled"
310 };
311 #ifdef USE_CYCLONE
312 static const struct retro_core_option_v2_definition var_fbneo_cyclone = {
313 	"fbneo-cyclone",
314 	"Enable cyclone",
315 	NULL,
316 	"Use at your own risk, it could improve performance on some emulated systems for low-end devices, but there are known side effects : savestates won't be compatible with normal interpreter, and some systems won't work",
317 	NULL,
318 	NULL,
319 	{
320 		{ "disabled", NULL },
321 		{ "enabled", NULL },
322 		{ NULL, NULL },
323 	},
324 	"disabled"
325 };
326 #endif
327 
328 // Neo Geo core options
329 static const struct retro_core_option_v2_definition var_fbneo_neogeo_mode = {
330 	"fbneo-neogeo-mode",
331 	"Neo-Geo mode",
332 	NULL,
333 	"Load appropriate bios depending on your choice, under the condition such a bios is compatible with the running game",
334 	NULL,
335 	NULL,
336 	{
337 		{ "DIPSWITCH", "Use bios set in BIOS dipswitch" },
338 		{ "MVS_EUR", "MVS Europe/Asia (English)" },
339 		{ "MVS_USA", "MVS USA (English - Censored)" },
340 		{ "MVS_JAP", "MVS Japan (Japanese)" },
341 		{ "AES_EUR", "AES Europe/Asia (English)" },
342 		{ "AES_JAP", "AES Japan (Japanese)" },
343 		{ "UNIBIOS", "UNIBIOS" },
344 		{ NULL, NULL },
345 	},
346 	"DIPSWITCH"
347 };
348 static const struct retro_core_option_v2_definition var_fbneo_memcard_mode = {
349 	"fbneo-memcard-mode",
350 	"Memory card mode",
351 	NULL,
352 	"Change the behavior for the memory card",
353 	NULL,
354 	NULL,
355 	{
356 		{ "disabled", NULL },
357 		{ "shared", NULL },
358 		{ "per-game", NULL },
359 		{ NULL, NULL },
360 	},
361 	"disabled"
362 };
363 
364 #ifdef FBNEO_DEBUG
365 static const struct retro_core_option_v2_definition var_fbneo_debug_layer_1 = {
366 	"fbneo-debug-layer-1",
367 	"Layer 1",
368 	NULL,
369 	"For debugging",
370 	NULL,
371 	"debug",
372 	{
373 		{ "disabled", NULL },
374 		{ "enabled", NULL },
375 		{ NULL, NULL },
376 	},
377 	"enabled"
378 };
379 static const struct retro_core_option_v2_definition var_fbneo_debug_layer_2 = {
380 	"fbneo-debug-layer-2",
381 	"Layer 2",
382 	NULL,
383 	"For debugging",
384 	NULL,
385 	"debug",
386 	{
387 		{ "disabled", NULL },
388 		{ "enabled", NULL },
389 		{ NULL, NULL },
390 	},
391 	"enabled"
392 };
393 static const struct retro_core_option_v2_definition var_fbneo_debug_layer_3 = {
394 	"fbneo-debug-layer-3",
395 	"Layer 3",
396 	NULL,
397 	"For debugging",
398 	NULL,
399 	"debug",
400 	{
401 		{ "disabled", NULL },
402 		{ "enabled", NULL },
403 		{ NULL, NULL },
404 	},
405 	"enabled"
406 };
407 static const struct retro_core_option_v2_definition var_fbneo_debug_layer_4 = {
408 	"fbneo-debug-layer-4",
409 	"Layer 4",
410 	NULL,
411 	"For debugging",
412 	NULL,
413 	"debug",
414 	{
415 		{ "disabled", NULL },
416 		{ "enabled", NULL },
417 		{ NULL, NULL },
418 	},
419 	"enabled"
420 };
421 static const struct retro_core_option_v2_definition var_fbneo_debug_sprite_1 = {
422 	"fbneo-debug-sprite-1",
423 	"Sprite 1",
424 	NULL,
425 	"For debugging",
426 	NULL,
427 	"debug",
428 	{
429 		{ "disabled", NULL },
430 		{ "enabled", NULL },
431 		{ NULL, NULL },
432 	},
433 	"enabled"
434 };
435 static const struct retro_core_option_v2_definition var_fbneo_debug_sprite_2 = {
436 	"fbneo-debug-sprite-2",
437 	"Sprite 2",
438 	NULL,
439 	"For debugging",
440 	NULL,
441 	"debug",
442 	{
443 		{ "disabled", NULL },
444 		{ "enabled", NULL },
445 		{ NULL, NULL },
446 	},
447 	"enabled"
448 };
449 static const struct retro_core_option_v2_definition var_fbneo_debug_sprite_3 = {
450 	"fbneo-debug-sprite-3",
451 	"Sprite 3",
452 	NULL,
453 	"For debugging",
454 	NULL,
455 	"debug",
456 	{
457 		{ "disabled", NULL },
458 		{ "enabled", NULL },
459 		{ NULL, NULL },
460 	},
461 	"enabled"
462 };
463 static const struct retro_core_option_v2_definition var_fbneo_debug_sprite_4 = {
464 	"fbneo-debug-sprite-4",
465 	"Sprite 4",
466 	NULL,
467 	"For debugging",
468 	NULL,
469 	"debug",
470 	{
471 		{ "disabled", NULL },
472 		{ "enabled", NULL },
473 		{ NULL, NULL },
474 	},
475 	"enabled"
476 };
477 static const struct retro_core_option_v2_definition var_fbneo_debug_sprite_5 = {
478 	"fbneo-debug-sprite-5",
479 	"Sprite 5",
480 	NULL,
481 	"For debugging",
482 	NULL,
483 	"debug",
484 	{
485 		{ "disabled", NULL },
486 		{ "enabled", NULL },
487 		{ NULL, NULL },
488 	},
489 	"enabled"
490 };
491 static const struct retro_core_option_v2_definition var_fbneo_debug_sprite_6 = {
492 	"fbneo-debug-sprite-6",
493 	"Sprite 6",
494 	NULL,
495 	"For debugging",
496 	NULL,
497 	"debug",
498 	{
499 		{ "disabled", NULL },
500 		{ "enabled", NULL },
501 		{ NULL, NULL },
502 	},
503 	"enabled"
504 };
505 static const struct retro_core_option_v2_definition var_fbneo_debug_sprite_7 = {
506 	"fbneo-debug-sprite-7",
507 	"Sprite 7",
508 	NULL,
509 	"For debugging",
510 	NULL,
511 	"debug",
512 	{
513 		{ "disabled", NULL },
514 		{ "enabled", NULL },
515 		{ NULL, NULL },
516 	},
517 	"enabled"
518 };
519 static const struct retro_core_option_v2_definition var_fbneo_debug_sprite_8 = {
520 	"fbneo-debug-sprite-8",
521 	"Sprite 8",
522 	NULL,
523 	"For debugging",
524 	NULL,
525 	"debug",
526 	{
527 		{ "disabled", NULL },
528 		{ "enabled", NULL },
529 		{ NULL, NULL },
530 	},
531 	"enabled"
532 };
533 #endif
534 
535 // Replace the char c_find by the char c_replace in the destination c string
str_char_replace(char * destination,char c_find,char c_replace)536 char* str_char_replace(char* destination, char c_find, char c_replace)
537 {
538 	for (unsigned str_idx = 0; str_idx < strlen(destination); str_idx++)
539 	{
540 		if (destination[str_idx] == c_find)
541 			destination[str_idx] = c_replace;
542 	}
543 
544 	return destination;
545 }
546 
set_neogeo_bios_availability(char * szName,uint32_t crc,bool ignoreCrc)547 void set_neogeo_bios_availability(char *szName, uint32_t crc, bool ignoreCrc)
548 {
549 	for (int i = 0; neogeo_bioses[i].filename != NULL; i++)
550 	{
551 		if ((strcmp(neogeo_bioses[i].filename, szName) == 0 && ignoreCrc) || neogeo_bioses[i].crc == crc)
552 		{
553 			neogeo_bioses[i].available = 1;
554 			return;
555 		}
556 	}
557 }
558 
find_neogeo_bios(uint32_t categories)559 static RomBiosInfo* find_neogeo_bios(uint32_t categories)
560 {
561 	for (int i = 0; neogeo_bioses[i].filename != NULL; i++)
562 	{
563 		if (neogeo_bioses[i].categories == categories && neogeo_bioses[i].available == 1)
564 		{
565 			return &neogeo_bioses[i];
566 		}
567 	}
568 
569 	return NULL;
570 }
571 
set_neo_system_bios()572 void set_neo_system_bios()
573 {
574 	if (g_opt_neo_geo_mode == 0)
575 	{
576 		// Nothing to do in DIPSWITCH mode because the NeoSystem variable is changed by the DIP Switch core option
577 		log_cb(RETRO_LOG_INFO, "DIPSWITCH Neo Geo Mode selected => NeoSystem: 0x%02x.\n", NeoSystem);
578 	}
579 	else
580 	{
581 		RomBiosInfo *available_neogeo_bios = find_neogeo_bios(g_opt_neo_geo_mode);
582 		NeoSystem &= ~(UINT8)0x1f;
583 		if (available_neogeo_bios)
584 		{
585 			NeoSystem |= available_neogeo_bios->NeoSystem;
586 			log_cb(RETRO_LOG_INFO, "Found this bios for requested mode => NeoSystem: 0x%02x (%s [0x%08x] (%s)).\n", NeoSystem, available_neogeo_bios->filename, available_neogeo_bios->crc, available_neogeo_bios->friendly_name);
587 		}
588 		else
589 		{
590 			log_cb(RETRO_LOG_INFO, "No bios found for requested mode, falling back to DIPSWITCH => NeoSystem: 0x%02x.\n", NeoSystem);
591 		}
592 	}
593 }
594 
evaluate_neogeo_bios_mode(const char * drvname)595 void evaluate_neogeo_bios_mode(const char* drvname)
596 {
597 	if (!is_neogeo_game)
598 		return;
599 
600 	bool is_bios_dipswitch_found = false;
601 
602 	// search the BIOS dipswitch
603 	for (int dip_idx = 0; dip_idx < dipswitch_core_options.size(); dip_idx++)
604 	{
605 		if (dipswitch_core_options[dip_idx].friendly_name.compare("[Dipswitch] BIOS") == 0)
606 		{
607 			is_bios_dipswitch_found = true;
608 			if (dipswitch_core_options[dip_idx].values.size() > 0)
609 			{
610 				// if the default is different than 0, this means that a different Bios is needed
611 				if (dipswitch_core_options[dip_idx].default_bdi.nSetting != 0x00)
612 				{
613 					neogeo_use_specific_default_bios = true;
614 					break;
615 				}
616 			}
617 		}
618 	}
619 
620 	// Games without the BIOS dipswitch don't handle alternative bioses very well
621 	if (!is_bios_dipswitch_found)
622 	{
623 		neogeo_use_specific_default_bios = true;
624 	}
625 
626 	if (neogeo_use_specific_default_bios)
627 	{
628 		// disable the NeoGeo mode core option
629 		allow_neogeo_mode = false;
630 
631 		// set the NeoGeo mode to DIPSWITCH to rely on the Default Bios Dipswitch
632 		g_opt_neo_geo_mode = 0;
633 	}
634 }
635 
set_environment()636 void set_environment()
637 {
638 	std::vector<const retro_core_option_v2_definition*> vars_systems;
639 	struct retro_core_option_v2_definition *option_defs_us;
640 #ifdef _MSC_VER
641 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
642 	#ifndef FORCE_USE_VFS
643 	#define FORCE_USE_VFS
644     #endif
645 #endif
646 #endif
647 
648 #ifdef FORCE_USE_VFS
649 	struct retro_vfs_interface_info vfs_iface_info;
650 #endif
651 
652 	// Add the Global core options
653 	vars_systems.push_back(&var_fbneo_allow_depth_32);
654 	vars_systems.push_back(&var_fbneo_vertical_mode);
655 	if (BurnDrvGetFlags() & BDF_HISCORE_SUPPORTED)
656 		vars_systems.push_back(&var_fbneo_hiscores);
657 	vars_systems.push_back(&var_fbneo_allow_patched_romsets);
658 	vars_systems.push_back(&var_fbneo_analog_speed);
659 	vars_systems.push_back(&var_fbneo_lightgun_hide_crosshair);
660 #ifdef USE_CYCLONE
661 	vars_systems.push_back(&var_fbneo_cyclone);
662 #endif
663 
664 	if (pgi_diag)
665 	{
666 		vars_systems.push_back(&var_fbneo_diagnostic_input);
667 	}
668 
669 	if (is_neogeo_game)
670 	{
671 		// Add the Neo Geo core options
672 		if (allow_neogeo_mode)
673 			vars_systems.push_back(&var_fbneo_neogeo_mode);
674 		vars_systems.push_back(&var_fbneo_memcard_mode);
675 	}
676 	vars_systems.push_back(&var_fbneo_cpu_speed_adjust);
677 
678 	// Frameskip settings
679 	if (bLibretroSupportsAudioBuffStatus)
680 	{
681 		vars_systems.push_back(&var_fbneo_frameskip_type);
682 		vars_systems.push_back(&var_fbneo_frameskip_manual_threshold);
683 	}
684 	vars_systems.push_back(&var_fbneo_fixed_frameskip);
685 
686 	// Audio settings
687 	if (nGameType != RETRO_GAME_TYPE_NEOCD)
688 		vars_systems.push_back(&var_fbneo_samplerate);
689 	vars_systems.push_back(&var_fbneo_sample_interpolation);
690 	vars_systems.push_back(&var_fbneo_fm_interpolation);
691 	vars_systems.push_back(&var_fbneo_lowpass_filter);
692 
693 #ifdef FBNEO_DEBUG
694 	// Debug settings
695 	vars_systems.push_back(&var_fbneo_debug_layer_1);
696 	vars_systems.push_back(&var_fbneo_debug_layer_2);
697 	vars_systems.push_back(&var_fbneo_debug_layer_3);
698 	vars_systems.push_back(&var_fbneo_debug_layer_4);
699 	vars_systems.push_back(&var_fbneo_debug_sprite_1);
700 	vars_systems.push_back(&var_fbneo_debug_sprite_2);
701 	vars_systems.push_back(&var_fbneo_debug_sprite_3);
702 	vars_systems.push_back(&var_fbneo_debug_sprite_4);
703 	vars_systems.push_back(&var_fbneo_debug_sprite_5);
704 	vars_systems.push_back(&var_fbneo_debug_sprite_6);
705 	vars_systems.push_back(&var_fbneo_debug_sprite_7);
706 	vars_systems.push_back(&var_fbneo_debug_sprite_8);
707 #endif
708 
709 	int nbr_vars = vars_systems.size();
710 	int nbr_dips = dipswitch_core_options.size();
711 	int nbr_cheats = cheat_core_options.size();
712 
713 #if 0
714 	log_cb(RETRO_LOG_INFO, "set_environment: SYSTEM: %d, DIPSWITCH: %d\n", nbr_vars, nbr_dips);
715 #endif
716 
717 	option_defs_us = (struct retro_core_option_v2_definition*)calloc(nbr_vars + nbr_dips + nbr_cheats + 1, sizeof(struct retro_core_option_v2_definition));
718 
719 	int idx_var = 0;
720 
721 	// Add the System core options
722 	for (int i = 0; i < nbr_vars; i++, idx_var++)
723 	{
724 		option_defs_us[idx_var] = *vars_systems[i];
725 	}
726 
727 	// Add the DIP switches core options
728 	for (int dip_idx = 0; dip_idx < nbr_dips; dip_idx++)
729 	{
730 		option_defs_us[idx_var].category_key     = "dipswitch";
731 		option_defs_us[idx_var].key              = dipswitch_core_options[dip_idx].option_name.c_str();
732 		option_defs_us[idx_var].desc             = dipswitch_core_options[dip_idx].friendly_name.c_str();
733 		option_defs_us[idx_var].desc_categorized = dipswitch_core_options[dip_idx].friendly_name_categorized.c_str();
734 		option_defs_us[idx_var].default_value    = dipswitch_core_options[dip_idx].default_bdi.szText;
735 		// Instead of filtering out the dips, make the description a warning if it's a neogeo game using a different default bios
736 		if (neogeo_use_specific_default_bios && is_neogeo_game && dipswitch_core_options[dip_idx].friendly_name.compare("[Dipswitch] BIOS") == 0)
737 			option_defs_us[idx_var].info         = "THIS NEOGEO GAME USES A DIFFERENT DEFAULT BIOS, CHANGE IT AT YOUR OWN RISK";
738 		else
739 			option_defs_us[idx_var].info         = "Dipswitch setting, setting is specific to the running romset";
740 		for (int dip_value_idx = 0; dip_value_idx < dipswitch_core_options[dip_idx].values.size(); dip_value_idx++)
741 		{
742 			option_defs_us[idx_var].values[dip_value_idx].value = dipswitch_core_options[dip_idx].values[dip_value_idx].friendly_name.c_str();
743 		}
744 		option_defs_us[idx_var].values[dipswitch_core_options[dip_idx].values.size()].value = NULL;
745 		if (option_defs_us[idx_var].default_value == NULL) HandleMessage(RETRO_LOG_ERROR, "Default value for '%s' not found, it's a bug, please report it\n", option_defs_us[idx_var].desc);
746 		idx_var++;
747 	}
748 
749 	// Add the cheats core options
750 	for (int cheat_idx = 0; cheat_idx < nbr_cheats; cheat_idx++)
751 	{
752 		option_defs_us[idx_var].category_key     = "cheat";
753 		option_defs_us[idx_var].key              = cheat_core_options[cheat_idx].option_name.c_str();
754 		option_defs_us[idx_var].desc             = cheat_core_options[cheat_idx].friendly_name.c_str();
755 		option_defs_us[idx_var].desc_categorized = cheat_core_options[cheat_idx].friendly_name_categorized.c_str();
756 		option_defs_us[idx_var].default_value    = cheat_core_options[cheat_idx].default_value.c_str();
757 		option_defs_us[idx_var].info             = "Specific to the running romset and your cheat database";
758 		for (int cheat_value_idx = 0; cheat_value_idx < cheat_core_options[cheat_idx].values.size(); cheat_value_idx++)
759 		{
760 			option_defs_us[idx_var].values[cheat_value_idx].value = cheat_core_options[cheat_idx].values[cheat_value_idx].friendly_name.c_str();
761 		}
762 		option_defs_us[idx_var].values[cheat_core_options[cheat_idx].values.size()].value = NULL;
763 		idx_var++;
764 	}
765 
766 	option_defs_us[idx_var] = var_empty;
767 
768 	static struct retro_core_option_v2_category option_cats_us[] =
769 	{
770 		{
771 			"frameskip",
772 			"Frameskip Settings",
773 			"Configure Frameskip Settings"
774 		},
775 		{
776 			"audio",
777 			"Audio Settings",
778 			"Configure Audio Settings"
779 		},
780 		{
781 			"dipswitch",
782 			"DIP Switches",
783 			"Configure DIP Switches"
784 		},
785 		{
786 			"cheat",
787 			"Cheat",
788 			"Enable Cheats"
789 		},
790 #ifdef FBNEO_DEBUG
791 		{
792 			"debug",
793 			"Debug",
794 			"Configure Debug Features"
795 		},
796 #endif
797 		{ NULL, NULL, NULL },
798 	};
799 
800 	struct retro_core_options_v2 options_us = {
801 		option_cats_us,
802 		option_defs_us
803 	};
804 
805 	bool libretro_supports_option_categories = false;
806 	unsigned version = 0;
807 
808 	if (!environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version))
809 		version = 0;
810 
811 	if (version >= 2)
812 	{
813 		libretro_supports_option_categories = environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2, &options_us);
814 	}
815 	else
816 	{
817 		size_t i, j;
818 		size_t num_options                                     = 0;
819 		struct retro_core_option_definition *option_v1_defs_us = NULL;
820 		struct retro_variable *variables                       = NULL;
821 		char **values_buf                                      = NULL;
822 
823 		/* Determine total number of options */
824 		while (true)
825 		{
826 			if (option_defs_us[num_options].key)
827 				num_options++;
828 			else
829 				break;
830 		}
831 
832 		if (version >= 1)
833 		{
834 			/* Allocate US array */
835 			option_v1_defs_us = (struct retro_core_option_definition *)calloc(num_options + 1, sizeof(struct retro_core_option_definition));
836 
837 			/* Copy parameters from option_defs_us array */
838 			for (i = 0; i < num_options; i++)
839 			{
840 				struct retro_core_option_v2_definition *option_def_us = &option_defs_us[i];
841 				struct retro_core_option_value *option_values         = option_def_us->values;
842 				struct retro_core_option_definition *option_v1_def_us = &option_v1_defs_us[i];
843 				struct retro_core_option_value *option_v1_values      = option_v1_def_us->values;
844 
845 				option_v1_def_us->key           = option_def_us->key;
846 				option_v1_def_us->desc          = option_def_us->desc;
847 				option_v1_def_us->info          = option_def_us->info;
848 				option_v1_def_us->default_value = option_def_us->default_value;
849 
850 				/* Values must be copied individually... */
851 				while (option_values->value)
852 				{
853 					option_v1_values->value = option_values->value;
854 					option_v1_values->label = option_values->label;
855 
856 					option_values++;
857 					option_v1_values++;
858 				}
859 			}
860 
861 			environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS, option_v1_defs_us);
862 		}
863 		else
864 		{
865 
866 			/* Allocate arrays */
867 			variables  = (struct retro_variable *)calloc(num_options + 1, sizeof(struct retro_variable));
868 			values_buf = (char **)calloc(num_options, sizeof(char *));
869 
870 			if (!variables || !values_buf)
871 				goto error;
872 
873 			/* Copy parameters from option_defs_us array */
874 			for (i = 0; i < num_options; i++)
875 			{
876 				const char *key                        = option_defs_us[i].key;
877 				const char *desc                       = option_defs_us[i].desc;
878 				const char *default_value              = option_defs_us[i].default_value;
879 				struct retro_core_option_value *values = option_defs_us[i].values;
880 				size_t buf_len                         = 3;
881 				size_t default_index                   = 0;
882 
883 				values_buf[i] = NULL;
884 
885 				if (desc)
886 				{
887 					size_t num_values = 0;
888 
889 					/* Determine number of values */
890 					while (true)
891 					{
892 						if (values[num_values].value)
893 						{
894 							/* Check if this is the default value */
895 							if (default_value)
896 								if (strcmp(values[num_values].value, default_value) == 0)
897 									default_index = num_values;
898 
899 							buf_len += strlen(values[num_values].value);
900 							num_values++;
901 						}
902 						else
903 							break;
904 					}
905 
906 					if (num_values > 0)
907 					{
908 
909 						buf_len += num_values - 1;
910 						buf_len += strlen(desc);
911 
912 						values_buf[i] = (char *)calloc(buf_len, sizeof(char));
913 						if (!values_buf[i])
914 							goto error;
915 
916 						strcpy(values_buf[i], desc);
917 						strcat(values_buf[i], "; ");
918 
919 						/* Default value goes first */
920 						strcat(values_buf[i], values[default_index].value);
921 
922 						/* Add remaining values */
923 						for (j = 0; j < num_values; j++)
924 						{
925 							if (j != default_index)
926 							{
927 								strcat(values_buf[i], "|");
928 								strcat(values_buf[i], values[j].value);
929 							}
930 						}
931 					}
932 				}
933 
934 				variables[i].key   = key;
935 				variables[i].value = values_buf[i];
936 			}
937 
938 			/* Set variables */
939 			environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables);
940 
941 		}
942 
943 error:
944 		/* Clean up */
945 
946 		if (option_v1_defs_us)
947 		{
948 			free(option_v1_defs_us);
949 			option_v1_defs_us = NULL;
950 		}
951 
952 		if (values_buf)
953 		{
954 			for (i = 0; i < num_options; i++)
955 			{
956 				if (values_buf[i])
957 				{
958 					free(values_buf[i]);
959 					values_buf[i] = NULL;
960 				}
961 			}
962 
963 			free(values_buf);
964 			values_buf = NULL;
965 		}
966 
967 		if (variables)
968 		{
969 			free(variables);
970 			variables = NULL;
971 		}
972 	}
973 
974 	// Initialize VFS
975 	// Only on UWP for now, since EEPROM saving is not VFS aware
976 #ifdef FORCE_USE_VFS
977 	vfs_iface_info.required_interface_version = FILESTREAM_REQUIRED_VFS_VERSION;
978 	vfs_iface_info.iface                      = NULL;
979 	if (environ_cb(RETRO_ENVIRONMENT_GET_VFS_INTERFACE, &vfs_iface_info))
980 		filestream_vfs_init(&vfs_iface_info);
981 #endif
982 }
983 
percent_parser(const char * value)984 static int percent_parser(const char *value)
985 {
986 	INT32 nVal = atoi(value);
987 	if (nVal == 0)
988 		nVal = 100;
989 
990 	return (int)((double)nVal * 256.0 / 100.0 + 0.5);
991 }
992 
check_variables(void)993 void check_variables(void)
994 {
995 	struct retro_variable var = {0};
996 
997 	var.key = var_fbneo_cpu_speed_adjust.key;
998 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
999 	{
1000 		nBurnCPUSpeedAdjust = percent_parser(var.value);
1001 	}
1002 
1003 	var.key = var_fbneo_allow_depth_32.key;
1004 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1005 	{
1006 		if (strcmp(var.value, "enabled") == 0)
1007 			bAllowDepth32 = true;
1008 		else
1009 			bAllowDepth32 = false;
1010 	}
1011 
1012 	var.key = var_fbneo_vertical_mode.key;
1013 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1014 	{
1015 		if (strcmp(var.value, "enabled") == 0)
1016 			nVerticalMode = 1;
1017 		else if (strcmp(var.value, "alternate") == 0)
1018 			nVerticalMode = 2;
1019 		else
1020 			nVerticalMode = 0;
1021 	}
1022 
1023 	if (bLibretroSupportsAudioBuffStatus)
1024 	{
1025 		var.key = var_fbneo_frameskip_type.key;
1026 		if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1027 		{
1028 			if (strcmp(var.value, "disabled") == 0)
1029 				nFrameskipType = 0;
1030 			else if (strcmp(var.value, "Fixed") == 0)
1031 				nFrameskipType = 1;
1032 			else if (strcmp(var.value, "Auto") == 0)
1033 				nFrameskipType = 2;
1034 			else if (strcmp(var.value, "Manual") == 0)
1035 				nFrameskipType = 3;
1036 		}
1037 
1038 		var.key = var_fbneo_frameskip_manual_threshold.key;
1039 		if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1040 			nFrameskipThreshold = strtol(var.value, NULL, 10);
1041 	}
1042 
1043 	var.key = var_fbneo_fixed_frameskip.key;
1044 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1045 	{
1046 		if (strcmp(var.value, "0") == 0)
1047 			nFrameskip = 1;
1048 		else if (strcmp(var.value, "1") == 0)
1049 			nFrameskip = 2;
1050 		else if (strcmp(var.value, "2") == 0)
1051 			nFrameskip = 3;
1052 		else if (strcmp(var.value, "3") == 0)
1053 			nFrameskip = 4;
1054 		else if (strcmp(var.value, "4") == 0)
1055 			nFrameskip = 5;
1056 		else if (strcmp(var.value, "5") == 0)
1057 			nFrameskip = 6;
1058 	}
1059 
1060 	if (pgi_diag)
1061 	{
1062 		var.key = var_fbneo_diagnostic_input.key;
1063 		if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1064 		{
1065 			if (strcmp(var.value, "Hold Start") == 0)
1066 			{
1067 				diag_input = diag_input_start;
1068 				SetDiagInpHoldFrameDelay(60);
1069 			}
1070 			else if(strcmp(var.value, "Start + A + B") == 0)
1071 			{
1072 				diag_input = diag_input_start_a_b;
1073 				SetDiagInpHoldFrameDelay(0);
1074 			}
1075 			else if(strcmp(var.value, "Hold Start + A + B") == 0)
1076 			{
1077 				diag_input = diag_input_start_a_b;
1078 				SetDiagInpHoldFrameDelay(60);
1079 			}
1080 			else if(strcmp(var.value, "Start + L + R") == 0)
1081 			{
1082 				diag_input = diag_input_start_l_r;
1083 				SetDiagInpHoldFrameDelay(0);
1084 			}
1085 			else if(strcmp(var.value, "Hold Start + L + R") == 0)
1086 			{
1087 				diag_input = diag_input_start_l_r;
1088 				SetDiagInpHoldFrameDelay(60);
1089 			}
1090 			else if(strcmp(var.value, "Hold Select") == 0)
1091 			{
1092 				diag_input = diag_input_select;
1093 				SetDiagInpHoldFrameDelay(60);
1094 			}
1095 			else if(strcmp(var.value, "Select + A + B") == 0)
1096 			{
1097 				diag_input = diag_input_select_a_b;
1098 				SetDiagInpHoldFrameDelay(0);
1099 			}
1100 			else if(strcmp(var.value, "Hold Select + A + B") == 0)
1101 			{
1102 				diag_input = diag_input_select_a_b;
1103 				SetDiagInpHoldFrameDelay(60);
1104 			}
1105 			else if(strcmp(var.value, "Select + L + R") == 0)
1106 			{
1107 				diag_input = diag_input_select_l_r;
1108 				SetDiagInpHoldFrameDelay(0);
1109 			}
1110 			else if(strcmp(var.value, "Hold Select + L + R") == 0)
1111 			{
1112 				diag_input = diag_input_select_l_r;
1113 				SetDiagInpHoldFrameDelay(60);
1114 			}
1115 			else
1116 			{
1117 				diag_input = NULL;
1118 				SetDiagInpHoldFrameDelay(0);
1119 			}
1120 		}
1121 	}
1122 
1123 	if (is_neogeo_game)
1124 	{
1125 		if (allow_neogeo_mode)
1126 		{
1127 			var.key = var_fbneo_neogeo_mode.key;
1128 			if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1129 			{
1130 				if (strcmp(var.value, "MVS_EUR") == 0)
1131 					g_opt_neo_geo_mode = NEOGEO_MVS | NEOGEO_EUR;
1132 				else if (strcmp(var.value, "MVS_USA") == 0)
1133 					g_opt_neo_geo_mode = NEOGEO_MVS | NEOGEO_USA;
1134 				else if (strcmp(var.value, "MVS_JAP") == 0)
1135 					g_opt_neo_geo_mode = NEOGEO_MVS | NEOGEO_JAP;
1136 				else if (strcmp(var.value, "AES_EUR") == 0)
1137 					g_opt_neo_geo_mode = NEOGEO_AES | NEOGEO_EUR;
1138 				else if (strcmp(var.value, "AES_JAP") == 0)
1139 					g_opt_neo_geo_mode = NEOGEO_AES | NEOGEO_JAP;
1140 				else if (strcmp(var.value, "UNIBIOS") == 0)
1141 					g_opt_neo_geo_mode = NEOGEO_UNI;
1142 				else
1143 					g_opt_neo_geo_mode = 0;
1144 			}
1145 		}
1146 		var.key = var_fbneo_memcard_mode.key;
1147 		if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1148 		{
1149 			if (strcmp(var.value, "disabled") == 0)
1150 				nMemcardMode = 0;
1151 			else if (strcmp(var.value, "shared") == 0)
1152 				nMemcardMode = 1;
1153 			else if (strcmp(var.value, "per-game") == 0)
1154 				nMemcardMode = 2;
1155 		}
1156 	}
1157 
1158 	if (BurnDrvGetFlags() & BDF_HISCORE_SUPPORTED)
1159 	{
1160 		var.key = var_fbneo_hiscores.key;
1161 		if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1162 		{
1163 			if (strcmp(var.value, "enabled") == 0)
1164 				EnableHiscores = true;
1165 			else
1166 				EnableHiscores = false;
1167 		}
1168 	}
1169 	else
1170 	{
1171 		EnableHiscores = false;
1172 	}
1173 
1174 	var.key = var_fbneo_allow_patched_romsets.key;
1175 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1176 	{
1177 		if (strcmp(var.value, "enabled") == 0)
1178 			bPatchedRomsetsEnabled = true;
1179 		else
1180 			bPatchedRomsetsEnabled = false;
1181 	}
1182 
1183 	if (nGameType != RETRO_GAME_TYPE_NEOCD)
1184 	{
1185 		var.key = var_fbneo_samplerate.key;
1186 		if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1187 		{
1188 			if (strcmp(var.value, "48000") == 0)
1189 				g_audio_samplerate = 48000;
1190 			else if (strcmp(var.value, "44100") == 0)
1191 				g_audio_samplerate = 44100;
1192 			else
1193 				g_audio_samplerate = 48000;
1194 		}
1195 	}
1196 	else
1197 	{
1198 		// src/burn/drv/neogeo/neo_run.cpp is mentioning issues with ngcd cdda playback if samplerate isn't 44100
1199 		g_audio_samplerate = 44100;
1200 	}
1201 
1202 	var.key = var_fbneo_sample_interpolation.key;
1203 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1204 	{
1205 		if (strcmp(var.value, "4-point 3rd order") == 0)
1206 			nInterpolation = 3;
1207 		else if (strcmp(var.value, "2-point 1st order") == 0)
1208 			nInterpolation = 1;
1209 		else if (strcmp(var.value, "disabled") == 0)
1210 			nInterpolation = 0;
1211 		else
1212 			nInterpolation = 3;
1213 	}
1214 
1215 	var.key = var_fbneo_fm_interpolation.key;
1216 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1217 	{
1218 		if (strcmp(var.value, "4-point 3rd order") == 0)
1219 			nFMInterpolation = 3;
1220 		else if (strcmp(var.value, "disabled") == 0)
1221 			nFMInterpolation = 0;
1222 		else
1223 			nFMInterpolation = 3;
1224 	}
1225 
1226 	var.key = var_fbneo_lowpass_filter.key;
1227 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1228 	{
1229 		if (strcmp(var.value, "enabled") == 0)
1230 			bLowPassFilterEnabled = true;
1231 		else
1232 			bLowPassFilterEnabled = false;
1233 	}
1234 
1235 	var.key = var_fbneo_analog_speed.key;
1236 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1237 	{
1238 		nAnalogSpeed = percent_parser(var.value);
1239 	}
1240 
1241 	var.key = var_fbneo_lightgun_hide_crosshair.key;
1242 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1243 	{
1244 		if (strcmp(var.value, "enabled") == 0)
1245 			bLightgunHideCrosshairEnabled = true;
1246 		else if (strcmp(var.value, "disabled") == 0)
1247 			bLightgunHideCrosshairEnabled = false;
1248 		RefreshLightgunCrosshair();
1249 	}
1250 
1251 #ifdef USE_CYCLONE
1252 	var.key = var_fbneo_cyclone.key;
1253 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1254 	{
1255 		if (strcmp(var.value, "enabled") == 0)
1256 			bCycloneEnabled = true;
1257 		else if (strcmp(var.value, "disabled") == 0)
1258 			bCycloneEnabled = false;
1259 	}
1260 #endif
1261 
1262 #ifdef FBNEO_DEBUG
1263 	var.key = var_fbneo_debug_layer_1.key;
1264 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1265 	{
1266 		if (strcmp(var.value, "enabled") == 0)
1267 			nBurnLayer |= 1;
1268 		else if (strcmp(var.value, "disabled") == 0)
1269 			nBurnLayer &= ~1;
1270 	}
1271 
1272 	var.key = var_fbneo_debug_layer_2.key;
1273 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1274 	{
1275 		if (strcmp(var.value, "enabled") == 0)
1276 			nBurnLayer |= 2;
1277 		else if (strcmp(var.value, "disabled") == 0)
1278 			nBurnLayer &= ~2;
1279 	}
1280 
1281 	var.key = var_fbneo_debug_layer_3.key;
1282 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1283 	{
1284 		if (strcmp(var.value, "enabled") == 0)
1285 			nBurnLayer |= 4;
1286 		else if (strcmp(var.value, "disabled") == 0)
1287 			nBurnLayer &= ~4;
1288 	}
1289 
1290 	var.key = var_fbneo_debug_layer_4.key;
1291 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1292 	{
1293 		if (strcmp(var.value, "enabled") == 0)
1294 			nBurnLayer |= 8;
1295 		else if (strcmp(var.value, "disabled") == 0)
1296 			nBurnLayer &= ~8;
1297 	}
1298 
1299 	var.key = var_fbneo_debug_sprite_1.key;
1300 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1301 	{
1302 		if (strcmp(var.value, "enabled") == 0)
1303 			nSpriteEnable |= 0x01;
1304 		else if (strcmp(var.value, "disabled") == 0)
1305 			nSpriteEnable &= ~0x01;
1306 	}
1307 
1308 	var.key = var_fbneo_debug_sprite_2.key;
1309 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1310 	{
1311 		if (strcmp(var.value, "enabled") == 0)
1312 			nSpriteEnable |= 0x02;
1313 		else if (strcmp(var.value, "disabled") == 0)
1314 			nSpriteEnable &= ~0x02;
1315 	}
1316 
1317 	var.key = var_fbneo_debug_sprite_3.key;
1318 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1319 	{
1320 		if (strcmp(var.value, "enabled") == 0)
1321 			nSpriteEnable |= 0x04;
1322 		else if (strcmp(var.value, "disabled") == 0)
1323 			nSpriteEnable &= ~0x04;
1324 	}
1325 
1326 	var.key = var_fbneo_debug_sprite_4.key;
1327 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1328 	{
1329 		if (strcmp(var.value, "enabled") == 0)
1330 			nSpriteEnable |= 0x08;
1331 		else if (strcmp(var.value, "disabled") == 0)
1332 			nSpriteEnable &= ~0x08;
1333 	}
1334 
1335 	var.key = var_fbneo_debug_sprite_5.key;
1336 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1337 	{
1338 		if (strcmp(var.value, "enabled") == 0)
1339 			nSpriteEnable |= 0x10;
1340 		else if (strcmp(var.value, "disabled") == 0)
1341 			nSpriteEnable &= ~0x10;
1342 	}
1343 
1344 	var.key = var_fbneo_debug_sprite_6.key;
1345 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1346 	{
1347 		if (strcmp(var.value, "enabled") == 0)
1348 			nSpriteEnable |= 0x20;
1349 		else if (strcmp(var.value, "disabled") == 0)
1350 			nSpriteEnable &= ~0x20;
1351 	}
1352 
1353 	var.key = var_fbneo_debug_sprite_7.key;
1354 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1355 	{
1356 		if (strcmp(var.value, "enabled") == 0)
1357 			nSpriteEnable |= 0x40;
1358 		else if (strcmp(var.value, "disabled") == 0)
1359 			nSpriteEnable &= ~0x40;
1360 	}
1361 
1362 	var.key = var_fbneo_debug_sprite_8.key;
1363 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
1364 	{
1365 		if (strcmp(var.value, "enabled") == 0)
1366 			nSpriteEnable |= 0x80;
1367 		else if (strcmp(var.value, "disabled") == 0)
1368 			nSpriteEnable &= ~0x80;
1369 	}
1370 #endif
1371 }
1372 
1373 #ifdef USE_CYCLONE
SetSekCpuCore()1374 void SetSekCpuCore()
1375 {
1376 	nSekCpuCore = (bCycloneEnabled ? 0 : 1);
1377 }
1378 #endif
1379