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"
29 #include "qt_gldraw.h"
30 #include "csp_logger.h"
32 void OSD::vm_draw_screen(void)
37 double OSD::vm_frame_rate(void)
39 #ifdef SUPPORT_VARIABLE_TIMING
40 return vm->get_frame_rate();
42 return FRAMES_PER_SEC;
46 Sint16* OSD::create_sound(int *extra_frames)
48 return (Sint16 *)vm->create_sound(extra_frames);
52 bool OSD::get_use_socket(void)
61 bool OSD::get_support_variable_timing(void)
63 #ifdef SUPPORT_VARIABLE_TIMING
70 bool OSD::get_notify_key_down(void)
72 #ifdef NOTIFY_KEY_DOWN
79 bool OSD::get_notify_key_down_lr_shift(void)
81 #ifdef NOTIFY_KEY_DOWN_LR_SHIFT
88 bool OSD::get_notify_key_down_lr_control(void)
90 #ifdef NOTIFY_KEY_DOWN_LR_CONTROL
97 bool OSD::get_notify_key_down_lr_menu(void)
99 #ifdef NOTIFY_KEY_DOWN_LR_MEHU
106 bool OSD::get_use_shift_numpad_key(void)
108 #ifdef USE_SHIFT_NUMPAD_KEY
115 bool OSD::get_use_auto_key(void)
124 bool OSD::get_dont_keeep_key_pressed(void)
126 #ifdef DONT_KEEEP_KEY_PRESSED
133 bool OSD::get_one_board_micro_computer(void)
135 #ifdef ONE_BOARD_MICRO_COMPUTER
142 bool OSD::get_use_screen_rotate(void)
144 #ifdef USE_SCREEN_ROTATE
151 bool OSD::get_use_movie_player(void)
153 #ifdef USE_MOVIE_PLAYER
160 bool OSD::get_use_video_capture(void)
162 #ifdef USE_VIDEO_CAPTURE
169 void OSD::vm_key_down(int code, bool flag)
171 #ifdef NOTIFY_KEY_DOWN
172 vm->key_down(code, flag);
176 void OSD::vm_key_up(int code)
178 #ifdef NOTIFY_KEY_DOWN
183 void OSD::vm_reset(void)
188 int OSD::get_vm_buttons_code(int num)
190 #ifdef ONE_BOARD_MICRO_COMPUTER
191 if(num < 0) return 0;
192 return vm_buttons[num].code;
198 void OSD::update_buttons(bool press_flag, bool release_flag)
200 #if defined(MAX_BUTTONS)
201 if(!press_flag && !release_flag) {
204 for(ii = 0; vm_buttons[ii].code != 0x00; ii++) {
205 if((mouse_ptrx >= vm_buttons[ii].x) && (mouse_ptrx < (vm_buttons[ii].x + vm_buttons[ii].width))) {
206 if((mouse_ptry >= vm_buttons[ii].y) && (mouse_ptry < (vm_buttons[ii].y + vm_buttons[ii].height))) {
207 if((key_status[vm_buttons[ii].code] & 0x7f) == 0) this->press_button(ii);
211 if((mouse_ptrx >= vm_buttons[ii].x) && (mouse_ptrx < (vm_buttons[ii].x + vm_buttons[ii].width))) {
212 if((mouse_ptry >= vm_buttons[ii].y) && (mouse_ptry < (vm_buttons[ii].y + vm_buttons[ii].height))) {
213 this->press_button(ii);
216 mouse_ptrx = mouse_ptry = 0;
222 QString OSD::get_vm_config_name(void)
224 #if defined(CONFIG_NAME)
225 return QString::fromUtf8(CONFIG_NAME);
227 return QString::fromUtf8(" ");
231 int OSD::get_screen_width(void)
236 int OSD::get_screen_height(void)
238 return SCREEN_HEIGHT;
241 void OSD::lock_vm(void)
244 if(parent_thread != NULL) {
245 if(!parent_thread->now_debugging()) VMSemaphore->acquire(1);
247 VMSemaphore->acquire(1);
251 void OSD::unlock_vm(void)
253 if(parent_thread != NULL) {
254 if(!parent_thread->now_debugging()) VMSemaphore->release(1);
256 VMSemaphore->release(1);
262 bool OSD::is_vm_locked(void)
267 void OSD::force_unlock_vm(void)
269 if(parent_thread == NULL) {
270 while(VMSemaphore->available() < 1) VMSemaphore->release(1);
274 if(parent_thread->now_debugging()) {
278 while(VMSemaphore->available() < 1) VMSemaphore->release(1);
282 void OSD::set_draw_thread(DrawThreadClass *handler)
284 this->moveToThread(handler);
285 connect(this, SIGNAL(sig_update_screen(bitmap_t *)), handler, SLOT(do_update_screen(bitmap_t *)));
286 connect(this, SIGNAL(sig_save_screen(const char *)), glv, SLOT(do_save_frame_screen(const char *)));
287 connect(this, SIGNAL(sig_resize_vm_screen(QImage *, int, int)), glv, SLOT(do_set_texture_size(QImage *, int, int)));
288 connect(parent_thread, SIGNAL(sig_debugger_input(QString)), this, SLOT(do_set_input_string(QString)));
289 connect(parent_thread, SIGNAL(sig_quit_debugger()), this, SLOT(do_close_debugger_thread()));
290 connect(this, SIGNAL(sig_close_window()), parent_thread, SLOT(doExit()));
291 connect(this, SIGNAL(sig_console_input_string(QString)), parent_thread, SLOT(do_call_debugger_command(QString)));
294 void OSD::initialize_screen()
296 host_window_width = base_window_width = WINDOW_WIDTH;
297 host_window_height = base_window_height = WINDOW_HEIGHT;
298 host_window_mode = true;
300 vm_screen_width = SCREEN_WIDTH;
301 vm_screen_height = SCREEN_HEIGHT;
302 vm_window_width = WINDOW_WIDTH;
303 vm_window_height = WINDOW_HEIGHT;
304 vm_window_width_aspect = WINDOW_WIDTH_ASPECT;
305 vm_window_height_aspect = WINDOW_HEIGHT_ASPECT;
307 QColor col(0, 0, 0, 255);
309 vm_screen_buffer.width = SCREEN_WIDTH;
310 vm_screen_buffer.height = SCREEN_HEIGHT;
311 vm_screen_buffer.pImage = QImage(SCREEN_WIDTH, SCREEN_HEIGHT, QImage::Format_ARGB32);
312 vm_screen_buffer.pImage.fill(col);
313 now_record_video = false;
315 first_draw_screen = false;
316 first_invalidate = true;
317 self_invalidate = false;
320 void OSD::release_screen()
323 release_screen_buffer(&vm_screen_buffer);
326 int OSD::get_window_mode_width(int mode)
328 if(get_use_screen_rotate()) {
329 if(p_config->rotate_type == 1 || p_config->rotate_type == 3) {
330 return (p_config->window_stretch_type == 0 ? vm_window_height : vm_window_height_aspect) * (mode + WINDOW_MODE_BASE);
333 return (p_config->window_stretch_type == 0 ? vm_window_width : vm_window_width_aspect) * (mode + WINDOW_MODE_BASE);
336 int OSD::get_window_mode_height(int mode)
338 if(get_use_screen_rotate()) {
339 if(p_config->rotate_type == 1 || p_config->rotate_type == 3) {
340 return (p_config->window_stretch_type == 0 ? vm_window_width : vm_window_width_aspect) * (mode + WINDOW_MODE_BASE);
343 return (p_config->window_stretch_type == 0 ? vm_window_height : vm_window_height_aspect) * (mode + WINDOW_MODE_BASE);
346 void OSD::initialize_video()
349 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
350 movie_loader = new MOVIE_LOADER(this, &config);
351 //connect(movie_loader, SIGNAL(sig_send_audio_frame(uint8_t *, long)), this, SLOT(do_run_movie_audio_callback2(uint8_t *, long)));
352 connect(movie_loader, SIGNAL(sig_movie_end(bool)), this, SLOT(do_video_movie_end(bool)));
353 connect(this, SIGNAL(sig_movie_play(void)), movie_loader, SLOT(do_play()));
354 connect(this, SIGNAL(sig_movie_stop(void)), movie_loader, SLOT(do_stop()));
355 connect(this, SIGNAL(sig_movie_pause(bool)), movie_loader, SLOT(do_pause(bool)));
356 connect(this, SIGNAL(sig_movie_seek_frame(bool, int)), movie_loader, SLOT(do_seek_frame(bool, int)));
357 //connect(this, SIGNAL(sig_movie_mute(bool, bool)), movie_loader, SLOT(do_mute(bool, bool)));
358 connect(movie_loader, SIGNAL(sig_decoding_error(int)), this, SLOT(do_video_decoding_error(int)));
362 void OSD::release_video()
364 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
371 bool OSD::open_movie_file(const _TCHAR* file_path)
374 if(file_path == NULL) return ret;
375 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
376 if(movie_loader != NULL) {
377 ret = movie_loader->open(QString::fromUtf8(file_path));
383 void OSD::close_movie_file()
385 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
386 if(movie_loader != NULL) {
387 movie_loader->close();
390 now_movie_play = false;
391 now_movie_pause = false;
395 uint32_t OSD::get_cur_movie_frame()
398 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
399 if(movie_loader != NULL) {
400 pos = movie_loader->get_current_frame();
404 return (uint32_t)pos;
410 void OSD::do_run_movie_audio_callback(uint8_t *data, long len)
412 if(data == NULL) return;
413 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
417 this->vm->movie_sound_callback(data, len);
425 void OSD::do_decode_movie(int frames)
427 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
428 movie_loader->do_decode_frames(frames, this->get_vm_window_width(), this->get_vm_window_height());
432 void OSD::get_video_buffer()
434 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
435 //movie_loader->do_decode_frames(1, this->get_vm_window_width(), this->get_vm_window_height());
436 movie_loader->get_video_frame();
441 int OSD::get_movie_sound_rate()
443 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
444 return movie_loader->get_movie_sound_rate();
448 void OSD::reset_vm_node()
451 device_node_list.clear();
453 for(DEVICE *p = vm->first_device; p != NULL; p = p->next_device) {
454 sp.id = p->this_device_id;
455 sp.name = p->this_device_name;
456 csp_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_GENERAL, "Device %d :%s", sp.id, sp.name);
457 device_node_list.append(sp);
458 if(max_vm_nodes <= p->this_device_id) max_vm_nodes = p->this_device_id + 1;
460 for(DEVICE *p = vm->first_device; p != NULL; p = p->next_device) {
461 emit sig_update_device_node_name(p->this_device_id, p->this_device_name);
465 #if defined(USE_SOCKET)
466 #include <QHostAddress>
467 #include "osd_socket.h"
470 void OSD::initialize_socket()
472 for(int i = 0; i < SOCKET_MAX; i++) {
473 tcp_socket[i] = NULL;
474 udp_socket[i] = NULL;
477 host_mode[i] = false;
481 void OSD::release_socket()
485 for(int i = 0; i < SOCKET_MAX; i++) {
486 if(tcp_socket[i] != NULL) {
487 if(tcp_socket[i]->isOpen()) tcp_socket[i]->close();
488 delete tcp_socket[i];
489 tcp_socket[i] = NULL;
491 if(udp_socket[i] != NULL) {
492 if(udp_socket[i]->isOpen()) udp_socket[i]->close();
493 delete udp_socket[i];
494 udp_socket[i] = NULL;
501 void OSD::notify_socket_connected(int ch)
503 do_notify_socket_connected(ch);
506 void OSD::do_notify_socket_connected(int ch)
509 vm->notify_socket_connected(ch);
514 void OSD::notify_socket_disconnected(int ch)
516 do_notify_socket_disconnected(ch);
520 void OSD::do_notify_socket_disconnected(int ch)
522 if(!socket_delay[ch]) {
523 socket_delay[ch] = 1;//56;
527 // Called per 1 frame.
528 void OSD::update_socket()
532 for(int i = 0; i < SOCKET_MAX; i++) {
535 if(tcp_socket[i] != NULL) {
536 if(tcp_socket[i]->isOpen()) {
541 if(udp_socket[i] != NULL) {
542 if(udp_socket[i]->isOpen()) {
549 bytes = p->bytesAvailable();
552 uint8_t* buf0 = vm->get_socket_recv_buffer0(i, &size0, &size1);
553 uint8_t* buf1 = vm->get_socket_recv_buffer1(i);
556 if(bytes > (qint64)(size0 + size1)) {
557 bytes = (qint64)(size0 + size1);
559 QByteArray src = p->read(bytes);
562 uint8_t *pp = (uint8_t *)(src.constData());
563 if(size <= (qint64)size0) {
564 memcpy(buf0, pp, size);
566 memcpy(buf0, pp, size0);
567 memcpy(buf1, pp + size0, (int)size - size0);
569 vm->inc_socket_recv_buffer_ptr(i, (int)size);
570 } else if(socket_delay[i] != 0) {
571 if(--socket_delay[i] == 0) {
572 vm->notify_socket_disconnected(i);
580 bool OSD::initialize_socket_tcp(int ch)
583 if(udp_socket[ch] != NULL) {
584 if(udp_socket[ch]->isOpen()) {
585 udp_socket[ch]->close();
587 delete udp_socket[ch];
588 udp_socket[ch] = NULL;
590 if(tcp_socket[ch] != NULL) {
591 if(tcp_socket[ch]->isOpen()) tcp_socket[ch]->close();
592 delete tcp_socket[ch];
595 tcp_socket[ch] = new QTcpSocket2(ch);
596 if(tcp_socket[ch] == NULL) return false;
597 tcp_socket[ch]->setChannel(ch);
598 connect(tcp_socket[ch], SIGNAL(connected()), tcp_socket[ch], SLOT(do_connected()));
599 connect(tcp_socket[ch], SIGNAL(sig_connected(int)), this, SLOT(do_notify_socket_connected(int)));
600 connect(tcp_socket[ch], SIGNAL(disconnected()), tcp_socket[ch], SLOT(do_disconnected()));
601 connect(tcp_socket[ch], SIGNAL(sig_disconnected(int)), this, SLOT(do_notify_socket_disconnected(int)));
606 bool OSD::initialize_socket_udp(int ch)
609 if(tcp_socket[ch] != NULL) {
610 if(tcp_socket[ch]->isOpen()) {
611 tcp_socket[ch]->close();
613 delete tcp_socket[ch];
614 tcp_socket[ch] = NULL;
616 if(udp_socket[ch] != NULL) {
617 if(udp_socket[ch]->isOpen()) udp_socket[ch]->close();
618 delete udp_socket[ch];
621 udp_socket[ch] = new QUdpSocket2(ch);
622 if(udp_socket[ch] == NULL) return false;
623 connect(udp_socket[ch], SIGNAL(connected()), udp_socket[ch], SLOT(do_connected()));
624 connect(udp_socket[ch], SIGNAL(sig_connected(int)), this, SLOT(do_notify_socket_connected(int)));
625 connect(udp_socket[ch], SIGNAL(disconnected()), udp_socket[ch], SLOT(do_disconnected()));
626 connect(udp_socket[ch], SIGNAL(sig_disconnected(int)), this, SLOT(do_notify_socket_disconnected(int)));
631 bool OSD::connect_socket(int ch, uint32_t ipaddr, int port)
634 QHostAddress addr = QHostAddress((quint32)ipaddr);
636 if(tcp_socket[ch] != NULL) {
637 tcp_socket[ch]->connectToHost(addr, (quint16)port);
642 if(udp_socket[ch] != NULL) {
643 udp_socket[ch]->connectToHost(addr, (quint16)port);
648 host_mode[ch] = false;
653 void OSD::disconnect_socket(int ch)
659 if(tcp_socket[ch] != NULL) {
660 if(tcp_socket[ch]->isOpen()) tcp_socket[ch]->close();
663 if(udp_socket[ch] != NULL) {
664 if(udp_socket[ch]->isOpen()) udp_socket[ch]->close();
669 if(tcp_socket[ch] != NULL) {
670 udp_socket[ch]->disconnectFromHost();
673 if(udp_socket[ch] != NULL) {
674 udp_socket[ch]->disconnectFromHost();
678 vm->notify_socket_disconnected(ch);
682 bool OSD::listen_socket(int ch)
685 //QHostAddress addr = QHostAddress(QHostAddress::AnyIPv4); // OK?
686 // This unit is dummy?
687 //connect(udp_socket[ch], SIGNAL(connected()), udp_socket[ch], SLOT(do_connected()));
688 //connect(udp_socket[ch], SIGNAL(sig_connected(int)), this, SLOT(do_notify_socket_connected(int)));
689 //connect(udp_socket[ch], SIGNAL(disconnected()), udp_socket[ch], SLOT(do_disconnected()));
690 //connect(udp_socket[ch], SIGNAL(sig_disconnected(int)), this, SLOT(do_notify_socket_disconnected(int)));
695 void OSD::send_socket_data_tcp(int ch)
701 uint8_t *buf = vm->get_socket_send_buffer(ch, &size);
706 if(tcp_socket[ch] != NULL) {
707 if(tcp_socket[ch]->isWritable()) {
708 size2 = tcp_socket[ch]->write((const char *)buf, (qint64)size);
710 disconnect_socket(ch);
711 notify_socket_disconnected(ch);
718 vm->inc_socket_send_buffer_ptr(ch, (int)size2);
724 void OSD::send_socket_data_udp(int ch, uint32_t ipaddr, int port)
727 QHostAddress addr = QHostAddress((quint32)ipaddr);
731 uint8_t *buf = vm->get_socket_send_buffer(ch, &size);
737 if(udp_socket[ch] != NULL) {
738 size2 = udp_socket[ch]->writeDatagram((const char *)buf, (qint64)size, addr, (quint16)port);
740 disconnect_socket(ch);
741 notify_socket_disconnected(ch);
747 vm->inc_socket_send_buffer_ptr(ch, (int)size2);
753 void OSD::send_socket_data(int ch)
758 void OSD::recv_socket_data(int ch)
763 int OSD::get_socket(int ch)
767 if(tcp_socket[ch] == NULL) return -1;
769 if(udp_socket[ch] == NULL) return -1;
776 #if defined(USE_SOCKET)
777 QTcpSocket2::QTcpSocket2(int channel, QObject *parent) : QTcpSocket(parent)
782 QTcpSocket2::~QTcpSocket2()
786 void QTcpSocket2::do_connected(void)
788 emit sig_connected(ch);
791 void QTcpSocket2::do_disconnected(void)
793 emit sig_disconnected(ch);
796 void QTcpSocket2::setChannel(int channel)
801 int QTcpSocket2::getChannel(void)
806 QUdpSocket2::QUdpSocket2(int channel, QObject *parent) : QUdpSocket(parent)
811 QUdpSocket2::~QUdpSocket2()
815 void QUdpSocket2::do_connected(void)
817 emit sig_connected(ch);
820 void QUdpSocket2::do_disconnected(void)
822 emit sig_disconnected(ch);
825 void QUdpSocket2::setChannel(int channel)
830 int QUdpSocket2::getChannel(void)