OSDN Git Service

[VM][FMTOWNS][MEMORY] Fix setup around memory banks by I/O 0404h and 0480h.
[csp-qt/common_source_project-fm7.git] / source / src / qt / common / qt_utils.cpp
1 /*
2         Skelton for retropc emulator
3         Author : Takeda.Toshiya
4         Port to Qt : K.Ohta <whatisthis.sowhat _at_ gmail.com>
5         Date   : 2006.08.18 -
6
7         [ win32 main ] -> [ agar main ]
8 */
9
10 #include <stdio.h>
11 #include <string>
12 #include <vector>
13 #include <memory>
14
15 #include <QApplication>
16 #include <QString>
17 #include <QTextCodec>
18 #include <QImage>
19 #include <QImageReader>
20 #include <QDateTime>
21 #include <QDir>
22 #include <QMap>
23 #include <QTranslator>
24 #include <QProcessEnvironment>
25 #include <QCommandLineParser>
26
27 #include "common.h"
28 #include "fileio.h"
29 #include "config.h"
30 #include "emu.h"
31 #include "../osd.h"
32
33 #include "menuclasses.h"
34 #include "mainwidget.h"
35 #include "commonclasses.h"
36 #include "qt_main.h"
37 #include "emu_thread.h"
38 #include "joy_thread.h"
39 #include "draw_thread.h"
40
41 #include "qt_gldraw.h"
42 #include "../gui/gl2/qt_glutil_gl2_0.h"
43 #include "csp_logger.h"
44
45 #include "dock_disks.h"
46
47 #include "menu_binary.h"
48 #include "menu_bubble.h"
49 #include "menu_cart.h"
50 #include "menu_cmt.h"
51 #include "menu_compactdisc.h"
52 #include "menu_disk.h"
53 #include "menu_harddisk.h"
54 #include "menu_laserdisc.h"
55 #include "menu_quickdisk.h"
56
57
58 #include "menu_flags_ext.h"
59 #include "dialog_movie.h"
60 #include "../avio/movie_saver.h"
61 // emulation core
62 #include "../../vm/vm_limits.h"
63 #include "../../vm/fmgen/fmgen.h"
64
65 //QApplication *GuiMain = NULL;
66 extern config_t config;
67
68 // Start to define MainWindow.
69 class META_MainWindow *rMainWindow;
70
71
72 // buttons
73
74 // menu
75 extern DLL_PREFIX_I std::string cpp_homedir;
76 extern DLL_PREFIX_I std::string cpp_confdir;
77 extern DLL_PREFIX_I std::string my_procname;
78 extern DLL_PREFIX_I std::string sRssDir;
79
80 void Ui_MainWindow::do_set_mouse_enable(bool flag)
81 {
82 #ifdef USE_MOUSE
83         if(hRunEmu == nullptr) return;
84         EMU_TEMPLATE *p_emu = hRunEmu->get_emu();
85         if(p_emu == nullptr) return;
86
87         p_emu->lock_vm();
88         if(flag) {
89                 graphicsView->grabMouse();
90                 p_emu->enable_mouse();
91         } else {
92                 graphicsView->releaseMouse();
93                 p_emu->disable_mouse();
94         }
95         p_emu->unlock_vm();
96 #endif
97 }
98
99 void Ui_MainWindow::do_toggle_mouse(void)
100 {
101 #ifdef USE_MOUSE
102         if(hRunEmu == nullptr) return;
103         EMU_TEMPLATE *p_emu = hRunEmu->get_emu();
104         if(p_emu == nullptr) return;
105         if(graphicsView == nullptr) return;
106
107         p_emu->lock_vm();
108         bool flag = p_emu->is_mouse_enabled();
109         if(!flag) {
110                 graphicsView->grabMouse();
111                 p_emu->enable_mouse();
112         } else {
113                 graphicsView->releaseMouse();
114                 p_emu->disable_mouse();
115         }
116         p_emu->unlock_vm();
117 #endif
118 }
119
120 void Ui_MainWindow::rise_movie_dialog(void)
121 {
122         CSP_DialogMovie *dlg = new CSP_DialogMovie(hSaveMovieThread, using_flags);
123         dlg->setWindowTitle(QApplication::translate("CSP_DialogMovie", "Configure movie encodings", 0));
124         dlg->show();
125 }
126
127 void Ui_MainWindow::LaunchEmuThread(EmuThreadClassBase *m)
128 {
129         QString objNameStr;
130         GLDrawClass *glv = this->getGraphicsView();
131
132         int drvs;
133
134         hRunEmu = m;
135         if(hRunEmu == nullptr) return;
136         EMU_TEMPLATE* p_emu = hRunEmu->get_emu();
137         if(p_emu == nullptr) return;
138
139         OSD_BASE* p_osd = p_emu->get_osd();
140         if(p_osd == nullptr) return;
141
142         connect(hRunEmu, SIGNAL(message_changed(QString)), this, SLOT(message_status_bar(QString)), Qt::QueuedConnection);
143         connect(hRunEmu, SIGNAL(sig_is_enable_mouse(bool)), this, SLOT(do_set_mouse_enable(bool)));
144         connect(glv, SIGNAL(sig_key_down(uint32_t, uint32_t, bool)), hRunEmu, SLOT(do_key_down(uint32_t, uint32_t, bool)));
145         connect(glv, SIGNAL(sig_key_up(uint32_t, uint32_t)),hRunEmu, SLOT(do_key_up(uint32_t, uint32_t)));
146         connect(this, SIGNAL(sig_quit_widgets()), glv, SLOT(do_stop_run_vm()));
147
148         if(action_ResetFixedCpu != nullptr) {
149                 connect(action_ResetFixedCpu, SIGNAL(triggered()),
150                                 hRunEmu, SLOT(do_set_emu_thread_to_fixed_cpu_from_action()));
151
152         }
153         for(int i = 0 ; i < 128 ; i++) {
154                 if(action_SetFixedCpu[i] == nullptr) break;
155                 connect(action_SetFixedCpu[i], SIGNAL(triggered()),
156                                 hRunEmu, SLOT(do_set_emu_thread_to_fixed_cpu_from_action()));
157         }
158         connect(this, SIGNAL(sig_vm_reset()), hRunEmu, SLOT(do_reset()));
159
160         for(int i = 0 ; i < using_flags->get_use_special_reset_num() ; i++) {
161                 if(actionSpecial_Reset[i] != nullptr) {
162                         connect(actionSpecial_Reset[i], SIGNAL(triggered()), hRunEmu, SLOT(do_special_reset()));
163                 }
164                 if(i >= 15) break;
165         }
166         connect(this, SIGNAL(sig_emu_update_config()), hRunEmu, SLOT(do_update_config()));
167         connect(this, SIGNAL(sig_emu_update_volume_level(int, int)), hRunEmu, SLOT(do_update_volume_level(int, int)));
168         connect(this, SIGNAL(sig_emu_update_volume_balance(int, int)), hRunEmu, SLOT(do_update_volume_balance(int, int)));
169         connect(this, SIGNAL(sig_emu_start_rec_sound()), hRunEmu, SLOT(do_start_record_sound()));
170         connect(this, SIGNAL(sig_emu_stop_rec_sound()), hRunEmu, SLOT(do_stop_record_sound()));
171         connect(this, SIGNAL(sig_emu_set_display_size(int, int, int, int)), hRunEmu, SLOT(do_set_display_size(int, int, int, int)));
172         connect(this, SIGNAL(sig_emu_thread_to_fixed_cpu(int)), hRunEmu, SLOT(do_set_emu_thread_to_fixed_cpu(int)));
173
174         if(using_flags->is_use_state()) {
175                 for(int i = 0; i < 10; i++) {
176                         connect(actionLoad_State[i], SIGNAL(triggered()), hRunEmu, SLOT(do_load_state())); // OK?
177                         connect(actionSave_State[i], SIGNAL(triggered()), hRunEmu, SLOT(do_save_state())); // OK?
178                 }
179         }
180 #if defined(USE_FLOPPY_DISK)
181 //      connect(this, SIGNAL(sig_write_protect_floppy_disk(int, bool)),
182 //                      hRunEmu, SLOT(do_write_protect_floppy_disk(int, bool)),
183 //                      Qt::QueuedConnection);
184         connect(this, SIGNAL(sig_open_floppy_disk(int, QString, int)),
185                         hRunEmu, SLOT(do_open_floppy_disk(int, QString, int)),
186                         Qt::QueuedConnection);
187         connect(this, SIGNAL(sig_close_floppy_disk_ui(int)),
188                         hRunEmu, SLOT(do_close_floppy_disk_ui(int)),
189                 Qt::QueuedConnection);
190         //connect(hRunEmu, SIGNAL(sig_change_osd_fd(int, QString)), this, SLOT(do_change_osd_fd(int, QString)));
191
192         // ToDo: eject from EMU_THREAD:: .
193         connect(p_osd, SIGNAL(sig_ui_floppy_insert_history(int, QString, quint64)),
194                                          this, SLOT(do_ui_floppy_insert_history(int, QString, quint64)),
195                                          Qt::QueuedConnection);
196         connect(p_osd, SIGNAL(sig_ui_floppy_write_protect(int, quint64)),
197                         this, SLOT(do_ui_write_protect_floppy_disk(int, quint64)),
198                         Qt::QueuedConnection);
199         connect(p_osd, SIGNAL(sig_ui_floppy_close(int)),
200                         this, SLOT(do_ui_eject_floppy_disk(int)),
201                         Qt::QueuedConnection);
202
203         drvs = USE_FLOPPY_DISK;
204         for(int ii = 0; ii < drvs; ii++) {
205                 if(menu_fds[ii] != nullptr) {
206                         menu_fds[ii]->connect_via_emu_thread(hRunEmu);
207                         connect(menu_fds[ii], SIGNAL(sig_set_inner_slot(int, int)),
208                                         hRunEmu, SLOT(do_select_floppy_disk_d88(int, int)),
209                                         Qt::QueuedConnection);
210                 }
211         }
212 #endif
213 #if defined(USE_HARD_DISK)
214         for(int ii = 0; ii < USE_HARD_DISK; ii++) {
215                 if(ii >= USE_HARD_DISK_TMP) break;
216                 Menu_HDDClass *mp = menu_hdds[ii];
217                 if(mp != nullptr) {
218                         mp->connect_via_emu_thread(hRunEmu);
219                 }
220         }
221         connect(this, SIGNAL(sig_open_hard_disk(int, QString)),
222                         hRunEmu, SLOT(do_open_hard_disk(int, QString)),
223                         Qt::QueuedConnection);
224 //      connect(this, SIGNAL(sig_close_hard_disk_ui(int)),
225 //                      hRunEmu, SLOT(do_close_hard_disk_ui(int)),
226 //                      Qt::QueuedConnection);
227
228         connect(p_osd, SIGNAL(sig_ui_hard_disk_insert_history(int, QString)),
229                                          this, SLOT(do_ui_hard_disk_insert_history(int, QString)),
230                                          Qt::QueuedConnection);
231         connect(p_osd, SIGNAL(sig_ui_hard_disk_close(int)),
232                         this, SLOT(do_ui_eject_hard_disk(int)),
233                         Qt::QueuedConnection);
234
235 #endif
236 #if defined(USE_TAPE)
237         for(int ii = 0; ii < USE_TAPE; ii++) {
238                 if(ii >= USE_TAPE_TMP) break;
239                 Menu_CMTClass *mp = menu_CMT[ii];
240                 if(mp != nullptr) {
241                         mp->connect_via_emu_thread(hRunEmu);
242                 }
243         }
244         connect(this, SIGNAL(sig_play_tape(int, QString)), hRunEmu, SLOT(do_play_tape(int, QString)));
245         connect(this, SIGNAL(sig_rec_tape(int, QString)),  hRunEmu, SLOT(do_rec_tape(int, QString)));
246
247         connect(p_osd, SIGNAL(sig_ui_tape_play_insert_history(int, QString)),
248                                          this, SLOT(do_ui_tape_play_insert_history(int, QString)),
249                                          Qt::QueuedConnection);
250         connect(p_osd, SIGNAL(sig_ui_tape_record_insert_history(int, QString)),
251                                          this, SLOT(do_ui_tape_record_insert_history(int, QString)),
252                                          Qt::QueuedConnection);
253         connect(p_osd, SIGNAL(sig_ui_tape_write_protect(int, quint64)),
254                         this, SLOT(do_ui_write_protect_tape(int, quint64)),
255                         Qt::QueuedConnection);
256         connect(p_osd, SIGNAL(sig_ui_tape_eject(int)),
257                         this, SLOT(do_ui_eject_tape(int)),
258                         Qt::QueuedConnection);
259 #endif
260 #if defined(USE_QUICK_DISK)
261         for(int ii = 0; ii < USE_QUICK_DISK; ii++) {
262                 if(ii >= USE_QUICK_DISK) break;
263                 Menu_QDClass *mp = menu_QDs[ii];
264                 if(mp != nullptr) {
265                         mp->connect_via_emu_thread(hRunEmu);
266                 }
267         }
268
269         connect(this, SIGNAL(sig_write_protect_quick_disk(int, bool)),
270                         hRunEmu, SLOT(do_write_protect_quick_disk(int, bool)),
271                         Qt::QueuedConnection);
272         connect(this, SIGNAL(sig_open_quick_disk(int, QString)),
273                         hRunEmu, SLOT(do_open_quick_disk(int, QString)),
274                         Qt::QueuedConnection);
275         connect(this, SIGNAL(sig_close_quick_disk_ui(int)),
276                         hRunEmu, SLOT(do_close_quick_disk_ui(int)),
277                 Qt::QueuedConnection);
278
279         connect(p_osd, SIGNAL(sig_ui_quick_disk_write_protect(int, quint64)),
280                         this, SLOT(do_ui_quick_disk_write_protect(int, quint64)),
281                         Qt::QueuedConnection);
282         connect(p_osd, SIGNAL(sig_ui_quick_disk_insert_history(int, QString)),
283                                          this, SLOT(do_ui_quick_disk_insert_history(int, QString)),
284                                          Qt::QueuedConnection);
285         connect(p_osd, SIGNAL(sig_ui_quick_disk_close(int)),
286                         this, SLOT(do_ui_eject_quick_disk(int)),
287                         Qt::QueuedConnection);
288
289 #endif
290 #if defined(USE_CART)
291         for(int ii = 0; ii < USE_CART; ii++) {
292                 if(ii >= USE_CART_TMP) break;
293                 Menu_CartClass *mp = menu_Cart[ii];
294                 if(mp != nullptr) {
295                         mp->connect_via_emu_thread(hRunEmu);
296                 }
297         }
298         connect(this, SIGNAL(sig_open_cartridge(int, QString)), hRunEmu, SLOT(do_open_cartridge(int, QString)));
299         connect(this, SIGNAL(sig_eject_cartridge_ui(int)), hRunEmu, SLOT(do_close_cartridge_ui(int)));
300
301         connect(p_osd, SIGNAL(sig_ui_cartridge_insert_history(int, QString)),
302                                          this, SLOT(do_ui_cartridge_insert_history(int, QString)),
303                                          Qt::QueuedConnection);
304         connect(p_osd, SIGNAL(sig_ui_cartridge_eject(int)),
305                         this, SLOT(do_ui_eject_cartridge(int)),
306                         Qt::QueuedConnection);
307 #endif
308 #if defined(USE_COMPACT_DISC)
309         for(int ii = 0; ii < USE_COMPACT_DISC; ii++) {
310                 if(ii >= USE_COMPACT_DISC_TMP) break;
311                 Menu_CompactDiscClass *mp = menu_CDROM[ii];
312                 if(mp != nullptr) {
313                         mp->connect_via_emu_thread(hRunEmu);
314                 }
315         }
316         connect(this, SIGNAL(sig_open_compact_disc(int, QString)),
317                         hRunEmu, SLOT(do_open_compact_disc(int, QString)),
318                         Qt::QueuedConnection);
319         connect(this, SIGNAL(sig_eject_compact_disc_ui(int)),
320                         hRunEmu, SLOT(do_eject_compact_disc_ui(int)),
321                         Qt::QueuedConnection);
322
323         connect(p_osd, SIGNAL(sig_ui_compact_disc_insert_history(int, QString)),
324                                          this, SLOT(do_ui_compact_disc_insert_history(int, QString)),
325                                          Qt::QueuedConnection);
326         connect(p_osd, SIGNAL(sig_ui_compact_disc_eject(int)),
327                         this, SLOT(do_ui_eject_compact_disc(int)),
328                         Qt::QueuedConnection);
329 #endif
330 #if defined(USE_LASER_DISC)
331         for(int ii = 0; ii < USE_LASER_DISC; ii++) {
332                 if(ii >= USE_LASER_DISC_TMP) break;
333                 Menu_LaserdiscClass *mp = menu_Laserdisc[ii];
334                 if(mp != nullptr) {
335                         mp->connect_via_emu_thread(hRunEmu);
336                 }
337         }
338         connect(this, SIGNAL(sig_open_laser_disc(int, QString)),
339                         hRunEmu, SLOT(do_open_laser_disc(int, QString)),
340                         Qt::QueuedConnection);
341         connect(this, SIGNAL(sig_close_laser_disc_ui(int)),
342                         hRunEmu, SLOT(do_close_laser_disc_ui(int)),
343                         Qt::QueuedConnection);
344
345         connect(p_osd, SIGNAL(sig_ui_laser_disc_insert_history(int, QString)),
346                                          this, SLOT(do_ui_laser_disc_insert_history(int, QString)),
347                                          Qt::QueuedConnection);
348         connect(p_osd, SIGNAL(sig_ui_laser_disc_eject(int)),
349                         this, SLOT(do_ui_eject_laser_disc(int)),
350                         Qt::QueuedConnection);
351
352         // ToDo: multiple LDs
353 #endif
354 #if defined(USE_BINARY_FILE)
355         connect(this, SIGNAL(sig_load_binary(int, QString)), hRunEmu, SLOT(do_load_binary(int, QString)));
356         connect(this, SIGNAL(sig_save_binary(int, QString)), hRunEmu, SLOT(do_save_binary(int, QString)));
357 #endif
358 #if defined(USE_BUBBLE)
359         for(int ii = 0; ii < USE_BUBBLE; ii++) {
360                 if(ii >= USE_BUBBLE_TMP) break;
361                 Menu_BubbleClass *mp = menu_bubbles[ii];
362                 if(mp != nullptr) {
363                         mp->connect_via_emu_thread(hRunEmu);
364                         connect(mp, SIGNAL(sig_set_inner_slot(int, int)),
365                                         hRunEmu, SLOT(do_select_bubble_casette_b77(int, int)),
366                                         Qt::QueuedConnection);
367                 }
368         }
369         connect(this, SIGNAL(sig_open_bubble(int, QString, int)),
370                         hRunEmu, SLOT(do_open_bubble_casette(int, QString, int)),
371                         Qt::QueuedConnection);
372         connect(this, SIGNAL(sig_close_bubble_ui(int)),
373                         hRunEmu, SLOT(do_close_bubble_casette_ui(int)),
374                         Qt::QueuedConnection);
375
376         connect(p_osd, SIGNAL(sig_ui_bubble_insert_history(int, QString, quint64)),
377                         this, SLOT(do_ui_bubble_insert_history(int, QString, quint64)),
378                                          Qt::QueuedConnection);
379         connect(p_osd, SIGNAL(sig_ui_bubble_write_protect(int, quint64)),
380                         this, SLOT(do_ui_bubble_write_protect(int, quint64)),
381                                          Qt::QueuedConnection);
382         connect(p_osd, SIGNAL(sig_ui_bubble_closed(int)),
383                         this, SLOT(do_ui_eject_bubble_casette(int)),
384                         Qt::QueuedConnection);
385
386 #endif
387
388         hRunEmu->set_tape_play(false);
389 #if defined(USE_KEY_LOCKED) || defined(USE_LED_DEVICE)
390         connect(hRunEmu, SIGNAL(sig_send_data_led(quint32)), this, SLOT(do_recv_data_led(quint32)), Qt::QueuedConnection);
391 #endif
392 #ifdef USE_AUTO_KEY
393         connect(this, SIGNAL(sig_start_auto_key(QString)), hRunEmu, SLOT(do_start_auto_key(QString)), Qt::QueuedConnection);
394         connect(this, SIGNAL(sig_stop_auto_key()), hRunEmu, SLOT(do_stop_auto_key()), Qt::QueuedConnection);
395         connect(this, SIGNAL(sig_set_roma_kana(bool)), hRunEmu, SLOT(do_set_roma_kana(bool)), Qt::QueuedConnection);
396 #endif
397
398         csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "EmuThread : Start.");
399         objNameStr = QString("EmuThreadClass");
400         hRunEmu->setObjectName(objNameStr);
401
402         hDrawEmu = new DrawThreadClass((OSD*)p_osd, csp_logger, this);
403         p_emu->set_parent_handler((EmuThreadClass*)hRunEmu, hDrawEmu);
404
405 #ifdef ONE_BOARD_MICRO_COMPUTER
406         QImageReader *reader = new QImageReader(":/background.png");
407         QImage *result = new QImage(reader->read()); // this acts as a default if the size is not matched
408         QImage result2 = result->convertToFormat(QImage::Format_ARGB32);
409         glv->updateBitmap(&result2);
410         p_osd->upload_bitmap(&result2);
411         delete result;
412         delete reader;
413         p_osd->set_buttons();
414 #endif
415
416         csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "DrawThread : Start.");
417
418         //connect(hDrawEmu, SIGNAL(sig_draw_frames(int)), hRunEmu, SLOT(do_print_framerate(int)), Qt::DirectConnection);
419         connect((OSD*)p_osd, SIGNAL(sig_draw_frames(int)), hRunEmu, SLOT(do_print_framerate(int)));
420         connect(hDrawEmu, SIGNAL(message_changed(QString)), this, SLOT(message_status_bar(QString)));
421         connect(this, SIGNAL(quit_draw_thread()), hDrawEmu, SLOT(doExit()));
422         connect(hDrawEmu, SIGNAL(finished()), hDrawEmu, SLOT(deleteLater()));
423
424         connect(hRunEmu, SIGNAL(window_title_changed(QString)), this, SLOT(do_set_window_title(QString)), Qt::QueuedConnection);
425         connect(this, SIGNAL(sig_quit_emu_thread()), hRunEmu, SLOT(doExit()), Qt::QueuedConnection);
426         connect(hRunEmu, SIGNAL(sig_mouse_enable(bool)),
427                         this, SLOT(do_set_mouse_enable(bool)), Qt::QueuedConnection);
428         /*if(config.use_separate_thread_draw) {
429                 connect(hRunEmu, SIGNAL(sig_draw_thread(bool)), hDrawEmu, SLOT(doDraw(bool)));
430                 connect(hRunEmu, SIGNAL(sig_set_draw_fps(double)), hDrawEmu, SLOT(do_set_frames_per_second(double)));
431                 connect(hRunEmu, SIGNAL(sig_draw_one_turn(bool)), hDrawEmu, SLOT(do_draw_one_turn(bool)));
432                 } else*/ {
433                 connect(hRunEmu, SIGNAL(sig_draw_thread(bool)), hDrawEmu, SLOT(doDraw(bool)));
434                 connect(hRunEmu, SIGNAL(sig_set_draw_fps(double)), hDrawEmu, SLOT(do_set_frames_per_second(double)));
435                 connect(hRunEmu, SIGNAL(sig_draw_one_turn(bool)), hDrawEmu, SLOT(do_draw_one_turn(bool)));
436         }
437         //connect(hRunEmu, SIGNAL(sig_draw_thread(bool)), (OSD*)p_osd, SLOT(do_draw(bool)));
438         connect(hRunEmu, SIGNAL(quit_draw_thread()), hDrawEmu, SLOT(doExit()));
439
440         connect(glv, SIGNAL(sig_notify_move_mouse(double, double, double, double)),
441                         hRunEmu, SLOT(do_move_mouse(double, double, double, double)), Qt::QueuedConnection);
442         connect(glv, SIGNAL(do_notify_button_pressed(Qt::MouseButton)),
443                 hRunEmu, SLOT(do_press_button_mouse(Qt::MouseButton)));
444         connect(glv, SIGNAL(do_notify_button_released(Qt::MouseButton)),
445                         hRunEmu, SLOT(do_release_button_mouse(Qt::MouseButton)));
446
447         connect(actionCapture_Screen, SIGNAL(triggered()), glv, SLOT(do_save_frame_screen()));
448         connect(this, SIGNAL(sig_emu_launched()), glv, SLOT(set_emu_launched()));
449
450 #ifdef USE_MOUSE
451         connect(glv, SIGNAL(sig_toggle_mouse(void)),
452                         this, SLOT(do_toggle_mouse(void)),  Qt::QueuedConnection);
453         connect(glv, SIGNAL(sig_toggle_grab_mouse()), this, SLOT(do_toggle_mouse()),  Qt::QueuedConnection);
454 #endif
455         connect(hRunEmu, SIGNAL(sig_resize_screen(int, int)),
456                         glv, SLOT(resizeGL(int, int)), Qt::QueuedConnection);
457         connect(hRunEmu, SIGNAL(sig_resize_osd(int)), driveData, SLOT(setScreenWidth(int)), Qt::QueuedConnection);
458         connect(hRunEmu, SIGNAL(sig_change_osd(int, int, QString)), driveData, SLOT(updateMessage(int, int, QString)), Qt::QueuedConnection);
459
460         connect(glv, SIGNAL(sig_resize_uibar(int, int)),
461                         this, SLOT(resize_statusbar(int, int)), Qt::QueuedConnection);
462         connect(hRunEmu, SIGNAL(sig_resize_uibar(int, int)),
463                         this, SLOT(resize_statusbar(int, int)), Qt::QueuedConnection);
464
465         connect((OSD*)p_osd, SIGNAL(sig_req_encueue_video(int, int, int)),
466                         hDrawEmu, SLOT(do_req_encueue_video(int, int, int)));
467
468         objNameStr = QString("EmuDrawThread");
469         hDrawEmu->setObjectName(objNameStr);
470
471         csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "DrawThread : Launch done.");
472
473         hSaveMovieThread = new MOVIE_SAVER(640, 400,  30, (OSD*)p_osd, &config);
474
475         // SAVING MOVIES
476 //      connect(this, SIGNAL(sig_start_saving_movie()), hRunEmu, SLOT(do_start_record_video()));
477         connect(actionStart_Record_Movie, SIGNAL(triggered()), hRunEmu, SLOT(do_start_record_video()));
478         connect(actionStop_Record_Movie, SIGNAL(triggered()), hRunEmu, SLOT(do_stop_record_video()));
479
480         connect(hSaveMovieThread, SIGNAL(sig_set_state_saving_movie(bool)), this, SLOT(do_set_state_saving_movie(bool)));
481
482         connect((OSD*)p_osd, SIGNAL(sig_save_as_movie(QString, int, int)),
483                         hSaveMovieThread, SLOT(do_open(QString, int, int)));
484         connect((OSD*)p_osd, SIGNAL(sig_stop_saving_movie()), hSaveMovieThread, SLOT(do_close()));
485
486         actionStop_Record_Movie->setIcon(QIcon(":/icon_process_stop.png"));
487         actionStop_Record_Movie->setVisible(false);
488
489         connect(this, SIGNAL(sig_movie_set_width(int)), hSaveMovieThread, SLOT(do_set_width(int)));
490         connect(this, SIGNAL(sig_movie_set_height(int)), hSaveMovieThread, SLOT(do_set_height(int)));
491
492         connect((OSD*)p_osd, SIGNAL(sig_movie_set_width(int)), hSaveMovieThread, SLOT(do_set_width(int)));
493         connect((OSD*)p_osd, SIGNAL(sig_movie_set_height(int)), hSaveMovieThread, SLOT(do_set_height(int)));
494
495         connect((OSD*)p_osd, SIGNAL(sig_enqueue_audio(int16_t*, int)), hSaveMovieThread, SLOT(enqueue_audio(int16_t *, int)));
496         connect((OSD*)p_osd, SIGNAL(sig_enqueue_video(int, int, int, QImage *)),
497                         hSaveMovieThread, SLOT(enqueue_video(int, int, int, QImage *)), Qt::DirectConnection);
498         connect(glv->extfunc, SIGNAL(sig_push_image_to_movie(int, int, int, QImage *)),
499                         hSaveMovieThread, SLOT(enqueue_video(int, int, int, QImage *)));
500         connect(this, SIGNAL(sig_quit_movie_thread()), hSaveMovieThread, SLOT(do_exit()));
501
502         objNameStr = QString("EmuMovieThread");
503         hSaveMovieThread->setObjectName(objNameStr);
504         hSaveMovieThread->start();
505         csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "MovieThread : Launch done.");
506
507         connect(action_SetupMovie, SIGNAL(triggered()), this, SLOT(rise_movie_dialog()));
508         connect(hRunEmu, SIGNAL(sig_change_access_lamp(int, int, QString)), driveData, SLOT(updateLabel(int, int, QString)), Qt::QueuedConnection);
509         connect(hRunEmu, SIGNAL(sig_set_access_lamp(int, bool)), graphicsView, SLOT(do_display_osd_leds(int, bool)), Qt::QueuedConnection);
510         connect(hRunEmu, SIGNAL(sig_change_virtual_media(int, int, QString)), driveData, SLOT(updateMediaFileName(int, int, QString)), Qt::QueuedConnection);
511         connect((OSD*)p_osd, SIGNAL(sig_change_virtual_media(int, int, QString)), driveData, SLOT(updateMediaFileName(int, int, QString)));
512         connect((OSD*)p_osd, SIGNAL(sig_enable_mouse()), glv, SLOT(do_enable_mouse()));
513         connect((OSD*)p_osd, SIGNAL(sig_disable_mouse()), glv, SLOT(do_disable_mouse()));
514
515         connect(this, SIGNAL(sig_unblock_task()), hRunEmu, SLOT(do_unblock()));
516         connect(this, SIGNAL(sig_block_task()), hRunEmu, SLOT(do_block()));
517         connect(this, SIGNAL(sig_start_emu_thread()), hRunEmu, SLOT(do_start_emu_thread()));
518         connect(this, SIGNAL(sig_start_draw_thread()), hDrawEmu, SLOT(do_start_draw_thread()));
519
520
521 //      hRunEmu->start(QThread::HighestPriority);
522         this->set_screen_aspect(config.window_stretch_type);
523         emit sig_movie_set_width(SCREEN_WIDTH);
524         emit sig_movie_set_height(SCREEN_HEIGHT);
525 //      hRunEmu->start(QThread::HighestPriority);
526         csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "EmuThread : Launch done.");
527 }
528
529 void Ui_MainWindow::do_create_d88_media(int drv, quint8 media_type, QString name)
530 {
531         if(hRunEmu == nullptr) return;
532         EMU_TEMPLATE *p_emu = hRunEmu->get_emu();
533         if(p_emu == nullptr) return;
534
535         if(!(name.isEmpty()) && (drv >= 0)) {
536 #if defined(USE_FLOPPY_DISK)
537                 if(drv < USE_FLOPPY_DISK) {
538                         const _TCHAR* path = (const _TCHAR *)(name.toLocal8Bit().data());
539                         if(p_emu->create_blank_floppy_disk(path, media_type)) {
540                                 emit sig_open_floppy_disk(drv, name, 0);
541                         }
542                 }
543 #endif
544         }
545 }
546
547 void Ui_MainWindow::do_create_hard_disk(int drv, int sector_size, int sectors, int surfaces, int cylinders, QString name)
548 {
549         if(hRunEmu == nullptr) return;
550         EMU_TEMPLATE *p_emu = hRunEmu->get_emu();
551         if(p_emu == nullptr) return;
552
553         if(!(name.isEmpty()) && (drv >= 0)) {
554 #if defined(USE_HARD_DISK)
555                 if(drv < USE_HARD_DISK) {
556                         const _TCHAR* path = (const _TCHAR *)(name.toLocal8Bit().data());
557                         if(p_emu->create_blank_hard_disk(path, sector_size, sectors, surfaces, cylinders)) {
558                                 emit sig_open_hard_disk(drv, name);
559                         }
560                 }
561 #endif
562         }
563 }
564
565 void Ui_MainWindow::LaunchJoyThread(void)
566 {
567 #if defined(USE_JOYSTICK)
568         if(hRunEmu == nullptr) return;
569         EMU_TEMPLATE *p_emu = hRunEmu->get_emu();
570         if(p_emu == nullptr) return;
571
572         hRunJoy = new JoyThreadClass(p_emu, using_flags, &config);
573         connect(this, SIGNAL(quit_joy_thread()), hRunJoy, SLOT(doExit()));
574         connect(hRunJoy, SIGNAL(finished()), hRunJoy, SLOT(deleteLater()));
575
576         hRunJoy->setObjectName("JoyThread");
577         hRunJoy->start();
578 #endif
579 }
580
581 void Ui_MainWindow::StopJoyThread(void)
582 {
583 #if defined(USE_JOYSTICK)
584         emit quit_joy_thread();
585 #endif
586 }
587
588 void Ui_MainWindow::delete_joy_thread(void)
589 {
590         //    delete hRunJoyThread;
591         //  delete hRunJoy;
592 }
593
594 void Ui_MainWindow::on_actionExit_triggered()
595 {
596         OnMainWindowClosed();
597 }
598
599 void Ui_MainWindow::OnWindowRedraw(void)
600 {
601         if(hRunEmu == nullptr) return;
602         EMU_TEMPLATE *p_emu = hRunEmu->get_emu();
603         if(p_emu == nullptr) return;
604         if(p_emu) {
605                 //emu->update_screen();
606         }
607 }
608
609 void Ui_MainWindow::OnWindowMove(void)
610 {
611         if(hRunEmu == nullptr) return;
612         EMU_TEMPLATE *p_emu = hRunEmu->get_emu();
613         if(p_emu == nullptr) return;
614
615         if(p_emu) {
616                 p_emu->suspend();
617         }
618 }
619
620
621
622 #include <string>
623
624 void Ui_MainWindow::OnMainWindowClosed(void)
625 {
626         // notify power off
627         emit sig_notify_power_off();
628         if(statusUpdateTimer != NULL) statusUpdateTimer->stop();
629 #if defined(USE_KEY_LOCKED) || defined(USE_LED_DEVICE)
630         if(ledUpdateTimer != NULL) ledUpdateTimer->stop();
631 #endif
632         emit quit_draw_thread();
633         emit quit_joy_thread();
634         emit sig_quit_emu_thread();
635         emit sig_quit_movie_thread();
636         emit sig_quit_widgets();
637
638         if(hSaveMovieThread != nullptr) {
639                 // When recording movie, stopping will spend a lot of seconds.
640                 if(!(hSaveMovieThread->wait(60 * 1000))) { // 60 Sec
641                         hSaveMovieThread->terminate();
642                         QThread::msleep(1000);
643                 }
644                 delete hSaveMovieThread;
645                 hSaveMovieThread = NULL;
646         }
647
648 //      if(hDrawEmu != nullptr) {
649 //              if(!(hDrawEmu->wait(1000))) {
650 //                      hDrawEmu->terminate();
651 //              }
652 //              delete hDrawEmu;
653 //              hDrawEmu = nullptr;
654 //      }
655         if(hRunEmu != nullptr) {
656                 OnCloseDebugger();
657                 if(hRunEmu->get_emu() != nullptr) {
658                         OSD* op = (OSD*)(hRunEmu->get_emu()->get_osd());
659                         if(op != nullptr) {
660                                 op->setParent(this);
661                                 op->moveToThread(this->thread());
662                         }
663                 }
664                 hRunEmu->quit();
665                 if(!(hRunEmu->wait(2000))) {
666                         hRunEmu->terminate();
667                         QThread::msleep(100);
668                 }
669                 delete hRunEmu;
670                 hRunEmu = nullptr;
671 #if 0
672                 save_config(create_local_path(_T("%s.ini"), _T(CONFIG_NAME)));
673 #else
674                 {
675                         char tmps[128] = {0};
676                         std::string localstr;
677                         //snprintf(tmps, sizeof(tmps), _T("%s.ini"), _T(CONFIG_NAME));
678                         my_stprintf_s(tmps, sizeof(tmps) - 1, _T("%s.ini"), _T(CONFIG_NAME));
679                         localstr = tmps;
680                         localstr = cpp_confdir + localstr;
681                         save_config(localstr.c_str());
682                 }
683 #endif
684         }
685 #if defined(USE_JOYSTICK)
686 //      if(hRunJoy != nullptr) {
687 //              if(!(hRunJoy->wait(1000))) {
688 //                      hRunJoy->terminate();
689 //              }
690 //              delete hRunJoy;
691 //              hRunJoy = nullptr;
692 //      }
693 #endif
694 //      do_release_emu_resources();
695
696         return;
697 }
698
699
700
701 // Will remove.
702 void Ui_MainWindow::do_release_emu_resources(void)
703 {
704         emit sig_quit_emu_thread();
705 }
706
707 extern void DLL_PREFIX_I get_long_full_path_name(_TCHAR* src, _TCHAR* dst);
708 extern _TCHAR* DLL_PREFIX_I get_parent_dir(_TCHAR* file);
709 extern void get_short_filename(_TCHAR *dst, _TCHAR *file, int maxlen);
710
711 #if defined(Q_OS_CYGWIN)
712 #include <sys/stat.h>
713 #endif
714 static void my_util_mkdir(std::string n)
715 {
716 #if !defined(Q_OS_CYGWIN)
717                 QDir dir = QDir::current();
718                 dir.mkdir( QString::fromStdString(n));
719 #else
720                 struct stat st;
721                 if(stat(n.c_str(), &st) != 0) {
722                         _mkdir(n.c_str()); // Not found
723                 }
724 #endif
725 }
726
727 static void setup_logs(void)
728 {
729         std::string delim;
730         char    *p;
731
732         my_procname = "emu";
733         my_procname = my_procname + CONFIG_NAME;
734 #if defined(Q_OS_WIN)
735         delim = "\\";
736 #else
737         delim = "/";
738 #endif
739 #if !defined(Q_OS_WIN)
740         p = SDL_getenv("HOME");
741         if(p == NULL) {
742                 p = SDL_getenv("PWD");
743                 if(p == NULL) {
744                         cpp_homedir = ".";
745                 } else {
746                         cpp_homedir = p;
747                 }
748                 std::string tmpstr;
749                 tmpstr = "Warning : Can't get HOME directory...Making conf on " +  cpp_homedir + delim;
750                 perror(tmpstr.c_str());
751         } else {
752                 cpp_homedir = p;
753         }
754 #else
755         cpp_homedir = ".";
756 #endif
757         cpp_homedir = cpp_homedir + delim;
758
759 #if !defined(CSP_OS_WINDOWS)
760         cpp_confdir = cpp_homedir + ".config" + delim;
761         my_util_mkdir(cpp_confdir);
762 #else
763         cpp_confdir = cpp_homedir;
764 #endif
765
766         cpp_confdir = cpp_confdir + "CommonSourceCodeProject" + delim;
767         my_util_mkdir(cpp_confdir);
768
769         cpp_confdir = cpp_confdir + my_procname + delim;
770         my_util_mkdir(cpp_confdir);
771    //AG_MkPath(cpp_confdir.c_str());
772    /* Gettext */
773 #ifndef RSSDIR
774 #if defined(_USE_AGAR) || defined(_USE_QT)
775         sRssDir = "/usr/local/share/";
776 #else
777         sRssDir = "." + delim;
778 #endif
779         sRssDir = sRssDir + "CommonSourceCodeProject" + delim + my_procname;
780 #else
781         sRssDir = RSSDIR;
782 #endif
783 }
784
785 extern QProcessEnvironment _envvars;
786 extern bool _b_dump_envvar;
787 extern std::string config_fullpath;
788
789
790 extern DLL_PREFIX QList<QCommandLineOption> SetOptions_Sub(QCommandLineParser *parser);
791
792 QCommandLineOption SetOptionsList(unsigned int drive, QStringList src, const QString desc, const QString name, const QString defaultValue)
793 {
794         QStringList new_s;
795
796         QString _apd = QString::number(drive);
797         for(auto _n = src.begin(); _n != src.end(); ++_n) {
798                 new_s.append((*_n) + _apd);
799         }
800         QCommandLineOption dst(new_s, desc, name, defaultValue);
801         return dst;
802 }
803
804 QList<QCommandLineOption> SetOptions(QCommandLineParser *cmdparser, QStringList& aliases)
805 {
806         QString emudesc = QString::fromUtf8("Emulator for ");
807         emudesc = emudesc + QString::fromUtf8(DEVICE_NAME);
808     cmdparser->setApplicationDescription(emudesc);
809     cmdparser->addHelpOption();
810     //cmdparser->addVersionOption();
811
812
813         QList<QCommandLineOption> _ret;
814         QStringList _cl;
815         SetOptions_Sub(cmdparser);
816
817         //
818         const QString _alias_bin     = (const QString)(QString::fromUtf8("vBinary"));
819         const QString _alias_sbin    = (const QString)(QString::fromUtf8("vSaveBinary"));
820         const QString _alias_bubble  = (const QString)(QString::fromUtf8("vBubble"));
821         const QString _alias_cd      = (const QString)(QString::fromUtf8("vCompactDisc"));
822         const QString _alias_cart    = (const QString)(QString::fromUtf8("vCart"));
823         const QString _alias_fdd     = (const QString)(QString::fromUtf8("vFloppy"));
824         const QString _alias_hdd     = (const QString)(QString::fromUtf8("vHardDisk"));
825         const QString _alias_ld      = (const QString)(QString::fromUtf8("vLaserDisc"));
826         const QString _alias_qd      = (const QString)(QString::fromUtf8("vQuickDisk"));
827         const QString _alias_tape    = (const QString)(QString::fromUtf8("vTape"));
828         const QString _alias_stape   = (const QString)(QString::fromUtf8("vSaveCMT"));
829
830         const QStringList _bin_list = {"bin", "vBinary", "vBIN"};
831         const QStringList _save_bin_list = {"sbin", "vSaveBinary", "vSBIN"};
832         const QStringList _bubble_list = {"bub", "vBubble", "vBUB"};
833         const QStringList _cart_list = {"cart", "vCartridge", "vCart", "vCART"};
834         const QStringList _cd_list = {"cd", "vCompactDisc", "vCd", "vCD"};
835         const QStringList _fdd_list = {"fd", "vFd", "vFloppy", "vFloppyDisk", "vFloppyDrive", "vFD", "vFDD"};
836         const QStringList _hdd_list       = {"hd", "vHardDisk", "vHardDrive", "vHD", "vHDD"};
837         const QStringList _ld_list        = {"ld", "vLaserDisc", "vLd", "vLD"};
838         const QStringList _qd_list        = {"qd", "vQuickDisk", "vQd", "vQD"};
839         const QStringList _tape_list      = {"tape", "vTape", "vCasette", "vCMT"};
840         const QStringList _save_tape_list = {"scmt", "vSaveTape", "vSaveCMT", "vSCMT"};
841
842 #if defined(USE_BINARY_FILE)
843         for(unsigned int i = 0; i < USE_BINARY_FILE; i++) {
844                 QString _alias = _alias_bin;
845                 _alias.append(QString::fromUtf8("%1").arg(i));
846                 aliases.append(_alias);
847
848                 QCommandLineOption _l =
849                         SetOptionsList(i, _bin_list,
850                                                    QCoreApplication::translate("main", "Set virtual BINARY file for LOADING slot %1.").arg(i),
851                                                    QCoreApplication::translate("main", "PATH"), QString::fromUtf8(""));
852                 _ret.append(_l);
853         }
854
855         for(unsigned int i = 0; i < USE_BINARY_FILE; i++) {
856                 QString _alias_s = _alias_sbin;
857                 _alias_s.append(QString::fromUtf8("%1").arg(i));
858                 aliases.append(_alias_s);
859         #if 0
860                 QCommandLineOption _ls =
861                         SetOptionsList(i, _sbin_list,
862                                                    QCoreApplication::translate("main", "Set virtual BINARY file for SAVING slot %1.").arg(i),
863                                                    QCoreApplication::translate("main", "PATH"), QString::fromUtf8(""));
864                 _ret.append(_ls);
865         #endif
866         }
867 #endif
868 #if defined(USE_BUBBLE)
869         for(unsigned int i = 0; i < USE_BUBBLE; i++) {
870                 QString _alias = _alias_bubble;
871                 _alias.append(QString::fromUtf8("%1").arg(i));
872                 aliases.append(_alias);
873
874                 QCommandLineOption _l =
875                         SetOptionsList(i, _bubble_list,
876                                                    QCoreApplication::translate("main", "Set virtual BUBBLE CASETTE %1.").arg(i),
877                                                    QCoreApplication::translate("main", "[W@|WP@][SLOT@]PATH"), QString::fromUtf8(""));
878                 _ret.append(_l);
879         }
880 #endif
881 #if defined(USE_CART)
882         for(unsigned int i = 0; i < USE_CART; i++) {
883                 QString _alias = _alias_cart;
884                 _alias.append(QString::fromUtf8("%1").arg(i));
885                 aliases.append(_alias);
886
887                 QCommandLineOption _l =
888                         SetOptionsList(i, _cart_list,
889                                                    QCoreApplication::translate("main", "Set virtual ROM CARTRIDGE %1.").arg(i),
890                                                    QCoreApplication::translate("main", "PATH"), QString::fromUtf8(""));
891                 _ret.append(_l);
892         }
893 #endif
894 #if defined(USE_COMPACT_DISC)
895         for(unsigned int i = 0; i < USE_COMPACT_DISC; i++) {
896                 QString _alias = _alias_cd;
897                 _alias.append(QString::fromUtf8("%1").arg(i));
898                 aliases.append(_alias);
899
900                 QCommandLineOption _l =
901                         SetOptionsList(i, _cd_list,
902                                                    QCoreApplication::translate("main", "Set virtual COMPACT DISC %1 to FILE.").arg(i),
903                                                    QCoreApplication::translate("main", "PATH"), QString::fromUtf8(""));
904                 _ret.append(_l);
905         }
906 #endif
907 #if defined(USE_FLOPPY_DISK)
908         for(unsigned int i = 0; i < USE_FLOPPY_DISK; i++) {
909                 QString _alias = _alias_fdd;
910                 _alias.append(QString::fromUtf8("%1").arg(i));
911                 aliases.append(_alias);
912
913                 QCommandLineOption _l =
914                         SetOptionsList(i, _fdd_list,
915                                                    QCoreApplication::translate("main", "Set virtual FLOPPY DISK %1.").arg(i),
916                                                    QCoreApplication::translate("main", "[W@|WP@][SLOT@]PATH"), QString::fromUtf8(""));
917                 _ret.append(_l);
918         }
919 #endif
920 #if defined(USE_HARD_DISK)
921         for(unsigned int i = 0; i < USE_HARD_DISK; i++) {
922                 QString _alias = _alias_hdd;
923                 _alias.append(QString::fromUtf8("%1").arg(i));
924                 aliases.append(_alias);
925
926                 QCommandLineOption _l =
927                         SetOptionsList(i, _hdd_list,
928                                                    QCoreApplication::translate("main", "Set virtual HARD DISK DRIVE %1 .").arg(i),
929                                                    QCoreApplication::translate("main", "PATH"), QString::fromUtf8(""));
930                 _ret.append(_l);
931         }
932 #endif
933 #if defined(USE_LASER_DISC)
934         // ToDo: Fix working around LASER DISC correctly. 20230224 K.O.
935         for(unsigned int i = 0; i < USE_LASER_DISC; i++) {
936                 QString _alias = _alias_ld;
937                 _alias.append(QString::fromUtf8("%1").arg(i));
938                 aliases.append(_alias);
939
940                 QCommandLineOption _l =
941                         SetOptionsList(i, _ld_list,
942                                                    QCoreApplication::translate("main", "Set virtual LASER DISC %1.").arg(i),
943                                                    QCoreApplication::translate("main", "PATH"), QString::fromUtf8(""));
944                 _ret.append(_l);
945         }
946 #endif
947 #if defined(USE_QUICK_DISK)
948         for(unsigned int i = 0; i < USE_QUICK_DISK; i++) {
949                 QString _alias = _alias_qd;
950                 _alias.append(QString::fromUtf8("%1").arg(i));
951                 aliases.append(_alias);
952
953                 QCommandLineOption _l =
954                         SetOptionsList(i, _qd_list,
955                                                    QCoreApplication::translate("main", "Set virtual QUICK DISK %1"),
956                                                    QCoreApplication::translate("main", "[W@|WP@][SLOT@]PATH"), QString::fromUtf8(""));
957
958                 _ret.append(_l);
959         }
960 #endif
961 #if defined(USE_TAPE)
962         for(unsigned int i = 0; i < USE_TAPE; i++) {
963                 QString _alias = _alias_tape;
964                 _alias.append(QString::fromUtf8("%1").arg(i));
965                 aliases.append(_alias);
966
967                 QCommandLineOption _l =
968                         SetOptionsList(i, _tape_list,
969                                                    QCoreApplication::translate("main", "Set virtual CASETTE TAPE %1 for loading.").arg(i),
970                                                    QCoreApplication::translate("main", "PATH"), QString::fromUtf8(""));
971                 _ret.append(_l);
972         }
973         for(unsigned int i = 0; i < USE_TAPE; i++) {
974                 QString _alias = _alias_stape;
975                 _alias.append(QString::fromUtf8("%1").arg(i));
976                 aliases.append(_alias);
977
978                 QCommandLineOption _l =
979                         SetOptionsList(i, _save_tape_list,
980                                                    QCoreApplication::translate("main", "Set virtual CASETTE TAPE %1 for SAVING.").arg(i),
981                                                    QCoreApplication::translate("main", "[W@|WP@][SLOT@]PATH"), QString::fromUtf8(""));
982
983                 _ret.append(_l);
984         }
985 #endif
986         if(cmdparser != nullptr) {
987                 cmdparser->addOptions(_ret);
988         }
989         return _ret;
990 }
991
992
993 extern void ProcessCmdLine_Sub(QCommandLineParser *cmdparser);
994
995 void ProcessCmdLine(QCommandLineParser *cmdparser, const QStringList vmedialist, QMap<QString, QString>& dstlist)
996 {
997         char homedir[_MAX_PATH] = {0};
998         std::string delim;
999 #if defined(Q_OS_WIN)
1000         delim = "\\";
1001 #else
1002         delim = "/";
1003 #endif
1004         ProcessCmdLine_Sub(cmdparser);
1005         {
1006                 char tmps[128] = {0};
1007                 std::string localstr;
1008                 if(cmdparser->isSet("cfgfile")) {
1009                         strncpy(tmps, cmdparser->value("cfgfile").toLocal8Bit().constData(), 127);
1010                 }
1011                 if(strlen(tmps) <= 0){
1012                         my_stprintf_s(tmps, sizeof(tmps) - 1, _T("%s.ini"), _T(CONFIG_NAME));
1013                 }
1014                 localstr = tmps;
1015                 localstr = cpp_confdir + localstr;
1016                 load_config(localstr.c_str());
1017                 config_fullpath = localstr;
1018         }
1019         QString rendervalue = QString::fromUtf8("");
1020         const QStringList fixedGLList = {"gl2", "gl3", "gl4", "gl43", "gl46", "gles2", "gles3" };
1021         for(auto _gl = fixedGLList.begin(); _gl != fixedGLList.end(); ++_gl) {
1022                 if(cmdparser->isSet((*_gl))) {
1023                         rendervalue = (*_gl);
1024                         break;
1025                 }
1026         }
1027         const QStringList fixedGLList_v2  = { "gl2", "glv2", "v2", "2", "openglv2" };
1028         const QStringList fixedGLList_v3  = { "gl3", "glv3", "v3", "3", "openglv3", "opengl", "gl" };
1029         const QStringList fixedGLList_v4  = { "gl4", "glv4", "4", "openglv4"};
1030         const QStringList fixedGLList_v43 = { "gl43", "glv43", "openglv43" "gl4_3", "4.3", "4_3"};
1031         const QStringList fixedGLList_v46 = { "gl46", "glv46", "openglv46" "gl4_6", "4.6", "4_6"};
1032         const QStringList fixedGLList_es2 = { "gles2", "glesv2", "gles", "es2", "esv2", "es" };
1033         const QStringList fixedGLList_es3 = { "gles3", "glesv3", "esv3", "es3" };
1034         if(rendervalue.isEmpty()) {
1035                 QString tmps = cmdparser->value("render");
1036                 if(fixedGLList_v2.contains(tmps, Qt::CaseInsensitive)) {
1037                         rendervalue = QString::fromUtf8("gl2");
1038                 } else if(fixedGLList_v3.contains(tmps, Qt::CaseInsensitive)) {
1039                         rendervalue = QString::fromUtf8("gl3");
1040                 } else if(fixedGLList_v4.contains(tmps, Qt::CaseInsensitive)) {
1041                         rendervalue = QString::fromUtf8("gl4");
1042                 } else if(fixedGLList_v43.contains(tmps, Qt::CaseInsensitive)) {
1043                         rendervalue = QString::fromUtf8("gl43");
1044                 } else if(fixedGLList_v46.contains(tmps, Qt::CaseInsensitive)) {
1045                         rendervalue = QString::fromUtf8("gl46");
1046                 } else if(fixedGLList_es2.contains(tmps, Qt::CaseInsensitive)) {
1047                         rendervalue = QString::fromUtf8("gles2");
1048                 } else if(fixedGLList_es3.contains(tmps, Qt::CaseInsensitive)) {
1049                         rendervalue = QString::fromUtf8("gles3");
1050                 } else {
1051                         rendervalue = tmps.toLower();
1052                 }
1053         }
1054         typedef struct x_s {
1055                 int type;
1056                 int major;
1057                 int minor;
1058         } x_t;
1059         QMap <QString, x_t> _glmap;
1060         _glmap.insert(QString::fromUtf8("gl2"),  {CONFIG_RENDER_PLATFORM_OPENGL_MAIN, 2, 0});
1061         _glmap.insert(QString::fromUtf8("gl3"),  {CONFIG_RENDER_PLATFORM_OPENGL_MAIN, 3, 0});
1062         _glmap.insert(QString::fromUtf8("gl4"),  {CONFIG_RENDER_PLATFORM_OPENGL_CORE, 4, 3});
1063         _glmap.insert(QString::fromUtf8("gl43"), {CONFIG_RENDER_PLATFORM_OPENGL_CORE, 4, 3});
1064         _glmap.insert(QString::fromUtf8("gl46"), {CONFIG_RENDER_PLATFORM_OPENGL_CORE, 4, 6});
1065         _glmap.insert(QString::fromUtf8("gles2"), {CONFIG_RENDER_PLATFORM_OPENGL_ES, 2, 1});
1066         _glmap.insert(QString::fromUtf8("gles3"), {CONFIG_RENDER_PLATFORM_OPENGL_ES, 3, 0});
1067
1068         x_t _t = {CONFIG_RENDER_PLATFORM_OPENGL_ES, 2, 1};
1069         if(_glmap.contains(rendervalue)) {
1070                 _t = _glmap.value(rendervalue);
1071         }
1072         config.render_platform = _t.type;
1073         config.render_major_version = _t.major;
1074         config.render_minor_version = _t.minor;
1075
1076         switch(config.render_platform) {
1077         case CONFIG_RENDER_PLATFORM_OPENGL_MAIN:
1078         case CONFIG_RENDER_PLATFORM_OPENGL_CORE:
1079                 QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL, true);
1080                 QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); // Enable shared contexts.
1081                 QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, false);
1082                 break;
1083         case CONFIG_RENDER_PLATFORM_OPENGL_ES:
1084                 QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL, false);
1085                 QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); // Enable shared contexts.
1086                 QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true);
1087                 break;
1088         default: // to GLES 2.1 as Default
1089                 QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL, false);
1090                 QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true);
1091                 config.render_platform = CONFIG_RENDER_PLATFORM_OPENGL_ES;
1092                 config.render_major_version = 2;
1093                 config.render_minor_version = 1;
1094                 break;
1095         }
1096
1097
1098         uint32_t dipsw_onbits = 0x0000000;
1099         uint32_t dipsw_offmask = 0xffffffff;
1100         if(cmdparser->isSet("offbit")) {
1101                 QStringList bitList = cmdparser->values("offbit");
1102                 QString tv;
1103                 bool num_ok;
1104                 for(int i = 0; i < bitList.size(); i++) {
1105                         tv = bitList.at(i);
1106                         int _bit = tv.toInt(&num_ok);
1107                         if(num_ok) {
1108                                 if((_bit >= 0) && (_bit < 32)) {
1109                                         dipsw_offmask &= (uint32_t)(~(1 << _bit));
1110                                 }
1111                         }
1112                 }
1113         }
1114         if(cmdparser->isSet("onbit")) {
1115                 QStringList bitList = cmdparser->values("onbit");
1116                 QString tv;
1117                 bool num_ok;
1118                 for(int i = 0; i < bitList.size(); i++) {
1119                         tv = bitList.at(i);
1120                         int _bit = tv.toInt(&num_ok);
1121                         if(num_ok) {
1122                                 if((_bit >= 0) && (_bit < 32)) {
1123                                         dipsw_onbits |= (uint32_t)(1 << _bit);
1124                                 }
1125                         }
1126                 }
1127         }
1128         config.dipswitch &= dipsw_offmask;
1129         config.dipswitch |= dipsw_onbits;
1130
1131         // Virtual Medias
1132         for(auto __l = vmedialist.begin(); __l != vmedialist.end(); ++__l) {
1133                 if(cmdparser->isSet(*__l)) {
1134                         QString tmps = *__l;
1135                         if(!(tmps.isEmpty())) {
1136                                 dstlist.insert(tmps, cmdparser->value(tmps));
1137                         }
1138                 }
1139         }
1140 }
1141
1142 void OpeningMessage(std::shared_ptr<CSP_Logger>p_logger, std::string archstr, const QMap<QString, QString> virtualMediaList)
1143 {
1144         p_logger->set_emu_vm_name(DEVICE_NAME); // Write to syslog, console
1145         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Start Common Source Project '%s'", my_procname.c_str());
1146         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "(C) Toshiya Takeda / Qt Version K.Ohta");
1147         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Architecture: %s", archstr.c_str());
1148         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Use -h or --help for help.");
1149
1150         //p_logger->debug_log(AGAR_LOG_INFO, " -? is print help(s).");
1151         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Home = %s, Resource directory = %s",
1152                                                   cpp_homedir.c_str(),
1153                                                   sRssDir.c_str()); // Debug
1154
1155         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Config dir = %s, config_file = %s",
1156                                                   cpp_confdir.c_str(),
1157                                                   config_fullpath.c_str()); // Debug
1158
1159         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "DIPSW VALUE IS 0x%08x", config.dipswitch);
1160         QList<QString> __keys = virtualMediaList.keys();
1161         for(auto __s = __keys.begin(); __s != __keys.end(); ++__s) {
1162                 QString __val = virtualMediaList.value(*__s);
1163                 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Virtual media :%s, name %s",
1164                                                         (*__s).toLocal8Bit().constData(),
1165                                                         __val.toLocal8Bit().constData());
1166         }
1167 }
1168
1169 void SetupSDL(std::shared_ptr<CSP_Logger>p_logger)
1170 {
1171         QStringList _el = _envvars.toStringList();
1172
1173         if(_el.size() > 0) {
1174                 for(int i = 0; i < _el.size(); i++) {
1175                         QString _s = _el.at(i);
1176                         if(_s.startsWith("SDL_")) {
1177                                 QString skey, svar;
1178                                 int _nl;
1179                                 _nl = _s.indexOf('=');
1180                                 if(_nl >= 0) {
1181                                         skey = _s.left(_nl);
1182                                         svar = _s.right(_s.length() - (_nl + 1));
1183                                 } else {
1184                                         skey = _s;
1185                                         svar = QString::fromUtf8("");
1186                                 }
1187                                 SDL_setenv(skey.toLocal8Bit().constData(), svar.toLocal8Bit().constData(), 1);
1188                                 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Note: SDL ENVIROMENT : %s to %s.",
1189                                                                           skey.toLocal8Bit().constData(),
1190                                                                           svar.toLocal8Bit().constData());
1191                         }
1192                 }
1193         }
1194 #if defined(USE_SDL2)
1195         //SDL_Init(SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK);
1196         SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK);
1197         //SDL_Init(SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS);
1198 #else
1199         SDL_Init(SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_VIDEO);
1200 #endif
1201         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Audio subsystem was initialised.");
1202 }
1203
1204 extern void DLL_PREFIX_I set_debug_logger(std::shared_ptr<CSP_Logger> p);
1205
1206 void SetupLogger(std::shared_ptr<CSP_Logger> csp_logger, QObject *parent, std::string emustr, int _size)
1207 {
1208
1209         csp_logger->set_emu_vm_name((const char *)(emustr.c_str()));
1210         csp_logger->set_log_stdout(CSP_LOG_DEBUG, true);
1211         csp_logger->set_log_stdout(CSP_LOG_INFO, true);
1212         csp_logger->set_log_stdout(CSP_LOG_WARN, true);
1213
1214         csp_logger->set_state_log(0, config.state_log_to_recording);
1215         csp_logger->set_state_log(1, config.state_log_to_syslog);
1216         csp_logger->set_state_log(2, config.state_log_to_console);
1217
1218         for(int ii = 0; ii < _size; ii++) {
1219                 for(int jj = 0; jj < 8; jj++) {
1220                         csp_logger->set_device_node_log(ii, 1, jj, config.dev_log_to_syslog[ii][jj]);
1221                         csp_logger->set_device_node_log(ii, 2, jj, config.dev_log_to_console[ii][jj]);
1222                         csp_logger->set_device_node_log(ii, 0, jj, config.dev_log_recording[ii][jj]);
1223                 }
1224         }
1225 }
1226
1227 int MainLoop(int argc, char *argv[])
1228 {
1229
1230         std::string archstr;
1231         std::string emustr("emu");
1232         std::string cfgstr(CONFIG_NAME);
1233         std::string delim;
1234         QString emudesc;
1235         setup_logs();
1236
1237 #if defined(Q_OS_WIN)
1238         delim = "\\";
1239 #else
1240         delim = "/";
1241 #endif
1242
1243         QApplication *GuiMain = NULL;
1244         GuiMain = new QApplication(argc, argv);
1245         GuiMain->setObjectName(QString::fromUtf8("Gui_Main"));
1246     QCommandLineParser cmdparser;
1247         QStringList vmedia_aliases;
1248
1249         vmedia_aliases.clear();
1250         SetOptions(&cmdparser, vmedia_aliases);
1251
1252         QStringList arglist;
1253         if(argv != NULL) {
1254                 for(int i = 0; i < argc; i++) {
1255                         if(argv[i] != NULL) {
1256                                 arglist.append(QString::fromLocal8Bit(argv[i]));
1257                         }
1258                 }
1259         }
1260         archstr = "Generic";
1261 #if defined(__x86_64__)
1262         archstr = "amd64";
1263 #endif
1264 #if defined(__i386__)
1265         archstr = "ia32";
1266 #endif
1267         emustr = emustr + cfgstr;
1268         std::shared_ptr<USING_FLAGS> using_flags = std::shared_ptr<USING_FLAGS>(new USING_FLAGS_EXT(&config));
1269         cmdparser.process(arglist);
1270
1271         QMap<QString, QString> virtualMediaList;
1272         virtualMediaList.clear();
1273
1274         ProcessCmdLine(&cmdparser, (const QStringList)vmedia_aliases, virtualMediaList);
1275
1276         _envvars = QProcessEnvironment::systemEnvironment();
1277
1278         std::shared_ptr<CSP_Logger>p_logger = std::shared_ptr<CSP_Logger>(new CSP_Logger(GuiMain, config.log_to_syslog, config.log_to_console, emustr.c_str()));
1279         set_debug_logger(p_logger);
1280         SetupLogger(p_logger, GuiMain, emustr, CSP_LOG_TYPE_VM_DEVICE_END - CSP_LOG_TYPE_VM_DEVICE_0 + 1);
1281         OpeningMessage(p_logger, archstr, (const QMap<QString, QString>)virtualMediaList);
1282         SetupSDL(p_logger);
1283
1284         /*
1285          * Into Qt's Loop.
1286          */
1287
1288         //SetupTranslators();
1289         QTranslator local_translator;
1290         QLocale s_locale = QLocale::system();
1291
1292         if(local_translator.load(s_locale, "machine", ".", ":/", ".qm")) {
1293                 GuiMain->installTranslator(&local_translator);
1294         }
1295         QTranslator s_translator;
1296         if(s_translator.load(s_locale, "gui", ".", ":/", ".qm")) {
1297                 GuiMain->installTranslator(&s_translator);
1298         }
1299
1300         QTranslator common_translator;
1301         if(common_translator.load(s_locale, "common", ".", ":/", ".qm")) {
1302                 GuiMain->installTranslator(&common_translator);
1303         }
1304         QTranslator debugger_translator;
1305         if(debugger_translator.load(s_locale, "debugger", ".", ":/", ".qm")) {
1306                 GuiMain->installTranslator(&debugger_translator);
1307         }
1308         //QProcessEnvironment::systemEnvironment() = _envvars;
1309         if(_b_dump_envvar) {
1310                 //QProcessEnvironment ev = QProcessEnvironment::systemEnvironment();
1311                 QProcessEnvironment ev = _envvars;
1312                 QStringList el = _envvars.toStringList();
1313                 if(el.size() > 0) {
1314                         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Environment Variables:");
1315                         for(int i = 0; i < el.size(); i++) {
1316                                 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "#%d : %s", i, el.at(i).toLocal8Bit().constData());
1317                         }
1318                 }
1319         }
1320
1321 //      USING_FLAGS_EXT *using_flags = new USING_FLAGS_EXT(&config);
1322         // initialize emulation core
1323         rMainWindow = new META_MainWindow(using_flags, p_logger);
1324         rMainWindow->connect(rMainWindow, SIGNAL(sig_quit_all(void)), rMainWindow, SLOT(deleteLater(void)));
1325         rMainWindow->setCoreApplication(GuiMain);
1326         rMainWindow->getWindow()->show();
1327         rMainWindow->retranselateUi_Depended_OSD();
1328 //      QMetaObject::connectSlotsByName(rMainWindow);
1329         EmuThreadClass *hRunEmu_Real = new EmuThreadClass(rMainWindow, using_flags);
1330         hRunEmu_Real->setVirtualMediaList((const QMap<QString, QString>)virtualMediaList);
1331
1332         OSD_BASE* p_osd = hRunEmu_Real->get_emu()->get_osd();
1333
1334         QObject::connect((OSD*)p_osd, SIGNAL(sig_update_device_node_name(int, const _TCHAR *)),
1335                                          rMainWindow, SLOT(do_update_device_node_name(int, const _TCHAR *)));
1336         for(int i = 0; i < (CSP_LOG_TYPE_VM_DEVICE_END - CSP_LOG_TYPE_VM_DEVICE_0 + 1); i++) {
1337                 rMainWindow->do_update_device_node_name(i, using_flags->get_vm_node_name(i));
1338         }
1339         p_logger->set_osd((OSD*)p_osd);
1340         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "InitInstance() OK.");
1341
1342         // ToDo: Update raltime.
1343         rMainWindow->connect(rMainWindow, SIGNAL(sig_osd_sound_output_device(QString)), (OSD*)p_osd, SLOT(do_set_host_sound_output_device(QString)));
1344         rMainWindow->do_update_sound_output_list();
1345
1346         QObject::connect((OSD*)p_osd, SIGNAL(sig_update_sound_output_list()), rMainWindow, SLOT(do_update_sound_output_list()));
1347         QObject::connect((OSD*)p_osd, SIGNAL(sig_clear_sound_output_list()), rMainWindow, SLOT(do_clear_sound_output_list()));
1348         QObject::connect((OSD*)p_osd, SIGNAL(sig_append_sound_output_list(QString)), rMainWindow, SLOT(do_append_sound_output_list(QString)));
1349
1350         QObject::connect(rMainWindow, SIGNAL(sig_update_master_volume(int)), (OSD*)p_osd, SLOT(do_update_master_volume(int)));
1351
1352         QObject::connect(GuiMain, SIGNAL(lastWindowClosed()),
1353                                          rMainWindow, SLOT(on_actionExit_triggered()));
1354
1355         QObject::connect((OSD*)p_osd, SIGNAL(sig_clear_keyname_table()),         rMainWindow, SLOT(do_clear_keyname_table()));
1356         QObject::connect((OSD*)p_osd, SIGNAL(sig_add_keyname_table(uint32_t, QString)),  rMainWindow, SLOT(do_add_keyname_table(uint32_t, QString)));
1357         p_osd->update_keyname_table();
1358
1359         QObject::connect(rMainWindow, SIGNAL(sig_notify_power_off()), hRunEmu_Real, SLOT(do_notify_power_off()), Qt::QueuedConnection);
1360
1361         GLDrawClass *pgl = rMainWindow->getGraphicsView();
1362         pgl->do_set_texture_size(NULL, -1, -1);  // It's very ugly workaround (;_;) 20191028 K.Ohta
1363 //      pgl->setFixedSize(pgl->width(), pgl->height());
1364         // main loop
1365         rMainWindow->LaunchEmuThread(hRunEmu_Real);
1366
1367 #if defined(USE_JOYSTICK)
1368         rMainWindow->LaunchJoyThread();
1369 #endif
1370         rMainWindow->do_start_emu_thread();
1371         rMainWindow->do_unblock_task();
1372         rMainWindow->do_start_draw_thread();
1373         GuiMain->exec();
1374         return 0;
1375 }
1376
1377
1378 #ifdef USE_DEBUGGER
1379 #include <../debugger/qt_debugger.h>
1380
1381 void Ui_MainWindow::OnOpenDebugger()
1382 {
1383         QAction *cp = qobject_cast<QAction*>(QObject::sender());
1384         if(cp == nullptr) return;
1385         int no = cp->data().value<int>();
1386
1387         if((no < 0) || (no >= MAX_CPU)) return;
1388         //emu->open_debugger(no);
1389         if(hRunEmu == nullptr) return;
1390         EMU_TEMPLATE *p_emu = hRunEmu->get_emu();
1391
1392         VM *vm = static_cast<VM*>(p_emu->get_vm());
1393
1394         // ToDo: Multiple debugger 20221105 K.O
1395         if((p_emu->now_debugging ) || (p_emu->hDebugger.get() != nullptr)) /* OnCloseDebugger(); */ return;
1396
1397         if(!(p_emu->now_debugging && p_emu->debugger_thread_param.cpu_index == no)) {
1398                 //p_emu->close_debugger();
1399                 if(vm->get_cpu(no) != NULL && vm->get_cpu(no)->get_debugger() != NULL) {
1400                         QString windowName = QString::fromUtf8(vm->get_cpu(no)->get_device_name());
1401                         windowName = QString::fromUtf8("Debugger ") + windowName;
1402                         p_emu->hDebugger.reset(new CSP_Debugger(p_emu, this));
1403                         if(p_emu->hDebugger.get() == nullptr) {
1404                                 return;
1405                         }
1406                         QString objNameStr = QString("EmuDebugThread");
1407                         p_emu->hDebugger->setObjectName(objNameStr);
1408
1409                         p_emu->hDebugger->debugger_thread_param.osd = (OSD_BASE *)(p_emu->get_osd());
1410                         p_emu->hDebugger->debugger_thread_param.emu = p_emu;
1411                         p_emu->hDebugger->debugger_thread_param.vm = vm;
1412                         p_emu->hDebugger->debugger_thread_param.cpu_index = no;
1413                         p_emu->hDebugger->debugger_thread_param.running = false;
1414                         p_emu->hDebugger->debugger_thread_param.request_terminate = false;
1415
1416                         p_emu->stop_record_sound();
1417                         p_emu->stop_record_video();
1418                         //p_emu->now_debugging = true;
1419                         connect(this, SIGNAL(quit_debugger_thread()), p_emu->hDebugger.get(), SLOT(doExit()));
1420                         connect(this, SIGNAL(destroyed()), p_emu->hDebugger.get(), SLOT(do_destroy_thread()));
1421                         //connect(this, SIGNAL(quit_debugger_thread()), p_emu->hDebugger, SLOT(close()));
1422                         connect(p_emu->hDebugger.get(), SIGNAL(sig_finished()), this, SLOT(OnCloseDebugger()));
1423                         connect(p_emu->hDebugger.get(), SIGNAL(sig_put_string(QString)), p_emu->hDebugger.get(), SLOT(put_string(QString)));
1424                         p_emu->hDebugger->show();
1425                         p_emu->hDebugger->run();
1426                         p_emu->hDebugger->setWindowTitle(windowName);
1427                 }
1428         }
1429 }
1430
1431 void Ui_MainWindow::OnCloseDebugger(void )
1432 {
1433         if(hRunEmu == nullptr) return;
1434         EMU_TEMPLATE *p_emu = hRunEmu->get_emu();
1435         if(p_emu == nullptr) {
1436                 return;
1437         }
1438 //      p_emu->close_debugger();
1439         // ToDo: Multiple debugger 20221105 K.O
1440         if((p_emu->now_debugging) && (p_emu->hDebugger.get() != nullptr)) {
1441                 if(p_emu->hDebugger->debugger_thread_param.running) {
1442                         emit quit_debugger_thread();
1443                         //if(!(p_emu->hDebugger->wait(2000))) {
1444                         //      p_emu->hDebugger->terminate();
1445                         //      QThread::msleep(100);
1446                         //}
1447                 }
1448         }
1449         p_emu->hDebugger.reset();
1450         p_emu->now_debugging = false;
1451 }
1452 #endif
1453
1454 QString Ui_MainWindow::get_system_version()
1455 {
1456         if(hRunEmu == nullptr) return QString::fromUtf8("");
1457         EMU_TEMPLATE *p_emu = hRunEmu->get_emu();
1458
1459         QString guiver = get_gui_version();
1460         QString aviover;
1461         QString vm_gitver;
1462         QString common_vmver;
1463         QString osdver;
1464         QString libcommon_ver;
1465         QString libfmgen_ver;
1466         QString build_date;
1467
1468         QString outstr;
1469
1470         aviover.clear();
1471         common_vmver.clear();
1472         vm_gitver.clear();
1473         osdver.clear();
1474         libcommon_ver.clear();
1475
1476         if(hSaveMovieThread != NULL) {
1477                 aviover = hSaveMovieThread->get_avio_version();
1478         }
1479
1480         if(p_emu != nullptr) {
1481                 if(p_emu->get_osd() != NULL) {
1482                         _TCHAR *cvp = (_TCHAR *)p_emu->get_osd()->get_lib_common_vm_version();
1483                         _TCHAR *gvp = (_TCHAR *)p_emu->get_osd()->get_lib_common_vm_git_version();
1484                         _TCHAR *ovp = (_TCHAR *)p_emu->get_osd()->get_lib_osd_version();
1485                         if(cvp != NULL) {
1486                                 common_vmver = QString::fromUtf8(cvp);
1487                         }
1488                         if(gvp != NULL) {
1489                                 vm_gitver = QString::fromUtf8(gvp);
1490                         }
1491                         if(ovp != NULL) {
1492                                 osdver = QString::fromUtf8(ovp);
1493                         }
1494                 }
1495         }
1496
1497         const _TCHAR *pp = get_lib_common_version();
1498         if(pp != NULL) {
1499                 libcommon_ver = QString::fromUtf8(pp);
1500         }
1501         libfmgen_ver = QString::fromUtf8(FM::get_libfmgen_version());
1502
1503         outstr.clear();
1504         outstr.append(QString::fromUtf8("<FONT SIZE=+1>"));
1505         if(!(common_vmver.isEmpty())) {
1506                 outstr.append(common_vmver);
1507                 outstr.append("<BR>\n");
1508         }
1509         if(!(libcommon_ver.isEmpty())) {
1510                 outstr.append(libcommon_ver);
1511                 outstr.append("<BR>\n");
1512         }
1513         if(!(osdver.isEmpty())) {
1514                 outstr.append(osdver);
1515                 outstr.append("<BR>\n");
1516         }
1517         if(!(libfmgen_ver.isEmpty())) {
1518                 outstr.append(libfmgen_ver);
1519                 outstr.append("<BR>\n");
1520         }
1521         if(!(osdver.isEmpty())) {
1522                 outstr.append(osdver);
1523                 outstr.append("<BR>\n");
1524         }
1525         if(!(guiver.isEmpty())) {
1526                 outstr.append(guiver);
1527                 outstr.append("<BR>\n");
1528         }
1529         if(!(aviover.isEmpty())) {
1530                 outstr.append(aviover);
1531                 outstr.append("<BR>\n");
1532         }
1533         outstr.append(QString::fromUtf8("</FONT>"));
1534         if(!(vm_gitver.isEmpty())) {
1535                 outstr.append("Build Version: ");
1536                 outstr.append(vm_gitver);
1537                 outstr.append("<BR>\n");
1538         }
1539         return outstr;
1540 }
1541
1542 QString Ui_MainWindow::get_build_date()
1543 {
1544 #if defined(__BUILD_DATE)
1545         return QString::fromUtf8(__BUILD_DATE);
1546 #else
1547         return QString::fromUtf8("");
1548 #endif
1549 }