2 Skelton for retropc emulator
4 Author : K.Ohta <whatisthis.sowhat _at_ gmail.com>
18 #include <QElapsedTimer>
38 #include "../vm/device.h"
39 #include "../common.h"
43 #include "emu_thread.h"
44 #include "draw_thread.h"
45 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
46 #include "avio/movie_loader.h"
48 #if defined(USE_SOUND_FILES)
49 #include "avio/sound_loader.h"
51 #include "qt_gldraw.h"
52 #include "csp_logger.h"
54 const _TCHAR *OSD::get_lib_common_vm_version()
56 if(vm->first_device != NULL) {
57 return vm->first_device->get_lib_common_vm_version();
59 return (const _TCHAR *)"\0";
63 const _TCHAR *OSD::get_lib_common_vm_git_version()
65 return vm->get_vm_git_version();
68 const _TCHAR *OSD::get_lib_osd_version()
70 const _TCHAR *p = (const _TCHAR *)"\0";
71 #if defined(__LIBOSD_VERSION)
72 p = (const _TCHAR *)__LIBOSD_VERSION;
78 void OSD::vm_draw_screen(void)
83 double OSD::vm_frame_rate(void)
85 #ifdef SUPPORT_VARIABLE_TIMING
86 return vm->get_frame_rate();
88 return FRAMES_PER_SEC;
92 Sint16* OSD::create_sound(int *extra_frames)
94 return (Sint16 *)vm->create_sound(extra_frames);
97 #ifdef USE_SOUND_FILES
98 void OSD::load_sound_file(int id, const _TCHAR *name, int16_t **data, int *dst_size)
101 if(data != NULL) *data = NULL;
102 if(dst_size != NULL) *dst_size = 0;
105 for(i = 0; i < USE_SOUND_FILES; i++) {
106 SOUND_LOADER *p = sound_file_obj[i];
108 if(p->get_id() == id) break;
112 if(i >= USE_SOUND_FILES) {
113 for(i = 0; i < USE_SOUND_FILES; i++) {
114 SOUND_LOADER *p = sound_file_obj[i];
116 if(p->get_id() < 0) {
123 if(i >= USE_SOUND_FILES) return;
124 SOUND_LOADER *p = sound_file_obj[i];
126 p->free_sound_buffer(NULL);
127 p->set_sound_rate(this->get_sound_rate());
128 if(p->open(id, QString::fromUtf8(name))) {
129 p->do_decode_frames();
131 if(data != NULL) *data = (int16_t *)(p->get_sound_buffer());
132 if(dst_size != NULL) *dst_size = p->get_dst_size();
137 void OSD::free_sound_file(int id, int16_t **data)
139 if(data == NULL) return;
140 for(int i = 0; i < USE_SOUND_FILES; i++) {
141 SOUND_LOADER *p = sound_file_obj[i];
143 if(p->get_id() == id) {
144 p->free_sound_buffer(*data);
152 void OSD::init_sound_files()
154 for(int i = 0; i < USE_SOUND_FILES; i++) {
155 sound_file_obj[i] = NULL;
156 SOUND_LOADER *p = new SOUND_LOADER((void *)tail_sound_file, p_logger);
158 sound_file_obj[i] = p;
164 void OSD::release_sound_files()
166 for(int i = 0; i < USE_SOUND_FILES; i++) {
167 SOUND_LOADER *p = sound_file_obj[i];
168 if(p != NULL) delete p;
169 sound_file_obj[i] = NULL;
173 bool OSD::get_use_socket(void)
182 bool OSD::get_support_variable_timing(void)
184 #ifdef SUPPORT_VARIABLE_TIMING
191 bool OSD::get_notify_key_down(void)
193 #ifdef NOTIFY_KEY_DOWN
200 bool OSD::get_notify_key_down_lr_shift(void)
202 #ifdef NOTIFY_KEY_DOWN_LR_SHIFT
209 bool OSD::get_notify_key_down_lr_control(void)
211 #ifdef NOTIFY_KEY_DOWN_LR_CONTROL
218 bool OSD::get_notify_key_down_lr_menu(void)
220 #ifdef NOTIFY_KEY_DOWN_LR_MEHU
227 bool OSD::get_use_shift_numpad_key(void)
229 #ifdef USE_SHIFT_NUMPAD_KEY
236 bool OSD::get_use_auto_key(void)
245 bool OSD::get_dont_keeep_key_pressed(void)
247 #ifdef DONT_KEEEP_KEY_PRESSED
254 bool OSD::get_one_board_micro_computer(void)
256 #ifdef ONE_BOARD_MICRO_COMPUTER
263 bool OSD::get_use_screen_rotate(void)
265 #ifdef USE_SCREEN_ROTATE
272 bool OSD::get_use_movie_player(void)
274 #ifdef USE_MOVIE_PLAYER
281 bool OSD::get_use_video_capture(void)
283 #ifdef USE_VIDEO_CAPTURE
290 void OSD::vm_key_down(int code, bool flag)
292 #ifdef NOTIFY_KEY_DOWN
293 vm->key_down(code, flag);
297 void OSD::vm_key_up(int code)
299 #ifdef NOTIFY_KEY_DOWN
304 void OSD::vm_reset(void)
309 int OSD::get_vm_buttons_code(int num)
311 #ifdef ONE_BOARD_MICRO_COMPUTER
312 if(num < 0) return 0;
313 return vm_buttons[num].code;
319 void OSD::update_buttons(bool press_flag, bool release_flag)
321 #if defined(MAX_BUTTONS)
322 if(!press_flag && !release_flag) {
325 for(ii = 0; vm_buttons[ii].code != 0x00; ii++) {
326 if((mouse_ptrx >= vm_buttons[ii].x) && (mouse_ptrx < (vm_buttons[ii].x + vm_buttons[ii].width))) {
327 if((mouse_ptry >= vm_buttons[ii].y) && (mouse_ptry < (vm_buttons[ii].y + vm_buttons[ii].height))) {
328 if((key_status[vm_buttons[ii].code] & 0x7f) == 0) this->press_button(ii);
332 if((mouse_ptrx >= vm_buttons[ii].x) && (mouse_ptrx < (vm_buttons[ii].x + vm_buttons[ii].width))) {
333 if((mouse_ptry >= vm_buttons[ii].y) && (mouse_ptry < (vm_buttons[ii].y + vm_buttons[ii].height))) {
334 this->press_button(ii);
337 mouse_ptrx = mouse_ptry = 0;
343 QString OSD::get_vm_config_name(void)
345 #if defined(CONFIG_NAME)
346 return QString::fromUtf8(CONFIG_NAME);
348 return QString::fromUtf8(" ");
352 int OSD::get_screen_width(void)
357 int OSD::get_screen_height(void)
359 return SCREEN_HEIGHT;
362 void OSD::lock_vm(void)
366 //if(parent_thread != NULL) {
367 //if(!parent_thread->now_debugging()) VMSemaphore->acquire(1);
368 //VMSemaphore->acquire(1);
370 // VMSemaphore->acquire(1);
374 void OSD::unlock_vm(void)
377 //if(parent_thread != NULL) {
378 // //if(!parent_thread->now_debugging()) VMSemaphore->release(1);
379 // VMSemaphore->release(1);
381 // VMSemaphore->release(1);
387 bool OSD::is_vm_locked(void)
392 void OSD::force_unlock_vm(void)
398 void OSD::set_draw_thread(DrawThreadClass *handler)
400 //this->moveToThread(handler);
401 connect(this, SIGNAL(sig_update_screen(bitmap_t *)), handler, SLOT(do_update_screen(bitmap_t *)));
402 connect(this, SIGNAL(sig_save_screen(const char *)), glv, SLOT(do_save_frame_screen(const char *)));
403 connect(this, SIGNAL(sig_resize_vm_screen(QImage *, int, int)), glv, SLOT(do_set_texture_size(QImage *, int, int)));
404 connect(this, SIGNAL(sig_resize_vm_lines(int)), glv, SLOT(do_set_horiz_lines(int)));
405 connect(parent_thread, SIGNAL(sig_debugger_input(QString)), this, SLOT(do_set_input_string(QString)));
406 connect(parent_thread, SIGNAL(sig_quit_debugger()), this, SLOT(do_close_debugger_thread()));
407 connect(this, SIGNAL(sig_move_mouse_to_center()), glv, SLOT(do_move_mouse_to_center()));
408 connect(this, SIGNAL(sig_close_window()), parent_thread, SLOT(doExit()));
411 void OSD::initialize_screen()
413 host_window_width = base_window_width = WINDOW_WIDTH;
414 host_window_height = base_window_height = WINDOW_HEIGHT;
415 host_window_mode = true;
417 vm_screen_width = SCREEN_WIDTH;
418 vm_screen_height = SCREEN_HEIGHT;
419 vm_window_width = WINDOW_WIDTH;
420 vm_window_height = WINDOW_HEIGHT;
421 vm_window_width_aspect = WINDOW_WIDTH_ASPECT;
422 vm_window_height_aspect = WINDOW_HEIGHT_ASPECT;
424 QColor col(0, 0, 0, 255);
426 vm_screen_buffer.width = SCREEN_WIDTH;
427 vm_screen_buffer.height = SCREEN_HEIGHT;
428 vm_screen_buffer.pImage = QImage(SCREEN_WIDTH, SCREEN_HEIGHT, QImage::Format_ARGB32);
429 vm_screen_buffer.pImage.fill(col);
430 now_record_video = false;
432 first_draw_screen = false;
433 first_invalidate = true;
434 self_invalidate = false;
437 void OSD::release_screen()
440 release_screen_buffer(&vm_screen_buffer);
443 int OSD::get_window_mode_width(int mode)
445 if(get_use_screen_rotate()) {
446 if(p_config->rotate_type == 1 || p_config->rotate_type == 3) {
447 return (p_config->window_stretch_type == 0 ? vm_window_height : vm_window_height_aspect) * (mode + WINDOW_MODE_BASE);
450 return (p_config->window_stretch_type == 0 ? vm_window_width : vm_window_width_aspect) * (mode + WINDOW_MODE_BASE);
453 int OSD::get_window_mode_height(int mode)
455 if(get_use_screen_rotate()) {
456 if(p_config->rotate_type == 1 || p_config->rotate_type == 3) {
457 return (p_config->window_stretch_type == 0 ? vm_window_width : vm_window_width_aspect) * (mode + WINDOW_MODE_BASE);
460 return (p_config->window_stretch_type == 0 ? vm_window_height : vm_window_height_aspect) * (mode + WINDOW_MODE_BASE);
463 void OSD::initialize_video()
466 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
467 movie_loader = new MOVIE_LOADER(this, &config);
468 //connect(movie_loader, SIGNAL(sig_send_audio_frame(uint8_t *, long)), this, SLOT(do_run_movie_audio_callback2(uint8_t *, long)));
469 connect(movie_loader, SIGNAL(sig_movie_end(bool)), this, SLOT(do_video_movie_end(bool)));
470 connect(this, SIGNAL(sig_movie_play(void)), movie_loader, SLOT(do_play()));
471 connect(this, SIGNAL(sig_movie_stop(void)), movie_loader, SLOT(do_stop()));
472 connect(this, SIGNAL(sig_movie_pause(bool)), movie_loader, SLOT(do_pause(bool)));
473 connect(this, SIGNAL(sig_movie_seek_frame(bool, int)), movie_loader, SLOT(do_seek_frame(bool, int)));
474 //connect(this, SIGNAL(sig_movie_mute(bool, bool)), movie_loader, SLOT(do_mute(bool, bool)));
475 connect(movie_loader, SIGNAL(sig_decoding_error(int)), this, SLOT(do_video_decoding_error(int)));
479 void OSD::release_video()
481 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
488 bool OSD::open_movie_file(const _TCHAR* file_path)
491 if(file_path == NULL) return ret;
492 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
493 if(movie_loader != NULL) {
494 ret = movie_loader->open(QString::fromUtf8(file_path));
500 void OSD::close_movie_file()
502 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
503 if(movie_loader != NULL) {
504 movie_loader->close();
507 now_movie_play = false;
508 now_movie_pause = false;
512 uint32_t OSD::get_cur_movie_frame()
514 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
515 if(movie_loader != NULL) {
517 pos = movie_loader->get_current_frame();
521 return (uint32_t)pos;
527 void OSD::do_run_movie_audio_callback(uint8_t *data, long len)
529 if(data == NULL) return;
530 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
534 this->vm->movie_sound_callback(data, len);
542 void OSD::do_decode_movie(int frames)
544 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
545 //movie_loader->do_decode_frames(frames, SCREEN_WIDTH, SCREEN_HEIGHT);
546 movie_loader->do_decode_frames(frames, vm_window_width_aspect, vm_window_height_aspect);
550 void OSD::get_video_buffer()
552 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
553 //movie_loader->do_decode_frames(1, this->get_vm_window_width(), this->get_vm_window_height());
554 movie_loader->get_video_frame();
559 int OSD::get_movie_sound_rate()
561 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
562 return movie_loader->get_movie_sound_rate();
567 void OSD::reset_vm_node()
570 device_node_list.clear();
573 for(DEVICE *p = vm->first_device; p != NULL; p = p->next_device) {
574 sp.id = p->this_device_id;
575 sp.name = p->this_device_name;
576 p_logger->set_device_name(sp.id, sp.name);
577 p_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_GENERAL, "Device %d :%s", sp.id, sp.name);
578 device_node_list.append(sp);
579 if(max_vm_nodes <= p->this_device_id) max_vm_nodes = p->this_device_id + 1;
581 for(DEVICE *p = vm->first_device; p != NULL; p = p->next_device) {
582 emit sig_update_device_node_name(p->this_device_id, p->this_device_name);
586 #if defined(USE_SOCKET)
587 #include <QHostAddress>
588 #include "osd_socket.h"
591 void OSD::initialize_socket()
593 for(int i = 0; i < SOCKET_MAX; i++) {
594 tcp_socket[i] = NULL;
595 udp_socket[i] = NULL;
598 host_mode[i] = false;
602 void OSD::release_socket()
606 for(int i = 0; i < SOCKET_MAX; i++) {
607 if(tcp_socket[i] != NULL) {
608 if(tcp_socket[i]->isOpen()) tcp_socket[i]->close();
609 delete tcp_socket[i];
610 tcp_socket[i] = NULL;
612 if(udp_socket[i] != NULL) {
613 if(udp_socket[i]->isOpen()) udp_socket[i]->close();
614 delete udp_socket[i];
615 udp_socket[i] = NULL;
622 void OSD::notify_socket_connected(int ch)
624 do_notify_socket_connected(ch);
627 void OSD::do_notify_socket_connected(int ch)
630 vm->notify_socket_connected(ch);
635 void OSD::notify_socket_disconnected(int ch)
637 do_notify_socket_disconnected(ch);
641 void OSD::do_notify_socket_disconnected(int ch)
643 if(!socket_delay[ch]) {
644 socket_delay[ch] = 1;//56;
648 // Called per 1 frame.
649 void OSD::update_socket()
653 for(int i = 0; i < SOCKET_MAX; i++) {
656 if(tcp_socket[i] != NULL) {
657 if(tcp_socket[i]->isOpen()) {
662 if(udp_socket[i] != NULL) {
663 if(udp_socket[i]->isOpen()) {
670 bytes = p->bytesAvailable();
673 uint8_t* buf0 = vm->get_socket_recv_buffer0(i, &size0, &size1);
674 uint8_t* buf1 = vm->get_socket_recv_buffer1(i);
677 if(bytes > (qint64)(size0 + size1)) {
678 bytes = (qint64)(size0 + size1);
680 QByteArray src = p->read(bytes);
683 uint8_t *pp = (uint8_t *)(src.constData());
684 if(size <= (qint64)size0) {
685 memcpy(buf0, pp, size);
687 memcpy(buf0, pp, size0);
688 memcpy(buf1, pp + size0, (int)size - size0);
690 vm->inc_socket_recv_buffer_ptr(i, (int)size);
691 } else if(socket_delay[i] != 0) {
692 if(--socket_delay[i] == 0) {
693 vm->notify_socket_disconnected(i);
701 bool OSD::initialize_socket_tcp(int ch)
704 if(udp_socket[ch] != NULL) {
705 if(udp_socket[ch]->isOpen()) {
706 udp_socket[ch]->close();
708 delete udp_socket[ch];
709 udp_socket[ch] = NULL;
711 if(tcp_socket[ch] != NULL) {
712 if(tcp_socket[ch]->isOpen()) tcp_socket[ch]->close();
713 delete tcp_socket[ch];
716 tcp_socket[ch] = new QTcpSocket2(ch);
717 if(tcp_socket[ch] == NULL) return false;
718 tcp_socket[ch]->setChannel(ch);
719 connect(tcp_socket[ch], SIGNAL(connected()), tcp_socket[ch], SLOT(do_connected()));
720 connect(tcp_socket[ch], SIGNAL(sig_connected(int)), this, SLOT(do_notify_socket_connected(int)));
721 connect(tcp_socket[ch], SIGNAL(disconnected()), tcp_socket[ch], SLOT(do_disconnected()));
722 connect(tcp_socket[ch], SIGNAL(sig_disconnected(int)), this, SLOT(do_notify_socket_disconnected(int)));
727 bool OSD::initialize_socket_udp(int ch)
730 if(tcp_socket[ch] != NULL) {
731 if(tcp_socket[ch]->isOpen()) {
732 tcp_socket[ch]->close();
734 delete tcp_socket[ch];
735 tcp_socket[ch] = NULL;
737 if(udp_socket[ch] != NULL) {
738 if(udp_socket[ch]->isOpen()) udp_socket[ch]->close();
739 delete udp_socket[ch];
742 udp_socket[ch] = new QUdpSocket2(ch);
743 if(udp_socket[ch] == NULL) return false;
744 connect(udp_socket[ch], SIGNAL(connected()), udp_socket[ch], SLOT(do_connected()));
745 connect(udp_socket[ch], SIGNAL(sig_connected(int)), this, SLOT(do_notify_socket_connected(int)));
746 connect(udp_socket[ch], SIGNAL(disconnected()), udp_socket[ch], SLOT(do_disconnected()));
747 connect(udp_socket[ch], SIGNAL(sig_disconnected(int)), this, SLOT(do_notify_socket_disconnected(int)));
752 bool OSD::connect_socket(int ch, uint32_t ipaddr, int port)
755 QHostAddress addr = QHostAddress((quint32)ipaddr);
757 if(tcp_socket[ch] != NULL) {
758 tcp_socket[ch]->connectToHost(addr, (quint16)port);
763 if(udp_socket[ch] != NULL) {
764 udp_socket[ch]->connectToHost(addr, (quint16)port);
769 host_mode[ch] = false;
774 void OSD::disconnect_socket(int ch)
780 if(tcp_socket[ch] != NULL) {
781 if(tcp_socket[ch]->isOpen()) tcp_socket[ch]->close();
784 if(udp_socket[ch] != NULL) {
785 if(udp_socket[ch]->isOpen()) udp_socket[ch]->close();
790 if(tcp_socket[ch] != NULL) {
791 udp_socket[ch]->disconnectFromHost();
794 if(udp_socket[ch] != NULL) {
795 udp_socket[ch]->disconnectFromHost();
799 vm->notify_socket_disconnected(ch);
803 bool OSD::listen_socket(int ch)
806 //QHostAddress addr = QHostAddress(QHostAddress::AnyIPv4); // OK?
807 // This unit is dummy?
808 //connect(udp_socket[ch], SIGNAL(connected()), udp_socket[ch], SLOT(do_connected()));
809 //connect(udp_socket[ch], SIGNAL(sig_connected(int)), this, SLOT(do_notify_socket_connected(int)));
810 //connect(udp_socket[ch], SIGNAL(disconnected()), udp_socket[ch], SLOT(do_disconnected()));
811 //connect(udp_socket[ch], SIGNAL(sig_disconnected(int)), this, SLOT(do_notify_socket_disconnected(int)));
816 void OSD::send_socket_data_tcp(int ch)
822 uint8_t *buf = vm->get_socket_send_buffer(ch, &size);
827 if(tcp_socket[ch] != NULL) {
828 if(tcp_socket[ch]->isWritable()) {
829 size2 = tcp_socket[ch]->write((const char *)buf, (qint64)size);
831 disconnect_socket(ch);
832 notify_socket_disconnected(ch);
839 vm->inc_socket_send_buffer_ptr(ch, (int)size2);
845 void OSD::send_socket_data_udp(int ch, uint32_t ipaddr, int port)
848 QHostAddress addr = QHostAddress((quint32)ipaddr);
852 uint8_t *buf = vm->get_socket_send_buffer(ch, &size);
858 if(udp_socket[ch] != NULL) {
859 size2 = udp_socket[ch]->writeDatagram((const char *)buf, (qint64)size, addr, (quint16)port);
861 disconnect_socket(ch);
862 notify_socket_disconnected(ch);
868 vm->inc_socket_send_buffer_ptr(ch, (int)size2);
874 void OSD::send_socket_data(int ch)
879 void OSD::recv_socket_data(int ch)
884 int OSD::get_socket(int ch)
888 if(tcp_socket[ch] == NULL) return -1;
890 if(udp_socket[ch] == NULL) return -1;
897 #if defined(USE_SOCKET)
898 QTcpSocket2::QTcpSocket2(int channel, QObject *parent) : QTcpSocket(parent)
903 QTcpSocket2::~QTcpSocket2()
907 void QTcpSocket2::do_connected(void)
909 emit sig_connected(ch);
912 void QTcpSocket2::do_disconnected(void)
914 emit sig_disconnected(ch);
917 void QTcpSocket2::setChannel(int channel)
922 int QTcpSocket2::getChannel(void)
927 QUdpSocket2::QUdpSocket2(int channel, QObject *parent) : QUdpSocket(parent)
932 QUdpSocket2::~QUdpSocket2()
936 void QUdpSocket2::do_connected(void)
938 emit sig_connected(ch);
941 void QUdpSocket2::do_disconnected(void)
943 emit sig_disconnected(ch);
946 void QUdpSocket2::setChannel(int channel)
951 int QUdpSocket2::getChannel(void)