OSDN Git Service

[UI][EMU][OSD][Qt][FLOPPY] Fix message routing.
[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 <QTranslator>
23 #include <QProcessEnvironment>
24 #include <QCommandLineParser>
25
26 #include "common.h"
27 #include "fileio.h"
28 #include "config.h"
29 #include "emu.h"
30 #include "../osd.h"
31
32 #include "menuclasses.h"
33 #include "mainwidget.h"
34 #include "commonclasses.h"
35 #include "qt_main.h"
36 #include "emu_thread.h"
37 #include "joy_thread.h"
38 #include "draw_thread.h"
39
40 #include "qt_gldraw.h"
41 #include "../gui/gl2/qt_glutil_gl2_0.h"
42 #include "csp_logger.h"
43 #include "dock_disks.h"
44 #include "menu_disk.h"
45 #include "menu_bubble.h"
46 #include "menu_flags_ext.h"
47 #include "dialog_movie.h"
48 #include "../avio/movie_saver.h"
49 // emulation core
50 #include "../../vm/vm_limits.h"
51 #include "../../vm/fmgen/fmgen.h"
52
53 EMU* emu;
54 //QApplication *GuiMain = NULL;
55 extern config_t config;
56
57 // Start to define MainWindow.
58 class META_MainWindow *rMainWindow;
59
60
61 // buttons
62 #ifdef MAX_BUTTONS
63 #define MAX_FONT_SIZE 32
64 #endif
65
66 // menu
67 extern DLL_PREFIX_I std::string cpp_homedir;
68 extern DLL_PREFIX_I std::string cpp_confdir;
69 extern DLL_PREFIX_I std::string my_procname;
70 extern DLL_PREFIX_I std::string sRssDir;
71
72 void Ui_MainWindow::do_set_mouse_enable(bool flag)
73 {
74 #ifdef USE_MOUSE
75         if(emu == NULL) return;
76         emu->lock_vm();
77         if(flag) {
78                 graphicsView->grabMouse();
79                 emu->enable_mouse();
80         } else {
81                 graphicsView->releaseMouse();
82                 emu->disable_mouse();
83         }
84         emu->unlock_vm();
85 #endif  
86 }
87
88 void Ui_MainWindow::do_toggle_mouse(void)
89 {
90 #ifdef USE_MOUSE
91         if(emu == NULL) return;
92         emu->lock_vm();
93         bool flag = emu->is_mouse_enabled();
94         if(!flag) {
95                 graphicsView->grabMouse();
96                 emu->enable_mouse();
97         } else {
98                 graphicsView->releaseMouse();
99                 emu->disable_mouse();
100         }
101         emu->unlock_vm();
102 #endif  
103 }
104
105 void Ui_MainWindow::rise_movie_dialog(void)
106 {
107         CSP_DialogMovie *dlg = new CSP_DialogMovie(hSaveMovieThread, using_flags);
108         dlg->setWindowTitle(QApplication::translate("CSP_DialogMovie", "Configure movie encodings", 0));
109         dlg->show();
110 }
111
112 void Ui_MainWindow::LaunchEmuThread(EmuThreadClassBase *m)
113 {
114         QString objNameStr;
115         GLDrawClass *glv = this->getGraphicsView();
116
117         int drvs;
118         
119         hRunEmu = m;
120         if(hRunEmu == nullptr) return;
121         OSD_BASE* p_osd = hRunEmu->get_emu()->get_osd();
122         
123         connect(hRunEmu, SIGNAL(message_changed(QString)), this, SLOT(message_status_bar(QString)), Qt::QueuedConnection);
124         connect(hRunEmu, SIGNAL(sig_is_enable_mouse(bool)), this, SLOT(do_set_mouse_enable(bool)));
125         connect(glv, SIGNAL(sig_key_down(uint32_t, uint32_t, bool)), hRunEmu, SLOT(do_key_down(uint32_t, uint32_t, bool)));
126         connect(glv, SIGNAL(sig_key_up(uint32_t, uint32_t)),hRunEmu, SLOT(do_key_up(uint32_t, uint32_t)));
127         connect(this, SIGNAL(sig_quit_widgets()), glv, SLOT(do_stop_run_vm()));
128
129         if(action_ResetFixedCpu != nullptr) {
130                 connect(action_ResetFixedCpu, SIGNAL(triggered()),
131                                 hRunEmu, SLOT(do_set_emu_thread_to_fixed_cpu_from_action()));
132                 
133         }
134         for(int i = 0 ; i < 128 ; i++) {
135                 if(action_SetFixedCpu[i] == nullptr) break;
136                 connect(action_SetFixedCpu[i], SIGNAL(triggered()),
137                                 hRunEmu, SLOT(do_set_emu_thread_to_fixed_cpu_from_action()));
138         }
139         //connect(hRunEmu, SIGNAL(sig_finished()), this, SLOT(delete_emu_thread()));
140         connect(this, SIGNAL(sig_vm_reset()), hRunEmu, SLOT(do_reset()));
141         
142         for(int i = 0 ; i < using_flags->get_use_special_reset_num() ; i++) {
143                 if(actionSpecial_Reset[i] != nullptr) {
144                         connect(actionSpecial_Reset[i], SIGNAL(triggered()), hRunEmu, SLOT(do_special_reset()));
145                 }
146                 if(i >= 15) break;
147         }
148         connect(this, SIGNAL(sig_emu_update_config()), hRunEmu, SLOT(do_update_config()));
149         connect(this, SIGNAL(sig_emu_update_volume_level(int, int)), hRunEmu, SLOT(do_update_volume_level(int, int)));
150         connect(this, SIGNAL(sig_emu_update_volume_balance(int, int)), hRunEmu, SLOT(do_update_volume_balance(int, int)));
151         connect(this, SIGNAL(sig_emu_start_rec_sound()), hRunEmu, SLOT(do_start_record_sound()));
152         connect(this, SIGNAL(sig_emu_stop_rec_sound()), hRunEmu, SLOT(do_stop_record_sound()));
153         connect(this, SIGNAL(sig_emu_set_display_size(int, int, int, int)), hRunEmu, SLOT(do_set_display_size(int, int, int, int)));
154         connect(this, SIGNAL(sig_emu_thread_to_fixed_cpu(int)), hRunEmu, SLOT(set_emu_thread_to_fixed_cpu(int)));
155         
156         if(using_flags->is_use_state()) {
157                 for(int i = 0; i < 10; i++) {
158                         connect(actionLoad_State[i], SIGNAL(triggered()), hRunEmu, SLOT(do_load_state())); // OK?
159                         connect(actionSave_State[i], SIGNAL(triggered()), hRunEmu, SLOT(do_save_state())); // OK?
160                 }
161         }
162 #if defined(USE_FLOPPY_DISK)
163         connect(this, SIGNAL(sig_write_protect_disk(int, bool)), hRunEmu, SLOT(do_write_protect_disk(int, bool)));
164         connect(this, SIGNAL(sig_open_disk(int, QString, int)), hRunEmu, SLOT(do_open_disk(int, QString, int)));
165         connect(this, SIGNAL(sig_close_disk(int)), hRunEmu, SLOT(do_close_disk(int)));
166         connect(hRunEmu, SIGNAL(sig_update_recent_disk(int)), this, SLOT(do_update_recent_disk(int)));
167         //connect(hRunEmu, SIGNAL(sig_change_osd_fd(int, QString)), this, SLOT(do_change_osd_fd(int, QString)));
168         connect(p_osd, SIGNAL(sig_ui_floppy_insert_history(int, QString, quint64)),
169                                          this, SLOT(do_ui_floppy_insert_history(int, QString, quint64)),
170                                          Qt::QueuedConnection);
171
172         drvs = USE_FLOPPY_DISK;
173         for(int ii = 0; ii < drvs; ii++) {
174                 menu_fds[ii]->setEmu(emu);
175                 connect(menu_fds[ii], SIGNAL(sig_update_inner_fd(int ,QStringList , class Action_Control **, QStringList , int, bool)),
176                                 this, SLOT(do_update_inner_fd(int ,QStringList , class Action_Control **, QStringList , int, bool)));
177         }
178 #endif
179 #if defined(USE_HARD_DISK)
180         connect(this, SIGNAL(sig_open_hard_disk(int, QString)), hRunEmu, SLOT(do_open_hard_disk(int, QString)));
181         connect(this, SIGNAL(sig_close_hard_disk(int)), hRunEmu, SLOT(do_close_hard_disk(int)));
182         connect(hRunEmu, SIGNAL(sig_update_recent_hard_disk(int)), this, SLOT(do_update_recent_hard_disk(int)));
183         //connect(hRunEmu, SIGNAL(sig_change_osd_fd(int, QString)), this, SLOT(do_change_osd_fd(int, QString)));
184 #endif
185 #if defined(USE_TAPE)
186         connect(this, SIGNAL(sig_play_tape(int, QString)), hRunEmu, SLOT(do_play_tape(int, QString)));
187         connect(this, SIGNAL(sig_rec_tape(int, QString)),  hRunEmu, SLOT(do_rec_tape(int, QString)));
188         connect(this, SIGNAL(sig_close_tape(int)),   hRunEmu, SLOT(do_close_tape(int)));
189         //connect(hRunEmu, SIGNAL(sig_change_osd_cmt(QString)), this, SLOT(do_change_osd_cmt(QString)));
190         connect(this, SIGNAL(sig_cmt_push_play(int)), hRunEmu, SLOT(do_cmt_push_play(int)));
191         connect(this, SIGNAL(sig_cmt_push_stop(int)), hRunEmu, SLOT(do_cmt_push_stop(int)));
192         connect(this, SIGNAL(sig_cmt_push_fast_forward(int)), hRunEmu, SLOT(do_cmt_push_fast_forward(int)));
193         connect(this, SIGNAL(sig_cmt_push_fast_rewind(int)),  hRunEmu, SLOT(do_cmt_push_fast_rewind(int)));
194         connect(this, SIGNAL(sig_cmt_push_apss_forward(int)), hRunEmu, SLOT(do_cmt_push_apss_forward(int)));
195         connect(this, SIGNAL(sig_cmt_push_apss_rewind(int)),  hRunEmu, SLOT(do_cmt_push_apss_rewind(int)));
196 #endif
197 #if defined(USE_QUICK_DISK)
198         connect(this, SIGNAL(sig_write_protect_quickdisk(int, bool)), hRunEmu, SLOT(do_write_protect_quickdisk(int, bool)));
199         connect(this, SIGNAL(sig_open_quickdisk(int, QString)), hRunEmu, SLOT(do_open_quickdisk(int, QString)));
200         connect(this, SIGNAL(sig_close_quickdisk(int)), hRunEmu, SLOT(do_close_quickdisk(int)));
201         //connect(hRunEmu, SIGNAL(sig_change_osd_qd(int, QString)), this, SLOT(do_change_osd_qd(int, QString)));
202 #endif
203 #if defined(USE_CART)
204         connect(this, SIGNAL(sig_open_cart(int, QString)), hRunEmu, SLOT(do_open_cart(int, QString)));
205         connect(this, SIGNAL(sig_close_cart(int)), hRunEmu, SLOT(do_close_cart(int)));
206 #endif
207 #if defined(USE_COMPACT_DISC)
208         connect(this, SIGNAL(sig_open_cdrom(int, QString)), hRunEmu, SLOT(do_open_cdrom(int, QString)));
209         connect(this, SIGNAL(sig_close_cdrom(int)), hRunEmu, SLOT(do_eject_cdrom(int)));
210         //connect(hRunEmu, SIGNAL(sig_change_osd_cdrom(QString)), this, SLOT(do_change_osd_cdrom(QString)));
211         // ToDo: multiple CDs
212 #endif  
213 #if defined(USE_LASER_DISC)
214         connect(this, SIGNAL(sig_open_laserdisc(int, QString)), hRunEmu, SLOT(do_open_laser_disc(int, QString)));
215         connect(this, SIGNAL(sig_close_laserdisc(int)), hRunEmu, SLOT(do_close_laser_disc(int)));
216         // ToDo: multiple LDs
217 #endif
218 #if defined(USE_BINARY_FILE)
219         connect(this, SIGNAL(sig_load_binary(int, QString)), hRunEmu, SLOT(do_load_binary(int, QString)));
220         connect(this, SIGNAL(sig_save_binary(int, QString)), hRunEmu, SLOT(do_save_binary(int, QString)));
221 #endif
222 #if defined(USE_BUBBLE)
223         connect(this, SIGNAL(sig_write_protect_bubble(int, bool)), hRunEmu, SLOT(do_write_protect_bubble_casette(int, bool)));
224         connect(this, SIGNAL(sig_open_bubble(int, QString, int)), hRunEmu, SLOT(do_open_bubble_casette(int, QString, int)));
225         connect(this, SIGNAL(sig_close_bubble(int)), hRunEmu, SLOT(do_close_bubble_casette(int)));
226         connect(hRunEmu, SIGNAL(sig_update_recent_bubble(int)), this, SLOT(do_update_recent_bubble(int)));
227         //connect(hRunEmu, SIGNAL(sig_change_osd_bubble(int, QString)), this, SLOT(do_change_osd_bubble(int, QString)));
228         drvs = USE_BUBBLE;
229         for(int ii = 0; ii < drvs; ii++) {
230                 menu_bubbles[ii]->setEmu(emu);
231                 connect(menu_bubbles[ii],
232                                 SIGNAL(sig_update_inner_bubble(int ,QStringList , class Action_Control **, QStringList , int, bool)),
233                                 this,
234                                 SLOT(do_update_inner_bubble(int ,QStringList , class Action_Control **, QStringList , int, bool))
235                         );
236         }
237 #endif
238         
239         connect(this, SIGNAL(quit_emu_thread()), hRunEmu, SLOT(doExit()));
240         connect(hRunEmu, SIGNAL(sig_mouse_enable(bool)),
241                         this, SLOT(do_set_mouse_enable(bool)));
242
243         
244         hRunEmu->set_tape_play(false);
245 #if defined(USE_KEY_LOCKED) || defined(USE_LED_DEVICE)
246         connect(hRunEmu, SIGNAL(sig_send_data_led(quint32)), this, SLOT(do_recv_data_led(quint32)), Qt::QueuedConnection);
247 #endif
248 #ifdef USE_AUTO_KEY
249         connect(this, SIGNAL(sig_start_auto_key(QString)), hRunEmu, SLOT(do_start_auto_key(QString)));
250         connect(this, SIGNAL(sig_stop_auto_key()), hRunEmu, SLOT(do_stop_auto_key()));
251         connect(this, SIGNAL(sig_set_roma_kana(bool)), hRunEmu, SLOT(set_romakana(bool)));
252 #endif  
253
254         csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "EmuThread : Start.");
255         objNameStr = QString("EmuThreadClass");
256         hRunEmu->setObjectName(objNameStr);
257         
258         hDrawEmu = new DrawThreadClass((OSD*)(emu->get_osd()), csp_logger, this);
259         emu->set_parent_handler((EmuThreadClass*)hRunEmu, hDrawEmu);
260         
261 #ifdef ONE_BOARD_MICRO_COMPUTER
262         QImageReader *reader = new QImageReader(":/background.png");
263         QImage *result = new QImage(reader->read()); // this acts as a default if the size is not matched
264         QImage result2 = result->convertToFormat(QImage::Format_ARGB32);
265         glv->updateBitmap(&result2);
266         emu->get_osd()->upload_bitmap(&result2);
267         delete result;
268         delete reader;
269         emu->get_osd()->set_buttons();
270 #endif
271         csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "DrawThread : Start.");
272         connect(hDrawEmu, SIGNAL(sig_draw_frames(int)), hRunEmu, SLOT(print_framerate(int)), Qt::DirectConnection);
273         //connect((OSD*)(emu->get_osd()), SIGNAL(sig_draw_frames(int)), hRunEmu, SLOT(print_framerate(int)));
274         connect(hRunEmu, SIGNAL(window_title_changed(QString)), this, SLOT(do_set_window_title(QString)), Qt::QueuedConnection);
275         connect(hDrawEmu, SIGNAL(message_changed(QString)), this, SLOT(message_status_bar(QString)));
276         connect(actionCapture_Screen, SIGNAL(triggered()), glv, SLOT(do_save_frame_screen()));
277         connect(this, SIGNAL(sig_emu_launched()), glv, SLOT(set_emu_launched()));
278
279         /*if(config.use_separate_thread_draw) {
280                 connect(hRunEmu, SIGNAL(sig_draw_thread(bool)), hDrawEmu, SLOT(doDraw(bool)));
281                 connect(hRunEmu, SIGNAL(sig_set_draw_fps(double)), hDrawEmu, SLOT(do_set_frames_per_second(double)));
282                 connect(hRunEmu, SIGNAL(sig_draw_one_turn(bool)), hDrawEmu, SLOT(do_draw_one_turn(bool)));
283                 } else*/ {
284                 connect(hRunEmu, SIGNAL(sig_draw_thread(bool)), hDrawEmu, SLOT(doDraw(bool)), Qt::DirectConnection);
285                 connect(hRunEmu, SIGNAL(sig_set_draw_fps(double)), hDrawEmu, SLOT(do_set_frames_per_second(double)));
286                 connect(hRunEmu, SIGNAL(sig_draw_one_turn(bool)), hDrawEmu, SLOT(do_draw_one_turn(bool)));
287         }
288         //connect(hRunEmu, SIGNAL(sig_draw_thread(bool)), (OSD*)(emu->get_osd()), SLOT(do_draw(bool)));
289         //connect(hRunEmu, SIGNAL(quit_draw_thread()), hDrawEmu, SLOT(doExit()));
290         connect(this, SIGNAL(quit_draw_thread()), hDrawEmu, SLOT(doExit()));
291
292         connect(glv, SIGNAL(sig_notify_move_mouse(double, double, double, double)),
293                         hRunEmu, SLOT(moved_mouse(double, double, double, double)));
294         connect(glv, SIGNAL(do_notify_button_pressed(Qt::MouseButton)),
295                 hRunEmu, SLOT(button_pressed_mouse(Qt::MouseButton)));
296         connect(glv, SIGNAL(do_notify_button_released(Qt::MouseButton)),
297                         hRunEmu, SLOT(button_released_mouse(Qt::MouseButton)));
298 #ifdef USE_MOUSE
299         connect(glv, SIGNAL(sig_toggle_mouse(void)),
300                         this, SLOT(do_toggle_mouse(void)));
301         connect(glv, SIGNAL(sig_toggle_grab_mouse()), this, SLOT(do_toggle_mouse()));
302 #endif
303         connect(hRunEmu, SIGNAL(sig_resize_screen(int, int)),
304                         glv, SLOT(resizeGL(int, int)), Qt::QueuedConnection);
305         connect(hRunEmu, SIGNAL(sig_resize_osd(int)), driveData, SLOT(setScreenWidth(int)), Qt::QueuedConnection);
306         connect(hRunEmu, SIGNAL(sig_change_osd(int, int, QString)), driveData, SLOT(updateMessage(int, int, QString)), Qt::QueuedConnection);
307         
308         connect(glv, SIGNAL(sig_resize_uibar(int, int)),
309                         this, SLOT(resize_statusbar(int, int)), Qt::QueuedConnection);
310         connect(hRunEmu, SIGNAL(sig_resize_uibar(int, int)),
311                         this, SLOT(resize_statusbar(int, int)), Qt::QueuedConnection);
312
313         connect((OSD*)(emu->get_osd()), SIGNAL(sig_req_encueue_video(int, int, int)),
314                         hDrawEmu, SLOT(do_req_encueue_video(int, int, int)));
315         connect(hRunEmu, SIGNAL(sig_finished()), glv, SLOT(releaseKeyCode(void)));
316         connect(hRunEmu, SIGNAL(sig_finished()), this, SLOT(delete_emu_thread()));
317         objNameStr = QString("EmuDrawThread");
318         hDrawEmu->setObjectName(objNameStr);
319
320         csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "DrawThread : Launch done.");
321
322         hSaveMovieThread = new MOVIE_SAVER(640, 400,  30, (OSD*)(emu->get_osd()), &config);
323
324         // SAVING MOVIES
325 //      connect(this, SIGNAL(sig_start_saving_movie()), hRunEmu, SLOT(do_start_record_video()));
326         connect(actionStart_Record_Movie, SIGNAL(triggered()), hRunEmu, SLOT(do_start_record_video()));
327         connect(actionStop_Record_Movie, SIGNAL(triggered()), hRunEmu, SLOT(do_stop_record_video()));
328         
329         connect(hSaveMovieThread, SIGNAL(sig_set_state_saving_movie(bool)), this, SLOT(do_set_state_saving_movie(bool)));
330
331         connect((OSD*)(emu->get_osd()), SIGNAL(sig_save_as_movie(QString, int, int)),
332                         hSaveMovieThread, SLOT(do_open(QString, int, int)));
333         connect((OSD*)(emu->get_osd()), SIGNAL(sig_stop_saving_movie()), hSaveMovieThread, SLOT(do_close()));
334         
335         actionStop_Record_Movie->setIcon(QIcon(":/icon_process_stop.png"));
336         actionStop_Record_Movie->setVisible(false);
337         
338         connect(this, SIGNAL(sig_movie_set_width(int)), hSaveMovieThread, SLOT(do_set_width(int)));
339         connect(this, SIGNAL(sig_movie_set_height(int)), hSaveMovieThread, SLOT(do_set_height(int)));
340  
341         connect((OSD*)(emu->get_osd()), SIGNAL(sig_movie_set_width(int)), hSaveMovieThread, SLOT(do_set_width(int)));
342         connect((OSD*)(emu->get_osd()), SIGNAL(sig_movie_set_height(int)), hSaveMovieThread, SLOT(do_set_height(int)));
343    
344         connect((OSD*)(emu->get_osd()), SIGNAL(sig_enqueue_audio(int16_t*, int)), hSaveMovieThread, SLOT(enqueue_audio(int16_t *, int)));
345         connect((OSD*)(emu->get_osd()), SIGNAL(sig_enqueue_video(int, int, int, QImage *)),
346                         hSaveMovieThread, SLOT(enqueue_video(int, int, int, QImage *)), Qt::DirectConnection);
347         connect(glv->extfunc, SIGNAL(sig_push_image_to_movie(int, int, int, QImage *)),
348                         hSaveMovieThread, SLOT(enqueue_video(int, int, int, QImage *)));
349         connect(this, SIGNAL(sig_quit_movie_thread()), hSaveMovieThread, SLOT(do_exit()));
350
351         objNameStr = QString("EmuMovieThread");
352         hSaveMovieThread->setObjectName(objNameStr);
353         hSaveMovieThread->start();
354         csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "MovieThread : Launch done.");
355
356         connect(action_SetupMovie, SIGNAL(triggered()), this, SLOT(rise_movie_dialog()));
357         connect(hRunEmu, SIGNAL(sig_change_access_lamp(int, int, QString)), driveData, SLOT(updateLabel(int, int, QString)), Qt::QueuedConnection);
358         connect(hRunEmu, SIGNAL(sig_set_access_lamp(int, bool)), graphicsView, SLOT(do_display_osd_leds(int, bool)), Qt::QueuedConnection);
359         connect(hRunEmu, SIGNAL(sig_change_virtual_media(int, int, QString)), driveData, SLOT(updateMediaFileName(int, int, QString)), Qt::QueuedConnection);
360         connect((OSD*)(emu->get_osd()), SIGNAL(sig_change_virtual_media(int, int, QString)), driveData, SLOT(updateMediaFileName(int, int, QString)));
361         connect((OSD*)(emu->get_osd()), SIGNAL(sig_enable_mouse()), glv, SLOT(do_enable_mouse()));
362         connect((OSD*)(emu->get_osd()), SIGNAL(sig_disable_mouse()), glv, SLOT(do_disable_mouse()));
363
364         connect(this, SIGNAL(sig_unblock_task()), hRunEmu, SLOT(do_unblock()));
365         connect(this, SIGNAL(sig_block_task()), hRunEmu, SLOT(do_block()));
366         connect(this, SIGNAL(sig_start_emu_thread()), hRunEmu, SLOT(do_start_emu_thread()));
367         connect(this, SIGNAL(sig_start_draw_thread()), hDrawEmu, SLOT(do_start_draw_thread()));
368
369
370 //      hRunEmu->start(QThread::HighestPriority);
371         this->set_screen_aspect(config.window_stretch_type);
372         emit sig_movie_set_width(SCREEN_WIDTH);
373         emit sig_movie_set_height(SCREEN_HEIGHT);
374 //      hRunEmu->start(QThread::HighestPriority);
375         csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "EmuThread : Launch done.");
376 }
377
378 void Ui_MainWindow::do_create_d88_media(int drv, quint8 media_type, QString name)
379 {
380         if(!(name.isEmpty()) && (drv >= 0)) {
381 #if defined(USE_FLOPPY_DISK)
382                 if(drv < USE_FLOPPY_DISK) {
383                         const _TCHAR* path = (const _TCHAR *)(name.toLocal8Bit().data());
384                         if(emu->create_blank_floppy_disk(path, media_type)) {
385                                 emit sig_open_disk(drv, name, 0);
386                         }
387                 }
388 #endif
389         }
390 }
391
392 void Ui_MainWindow::do_create_hard_disk(int drv, int sector_size, int sectors, int surfaces, int cylinders, QString name)
393 {
394         if(!(name.isEmpty()) && (drv >= 0)) {
395 #if defined(USE_HARD_DISK)
396                 if(drv < USE_HARD_DISK) {
397                         const _TCHAR* path = (const _TCHAR *)(name.toLocal8Bit().data());
398                         if(emu->create_blank_hard_disk(path, sector_size, sectors, surfaces, cylinders)) {
399                                 emit sig_open_hard_disk(drv, name);
400                         }
401                 }
402 #endif
403         }
404 }
405
406 void Ui_MainWindow::LaunchJoyThread(void)
407 {
408 #if defined(USE_JOYSTICK)
409         hRunJoy = new JoyThreadClass(emu, using_flags, &config);
410         connect(this, SIGNAL(quit_joy_thread()), hRunJoy, SLOT(doExit()));
411         hRunJoy->setObjectName("JoyThread");
412         hRunJoy->start();
413 #endif  
414 }
415
416 void Ui_MainWindow::StopJoyThread(void)
417 {
418 #if defined(USE_JOYSTICK)
419         emit quit_joy_thread();
420 #endif  
421 }
422
423 void Ui_MainWindow::delete_joy_thread(void)
424 {
425         //    delete hRunJoyThread;
426         //  delete hRunJoy;
427 }
428
429 void Ui_MainWindow::on_actionExit_triggered()
430 {
431         OnMainWindowClosed();
432 }
433
434 void Ui_MainWindow::OnWindowRedraw(void)
435 {
436         if(emu) {
437                 //emu->update_screen();
438         }
439 }
440
441 void Ui_MainWindow::OnWindowMove(void)
442 {
443         if(emu) {
444                 emu->suspend();
445         }
446 }
447
448
449
450 #include <string>
451
452 void Ui_MainWindow::OnMainWindowClosed(void)
453 {
454         // notify power off
455         emit sig_notify_power_off();
456         if(statusUpdateTimer != NULL) statusUpdateTimer->stop();
457 #if defined(USE_KEY_LOCKED) || defined(USE_LED_DEVICE)
458         if(ledUpdateTimer != NULL) ledUpdateTimer->stop();
459 #endif
460         emit quit_draw_thread();
461         emit quit_joy_thread();
462         emit quit_emu_thread();
463         emit sig_quit_movie_thread();
464         emit sig_quit_widgets();
465         
466         if(hSaveMovieThread != nullptr) {
467                 // When recording movie, stopping will spend a lot of seconds.
468                 if(!(hSaveMovieThread->wait(60 * 1000))) { // 60 Sec
469                         hSaveMovieThread->terminate();
470                         QThread::msleep(1000);
471                 }
472                 delete hSaveMovieThread;
473                 hSaveMovieThread = NULL;
474         }
475    
476         if(hDrawEmu != nullptr) {
477                 if(!(hDrawEmu->wait(1000))) {
478                         hDrawEmu->terminate();
479                 }
480                 delete hDrawEmu;
481                 hDrawEmu = nullptr;
482         }
483         if(hRunEmu != nullptr) {
484                 OnCloseDebugger();
485                 OSD* op = (OSD*)(emu->get_osd());
486                 if(op != nullptr) {
487                         op->setParent(this);
488                         op->moveToThread(this->thread());
489                 }
490                 hRunEmu->quit();
491                 if(!(hRunEmu->wait(2000))) {
492                         hRunEmu->terminate();
493                         QThread::msleep(100);
494                 }
495                 delete hRunEmu;
496                 hRunEmu = nullptr;
497 #if 0
498                 save_config(create_local_path(_T("%s.ini"), _T(CONFIG_NAME)));
499 #else
500                 {
501                         char tmps[128] = {0};
502                         std::string localstr;
503                         //snprintf(tmps, sizeof(tmps), _T("%s.ini"), _T(CONFIG_NAME));
504                         my_stprintf_s(tmps, sizeof(tmps) - 1, _T("%s.ini"), _T(CONFIG_NAME));
505                         localstr = tmps;
506                         localstr = cpp_confdir + localstr;
507                         save_config(localstr.c_str());
508                 }
509 #endif
510         }
511 #if defined(USE_JOYSTICK)
512         if(hRunJoy != nullptr) {
513                 if(!(hRunJoy->wait(1000))) {
514                         hRunJoy->terminate();
515                 }
516                 delete hRunJoy;
517                 hRunJoy = nullptr;
518         }
519 #endif
520         do_release_emu_resources();
521         hRunEmu = nullptr;
522
523         return;
524 }
525
526 extern "C" {
527
528 void LostFocus(QWidget *widget)
529 {
530         if(emu) {
531                 emu->key_lost_focus();
532         }
533 }
534  
535 }  // extern "C"
536
537 void Ui_MainWindow::do_release_emu_resources(void)
538 {
539         if(emu) {
540                 delete emu;
541                 emu = NULL;
542         }
543 }
544
545 extern void DLL_PREFIX_I get_long_full_path_name(_TCHAR* src, _TCHAR* dst);
546 extern _TCHAR* DLL_PREFIX_I get_parent_dir(_TCHAR* file);
547 extern void get_short_filename(_TCHAR *dst, _TCHAR *file, int maxlen);
548
549 #if defined(Q_OS_CYGWIN)        
550 #include <sys/stat.h>
551 #endif
552 static void my_util_mkdir(std::string n)
553 {
554 #if !defined(Q_OS_CYGWIN)       
555                 QDir dir = QDir::current();
556                 dir.mkdir( QString::fromStdString(n));
557 #else
558                 struct stat st;
559                 if(stat(n.c_str(), &st) != 0) {
560                         _mkdir(n.c_str()); // Not found
561                 }
562 #endif   
563 }       
564
565 static void setup_logs(void)
566 {
567         std::string delim;
568         char    *p;
569
570         my_procname = "emu";
571         my_procname = my_procname + CONFIG_NAME;
572 #if defined(Q_OS_WIN)
573         delim = "\\";
574 #else
575         delim = "/";
576 #endif
577 #if !defined(Q_OS_WIN)
578         p = SDL_getenv("HOME");
579         if(p == NULL) {
580                 p = SDL_getenv("PWD");
581                 if(p == NULL) {
582                         cpp_homedir = ".";
583                 } else {
584                         cpp_homedir = p;
585                 }
586                 std::string tmpstr;
587                 tmpstr = "Warning : Can't get HOME directory...Making conf on " +  cpp_homedir + delim;
588                 perror(tmpstr.c_str());
589         } else {
590                 cpp_homedir = p;
591         }
592 #else
593         cpp_homedir = ".";
594 #endif  
595         cpp_homedir = cpp_homedir + delim;
596
597 #if !defined(CSP_OS_WINDOWS)
598         cpp_confdir = cpp_homedir + ".config" + delim;
599         my_util_mkdir(cpp_confdir);
600 #else
601         cpp_confdir = cpp_homedir;
602 #endif
603
604         cpp_confdir = cpp_confdir + "CommonSourceCodeProject" + delim;
605         my_util_mkdir(cpp_confdir);
606         
607         cpp_confdir = cpp_confdir + my_procname + delim;
608         my_util_mkdir(cpp_confdir);
609    //AG_MkPath(cpp_confdir.c_str());
610    /* Gettext */
611 #ifndef RSSDIR
612 #if defined(_USE_AGAR) || defined(_USE_QT)
613         sRssDir = "/usr/local/share/";
614 #else
615         sRssDir = "." + delim;
616 #endif
617         sRssDir = sRssDir + "CommonSourceCodeProject" + delim + my_procname;
618 #else
619         sRssDir = RSSDIR;
620 #endif
621 }
622
623 QStringList virtualMediaList; // {TYPE, POSITION}
624 QCommandLineOption *_opt_fds[8];
625 QCommandLineOption *_opt_hdds[8];
626 QCommandLineOption *_opt_cmts[2];
627 QCommandLineOption *_opt_lds[2];
628 QCommandLineOption *_opt_cds[2];
629 QCommandLineOption *_opt_binaries[8];
630 QCommandLineOption *_opt_bubbles[8];
631 QCommandLineOption *_opt_qds[8];
632 QCommandLineOption *_opt_carts[8];
633 extern QCommandLineOption *_opt_homedir;
634 extern QCommandLineOption *_opt_cfgfile;
635 extern QCommandLineOption *_opt_cfgdir;
636 extern QCommandLineOption *_opt_resdir;
637 extern QCommandLineOption *_opt_opengl;
638 extern QCommandLineOption *_opt_envver;
639 extern QCommandLineOption *_opt_dump_envver;
640 extern QCommandLineOption *_opt_dipsw_on;
641 extern QCommandLineOption *_opt_dipsw_off;
642 extern QProcessEnvironment _envvers;
643 extern bool _b_dump_envver;
644 extern std::string config_fullpath;
645
646 void SetFDOptions(QCommandLineParser *cmdparser)
647 {
648 #if defined(USE_FLOPPY_DISK)
649         for(int i = 0; i < USE_FLOPPY_DISK; i++) {
650                 QString sfdType1 = QString::fromUtf8("fd%1").arg(i);
651                 QString sfdType2 = QString::fromUtf8("vFd%1").arg(i);
652                 QString sfdType3 = QString::fromUtf8("vFloppyDisk%1").arg(i);
653                 QStringList _cl;
654                 _cl.append(sfdType1);
655                 _cl.append(sfdType2);
656                 _cl.append(sfdType3);
657                 _opt_fds[i] = new QCommandLineOption(_cl,QCoreApplication::translate("main", "Set virtual floppy disk %1.").arg(i) , "[D88_SLOT@]fullpath");
658                 cmdparser->addOption(*_opt_fds[i]);
659                 _cl.clear();
660         }
661 #endif
662 }
663
664 void SetHDDOptions(QCommandLineParser *cmdparser)
665 {
666 #if defined(USE_HARD_DISK)
667         for(int i = 0; i < USE_HARD_DISK; i++) {
668                 QString sfdType1 = QString::fromUtf8("hd%1").arg(i);
669                 QString sfdType2 = QString::fromUtf8("vHd%1").arg(i);
670                 QString sfdType3 = QString::fromUtf8("vHardDisk%1").arg(i);
671                 QString sfdType4 = QString::fromUtf8("vHardDrive%1").arg(i);
672                 QStringList _cl;
673                 _cl.append(sfdType1);
674                 _cl.append(sfdType2);
675                 _cl.append(sfdType3);
676                 _cl.append(sfdType4);
677                 _opt_hdds[i] = new QCommandLineOption(_cl,QCoreApplication::translate("main", "Set virtual hard drive %1.").arg(i) , "[D88_SLOT@]fullpath");
678                 cmdparser->addOption(*_opt_hdds[i]);
679                 _cl.clear();
680         }
681 #endif
682 }
683
684 void SetBinaryOptions(QCommandLineParser *cmdparser)
685 {
686 #if defined(USE_BINARY_FILE)
687         for(int i = 0; i < USE_BINARY_FILE; i++) {
688                 QString sfdType1 = QString::fromUtf8("bin%1").arg(i);
689                 QString sfdType2 = QString::fromUtf8("vBinary%1").arg(i);
690                 QStringList _cl;
691                 _cl.append(sfdType1);
692                 _cl.append(sfdType2);
693                 _opt_binaries[i] = new QCommandLineOption(_cl,QCoreApplication::translate("main", "Set virtual binary image %1.").arg(i) , "fullpath");
694                 cmdparser->addOption(*_opt_binaries[i]);
695                 _cl.clear();
696         }
697 #endif
698 }
699
700 void SetCartOptions(QCommandLineParser *cmdparser)
701 {
702 #if defined(USE_CART)
703         for(int i = 0; i < USE_CART; i++) {
704                 QString sfdType1 = QString::fromUtf8("cart%1").arg(i);
705                 QString sfdType2 = QString::fromUtf8("vCart%1").arg(i);
706                 QString sfdType3 = QString::fromUtf8("vCartridge%1").arg(i);
707                 QStringList _cl;
708                 _cl.append(sfdType1);
709                 _cl.append(sfdType2);
710                 _cl.append(sfdType3);
711                 _opt_carts[i] = new QCommandLineOption(_cl,QCoreApplication::translate("main", "Set virtual cartridge %1 (mostly ROM).").arg(i) , "fullpath");
712                 cmdparser->addOption(*_opt_carts[i]);
713                 _cl.clear();
714         }
715 #endif
716 }
717 void SetBubbleOptions(QCommandLineParser *cmdparser)
718 {
719 #if defined(USE_BUBBLE)
720         for(int i = 0; i < USE_BUBBLE; i++) {
721                 QString sfdType1 = QString::fromUtf8("bub%1").arg(i);
722                 QString sfdType2 = QString::fromUtf8("vBubble%1").arg(i);
723                 QStringList _cl;
724                 _cl.append(sfdType1);
725                 _cl.append(sfdType2);
726                 _opt_bubbles[i] = new QCommandLineOption(_cl,QCoreApplication::translate("main", "Set virtual bubble cartridge %1.").arg(i) , "[B88_SLOT@]fullpath");
727                 cmdparser->addOption(*_opt_bubbles[i]);
728         }
729 #endif
730 }
731
732 void SetLDOptions(QCommandLineParser *cmdparser)
733 {
734 #if defined(USE_LASER_DISC)
735         for(int i = 0; i < USE_LASER_DISC; i++) {
736                 QString sfdType1 = QString::fromUtf8("ld%1").arg(i);
737                 QString sfdType2 = QString::fromUtf8("vLaserDisc%1").arg(i);
738                 QStringList _cl;
739                 _cl.append(sfdType1);
740                 _cl.append(sfdType2);
741                 _opt_lds[i] = new QCommandLineOption(_cl, QCoreApplication::translate("main", "Set virtual laser disc %1 (mostly movie file).").arg(i) , "fullpath");
742                 cmdparser->addOption(*_opt_lds[i]);
743                 _cl.clear();
744         }
745 #endif
746 }
747 void SetCDOptions(QCommandLineParser *cmdparser)
748 {
749 #if defined(USE_COMPACT_DISC)
750         for(int i = 0; i < USE_COMPACT_DISC; i++) {
751                 QString sfdType1 = QString::fromUtf8("cd%1").arg(i);
752                 QString sfdType2 = QString::fromUtf8("vCompactDisc%1").arg(i);
753                 QStringList _cl;
754                 _cl.append(sfdType1);
755                 _cl.append(sfdType2);
756                 _opt_cds[i] = new QCommandLineOption(_cl,QCoreApplication::translate("main", "Set virtual compact disc %1.").arg(i) , "fullpath");
757                 cmdparser->addOption(*_opt_cds[i]);
758                 _cl.clear();
759         }
760 #endif
761 }
762
763 void SetCmtOptions(QCommandLineParser *cmdparser)
764 {
765 #if defined(USE_TAPE)
766         for(int i = 0; i < USE_TAPE; i++) {
767                 QString sfdType1 = QString::fromUtf8("cmt%1").arg(i);
768                 QString sfdType2 = QString::fromUtf8("tape%1").arg(i);
769                 QString sfdType3 = QString::fromUtf8("vCmt%1").arg(i);
770                 QString sfdType4 = QString::fromUtf8("vTape%1").arg(i);
771                 QStringList _cl;
772                 _cl.append(sfdType1);
773                 _cl.append(sfdType2);
774                 _cl.append(sfdType3);
775                 _cl.append(sfdType4);
776                 _opt_cmts[i] = new QCommandLineOption(_cl, QCoreApplication::translate("main", "Set virtual casette tape %1.").arg(i) , "fullpath");
777                 cmdparser->addOption(*_opt_cmts[i]);
778                 _cl.clear();
779         }
780 #endif
781 }
782
783 void SetQuickDiskOptions(QCommandLineParser *cmdparser)
784 {
785 #if defined(USE_QUICK_DISK)
786         for(int i = 0; i < USE_QUICK_DISK; i++) {
787                 QString sfdType1 = QString::fromUtf8("qd%1").arg(i);
788                 QString sfdType2 = QString::fromUtf8("vQuickDisk%1").arg(i);
789
790                 QStringList _cl;
791                 _cl.append(sfdType1);
792                 _cl.append(sfdType2);
793                 _opt_qds[i] = new QCommandLineOption(_cl, QCoreApplication::translate("main", "Set virtual quick disk %1.").arg(i) , "fullpath");
794                 cmdparser->addOption(*_opt_qds[i]);
795                 _cl.clear();
796         }
797 #endif
798 }
799
800
801 void SetProcCmdFD(QCommandLineParser *cmdparser, QStringList *_l)
802 {
803 #if defined(USE_FLOPPY_DISK)
804         for(int i = 0; i < USE_FLOPPY_DISK; i++) {
805                 if(_opt_fds[i] != NULL) {
806                         if(cmdparser->isSet(*_opt_fds[i])) {
807                                 QString sfdType = QString::fromUtf8("vFloppyDisk%1").arg(i);
808                                 QString medianame = cmdparser->value(*_opt_fds[i]);
809                                 _l->append(sfdType);
810                                 _l->append(medianame);
811                         }
812                 }
813         }
814 #endif
815 }
816
817 void SetProcCmdHDD(QCommandLineParser *cmdparser, QStringList *_l)
818 {
819 #if defined(USE_HARD_DISK)
820         for(int i = 0; i < USE_HARD_DISK; i++) {
821                 if(_opt_hdds[i] != NULL) {
822                         if(cmdparser->isSet(*_opt_hdds[i])) {
823                                 QString sfdType = QString::fromUtf8("vHardDisk%1").arg(i);
824                                 QString medianame = cmdparser->value(*_opt_hdds[i]);
825                                 _l->append(sfdType);
826                                 _l->append(medianame);
827                         }
828                 }
829         }
830 #endif
831 }
832
833 void SetProcCmdQuickDisk(QCommandLineParser *cmdparser, QStringList *_l)
834 {
835 #if defined(USE_QUICK_DISK)
836         for(int i = 0; i < USE_QUICK_DISK; i++) {
837                 if(_opt_qds[i] != NULL) {
838                         if(cmdparser->isSet(*_opt_qds[i])) {
839                                 QString sfdType = QString::fromUtf8("vQuickDisk%1").arg(i);
840                                 QString medianame = cmdparser->value(*_opt_qds[i]);
841                                 _l->append(sfdType);
842                                 _l->append(medianame);
843                         }
844                 }
845         }
846 #endif
847 }
848
849 void SetProcCmdCmt(QCommandLineParser *cmdparser, QStringList *_l)
850 {
851 #if defined(USE_TAPE)
852         for(int i = 0; i < USE_TAPE; i++) {
853                 if(_opt_cmts[i] != NULL) {
854                         if(cmdparser->isSet(*_opt_cmts[i])) {
855                                 QString sfdType = QString::fromUtf8("vCmt%1").arg(i);
856                                 QString medianame = cmdparser->value(*_opt_cmts[i]);
857                                 _l->append(sfdType);
858                                 _l->append(medianame);
859                         }
860                 }
861         }
862 #endif
863 }
864
865 void SetProcCmdBinary(QCommandLineParser *cmdparser, QStringList *_l)
866 {
867 #if defined(USE_BINARY_FILE)
868         for(int i = 0; i < USE_BINARY_FILE; i++) {
869                 if(_opt_binaries[i] != NULL) {
870                         if(cmdparser->isSet(*_opt_binaries[i])) {
871                                 QString sfdType = QString::fromUtf8("vBinary%1").arg(i);
872                                 QString medianame = cmdparser->value(*_opt_binaries[i]);
873                                 _l->append(sfdType);
874                                 _l->append(medianame);
875                         }
876                 }
877         }
878 #endif
879 }
880
881 void SetProcCmdBubble(QCommandLineParser *cmdparser, QStringList *_l)
882 {
883 #if defined(USE_BUBBLE)
884         for(int i = 0; i < USE_BUBBLE; i++) {
885                 if(_opt_bubbles[i] != NULL) {
886                         if(cmdparser->isSet(*_opt_bubbles[i])) {
887                                 QString sfdType = QString::fromUtf8("vBubble%1").arg(i);
888                                 QString medianame = cmdparser->value(*_opt_bubbles[i]);
889                                 _l->append(sfdType);
890                                 _l->append(medianame);
891                         }
892                 }
893         }
894 #endif
895 }
896
897 void SetProcCmdCart(QCommandLineParser *cmdparser, QStringList *_l)
898 {
899 #if defined(USE_CART)
900         for(int i = 0; i < USE_CART; i++) {
901                 if(_opt_carts[i] != NULL) {
902                         if(cmdparser->isSet(*_opt_carts[i])) {
903                                 QString sfdType = QString::fromUtf8("vCart%1").arg(i);
904                                 QString medianame = cmdparser->value(*_opt_carts[i]);
905                                 _l->append(sfdType);
906                                 _l->append(medianame);
907                         }
908                 }
909         }
910 #endif
911 }
912
913 void SetProcCmdLD(QCommandLineParser *cmdparser, QStringList *_l)
914 {
915 #if defined(USE_LASER_DISC)
916         for(int i = 0; i < USE_LASER_DISC; i++) {
917                 if(_opt_lds[i] != NULL) {
918                         if(cmdparser->isSet(*_opt_lds[i])) {
919                                 QString sfdType = QString::fromUtf8("vLD%1").arg(i);
920                                 QString medianame = cmdparser->value(*_opt_lds[i]);
921                                 _l->append(sfdType);
922                                 _l->append(medianame);
923                         }
924                 }
925         }
926 #endif
927 }
928
929 void SetProcCmdCD(QCommandLineParser *cmdparser, QStringList *_l)
930 {
931 #if defined(USE_COMPACT_DISC)
932         for(int i = 0; i < USE_COMPACT_DISC; i++) {
933                 if(_opt_cds[i] != NULL) {
934                         if(cmdparser->isSet(*_opt_cds[i])) {
935                                 QString sfdType = QString::fromUtf8("vCD%1").arg(i);
936                                 QString medianame = cmdparser->value(*_opt_cds[i]);
937                                 _l->append(sfdType);
938                                 _l->append(medianame);
939                         }
940                 }
941         }
942 #endif
943 }
944
945 extern void SetOptions_Sub(QCommandLineParser *cmdparser);
946 void SetOptions(QCommandLineParser *cmdparser)
947 {
948         QString emudesc = QString::fromUtf8("Emulator for ");
949         emudesc = emudesc + QString::fromUtf8(DEVICE_NAME);
950     cmdparser->setApplicationDescription(emudesc);
951     cmdparser->addHelpOption();
952     //cmdparser->addVersionOption();
953
954         SetOptions_Sub(cmdparser);
955         QStringList _cl;
956         
957         for(int i = 0; i < 8; i++) {
958                 _opt_fds[i] = NULL;
959                 _opt_hdds[i] = NULL;
960                 _opt_qds[i] = NULL;
961                 _opt_bubbles[i] = NULL;
962                 _opt_binaries[i] = NULL;
963                 _opt_carts[i] = NULL;
964         }
965         for(int i = 0; i < 2; i++) {
966                 _opt_cmts[i] = NULL;
967                 _opt_lds[i] = NULL;
968                 _opt_cds[i] = NULL;
969         }               
970
971         SetFDOptions(cmdparser);
972         SetHDDOptions(cmdparser);
973         //SetBinaryOptions(cmdparser); // Temporally disabled.
974         SetCmtOptions(cmdparser);
975         SetCartOptions(cmdparser);
976         SetBubbleOptions(cmdparser); // Temporally disabled.
977         SetQuickDiskOptions(cmdparser);
978         SetLDOptions(cmdparser); // Temporally disabled.
979         SetCDOptions(cmdparser);
980         
981     cmdparser->addOption(*_opt_envver);
982     cmdparser->addOption(*_opt_dump_envver);
983 }
984
985 extern void ProcessCmdLine_Sub(QCommandLineParser *cmdparser, QStringList *_l);
986
987 void ProcessCmdLine(QCommandLineParser *cmdparser, QStringList *_l)
988 {
989         char homedir[PATH_MAX];
990         std::string delim;
991 #if defined(Q_OS_WIN)
992         delim = "\\";
993 #else
994         delim = "/";
995 #endif
996         ProcessCmdLine_Sub(cmdparser, _l);      
997         {
998                 char tmps[128];
999                 std::string localstr;
1000                 memset(tmps, 0x00, 128);
1001                 if(cmdparser->isSet(*_opt_cfgfile)) {
1002                         strncpy(tmps, cmdparser->value(*_opt_cfgfile).toLocal8Bit().constData(), 127);
1003                 }
1004                 if(strlen(tmps) <= 0){
1005                         my_stprintf_s(tmps, sizeof(tmps) - 1, _T("%s.ini"), _T(CONFIG_NAME));
1006                 }
1007                 localstr = tmps;
1008                 localstr = cpp_confdir + localstr;
1009                 load_config(localstr.c_str());
1010                 config_fullpath = localstr;
1011         }
1012         if(cmdparser->isSet(*_opt_opengl)) {
1013                 char tmps[128] = {0};
1014                 strncpy(tmps, cmdparser->value(*_opt_opengl).toLocal8Bit().constData(), 128 - 1);
1015                 if(strlen(tmps) > 0) {
1016                         QString render = QString::fromLocal8Bit(tmps).toUpper();
1017                         if((render == QString::fromUtf8("GL2")) ||
1018                            (render == QString::fromUtf8("GLV2"))) {
1019                                 config.render_platform = CONFIG_RENDER_PLATFORM_OPENGL_MAIN;
1020                                 config.render_major_version = 2;
1021                                 config.render_minor_version = 0;
1022                         } else if((render == QString::fromUtf8("GL3")) ||
1023                                           (render == QString::fromUtf8("GLV3")) ||
1024                                           (render == QString::fromUtf8("OPENGLV3")) ||
1025                                           (render == QString::fromUtf8("OPENGL")) ||
1026                                           (render == QString::fromUtf8("GL"))) {
1027                                 config.render_platform = CONFIG_RENDER_PLATFORM_OPENGL_MAIN;
1028                                 config.render_major_version = 3;
1029                                 config.render_minor_version = 0;
1030                         } else if((render == QString::fromUtf8("GLES2")) ||
1031                                           (render == QString::fromUtf8("GLESV2")) ||
1032                                           (render == QString::fromUtf8("ESV2")) ||
1033                                           (render == QString::fromUtf8("ES2")) ||
1034                                           (render == QString::fromUtf8("ES")) ||
1035                                           (render == QString::fromUtf8("GLES"))) {
1036                                 config.render_platform = CONFIG_RENDER_PLATFORM_OPENGL_ES;
1037                                 config.render_major_version = 2;
1038                                 config.render_minor_version = 1;
1039                         } else if((render == QString::fromUtf8("GLES3")) ||
1040                                           (render == QString::fromUtf8("GLESV3")) ||
1041                                           (render == QString::fromUtf8("ESV3")) ||
1042                                           (render == QString::fromUtf8("ES3"))) {
1043                                 config.render_platform = CONFIG_RENDER_PLATFORM_OPENGL_ES;
1044                                 config.render_major_version = 3;
1045                                 config.render_minor_version = 1;
1046                         } else if((render == QString::fromUtf8("GL4")) ||
1047                                          (render == QString::fromUtf8("GL43")) ||
1048                                          (render == QString::fromUtf8("GL4.3")) ||
1049                                          (render == QString::fromUtf8("GL4_3")) ||
1050                                          (render == QString::fromUtf8("GL4_CORE"))) {
1051                                 config.render_platform = CONFIG_RENDER_PLATFORM_OPENGL_CORE;
1052                                 config.render_major_version = 4;
1053                                 config.render_minor_version = 3;
1054                         }
1055                 }
1056         }
1057         switch(config.render_platform) {
1058         case CONFIG_RENDER_PLATFORM_OPENGL_MAIN:
1059         case CONFIG_RENDER_PLATFORM_OPENGL_CORE:
1060                 QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL, true);
1061                 QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); // Enable shared contexts.            
1062                 QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, false);
1063                 break;
1064         case CONFIG_RENDER_PLATFORM_OPENGL_ES:
1065                 QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL, false);
1066                 QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); // Enable shared contexts.
1067                 QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true);
1068                 break;
1069         default: // to GLES 2.1 as Default
1070                 QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL, false);
1071                 QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true);
1072                 config.render_platform = CONFIG_RENDER_PLATFORM_OPENGL_ES;
1073                 config.render_major_version = 2;
1074                 config.render_minor_version = 1;
1075                 break;
1076         }
1077
1078         SetProcCmdFD(cmdparser, _l);
1079         SetProcCmdHDD(cmdparser, _l);
1080         SetProcCmdQuickDisk(cmdparser, _l);
1081         SetProcCmdCmt(cmdparser, _l);
1082         SetProcCmdCart(cmdparser, _l);
1083         SetProcCmdBinary(cmdparser, _l);
1084         SetProcCmdBubble(cmdparser, _l);
1085         SetProcCmdLD(cmdparser, _l);
1086         SetProcCmdCD(cmdparser, _l);
1087
1088         uint32_t dipsw_onbits = 0x0000000;
1089         uint32_t dipsw_offmask = 0xffffffff;
1090         if(cmdparser->isSet(*_opt_dipsw_off)) {
1091                 QStringList bitList = cmdparser->values(*_opt_dipsw_off);
1092                 QString tv;
1093                 bool num_ok;
1094                 for(int i = 0; i < bitList.size(); i++) {
1095                         tv = bitList.at(i);
1096                         int _bit = tv.toInt(&num_ok);
1097                         if(num_ok) {
1098                                 if((_bit >= 0) && (_bit < 32)) {
1099                                         dipsw_offmask &= (uint32_t)(~(1 << _bit));
1100                                 }
1101                         }
1102                 }
1103         }
1104         if(cmdparser->isSet(*_opt_dipsw_on)) {
1105                 QStringList bitList = cmdparser->values(*_opt_dipsw_on);
1106                 QString tv;
1107                 bool num_ok;
1108                 for(int i = 0; i < bitList.size(); i++) {
1109                         tv = bitList.at(i);
1110                         int _bit = tv.toInt(&num_ok);
1111                         if(num_ok) {
1112                                 if((_bit >= 0) && (_bit < 32)) {
1113                                         dipsw_onbits |= (uint32_t)(1 << _bit);
1114                                 }
1115                         }
1116                 }
1117         }
1118         config.dipswitch &= dipsw_offmask;
1119         config.dipswitch |= dipsw_onbits;
1120 }
1121
1122 void OpeningMessage(std::shared_ptr<CSP_Logger>p_logger, std::string archstr)
1123 {
1124         p_logger->set_emu_vm_name(DEVICE_NAME); // Write to syslog, console
1125         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Start Common Source Project '%s'", my_procname.c_str());
1126         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "(C) Toshiya Takeda / Qt Version K.Ohta");
1127         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Architecture: %s", archstr.c_str());
1128         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Use -h or --help for help.");
1129         
1130         //p_logger->debug_log(AGAR_LOG_INFO, " -? is print help(s).");
1131         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Home = %s, Resource directory = %s",
1132                                                   cpp_homedir.c_str(),
1133                                                   sRssDir.c_str()); // Debug
1134         
1135         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Config dir = %s, config_file = %s",
1136                                                   cpp_confdir.c_str(),
1137                                                   config_fullpath.c_str()); // Debug
1138         
1139         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "DIPSW VALUE IS 0x%08x", config.dipswitch);
1140         if(virtualMediaList.size() >= 2) {
1141                 for(int i = 0; i < virtualMediaList.size(); i += 2) {
1142                         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Virtual media %d, type %s, name %s",
1143                                                                   i / 2,
1144                                                                   virtualMediaList.at(i).toLocal8Bit().constData(),
1145                                                                   virtualMediaList.at(i + 1).toLocal8Bit().constData());
1146                 }
1147         }
1148 }
1149
1150 void SetupSDL(std::shared_ptr<CSP_Logger>p_logger)
1151 {
1152         QStringList _el = _envvers.toStringList();
1153
1154         if(_el.size() > 0) {
1155                 for(int i = 0; i < _el.size(); i++) {
1156                         QString _s = _el.at(i);
1157                         if(_s.startsWith("SDL_")) {
1158                                 QString skey, svar;
1159                                 int _nl;
1160                                 _nl = _s.indexOf('=');
1161                                 if(_nl >= 0) {
1162                                         skey = _s.left(_nl);
1163                                         svar = _s.right(_s.length() - (_nl + 1));
1164                                 } else {
1165                                         skey = _s;
1166                                         svar = QString::fromUtf8("");
1167                                 }
1168                                 SDL_setenv(skey.toLocal8Bit().constData(), svar.toLocal8Bit().constData(), 1);
1169                                 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Note: SDL ENVIROMENT : %s to %s.",
1170                                                                           skey.toLocal8Bit().constData(),
1171                                                                           svar.toLocal8Bit().constData());
1172                         }
1173                 }
1174         }
1175 #if defined(USE_SDL2)
1176         //SDL_Init(SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK);
1177         SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK);
1178         //SDL_Init(SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS);
1179 #else
1180         SDL_Init(SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_VIDEO);
1181 #endif
1182         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Audio subsystem was initialised.");
1183 }
1184
1185 extern void DLL_PREFIX_I set_debug_logger(std::shared_ptr<CSP_Logger> p);
1186
1187 void SetupLogger(std::shared_ptr<CSP_Logger> csp_logger, QObject *parent, std::string emustr, int _size)
1188 {
1189
1190         csp_logger->set_emu_vm_name((const char *)(emustr.c_str()));
1191         csp_logger->set_log_stdout(CSP_LOG_DEBUG, true);
1192         csp_logger->set_log_stdout(CSP_LOG_INFO, true);
1193         csp_logger->set_log_stdout(CSP_LOG_WARN, true);
1194         
1195         csp_logger->set_state_log(0, config.state_log_to_recording);
1196         csp_logger->set_state_log(1, config.state_log_to_syslog);
1197         csp_logger->set_state_log(2, config.state_log_to_console);
1198         
1199         for(int ii = 0; ii < _size; ii++) {
1200                 for(int jj = 0; jj < 8; jj++) {
1201                         csp_logger->set_device_node_log(ii, 1, jj, config.dev_log_to_syslog[ii][jj]);
1202                         csp_logger->set_device_node_log(ii, 2, jj, config.dev_log_to_console[ii][jj]);
1203                         csp_logger->set_device_node_log(ii, 0, jj, config.dev_log_recording[ii][jj]);
1204                 }
1205         }
1206 }
1207
1208 int MainLoop(int argc, char *argv[])
1209 {
1210
1211         std::string archstr;
1212         std::string emustr("emu");
1213         std::string cfgstr(CONFIG_NAME);
1214         std::string delim;
1215         QString emudesc;
1216         setup_logs();
1217
1218 #if defined(Q_OS_WIN)
1219         delim = "\\";
1220 #else
1221         delim = "/";
1222 #endif
1223         
1224         QApplication *GuiMain = NULL;
1225         GuiMain = new QApplication(argc, argv);
1226         GuiMain->setObjectName(QString::fromUtf8("Gui_Main"));
1227     QCommandLineParser cmdparser;
1228
1229         virtualMediaList.clear();
1230         SetOptions(&cmdparser);
1231
1232         QStringList arglist;
1233         if(argv != NULL) {
1234                 for(int i = 0; i < argc; i++) {
1235                         if(argv[i] != NULL) {
1236                                 arglist.append(QString::fromLocal8Bit(argv[i]));
1237                         }
1238                 }
1239         }
1240         archstr = "Generic";
1241 #if defined(__x86_64__)
1242         archstr = "amd64";
1243 #endif
1244 #if defined(__i386__)
1245         archstr = "ia32";
1246 #endif
1247         emustr = emustr + cfgstr;
1248         std::shared_ptr<USING_FLAGS> using_flags = std::shared_ptr<USING_FLAGS>(new USING_FLAGS_EXT(&config));
1249         cmdparser.process(arglist);
1250         ProcessCmdLine(&cmdparser, &virtualMediaList);
1251
1252         _envvers = QProcessEnvironment::systemEnvironment();
1253
1254         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()));
1255         set_debug_logger(p_logger);     
1256         SetupLogger(p_logger, GuiMain, emustr, CSP_LOG_TYPE_VM_DEVICE_END - CSP_LOG_TYPE_VM_DEVICE_0 + 1);
1257         OpeningMessage(p_logger, archstr);
1258         SetupSDL(p_logger);
1259
1260
1261         /*
1262          * Into Qt's Loop.
1263          */
1264
1265         //SetupTranslators();
1266         QTranslator local_translator;
1267         QLocale s_locale = QLocale::system();
1268
1269         if(local_translator.load(s_locale, "machine", ".", ":/", ".qm")) {
1270                 GuiMain->installTranslator(&local_translator);
1271         }
1272         QTranslator s_translator;
1273         if(s_translator.load(s_locale, "gui", ".", ":/", ".qm")) {
1274                 GuiMain->installTranslator(&s_translator);
1275         }
1276
1277         QTranslator common_translator;
1278         if(common_translator.load(s_locale, "common", ".", ":/", ".qm")) {
1279                 GuiMain->installTranslator(&common_translator);
1280         }
1281         QTranslator debugger_translator;
1282         if(debugger_translator.load(s_locale, "debugger", ".", ":/", ".qm")) {
1283                 GuiMain->installTranslator(&debugger_translator);
1284         }
1285         //QProcessEnvironment::systemEnvironment() = _envvers;
1286         if(_b_dump_envver) {
1287                 //QProcessEnvironment ev = QProcessEnvironment::systemEnvironment();
1288                 QProcessEnvironment ev = _envvers;
1289                 QStringList el = _envvers.toStringList();
1290                 if(el.size() > 0) {
1291                         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "Environment Variables:");
1292                         for(int i = 0; i < el.size(); i++) {
1293                                 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "#%d : %s", i, el.at(i).toLocal8Bit().constData());
1294                         }
1295                 }
1296         }
1297         
1298 //      USING_FLAGS_EXT *using_flags = new USING_FLAGS_EXT(&config);
1299         // initialize emulation core
1300         rMainWindow = new META_MainWindow(using_flags, p_logger);
1301         rMainWindow->connect(rMainWindow, SIGNAL(sig_quit_all(void)), rMainWindow, SLOT(deleteLater(void)));
1302         rMainWindow->setCoreApplication(GuiMain);
1303         rMainWindow->getWindow()->show();
1304         rMainWindow->retranselateUi_Depended_OSD();
1305 //      QMetaObject::connectSlotsByName(rMainWindow);
1306         EmuThreadClass *hRunEmu_Real = new EmuThreadClass(rMainWindow, using_flags);
1307         OSD_BASE* p_osd = hRunEmu_Real->get_emu()->get_osd();
1308         
1309         QObject::connect((OSD*)p_osd, SIGNAL(sig_update_device_node_name(int, const _TCHAR *)),
1310                                          rMainWindow, SLOT(do_update_device_node_name(int, const _TCHAR *)));
1311         for(int i = 0; i < (CSP_LOG_TYPE_VM_DEVICE_END - CSP_LOG_TYPE_VM_DEVICE_0 + 1); i++) {
1312                 rMainWindow->do_update_device_node_name(i, using_flags->get_vm_node_name(i));
1313         }
1314         p_logger->set_osd((OSD*)p_osd);
1315         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "InitInstance() OK.");
1316         
1317         // ToDo: Update raltime.
1318         rMainWindow->connect(rMainWindow, SIGNAL(sig_osd_sound_output_device(QString)), (OSD*)p_osd, SLOT(do_set_host_sound_output_device(QString)));
1319         rMainWindow->do_update_sound_output_list();
1320
1321         QObject::connect((OSD*)p_osd, SIGNAL(sig_update_sound_output_list()), rMainWindow, SLOT(do_update_sound_output_list()));
1322         QObject::connect((OSD*)p_osd, SIGNAL(sig_clear_sound_output_list()), rMainWindow, SLOT(do_clear_sound_output_list()));
1323         QObject::connect((OSD*)p_osd, SIGNAL(sig_append_sound_output_list(QString)), rMainWindow, SLOT(do_append_sound_output_list(QString)));
1324                                          
1325         QObject::connect(rMainWindow, SIGNAL(sig_update_master_volume(int)), (OSD*)p_osd, SLOT(do_update_master_volume(int)));
1326         
1327         QObject::connect(GuiMain, SIGNAL(lastWindowClosed()),
1328                                          rMainWindow, SLOT(on_actionExit_triggered()));
1329
1330         QObject::connect((OSD*)p_osd, SIGNAL(sig_clear_keyname_table()),         rMainWindow, SLOT(do_clear_keyname_table()));
1331         QObject::connect((OSD*)p_osd, SIGNAL(sig_add_keyname_table(uint32_t, QString)),  rMainWindow, SLOT(do_add_keyname_table(uint32_t, QString)));
1332         p_osd->update_keyname_table();
1333
1334         QObject::connect(rMainWindow, SIGNAL(sig_notify_power_off()), hRunEmu_Real, SLOT(do_notify_power_off()), Qt::QueuedConnection);
1335
1336         GLDrawClass *pgl = rMainWindow->getGraphicsView();
1337         pgl->do_set_texture_size(NULL, -1, -1);  // It's very ugly workaround (;_;) 20191028 K.Ohta
1338 //      pgl->setFixedSize(pgl->width(), pgl->height());
1339         // main loop
1340         rMainWindow->LaunchEmuThread(hRunEmu_Real);
1341         
1342 #if defined(USE_JOYSTICK)
1343         rMainWindow->LaunchJoyThread();
1344 #endif
1345         rMainWindow->do_start_emu_thread();
1346         rMainWindow->do_unblock_task();
1347         rMainWindow->do_start_draw_thread();
1348         GuiMain->exec();
1349         return 0;
1350 }
1351
1352 void Ui_MainWindow::do_update_inner_fd(int drv, QStringList base, class Action_Control **action_select_media_list,
1353                                        QStringList lst, int num, bool use_d88_menus)
1354 {
1355 #if defined(USE_FLOPPY_DISK)
1356         if(use_d88_menus) {
1357                 for(int ii = 0; ii < using_flags->get_max_d88_banks(); ii++) {
1358                         if(ii < emu->d88_file[drv].bank_num) {
1359                                 base << lst.value(ii);
1360                                 action_select_media_list[ii]->setText(lst.value(ii));
1361                                 action_select_media_list[ii]->setVisible(true);
1362                                 if(ii == num) action_select_media_list[ii]->setChecked(true);
1363                         } else {
1364                                 if(action_select_media_list[ii] != NULL) {
1365                                         action_select_media_list[ii]->setText(QString::fromUtf8(""));
1366                                         action_select_media_list[ii]->setVisible(false);
1367                                 }
1368                         }
1369                 }
1370         }
1371 #endif  
1372 }
1373
1374 void Ui_MainWindow::do_update_inner_bubble(int drv, QStringList base, class Action_Control **action_select_media_list,
1375                                        QStringList lst, int num, bool use_d88_menus)
1376 {
1377 #if defined(USE_BUBBLE) 
1378         if(use_d88_menus) {
1379                 for(int ii = 0; ii < using_flags->get_max_b77_banks(); ii++) {
1380                         if(ii < emu->b77_file[drv].bank_num) {
1381                                 base << lst.value(ii);
1382                                 action_select_media_list[ii]->setText(lst.value(ii));
1383                                 action_select_media_list[ii]->setVisible(true);
1384                                 if(ii == num) action_select_media_list[ii]->setChecked(true);
1385                         } else {
1386                                 if(action_select_media_list[ii] != NULL) {
1387                                         action_select_media_list[ii]->setText(QString::fromUtf8(""));
1388                                         action_select_media_list[ii]->setVisible(false);
1389                                 }
1390                         }
1391                 }
1392         }
1393 #endif  
1394 }
1395
1396 int Ui_MainWindow::GetBubbleBankNum(int drv)
1397 {
1398 #if MAX_BUBBLE
1399         if((emu != NULL) && (drv >= 0) && (drv < MAX_BUBBLE)) {
1400                 return emu->b77_file[drv].bank_num;
1401         }
1402 #endif
1403         return 0;
1404 }
1405
1406 int Ui_MainWindow::GetBubbleCurrentBankNum(int drv)
1407 {
1408 #if MAX_BUBBLE
1409         if((emu != NULL) && (drv >= 0) && (drv < MAX_BUBBLE)) {
1410                 return emu->b77_file[drv].cur_bank;
1411         }
1412 #endif
1413         return 0;
1414 }
1415
1416 bool Ui_MainWindow::GetBubbleCasetteIsProtected(int drv)
1417 {
1418 #if MAX_BUBBLE
1419         if(emu != NULL) {
1420                 if((drv >= 0) && (drv < MAX_BUBBLE)) {
1421                         return emu->is_bubble_casette_protected(drv);
1422                 }
1423         }
1424 #endif
1425         return false;
1426 }
1427
1428 QString Ui_MainWindow::GetBubbleB77FileName(int drv)
1429 {
1430         QString ans = QString::fromUtf8("");
1431 #if MAX_BUBBLE
1432         if(emu != NULL) {
1433                 if((drv < MAX_BUBBLE) && (drv >= 0)) {
1434                         ans = QString::fromLocal8Bit(emu->b77_file[drv].path);
1435                 }
1436         }
1437 #endif
1438         return ans;
1439 }
1440
1441 QString Ui_MainWindow::GetBubbleB77BubbleName(int drv, int num)
1442 {
1443         QString ans = QString::fromUtf8("");
1444 #if MAX_BUBBLE
1445         if(emu != NULL) {
1446                 if((drv < MAX_BUBBLE) && (drv >= 0)) {
1447                         if((num >= 0) && (num < MAX_B77_BANKS)) {
1448                                 ans = QString::fromLocal8Bit(emu->b77_file[drv].bubble_name[num]);
1449                         }
1450                 }
1451         }
1452 #endif
1453         return ans;
1454 }
1455
1456 #ifdef USE_DEBUGGER
1457 #include <../debugger/qt_debugger.h>
1458
1459 void Ui_MainWindow::OnOpenDebugger()
1460 {
1461         QAction *cp = qobject_cast<QAction*>(QObject::sender());
1462         if(cp == nullptr) return;
1463         int no = cp->data().value<int>();
1464
1465         if((no < 0) || (no >= MAX_CPU)) return;
1466         //emu->open_debugger(no);
1467         VM *vm = static_cast<VM*>(emu->get_vm());
1468
1469         // ToDo: Multiple debugger 20221105 K.O
1470         if((emu->now_debugging ) || (emu->hDebugger.get() != nullptr)) /* OnCloseDebugger(); */ return;
1471         
1472         if(!(emu->now_debugging && emu->debugger_thread_param.cpu_index == no)) {
1473                 //emu->close_debugger();
1474                 if(vm->get_cpu(no) != NULL && vm->get_cpu(no)->get_debugger() != NULL) {
1475                         QString windowName = QString::fromUtf8(vm->get_cpu(no)->get_device_name());
1476                         windowName = QString::fromUtf8("Debugger ") + windowName;
1477                         emu->hDebugger.reset(new CSP_Debugger(emu, this));
1478                         if(emu->hDebugger.get() == nullptr) {
1479                                 return;
1480                         }
1481                         QString objNameStr = QString("EmuDebugThread");
1482                         emu->hDebugger->setObjectName(objNameStr);
1483                         
1484                         emu->hDebugger->debugger_thread_param.osd = (OSD_BASE *)(emu->get_osd());
1485                         emu->hDebugger->debugger_thread_param.emu = emu;
1486                         emu->hDebugger->debugger_thread_param.vm = vm;
1487                         emu->hDebugger->debugger_thread_param.cpu_index = no;
1488                         emu->hDebugger->debugger_thread_param.running = false;
1489                         emu->hDebugger->debugger_thread_param.request_terminate = false;
1490                         
1491                         emu->stop_record_sound();
1492                         emu->stop_record_video();
1493                         //emu->now_debugging = true;
1494                         connect(this, SIGNAL(quit_debugger_thread()), emu->hDebugger.get(), SLOT(doExit()));
1495                         connect(this, SIGNAL(destroyed()), emu->hDebugger.get(), SLOT(do_destroy_thread()));
1496                         //connect(this, SIGNAL(quit_debugger_thread()), emu->hDebugger, SLOT(close()));
1497                         connect(emu->hDebugger.get(), SIGNAL(sig_finished()), this, SLOT(OnCloseDebugger()));
1498                         connect(emu->hDebugger.get(), SIGNAL(sig_put_string(QString)), emu->hDebugger.get(), SLOT(put_string(QString)));
1499                         emu->hDebugger->show();
1500                         emu->hDebugger->run();
1501                         emu->hDebugger->setWindowTitle(windowName);
1502                 }
1503         }
1504 }
1505
1506 void Ui_MainWindow::OnCloseDebugger(void )
1507 {
1508         if(emu == nullptr) {
1509                 return;
1510         }
1511 //      emu->close_debugger();
1512         // ToDo: Multiple debugger 20221105 K.O
1513         if((emu->now_debugging) && (emu->hDebugger.get() != nullptr)) {
1514                 if(emu->hDebugger->debugger_thread_param.running) {
1515                         emit quit_debugger_thread();
1516                         //if(!(emu->hDebugger->wait(2000))) {
1517                         //      emu->hDebugger->terminate();
1518                         //      QThread::msleep(100);
1519                         //}
1520                 }
1521         }
1522         emu->hDebugger.reset();
1523         emu->now_debugging = false;
1524 }
1525 #endif
1526
1527 QString Ui_MainWindow::get_system_version()
1528 {
1529         QString guiver = get_gui_version();
1530         QString aviover;
1531         QString vm_gitver;
1532         QString common_vmver;
1533         QString osdver;
1534         QString libcommon_ver;
1535         QString libfmgen_ver;
1536         QString build_date;
1537         
1538         QString outstr;
1539         
1540         aviover.clear();
1541         common_vmver.clear();
1542         vm_gitver.clear();
1543         osdver.clear();
1544         libcommon_ver.clear();
1545         
1546         if(hSaveMovieThread != NULL) {
1547                 aviover = hSaveMovieThread->get_avio_version();
1548         }
1549         if(emu != NULL) {
1550                 if(emu->get_osd() != NULL) {
1551                         _TCHAR *cvp = (_TCHAR *)emu->get_osd()->get_lib_common_vm_version();
1552                         _TCHAR *gvp = (_TCHAR *)emu->get_osd()->get_lib_common_vm_git_version();
1553                         _TCHAR *ovp = (_TCHAR *)emu->get_osd()->get_lib_osd_version();
1554                         if(cvp != NULL) {
1555                                 common_vmver = QString::fromUtf8(cvp);
1556                         }
1557                         if(gvp != NULL) {
1558                                 vm_gitver = QString::fromUtf8(gvp);
1559                         }
1560                         if(ovp != NULL) {
1561                                 osdver = QString::fromUtf8(ovp);
1562                         }
1563                 }
1564         }
1565         
1566         const _TCHAR *pp = get_lib_common_version();
1567         if(pp != NULL) {
1568                 libcommon_ver = QString::fromUtf8(pp);
1569         }
1570         libfmgen_ver = QString::fromUtf8(FM::get_libfmgen_version());
1571         
1572         outstr.clear();
1573         outstr.append(QString::fromUtf8("<FONT SIZE=+1>"));
1574         if(!(common_vmver.isEmpty())) {
1575                 outstr.append(common_vmver);
1576                 outstr.append("<BR>\n");
1577         }
1578         if(!(libcommon_ver.isEmpty())) {
1579                 outstr.append(libcommon_ver);
1580                 outstr.append("<BR>\n");
1581         }
1582         if(!(osdver.isEmpty())) {
1583                 outstr.append(osdver);
1584                 outstr.append("<BR>\n");
1585         }
1586         if(!(libfmgen_ver.isEmpty())) {
1587                 outstr.append(libfmgen_ver);
1588                 outstr.append("<BR>\n");
1589         }
1590         if(!(osdver.isEmpty())) {
1591                 outstr.append(osdver);
1592                 outstr.append("<BR>\n");
1593         }
1594         if(!(guiver.isEmpty())) {
1595                 outstr.append(guiver);
1596                 outstr.append("<BR>\n");
1597         }
1598         if(!(aviover.isEmpty())) {
1599                 outstr.append(aviover);
1600                 outstr.append("<BR>\n");
1601         }
1602         outstr.append(QString::fromUtf8("</FONT>"));
1603         if(!(vm_gitver.isEmpty())) {
1604                 outstr.append("Build Version: ");
1605                 outstr.append(vm_gitver);
1606                 outstr.append("<BR>\n");
1607         }
1608         return outstr;
1609 }
1610
1611 QString Ui_MainWindow::get_build_date()
1612 {
1613 #if defined(__BUILD_DATE)
1614         return QString::fromUtf8(__BUILD_DATE);
1615 #else
1616         return QString::fromUtf8("");
1617 #endif
1618 }