1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #define _GNU_SOURCE 1
6 #include <uae/uae.h>
7 #ifdef USE_SDL
8 /* We must include SDL first before emu.h, so libfsemu's #definition of main
9 * is the current one (on Windows) when main is encountered further down. */
10 #include <SDL.h>
11 #endif
12 #ifdef MACOSX
13 #include <SDL.h>
14 #endif
15 #include <fs/base.h>
16 #include <fs/data.h>
17 #include <fs/emu.h>
18 #include <fs/emu/audio.h>
19 #include <fs/emu/path.h>
20 #include <fs/emu/video.h>
21 #include <fs/glib.h>
22 #include <fs/lazyness.h>
23 #include <fs/main.h>
24 #include <fs/i18n.h>
25 #include <fs/thread.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <strings.h>
30 #include <locale.h>
31 #include "fs-uae.h"
32 #include "recording.h"
33 #include "plugins.h"
34 #include "options.h"
35 #include "paths.h"
36 #include "config-drives.h"
37 #ifdef WITH_CEF
38 #include <fs/emu/cef.h>
39 #endif
40 #include <fs/emu/hacks.h>
41
42 #ifdef LINUX
43 #include "../../gamemode/lib/gamemode_client.h"
44 #endif
45
46 static int fs_uae_argc;
47 static char **fs_uae_argv;
48 static int g_warn_about_missing_config_file;
49
50 #define LOG_LINE "---------------------------------------------------------" \
51 "-------------------\n"
52
change_port_device_mode(int data)53 static void change_port_device_mode(int data)
54 {
55 int modes = INPUTEVENT_AMIGA_JOYPORT_MODE_0_LAST -
56 INPUTEVENT_AMIGA_JOYPORT_MODE_0_NONE + 1;
57 int port = data / modes;
58 int mode = data % modes;
59 if (port >= 0 && port < FS_UAE_NUM_INPUT_PORTS) {
60 g_fs_uae_input_ports[port].mode = mode;
61 g_fs_uae_input_ports[port].new_mode = mode;
62 // The fifth port isn't an Amiga port, but rather a fake
63 // port used with custom input mapping only
64 if (port < 4) {
65 amiga_set_joystick_port_mode(port, mode);
66 }
67 fs_uae_reconfigure_input_ports_host();
68 fs_emu_menu_update_current();
69 }
70 }
71
select_port_0_device(int data)72 static void select_port_0_device(int data)
73 {
74 printf("--> device index %d\n", data);
75 int port = 0;
76 if (data == 9) {
77 // 9 is currently a hack to indicate the local mouse
78 g_fs_uae_input_ports[port].mode = AMIGA_JOYPORT_MOUSE;
79 g_fs_uae_input_ports[port].new_mode = AMIGA_JOYPORT_MOUSE;
80 strcpy(g_fs_uae_input_ports[port].device, "MOUSE");
81 amiga_set_joystick_port_mode(port, AMIGA_JOYPORT_MOUSE);
82 // FIXME: not a warning, rather a notification
83 fs_emu_warning(_("Port 0: %s"), _("Mouse"));
84 }
85 else {
86 int count = 0;
87 int new_mode = AMIGA_JOYPORT_DJOY;
88 if (g_fs_uae_amiga_model == MODEL_CD32) {
89 new_mode = AMIGA_JOYPORT_CD32JOY;
90 }
91 fs_emu_input_device *devices = fs_emu_get_input_devices(&count);
92 if (data < count) {
93 g_fs_uae_input_ports[port].mode = new_mode;
94 g_fs_uae_input_ports[port].new_mode = new_mode;
95 uae_strlcpy(g_fs_uae_input_ports[port].device, devices[data].name,
96 sizeof(g_fs_uae_input_ports[port].device));
97 amiga_set_joystick_port_mode(port, new_mode);
98 // FIXME: not a warning, rather a notification
99 fs_emu_warning(_("Port 0: %s"), devices[data].name);
100 }
101 }
102 fs_uae_reconfigure_input_ports_host();
103 fs_emu_menu_update_current();
104
105 //fs_emu_get_input_devices()
106 //g_fs_uae_input_ports[port].mode = mode;
107 //amiga_set_joystick_port_mode(port, mode);
108 //g_fs_uae_input_ports[port].new_mode = mode;
109 //fs_uae_reconfigure_input_ports_host();
110 //fs_emu_menu_update_current();
111 }
112
113 int g_fs_uae_last_input_event = 0;
114 int g_fs_uae_last_input_event_state = 0;
115 int g_fs_uae_state_number = 0;
116
fs_uae_process_input_event(int line,int action,int state,int playback)117 void fs_uae_process_input_event(int line, int action, int state, int playback)
118 {
119 static int first_time = 1;
120 if (first_time == 1) {
121 first_time = 0;
122 int load_state_number = fs_config_get_int("load_state");
123 if (load_state_number >= 1 && load_state_number <= 9) {
124 // FIXME: improvement, check if state file exists and show
125 // GUI warning if not...
126 fs_log("trying to load state number: %d\n", load_state_number);
127 amiga_send_input_event(
128 INPUTEVENT_SPC_STATERESTORE1 - 1 + load_state_number, 1);
129 }
130 }
131
132 #if 0
133 g_fs_uae_last_input_event = input_event;
134 g_fs_uae_last_input_event_state = state;
135 fs_emu_lua_run_handler("on_fs_uae_input_event");
136 // handler can modify input event
137 amiga_send_input_event(g_fs_uae_last_input_event,
138 g_fs_uae_last_input_event_state);
139 #endif
140
141 #if 0
142 if (action == INPUTEVENT_KEY_RETURN) {
143 printf("FIXME: ignoring RETURN event for now\n");
144 return;
145 }
146 #endif
147
148 if (action >= INPUTEVENT_AMIGA_JOYPORT_MODE_0_NONE &&
149 action < INPUTEVENT_AMIGA_JOYPORT_MODE_3_LAST) {
150 change_port_device_mode(
151 action - INPUTEVENT_AMIGA_JOYPORT_MODE_0_NONE);
152 return;
153
154 }
155 if (action >= INPUTEVENT_AMIGA_JOYPORT_0_DEVICE_0 &&
156 action < INPUTEVENT_AMIGA_JOYPORT_0_DEVICE_LAST) {
157 select_port_0_device(action - INPUTEVENT_AMIGA_JOYPORT_0_DEVICE_0);
158 return;
159 }
160 if (state && action >= INPUTEVENT_AMIGA_JOYPORT_0_AUTOFIRE &&
161 action <= INPUTEVENT_AMIGA_JOYPORT_3_AUTOFIRE) {
162 int port = action - INPUTEVENT_AMIGA_JOYPORT_0_AUTOFIRE;
163 if (g_fs_uae_input_ports[port].autofire_mode) {
164 g_fs_uae_input_ports[port].autofire_mode = 0;
165 amiga_set_joystick_port_autofire(port, 0);
166 fs_emu_warning(_("Auto-fire disabled for port %d"), port);
167 }
168 else {
169 g_fs_uae_input_ports[port].autofire_mode = 1;
170 amiga_set_joystick_port_autofire(port, 1);
171 fs_emu_warning(_("Auto-fire enabled for port %d"), port);
172 }
173 fs_emu_menu_update_current();
174 // this event must be passed on to the Amiga core
175 }
176
177 int record_event = 1;
178 if (playback) {
179 record_event = 0;
180 }
181
182 int load_state = 0;
183 int save_state = 0;
184 if (action >= INPUTEVENT_SPC_STATESAVE1 &&
185 action <= INPUTEVENT_SPC_STATESAVE9) {
186 save_state = action - INPUTEVENT_SPC_STATESAVE1 + 1;
187 g_fs_uae_state_number = save_state;
188 }
189
190 if (action >= INPUTEVENT_SPC_STATERESTORE1 &&
191 action <= INPUTEVENT_SPC_STATERESTORE9) {
192 load_state = action - INPUTEVENT_SPC_STATERESTORE1 + 1;
193 g_fs_uae_state_number = load_state;
194 }
195
196 if (load_state) {
197 #ifdef WITH_LUA
198 fs_log("run handler on_fs_uae_load_state\n");
199 fs_emu_lua_run_handler("on_fs_uae_load_state");
200 #endif
201 record_event = 0;
202 }
203 else if (save_state) {
204 #ifdef WITH_LUA
205 fs_log("run handler on_fs_uae_save_state\n");
206 fs_emu_lua_run_handler("on_fs_uae_save_state");
207 #endif
208 record_event = 0;
209 }
210
211 if (record_event) {
212 fs_uae_record_input_event(line, action, state);
213 }
214 amiga_send_input_event(action, state);
215
216 if (load_state) {
217 #ifdef WITH_LUA
218 fs_log("run handler on_fs_uae_load_state_done\n");
219 fs_emu_lua_run_handler("on_fs_uae_load_state_done");
220 #endif
221 }
222 else if (save_state) {
223 #ifdef WITH_LUA
224 fs_log("run handler on_fs_uae_save_state_done\n");
225 fs_emu_lua_run_handler("on_fs_uae_save_state_done");
226 #endif
227 }
228 }
229
230 int g_fs_uae_frame = 0;
231
input_handler_loop(int line)232 static int input_handler_loop(int line)
233 {
234 static int last_frame = -1;
235 if (g_fs_uae_frame != last_frame) {
236 // only run this for the first input handler loop per frame
237 #ifdef WITH_LUA
238 fs_emu_lua_run_handler("on_fs_uae_read_input");
239 #endif
240 last_frame = g_fs_uae_frame;
241 }
242
243 // FIXME: Move to another place?
244 uae_clipboard_update();
245
246 int action;
247 //int reconfigure_input = 0;
248 while ((action = fs_emu_get_input_event()) != 0) {
249 //printf("event_handler_loop received input action %d\n", action);
250 int istate = (action & 0x00ff0000) >> 16;
251 // force to -128 to 127 range
252 signed char state = (signed char) istate;
253 action = action & 0x0000ffff;
254 //amiga_keyboard_set_host_key(input_event, state);
255
256 g_fs_uae_last_input_event = action;
257 g_fs_uae_last_input_event_state = state;
258 #ifdef WITH_LUA
259 fs_emu_lua_run_handler("on_fs_uae_input_event");
260 #endif
261
262 // handler can modify input event
263 //action = g_fs_uae_last_input_event;
264 //state = g_fs_uae_last_input_event_state;
265 fs_uae_process_input_event(line, g_fs_uae_last_input_event,
266 g_fs_uae_last_input_event_state, 0);
267 }
268
269 #if 0
270 if (line == 0) {
271 int o = 300;
272 if (g_fs_uae_frame == o + 600) {
273 printf("Fake events!\n");
274 fs_uae_process_input_event(line, INPUTEVENT_MOUSE1_HORIZ, 50, 0);
275 }
276 if (g_fs_uae_frame == o + 650) {
277 fs_uae_process_input_event(line, INPUTEVENT_MOUSE1_VERT, 200, 0);
278 }
279 if (g_fs_uae_frame == o + 675) {
280 fs_uae_process_input_event(line, INPUTEVENT_MOUSE1_VERT, 30, 0);
281 }
282 if (g_fs_uae_frame == o + 700) {
283 fs_uae_process_input_event(line, INPUTEVENT_JOY1_FIRE_BUTTON, 1, 0);
284 }
285 if (g_fs_uae_frame == o + 710) {
286 fs_uae_process_input_event(line, INPUTEVENT_JOY1_FIRE_BUTTON, 0, 0);
287 }
288 if (g_fs_uae_frame == o + 800) {
289 fs_uae_process_input_event(line, INPUTEVENT_JOY1_FIRE_BUTTON, 1, 0);
290 }
291 if (g_fs_uae_frame == o + 810) {
292 fs_uae_process_input_event(line, INPUTEVENT_JOY1_FIRE_BUTTON, 0, 0);
293 }
294 if (g_fs_uae_frame == o + 900) {
295 fs_uae_process_input_event(line, INPUTEVENT_JOY1_FIRE_BUTTON, 1, 0);
296 }
297 if (g_fs_uae_frame == o + 910) {
298 fs_uae_process_input_event(line, INPUTEVENT_JOY1_FIRE_BUTTON, 0, 0);
299 }
300 #if 0
301 if (g_fs_uae_frame == 1000) {
302 fs_uae_process_input_event(line, INPUTEVENT_JOY1_2ND_BUTTON, 1, 0);
303 }
304 if (g_fs_uae_frame == 1050) {
305 fs_uae_process_input_event(line, INPUTEVENT_JOY1_2ND_BUTTON, 0, 0);
306 }
307 #endif
308 }
309 #endif
310
311 int event, state;
312 while (fs_uae_get_recorded_input_event(g_fs_uae_frame, line, &event, &state)) {
313 fs_uae_process_input_event(line, event, state, 1);
314 }
315
316 return 1;
317 }
318
pause_throttle(void)319 static void pause_throttle(void)
320 {
321 /*
322 if (fs_emu_get_vblank_sync()) {
323 return;
324 }
325 */
326 fs_emu_msleep(5);
327 }
328
event_handler(int line)329 static void event_handler(int line)
330 {
331 // printf("%d\n", line);
332 if (line >= 0) {
333 input_handler_loop(line);
334 return;
335 }
336 //static int busy = 0;
337 //static int idle = 0;
338 //static int64_t last_time = 0;
339 g_fs_uae_frame = g_fs_uae_frame + 1;
340
341 #if 0
342 if (g_fs_uae_frame != amiga_get_vsync_counter()) {
343 printf("g_fs_uae_frame %d amiga_get_vsync_count %d\n", g_fs_uae_frame, amiga_get_vsync_counter());
344 }
345 #endif
346 //printf("event_handler frame=%d\n", frame);
347
348 fs_uae_record_frame(g_fs_uae_frame);
349
350 /*
351 int64_t t = fs_emu_monotonic_time();
352 if (last_time > 0) {
353 int dt = (t - last_time) / 1000;
354 printf("%d\n", dt);
355 }
356 */
357
358 //fs_emu_lua_run_handler("on_fs_uae_frame_start");
359
360 fs_emu_wait_for_frame(g_fs_uae_frame);
361 if (g_fs_uae_frame == 1) {
362 if (!fs_emu_netplay_enabled()) {
363 if (fs_config_true(OPTION_WARP_MODE)) {
364 amiga_send_input_event(INPUTEVENT_SPC_WARP, 1);
365 }
366 }
367 /* We configure input ports after first frame are confirmed,
368 * because otherwise configure events would get lost if initially
369 * connected to the server (for net play game), but aborted connection
370 * before game started. */
371 fs_uae_reconfigure_input_ports_amiga();
372 /* Also configure input ports now (which also makes sure keyboard
373 * etc. is initialized) to ensure it is configured at least once. */
374 fs_uae_reconfigure_input_ports_host();
375 }
376
377 if (fs_emu_is_quitting()) {
378 if (fs_emu_is_paused()) {
379 fs_emu_pause(0);
380 }
381 static int quit_called = 0;
382 if (quit_called == 0) {
383 fs_log("calling amiga_quit\n");
384 amiga_quit();
385 quit_called = 1;
386 }
387 //return;
388 }
389 while (fs_emu_is_paused()) {
390 /*
391 if (!event_handler_loop()) {
392 break;
393 }
394 */
395 pause_throttle();
396 if (fs_emu_is_quitting()) {
397 break;
398 }
399 }
400
401 //last_time = fs_emu_monotonic_time();
402
403 }
404
405 char *g_fs_uae_disk_file_path = NULL;
406 char *g_fs_uae_config_file_path = NULL;
407 char *g_fs_uae_config_dir_path = NULL;
408 //GKeyFile *g_fs_uae_config = NULL;
409
audio_callback_function(int type,int16_t * buffer,int size)410 static int audio_callback_function(int type, int16_t *buffer, int size)
411 {
412 if (type == 0) {
413 return fse_queue_audio_buffer(0, buffer, size);
414 } else if (type == 1) {
415 fse_set_audio_paused(0, true);
416 return 0;
417 } else if (type == 2) {
418 fse_set_audio_paused(0, false);
419 return 0;
420 } else if (type == 3) {
421 /* CD audio stream */
422 if (buffer == NULL) {
423 /* Check status of buffer number given by size. */
424 return fse_check_audio_buffer(1, size);
425 }
426 return fse_queue_audio_buffer(1, buffer, size);
427 }
428 return -1;
429 }
430
fs_uae_load_rom_files(const char * path)431 void fs_uae_load_rom_files(const char *path)
432 {
433 fs_log("fs_uae_load_rom_files %s\n", path);
434 GDir *dir = g_dir_open(path, 0, NULL);
435 if (dir == NULL) {
436 fs_log("error opening dir\n");
437 return;
438 }
439
440 // we include the rom key when generating the cache name for the
441 // kickstart cache file, so the cache will be regenerated if rom.key
442 // is replaced or removed/added.
443 char *key_path = g_build_filename(path, "rom.key", NULL);
444 GChecksum *rom_checksum = g_checksum_new(G_CHECKSUM_MD5);
445 FILE *f = g_fopen(key_path, "rb");
446 if (f != NULL) {
447 int64_t key_size = fs_path_get_size(key_path);
448 if (key_size > 0 && key_size < 1024 * 1024) {
449 guchar *key_data = malloc(key_size);
450 if (fread(key_data, key_size, 1, f) != 1) {
451 free(key_data);
452 }
453 else {
454 fs_log("read rom key file, size = %d\n", key_size);
455 g_checksum_update(rom_checksum, key_data, key_size);
456 }
457 }
458 fclose(f);
459 }
460 g_free(key_path);
461
462 amiga_add_key_dir(path);
463 const char *name = g_dir_read_name(dir);
464 while (name) {
465 char *lname = g_utf8_strdown(name, -1);
466 if (g_str_has_suffix(lname, ".rom")
467 || g_str_has_suffix(lname, ".bin")) {
468 fs_log("found file \"%s\"\n", name);
469 char *full_path = g_build_filename(path, name, NULL);
470 //GChecksum *checksum = g_checksum_new(G_CHECKSUM_MD5);
471 GChecksum *checksum = g_checksum_copy(rom_checksum);
472 g_checksum_update(
473 checksum, (guchar *) full_path, strlen(full_path));
474 const gchar *cache_name = g_checksum_get_string(checksum);
475 char* cache_path = g_build_filename(
476 fs_uae_kickstarts_cache_dir(), cache_name, NULL);
477 amiga_add_rom_file(full_path, cache_path);
478 // check if amiga_add_rom_file needs to own full_path
479 //free(full_path);
480 if (cache_path != NULL) {
481 free(cache_path);
482 }
483 g_checksum_free(checksum);
484 }
485 free(lname);
486 name = g_dir_read_name(dir);
487 }
488 g_dir_close(dir);
489
490 if (rom_checksum != NULL) {
491 g_checksum_free(rom_checksum);
492 }
493 //exit(1);
494 }
495
fs_uae_encode_path(const char * path)496 char *fs_uae_encode_path(const char *path)
497 {
498 // FIXME: libamiga now always accepts UTF-8, so this function is
499 // deprecated. Simply returning a duplicate now.
500 return g_strdup(path);
501 }
502
fs_uae_decode_path(const char * path)503 char *fs_uae_decode_path(const char *path)
504 {
505 // FIXME: libamiga now always accepts UTF-8, so this function is
506 // deprecated. Simply returning a duplicate now.
507 return g_strdup(path);
508 }
509
on_gui_message(const char * message)510 static void on_gui_message(const char *message)
511 {
512 printf("MESSAGE: %s\n", message);
513 fs_emu_warning("%s", message);
514 }
515
on_init(void)516 static void on_init(void)
517 {
518 fs_log("\n");
519 fs_log(LOG_LINE);
520 fs_log("uae configuration\n");
521 fs_log(LOG_LINE);
522 fs_log("\n");
523
524 amiga_set_gui_message_function(on_gui_message);
525
526 //fs_uae_configure_amiga_model();
527 fs_uae_configure_amiga_hardware();
528 fs_uae_configure_floppies();
529 fs_uae_configure_hard_drives();
530 fs_uae_configure_cdrom();
531 fs_uae_configure_input();
532 fs_uae_configure_directories();
533
534 if (fs_config_get_int("save_state_compression") == 0) {
535 amiga_set_save_state_compression(0);
536 }
537 else {
538 amiga_set_save_state_compression(1);
539 }
540
541 if (fs_config_get_int("min_first_line_pal") != FS_CONFIG_NONE) {
542 amiga_set_min_first_line(fs_config_get_int("min_first_line_pal"), 0);
543 }
544 if (fs_config_get_int("min_first_line_ntsc") != FS_CONFIG_NONE) {
545 amiga_set_min_first_line(fs_config_get_int("min_first_line_ntsc"), 1);
546 }
547 if (fs_config_true(OPTION_CLIPBOARD_SHARING)) {
548 amiga_set_option("clipboard_sharing", "yes");
549 }
550
551 /*
552 if (fs_emu_get_video_sync()) {
553 fs_log("fs_emu_get_video_sync returned true\n");
554 amiga_set_option("gfx_vsync", "true");
555 }
556 else {
557 fs_log("fs_emu_get_video_sync returned false\n");
558 }
559 if (fs_emu_netplay_enabled()) {
560 fs_log("netplay is enabled\n");
561 // make sure UAE does not sleep between frames, we must be able
562 // to control sleep times for net play
563 amiga_set_option("gfx_vsync", "true");
564 }
565 */
566
567 /* With sound_auto set to true, UAE stops audio output if the amiga does
568 * not produce sound. */
569 // amiga_set_option("sound_auto", "false");
570
571 amiga_set_audio_frequency(fs_emu_audio_output_frequency());
572
573 //amiga_set_audio_frequency(22050);
574
575
576 // set the input frequency to the output frequency, since we configured
577 // libamiga to output at the same frequency
578
579 // FIXME: check the actual frequency libuae/libamiga outputs, seems
580 // to output at 44100 Hz even though currprefs.freq says 48000.
581 // fs_emu_set_audio_buffer_frequency(0, fs_emu_get_audio_frequency());
582
583 //amiga_set_option("gfx_gamma", "40");
584
585 fs_uae_set_uae_paths();
586 fs_uae_read_custom_uae_options(fs_uae_argc, fs_uae_argv);
587
588 char *uae_file;
589
590 uae_file = g_build_filename(fs_uae_logs_dir(), "LastConfig.uae", NULL);
591 if (fs_path_exists(uae_file)) {
592 g_unlink(uae_file);
593 }
594 g_free(uae_file);
595
596 uae_file = g_build_filename(fs_uae_logs_dir(), "DebugConfig.uae", NULL);
597 if (fs_path_exists(uae_file)) {
598 g_unlink(uae_file);
599 }
600 g_free(uae_file);
601
602 uae_file = g_build_filename(fs_uae_logs_dir(), "Debug.uae", NULL);
603 if (fs_path_exists(uae_file)) {
604 g_unlink(uae_file);
605 }
606 g_free(uae_file);
607
608 uae_file = g_build_filename(fs_uae_logs_dir(), "debug.uae", NULL);
609 amiga_write_uae_config(uae_file);
610 g_free(uae_file);
611
612 fs_log("\n");
613 fs_log(LOG_LINE);
614 fs_log("end of uae configuration\n");
615 fs_log(LOG_LINE);
616 fs_log("\n");
617 }
618
pause_function(int pause)619 static void pause_function(int pause)
620 {
621 fs_log("pause_function %d\n", pause);
622 //uae_pause(pause);
623 amiga_pause(pause);
624 }
625
load_config_file(void)626 static int load_config_file(void)
627 {
628 fs_log("load config file\n");
629 const char *msg = "checking config file %s\n";
630
631 char *data;
632 int size;
633 if (fs_data_file_content("META-INF/Config.fs-uae", &data, &size) == 0) {
634 fs_ini_file *ini_file = fs_ini_file_open_data(data, size);
635 if (ini_file == NULL) {
636 fs_log("error loading config file\n");
637 return 1;
638 }
639 fs_config_parse_ini_file(ini_file, 0);
640 fs_ini_file_destroy(ini_file);
641 return 0;
642 }
643
644 //g_fs_uae_config = g_key_file_new();
645 if (g_fs_uae_config_file_path == NULL) {
646 char *path = g_build_filename(fs_uae_exe_dir(), "Config.fs-uae",
647 NULL);
648 fs_log(msg, path);
649 if (fs_path_exists(path)) {
650 g_fs_uae_config_file_path = path;
651 }
652 else {
653 free(path);
654 }
655 }
656 #ifdef MACOSX
657 if (g_fs_uae_config_file_path == NULL) {
658 char *path = g_build_filename(fs_uae_exe_dir(), "..", "..",
659 "Config.fs-uae", NULL);
660 fs_log(msg, path);
661 if (fs_path_exists(path)) {
662 g_fs_uae_config_file_path = path;
663 }
664 else {
665 free(path);
666 }
667 }
668 #endif
669 if (g_fs_uae_config_file_path == NULL) {
670 fs_log(msg, "Config.fs-uae");
671 if (fs_path_exists("Config.fs-uae")) {
672 g_fs_uae_config_file_path = "Config.fs-uae";
673 }
674 }
675 if (g_fs_uae_config_file_path == NULL) {
676 fs_log(msg, "fs-uae.conf");
677 if (fs_path_exists("fs-uae.conf")) {
678 g_fs_uae_config_file_path = "fs-uae.conf";
679 }
680 }
681 if (g_fs_uae_config_file_path == NULL) {
682 char *path = g_build_filename(fse_user_config_dir(),
683 "fs-uae", "fs-uae.conf", NULL);
684 fs_log(msg, path);
685 if (fs_path_exists(path)) {
686 g_fs_uae_config_file_path = path;
687 }
688 else {
689 free(path);
690 }
691 }
692 if (g_fs_uae_config_file_path == NULL) {
693 char *path = g_build_filename(fs_uae_configurations_dir(),
694 "Default.fs-uae", NULL);
695 fs_log(msg, path);
696 if (fs_path_exists(path)) {
697 g_fs_uae_config_file_path = path;
698 }
699 else {
700 free(path);
701 }
702 }
703 if (g_fs_uae_config_file_path) {
704 fs_log("loading config from %s\n", g_fs_uae_config_file_path);
705 fs_config_read_file(g_fs_uae_config_file_path, 0);
706 g_fs_uae_config_dir_path = g_path_get_dirname(
707 g_fs_uae_config_file_path);
708 }
709 #if 0
710 else {
711 if (fs_config_get_boolean("end_config") == 1) {
712 // do not warn in case end_config was specified via argv
713 }
714 else {
715 fs_log("No configuration file was found");
716 g_warn_about_missing_config_file = 1;
717 }
718 }
719 #endif
720
721 char *path = g_build_filename(fs_uae_configurations_dir(),
722 "Host.fs-uae", NULL);
723 fs_log(msg, path);
724 if (fs_path_exists(path)) {
725 fs_config_read_file(path, 0);
726 free(path);
727 }
728
729 return 0;
730 }
731
log_to_libfsemu(const char * message)732 static void log_to_libfsemu(const char *message)
733 {
734 /* UAE logs some messages char-for-char, so we need to buffer logging
735 * here if we want to log with [UAE] prefix. */
736 // fs_log("[UAE] %s", message);
737 static bool initialized;
738 static bool ignore;
739 if (!initialized) {
740 initialized = true;
741 ignore = fs_config_false(OPTION_UAELOG);
742 }
743 if (!ignore) {
744 fs_log_string(message);
745 }
746 }
747
main_function()748 static void main_function()
749 {
750 amiga_main();
751 fs_log("[CORE] Return from amiga_main\n");
752 fs_uae_write_recorded_session();
753 }
754
755 #ifdef WINDOWS
756 // FIXME: move to fs_putenv
757 // int _putenv(const char *envstring);
758 #endif
759
init_i18n(void)760 static void init_i18n(void)
761 {
762 // FIXME: language = 0 instead?
763 if (fs_config_get_boolean("localization") == 0) {
764 fs_log("[I18N ] Localization was forcefully disabled\n");
765 return;
766 }
767
768 char *locale = setlocale(LC_MESSAGES, "");
769 if (locale) {
770 fs_log("[I18N] Locale is set to %s\n", locale);
771 } else {
772 fs_log("[I18N] Failed to set current locale\n");
773 }
774
775 const char *language = fs_config_get_const_string("language");
776 if (language) {
777 fs_log("[I18N] Set environment LANGUAGE=%s\n", language);
778 char *env_str = g_strdup_printf("LANGUAGE=%s", language);
779 #ifdef WINDOWS
780 _putenv(env_str);
781 #else
782 putenv(env_str);
783 #endif
784 /* Do not free env_str, it's put directly in the environment. */
785 }
786
787 #ifndef ANDROID
788 textdomain("fs-uae");
789
790 char executable_dir[FS_PATH_MAX];
791 fs_get_application_exe_dir(executable_dir, FS_PATH_MAX);
792 char *locale_base = g_build_filename(
793 executable_dir, "..", "..", "Data", "Locale", NULL);
794 if (g_file_test(locale_base, G_FILE_TEST_IS_DIR)) {
795 fs_log("[I18N] Using locale dir \"%s\"\n", locale_base);
796 bindtextdomain("fs-uae", locale_base);
797 free(locale_base);
798 } else {
799 char *path = fs_get_data_file("fs-uae/share-dir");
800 if (path) {
801 fs_log("[I18N] Using data dir \"%s\"\n", path);
802 /* Remove trailing "fs-uae/share-dir" from the returned path. */
803 int len = strlen(path);
804 if (len > 16) {
805 path[len - 16] = '\0';
806 }
807 char *locale_base = g_build_filename(path, "locale", NULL);
808 fs_log("[I18N] Using locale dir \"%s\"\n", locale_base);
809 bindtextdomain("fs-uae", locale_base);
810 free(locale_base);
811 free(path);
812 }
813 }
814 bind_textdomain_codeset("fs-uae", "UTF-8");
815 #endif
816 }
817
led_function(int led,int state)818 static void led_function(int led, int state)
819 {
820 /* floppy led status is custom overlay 0..3 */
821 #if 0
822 if (led >= 0) {
823 printf("led %d state %d\n", led, state);
824 }
825 #endif
826 fs_emu_set_custom_overlay_state(led, state);
827 }
828
on_update_leds(void * data)829 static void on_update_leds(void *data)
830 {
831 amiga_led_data *leds = (amiga_led_data *) data;
832 for (int i = 0; i < 4; i++) {
833 int led = 12; // df0_d1
834 led = led + i * 2;
835 fs_emu_set_custom_overlay_state(led + 0, leds->df_t1[i]);
836 fs_emu_set_custom_overlay_state(led + 1, leds->df_t0[i]);
837 }
838 }
839
840 static unsigned int whdload_quit_key = 0;
841 static int64_t whdload_quit_time = 0;
842
fs_emu_send_whdload_quit_key(int whdload_quit_key)843 static void fs_emu_send_whdload_quit_key(int whdload_quit_key) {
844 fs_log("Find input event for amiga key %d\n", whdload_quit_key);
845 int input_event = amiga_find_input_event_for_key(whdload_quit_key);
846 fs_log("Found input event %d for amiga key %d\n", input_event, whdload_quit_key);
847 if (input_event) {
848 fs_log("Sending WHDLoad quit key input");
849 fs_emu_queue_action(input_event, 1);
850 }
851 }
852
quit_function()853 static int quit_function()
854 {
855 fs_log("quit_function\n");
856 if (whdload_quit_key) {
857 if (whdload_quit_time > 0) {
858 int64_t diff = fs_ml_monotonic_time() - whdload_quit_time;
859 if (diff < 0.1 * 1000000) {
860 // Duplicate SDL_QUIT event?
861 return 0;
862 }
863 // Press quit twice within one second to force quit
864 if (diff < 1.0 * 1000000) {
865 return 1;
866 }
867 }
868 fs_log("NOT QUITING\n");
869 if (whdload_quit_time == 0) {
870 // Only show this message once
871 fs_emu_warning(
872 "Sent WHDLoad quit key ($%02X) to exit gracefully",
873 whdload_quit_key
874 );
875 } else {
876 fs_emu_warning("Press Quit twice to force quit");
877 }
878 fs_emu_send_whdload_quit_key(whdload_quit_key);
879 whdload_quit_time = fs_ml_monotonic_time();
880 return 0;
881 }
882 return 1;
883 }
884
media_function(int drive,const char * path)885 static void media_function(int drive, const char *path)
886 {
887 // media insertion status is custom overlay 4..7
888 fs_emu_set_custom_overlay_state(4 + drive, path && path[0]);
889 }
890
891 int ManyMouse_Init(void);
892 void ManyMouse_Quit(void);
893 const char *ManyMouse_DeviceName(unsigned int index);
894
list_joysticks()895 static void list_joysticks()
896 {
897 printf("# FS-UAE %s\n", PACKAGE_VERSION);
898 printf("# listing keyboards\n");
899 printf("K: Keyboard\n");
900 printf("# listing mice\n");
901 printf("M: Mouse\n");
902 int count = ManyMouse_Init();
903 if (count >= 0) {
904 for (int i = 0; i < count; i++) {
905 const char *name = ManyMouse_DeviceName(i);
906 if (name[0] == 0 || strcasecmp(name, "mouse") == 0) {
907 printf("M: Unnamed Mouse\n");
908 }
909 else {
910 printf("M: %s\n", ManyMouse_DeviceName(i));
911 }
912 }
913 ManyMouse_Quit();
914 }
915
916 printf("# listing joysticks\n");
917 #ifdef USE_SDL
918 if (SDL_Init(SDL_INIT_JOYSTICK ) < 0) {
919 printf("# SDL_Init(SDL_INIT_JOYSTICK ) < 0\n");
920 return;
921 }
922 printf("# SDL_NumJoysticks(): %d\n", SDL_NumJoysticks());
923 for(int i = 0; i < SDL_NumJoysticks(); i++) {
924 if (SDL_JoystickName(i)[0] == '\0') {
925 printf("J: Unnamed\n");
926 }
927 else {
928 printf("J: %s\n", SDL_JoystickName(i));
929 }
930 }
931 #else
932 printf("# USE_SDL is not defined\n");
933 #endif
934 printf("# listing joysticks done\n");
935 }
936
937 extern int disk_debug_logging;
938 extern int g_frame_debug_logging;
939 extern int g_fsdb_debug;
940 extern int g_random_debug_logging;
941 extern int inputdevice_logging;
942
configure_logging(const char * logstr)943 static void configure_logging(const char *logstr)
944 {
945 if (fs_config_get_int(OPTION_LOG_BSDSOCKET) == 1) {
946 log_bsd = 1;
947 }
948
949 if (!logstr) {
950 fs_log("configure logging: none\n");
951 return;
952 }
953 fs_log("configure logging: %s\n", logstr);
954 int all = strstr(logstr, "all") != 0;
955 int uae_all = all || strstr(logstr, "uae") != 0;
956 if (uae_all || strstr(logstr, "uae_disk")) {
957 disk_debug_logging = 2;
958 }
959 if (uae_all || strstr(logstr, "uae_rand")) {
960 g_random_debug_logging = 2;
961 }
962 if (uae_all || strstr(logstr, "uae_input")) {
963 inputdevice_logging = 0xffff;
964 }
965 if (uae_all || strstr(logstr, "uae_fs")) {
966 g_fsdb_debug = 1;
967 }
968 if (uae_all || strstr(logstr, "uae_frame")) {
969 g_frame_debug_logging = 1;
970 }
971 }
972
cleanup_old_file(const char * path)973 static void cleanup_old_file(const char *path)
974 {
975 char *p = fs_uae_expand_path(path);
976 if (fs_path_exists(p)) {
977 if (fs_path_is_dir(p)) {
978 fs_log("trying to remove old directory %s\n", p);
979 g_rmdir(p);
980 }
981 else {
982 fs_log("trying to remove old file %s\n", p);
983 g_unlink(p);
984 }
985 }
986 free(p);
987 }
988
cleanup_old_files()989 static void cleanup_old_files()
990 {
991 // Logs are now stored in $BASE/Cache/Logs by default
992 cleanup_old_file("$BASE/Logs/FS-UAE.log");
993 cleanup_old_file("$BASE/Logs/FS-UAE.log.txt");
994 cleanup_old_file("$BASE/Logs/DebugConfig.uae");
995 cleanup_old_file("$BASE/Logs/Launcher.log.txt");
996 cleanup_old_file("$BASE/Logs/Synchronization.log");
997 // try to remove the dir - if it now is empty
998 cleanup_old_file("$BASE/Logs");
999 }
1000
check_extension(const char * path,const char * ext)1001 static bool check_extension(const char *path, const char *ext)
1002 {
1003 if (path == NULL) {
1004 return false;
1005 }
1006 gchar* path_lower = g_ascii_strdown(path, -1);
1007 bool result = g_str_has_suffix(path_lower, ext);
1008 g_free(path_lower);
1009 return result;
1010 }
1011
1012 #ifdef LINUX
check_linux_cpu_governor()1013 static void check_linux_cpu_governor()
1014 {
1015 gchar *governor;
1016 if (!g_file_get_contents(
1017 "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor",
1018 &governor, NULL, NULL)) {
1019 return;
1020 }
1021 g_strstrip(governor);
1022 fs_log("CPU scaling governor: '%s'\n", governor);
1023 if (fs_config_get_boolean(OPTION_GOVERNOR_WARNING) == 0) {
1024 return;
1025 }
1026 if (strcmp(governor, "performance") != 0) {
1027 fs_emu_warning(
1028 _("CPU scaling governor is '%s', not '%s'"),
1029 governor,
1030 "performance"
1031 );
1032 fs_emu_warning(_("Emulation frame rate may suffer"));
1033 }
1034 g_free(governor);
1035 }
1036 #endif
1037
1038 static const char *overlay_names[] = {
1039 "df0_led", // 0
1040 "df1_led", // 1
1041 "df2_led", // 2
1042 "df3_led", // 3
1043 "df0_disk", // 4
1044 "df1_disk", // 5
1045 "df2_disk", // 6
1046 "df3_disk", // 7
1047 "power_led", // 8
1048 "hd_led", // 9
1049 "cd_led", // 10
1050 "md_led", // 11
1051
1052 "df0_d1", // 12
1053 "df0_d0",
1054 "df1_d1",
1055 "df1_d0",
1056 "df2_d1",
1057 "df2_d0",
1058 "df3_d1",
1059 "df3_d0",
1060 NULL,
1061 };
1062
1063 #if defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
1064 #define ARCH_NAME_2 "x86-64"
1065 #elif defined(__i386__) || defined (_M_IX86)
1066 #define ARCH_NAME_2 "x86"
1067 #elif defined(__ppc__)
1068 #define ARCH_NAME_2 "PPC"
1069 #elif defined(__arm__)
1070 #define ARCH_NAME_2 "ARM"
1071 #else
1072 #define ARCH_NAME_2 "?"
1073 #endif
1074
1075 #define COPYRIGHT_NOTICE "FS-UAE %s (Built for %s %s)\n" \
1076 "Copyright 1995-2002 Bernd Schmidt, 1999-2017 Toni Wilen,\n" \
1077 "2003-2007 Richard Drummond, 2006-2011 Mustafa 'GnoStiC' Tufan,\n" \
1078 "2011-2017 Frode Solheim, and contributors.\n" \
1079 "\n" \
1080 "This is free software; see the file COPYING for copying conditions. There\n" \
1081 "is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" \
1082 "PURPOSE. See the README for more copyright info, and the source code for\n" \
1083 "a full list of contributors\n\n"
1084
1085 #define EXTRA_HELP_TEXT "" \
1086 "Documentation is available at http://fs-uae.net/documentation\n" \
1087 "(See http://fs-uae.net/options for a list of configuration options)\n" \
1088 "\n"
1089
1090 FILE *g_state_log_file = NULL;
1091
main(int argc,char * argv[])1092 int main(int argc, char *argv[])
1093 {
1094 fs_uae_argc = argc;
1095 fs_uae_argv = argv;
1096 fs_set_argv(argc, argv);
1097
1098 #ifdef WITH_CEF
1099 cef_init(argc, argv);
1100 #endif
1101
1102 char **arg;
1103 arg = argv + 1;
1104 while (arg && *arg) {
1105 if (strcmp(*arg, "--list-joysticks") == 0) {
1106 list_joysticks();
1107 exit(0);
1108 } else if (strcmp(*arg, "--list-devices") == 0) {
1109 list_joysticks();
1110 exit(0);
1111 } else if (strcmp(*arg, "--version") == 0) {
1112 printf("%s\n", PACKAGE_VERSION);
1113 exit(0);
1114 } else if (strcmp(*arg, "--help") == 0) {
1115 printf(COPYRIGHT_NOTICE, PACKAGE_VERSION, OS_NAME_2, ARCH_NAME_2);
1116 printf(EXTRA_HELP_TEXT);
1117 exit(0);
1118 }
1119 arg++;
1120 }
1121
1122 fs_init();
1123 int error = fs_data_init("fs-uae", "fs-uae.dat");
1124 if (error) {
1125 printf("WARNING: error (%d) loading fs-uae.dat\n", error);
1126 }
1127
1128 fs_set_prgname("fs-uae");
1129 fs_set_application_name("Amiga Emulator");
1130
1131 amiga_set_log_function(log_to_libfsemu);
1132
1133 //result = parse_options(argc, argv);
1134
1135 printf(COPYRIGHT_NOTICE, PACKAGE_VERSION, OS_NAME_2, ARCH_NAME_2);
1136 fs_log(COPYRIGHT_NOTICE, PACKAGE_VERSION, OS_NAME_2, ARCH_NAME_2);
1137
1138 char *current_dir = g_get_current_dir();
1139 fs_log("current directory is %s\n", current_dir);
1140 g_free(current_dir);
1141
1142 amiga_init();
1143
1144 #ifdef MACOSX
1145 /* Can be overriden via environment variable (or launcher setting):
1146 * SDL_VIDEO_MAC_FULLSCREEN_SPACES = 1 */
1147 SDL_SetHint(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, "0");
1148
1149 SDL_Init(SDL_INIT_EVERYTHING);
1150 SDL_PumpEvents();
1151 SDL_Event event;
1152 fs_log("OS X: Check for pending SDL_DROPFILE event\n");
1153 while (SDL_PollEvent(&event)) {
1154 fs_log("Got SDL event 0x%x\n", event.type);
1155 if (event.type == SDL_DROPFILE) {
1156 if (event.drop.file != NULL) {
1157 g_fs_uae_config_file_path = strdup(event.drop.file);
1158 }
1159 SDL_free(event.drop.file);
1160 }
1161 }
1162 #endif
1163
1164 // skip first entry
1165 arg = argv + 1;
1166 if (g_fs_uae_config_file_path == NULL) {
1167 while (arg && *arg) {
1168 const gchar *test_path = *arg;
1169 if (test_path && fs_path_exists(test_path)) {
1170 if (check_extension(test_path, ".fs-uae")) {
1171 g_fs_uae_config_file_path = g_strdup(test_path);
1172 } else if (check_extension(test_path, ".conf")) {
1173 g_fs_uae_config_file_path = g_strdup(test_path);
1174 } else if (check_extension(test_path, ".adf")) {
1175 g_fs_uae_disk_file_path = g_strdup(test_path);
1176 } else if (check_extension(test_path, ".ipf")) {
1177 g_fs_uae_disk_file_path = g_strdup(test_path);
1178 } else if (check_extension(test_path, ".dms")) {
1179 g_fs_uae_disk_file_path = g_strdup(test_path);
1180 }
1181 }
1182 arg++;
1183 }
1184 }
1185
1186 /* Parse options first, in case base_dir, logging options etc is
1187 * specified on the command line. */
1188 fs_config_parse_options(argc - 1, argv + 1);
1189
1190 fs_log("\n");
1191 fs_log(LOG_LINE);
1192 fs_log("libfsemu init\n");
1193 fs_log(LOG_LINE);
1194 fs_log("\n");
1195
1196 fs_emu_path_set_expand_function(fs_uae_expand_path);
1197
1198 fs_emu_init_overlays(overlay_names);
1199 fse_init_early();
1200
1201 /* Then load the config file and set data dir */
1202 load_config_file();
1203 fs_set_data_dir(fs_uae_data_dir());
1204
1205 init_i18n();
1206
1207 if (g_fs_uae_disk_file_path) {
1208 fs_config_set_string(OPTION_FLOPPY_DRIVE_0, g_fs_uae_disk_file_path);
1209 g_warn_about_missing_config_file = 0;
1210 }
1211
1212 if (g_warn_about_missing_config_file) {
1213 fs_emu_warning(_("No configuration file was found"));
1214 }
1215 #if 0
1216 const char *expect_version = fs_config_get_const_string(
1217 OPTION_EXPECT_VERSION);
1218 if (expect_version && strcmp(expect_version, PACKAGE_VERSION) != 0) {
1219 fs_emu_warning(_("Expected FS-UAE version %s, got %s"),
1220 expect_version, PACKAGE_VERSION);
1221 }
1222 #endif
1223
1224 #ifdef LINUX
1225 if (fs_config_get_boolean(OPTION_GAME_MODE) != 0) {
1226 if (gamemode_request_start() < 0) {
1227 fs_log("GameMode: Request failed: %s\n", gamemode_error_string());
1228 } else {
1229 fs_log("GameMode: Enabled game mode\n");
1230 }
1231 }
1232 check_linux_cpu_governor();
1233 #endif
1234
1235 fs_log("\n");
1236 fs_log(LOG_LINE);
1237 fs_log("fs-uae init\n");
1238 fs_log(LOG_LINE);
1239 fs_log("\n");
1240
1241 configure_logging(fs_config_get_const_string("log"));
1242
1243 fs_log("[GLIB] Version %d.%d.%d (Compiled against %d.%d.%d)\n",
1244 glib_major_version, glib_minor_version, glib_micro_version,
1245 GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
1246 #if 0
1247 fs_log("[GLIB] Using system malloc: %s\n",
1248 g_mem_is_system_malloc() ? "Yes" : "No");
1249 #endif
1250
1251 fs_emu_set_state_check_function(amiga_get_state_checksum);
1252 fs_emu_set_rand_check_function(amiga_get_rand_checksum);
1253 fs_emu_set_quit_function(quit_function);
1254
1255 // force creation of some recommended default directories
1256 fs_uae_kickstarts_dir();
1257 fs_uae_configurations_dir();
1258 fs_uae_init_path_resolver();
1259
1260 fs_uae_plugins_init();
1261
1262 // must be called early, before fs_emu_init -affects video output
1263 fs_uae_configure_amiga_model();
1264
1265 // force creation of state directories
1266 //fs_uae_flash_memory_dir();
1267 //fs_uae_save_states_dir();
1268 //fs_uae_floppy_overlays_dir();
1269 fs_uae_state_dir();
1270
1271 const char *controllers_dir = fs_uae_controllers_dir();
1272 if (controllers_dir) {
1273 fs_emu_set_controllers_dir(controllers_dir);
1274 }
1275 const char *logs_dir = fs_uae_logs_dir();
1276 if (logs_dir) {
1277 char *log_file;
1278
1279 log_file = g_build_filename(logs_dir, "FS-UAE.log", NULL);
1280 if (fs_path_exists(log_file)) {
1281 g_unlink(log_file);
1282 }
1283 g_free(log_file);
1284
1285 log_file = g_build_filename(logs_dir, "FS-UAE.log.txt", NULL);
1286 if (fs_path_exists(log_file)) {
1287 g_unlink(log_file);
1288 }
1289 g_free(log_file);
1290
1291 log_file = g_build_filename(logs_dir, "Emulator.log.txt", NULL);
1292 if (fs_path_exists(log_file)) {
1293 g_unlink(log_file);
1294 }
1295 g_free(log_file);
1296
1297 log_file = g_build_filename(logs_dir, "fs-uae.log.txt", NULL);
1298 fs_config_set_log_file(log_file);
1299 g_free(log_file);
1300 }
1301
1302 fs_config_set_string_if_unset("themes_dir", fs_uae_themes_dir());
1303
1304 fs_emu_set_pause_function(pause_function);
1305
1306 //fs_uae_init_input();
1307 fse_init(FS_EMU_INIT_EVERYTHING);
1308
1309 // we initialize the recording module either it is used or not, so it
1310 // can delete state-specific recordings (if necessary) when states are
1311 // saved
1312 fs_uae_init_recording();
1313
1314 int deterministic_mode = 0;
1315 const char* record_file = fs_config_get_const_string("record");
1316 if (record_file) {
1317 fs_log("record file specified: %s, forcing deterministic mode\n",
1318 record_file);
1319 deterministic_mode = 1;
1320 fs_uae_enable_recording(record_file);
1321 } else {
1322 fs_log("not running in record mode\n");
1323 }
1324 if (fs_emu_netplay_enabled() ||
1325 fs_config_get_boolean(OPTION_DETERMINISTIC) == 1) {
1326 deterministic_mode = 1;
1327 }
1328 if (deterministic_mode) {
1329 amiga_set_deterministic_mode();
1330 }
1331
1332 if (logs_dir) {
1333 if (fs_emu_netplay_enabled()) {
1334 char *sync_log_file = g_build_filename(logs_dir,
1335 "Synchronization.log", NULL);
1336 amiga_set_synchronization_log_file(sync_log_file);
1337 free(sync_log_file);
1338 }
1339 }
1340
1341 #if 1 // def FSE_DRIVERS
1342 fse_audio_stream_options **options = fs_emu_audio_alloc_stream_options(2);
1343 options[0]->frequency = fs_emu_audio_output_frequency();
1344 /* 12 * 2352 is CDDA_BUFFERS * 2352 (blkdev_cdimage.cpp) */
1345 options[1]->buffer_size = 12 * 2352;
1346 // begin playing with only one buffer queued
1347 options[1]->min_buffers = 1;
1348 fs_emu_audio_configure(options);
1349 amiga_set_audio_buffer_size(options[0]->buffer_size);
1350 fs_emu_audio_free_stream_options(options);
1351 #else
1352 // this stream is for paula output and drive clicks
1353 // FIXME: could mix drive clicks in its own stream instead, -might
1354 // give higher quality mixing
1355 fse_audio_stream_options options;
1356 options.struct_size = sizeof(fse_audio_stream_options);
1357 fs_emu_init_audio_stream_options(&options);
1358 options.frequency = fs_emu_audio_output_frequency();
1359 fs_emu_init_audio_stream(0, &options);
1360 amiga_set_audio_buffer_size(options.buffer_size);
1361
1362 // this stream is for CD audio output (CDTV/CD32)
1363 fs_emu_init_audio_stream_options(&options);
1364 // 12 * 2352 is CDDA_BUFFERS * 2352 (blkdev_cdimage.cpp)
1365 options.buffer_size = 12 * 2352;
1366 // begin playing with only one buffer queued
1367 options.min_buffers = 1;
1368 fs_emu_init_audio_stream(1, &options);
1369 #endif
1370
1371 amiga_set_audio_callback(audio_callback_function);
1372 amiga_set_cd_audio_callback(audio_callback_function);
1373 amiga_set_event_function(event_handler);
1374
1375 amiga_set_led_function(led_function);
1376 amiga_on_update_leds(on_update_leds);
1377
1378 amiga_set_media_function(media_function);
1379 amiga_set_init_function(on_init);
1380
1381 if (fs_config_get_boolean(OPTION_JIT_COMPILER) == 1) {
1382 amiga_init_jit_compiler();
1383 }
1384
1385 #ifdef WITH_LUA
1386 amiga_init_lua(fs_emu_acquire_lua, fs_emu_release_lua);
1387 amiga_init_lua_state(fs_emu_get_lua_state());
1388 fs_uae_init_lua_state(fs_emu_get_lua_state());
1389 #endif
1390
1391 if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_RGBA) {
1392 amiga_set_video_format(AMIGA_VIDEO_FORMAT_RGBA);
1393 } else if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_BGRA) {
1394 amiga_set_video_format(AMIGA_VIDEO_FORMAT_BGRA);
1395 } else if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_R5G6B5) {
1396 amiga_set_video_format(AMIGA_VIDEO_FORMAT_R5G6B5);
1397 } else if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_R5G5B5A1) {
1398 amiga_set_video_format(AMIGA_VIDEO_FORMAT_R5G5B5A1);
1399 } else {
1400 fs_emu_warning("Unsupported video format requested");
1401 }
1402 amiga_add_rtg_resolution(672, 540);
1403 amiga_add_rtg_resolution(960, 540);
1404 amiga_add_rtg_resolution(672 * 2, 540 * 2);
1405 amiga_add_rtg_resolution(fs_emu_get_windowed_width(),
1406 fs_emu_get_windowed_height());
1407 amiga_add_rtg_resolution(fs_emu_get_fullscreen_width(),
1408 fs_emu_get_fullscreen_height());
1409 fs_uae_init_video();
1410
1411 //fs_uae_init_keyboard();
1412 fs_uae_init_mouse();
1413 fs_uae_configure_menu();
1414
1415 const char *value = fs_config_get_const_string("whdload_quit_key");
1416 if (value) {
1417 sscanf(value, "%02x", &whdload_quit_key);
1418 if (whdload_quit_key) {
1419 fs_log("Using WHDLoad quit key: %02X\n", whdload_quit_key);
1420 }
1421 }
1422
1423 fs_emu_run(main_function);
1424 fs_log("fs-uae shutting down, fs_emu_run returned\n");
1425 if (g_rmdir(fs_uae_state_dir()) == 0) {
1426 fs_log("state dir %s was removed because it was empty\n",
1427 fs_uae_state_dir());
1428 }
1429 else {
1430 fs_log("state dir %s was not removed (non-empty)\n",
1431 fs_uae_state_dir());
1432 }
1433 fs_log("end of main function\n");
1434 cleanup_old_files();
1435
1436 #ifdef WITH_CEF
1437 cef_destroy();
1438 #endif
1439 return 0;
1440 }
1441