Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/yabause/src/gtk/main.c
2 views
1
/* Copyright 2006 Guillaume Duhamel
2
Copyright 2006 Fabien Coulon
3
Copyright 2005 Joost Peters
4
5
This file is part of Yabause.
6
7
Yabause is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
11
12
Yabause is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
16
17
You should have received a copy of the GNU General Public License
18
along with Yabause; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
22
#include "gtkglwidget.h"
23
#include "yuiwindow.h"
24
25
#include "../yabause.h"
26
#include "../yui.h"
27
#include "../peripheral.h"
28
#include "../sh2core.h"
29
#include "../sh2int.h"
30
#include "../vidogl.h"
31
#include "../vidsoft.h"
32
#include "../cs0.h"
33
#include "../cs2.h"
34
#include "../cdbase.h"
35
#include "../scsp.h"
36
#include "../sndsdl.h"
37
#include "../sndal.h"
38
#include "../persdljoy.h"
39
#ifdef ARCH_IS_LINUX
40
#include "../perlinuxjoy.h"
41
#endif
42
#include "../debug.h"
43
#include "../m68kcore.h"
44
#include "../m68kc68k.h"
45
#include "pergtk.h"
46
#include "../psp/psp-sh2.h"
47
48
#include "settings.h"
49
50
static char biospath[256] = "\0";
51
static char cdpath[256] = "\0";
52
static char buppath[256] = "\0";
53
static char mpegpath[256] = "\0";
54
static char cartpath[256] = "\0";
55
56
M68K_struct * M68KCoreList[] = {
57
&M68KDummy,
58
#ifdef HAVE_C68K
59
&M68KC68K,
60
#endif
61
#ifdef HAVE_Q68
62
&M68KQ68,
63
#endif
64
NULL
65
};
66
67
SH2Interface_struct *SH2CoreList[] = {
68
&SH2Interpreter,
69
&SH2DebugInterpreter,
70
#ifdef TEST_PSP_SH2
71
&SH2PSP,
72
#endif
73
#ifdef SH2_DYNAREC
74
&SH2Dynarec,
75
#endif
76
NULL
77
};
78
79
PerInterface_struct *PERCoreList[] = {
80
&PERDummy,
81
&PERGTK,
82
#ifdef HAVE_LIBSDL
83
&PERSDLJoy,
84
#endif
85
#ifdef ARCH_IS_LINUX
86
&PERLinuxJoy,
87
#endif
88
NULL
89
};
90
91
CDInterface *CDCoreList[] = {
92
&DummyCD,
93
&ISOCD,
94
#ifndef UNKNOWN_ARCH
95
&ArchCD,
96
#endif
97
NULL
98
};
99
100
SoundInterface_struct *SNDCoreList[] = {
101
&SNDDummy,
102
#ifdef HAVE_LIBSDL
103
&SNDSDL,
104
#endif
105
#ifdef HAVE_LIBAL
106
&SNDAL,
107
#endif
108
NULL
109
};
110
111
VideoInterface_struct *VIDCoreList[] = {
112
&VIDDummy,
113
#ifdef HAVE_LIBGTKGLEXT
114
&VIDOGL,
115
#endif
116
&VIDSoft,
117
NULL
118
};
119
120
#ifdef YAB_PORT_OSD
121
OSD_struct *OSDCoreList[] = {
122
&OSDDummy,
123
#ifdef HAVE_LIBGLUT
124
&OSDGlut,
125
#endif
126
&OSDSoft,
127
NULL
128
};
129
#endif
130
131
GtkWidget * yui;
132
GKeyFile * keyfile;
133
yabauseinit_struct yinit;
134
135
static int yui_main(gpointer data) {
136
PERCore->HandleEvents();
137
return TRUE;
138
}
139
140
static GtkWidget * yui_new(void) {
141
yui = yui_window_new(NULL, G_CALLBACK(YabauseInit), &yinit, yui_main, G_CALLBACK(YabauseReset));
142
143
gtk_widget_show(yui);
144
145
return yui;
146
}
147
148
static void yui_settings_init(void) {
149
yinit.m68kcoretype = M68KCORE_C68K;
150
yinit.percoretype = PERCORE_GTK;
151
yinit.sh2coretype = SH2CORE_DEFAULT;
152
#ifdef HAVE_LIBGTKGLEXT
153
yinit.vidcoretype = VIDCORE_OGL;
154
#else
155
yinit.vidcoretype = VIDCORE_SOFT;
156
#endif
157
yinit.sndcoretype = SNDCORE_DUMMY;
158
yinit.cdcoretype = CDCORE_DEFAULT;
159
yinit.carttype = CART_NONE;
160
yinit.regionid = 0;
161
yinit.biospath = biospath;
162
yinit.cdpath = cdpath;
163
yinit.buppath = buppath;
164
yinit.mpegpath = mpegpath;
165
yinit.cartpath = cartpath;
166
yinit.videoformattype = VIDEOFORMATTYPE_NTSC;
167
yinit.osdcoretype = OSDCORE_DEFAULT;
168
}
169
170
gchar * inifile;
171
172
static int safe_strcmp(const char * s1, const char * s2) {
173
if (s1) {
174
if (s2) {
175
return strcmp(s1, s2);
176
} else {
177
return 1;
178
}
179
} else {
180
if (s2) {
181
return -1;
182
} else {
183
return 0;
184
}
185
}
186
}
187
188
extern void * padbits;
189
void * padbits;
190
191
static gboolean yui_settings_load(void) {
192
int i, tmp;
193
long tmptime;
194
gchar * stmp;
195
gboolean mustRestart = FALSE;
196
197
g_key_file_load_from_file(keyfile, inifile, G_KEY_FILE_NONE, 0);
198
199
/* bios */
200
stmp = g_key_file_get_value(keyfile, "General", "BiosPath", 0);
201
if (stmp && !*stmp) stmp = NULL;
202
if ((YUI_WINDOW(yui)->state & YUI_IS_INIT) && safe_strcmp(stmp, yinit.biospath)) {
203
mustRestart = TRUE;
204
}
205
if (stmp) {
206
g_strlcpy(biospath, stmp, 256);
207
yinit.biospath = biospath;
208
}
209
else yinit.biospath = NULL;
210
211
/* cd core */
212
stmp = g_key_file_get_value(keyfile, "General", "CDROMDrive", 0);
213
if (stmp && !*stmp) stmp = NULL;
214
if((YUI_WINDOW(yui)->state & YUI_IS_INIT) && safe_strcmp(stmp, yinit.cdpath)) {
215
Cs2ChangeCDCore(yinit.cdcoretype, stmp);
216
}
217
if (stmp) g_strlcpy(cdpath, stmp, 256);
218
219
tmp = yinit.cdcoretype;
220
yinit.cdcoretype = g_key_file_get_integer(keyfile, "General", "CDROMCore", 0);
221
if((YUI_WINDOW(yui)->state & YUI_IS_INIT) && (tmp != yinit.cdcoretype)) {
222
Cs2ChangeCDCore(yinit.cdcoretype, yinit.cdpath);
223
}
224
225
/* region */
226
{
227
char * region = g_key_file_get_value(keyfile, "General", "Region", 0);
228
tmp = yinit.regionid;
229
if ((region == 0) || !strcmp(region, "Auto")) {
230
yinit.regionid = 0;
231
} else {
232
switch(region[0]) {
233
case 'J': yinit.regionid = 1; break;
234
case 'T': yinit.regionid = 2; break;
235
case 'U': yinit.regionid = 4; break;
236
case 'B': yinit.regionid = 5; break;
237
case 'K': yinit.regionid = 6; break;
238
case 'A': yinit.regionid = 0xA; break;
239
case 'E': yinit.regionid = 0xC; break;
240
case 'L': yinit.regionid = 0xD; break;
241
}
242
}
243
244
if ((YUI_WINDOW(yui)->state & YUI_IS_INIT) && (tmp != yinit.regionid)) {
245
mustRestart = TRUE;
246
}
247
}
248
249
/* cart */
250
stmp = g_key_file_get_value(keyfile, "General", "CartPath", 0);
251
if (stmp && !*stmp) stmp = NULL;
252
if ((YUI_WINDOW(yui)->state & YUI_IS_INIT) && safe_strcmp(stmp, yinit.cartpath)) {
253
mustRestart = TRUE;
254
}
255
if (stmp) {
256
g_strlcpy(cartpath, stmp, 256);
257
yinit.cartpath = cartpath;
258
}
259
else yinit.cartpath = NULL;
260
261
tmp = yinit.carttype;
262
yinit.carttype = g_key_file_get_integer(keyfile, "General", "CartType", 0);
263
if ((YUI_WINDOW(yui)->state & YUI_IS_INIT) && (tmp != yinit.carttype)) {
264
mustRestart = TRUE;
265
}
266
267
/* backup ram */
268
stmp = g_key_file_get_value(keyfile, "General", "BackupRamPath", 0);
269
if (stmp && !*stmp) stmp = NULL;
270
if ((YUI_WINDOW(yui)->state & YUI_IS_INIT) && safe_strcmp(stmp, yinit.buppath)) {
271
mustRestart = TRUE;
272
}
273
if (stmp) {
274
g_strlcpy(buppath, stmp, 256);
275
yinit.buppath = buppath;
276
}
277
else yinit.buppath = NULL;
278
279
/* mpeg rom */
280
stmp = g_key_file_get_value(keyfile, "General", "MpegRomPath", 0);
281
if (stmp && !*stmp) stmp = NULL;
282
if ((YUI_WINDOW(yui)->state & YUI_IS_INIT) && safe_strcmp(stmp, yinit.mpegpath)) {
283
mustRestart = TRUE;
284
}
285
if (stmp) {
286
g_strlcpy(mpegpath, stmp, 256);
287
yinit.mpegpath = mpegpath;
288
}
289
else yinit.mpegpath = NULL;
290
291
/* sh2 */
292
tmp = yinit.sh2coretype;
293
yinit.sh2coretype = g_key_file_get_integer(keyfile, "General", "SH2Int", 0);
294
if ((YUI_WINDOW(yui)->state & YUI_IS_INIT) && (tmp != yinit.sh2coretype)) {
295
mustRestart = TRUE;
296
}
297
298
/* m68k */
299
tmp = yinit.m68kcoretype;
300
yinit.m68kcoretype = g_key_file_get_integer(keyfile, "General", "M68kInt", 0);
301
if ((YUI_WINDOW(yui)->state & YUI_IS_INIT) && (tmp != yinit.m68kcoretype)) {
302
mustRestart = TRUE;
303
}
304
305
/* video core */
306
tmp = yinit.vidcoretype;
307
yinit.vidcoretype = g_key_file_get_integer(keyfile, "General", "VideoCore", 0);
308
if ((YUI_WINDOW(yui)->state & YUI_IS_INIT) && (tmp != yinit.vidcoretype)) {
309
VideoChangeCore(yinit.vidcoretype);
310
VIDCore->Resize(
311
GTK_WIDGET(YUI_WINDOW(yui)->area)->allocation.width,
312
GTK_WIDGET(YUI_WINDOW(yui)->area)->allocation.height,
313
FALSE);
314
}
315
316
/* osd core */
317
tmp = yinit.osdcoretype;
318
yinit.osdcoretype = g_key_file_get_integer(keyfile, "General", "OSDCore", 0);
319
if ((YUI_WINDOW(yui)->state & YUI_IS_INIT) && (tmp != yinit.osdcoretype)) {
320
OSDChangeCore(yinit.osdcoretype);
321
}
322
323
/* sound core */
324
tmp = yinit.sndcoretype;
325
yinit.sndcoretype = g_key_file_get_integer(keyfile, "General", "SoundCore", 0);
326
if ((YUI_WINDOW(yui)->state & YUI_IS_INIT) && (tmp != yinit.sndcoretype)) {
327
ScspChangeSoundCore(yinit.sndcoretype);
328
}
329
330
ScspSetVolume(g_key_file_get_integer(keyfile, "General", "Volume", NULL));
331
332
/* peripheral core */
333
yinit.percoretype = g_key_file_get_integer(keyfile, "General", "PerCore", 0);
334
335
/* audio sync */
336
tmp = g_key_file_get_boolean(keyfile, "General", "AudioSync", 0);
337
ScspSetFrameAccurate(tmp);
338
339
/* clock sync */
340
tmp = yinit.clocksync;
341
yinit.clocksync = g_key_file_get_boolean(keyfile, "General", "ClockSync", 0);
342
if ((YUI_WINDOW(yui)->state & YUI_IS_INIT) && (tmp != yinit.clocksync)) {
343
mustRestart = TRUE;
344
}
345
tmptime = yinit.basetime;
346
tmp = g_key_file_get_boolean(keyfile, "General", "FixedBaseTime", 0);
347
if (tmp && yinit.clocksync) {
348
/* Find timestamp of 1998-01-01 12:00 in the local time zone */
349
time_t utc = 883656000; // 1998-01-01 12:00 UTC
350
struct tm tm;
351
long local, noon;
352
localtime_r(&utc, &tm);
353
local = tm.tm_hour*3600 + tm.tm_min*60 + tm.tm_sec;
354
if (tm.tm_mday == 2) // 1998-01-02
355
local += 86400;
356
else if (tm.tm_mday == 31) // 1997-12-31
357
local -= 86400;
358
noon = 12*3600 + 0*60 + 0;
359
yinit.basetime = (long)utc + (noon - local);
360
} else {
361
yinit.basetime = 0;
362
}
363
if ((YUI_WINDOW(yui)->state & YUI_IS_INIT) && (tmptime != yinit.basetime)) {
364
mustRestart = TRUE;
365
}
366
367
/* threads */
368
tmp = g_key_file_get_boolean(keyfile, "General", "UseThreads", 0);
369
if ((YUI_WINDOW(yui)->state & YUI_IS_INIT) && (tmp != yinit.usethreads)) {
370
mustRestart = TRUE;
371
}
372
yinit.usethreads = tmp;
373
374
PerInit(yinit.percoretype);
375
376
PerPortReset();
377
switch(g_key_file_get_integer(keyfile, "General", "PerType", NULL))
378
{
379
case PERMOUSE:
380
padbits = PerMouseAdd(&PORTDATA1);
381
i = 0;
382
383
while(PerMouseNames[i]) {
384
char tmp[100];
385
u32 key;
386
sprintf(tmp, "Mouse.%s.1", PerMouseNames[i]);
387
key = g_key_file_get_integer(keyfile, PERCore->Name, tmp, 0);
388
PerSetKey(key, i + 13, padbits);
389
i++;
390
}
391
break;
392
case PERPAD:
393
default:
394
padbits = PerPadAdd(&PORTDATA1);
395
i = 0;
396
397
while(PerPadNames[i]) {
398
char tmp[100];
399
u32 key;
400
sprintf(tmp, "Pad.%s.1", PerPadNames[i]);
401
key = g_key_file_get_integer(keyfile, PERCore->Name, tmp, 0);
402
PerSetKey(key, i, padbits);
403
i++;
404
}
405
}
406
407
yui_resize(g_key_file_get_integer(keyfile, "General", "Width", 0),
408
g_key_file_get_integer(keyfile, "General", "Height", 0),
409
g_key_file_get_integer(keyfile, "General", "Fullscreen", 0));
410
411
yinit.videoformattype = g_key_file_get_integer(keyfile, "General", "VideoFormat", 0);
412
413
yui_window_set_frameskip(YUI_WINDOW(yui), g_key_file_get_integer(keyfile, "General", "Frameskip", NULL));
414
415
return mustRestart;
416
}
417
418
void YuiErrorMsg(const char * string) {
419
GtkWidget* warningDlg = gtk_message_dialog_new (GTK_WINDOW(yui), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
420
GTK_BUTTONS_OK, string, NULL);
421
gtk_dialog_run (GTK_DIALOG(warningDlg));
422
gtk_widget_destroy (warningDlg);
423
}
424
425
int main(int argc, char *argv[]) {
426
#ifndef NO_CLI
427
int i;
428
#endif
429
LogStart();
430
LogChangeOutput( DEBUG_STDERR, NULL );
431
inifile = g_build_filename(g_get_user_config_dir(), "yabause", "gtk", "yabause.ini", NULL);
432
433
if (! g_file_test(inifile, G_FILE_TEST_EXISTS)) {
434
// no inifile found, but it could be in the old location
435
gchar * oldinifile = g_build_filename(g_get_user_config_dir(), "yabause.ini", NULL);
436
437
// we need to create the directory for the new file anyways
438
gchar * xdgpath = g_build_filename(g_get_user_config_dir(), "yabause", "gtk", NULL);
439
440
if (! g_file_test(xdgpath, G_FILE_TEST_EXISTS))
441
g_mkdir_with_parents(xdgpath, 0755);
442
g_free(xdgpath);
443
444
if (g_file_test(oldinifile, G_FILE_TEST_EXISTS)) {
445
// ok, we found an old .ini file, let's copy the content
446
gchar * data;
447
448
g_file_get_contents(oldinifile, &data, NULL, NULL);
449
g_file_set_contents(inifile, data, -1, NULL);
450
}
451
452
g_free(oldinifile);
453
}
454
455
keyfile = g_key_file_new();
456
457
gtk_init(&argc, &argv);
458
#ifdef HAVE_LIBGTKGLEXT
459
gtk_gl_init(&argc, &argv);
460
#endif
461
462
yui_settings_init();
463
464
#ifdef HAVE_LIBMINI18N
465
mini18n_set_domain(YTSDIR);
466
g_key_file_load_from_file(keyfile, inifile, G_KEY_FILE_NONE, 0);
467
mini18n_set_locale(g_key_file_get_value(keyfile, "General", "TranslationPath", NULL));
468
#endif
469
470
yui = yui_new();
471
472
yui_settings_load();
473
474
gtk_window_move(GTK_WINDOW(yui), g_key_file_get_integer(keyfile, "Gtk", "X", 0), g_key_file_get_integer(keyfile, "Gtk", "Y", 0));
475
476
#ifndef NO_CLI
477
//handle command line arguments
478
for (i = 1; i < argc; ++i) {
479
if (argv[i]) {
480
//show usage
481
if (0 == strcmp(argv[i], "-h") || 0 == strcmp(argv[i], "-?") || 0 == strcmp(argv[i], "--help")) {
482
print_usage(argv[0]);
483
return 0;
484
}
485
486
//set bios
487
if (0 == strcmp(argv[i], "-b") && argv[i + 1]) {
488
g_strlcpy(biospath, argv[i + 1], 256);
489
yinit.biospath = biospath;
490
} else if (strstr(argv[i], "--bios=")) {
491
g_strlcpy(biospath, argv[i] + strlen("--bios="), 256);
492
yinit.biospath = biospath;
493
}
494
//set iso
495
else if (0 == strcmp(argv[i], "-i") && argv[i + 1]) {
496
g_strlcpy(cdpath, argv[i + 1], 256);
497
yinit.cdcoretype = 1;
498
} else if (strstr(argv[i], "--iso=")) {
499
g_strlcpy(cdpath, argv[i] + strlen("--iso="), 256);
500
yinit.cdcoretype = 1;
501
}
502
//set cdrom
503
else if (0 == strcmp(argv[i], "-c") && argv[i + 1]) {
504
g_strlcpy(cdpath, argv[i + 1], 256);
505
yinit.cdcoretype = 2;
506
} else if (strstr(argv[i], "--cdrom=")) {
507
g_strlcpy(cdpath, argv[i] + strlen("--cdrom="), 256);
508
yinit.cdcoretype = 2;
509
}
510
// Set sound
511
else if (strcmp(argv[i], "-ns") == 0 || strcmp(argv[i], "--nosound") == 0) {
512
yinit.sndcoretype = 0;
513
}
514
// Autoload
515
else if (strcmp(argv[i], "--autoload") == 0) {
516
yui_window_start(YUI_WINDOW(yui));
517
YuiLoadState();
518
yui_window_run(YUI_WINDOW(yui));
519
}
520
// Autostart
521
else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--autostart") == 0) {
522
yui_window_run(YUI_WINDOW(yui));
523
}
524
// Fullscreen
525
else if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--fullscreen") == 0) {
526
yui_window_set_fullscreen(YUI_WINDOW(yui), TRUE);
527
}
528
// Auto frame skip
529
else if (strstr(argv[i], "--autoframeskip=")) {
530
int fscount;
531
int fsenable;
532
fscount = sscanf(argv[i] + strlen("--autoframeskip="), "%d", &fsenable);
533
if (fscount > 0)
534
yui_window_set_frameskip(YUI_WINDOW(yui), fsenable);
535
}
536
// Binary
537
else if (strstr(argv[i], "--binary=")) {
538
char binname[1024];
539
unsigned int binaddress;
540
int bincount;
541
542
bincount = sscanf(argv[i] + strlen("--binary="), "%[^:]:%x", binname, &binaddress);
543
if (bincount > 0) {
544
if (bincount < 2) binaddress = 0x06004000;
545
546
yui_window_run(YUI_WINDOW(yui));
547
MappedMemoryLoadExec(binname, binaddress);
548
}
549
}
550
}
551
}
552
#endif
553
554
gtk_main ();
555
556
YabauseDeInit();
557
LogStop();
558
559
return 0;
560
}
561
562
void YuiSetVideoAttribute(int type, int val) {
563
}
564
565
int YuiSetVideoMode(int width, int height, int bpp, int fullscreen) {
566
return 0;
567
}
568
569
void YuiSwapBuffers(void) {
570
yui_window_update(YUI_WINDOW(yui));
571
}
572
573
void yui_conf(void) {
574
gint result;
575
GtkWidget * dialog;
576
577
dialog = create_dialog1();
578
579
result = gtk_dialog_run(GTK_DIALOG(dialog));
580
gtk_widget_destroy(dialog);
581
switch(result) {
582
case GTK_RESPONSE_OK:
583
{
584
gboolean mustRestart;
585
g_file_set_contents(inifile, g_key_file_to_data(keyfile, 0, 0), -1, 0);
586
mustRestart = yui_settings_load();
587
if (mustRestart) {
588
GtkWidget* warningDlg = gtk_message_dialog_new (GTK_WINDOW(yui),
589
GTK_DIALOG_MODAL,
590
GTK_MESSAGE_WARNING,
591
GTK_BUTTONS_OK,
592
"You must restart Yabause before the changes take effect.");
593
594
gtk_dialog_run (GTK_DIALOG(warningDlg));
595
gtk_widget_destroy (warningDlg);
596
}
597
break;
598
}
599
case GTK_RESPONSE_CANCEL:
600
g_key_file_load_from_file(keyfile, inifile, G_KEY_FILE_NONE, 0);
601
break;
602
}
603
}
604
605
void yui_resize(guint width, guint height, gboolean fullscreen) {
606
if (width <= 0) width = 320;
607
if (height <= 0) height = 224;
608
609
if (g_key_file_get_integer(keyfile, "General", "KeepRatio", 0))
610
{
611
GdkGeometry geometry;
612
geometry.min_aspect = (float) width / height;
613
geometry.max_aspect = (float) width / height;
614
gtk_window_set_geometry_hints(GTK_WINDOW(yui), YUI_WINDOW(yui)->area, &geometry, GDK_HINT_ASPECT);
615
}
616
else
617
{
618
gtk_window_set_geometry_hints(GTK_WINDOW(yui), YUI_WINDOW(yui)->area, NULL, 0);
619
}
620
621
gtk_window_resize(GTK_WINDOW(yui), width, height + YUI_WINDOW(yui)->menu->allocation.height);
622
623
yui_window_set_fullscreen(YUI_WINDOW(yui), fullscreen);
624
}
625
626