2 Skelton for retropc emulator
3 Author : Takeda.Toshiya
4 Port to Qt : K.Ohta <whatisthis.sowhat _at_ gmail.com>
7 [ win32 main ] -> [ agar main ]
16 #include <QImageReader>
22 #include "menuclasses.h"
23 #include "mainwidget.h"
24 #include "commonclasses.h"
26 #include "emu_thread.h"
27 #include "joy_thread.h"
28 #include "draw_thread.h"
30 #include "qt_gldraw.h"
31 #include "agar_logger.h"
33 #include "menu_disk.h"
34 #include "menu_bubble.h"
35 #include "menu_flags.h"
39 QApplication *GuiMain = NULL;
40 extern USING_FLAGS *using_flags;
42 // Start to define MainWindow.
43 class META_MainWindow *rMainWindow;
47 #define MAX_FONT_SIZE 32
51 std::string cpp_homedir;
52 std::string cpp_confdir;
53 std::string my_procname;
55 bool now_menuloop = false;
56 static int close_notified = 0;
60 unsigned int desktop_width;
61 unsigned int desktop_height;
63 int prev_window_mode = 0;
64 bool now_fullscreen = false;
66 int window_mode_count;
68 void Ui_MainWindow::do_set_mouse_enable(bool flag)
71 if(emu == NULL) return;
74 graphicsView->grabMouse();
77 graphicsView->releaseMouse();
84 void Ui_MainWindow::do_toggle_mouse(void)
87 if(emu == NULL) return;
89 bool flag = emu->is_mouse_enabled();
91 graphicsView->grabMouse();
94 graphicsView->releaseMouse();
101 void Ui_MainWindow::LaunchEmuThread(void)
104 GLDrawClass *glv = this->getGraphicsView();
108 hRunEmu = new EmuThreadClass(rMainWindow, emu, this);
109 connect(hRunEmu, SIGNAL(message_changed(QString)), this, SLOT(message_status_bar(QString)));
110 connect(hRunEmu, SIGNAL(sig_is_enable_mouse(bool)), glv, SLOT(do_set_mouse_enabled(bool)));
111 connect(glv, SIGNAL(sig_key_down(uint32_t, uint32_t, bool)), hRunEmu, SLOT(do_key_down(uint32_t, uint32_t, bool)));
112 connect(glv, SIGNAL(sig_key_up(uint32_t, uint32_t)), hRunEmu, SLOT(do_key_up(uint32_t, uint32_t)));
114 //connect(hRunEmu, SIGNAL(sig_finished()), this, SLOT(delete_emu_thread()));
115 connect(this, SIGNAL(sig_vm_reset()), hRunEmu, SLOT(doReset()));
116 connect(this, SIGNAL(sig_vm_specialreset()), hRunEmu, SLOT(doSpecialReset()));
117 connect(this, SIGNAL(sig_vm_loadstate()), hRunEmu, SLOT(doLoadState()));
118 connect(this, SIGNAL(sig_vm_savestate()), hRunEmu, SLOT(doSaveState()));
120 connect(this, SIGNAL(sig_emu_update_config()), hRunEmu, SLOT(doUpdateConfig()));
121 connect(this, SIGNAL(sig_emu_update_volume_level(int, int)), hRunEmu, SLOT(doUpdateVolumeLevel(int, int)));
122 connect(this, SIGNAL(sig_emu_update_volume_balance(int, int)), hRunEmu, SLOT(doUpdateVolumeBalance(int, int)));
123 connect(this, SIGNAL(sig_emu_start_rec_sound()), hRunEmu, SLOT(doStartRecordSound()));
124 connect(this, SIGNAL(sig_emu_stop_rec_sound()), hRunEmu, SLOT(doStopRecordSound()));
125 connect(this, SIGNAL(sig_emu_set_display_size(int, int, int, int)), hRunEmu, SLOT(doSetDisplaySize(int, int, int, int)));
128 #if defined(USE_FD1) || defined(USE_FD2) || defined(USE_FD3) || defined(USE_FD4) || \
129 defined(USE_FD5) || defined(USE_FD6) || defined(USE_FD7) || defined(USE_FD8)
130 connect(this, SIGNAL(sig_write_protect_disk(int, bool)), hRunEmu, SLOT(do_write_protect_disk(int, bool)));
131 connect(this, SIGNAL(sig_open_disk(int, QString, int)), hRunEmu, SLOT(do_open_disk(int, QString, int)));
132 connect(this, SIGNAL(sig_close_disk(int)), hRunEmu, SLOT(do_close_disk(int)));
133 connect(hRunEmu, SIGNAL(sig_update_recent_disk(int)), this, SLOT(do_update_recent_disk(int)));
134 connect(hRunEmu, SIGNAL(sig_change_osd_fd(int, QString)), this, SLOT(do_change_osd_fd(int, QString)));
136 # if defined(USE_FD1)
139 # if defined(USE_FD2)
142 # if defined(USE_FD3)
145 # if defined(USE_FD4)
148 # if defined(USE_FD5)
151 # if defined(USE_FD6)
154 # if defined(USE_FD7)
157 # if defined(USE_FD8)
160 for(int ii = 0; ii < drvs; ii++) {
161 menu_fds[ii]->setEmu(emu);
164 #if defined(USE_TAPE)
165 connect(this, SIGNAL(sig_play_tape(QString)), hRunEmu, SLOT(do_play_tape(QString)));
166 connect(this, SIGNAL(sig_rec_tape(QString)), hRunEmu, SLOT(do_rec_tape(QString)));
167 connect(this, SIGNAL(sig_close_tape(void)), hRunEmu, SLOT(do_close_tape(void)));
168 connect(hRunEmu, SIGNAL(sig_change_osd_cmt(QString)), this, SLOT(do_change_osd_cmt(QString)));
169 # if defined(USE_TAPE_BUTTON)
170 connect(this, SIGNAL(sig_cmt_push_play(void)), hRunEmu, SLOT(do_cmt_push_play(void)));
171 connect(this, SIGNAL(sig_cmt_push_stop(void)), hRunEmu, SLOT(do_cmt_push_stop(void)));
172 connect(this, SIGNAL(sig_cmt_push_fast_forward(void)), hRunEmu, SLOT(do_cmt_push_fast_forward(void)));
173 connect(this, SIGNAL(sig_cmt_push_fast_rewind(void)), hRunEmu, SLOT(do_cmt_push_fast_rewind(void)));
174 connect(this, SIGNAL(sig_cmt_push_apss_forward(void)), hRunEmu, SLOT(do_cmt_push_apss_forward(void)));
175 connect(this, SIGNAL(sig_cmt_push_apss_rewind(void)), hRunEmu, SLOT(do_cmt_push_apss_rewind(void)));
179 connect(this, SIGNAL(sig_write_protect_quickdisk(int, bool)), hRunEmu, SLOT(do_write_protect_quickdisk(int, bool)));
180 connect(this, SIGNAL(sig_open_quickdisk(int, QString)), hRunEmu, SLOT(do_open_quickdisk(int, QString)));
181 connect(this, SIGNAL(sig_close_quickdisk(int)), hRunEmu, SLOT(do_close_quickdisk(int)));
182 connect(hRunEmu, SIGNAL(sig_change_osd_qd(int, QString)), this, SLOT(do_change_osd_qd(int, QString)));
184 #if defined(USE_CART1)
185 connect(this, SIGNAL(sig_open_cart(int, QString)), hRunEmu, SLOT(do_open_cart(int, QString)));
186 connect(this, SIGNAL(sig_close_cart(int)), hRunEmu, SLOT(do_close_cart(int)));
188 #if defined(USE_COMPACT_DISC)
189 connect(this, SIGNAL(sig_open_cdrom(QString)), hRunEmu, SLOT(do_open_cdrom(QString)));
190 connect(this, SIGNAL(sig_close_cdrom()), hRunEmu, SLOT(do_eject_cdrom()));
191 connect(hRunEmu, SIGNAL(sig_change_osd_cdrom(QString)), this, SLOT(do_change_osd_cdrom(QString)));
193 #if defined(USE_LASER_DISK)
194 connect(this, SIGNAL(sig_open_laser_disk(QString)), hRunEmu, SLOT(do_open_laser_disk(QString)));
195 connect(this, SIGNAL(sig_close_laser_disk(void)), hRunEmu, SLOT(do_close_laser_disk(void)));
197 #if defined(USE_BINARY_FILE1)
198 connect(this, SIGNAL(sig_load_binary(int, QString)), hRunEmu, SLOT(do_load_binary(int, QString)));
199 connect(this, SIGNAL(sig_save_binary(int, QString)), hRunEmu, SLOT(do_save_binary(int, QString)));
201 #if defined(USE_BUBBLE1)
202 connect(this, SIGNAL(sig_write_protect_bubble(int, bool)), hRunEmu, SLOT(do_write_protect_bubble_casette(int, bool)));
203 connect(this, SIGNAL(sig_open_bubble(int, QString, int)), hRunEmu, SLOT(do_open_bubble_casette(int, QString, int)));
204 connect(this, SIGNAL(sig_close_bubble(int)), hRunEmu, SLOT(do_close_bubble_casette(int)));
205 connect(hRunEmu, SIGNAL(sig_update_recent_bubble(int)), this, SLOT(do_update_recent_bubble(int)));
206 connect(hRunEmu, SIGNAL(sig_change_osd_bubble(int, QString)), this, SLOT(do_change_osd_bubble(int, QString)));
208 # if defined(USE_BUBBLE1)
211 # if defined(USE_BUBBLE2)
214 for(int ii = 0; ii < drvs; ii++) {
215 menu_bubbles[ii]->setEmu(emu);
219 connect(this, SIGNAL(quit_emu_thread()), hRunEmu, SLOT(doExit()));
220 connect(hRunEmu, SIGNAL(sig_mouse_enable(bool)),
221 this, SLOT(do_set_mouse_enable(bool)));
222 #ifdef USE_TAPE_BUTTON
223 hRunEmu->set_tape_play(false);
225 #ifdef USE_LED_DEVICE
226 connect(hRunEmu, SIGNAL(sig_send_data_led(quint32)), this, SLOT(do_recv_data_led(quint32)));
229 connect(this, SIGNAL(sig_start_auto_key(QString)), hRunEmu, SLOT(do_start_auto_key(QString)));
230 connect(this, SIGNAL(sig_stop_auto_key()), hRunEmu, SLOT(do_stop_auto_key()));
232 //connect(actionExit_Emulator, SIGNAL(triggered()), hRunEmu, SLOT(doExit()));
233 AGAR_DebugLog(AGAR_LOG_DEBUG, "EmuThread : Start.");
234 objNameStr = QString("EmuThreadClass");
235 hRunEmu->setObjectName(objNameStr);
237 hDrawEmu = new DrawThreadClass(emu, emu->get_osd(), this);
238 emu->set_parent_handler(hRunEmu, hDrawEmu);
240 #ifdef ONE_BOARD_MICRO_COMPUTER
241 QImageReader *reader = new QImageReader(":/background.png");
242 QImage *result = new QImage(reader->read()); // this acts as a default if the size is not matched
243 glv->updateBitmap(result);
247 AGAR_DebugLog(AGAR_LOG_DEBUG, "DrawThread : Start.");
248 connect(hDrawEmu, SIGNAL(sig_draw_frames(int)), hRunEmu, SLOT(print_framerate(int)));
249 connect(hRunEmu, SIGNAL(window_title_changed(QString)), this, SLOT(do_set_window_title(QString)));
250 connect(hDrawEmu, SIGNAL(message_changed(QString)), this, SLOT(message_status_bar(QString)));
251 connect(actionCapture_Screen, SIGNAL(triggered()), glv, SLOT(do_save_frame_screen()));
253 connect(hRunEmu, SIGNAL(sig_draw_thread(bool)), hDrawEmu, SLOT(doDraw(bool)));
254 //connect(hRunEmu, SIGNAL(quit_draw_thread()), hDrawEmu, SLOT(doExit()));
255 connect(this, SIGNAL(quit_draw_thread()), hDrawEmu, SLOT(doExit()));
257 connect(glv, SIGNAL(sig_draw_timing(bool)), hRunEmu, SLOT(do_draw_timing(bool)));
258 connect(hDrawEmu, SIGNAL(sig_draw_timing(bool)), hRunEmu, SLOT(do_draw_timing(bool)));
260 connect(glv, SIGNAL(do_notify_move_mouse(int, int)),
261 hRunEmu, SLOT(moved_mouse(int, int)));
262 connect(glv, SIGNAL(do_notify_button_pressed(Qt::MouseButton)),
263 hRunEmu, SLOT(button_pressed_mouse(Qt::MouseButton)));
264 connect(glv, SIGNAL(do_notify_button_released(Qt::MouseButton)),
265 hRunEmu, SLOT(button_released_mouse(Qt::MouseButton)));
267 connect(glv, SIGNAL(sig_toggle_mouse(void)),
268 this, SLOT(do_toggle_mouse(void)));
270 connect(hRunEmu, SIGNAL(sig_resize_screen(int, int)),
271 glv, SLOT(resizeGL(int, int)));
273 connect(glv, SIGNAL(sig_resize_uibar(int, int)),
274 this, SLOT(resize_statusbar(int, int)));
275 connect(hRunEmu, SIGNAL(sig_resize_uibar(int, int)),
276 this, SLOT(resize_statusbar(int, int)));
278 connect(hRunEmu, SIGNAL(sig_finished()), glv, SLOT(releaseKeyCode(void)));
279 connect(hRunEmu, SIGNAL(sig_finished()), this, SLOT(delete_emu_thread()));
280 objNameStr = QString("EmuDrawThread");
281 hDrawEmu->setObjectName(objNameStr);
283 AGAR_DebugLog(AGAR_LOG_DEBUG, "DrawThread : Launch done.");
286 AGAR_DebugLog(AGAR_LOG_DEBUG, "EmuThread : Launch done.");
287 this->set_screen_aspect(config.window_stretch_type);
290 void Ui_MainWindow::LaunchJoyThread(void)
292 #if defined(USE_JOYSTICK)
293 hRunJoy = new JoyThreadClass(emu, emu->get_osd(), this);
294 connect(this, SIGNAL(quit_joy_thread()), hRunJoy, SLOT(doExit()));
295 hRunJoy->setObjectName("JoyThread");
300 void Ui_MainWindow::StopJoyThread(void)
302 #if defined(USE_JOYSTICK)
303 emit quit_joy_thread();
307 void Ui_MainWindow::delete_joy_thread(void)
309 // delete hRunJoyThread;
313 void Ui_MainWindow::on_actionExit_triggered()
315 save_config(create_local_path(_T("%s.ini"), _T(CONFIG_NAME)));
316 OnMainWindowClosed();
319 void Ui_MainWindow::OnWindowRedraw(void)
322 //emu->update_screen();
326 void Ui_MainWindow::OnWindowMove(void)
335 bool Ui_MainWindow::GetPowerState(void)
337 if(close_notified == 0) return true;
342 void Ui_MainWindow::OnMainWindowClosed(void)
347 if(!close_notified) {
349 emu->notify_power_off();
356 if(statusUpdateTimer != NULL) statusUpdateTimer->stop();
357 #ifdef USE_LED_DEVICE
358 if(ledUpdateTimer != NULL) ledUpdateTimer->stop();
360 emit quit_draw_thread();
361 emit quit_joy_thread();
362 emit quit_emu_thread();
363 if(hDrawEmu != NULL) {
367 if(hRunEmu != NULL) {
371 #if defined(USE_JOYSTICK)
372 if(hRunJoy != NULL) {
377 do_release_emu_resources();
381 //ChangeDisplaySettings(NULL, 0);
383 now_fullscreen = false;
389 void LostFocus(QWidget *widget)
392 emu->key_lost_focus();
398 void Ui_MainWindow::do_release_emu_resources(void)
406 extern void get_long_full_path_name(_TCHAR* src, _TCHAR* dst);
407 extern _TCHAR* get_parent_dir(_TCHAR* file);
408 extern void get_short_filename(_TCHAR *dst, _TCHAR *file, int maxlen);
411 static void setup_logs(void)
420 my_procname = my_procname + CONFIG_NAME;
421 #if defined(Q_OS_WIN)
426 #if !defined(Q_OS_WIN)
427 p = SDL_getenv("HOME");
429 p = SDL_getenv("PWD");
436 tmpstr = "Warning : Can't get HOME directory...Making conf on " + cpp_homedir + delim;
437 perror(tmpstr.c_str());
444 cpp_homedir = cpp_homedir + delim;
446 cpp_confdir = cpp_homedir + my_procname + delim;
448 cpp_confdir = cpp_homedir + ".config" + delim + my_procname + delim;
452 AGAR_OpenLog(bLogSYSLOG, bLogSTDOUT, DEVICE_NAME); // Write to syslog, console
455 #if defined(__x86_64__)
458 #if defined(__i386__)
461 AGAR_DebugLog(AGAR_LOG_INFO, "Start Common Source Project '%s'", my_procname.c_str());
462 AGAR_DebugLog(AGAR_LOG_INFO, "(C) Toshiya Takeda / Qt Version K.Ohta");
463 AGAR_DebugLog(AGAR_LOG_INFO, "Architecture: %s", archstr.c_str());
465 //AGAR_DebugLog(AGAR_LOG_INFO, " -? is print help(s).");
466 AGAR_DebugLog(AGAR_LOG_DEBUG, "Moduledir = %s home = %s", cpp_confdir.c_str(), cpp_homedir.c_str()); // Debug
467 #if !defined(Q_OS_CYGWIN)
470 dir.mkdir( QString::fromStdString(cpp_confdir));
473 //AG_MkPath(cpp_confdir.c_str());
476 #if defined(_USE_AGAR) || defined(_USE_QT)
477 sRssDir = "/usr/local/share/";
479 sRssDir = "." + delim;
481 sRssDir = sRssDir + "CommonSourceCodeProject" + delim + my_procname;
487 int MainLoop(int argc, char *argv[])
492 char homedir[PATH_MAX];
496 cpp_homedir.copy(homedir, PATH_MAX - 1, 0);
501 #if defined(USE_SDL2)
502 SDL_Init(SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER);
504 SDL_Init(SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_VIDEO);
505 //SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO);
507 AGAR_DebugLog(AGAR_LOG_DEBUG, "Audio and JOYSTICK subsystem was initialised.");
508 GuiMain = new QApplication(argc, argv);
510 load_config(create_local_path(_T("%s.ini"), _T(CONFIG_NAME)));
512 rMainWindow = new META_MainWindow();
513 rMainWindow->connect(rMainWindow, SIGNAL(sig_quit_all(void)), rMainWindow, SLOT(deleteLater(void)));
514 rMainWindow->setCoreApplication(GuiMain);
516 AGAR_DebugLog(AGAR_LOG_DEBUG, "InitInstance() OK.");
520 // initialize emulation core
521 rMainWindow->getWindow()->show();
522 emu = new EMU(rMainWindow, rMainWindow->getGraphicsView());
523 #ifdef SUPPORT_DRAG_DROP
524 // open command line path
525 // if(szCmdLine[0]) {
526 // if(szCmdLine[0] == _T('"')) {
527 // int len = strlen(szCmdLine);
528 // szCmdLine[len - 1] = _T('\0');
531 // _TCHAR path[_MAX_PATH];
532 // get_long_full_path_name(szCmdLine, path);
533 // open_any_file(path);
540 GLDrawClass *pgl = rMainWindow->getGraphicsView();
542 pgl->setFixedSize(pgl->width(), pgl->height());
544 #if defined(USE_JOYSTICK)
545 rMainWindow->LaunchJoyThread();
547 rMainWindow->LaunchEmuThread();
548 QObject::connect(GuiMain, SIGNAL(lastWindowClosed()),
549 rMainWindow, SLOT(on_actionExit_triggered()));
555 #include <../debugger/qt_debugger.h>
557 void Ui_MainWindow::OnOpenDebugger(int no)
559 if((no < 0) || (no > 3)) return;
560 //emu->open_debugger(no);
561 VM *vm = emu->get_vm();
563 if(emu->now_debugging) this->OnCloseDebugger();
564 if(!(emu->now_debugging && emu->debugger_thread_param.cpu_index == no)) {
565 //emu->close_debugger();
566 if(vm->get_cpu(no) != NULL && vm->get_cpu(no)->get_debugger() != NULL) {
568 emu->hDebugger = new CSP_Debugger(this);
569 QString objNameStr = QString("EmuDebugThread");
570 emu->hDebugger->setObjectName(objNameStr);
571 emu->hDebugger->debugger_thread_param.osd = emu->get_osd();
572 emu->hDebugger->debugger_thread_param.vm = vm;
573 emu->hDebugger->debugger_thread_param.cpu_index = no;
574 emu->stop_record_sound();
575 emu->stop_record_video();
576 emu->now_debugging = true;
577 connect(this, SIGNAL(quit_debugger_thread()), emu->hDebugger, SLOT(doExit()));
578 //connect(this, SIGNAL(quit_debugger_thread()), emu->hDebugger, SLOT(close()));
579 connect(emu->hDebugger, SIGNAL(sig_finished()), this, SLOT(OnCloseDebugger()));
580 connect(emu->hDebugger, SIGNAL(sig_put_string(QString)), emu->hDebugger, SLOT(put_string(QString)));
581 emu->hDebugger->show();
582 emu->hDebugger->run();
587 void Ui_MainWindow::OnCloseDebugger(void )
590 // emu->close_debugger();
591 if(emu->now_debugging) {
592 if(emu->hDebugger->debugger_thread_param.running) {
593 emit quit_debugger_thread();
594 //emu->hDebugger->wait();
596 delete emu->hDebugger;
597 emu->hDebugger = NULL;
598 emu->now_debugging = false;