2 Skelton for retropc emulator
4 Author : K.Ohta <whatisthis.sowhat _at_ gmail.com>
19 #include "../vm/device.h"
23 #include "emu_thread.h"
24 #include "draw_thread.h"
25 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
26 #include "avio/movie_loader.h"
28 #if defined(USE_SOUND_FILES)
29 #include "avio/sound_loader.h"
31 #include "qt_gldraw.h"
32 #include "csp_logger.h"
34 void OSD::vm_draw_screen(void)
39 double OSD::vm_frame_rate(void)
41 #ifdef SUPPORT_VARIABLE_TIMING
42 return vm->get_frame_rate();
44 return FRAMES_PER_SEC;
48 Sint16* OSD::create_sound(int *extra_frames)
50 return (Sint16 *)vm->create_sound(extra_frames);
53 #ifdef USE_SOUND_FILES
54 void OSD::load_sound_file(int id, const _TCHAR *name, int16_t **data, int *dst_size)
57 if(data != NULL) *data = NULL;
58 if(dst_size != NULL) *dst_size = 0;
61 for(i = 0; i < USE_SOUND_FILES; i++) {
62 SOUND_LOADER *p = sound_file_obj[i];
64 if(p->get_id() == id) break;
68 if(i >= USE_SOUND_FILES) {
69 for(i = 0; i < USE_SOUND_FILES; i++) {
70 SOUND_LOADER *p = sound_file_obj[i];
79 if(i >= USE_SOUND_FILES) return;
80 SOUND_LOADER *p = sound_file_obj[i];
82 p->free_sound_buffer(NULL);
83 p->set_sound_rate(this->get_sound_rate());
84 if(p->open(id, QString::fromUtf8(name))) {
85 p->do_decode_frames();
87 if(data != NULL) *data = (int16_t *)(p->get_sound_buffer());
88 if(dst_size != NULL) *dst_size = p->get_dst_size();
93 void OSD::free_sound_file(int id, int16_t **data)
95 if(data == NULL) return;
96 for(int i = 0; i < USE_SOUND_FILES; i++) {
97 SOUND_LOADER *p = sound_file_obj[i];
99 if(p->get_id() == id) {
100 p->free_sound_buffer(*data);
108 void OSD::init_sound_files()
110 for(int i = 0; i < USE_SOUND_FILES; i++) {
111 sound_file_obj[i] = NULL;
112 SOUND_LOADER *p = new SOUND_LOADER((void *)tail_sound_file);
114 sound_file_obj[i] = p;
120 void OSD::release_sound_files()
122 for(int i = 0; i < USE_SOUND_FILES; i++) {
123 SOUND_LOADER *p = sound_file_obj[i];
124 if(p != NULL) delete p;
125 sound_file_obj[i] = NULL;
129 bool OSD::get_use_socket(void)
138 bool OSD::get_support_variable_timing(void)
140 #ifdef SUPPORT_VARIABLE_TIMING
147 bool OSD::get_notify_key_down(void)
149 #ifdef NOTIFY_KEY_DOWN
156 bool OSD::get_notify_key_down_lr_shift(void)
158 #ifdef NOTIFY_KEY_DOWN_LR_SHIFT
165 bool OSD::get_notify_key_down_lr_control(void)
167 #ifdef NOTIFY_KEY_DOWN_LR_CONTROL
174 bool OSD::get_notify_key_down_lr_menu(void)
176 #ifdef NOTIFY_KEY_DOWN_LR_MEHU
183 bool OSD::get_use_shift_numpad_key(void)
185 #ifdef USE_SHIFT_NUMPAD_KEY
192 bool OSD::get_use_auto_key(void)
201 bool OSD::get_dont_keeep_key_pressed(void)
203 #ifdef DONT_KEEEP_KEY_PRESSED
210 bool OSD::get_one_board_micro_computer(void)
212 #ifdef ONE_BOARD_MICRO_COMPUTER
219 bool OSD::get_use_screen_rotate(void)
221 #ifdef USE_SCREEN_ROTATE
228 bool OSD::get_use_movie_player(void)
230 #ifdef USE_MOVIE_PLAYER
237 bool OSD::get_use_video_capture(void)
239 #ifdef USE_VIDEO_CAPTURE
246 void OSD::vm_key_down(int code, bool flag)
248 #ifdef NOTIFY_KEY_DOWN
249 vm->key_down(code, flag);
253 void OSD::vm_key_up(int code)
255 #ifdef NOTIFY_KEY_DOWN
260 void OSD::vm_reset(void)
265 int OSD::get_vm_buttons_code(int num)
267 #ifdef ONE_BOARD_MICRO_COMPUTER
268 if(num < 0) return 0;
269 return vm_buttons[num].code;
275 void OSD::update_buttons(bool press_flag, bool release_flag)
277 #if defined(MAX_BUTTONS)
278 if(!press_flag && !release_flag) {
281 for(ii = 0; vm_buttons[ii].code != 0x00; ii++) {
282 if((mouse_ptrx >= vm_buttons[ii].x) && (mouse_ptrx < (vm_buttons[ii].x + vm_buttons[ii].width))) {
283 if((mouse_ptry >= vm_buttons[ii].y) && (mouse_ptry < (vm_buttons[ii].y + vm_buttons[ii].height))) {
284 if((key_status[vm_buttons[ii].code] & 0x7f) == 0) this->press_button(ii);
288 if((mouse_ptrx >= vm_buttons[ii].x) && (mouse_ptrx < (vm_buttons[ii].x + vm_buttons[ii].width))) {
289 if((mouse_ptry >= vm_buttons[ii].y) && (mouse_ptry < (vm_buttons[ii].y + vm_buttons[ii].height))) {
290 this->press_button(ii);
293 mouse_ptrx = mouse_ptry = 0;
299 QString OSD::get_vm_config_name(void)
301 #if defined(CONFIG_NAME)
302 return QString::fromUtf8(CONFIG_NAME);
304 return QString::fromUtf8(" ");
308 int OSD::get_screen_width(void)
313 int OSD::get_screen_height(void)
315 return SCREEN_HEIGHT;
318 void OSD::lock_vm(void)
321 if(parent_thread != NULL) {
322 if(!parent_thread->now_debugging()) VMSemaphore->acquire(1);
324 VMSemaphore->acquire(1);
328 void OSD::unlock_vm(void)
330 if(parent_thread != NULL) {
331 if(!parent_thread->now_debugging()) VMSemaphore->release(1);
333 VMSemaphore->release(1);
339 bool OSD::is_vm_locked(void)
344 void OSD::force_unlock_vm(void)
346 if(parent_thread == NULL) {
347 while(VMSemaphore->available() < 1) VMSemaphore->release(1);
351 if(parent_thread->now_debugging()) {
355 while(VMSemaphore->available() < 1) VMSemaphore->release(1);
359 void OSD::set_draw_thread(DrawThreadClass *handler)
361 //this->moveToThread(handler);
362 connect(this, SIGNAL(sig_update_screen(bitmap_t *)), handler, SLOT(do_update_screen(bitmap_t *)));
363 connect(this, SIGNAL(sig_save_screen(const char *)), glv, SLOT(do_save_frame_screen(const char *)));
364 connect(this, SIGNAL(sig_resize_vm_screen(QImage *, int, int)), glv, SLOT(do_set_texture_size(QImage *, int, int)));
365 connect(parent_thread, SIGNAL(sig_debugger_input(QString)), this, SLOT(do_set_input_string(QString)));
366 connect(parent_thread, SIGNAL(sig_quit_debugger()), this, SLOT(do_close_debugger_thread()));
367 connect(this, SIGNAL(sig_close_window()), parent_thread, SLOT(doExit()));
370 void OSD::initialize_screen()
372 host_window_width = base_window_width = WINDOW_WIDTH;
373 host_window_height = base_window_height = WINDOW_HEIGHT;
374 host_window_mode = true;
376 vm_screen_width = SCREEN_WIDTH;
377 vm_screen_height = SCREEN_HEIGHT;
378 vm_window_width = WINDOW_WIDTH;
379 vm_window_height = WINDOW_HEIGHT;
380 vm_window_width_aspect = WINDOW_WIDTH_ASPECT;
381 vm_window_height_aspect = WINDOW_HEIGHT_ASPECT;
383 QColor col(0, 0, 0, 255);
385 vm_screen_buffer.width = SCREEN_WIDTH;
386 vm_screen_buffer.height = SCREEN_HEIGHT;
387 vm_screen_buffer.pImage = QImage(SCREEN_WIDTH, SCREEN_HEIGHT, QImage::Format_ARGB32);
388 vm_screen_buffer.pImage.fill(col);
389 now_record_video = false;
391 first_draw_screen = false;
392 first_invalidate = true;
393 self_invalidate = false;
396 void OSD::release_screen()
399 release_screen_buffer(&vm_screen_buffer);
402 int OSD::get_window_mode_width(int mode)
404 if(get_use_screen_rotate()) {
405 if(p_config->rotate_type == 1 || p_config->rotate_type == 3) {
406 return (p_config->window_stretch_type == 0 ? vm_window_height : vm_window_height_aspect) * (mode + WINDOW_MODE_BASE);
409 return (p_config->window_stretch_type == 0 ? vm_window_width : vm_window_width_aspect) * (mode + WINDOW_MODE_BASE);
412 int OSD::get_window_mode_height(int mode)
414 if(get_use_screen_rotate()) {
415 if(p_config->rotate_type == 1 || p_config->rotate_type == 3) {
416 return (p_config->window_stretch_type == 0 ? vm_window_width : vm_window_width_aspect) * (mode + WINDOW_MODE_BASE);
419 return (p_config->window_stretch_type == 0 ? vm_window_height : vm_window_height_aspect) * (mode + WINDOW_MODE_BASE);
422 void OSD::initialize_video()
425 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
426 movie_loader = new MOVIE_LOADER(this, &config);
427 //connect(movie_loader, SIGNAL(sig_send_audio_frame(uint8_t *, long)), this, SLOT(do_run_movie_audio_callback2(uint8_t *, long)));
428 connect(movie_loader, SIGNAL(sig_movie_end(bool)), this, SLOT(do_video_movie_end(bool)));
429 connect(this, SIGNAL(sig_movie_play(void)), movie_loader, SLOT(do_play()));
430 connect(this, SIGNAL(sig_movie_stop(void)), movie_loader, SLOT(do_stop()));
431 connect(this, SIGNAL(sig_movie_pause(bool)), movie_loader, SLOT(do_pause(bool)));
432 connect(this, SIGNAL(sig_movie_seek_frame(bool, int)), movie_loader, SLOT(do_seek_frame(bool, int)));
433 //connect(this, SIGNAL(sig_movie_mute(bool, bool)), movie_loader, SLOT(do_mute(bool, bool)));
434 connect(movie_loader, SIGNAL(sig_decoding_error(int)), this, SLOT(do_video_decoding_error(int)));
438 void OSD::release_video()
440 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
447 bool OSD::open_movie_file(const _TCHAR* file_path)
450 if(file_path == NULL) return ret;
451 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
452 if(movie_loader != NULL) {
453 ret = movie_loader->open(QString::fromUtf8(file_path));
459 void OSD::close_movie_file()
461 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
462 if(movie_loader != NULL) {
463 movie_loader->close();
466 now_movie_play = false;
467 now_movie_pause = false;
471 uint32_t OSD::get_cur_movie_frame()
473 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
474 if(movie_loader != NULL) {
476 pos = movie_loader->get_current_frame();
480 return (uint32_t)pos;
486 void OSD::do_run_movie_audio_callback(uint8_t *data, long len)
488 if(data == NULL) return;
489 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
493 this->vm->movie_sound_callback(data, len);
501 void OSD::do_decode_movie(int frames)
503 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
504 movie_loader->do_decode_frames(frames, this->get_vm_window_width(), this->get_vm_window_height());
508 void OSD::get_video_buffer()
510 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
511 //movie_loader->do_decode_frames(1, this->get_vm_window_width(), this->get_vm_window_height());
512 movie_loader->get_video_frame();
517 int OSD::get_movie_sound_rate()
519 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
520 return movie_loader->get_movie_sound_rate();
525 void OSD::reset_vm_node()
528 device_node_list.clear();
531 for(DEVICE *p = vm->first_device; p != NULL; p = p->next_device) {
532 sp.id = p->this_device_id;
533 sp.name = p->this_device_name;
534 csp_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_GENERAL, "Device %d :%s", sp.id, sp.name);
535 device_node_list.append(sp);
536 if(max_vm_nodes <= p->this_device_id) max_vm_nodes = p->this_device_id + 1;
538 for(DEVICE *p = vm->first_device; p != NULL; p = p->next_device) {
539 emit sig_update_device_node_name(p->this_device_id, p->this_device_name);
543 #if defined(USE_SOCKET)
544 #include <QHostAddress>
545 #include "osd_socket.h"
548 void OSD::initialize_socket()
550 for(int i = 0; i < SOCKET_MAX; i++) {
551 tcp_socket[i] = NULL;
552 udp_socket[i] = NULL;
555 host_mode[i] = false;
559 void OSD::release_socket()
563 for(int i = 0; i < SOCKET_MAX; i++) {
564 if(tcp_socket[i] != NULL) {
565 if(tcp_socket[i]->isOpen()) tcp_socket[i]->close();
566 delete tcp_socket[i];
567 tcp_socket[i] = NULL;
569 if(udp_socket[i] != NULL) {
570 if(udp_socket[i]->isOpen()) udp_socket[i]->close();
571 delete udp_socket[i];
572 udp_socket[i] = NULL;
579 void OSD::notify_socket_connected(int ch)
581 do_notify_socket_connected(ch);
584 void OSD::do_notify_socket_connected(int ch)
587 vm->notify_socket_connected(ch);
592 void OSD::notify_socket_disconnected(int ch)
594 do_notify_socket_disconnected(ch);
598 void OSD::do_notify_socket_disconnected(int ch)
600 if(!socket_delay[ch]) {
601 socket_delay[ch] = 1;//56;
605 // Called per 1 frame.
606 void OSD::update_socket()
610 for(int i = 0; i < SOCKET_MAX; i++) {
613 if(tcp_socket[i] != NULL) {
614 if(tcp_socket[i]->isOpen()) {
619 if(udp_socket[i] != NULL) {
620 if(udp_socket[i]->isOpen()) {
627 bytes = p->bytesAvailable();
630 uint8_t* buf0 = vm->get_socket_recv_buffer0(i, &size0, &size1);
631 uint8_t* buf1 = vm->get_socket_recv_buffer1(i);
634 if(bytes > (qint64)(size0 + size1)) {
635 bytes = (qint64)(size0 + size1);
637 QByteArray src = p->read(bytes);
640 uint8_t *pp = (uint8_t *)(src.constData());
641 if(size <= (qint64)size0) {
642 memcpy(buf0, pp, size);
644 memcpy(buf0, pp, size0);
645 memcpy(buf1, pp + size0, (int)size - size0);
647 vm->inc_socket_recv_buffer_ptr(i, (int)size);
648 } else if(socket_delay[i] != 0) {
649 if(--socket_delay[i] == 0) {
650 vm->notify_socket_disconnected(i);
658 bool OSD::initialize_socket_tcp(int ch)
661 if(udp_socket[ch] != NULL) {
662 if(udp_socket[ch]->isOpen()) {
663 udp_socket[ch]->close();
665 delete udp_socket[ch];
666 udp_socket[ch] = NULL;
668 if(tcp_socket[ch] != NULL) {
669 if(tcp_socket[ch]->isOpen()) tcp_socket[ch]->close();
670 delete tcp_socket[ch];
673 tcp_socket[ch] = new QTcpSocket2(ch);
674 if(tcp_socket[ch] == NULL) return false;
675 tcp_socket[ch]->setChannel(ch);
676 connect(tcp_socket[ch], SIGNAL(connected()), tcp_socket[ch], SLOT(do_connected()));
677 connect(tcp_socket[ch], SIGNAL(sig_connected(int)), this, SLOT(do_notify_socket_connected(int)));
678 connect(tcp_socket[ch], SIGNAL(disconnected()), tcp_socket[ch], SLOT(do_disconnected()));
679 connect(tcp_socket[ch], SIGNAL(sig_disconnected(int)), this, SLOT(do_notify_socket_disconnected(int)));
684 bool OSD::initialize_socket_udp(int ch)
687 if(tcp_socket[ch] != NULL) {
688 if(tcp_socket[ch]->isOpen()) {
689 tcp_socket[ch]->close();
691 delete tcp_socket[ch];
692 tcp_socket[ch] = NULL;
694 if(udp_socket[ch] != NULL) {
695 if(udp_socket[ch]->isOpen()) udp_socket[ch]->close();
696 delete udp_socket[ch];
699 udp_socket[ch] = new QUdpSocket2(ch);
700 if(udp_socket[ch] == NULL) return false;
701 connect(udp_socket[ch], SIGNAL(connected()), udp_socket[ch], SLOT(do_connected()));
702 connect(udp_socket[ch], SIGNAL(sig_connected(int)), this, SLOT(do_notify_socket_connected(int)));
703 connect(udp_socket[ch], SIGNAL(disconnected()), udp_socket[ch], SLOT(do_disconnected()));
704 connect(udp_socket[ch], SIGNAL(sig_disconnected(int)), this, SLOT(do_notify_socket_disconnected(int)));
709 bool OSD::connect_socket(int ch, uint32_t ipaddr, int port)
712 QHostAddress addr = QHostAddress((quint32)ipaddr);
714 if(tcp_socket[ch] != NULL) {
715 tcp_socket[ch]->connectToHost(addr, (quint16)port);
720 if(udp_socket[ch] != NULL) {
721 udp_socket[ch]->connectToHost(addr, (quint16)port);
726 host_mode[ch] = false;
731 void OSD::disconnect_socket(int ch)
737 if(tcp_socket[ch] != NULL) {
738 if(tcp_socket[ch]->isOpen()) tcp_socket[ch]->close();
741 if(udp_socket[ch] != NULL) {
742 if(udp_socket[ch]->isOpen()) udp_socket[ch]->close();
747 if(tcp_socket[ch] != NULL) {
748 udp_socket[ch]->disconnectFromHost();
751 if(udp_socket[ch] != NULL) {
752 udp_socket[ch]->disconnectFromHost();
756 vm->notify_socket_disconnected(ch);
760 bool OSD::listen_socket(int ch)
763 //QHostAddress addr = QHostAddress(QHostAddress::AnyIPv4); // OK?
764 // This unit is dummy?
765 //connect(udp_socket[ch], SIGNAL(connected()), udp_socket[ch], SLOT(do_connected()));
766 //connect(udp_socket[ch], SIGNAL(sig_connected(int)), this, SLOT(do_notify_socket_connected(int)));
767 //connect(udp_socket[ch], SIGNAL(disconnected()), udp_socket[ch], SLOT(do_disconnected()));
768 //connect(udp_socket[ch], SIGNAL(sig_disconnected(int)), this, SLOT(do_notify_socket_disconnected(int)));
773 void OSD::send_socket_data_tcp(int ch)
779 uint8_t *buf = vm->get_socket_send_buffer(ch, &size);
784 if(tcp_socket[ch] != NULL) {
785 if(tcp_socket[ch]->isWritable()) {
786 size2 = tcp_socket[ch]->write((const char *)buf, (qint64)size);
788 disconnect_socket(ch);
789 notify_socket_disconnected(ch);
796 vm->inc_socket_send_buffer_ptr(ch, (int)size2);
802 void OSD::send_socket_data_udp(int ch, uint32_t ipaddr, int port)
805 QHostAddress addr = QHostAddress((quint32)ipaddr);
809 uint8_t *buf = vm->get_socket_send_buffer(ch, &size);
815 if(udp_socket[ch] != NULL) {
816 size2 = udp_socket[ch]->writeDatagram((const char *)buf, (qint64)size, addr, (quint16)port);
818 disconnect_socket(ch);
819 notify_socket_disconnected(ch);
825 vm->inc_socket_send_buffer_ptr(ch, (int)size2);
831 void OSD::send_socket_data(int ch)
836 void OSD::recv_socket_data(int ch)
841 int OSD::get_socket(int ch)
845 if(tcp_socket[ch] == NULL) return -1;
847 if(udp_socket[ch] == NULL) return -1;
854 #if defined(USE_SOCKET)
855 QTcpSocket2::QTcpSocket2(int channel, QObject *parent) : QTcpSocket(parent)
860 QTcpSocket2::~QTcpSocket2()
864 void QTcpSocket2::do_connected(void)
866 emit sig_connected(ch);
869 void QTcpSocket2::do_disconnected(void)
871 emit sig_disconnected(ch);
874 void QTcpSocket2::setChannel(int channel)
879 int QTcpSocket2::getChannel(void)
884 QUdpSocket2::QUdpSocket2(int channel, QObject *parent) : QUdpSocket(parent)
889 QUdpSocket2::~QUdpSocket2()
893 void QUdpSocket2::do_connected(void)
895 emit sig_connected(ch);
898 void QUdpSocket2::do_disconnected(void)
900 emit sig_disconnected(ch);
903 void QUdpSocket2::setChannel(int channel)
908 int QUdpSocket2::getChannel(void)