1 #include <fs/filesys.h>
2 #include "sysconfig.h"
3 #include "sysdeps.h"
4 
5 #include "uae.h"
6 
7 #include <string.h>
8 #include <string.h>
9 
10 #include "uae/memory.h"
11 #include "autoconf.h"
12 #include "options.h"
13 #include "blkdev.h"
14 #include "clipboard.h"
15 #include "custom.h"
16 #include "keyboard.h"
17 #include "inputdevice.h"
18 #include "disk.h"
19 #include "gui.h"
20 #include "events.h"
21 #include "luascript.h"
22 
23 #include "uae/fs.h"
24 #include "uae/log.h"
25 #include "uae/glib.h"
26 #include "uae/time.h"
27 
28 void keyboard_settrans (void);
29 libamiga_callbacks g_libamiga_callbacks = {};
30 log_function g_amiga_gui_message_function = NULL;
31 amiga_media_function g_amiga_media_function = NULL;
32 
33 int g_uae_deterministic_mode = 0;
34 int g_amiga_paused = 0;
35 bool g_fs_uae_jit_compiler;
36 int g_amiga_savestate_docompress = 1;
37 
38 #ifdef DEBUG_SYNC
39 FILE* g_fs_uae_sync_debug_file = NULL;
40 #endif
41 
42 int g_amiga_video_format = AMIGA_VIDEO_FORMAT_RGBA;
43 int g_amiga_video_bpp = 4;
44 
45 static char *g_floppy_sounds_dir;
46 
47 int g_fs_uae_writable_disk_images = 0;
48 
49 // This is called from the main UAE thread to inform the GUI that a floppy
50 // disk has been inserted or ejected.
51 
gui_filename(int num,const char * name)52 void gui_filename (int num, const char *name) {
53     if (g_amiga_media_function) {
54         g_amiga_media_function(num, name);
55     }
56 }
57 
58 uae_callback_function *uae_on_save_state_finished = NULL;
59 uae_callback_function *uae_on_restore_state_finished = NULL;
60 uae_callback_function *uae_on_update_leds = NULL;
61 
62 
63 extern "C" {
64 
amiga_set_min_first_line(int line,int ntsc)65 int amiga_set_min_first_line(int line, int ntsc) {
66     if (line < 0 || line > 100) {
67         return 1;
68     }
69     if (ntsc) {
70         g_uae_min_first_line_ntsc = line;
71     }
72     else {
73         g_uae_min_first_line_pal = line;
74     }
75     return 0;
76 }
77 
amiga_get_vsync_counter()78 int amiga_get_vsync_counter() {
79     return g_uae_vsync_counter;
80 }
81 
amiga_set_vsync_counter(int vsync_counter)82 void amiga_set_vsync_counter(int vsync_counter) {
83     g_uae_vsync_counter = vsync_counter;
84 }
85 
amiga_on_restore_state_finished(amiga_callback_function * function)86 void amiga_on_restore_state_finished(amiga_callback_function *function) {
87     uae_on_restore_state_finished = function;
88 }
89 
amiga_on_save_state_finished(amiga_callback_function * function)90 void amiga_on_save_state_finished(amiga_callback_function *function) {
91     uae_on_save_state_finished = function;
92 }
93 
amiga_set_save_state_compression(int compress)94 void amiga_set_save_state_compression(int compress) {
95     g_amiga_savestate_docompress = compress ? 1 : 0;
96 }
97 
98 #ifdef WITH_LUA
99 
amiga_init_lua(void (* lock)(void),void (* unlock)(void))100 void amiga_init_lua(void (*lock)(void), void (*unlock)(void)) {
101     //uae_lua_init(lock, unlock);
102     write_log("WARNING: not sending lock function to uae_lua_init\n");
103     uae_lua_init();
104 }
105 
amiga_init_lua_state(lua_State * L)106 void amiga_init_lua_state(lua_State *L) {
107     uae_lua_init_state(L);
108 }
109 
110 #endif
111 
amiga_set_floppy_sounds_dir(const char * path)112 void amiga_set_floppy_sounds_dir(const char *path) {
113     int len = strlen(path);
114     if (path[len - 1] == '/') {
115         g_floppy_sounds_dir = g_strdup(path);
116     }
117     else {
118         // must have directory separator at the end
119         g_floppy_sounds_dir = g_strconcat(path, "/", NULL);
120     }
121 }
122 
amiga_set_media_function(amiga_media_function function)123 void amiga_set_media_function(amiga_media_function function) {
124     g_amiga_media_function = function;
125 }
126 
amiga_floppy_set_writable_images(int writable)127 void amiga_floppy_set_writable_images(int writable) {
128     g_fs_uae_writable_disk_images = writable;
129 }
130 
amiga_init(void)131 int amiga_init(void)
132 {
133     printf("UAE: Initializing core derived from %s\n", UAE_BASE_VERSION);
134     write_log("UAE: Initializing core derived from %s\n", UAE_BASE_VERSION);
135 
136     uae_register_main_thread();
137     uae_time_init();
138 
139     /*
140 #ifdef DEBUG_SYNC
141     g_sync_debug_file = fopen("sync.log", "wb");
142 #endif
143     */
144 
145     // clock sync base is 1000000 (microseconds)
146     syncbase = 1000000;
147 
148     // clock sync base is 10000 (tenths of milliseconds)
149     //syncbase = 10000;
150 
151     filesys_host_init();
152 
153     romlist_init();
154     clipboard_init();
155     return 1;
156 }
157 
amiga_init_jit_compiler(void)158 bool amiga_init_jit_compiler(void)
159 {
160     write_log("JIT: Enabling JIT compiler\n");
161     g_fs_uae_jit_compiler = true;
162     return true;
163 }
164 
amiga_set_video_format(int format)165 void amiga_set_video_format(int format) {
166     g_amiga_video_format = format;
167     if (format == AMIGA_VIDEO_FORMAT_R5G6B5) {
168         g_amiga_video_bpp = 2;
169     }
170     else if (format == AMIGA_VIDEO_FORMAT_R5G5B5A1) {
171         g_amiga_video_bpp = 2;
172     }
173     else {
174         g_amiga_video_bpp = 4;
175     }
176 }
177 
amiga_add_rtg_resolution(int width,int height)178 void amiga_add_rtg_resolution(int width, int height) {
179     write_log("adding rtg resolution %dx%d\n", width, height);
180     int *m = g_amiga_rtg_modes;
181     while (1) {
182         if (*m == -1) {
183             write_log("too many resolutions\n");
184             return;
185         }
186         if (*m == width && *(m + 1) == height) {
187             write_log("resolution already exists\n");
188             return;
189         }
190         if (*m == 0 && *(m + 1) ==0) {
191             *m = width;
192             *(m + 1) = height;
193             return;
194         }
195         m += 2;
196     }
197 }
198 
amiga_map_cd_drives(int enable)199 void amiga_map_cd_drives(int enable) {
200     write_log("setting automount_cddrives to %d\n", enable != 0);
201     currprefs.win32_automount_cddrives = (enable != 0);
202     changed_prefs.win32_automount_cddrives = (enable != 0);
203 }
204 
amiga_set_deterministic_mode()205 void amiga_set_deterministic_mode() {
206     write_log("libamiga enabling net play mode\n");
207     g_uae_deterministic_mode = 1;
208 }
209 
amiga_write_uae_config(const char * path)210 void amiga_write_uae_config(const char *path) {
211     write_log("writing uae config to %s\n", path);
212     cfgfile_save(&currprefs, path, 0);
213 }
214 
set_path(TCHAR * d1,TCHAR * d2,const TCHAR * s)215 static void set_path(TCHAR *d1, TCHAR *d2, const TCHAR *s)
216 {
217     /* Use PATH_MAX - 1 so we have space for any trailing slash */
218     uae_strlcpy(d1, s, PATH_MAX - 1);
219     int d1_len = strlen(d1);
220     if (d1[d1_len - 1] != '/') {
221         strcat(d1, "/");
222     }
223     uae_strlcpy(d2, d1, PATH_MAX);
224 }
225 
amiga_set_paths(const char ** rom_paths,const char ** floppy_paths,const char ** cd_paths,const char ** hd_paths)226 void amiga_set_paths(const char **rom_paths, const char **floppy_paths,
227                      const char **cd_paths, const char **hd_paths)
228 {
229     for (int i = 0; i < MAX_PATHS; i++) {
230         if (floppy_paths[i] == NULL || floppy_paths[i][0] == '\0') {
231             break;
232         }
233         set_path(currprefs.path_floppy.path[i],
234                  changed_prefs.path_floppy.path[i], floppy_paths[i]);
235     }
236     for (int i = 0; i < MAX_PATHS; i++) {
237         if (cd_paths[i] == NULL || cd_paths[i][0] == '\0') {
238             break;
239         }
240         set_path(currprefs.path_cd.path[i],
241                  changed_prefs.path_cd.path[i], cd_paths[i]);
242     }
243     for (int i = 0; i < MAX_PATHS; i++) {
244         if (hd_paths[i] == NULL || hd_paths[i][0] == '\0') {
245             break;
246         }
247         set_path(currprefs.path_hardfile.path[i],
248                  changed_prefs.path_hardfile.path[i], hd_paths[i]);
249     }
250     for (int i = 0; i < MAX_PATHS; i++) {
251         if (rom_paths[i] == NULL || rom_paths[i][0] == '\0') {
252             break;
253         }
254         set_path(currprefs.path_rom.path[i],
255                  changed_prefs.path_rom.path[i], rom_paths[i]);
256     }
257 }
258 
amiga_set_synchronization_log_file(const char * path)259 int amiga_set_synchronization_log_file(const char *path) {
260 #ifdef DEBUG_SYNC
261     FILE *f = g_fopen(path, "wb");
262     if (f) {
263         write_log("sync debug log to %s\n", path);
264         g_fs_uae_sync_debug_file = f;
265         return 1;
266     }
267     else {
268         write_log("error opening synchronization log file\n");
269         return 0;
270     }
271 #endif
272 }
273 
amiga_quickstart(int quickstart_model,int quickstart_config,int accuracy)274 int amiga_quickstart(int quickstart_model, int quickstart_config,
275         int accuracy) {
276     int quickstart_compa = 1 - accuracy;
277     int quickstart_romcheck = 0;
278     write_log("amiga_quickstart model=%d config=%d compa=%d (accuracy %d)\n",
279             quickstart_model, quickstart_config, quickstart_compa, accuracy);
280     return built_in_prefs(&currprefs, quickstart_model, quickstart_config,
281             quickstart_compa, quickstart_romcheck);
282 }
283 
amiga_get_rand_checksum()284 int amiga_get_rand_checksum() {
285     return uaerand() & 0x00ffffff;
286 }
287 
amiga_get_state_checksum(void)288 int amiga_get_state_checksum(void)
289 {
290     int checksum = uae_get_memory_checksum(NULL, 0);
291 #ifdef DEBUG_SYNC
292     write_sync_log("memcheck: %08x\n", checksum);
293 #endif
294     return checksum & 0x00ffffff;
295 }
296 
amiga_get_state_checksum_and_dump(void * data,int size)297 int amiga_get_state_checksum_and_dump(void *data, int size)
298 {
299     int checksum = uae_get_memory_checksum(data, size);
300     return checksum & 0x00ffffff;
301 }
302 
amiga_main(void)303 void amiga_main(void)
304 {
305     write_log("amiga_main\n");
306     uae_register_emulation_thread();
307 
308     keyboard_settrans();
309 
310     int argc = 1;
311     char *argv[4] = {
312             strdup("fs-uae"),
313             NULL,
314     };
315     real_main(argc, argv);
316 #ifdef FILESYS
317     write_log("real_main returned\n");
318     write_log("calling filesys_flush_cache\n");
319     filesys_flush_cache ();
320 #endif
321     write_log("flushing all file streams\n");
322     fflush(NULL);
323 }
324 
amiga_write_config(const char * path)325 void amiga_write_config(const char *path) {
326     cfgfile_save(&currprefs, path, 0);
327 }
328 
amiga_enable_serial_port(const char * serial_name)329 int amiga_enable_serial_port(const char *serial_name)
330 {
331     write_log("amiga_enable_serial_port\n");
332     if (serial_name != NULL && serial_name[0]) {
333         write_log("serial port device: %s\n", serial_name);
334         strcpy(changed_prefs.sername, serial_name);
335         strcpy(currprefs.sername, serial_name);
336         changed_prefs.use_serial = 1;
337         currprefs.use_serial = 1;
338         return 1;
339     }
340     return 0;
341 }
342 
amiga_enable_parallel_port(const char * parallel_name)343 int amiga_enable_parallel_port(const char *parallel_name)
344 {
345     write_log("amiga_enable_parallel_port\n");
346     if (parallel_name != NULL && parallel_name[0]) {
347         write_log("Parallel port device: %s\n", parallel_name);
348         strcpy(changed_prefs.prtname, parallel_name);
349         strcpy(currprefs.prtname, parallel_name);
350         return 1;
351     }
352     return 0;
353 }
354 
amiga_set_cpu_idle(int idle)355 void amiga_set_cpu_idle(int idle)
356 {
357     idle = CLAMP(idle, 0, 10);
358     if (idle != 0) {
359         idle = (12 - idle) * 15;
360     }
361     uae_log("setting cpu_idle = %d\n", idle);
362     changed_prefs.cpu_idle = idle;
363     currprefs.cpu_idle = idle;
364 }
365 
amiga_pause(int pause)366 int amiga_pause(int pause) {
367     //pause_emulation = pause;
368     if (pause) {
369         write_log("calling pausemode (1)\n");
370         //pausemode(-1);
371         g_amiga_paused = 1;
372         pausemode(9);
373     }
374     else {
375         write_log("calling pausemode (0)\n");
376         g_amiga_paused = 0;
377         //pausemode(-1);
378         pausemode(0);
379     }
380     return 0;
381 }
382 
amiga_reset(int hard)383 int amiga_reset(int hard) {
384     uae_reset(hard, 1);
385     return hard;
386 }
387 
amiga_state_save(int slot)388 int amiga_state_save(int slot) {
389     if (slot < 0) {
390         return 0;
391     }
392     if (slot >= 9) {
393         return 0;
394     }
395     write_log("amiga_state_save %d\n", slot);
396     int code = AKS_STATESAVEQUICK1 + slot * 2;
397     inputdevice_add_inputcode(code, 1);
398     return 1;
399 }
400 
amiga_state_load(int slot)401 int amiga_state_load(int slot) {
402     if (slot < 0) {
403         return 0;
404     }
405     if (slot >= 9) {
406         return 0;
407     }
408     write_log("amiga_state_load %d\n", slot);
409     int code = AKS_STATERESTOREQUICK1 + slot * 2;
410     inputdevice_add_inputcode(code, 1);
411     return 1;
412 }
413 
amiga_floppy_get_file(int index)414 const char *amiga_floppy_get_file(int index) {
415     return currprefs.floppyslots[index].df;
416 }
417 
amiga_floppy_get_list_entry(int index)418 const char *amiga_floppy_get_list_entry(int index) {
419     return currprefs.dfxlist[index];
420 }
421 
amiga_floppy_get_drive_type(int index)422 int amiga_floppy_get_drive_type(int index) {
423     return currprefs.floppyslots[index].dfxtype + 1;
424 }
425 
amiga_get_num_cdrom_drives()426 int amiga_get_num_cdrom_drives() {
427     // FIXME: a bit hackish, do some sanity check on this method
428     for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
429         if (currprefs.cdslots[i].inuse != 0) {
430             return i + 1;
431         }
432     }
433     return 0;
434 }
435 
amiga_get_num_floppy_drives()436 int amiga_get_num_floppy_drives() {
437     for (int i = 0; i < 4; i++) {
438         if (currprefs.floppyslots[i].dfxtype < 0) {
439             return i;
440         }
441     }
442     return 4;
443 }
444 
amiga_floppy_set_from_list(int drive,int index)445 int amiga_floppy_set_from_list(int drive, int index) {
446     write_log("insert floppy (%d) into drive (%d)\n", index, drive);
447     if (drive < 0 || drive > 3) {
448         // assert
449         return 0;
450     }
451     if (index < 0 || index >= AMIGA_FLOPPY_LIST_SIZE) {
452         // assert
453         return 0;
454     }
455     write_log("perform disk_swap drive %d floppy entry %d\n", drive, index);
456     strcpy(changed_prefs.floppyslots[drive].df, currprefs.dfxlist[index]);
457     //strcpy(currprefs.floppyslots[drive].df, currprefs.dfxlist[entry]);
458     disk_insert(drive, currprefs.floppyslots[drive].df);
459     /*
460     int i;
461     // eject disk from other drive (if inserted)
462     for (i = 0; i < 4; i++) {
463         if (strcmp (currprefs.floppyslots[i].df, currprefs.dfxlist[index]) == 0)
464             changed_prefs.floppyslots[i].df[0] = 0;
465     }
466     // insert disk
467     // FIXME: IMPORTANT: CHECK length of file (prevent buffer overrun)
468     strcpy(changed_prefs.floppyslots[drive].df, currprefs.dfxlist[index]);
469     config_changed = 1;
470     return 1;
471     */
472     return 1;
473 }
474 
amiga_floppy_set_file(int drive,const char * file)475 int amiga_floppy_set_file(int drive, const char *file) {
476     write_log("insert floppy (%s) into drive (%d)\n", file, drive);
477     int i;
478     // eject disk from other drive (if inserted)
479     for (i = 0; i < 4; i++) {
480         if (strcmp (currprefs.floppyslots[i].df, file) == 0) {
481             changed_prefs.floppyslots[i].df[0] = 0;
482         }
483     }
484     // insert disk
485     // FIXME: IMPORTANT: CHECK length of file (prevent buffer overrun)
486     strcpy(changed_prefs.floppyslots[drive].df, file);
487     config_changed = 1;
488     return 1;
489 }
490 
amiga_cdrom_get_file(int index)491 const char *amiga_cdrom_get_file(int index) {
492     return currprefs.cdslots[index].name;
493 }
494 
amiga_cdrom_eject(int drive)495 void amiga_cdrom_eject(int drive)
496 {
497     write_log("CD-ROM: eject drive %d\n", drive);
498 #if 0
499     write_log("  (currprefs.cdslots[%d].name = %s)\n",
500               drive, currprefs.cdslots[drive].name);
501 #endif
502 
503     // changed_prefs.cdslots[drive].inuse = false;
504     changed_prefs.cdslots[drive].name[0] = '\0';
505     changed_prefs.cdslots[drive].type = SCSI_UNIT_DEFAULT;
506     config_changed = 1;
507 }
508 
amiga_cdrom_set_file(int drive,const char * file)509 int amiga_cdrom_set_file(int drive, const char *file)
510 {
511     write_log("CD-ROM: insert \"%s\" into drive %d\n", file, drive);
512 #if 0
513     write_log("  (currprefs.cdslots[%d].name = %s)\n",
514               drive, currprefs.cdslots[drive].name);
515     write_log("  (changed_prefs.cdslots[%d].name = %s)\n",
516               drive, changed_prefs.cdslots[drive].name);
517 #endif
518 
519     /* Eject CD from current drive */
520     amiga_cdrom_eject(drive);
521 
522     /* Insert new CD */
523     if (file[0] != '\0') {
524         uae_tcslcpy(changed_prefs.cdslots[drive].name, file, MAX_DPATH);
525         // changed_prefs.cdslots[drive].inuse = 1;
526 
527         /* Ejecting CD from other drives if it is inserted there */
528         // FIXME: REPLACE 4 with constant
529         for (int i = 0; i < 4; i++) {
530             if (i != drive && strcmp (currprefs.cdslots[i].name, file) == 0) {
531                 amiga_cdrom_eject(i);
532             }
533         }
534     }
535     config_changed = 1;
536 
537     return 1;
538 }
539 
amiga_floppy_get_speed()540 int amiga_floppy_get_speed() {
541     int speed = currprefs.floppy_speed;
542     write_log("speed is %d\n", speed);
543     return speed / 100;
544 }
545 
amiga_floppy_set_speed(int speed)546 int amiga_floppy_set_speed(int speed) {
547     write_log("set floppy speed to %d\n", speed);
548     changed_prefs.floppy_speed = speed * 100;
549     config_changed = 1;
550     return 1;
551 }
552 
amiga_cpu_get_speed()553 int amiga_cpu_get_speed() {
554     int speed = currprefs.m68k_speed;
555     write_log("cpu speed is %d\n", speed);
556     write_log("cpu freq is %d\n", currprefs.cpu_frequency);
557     write_log("cpu mult is %d\n", currprefs.cpu_clock_multiplier);
558     return speed;
559 }
560 
amiga_cpu_set_speed(int speed)561 int amiga_cpu_set_speed(int speed) {
562     static int initialized = 0;
563     static int org_cpu_clock_multiplier;
564     static int org_cpu_cycle_exact;
565     if (!initialized) {
566         org_cpu_clock_multiplier = currprefs.cpu_clock_multiplier;
567         org_cpu_cycle_exact = currprefs.cpu_cycle_exact;
568         initialized = 1;
569     }
570     write_log("set cpu speed to %d\n", speed);
571     changed_prefs.m68k_speed = speed;
572     if (speed == 0) {
573         changed_prefs.cpu_clock_multiplier = org_cpu_clock_multiplier;
574         changed_prefs.cpu_cycle_exact = org_cpu_cycle_exact;
575     }
576     else {
577         changed_prefs.cpu_clock_multiplier = 32;
578         changed_prefs.cpu_cycle_exact = 0;
579     }
580     config_changed = 1;
581     return 1;
582 }
583 
amiga_parse_option(const char * option,const char * value,int type)584 static int amiga_parse_option(const char *option, const char *value, int type) {
585     // some strings are modified during parsing
586     char *value2 = strdup(value);
587     int result = cfgfile_parse_option(&currprefs, (char*) option,
588             (char*) value2, type);
589     free(value2);
590     write_log("set option \"%s\" to \"%s\" (result: %d)\n", option,
591             value, result);
592     if (result != 1) {
593         gui_message("Option failed: %s = %s", option, value);
594         amiga_log_warning("failed to set option \"%s\" to \"%s\" "
595                 "(result: %d)\n", option, value, result);
596     }
597     return result;
598 }
599 
amiga_set_option(const char * option,const char * value)600 int amiga_set_option(const char *option, const char *value) {
601     return amiga_parse_option(option, value, 0);
602 }
603 
amiga_set_option_and_free(const char * option,char * value,amiga_free_function free_function)604 int amiga_set_option_and_free(const char *option, char *value,
605         amiga_free_function free_function) {
606     int result = amiga_set_option(option, value);
607     free_function(value);
608     return result;
609 }
610 
amiga_set_hardware_option(const char * option,const char * value)611 int amiga_set_hardware_option(const char *option, const char *value) {
612     return amiga_parse_option(option, value, CONFIG_TYPE_HARDWARE);
613 }
614 
amiga_set_int_option(const char * option,int value)615 int amiga_set_int_option(const char *option, int value) {
616     char *str_value = g_strdup_printf("%d", value);
617     int result = amiga_set_option(option, str_value);
618     g_free(str_value);
619     return result;
620 }
621 
amiga_quit()622 int amiga_quit()
623 {
624     printf("UAE: Calling uae_quit\n");
625     uae_quit();
626     return 1;
627 }
628 
amiga_set_display_function(display_function event_handler)629 void amiga_set_display_function(display_function event_handler) {
630     g_libamiga_callbacks.display = event_handler;
631 }
632 
amiga_set_event_function(event_function event_handler)633 void amiga_set_event_function(event_function event_handler) {
634     g_libamiga_callbacks.event = event_handler;
635 }
636 
amiga_set_init_function(init_function function)637 void amiga_set_init_function(init_function function) {
638     g_libamiga_callbacks.init = function;
639 }
640 
amiga_set_render_function(render_function function)641 void amiga_set_render_function(render_function function) {
642     g_libamiga_callbacks.render = function;
643 }
644 
amiga_set_log_function(log_function function)645 void amiga_set_log_function(log_function function) {
646     g_libamiga_callbacks.log = function;
647 }
648 
amiga_set_gui_message_function(log_function function)649 void amiga_set_gui_message_function(log_function function) {
650     g_amiga_gui_message_function = function;
651 }
652 
653 } // extern "C"
654 
655 int disk_setwriteprotect (int num, const TCHAR *name, bool writeprotected);
gui_disk_image_change(int unitnum,const TCHAR * name,bool writeprotected)656 void gui_disk_image_change (int unitnum, const TCHAR *name, bool writeprotected) {
657     if (name && strlen(name) > 0) {
658         write_log("gui_disk_image_change drive %d name %s write protected %d\n",
659                 unitnum, name, writeprotected);
660         /*
661         if (writeprotected) {
662             write_log("calling disk_setwriteprotect 0\n");
663             disk_setwriteprotect(unitnum, name, 0);
664         }
665         */
666     }
667     else {
668         write_log("gui_disk_image_change drive %d <no disk>\n", unitnum);
669     }
670 
671 }
672 
get_plugin_path(TCHAR * out,int size,const TCHAR * path)673 bool get_plugin_path (TCHAR *out, int size, const TCHAR *path) {
674     // static char* plugin_path_none = NULL;
675 
676     if (strcmp(path, "floppysounds") == 0) {
677         if (g_floppy_sounds_dir) {
678             strncpy(out, g_floppy_sounds_dir, size);
679         }
680         else {
681             strncpy(out, "floppy_sounds", size);
682         }
683         // make sure out is null-terminated in any case
684         out[size - 1] = '\0';
685     }
686     else {
687         write_log("\n-----------------> STUB: get_plugin_path, "
688                 "size: %d, path: %s\n", size, path);
689         out[0] = '\0';
690     }
691     return TRUE;
692 }
693 
694