2 Skelton for retropc emulator
4 Author : K.Ohta <whatisthis.sowhat _at_ gmail.com>
18 #include <QElapsedTimer>
38 #include "../vm/device.h"
42 #include "emu_thread.h"
43 #include "draw_thread.h"
44 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
45 #include "avio/movie_loader.h"
47 #if defined(USE_SOUND_FILES)
48 #include "avio/sound_loader.h"
50 #include "qt_gldraw.h"
51 #include "csp_logger.h"
53 void OSD::vm_draw_screen(void)
58 double OSD::vm_frame_rate(void)
60 #ifdef SUPPORT_VARIABLE_TIMING
61 return vm->get_frame_rate();
63 return FRAMES_PER_SEC;
67 Sint16* OSD::create_sound(int *extra_frames)
69 return (Sint16 *)vm->create_sound(extra_frames);
72 #ifdef USE_SOUND_FILES
73 void OSD::load_sound_file(int id, const _TCHAR *name, int16_t **data, int *dst_size)
76 if(data != NULL) *data = NULL;
77 if(dst_size != NULL) *dst_size = 0;
80 for(i = 0; i < USE_SOUND_FILES; i++) {
81 SOUND_LOADER *p = sound_file_obj[i];
83 if(p->get_id() == id) break;
87 if(i >= USE_SOUND_FILES) {
88 for(i = 0; i < USE_SOUND_FILES; i++) {
89 SOUND_LOADER *p = sound_file_obj[i];
98 if(i >= USE_SOUND_FILES) return;
99 SOUND_LOADER *p = sound_file_obj[i];
101 p->free_sound_buffer(NULL);
102 p->set_sound_rate(this->get_sound_rate());
103 if(p->open(id, QString::fromUtf8(name))) {
104 p->do_decode_frames();
106 if(data != NULL) *data = (int16_t *)(p->get_sound_buffer());
107 if(dst_size != NULL) *dst_size = p->get_dst_size();
112 void OSD::free_sound_file(int id, int16_t **data)
114 if(data == NULL) return;
115 for(int i = 0; i < USE_SOUND_FILES; i++) {
116 SOUND_LOADER *p = sound_file_obj[i];
118 if(p->get_id() == id) {
119 p->free_sound_buffer(*data);
127 void OSD::init_sound_files()
129 for(int i = 0; i < USE_SOUND_FILES; i++) {
130 sound_file_obj[i] = NULL;
131 SOUND_LOADER *p = new SOUND_LOADER((void *)tail_sound_file, p_logger);
133 sound_file_obj[i] = p;
139 void OSD::release_sound_files()
141 for(int i = 0; i < USE_SOUND_FILES; i++) {
142 SOUND_LOADER *p = sound_file_obj[i];
143 if(p != NULL) delete p;
144 sound_file_obj[i] = NULL;
148 bool OSD::get_use_socket(void)
157 bool OSD::get_support_variable_timing(void)
159 #ifdef SUPPORT_VARIABLE_TIMING
166 bool OSD::get_notify_key_down(void)
168 #ifdef NOTIFY_KEY_DOWN
175 bool OSD::get_notify_key_down_lr_shift(void)
177 #ifdef NOTIFY_KEY_DOWN_LR_SHIFT
184 bool OSD::get_notify_key_down_lr_control(void)
186 #ifdef NOTIFY_KEY_DOWN_LR_CONTROL
193 bool OSD::get_notify_key_down_lr_menu(void)
195 #ifdef NOTIFY_KEY_DOWN_LR_MEHU
202 bool OSD::get_use_shift_numpad_key(void)
204 #ifdef USE_SHIFT_NUMPAD_KEY
211 bool OSD::get_use_auto_key(void)
220 bool OSD::get_dont_keeep_key_pressed(void)
222 #ifdef DONT_KEEEP_KEY_PRESSED
229 bool OSD::get_one_board_micro_computer(void)
231 #ifdef ONE_BOARD_MICRO_COMPUTER
238 bool OSD::get_use_screen_rotate(void)
240 #ifdef USE_SCREEN_ROTATE
247 bool OSD::get_use_movie_player(void)
249 #ifdef USE_MOVIE_PLAYER
256 bool OSD::get_use_video_capture(void)
258 #ifdef USE_VIDEO_CAPTURE
265 void OSD::vm_key_down(int code, bool flag)
267 #ifdef NOTIFY_KEY_DOWN
268 vm->key_down(code, flag);
272 void OSD::vm_key_up(int code)
274 #ifdef NOTIFY_KEY_DOWN
279 void OSD::vm_reset(void)
284 int OSD::get_vm_buttons_code(int num)
286 #ifdef ONE_BOARD_MICRO_COMPUTER
287 if(num < 0) return 0;
288 return vm_buttons[num].code;
294 void OSD::update_buttons(bool press_flag, bool release_flag)
296 #if defined(MAX_BUTTONS)
297 if(!press_flag && !release_flag) {
300 for(ii = 0; vm_buttons[ii].code != 0x00; ii++) {
301 if((mouse_ptrx >= vm_buttons[ii].x) && (mouse_ptrx < (vm_buttons[ii].x + vm_buttons[ii].width))) {
302 if((mouse_ptry >= vm_buttons[ii].y) && (mouse_ptry < (vm_buttons[ii].y + vm_buttons[ii].height))) {
303 if((key_status[vm_buttons[ii].code] & 0x7f) == 0) this->press_button(ii);
307 if((mouse_ptrx >= vm_buttons[ii].x) && (mouse_ptrx < (vm_buttons[ii].x + vm_buttons[ii].width))) {
308 if((mouse_ptry >= vm_buttons[ii].y) && (mouse_ptry < (vm_buttons[ii].y + vm_buttons[ii].height))) {
309 this->press_button(ii);
312 mouse_ptrx = mouse_ptry = 0;
318 QString OSD::get_vm_config_name(void)
320 #if defined(CONFIG_NAME)
321 return QString::fromUtf8(CONFIG_NAME);
323 return QString::fromUtf8(" ");
327 int OSD::get_screen_width(void)
332 int OSD::get_screen_height(void)
334 return SCREEN_HEIGHT;
337 void OSD::lock_vm(void)
341 //if(parent_thread != NULL) {
342 //if(!parent_thread->now_debugging()) VMSemaphore->acquire(1);
343 //VMSemaphore->acquire(1);
345 // VMSemaphore->acquire(1);
349 void OSD::unlock_vm(void)
352 //if(parent_thread != NULL) {
353 // //if(!parent_thread->now_debugging()) VMSemaphore->release(1);
354 // VMSemaphore->release(1);
356 // VMSemaphore->release(1);
362 bool OSD::is_vm_locked(void)
367 void OSD::force_unlock_vm(void)
373 void OSD::set_draw_thread(DrawThreadClass *handler)
375 //this->moveToThread(handler);
376 connect(this, SIGNAL(sig_update_screen(bitmap_t *)), handler, SLOT(do_update_screen(bitmap_t *)));
377 connect(this, SIGNAL(sig_save_screen(const char *)), glv, SLOT(do_save_frame_screen(const char *)));
378 connect(this, SIGNAL(sig_resize_vm_screen(QImage *, int, int)), glv, SLOT(do_set_texture_size(QImage *, int, int)));
379 connect(this, SIGNAL(sig_resize_vm_lines(int)), glv, SLOT(do_set_horiz_lines(int)));
380 connect(parent_thread, SIGNAL(sig_debugger_input(QString)), this, SLOT(do_set_input_string(QString)));
381 connect(parent_thread, SIGNAL(sig_quit_debugger()), this, SLOT(do_close_debugger_thread()));
382 connect(this, SIGNAL(sig_move_mouse_to_center()), glv, SLOT(do_move_mouse_to_center()));
383 connect(this, SIGNAL(sig_close_window()), parent_thread, SLOT(doExit()));
386 void OSD::initialize_screen()
388 host_window_width = base_window_width = WINDOW_WIDTH;
389 host_window_height = base_window_height = WINDOW_HEIGHT;
390 host_window_mode = true;
392 vm_screen_width = SCREEN_WIDTH;
393 vm_screen_height = SCREEN_HEIGHT;
394 vm_window_width = WINDOW_WIDTH;
395 vm_window_height = WINDOW_HEIGHT;
396 vm_window_width_aspect = WINDOW_WIDTH_ASPECT;
397 vm_window_height_aspect = WINDOW_HEIGHT_ASPECT;
399 QColor col(0, 0, 0, 255);
401 vm_screen_buffer.width = SCREEN_WIDTH;
402 vm_screen_buffer.height = SCREEN_HEIGHT;
403 vm_screen_buffer.pImage = QImage(SCREEN_WIDTH, SCREEN_HEIGHT, QImage::Format_ARGB32);
404 vm_screen_buffer.pImage.fill(col);
405 now_record_video = false;
407 first_draw_screen = false;
408 first_invalidate = true;
409 self_invalidate = false;
412 void OSD::release_screen()
415 release_screen_buffer(&vm_screen_buffer);
418 int OSD::get_window_mode_width(int mode)
420 if(get_use_screen_rotate()) {
421 if(p_config->rotate_type == 1 || p_config->rotate_type == 3) {
422 return (p_config->window_stretch_type == 0 ? vm_window_height : vm_window_height_aspect) * (mode + WINDOW_MODE_BASE);
425 return (p_config->window_stretch_type == 0 ? vm_window_width : vm_window_width_aspect) * (mode + WINDOW_MODE_BASE);
428 int OSD::get_window_mode_height(int mode)
430 if(get_use_screen_rotate()) {
431 if(p_config->rotate_type == 1 || p_config->rotate_type == 3) {
432 return (p_config->window_stretch_type == 0 ? vm_window_width : vm_window_width_aspect) * (mode + WINDOW_MODE_BASE);
435 return (p_config->window_stretch_type == 0 ? vm_window_height : vm_window_height_aspect) * (mode + WINDOW_MODE_BASE);
438 void OSD::initialize_video()
441 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
442 movie_loader = new MOVIE_LOADER(this, &config);
443 //connect(movie_loader, SIGNAL(sig_send_audio_frame(uint8_t *, long)), this, SLOT(do_run_movie_audio_callback2(uint8_t *, long)));
444 connect(movie_loader, SIGNAL(sig_movie_end(bool)), this, SLOT(do_video_movie_end(bool)));
445 connect(this, SIGNAL(sig_movie_play(void)), movie_loader, SLOT(do_play()));
446 connect(this, SIGNAL(sig_movie_stop(void)), movie_loader, SLOT(do_stop()));
447 connect(this, SIGNAL(sig_movie_pause(bool)), movie_loader, SLOT(do_pause(bool)));
448 connect(this, SIGNAL(sig_movie_seek_frame(bool, int)), movie_loader, SLOT(do_seek_frame(bool, int)));
449 //connect(this, SIGNAL(sig_movie_mute(bool, bool)), movie_loader, SLOT(do_mute(bool, bool)));
450 connect(movie_loader, SIGNAL(sig_decoding_error(int)), this, SLOT(do_video_decoding_error(int)));
454 void OSD::release_video()
456 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
463 bool OSD::open_movie_file(const _TCHAR* file_path)
466 if(file_path == NULL) return ret;
467 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
468 if(movie_loader != NULL) {
469 ret = movie_loader->open(QString::fromUtf8(file_path));
475 void OSD::close_movie_file()
477 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
478 if(movie_loader != NULL) {
479 movie_loader->close();
482 now_movie_play = false;
483 now_movie_pause = false;
487 uint32_t OSD::get_cur_movie_frame()
489 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
490 if(movie_loader != NULL) {
492 pos = movie_loader->get_current_frame();
496 return (uint32_t)pos;
502 void OSD::do_run_movie_audio_callback(uint8_t *data, long len)
504 if(data == NULL) return;
505 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
509 this->vm->movie_sound_callback(data, len);
517 void OSD::do_decode_movie(int frames)
519 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
520 //movie_loader->do_decode_frames(frames, SCREEN_WIDTH, SCREEN_HEIGHT);
521 movie_loader->do_decode_frames(frames, vm_window_width_aspect, vm_window_height_aspect);
525 void OSD::get_video_buffer()
527 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
528 //movie_loader->do_decode_frames(1, this->get_vm_window_width(), this->get_vm_window_height());
529 movie_loader->get_video_frame();
534 int OSD::get_movie_sound_rate()
536 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
537 return movie_loader->get_movie_sound_rate();
542 void OSD::reset_vm_node()
545 device_node_list.clear();
548 for(DEVICE *p = vm->first_device; p != NULL; p = p->next_device) {
549 sp.id = p->this_device_id;
550 sp.name = p->this_device_name;
551 p_logger->set_device_name(sp.id, sp.name);
552 p_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_GENERAL, "Device %d :%s", sp.id, sp.name);
553 device_node_list.append(sp);
554 if(max_vm_nodes <= p->this_device_id) max_vm_nodes = p->this_device_id + 1;
556 for(DEVICE *p = vm->first_device; p != NULL; p = p->next_device) {
557 emit sig_update_device_node_name(p->this_device_id, p->this_device_name);
561 #if defined(USE_SOCKET)
562 #include <QHostAddress>
563 #include "osd_socket.h"
566 void OSD::initialize_socket()
568 for(int i = 0; i < SOCKET_MAX; i++) {
569 tcp_socket[i] = NULL;
570 udp_socket[i] = NULL;
573 host_mode[i] = false;
577 void OSD::release_socket()
581 for(int i = 0; i < SOCKET_MAX; i++) {
582 if(tcp_socket[i] != NULL) {
583 if(tcp_socket[i]->isOpen()) tcp_socket[i]->close();
584 delete tcp_socket[i];
585 tcp_socket[i] = NULL;
587 if(udp_socket[i] != NULL) {
588 if(udp_socket[i]->isOpen()) udp_socket[i]->close();
589 delete udp_socket[i];
590 udp_socket[i] = NULL;
597 void OSD::notify_socket_connected(int ch)
599 do_notify_socket_connected(ch);
602 void OSD::do_notify_socket_connected(int ch)
605 vm->notify_socket_connected(ch);
610 void OSD::notify_socket_disconnected(int ch)
612 do_notify_socket_disconnected(ch);
616 void OSD::do_notify_socket_disconnected(int ch)
618 if(!socket_delay[ch]) {
619 socket_delay[ch] = 1;//56;
623 // Called per 1 frame.
624 void OSD::update_socket()
628 for(int i = 0; i < SOCKET_MAX; i++) {
631 if(tcp_socket[i] != NULL) {
632 if(tcp_socket[i]->isOpen()) {
637 if(udp_socket[i] != NULL) {
638 if(udp_socket[i]->isOpen()) {
645 bytes = p->bytesAvailable();
648 uint8_t* buf0 = vm->get_socket_recv_buffer0(i, &size0, &size1);
649 uint8_t* buf1 = vm->get_socket_recv_buffer1(i);
652 if(bytes > (qint64)(size0 + size1)) {
653 bytes = (qint64)(size0 + size1);
655 QByteArray src = p->read(bytes);
658 uint8_t *pp = (uint8_t *)(src.constData());
659 if(size <= (qint64)size0) {
660 memcpy(buf0, pp, size);
662 memcpy(buf0, pp, size0);
663 memcpy(buf1, pp + size0, (int)size - size0);
665 vm->inc_socket_recv_buffer_ptr(i, (int)size);
666 } else if(socket_delay[i] != 0) {
667 if(--socket_delay[i] == 0) {
668 vm->notify_socket_disconnected(i);
676 bool OSD::initialize_socket_tcp(int ch)
679 if(udp_socket[ch] != NULL) {
680 if(udp_socket[ch]->isOpen()) {
681 udp_socket[ch]->close();
683 delete udp_socket[ch];
684 udp_socket[ch] = NULL;
686 if(tcp_socket[ch] != NULL) {
687 if(tcp_socket[ch]->isOpen()) tcp_socket[ch]->close();
688 delete tcp_socket[ch];
691 tcp_socket[ch] = new QTcpSocket2(ch);
692 if(tcp_socket[ch] == NULL) return false;
693 tcp_socket[ch]->setChannel(ch);
694 connect(tcp_socket[ch], SIGNAL(connected()), tcp_socket[ch], SLOT(do_connected()));
695 connect(tcp_socket[ch], SIGNAL(sig_connected(int)), this, SLOT(do_notify_socket_connected(int)));
696 connect(tcp_socket[ch], SIGNAL(disconnected()), tcp_socket[ch], SLOT(do_disconnected()));
697 connect(tcp_socket[ch], SIGNAL(sig_disconnected(int)), this, SLOT(do_notify_socket_disconnected(int)));
702 bool OSD::initialize_socket_udp(int ch)
705 if(tcp_socket[ch] != NULL) {
706 if(tcp_socket[ch]->isOpen()) {
707 tcp_socket[ch]->close();
709 delete tcp_socket[ch];
710 tcp_socket[ch] = NULL;
712 if(udp_socket[ch] != NULL) {
713 if(udp_socket[ch]->isOpen()) udp_socket[ch]->close();
714 delete udp_socket[ch];
717 udp_socket[ch] = new QUdpSocket2(ch);
718 if(udp_socket[ch] == NULL) return false;
719 connect(udp_socket[ch], SIGNAL(connected()), udp_socket[ch], SLOT(do_connected()));
720 connect(udp_socket[ch], SIGNAL(sig_connected(int)), this, SLOT(do_notify_socket_connected(int)));
721 connect(udp_socket[ch], SIGNAL(disconnected()), udp_socket[ch], SLOT(do_disconnected()));
722 connect(udp_socket[ch], SIGNAL(sig_disconnected(int)), this, SLOT(do_notify_socket_disconnected(int)));
727 bool OSD::connect_socket(int ch, uint32_t ipaddr, int port)
730 QHostAddress addr = QHostAddress((quint32)ipaddr);
732 if(tcp_socket[ch] != NULL) {
733 tcp_socket[ch]->connectToHost(addr, (quint16)port);
738 if(udp_socket[ch] != NULL) {
739 udp_socket[ch]->connectToHost(addr, (quint16)port);
744 host_mode[ch] = false;
749 void OSD::disconnect_socket(int ch)
755 if(tcp_socket[ch] != NULL) {
756 if(tcp_socket[ch]->isOpen()) tcp_socket[ch]->close();
759 if(udp_socket[ch] != NULL) {
760 if(udp_socket[ch]->isOpen()) udp_socket[ch]->close();
765 if(tcp_socket[ch] != NULL) {
766 udp_socket[ch]->disconnectFromHost();
769 if(udp_socket[ch] != NULL) {
770 udp_socket[ch]->disconnectFromHost();
774 vm->notify_socket_disconnected(ch);
778 bool OSD::listen_socket(int ch)
781 //QHostAddress addr = QHostAddress(QHostAddress::AnyIPv4); // OK?
782 // This unit is dummy?
783 //connect(udp_socket[ch], SIGNAL(connected()), udp_socket[ch], SLOT(do_connected()));
784 //connect(udp_socket[ch], SIGNAL(sig_connected(int)), this, SLOT(do_notify_socket_connected(int)));
785 //connect(udp_socket[ch], SIGNAL(disconnected()), udp_socket[ch], SLOT(do_disconnected()));
786 //connect(udp_socket[ch], SIGNAL(sig_disconnected(int)), this, SLOT(do_notify_socket_disconnected(int)));
791 void OSD::send_socket_data_tcp(int ch)
797 uint8_t *buf = vm->get_socket_send_buffer(ch, &size);
802 if(tcp_socket[ch] != NULL) {
803 if(tcp_socket[ch]->isWritable()) {
804 size2 = tcp_socket[ch]->write((const char *)buf, (qint64)size);
806 disconnect_socket(ch);
807 notify_socket_disconnected(ch);
814 vm->inc_socket_send_buffer_ptr(ch, (int)size2);
820 void OSD::send_socket_data_udp(int ch, uint32_t ipaddr, int port)
823 QHostAddress addr = QHostAddress((quint32)ipaddr);
827 uint8_t *buf = vm->get_socket_send_buffer(ch, &size);
833 if(udp_socket[ch] != NULL) {
834 size2 = udp_socket[ch]->writeDatagram((const char *)buf, (qint64)size, addr, (quint16)port);
836 disconnect_socket(ch);
837 notify_socket_disconnected(ch);
843 vm->inc_socket_send_buffer_ptr(ch, (int)size2);
849 void OSD::send_socket_data(int ch)
854 void OSD::recv_socket_data(int ch)
859 int OSD::get_socket(int ch)
863 if(tcp_socket[ch] == NULL) return -1;
865 if(udp_socket[ch] == NULL) return -1;
872 #if defined(USE_SOCKET)
873 QTcpSocket2::QTcpSocket2(int channel, QObject *parent) : QTcpSocket(parent)
878 QTcpSocket2::~QTcpSocket2()
882 void QTcpSocket2::do_connected(void)
884 emit sig_connected(ch);
887 void QTcpSocket2::do_disconnected(void)
889 emit sig_disconnected(ch);
892 void QTcpSocket2::setChannel(int channel)
897 int QTcpSocket2::getChannel(void)
902 QUdpSocket2::QUdpSocket2(int channel, QObject *parent) : QUdpSocket(parent)
907 QUdpSocket2::~QUdpSocket2()
911 void QUdpSocket2::do_connected(void)
913 emit sig_connected(ch);
916 void QUdpSocket2::do_disconnected(void)
918 emit sig_disconnected(ch);
921 void QUdpSocket2::setChannel(int channel)
926 int QUdpSocket2::getChannel(void)