1 /*----------------
2  * Stuff to finish:
3  *
4  * It wouldn't be a stretch of the imagination to think the whole of the sdl 'port' needs a redo but here are the main things wrong with this version:
5  *
6  *
7  * The audio output code code could maybe do with some work, but it's getting there...
8  * There are lots of problems with the opengl renderer, but you should just use the SDL2 build anyway
9  *
10  * TODO for SDL2:
11  * Add autostart to menu as an ini config option
12  * Add menu for options e.g. dips, mapping, saves, IPS patches
13  * Maybe a better font output setup with some sort of scaling, maybe add sdl1 support?
14  * figure out what is going on with the sdl sound output, something breaks after a few frames
15  * ------------------*/
16 
17 #include "burner.h"
18 
19 INT32 Init_Joysticks(int p1_use_joystick);
20 
21 int  nAppVirtualFps = 0;         // App fps * 100
22 bool bRunPause = 0;
23 bool bAppFullscreen = 0;
24 bool bAlwaysProcessKeyboardInput = 0;
25 int  usemenu = 0, usejoy = 0, vsync = 1, dat = 0;
26 bool bSaveconfig = 1;
27 bool bIntegerScale = false;
28 bool bAlwaysMenu = false;
29 int nGameSelect = 0;
30 int nFilterSelect = HARDWARE_PUBLIC_MASK;
31 bool bShowAvailableOnly = true;
32 bool bShowClones = true;
33 int gameSelectedFromFilter = -1;
34 TCHAR szAppBurnVer[16];
35 char videofiltering[3];
36 
37 #ifdef BUILD_SDL2
38 SDL_Window* sdlWindow = NULL;
39 
40 static char* szSDLeepromPath = NULL;
41 static char* szSDLhiscorePath = NULL;
42 static char* szSDLHDDPath = NULL;
43 static char* szSDLSamplePath = NULL;
44 #endif
45 
46 #define set_commandline_option_not_config(i,v) i = v;
47 #define set_commandline_option(i,v) i = v; bSaveconfig = 0;
48 #define set_commandline_option_string(i, v, length) snprintf(i, length, v); bSaveconfig = 0;
49 
parseSwitches(int argc,char * argv[])50 int parseSwitches(int argc, char* argv[])
51 {
52 	for (int i = 1; i < argc; i++)
53 	{
54 		if (*argv[i] != '-')
55 		{
56 			continue;
57 		}
58 
59 		if (strcmp(argv[i] + 1, "joy") == 0)
60 		{
61 			set_commandline_option(usejoy, 1)
62 		}
63 
64 		if (strcmp(argv[i] + 1, "menu") == 0)
65 		{
66 			set_commandline_option_not_config(usemenu, 1)
67 
68 		}
69 
70 		if (strcmp(argv[i] + 1, "novsync") == 0)
71 		{
72 			set_commandline_option(vsync, 0)
73 		}
74 
75 		if (strcmp(argv[i] + 1, "integerscale") == 0)
76 		{
77 			set_commandline_option(bIntegerScale, 1)
78 		}
79 
80 		if (strcmp(argv[i] + 1, "dat") == 0)
81 		{
82 			set_commandline_option_not_config(dat, 1)
83 		}
84 
85 		if (strcmp(argv[i] + 1, "fullscreen") == 0)
86 		{
87 			set_commandline_option(bAppFullscreen, 1)
88 		}
89 
90 		if (strcmp(argv[i] + 1, "nearest") == 0)
91 		{
92 			set_commandline_option_string(videofiltering, "0", 3)
93 		}
94 
95 		if (strcmp(argv[i] + 1, "linear") == 0)
96 		{
97 			set_commandline_option_string(videofiltering, "1", 3)
98 		}
99 
100 		if (strcmp(argv[i] + 1, "best") == 0)
101 		{
102 			set_commandline_option_string(videofiltering, "2", 3)
103 		}
104 		if (strcmp(argv[i] + 1, "autosave") == 0)
105 		{
106 			bDrvSaveAll = 1;
107 		}
108 		if (strcmp(argv[i] + 1, "cd") == 0)
109 		{
110 			_tcscpy(CDEmuImage, argv[i + 1]);
111 		}
112 	}
113 	return 0;
114 }
115 
generateDats()116 void generateDats()
117 {
118 	char filename[1024] = { 0 };
119 
120 #if defined(BUILD_SDL2)
121 	printf("Creating fbneo dats in %s\n", SDL_GetPrefPath("fbneo", "dats"));
122 #if defined(ALT_DAT)
123 	sprintf(filename, "%sFBNeo_-_ALL_SYSTEMS.dat", SDL_GetPrefPath("fbneo", "dats"));
124 	create_datfile(filename, -1);
125 #endif
126 	sprintf(filename, "%sFBNeo_-_Arcade.dat", SDL_GetPrefPath("fbneo", "dats"));
127 	create_datfile(filename, DAT_ARCADE_ONLY);
128 
129 	sprintf(filename, "%sFBNeo_-_MegaDrive.dat", SDL_GetPrefPath("fbneo", "dats"));
130 	create_datfile(filename, DAT_MEGADRIVE_ONLY);
131 
132 	sprintf(filename, "%sFBNeo_-_PC_ENGINE.dat", SDL_GetPrefPath("fbneo", "dats"));
133 	create_datfile(filename, DAT_PCENGINE_ONLY);
134 
135 	sprintf(filename, "%sFBNeo_-_TurboGrafx-16.dat", SDL_GetPrefPath("fbneo", "dats"));
136 	create_datfile(filename, DAT_TG16_ONLY);
137 
138 	sprintf(filename, "%sFBNeo_-_PC_Engine_SuperGrafx.dat", SDL_GetPrefPath("fbneo", "dats"));
139 	create_datfile(filename, DAT_SGX_ONLY);
140 
141 	sprintf(filename, "%sFBNeo_-_Sega_SG-1000.dat", SDL_GetPrefPath("fbneo", "dats"));
142 	create_datfile(filename, DAT_SG1000_ONLY);
143 
144 	sprintf(filename, "%sFBNeo_-_ColecoVision.dat", SDL_GetPrefPath("fbneo", "dats"));
145 	create_datfile(filename, DAT_COLECO_ONLY);
146 
147 	sprintf(filename, "%sFBNeo_-_Sega_Master_System.dat", SDL_GetPrefPath("fbneo", "dats"));
148 	create_datfile(filename, DAT_MASTERSYSTEM_ONLY);
149 
150 	sprintf(filename, "%sFBNeo_-_Sega_Game_Gear.dat", SDL_GetPrefPath("fbneo", "dats"));
151 	create_datfile(filename, DAT_GAMEGEAR_ONLY);
152 
153 	sprintf(filename, "%sFBNeo_-_MSX.dat", SDL_GetPrefPath("fbneo", "dats"));
154 	create_datfile(filename, DAT_MSX_ONLY);
155 
156 	sprintf(filename, "%sFBNeo_-_Sinclair_ZX_Spectrum.dat", SDL_GetPrefPath("fbneo", "dats"));
157 	create_datfile(filename, DAT_SPECTRUM_ONLY);
158 
159 	sprintf(filename, "%sFBNeo_-_Neogeo.dat", SDL_GetPrefPath("fbneo", "dats"));
160 	create_datfile(filename, DAT_NEOGEO_ONLY);
161 
162 	sprintf(filename, "%sFBNeo_-_Nintendo_Entertainment_System.dat", SDL_GetPrefPath("fbneo", "dats"));
163 	create_datfile(filename, DAT_NES_ONLY);
164 
165 	sprintf(filename, "%sFBNeo_-_Nintendo_Famicom_Disk_System.dat", SDL_GetPrefPath("fbneo", "dats"));
166 	create_datfile(filename, DAT_FDS_ONLY);
167 
168 	sprintf(filename, "%sFBNeo_-_Neo_Geo_Pocket.dat", SDL_GetPrefPath("fbneo", "dats"));
169 	create_datfile(filename, DAT_NGP_ONLY);
170 
171 	sprintf(filename, "%sFBNeo_-_Fairchild_Channel_F.dat", SDL_GetPrefPath("fbneo", "dats"));
172 	create_datfile(filename, DAT_CHANNELF_ONLY);
173 
174 #else
175 	printf("Creating fbneo dats\n");
176 
177 #if defined(ALT_DAT)
178 	sprintf(filename, "FBNeo_-_ALL_SYSTEMS.dat");
179 	create_datfile(filename, -1);
180 #endif
181 	sprintf(filename, "FBNeo_-_Arcade.dat");
182 	create_datfile(filename, DAT_ARCADE_ONLY);
183 
184 	sprintf(filename, "FBNeo_-_MegaDrive.dat");
185 	create_datfile(filename, DAT_MEGADRIVE_ONLY);
186 
187 	sprintf(filename, "FBNeo_-_PC_ENGINE.dat");
188 	create_datfile(filename, DAT_PCENGINE_ONLY);
189 
190 	sprintf(filename, "FBNeo_-_TurboGrafx-16.dat");
191 	create_datfile(filename, DAT_TG16_ONLY);
192 
193 	sprintf(filename, "FBNeo_-_PC_Engine_SuperGrafx.dat");
194 	create_datfile(filename, DAT_SGX_ONLY);
195 
196 	sprintf(filename, "FBNeo_-_Sega_SG-1000.dat");
197 	create_datfile(filename, DAT_SG1000_ONLY);
198 
199 	sprintf(filename, "FBNeo_-_ColecoVision.dat");
200 	create_datfile(filename, DAT_COLECO_ONLY);
201 
202 	sprintf(filename, "FBNeo_-_Sega_Master_System.dat");
203 	create_datfile(filename, DAT_MASTERSYSTEM_ONLY);
204 
205 	sprintf(filename, "FBNeo_-_Sega_Game_Gear.dat");
206 	create_datfile(filename, DAT_GAMEGEAR_ONLY);
207 
208 	sprintf(filename, "FBNeo_-_MSX.dat");
209 	create_datfile(filename, DAT_MSX_ONLY);
210 
211 	sprintf(filename, "FBNeo_-_Sinclair_ZX_Spectrum.dat");
212 	create_datfile(filename, DAT_SPECTRUM_ONLY);
213 
214 	sprintf(filename, "FBNeo_-_Neogeo.dat");
215 	create_datfile(filename, DAT_NEOGEO_ONLY);
216 
217 	sprintf(filename, "FBNeo_-_Nintendo_Entertainment_System.dat");
218 	create_datfile(filename, DAT_NES_ONLY);
219 
220 	sprintf(filename, "FBNeo_-_Nintendo_Famicom_Disk_System.dat");
221 	create_datfile(filename, DAT_FDS_ONLY);
222 
223 	sprintf(filename, "FBNeo_-_Neo_Geo_Pocket.dat");
224 	create_datfile(filename, DAT_NGP_ONLY);
225 
226 	sprintf(filename, "FBNeo_-_Fairchild_Channel_F.dat");
227 	create_datfile(filename, DAT_CHANNELF_ONLY);
228 #endif
229 }
230 
231 
DoGame(int gameToRun)232 void DoGame(int gameToRun)
233 {
234 
235 	if (!DrvInit(gameToRun, 0))
236 	{
237 		MediaInit();
238 		Init_Joysticks(usejoy);
239 		RunMessageLoop();
240 	}
241 	else
242 	{
243 		printf("There was an error loading your selected game.\n");
244 	}
245 
246 	if (bSaveconfig)
247 	{
248 		ConfigAppSave();
249 	}
250 	DrvExit();
251 	MediaExit();
252 }
253 
bye(void)254 void bye(void)
255 {
256 	printf("Doing exit cleanup\n");
257 
258 	DrvExit();
259 	MediaExit();
260 	BurnLibExit();
261 	SDL_Quit();
262 }
263 
AppDebugPrintf(int nStatus,TCHAR * pszFormat,...)264 static int __cdecl AppDebugPrintf(int nStatus, TCHAR* pszFormat, ...)
265 {
266 
267 	va_list args;
268 	va_start(args, pszFormat);
269 	printf(pszFormat, args);
270 	va_end(args);
271 
272 	return 0;
273 }
274 
main(int argc,char * argv[])275 int main(int argc, char* argv[])
276 {
277 	const char* romname = NULL;
278 	UINT32      i = 0;
279 	bool gamefound = 0;
280 	int fail = 0;
281 	atexit(bye);
282 	// TODO: figure out if we can use hardware Gamma until then, force software gamma
283 	bVidUseHardwareGamma = 0;
284 	bHardwareGammaOnly = 0;
285 	//
286 
287 	// Make version string
288 	if (nBurnVer & 0xFF)
289 	{
290 		// private version (alpha)
291 		_stprintf(szAppBurnVer, _T("%x.%x.%x.%02x"), nBurnVer >> 20, (nBurnVer >> 16) & 0x0F, (nBurnVer >> 8) & 0xFF, nBurnVer & 0xFF);
292 	}
293 	else
294 	{
295 		// public version
296 		_stprintf(szAppBurnVer, _T("%x.%x.%x"), nBurnVer >> 20, (nBurnVer >> 16) & 0x0F, (nBurnVer >> 8) & 0xFF);
297 	}
298 
299 	// set default videofiltering
300 	snprintf(videofiltering, 3, "0");
301 
302 	printf("FBNeo v%s\n", szAppBurnVer);
303 
304 	// create a default ini if one is not valid
305 	fail = ConfigAppLoad();
306 	if (fail)
307 	{
308 		if (bSaveconfig)
309 		{
310 			ConfigAppSave();
311 		}
312 	}
313 
314 	for (int i = 1; i < argc; i++)
315 	{
316 		if (*argv[i] != '-' && !gamefound)
317 		{
318 			romname = argv[i];
319 			gamefound = 1;
320 		}
321 	}
322 
323 	parseSwitches(argc, argv);
324 
325 	if (romname == NULL)
326 	{
327 		printf("Usage: %s [-cd] [-joy] [-menu] [-novsync] [-integerscale] [-fullscreen] [-dat] [-autosave] [-nearest] [-linear] [-best] <romname>\n", argv[0]);
328 		printf("Note the -menu switch does not require a romname\n");
329 		printf("e.g.: %s mslug\n", argv[0]);
330 		printf("e.g.: %s -menu -joy\n", argv[0]);
331 		printf("For NeoCD games:\n");
332 		printf("%s neocdz -cd path/to/ccd/filename.cue (or .ccd)\n", argv[0]);
333 		printf("Usage is restricted by the license at https://raw.githubusercontent.com/finalburnneo/FBNeo/master/src/license.txt\n");
334 
335 		if (!usemenu && !bAlwaysMenu && !dat)
336 		{
337 			return 0;
338 		}
339 	}
340 
341 	// Do these bits before override via ConfigAppLoad
342 	bCheatsAllowed = 1;
343 	nAudDSPModule[0] = 0;
344 	EnableHiscores = 1;
345 
346 #ifdef BUILD_SDL
347 	SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO);
348 
349 	SDL_WM_SetCaption("FinalBurn Neo", "FinalBurn Neo");
350 #endif
351 
352 #ifdef BUILD_SDL2
353 #ifdef SDL_WINDOWS
354 	char *base_path = SDL_GetBasePath();
355 #define DIRCNT 9
356 	// Make sure there are roms and cfg subdirectories
357 	TCHAR szDirs[DIRCNT][MAX_PATH] = {
358 		{_T("config")},
359 		{_T("config/games")},
360 		{_T("config/ips")},
361 		{_T("config/localisation")},
362 		{_T("config/presets")},
363 		{_T("recordings")},
364 		{_T("roms")},
365 		{_T("savestates")},
366 		{_T("screenshots")},
367 	};
368 	TCHAR currentPath[MAX_PATH];
369 	for(int x = 0; x < DIRCNT; x++) {
370 		snprintf(currentPath, MAX_PATH, "%s%s", base_path, szDirs[x]);
371 		CreateDirectory(currentPath, NULL);
372 	}
373 #undef DIRCNT
374 
375 	SDL_setenv("SDL_AUDIODRIVER", "directsound", true);        // fix audio for windows
376 #endif
377 	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO) < 0)
378 	{
379 		printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
380 		return 0;
381 	}
382 #endif
383 
384 	//SDL_ShowCursor(SDL_DISABLE);
385 
386 #if defined(BUILD_SDL2) && !defined(SDL_WINDOWS)
387 	szSDLhiscorePath = SDL_GetPrefPath("fbneo", "hiscore");
388 	szSDLeepromPath = SDL_GetPrefPath("fbneo", "eeprom");
389 	szSDLHDDPath = SDL_GetPrefPath("fbneo", "hdd");
390 	szSDLSamplePath = SDL_GetPrefPath("fbneo", "samples");
391 	_stprintf(szAppHiscorePath, _T("%s"), szSDLhiscorePath);
392 	_stprintf(szAppEEPROMPath, _T("%s"), szSDLeepromPath);
393 	_stprintf(szAppHDDPath, _T("%s"), szSDLHDDPath);
394 	_stprintf(szAppSamplesPath, _T("%s"), szSDLSamplePath);
395 #endif
396 
397 	fail = ConfigAppLoad();
398 	if (fail)
399 	{
400 		if (bSaveconfig)
401 		{
402 			ConfigAppSave();
403 		}
404 	}
405 	ComputeGammaLUT();
406 #if defined(BUILD_SDL2) && !defined(SDL_WINDOWS)
407 	bprintf = AppDebugPrintf;
408 #endif
409 	BurnLibInit();
410 
411 	// Search for a game now, for use in the menu and loading a games
412 	if (romname != NULL)
413 	{
414 		for (i = 0; i < nBurnDrvCount; i++)
415 		{
416 			nBurnDrvActive = i;
417 			if (strcmp(BurnDrvGetTextA(DRV_NAME), romname) == 0)
418 			{
419 				break;
420 			}
421 		}
422 	}
423 
424 	if (usemenu || bAlwaysMenu)
425 	{
426 #ifdef BUILD_SDL2
427 		bool quit = 0;
428 
429 		while (!quit)
430 		{
431 			gui_init();
432 			int selectedOk = gui_process();
433 			gui_exit();
434 
435 			switch (selectedOk)
436 			{
437 			case -1:
438 				BurnLibExit();
439 				SDL_Quit();
440 				quit = 1;
441 				return 0;
442 
443 			default:
444 				DoGame(selectedOk);
445 				break;
446 			}
447 		}
448 #endif
449 	}
450 	else if (dat)
451 	{
452 		generateDats();
453 	}
454 	else
455 	{
456 		if (i == nBurnDrvCount)
457 		{
458 			printf("%s is not supported by FinalBurn Neo.\n", romname);
459 			return 1;
460 		}
461 
462 		DoGame(i);
463 	}
464 
465 	return 0;
466 }
467 
ANSIToTCHAR(const char * pszInString,TCHAR * pszOutString,int nOutSize)468 /* const */ TCHAR* ANSIToTCHAR(const char* pszInString, TCHAR* pszOutString, int nOutSize)
469 {
470 #if defined (UNICODE)
471 	static TCHAR szStringBuffer[1024];
472 
473 	TCHAR* pszBuffer = pszOutString ? pszOutString : szStringBuffer;
474 	int    nBufferSize = pszOutString ? nOutSize * 2 : sizeof(szStringBuffer);
475 
476 	if (MultiByteToWideChar(CP_ACP, 0, pszInString, -1, pszBuffer, nBufferSize))
477 	{
478 		return pszBuffer;
479 	}
480 
481 	return NULL;
482 #else
483 	if (pszOutString)
484 	{
485 		_tcscpy(pszOutString, pszInString);
486 		return pszOutString;
487 	}
488 
489 	return (TCHAR*)pszInString;
490 #endif
491 }
492 
TCHARToANSI(const TCHAR * pszInString,char * pszOutString,int nOutSize)493 /* const */ char* TCHARToANSI(const TCHAR* pszInString, char* pszOutString, int nOutSize)
494 {
495 #if defined (UNICODE)
496 	static char szStringBuffer[1024];
497 	memset(szStringBuffer, 0, sizeof(szStringBuffer));
498 
499 	char* pszBuffer = pszOutString ? pszOutString : szStringBuffer;
500 	int   nBufferSize = pszOutString ? nOutSize * 2 : sizeof(szStringBuffer);
501 
502 	if (WideCharToMultiByte(CP_ACP, 0, pszInString, -1, pszBuffer, nBufferSize, NULL, NULL))
503 	{
504 		return pszBuffer;
505 	}
506 
507 	return NULL;
508 #else
509 	if (pszOutString)
510 	{
511 		strcpy(pszOutString, pszInString);
512 		return pszOutString;
513 	}
514 
515 	return (char*)pszInString;
516 #endif
517 }
518 
AppProcessKeyboardInput()519 bool AppProcessKeyboardInput()
520 {
521 	return true;
522 }
523