2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
7 [ win32 emulation i/f ]
18 // ----------------------------------------------------------------------------
20 // ----------------------------------------------------------------------------
21 static const int sound_frequency_table[8] = {
22 2000, 4000, 8000, 11025, 22050, 44100,
23 #ifdef OVERRIDE_SOUND_FREQ_48000HZ
24 OVERRIDE_SOUND_FREQ_48000HZ,
30 static const double sound_latency_table[5] = {0.05, 0.1, 0.2, 0.3, 0.4};
33 // Please permit at least them m(.. )m
34 //extern void get_long_full_path_name(_TCHAR* src, _TCHAR* dst);
36 extern CSP_Logger *csp_logger;
40 EMU::EMU(class Ui_MainWindow *hwnd, GLDrawClass *hinst, USING_FLAGS *p)
41 #elif defined(OSD_WIN32)
42 EMU::EMU(HWND hwnd, HINSTANCE hinst)
48 // store main window handle
49 #ifdef USE_FLOPPY_DISK
50 // initialize d88 file info
51 memset(d88_file, 0, sizeof(d88_file));
54 // initialize d88 file info
55 memset(b77_file, 0, sizeof(b77_file));
59 if(!(0 <= config.sound_frequency && config.sound_frequency < 8)) {
60 config.sound_frequency = 6; // default: 48KHz
62 if(!(0 <= config.sound_latency && config.sound_latency < 5)) {
63 config.sound_latency = 1; // default: 100msec
65 sound_frequency = config.sound_frequency;
66 sound_latency = config.sound_latency;
67 sound_rate = sound_frequency_table[config.sound_frequency];
68 sound_samples = (int)(sound_rate * sound_latency_table[config.sound_latency] + 0.5);
71 cpu_type = config.cpu_type;
74 sound_type = config.sound_type;
76 #ifdef USE_PRINTER_TYPE
77 printer_type = config.printer_type;
80 // initialize b77 file info
81 memset(b77_file, 0, sizeof(b77_file));
86 osd = new OSD(p, csp_logger);
87 osd->main_window_handle = hwnd;
90 #elif defined(OSD_WIN32)
92 osd->main_window_handle = hwnd;
93 osd->instance_handle = hinst;
95 osd->initialize(sound_rate, sound_samples);
97 osd->vm = vm = new VM(this);
102 initialize_auto_key();
105 initialize_debugger();
108 vm->initialize_sound(sound_rate, sound_samples);
109 #ifdef USE_SOUND_VOLUME
110 for(int i = 0; i < USE_SOUND_VOLUME; i++) {
111 vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
115 now_suspended = false;
135 EmuThreadClass *EMU::get_parent_handler()
137 return osd->get_parent_handler();
140 void EMU::set_parent_handler(EmuThreadClass *p, DrawThreadClass *q)
142 osd->set_parent_thread(p);
143 osd->set_draw_thread(q);
146 void EMU::set_host_cpus(int v)
148 osd->host_cpus = (v <= 0) ? 1 : v;
151 int EMU::get_host_cpus()
153 return osd->host_cpus;
157 // ----------------------------------------------------------------------------
159 // ----------------------------------------------------------------------------
161 double EMU::get_frame_rate()
163 #ifdef SUPPORT_VARIABLE_TIMING
164 return vm->get_frame_rate();
166 return FRAMES_PER_SEC;
170 int EMU::get_frame_interval()
172 #ifdef SUPPORT_VARIABLE_TIMING
173 static int prev_interval = 0;
174 static double prev_fps = -1;
175 double fps = vm->get_frame_rate();
176 if(prev_fps != fps) {
177 prev_interval = (int)(1024. * 1000. / fps + 0.5);
180 return prev_interval;
182 return (int)(1024. * 1000. / FRAMES_PER_SEC + 0.5);
186 bool EMU::is_frame_skippable()
188 return vm->is_frame_skippable();
195 now_suspended = false;
206 #if !defined(_USE_QT) // Temporally
207 osd->update_socket();
212 // virtual machine may be driven to fill sound buffer
213 int extra_frames = 0;
214 osd->update_sound(&extra_frames);
216 // drive virtual machine
217 if(extra_frames == 0) {
223 osd->add_extra_frames(extra_frames);
231 config.romaji_to_kana = false;
234 // check if virtual machine should be reinitialized
235 bool reinitialize = false;
237 reinitialize |= (cpu_type != config.cpu_type);
238 cpu_type = config.cpu_type;
240 #ifdef USE_SOUND_TYPE
241 reinitialize |= (sound_type != config.sound_type);
242 sound_type = config.sound_type;
244 #ifdef USE_PRINTER_TYPE
245 reinitialize |= (printer_type != config.printer_type);
246 printer_type = config.printer_type;
251 // reinitialize virtual machine
254 osd->vm = vm = new VM(this);
256 osd->reset_vm_node();
258 sound_rate = sound_frequency_table[config.sound_frequency];
259 sound_samples = (int)(sound_rate * sound_latency_table[config.sound_latency] + 0.5);
260 vm->initialize_sound(sound_rate, sound_samples);
261 #ifdef USE_SOUND_VOLUME
262 for(int i = 0; i < USE_SOUND_VOLUME; i++) {
263 vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
268 // restore inserted medias
271 // reset virtual machine
277 #if !defined(_USE_QT) // Temporally
279 osd->restart_record_sound();
280 osd->restart_record_video();
284 #ifdef USE_SPECIAL_RESET
285 void EMU::special_reset()
289 config.romaji_to_kana = false;
292 // reset virtual machine
297 #if !defined(_USE_QT) // Temporally
298 restart_record_sound();
299 restart_record_video();
304 #ifdef USE_NOTIFY_POWER_OFF
305 void EMU::notify_power_off()
307 vm->notify_power_off();
311 void EMU::power_off()
320 now_suspended = true;
329 void EMU::unlock_vm()
334 void EMU::force_unlock_vm()
336 osd->force_unlock_vm();
339 bool EMU::is_vm_locked()
341 return osd->is_vm_locked();
344 // ----------------------------------------------------------------------------
346 // ----------------------------------------------------------------------------
349 void EMU::key_down(int code, bool extended, bool repeat)
353 shift_pressed = true;
355 if(config.romaji_to_kana) {
357 // Page Up, Page Down, End, Home, Left, Up, Right, Down, Ins, Del, Help, and F1-F12
358 if((code >= 0x21 && code <= 0x2f) || (code >= 0x70 && code <= 0x7b)) {
360 auto_key_buffer->write(code | 0x100);
362 auto_key_buffer->write(code);
364 if(!is_auto_key_running()) {
369 } else if(!is_auto_key_running())
371 osd->key_down(code, extended, repeat);
374 void EMU::key_up(int code, bool extended)
378 shift_pressed = false;
380 if(config.romaji_to_kana) {
382 } else if(!is_auto_key_running())
384 osd->key_up(code, extended);
387 void EMU::key_char(char code)
390 if(config.romaji_to_kana) {
391 set_auto_key_char(code);
396 #ifdef USE_KEY_LOCKED
397 bool EMU::get_caps_locked()
399 return vm->get_caps_locked();
402 bool EMU::get_kana_locked()
404 return vm->get_kana_locked();
408 void EMU::key_lost_focus()
410 osd->key_lost_focus();
413 #ifdef ONE_BOARD_MICRO_COMPUTER
414 void EMU::press_button(int num)
416 int code = vm_buttons[num].code;
419 osd->key_down_native(code, false);
420 osd->get_key_buffer()[code] = KEY_KEEP_FRAMES;
422 // code=0: reset virtual machine
429 void EMU::enable_mouse()
434 void EMU::disable_mouse()
436 osd->disable_mouse();
439 void EMU::toggle_mouse()
444 bool EMU::is_mouse_enabled()
446 return osd->is_mouse_enabled();
451 static const int auto_key_table_base[][2] = {
456 {0x08, 0x000 | 0x08}, // BS
457 {0x09, 0x000 | 0x09}, // Tab
458 {0x0d, 0x000 | 0x0d}, // Enter
459 {0x1b, 0x000 | 0x1b}, // Escape
460 {0x20, 0x000 | 0x20}, // ' '
462 {0x21, 0x100 | 0x31}, // '!'
463 {0x22, 0x100 | 0xba}, // '"'
464 {0x23, 0x100 | 0x33}, // '#'
465 {0x24, 0x100 | 0x34}, // '$'
466 {0x25, 0x100 | 0x35}, // '%'
467 {0x26, 0x100 | 0x37}, // '&'
468 {0x27, 0x000 | 0xba}, // '''
469 {0x28, 0x100 | 0x39}, // '('
470 {0x29, 0x100 | 0x30}, // ')'
471 {0x2a, 0x100 | 0x38}, // '*'
472 {0x2b, 0x100 | 0xde}, // '+'
473 {0x2c, 0x000 | 0xbc}, // ','
474 {0x2d, 0x000 | 0xbd}, // '-'
475 {0x2e, 0x000 | 0xbe}, // '.'
476 {0x2f, 0x000 | 0xbf}, // '/'
478 {0x21, 0x100 | 0x31}, // '!'
479 {0x22, 0x100 | 0x32}, // '"'
480 {0x23, 0x100 | 0x33}, // '#'
481 {0x24, 0x100 | 0x34}, // '$'
482 {0x25, 0x100 | 0x35}, // '%'
483 {0x26, 0x100 | 0x36}, // '&'
484 {0x27, 0x100 | 0x37}, // '''
485 {0x28, 0x100 | 0x38}, // '('
486 {0x29, 0x100 | 0x39}, // ')'
487 {0x2a, 0x100 | 0xba}, // '*'
488 {0x2b, 0x100 | 0xbb}, // '+'
489 {0x2c, 0x000 | 0xbc}, // ','
490 {0x2d, 0x000 | 0xbd}, // '-'
491 {0x2e, 0x000 | 0xbe}, // '.'
492 {0x2f, 0x000 | 0xbf}, // '/'
494 {0x30, 0x000 | 0x30}, // '0'
495 {0x31, 0x000 | 0x31}, // '1'
496 {0x32, 0x000 | 0x32}, // '2'
497 {0x33, 0x000 | 0x33}, // '3'
498 {0x34, 0x000 | 0x34}, // '4'
499 {0x35, 0x000 | 0x35}, // '5'
500 {0x36, 0x000 | 0x36}, // '6'
501 {0x37, 0x000 | 0x37}, // '7'
502 {0x38, 0x000 | 0x38}, // '8'
503 {0x39, 0x000 | 0x39}, // '9'
505 {0x3a, 0x100 | 0xbb}, // ':'
506 {0x3b, 0x000 | 0xbb}, // ';'
507 {0x3c, 0x100 | 0xbc}, // '<'
508 {0x3d, 0x000 | 0xde}, // '='
509 {0x3e, 0x100 | 0xbe}, // '>'
510 {0x3f, 0x100 | 0xbf}, // '?'
511 {0x40, 0x100 | 0x32}, // '@'
513 {0x3a, 0x000 | 0xba}, // ':'
514 {0x3b, 0x000 | 0xbb}, // ';'
515 {0x3c, 0x100 | 0xbc}, // '<'
516 {0x3d, 0x100 | 0xbd}, // '='
517 {0x3e, 0x100 | 0xbe}, // '>'
518 {0x3f, 0x100 | 0xbf}, // '?'
519 {0x40, 0x000 | 0xc0}, // '@'
521 {0x41, 0x400 | 0x41}, // 'A'
522 {0x42, 0x400 | 0x42}, // 'B'
523 {0x43, 0x400 | 0x43}, // 'C'
524 {0x44, 0x400 | 0x44}, // 'D'
525 {0x45, 0x400 | 0x45}, // 'E'
526 {0x46, 0x400 | 0x46}, // 'F'
527 {0x47, 0x400 | 0x47}, // 'G'
528 {0x48, 0x400 | 0x48}, // 'H'
529 {0x49, 0x400 | 0x49}, // 'I'
530 {0x4a, 0x400 | 0x4a}, // 'J'
531 {0x4b, 0x400 | 0x4b}, // 'K'
532 {0x4c, 0x400 | 0x4c}, // 'L'
533 {0x4d, 0x400 | 0x4d}, // 'M'
534 {0x4e, 0x400 | 0x4e}, // 'N'
535 {0x4f, 0x400 | 0x4f}, // 'O'
536 {0x50, 0x400 | 0x50}, // 'P'
537 {0x51, 0x400 | 0x51}, // 'Q'
538 {0x52, 0x400 | 0x52}, // 'R'
539 {0x53, 0x400 | 0x53}, // 'S'
540 {0x54, 0x400 | 0x54}, // 'T'
541 {0x55, 0x400 | 0x55}, // 'U'
542 {0x56, 0x400 | 0x56}, // 'V'
543 {0x57, 0x400 | 0x57}, // 'W'
544 {0x58, 0x400 | 0x58}, // 'X'
545 {0x59, 0x400 | 0x59}, // 'Y'
546 {0x5a, 0x400 | 0x5a}, // 'Z'
548 {0x5b, 0x000 | 0xc0}, // '['
549 {0x5c, 0x000 | 0xe2}, // '\'
550 {0x5d, 0x000 | 0xdb}, // ']'
551 {0x5e, 0x100 | 0x36}, // '^'
552 {0x5f, 0x100 | 0xbd}, // '_'
553 {0x60, 0x000 | 0xdd}, // '`'
555 {0x5b, 0x000 | 0xdb}, // '['
556 {0x5c, 0x000 | 0xdc}, // '\'
557 {0x5d, 0x000 | 0xdd}, // ']'
558 {0x5e, 0x000 | 0xde}, // '^'
559 {0x5f, 0x100 | 0xe2}, // '_'
560 {0x60, 0x100 | 0xc0}, // '`'
562 {0x61, 0x800 | 0x41}, // 'a'
563 {0x62, 0x800 | 0x42}, // 'b'
564 {0x63, 0x800 | 0x43}, // 'c'
565 {0x64, 0x800 | 0x44}, // 'd'
566 {0x65, 0x800 | 0x45}, // 'e'
567 {0x66, 0x800 | 0x46}, // 'f'
568 {0x67, 0x800 | 0x47}, // 'g'
569 {0x68, 0x800 | 0x48}, // 'h'
570 {0x69, 0x800 | 0x49}, // 'i'
571 {0x6a, 0x800 | 0x4a}, // 'j'
572 {0x6b, 0x800 | 0x4b}, // 'k'
573 {0x6c, 0x800 | 0x4c}, // 'l'
574 {0x6d, 0x800 | 0x4d}, // 'm'
575 {0x6e, 0x800 | 0x4e}, // 'n'
576 {0x6f, 0x800 | 0x4f}, // 'o'
577 {0x70, 0x800 | 0x50}, // 'p'
578 {0x71, 0x800 | 0x51}, // 'q'
579 {0x72, 0x800 | 0x52}, // 'r'
580 {0x73, 0x800 | 0x53}, // 's'
581 {0x74, 0x800 | 0x54}, // 't'
582 {0x75, 0x800 | 0x55}, // 'u'
583 {0x76, 0x800 | 0x56}, // 'v'
584 {0x77, 0x800 | 0x57}, // 'w'
585 {0x78, 0x800 | 0x58}, // 'x'
586 {0x79, 0x800 | 0x59}, // 'y'
587 {0x7a, 0x800 | 0x5a}, // 'z'
589 {0x7b, 0x100 | 0xc0}, // '{'
590 {0x7c, 0x100 | 0xe2}, // '|'
591 {0x7d, 0x100 | 0xdb}, // '}'
592 {0x7e, 0x100 | 0xdd}, // '~'
594 {0x7b, 0x100 | 0xdb}, // '{'
595 {0x7c, 0x100 | 0xdc}, // '|'
596 {0x7d, 0x100 | 0xdd}, // '}'
597 {0x7e, 0x100 | 0xde}, // '~'
602 static const int auto_key_table_kana_base[][2] = {
603 {0xa1, 0x300 | 0xbe}, // '¡'
604 {0xa2, 0x300 | 0xdb}, // '¢'
605 {0xa3, 0x300 | 0xdd}, // '£'
606 {0xa4, 0x300 | 0xbc}, // '¤'
607 {0xa5, 0x300 | 0xbf}, // '¥'
608 {0xa6, 0x300 | 0x30}, // '¦'
609 {0xa7, 0x300 | 0x33}, // '§'
610 {0xa8, 0x300 | 0x45}, // '¨'
611 {0xa9, 0x300 | 0x34}, // '©'
612 {0xaa, 0x300 | 0x35}, // 'ª'
613 {0xab, 0x300 | 0x36}, // '«'
614 {0xac, 0x300 | 0x37}, // '¬'
615 {0xad, 0x300 | 0x38}, // ''
616 {0xae, 0x300 | 0x39}, // '®'
617 {0xaf, 0x300 | 0x5a}, // '¯'
618 {0xb0, 0x200 | 0xdc}, // '°'
619 {0xb1, 0x200 | 0x33}, // '±'
620 {0xb2, 0x200 | 0x45}, // '²'
621 {0xb3, 0x200 | 0x34}, // '³'
622 {0xb4, 0x200 | 0x35}, // '´'
623 {0xb5, 0x200 | 0x36}, // 'µ'
624 {0xb6, 0x200 | 0x54}, // '¶'
625 {0xb7, 0x200 | 0x47}, // '·'
626 {0xb8, 0x200 | 0x48}, // '¸'
627 {0xb9, 0x200 | 0xba}, // '¹'
628 {0xba, 0x200 | 0x42}, // 'º'
629 {0xbb, 0x200 | 0x58}, // '»'
630 {0xbc, 0x200 | 0x44}, // '¼'
631 {0xbd, 0x200 | 0x52}, // '½'
632 {0xbe, 0x200 | 0x50}, // '¾'
633 {0xbf, 0x200 | 0x43}, // '¿'
634 {0xc0, 0x200 | 0x51}, // 'À'
635 {0xc1, 0x200 | 0x41}, // 'Á'
636 {0xc2, 0x200 | 0x5a}, // 'Â'
637 {0xc3, 0x200 | 0x57}, // 'Ã'
638 {0xc4, 0x200 | 0x53}, // 'Ä'
639 {0xc5, 0x200 | 0x55}, // 'Å'
640 {0xc6, 0x200 | 0x49}, // 'Æ'
641 {0xc7, 0x200 | 0x31}, // 'Ç'
642 {0xc8, 0x200 | 0xbc}, // 'È'
643 {0xc9, 0x200 | 0x4b}, // 'É'
644 {0xca, 0x200 | 0x46}, // 'Ê'
645 {0xcb, 0x200 | 0x56}, // 'Ë'
646 {0xcc, 0x200 | 0x32}, // 'Ì'
647 {0xcd, 0x200 | 0xde}, // 'Í'
648 {0xce, 0x200 | 0xbd}, // 'Î'
649 {0xcf, 0x200 | 0x4a}, // 'Ï'
650 {0xd0, 0x200 | 0x4e}, // 'Ð'
651 {0xd1, 0x200 | 0xdd}, // 'Ñ'
652 {0xd2, 0x200 | 0xbf}, // 'Ò'
653 {0xd3, 0x200 | 0x4d}, // 'Ó'
654 {0xd4, 0x200 | 0x37}, // 'Ô'
655 {0xd5, 0x200 | 0x38}, // 'Õ'
656 {0xd6, 0x200 | 0x39}, // 'Ö'
657 {0xd7, 0x200 | 0x4f}, // '×'
658 {0xd8, 0x200 | 0x4c}, // 'Ø'
659 {0xd9, 0x200 | 0xbe}, // 'Ù'
660 {0xda, 0x200 | 0xbb}, // 'Ú'
661 {0xdb, 0x200 | 0xe2}, // 'Û'
662 {0xdc, 0x200 | 0x30}, // 'Ü'
663 {0xdd, 0x200 | 0x59}, // 'Ý'
664 {0xde, 0x200 | 0xc0}, // 'Þ'
665 {0xdf, 0x200 | 0xdb}, // 'ß'
669 static const int auto_key_table_50on_base[][2] = {
670 {0xa1, 0x300 | 0xbf}, // '¡'
671 {0xa2, 0x300 | 0xdb}, // '¢'
672 {0xa3, 0x300 | 0xdd}, // '£'
673 {0xa4, 0x300 | 0xbe}, // '¤'
674 {0xa5, 0x300 | 0xe2}, // '¥'
675 {0xa6, 0x200 | 0xbf}, // '¦'
676 {0xa7, 0x300 | 0x31}, // '§'
677 {0xa8, 0x300 | 0x32}, // '¨'
678 {0xa9, 0x300 | 0x33}, // '©'
679 {0xaa, 0x300 | 0x34}, // 'ª'
680 {0xab, 0x300 | 0x35}, // '«'
681 {0xac, 0x300 | 0x4e}, // '¬'
682 {0xad, 0x300 | 0x4d}, // ''
683 {0xae, 0x300 | 0xbc}, // '®'
684 {0xaf, 0x300 | 0x43}, // '¯'
685 {0xb0, 0x300 | 0xba}, // '°'
686 {0xb1, 0x200 | 0x31}, // '±'
687 {0xb2, 0x200 | 0x32}, // '²'
688 {0xb3, 0x200 | 0x33}, // '³'
689 {0xb4, 0x200 | 0x34}, // '´'
690 {0xb5, 0x200 | 0x35}, // 'µ'
691 {0xb6, 0x200 | 0x51}, // '¶'
692 {0xb7, 0x200 | 0x57}, // '·'
693 {0xb8, 0x200 | 0x45}, // '¸'
694 {0xb9, 0x200 | 0x52}, // '¹'
695 {0xba, 0x200 | 0x54}, // 'º'
696 {0xbb, 0x200 | 0x41}, // '»'
697 {0xbc, 0x200 | 0x53}, // '¼'
698 {0xbd, 0x200 | 0x44}, // '½'
699 {0xbe, 0x200 | 0x46}, // '¾'
700 {0xbf, 0x200 | 0x47}, // '¿'
701 {0xc0, 0x200 | 0x5a}, // 'À'
702 {0xc1, 0x200 | 0x58}, // 'Á'
703 {0xc2, 0x200 | 0x43}, // 'Â'
704 {0xc3, 0x200 | 0x56}, // 'Ã'
705 {0xc4, 0x200 | 0x42}, // 'Ä'
706 {0xc5, 0x200 | 0x36}, // 'Å'
707 {0xc6, 0x200 | 0x37}, // 'Æ'
708 {0xc7, 0x200 | 0x38}, // 'Ç'
709 {0xc8, 0x200 | 0x39}, // 'È'
710 {0xc9, 0x200 | 0x30}, // 'É'
711 {0xca, 0x200 | 0x59}, // 'Ê'
712 {0xcb, 0x200 | 0x55}, // 'Ë'
713 {0xcc, 0x200 | 0x49}, // 'Ì'
714 {0xcd, 0x200 | 0x4f}, // 'Í'
715 {0xce, 0x200 | 0x50}, // 'Î'
716 {0xcf, 0x200 | 0x48}, // 'Ï'
717 {0xd0, 0x200 | 0x4a}, // 'Ð'
718 {0xd1, 0x200 | 0x4b}, // 'Ñ'
719 {0xd2, 0x200 | 0x4c}, // 'Ò'
720 {0xd3, 0x200 | 0xbb}, // 'Ó'
721 {0xd4, 0x200 | 0x4e}, // 'Ô'
722 {0xd5, 0x200 | 0x4d}, // 'Õ'
723 {0xd6, 0x200 | 0xbc}, // 'Ö'
724 {0xd7, 0x200 | 0xbd}, // '×'
725 {0xd8, 0x200 | 0xde}, // 'Ø'
726 {0xd9, 0x200 | 0xdc}, // 'Ù'
727 {0xda, 0x200 | 0xc0}, // 'Ú'
728 {0xdb, 0x200 | 0xdb}, // 'Û'
729 {0xdc, 0x200 | 0xbe}, // 'Ü'
730 {0xdd, 0x200 | 0xe2}, // 'Ý'
731 {0xde, 0x200 | 0xba}, // 'Þ'
732 {0xdf, 0x200 | 0xdd}, // 'ß'
736 static const struct {
738 const uint8_t kana[4];
740 {"ltsu", {0xaf, 0x00}},
741 {"xtsu", {0xaf, 0x00}},
742 {"ltu", {0xaf, 0x00}},
743 {"xtu", {0xaf, 0x00}},
744 {"bya", {0xcb, 0xde, 0xac, 0x00}},
745 {"byi", {0xcb, 0xde, 0xa8, 0x00}},
746 {"byu", {0xcb, 0xde, 0xad, 0x00}},
747 {"bye", {0xcb, 0xde, 0xaa, 0x00}},
748 {"byo", {0xcb, 0xde, 0xae, 0x00}},
749 {"cha", {0xc1, 0xac, 0x00}},
750 {"chi", {0xc1, 0x00}},
751 {"chu", {0xc1, 0xad, 0x00}},
752 {"che", {0xc1, 0xaa, 0x00}},
753 {"cho", {0xc1, 0xae, 0x00}},
754 {"cya", {0xc1, 0xac, 0x00}},
755 {"cyi", {0xc1, 0xa8, 0x00}},
756 {"cyu", {0xc1, 0xad, 0x00}},
757 {"cye", {0xc1, 0xaa, 0x00}},
758 {"cyo", {0xc1, 0xae, 0x00}},
759 {"dha", {0xc3, 0xde, 0xac, 0x00}},
760 {"dhi", {0xc3, 0xde, 0xa8, 0x00}},
761 {"dhu", {0xc3, 0xde, 0xad, 0x00}},
762 {"dhe", {0xc3, 0xde, 0xaa, 0x00}},
763 {"dho", {0xc3, 0xde, 0xae, 0x00}},
764 {"dwa", {0xc4, 0xde, 0xa7, 0x00}},
765 {"dwi", {0xc4, 0xde, 0xa8, 0x00}},
766 {"dwu", {0xc4, 0xde, 0xa9, 0x00}},
767 {"dwe", {0xc4, 0xde, 0xaa, 0x00}},
768 {"dwo", {0xc4, 0xde, 0xab, 0x00}},
769 {"dya", {0xc1, 0xde, 0xac, 0x00}},
770 {"dyi", {0xc1, 0xde, 0xa8, 0x00}},
771 {"dyu", {0xc1, 0xde, 0xad, 0x00}},
772 {"dye", {0xc1, 0xde, 0xaa, 0x00}},
773 {"dyo", {0xc1, 0xde, 0xae, 0x00}},
774 {"fwa", {0xcc, 0xa7, 0x00}},
775 {"fwi", {0xcc, 0xa8, 0x00}},
776 {"fwu", {0xcc, 0xa9, 0x00}},
777 {"fwe", {0xcc, 0xaa, 0x00}},
778 {"fwo", {0xcc, 0xab, 0x00}},
779 {"fya", {0xcc, 0xac, 0x00}},
780 {"fyi", {0xcc, 0xa8, 0x00}},
781 {"fyu", {0xcc, 0xad, 0x00}},
782 {"fye", {0xcc, 0xaa, 0x00}},
783 {"fyo", {0xcc, 0xae, 0x00}},
784 {"gwa", {0xb8, 0xde, 0xa7, 0x00}},
785 {"gwi", {0xb8, 0xde, 0xa8, 0x00}},
786 {"gwu", {0xb8, 0xde, 0xa9, 0x00}},
787 {"gwe", {0xb8, 0xde, 0xaa, 0x00}},
788 {"gwo", {0xb8, 0xde, 0xab, 0x00}},
789 {"gya", {0xb7, 0xde, 0xac, 0x00}},
790 {"gyi", {0xb7, 0xde, 0xa8, 0x00}},
791 {"gyu", {0xb7, 0xde, 0xad, 0x00}},
792 {"gye", {0xb7, 0xde, 0xaa, 0x00}},
793 {"gyo", {0xb7, 0xde, 0xae, 0x00}},
794 {"hya", {0xcb, 0xac, 0x00}},
795 {"hyi", {0xcb, 0xa8, 0x00}},
796 {"hyu", {0xcb, 0xad, 0x00}},
797 {"hye", {0xcb, 0xaa, 0x00}},
798 {"hyo", {0xcb, 0xae, 0x00}},
799 {"jya", {0xbc, 0xde, 0xac, 0x00}},
800 {"jyi", {0xbc, 0xde, 0xa8, 0x00}},
801 {"jyu", {0xbc, 0xde, 0xad, 0x00}},
802 {"jye", {0xbc, 0xde, 0xaa, 0x00}},
803 {"jyo", {0xbc, 0xde, 0xae, 0x00}},
804 {"kya", {0xb7, 0xac, 0x00}},
805 {"kyi", {0xb7, 0xa8, 0x00}},
806 {"kyu", {0xb7, 0xad, 0x00}},
807 {"kye", {0xb7, 0xaa, 0x00}},
808 {"kyo", {0xb7, 0xae, 0x00}},
809 {"lya", {0xac, 0x00}},
810 {"lyi", {0xa8, 0x00}},
811 {"lyu", {0xad, 0x00}},
812 {"lye", {0xaa, 0x00}},
813 {"lyo", {0xae, 0x00}},
814 {"mya", {0xd0, 0xac, 0x00}},
815 {"myi", {0xd0, 0xa8, 0x00}},
816 {"myu", {0xd0, 0xad, 0x00}},
817 {"mye", {0xd0, 0xaa, 0x00}},
818 {"myo", {0xd0, 0xae, 0x00}},
819 {"nya", {0xc6, 0xac, 0x00}},
820 {"nyi", {0xc6, 0xa8, 0x00}},
821 {"nyu", {0xc6, 0xad, 0x00}},
822 {"nye", {0xc6, 0xaa, 0x00}},
823 {"nyo", {0xc6, 0xae, 0x00}},
824 {"pya", {0xcb, 0xdf, 0xac, 0x00}},
825 {"pyi", {0xcb, 0xdf, 0xa8, 0x00}},
826 {"pyu", {0xcb, 0xdf, 0xad, 0x00}},
827 {"pye", {0xcb, 0xdf, 0xaa, 0x00}},
828 {"pyo", {0xcb, 0xdf, 0xae, 0x00}},
829 {"qwa", {0xb8, 0xa7, 0x00}},
830 {"qwi", {0xb8, 0xa8, 0x00}},
831 {"qwu", {0xb8, 0xa9, 0x00}},
832 {"qwe", {0xb8, 0xaa, 0x00}},
833 {"qwo", {0xb8, 0xab, 0x00}},
834 {"qya", {0xb8, 0xac, 0x00}},
835 {"qyi", {0xb8, 0xa8, 0x00}},
836 {"qyu", {0xb8, 0xad, 0x00}},
837 {"qye", {0xb8, 0xaa, 0x00}},
838 {"qyo", {0xb8, 0xae, 0x00}},
839 {"rya", {0xd8, 0xac, 0x00}},
840 {"ryi", {0xd8, 0xa8, 0x00}},
841 {"ryu", {0xd8, 0xad, 0x00}},
842 {"rye", {0xd8, 0xaa, 0x00}},
843 {"ryo", {0xd8, 0xae, 0x00}},
844 {"sha", {0xbc, 0xac, 0x00}},
845 {"shi", {0xbc, 0x00}},
846 {"shu", {0xbc, 0xad, 0x00}},
847 {"she", {0xbc, 0xaa, 0x00}},
848 {"sho", {0xbc, 0xae, 0x00}},
849 {"swa", {0xbd, 0xa7, 0x00}},
850 {"swi", {0xbd, 0xa8, 0x00}},
851 {"swu", {0xbd, 0xa9, 0x00}},
852 {"swe", {0xbd, 0xaa, 0x00}},
853 {"swo", {0xbd, 0xab, 0x00}},
854 {"sya", {0xbc, 0xac, 0x00}},
855 {"syi", {0xbc, 0xa8, 0x00}},
856 {"syu", {0xbc, 0xad, 0x00}},
857 {"sye", {0xbc, 0xaa, 0x00}},
858 {"syo", {0xbc, 0xae, 0x00}},
859 {"tha", {0xc3, 0xac, 0x00}},
860 {"thi", {0xc3, 0xa8, 0x00}},
861 {"thu", {0xc3, 0xad, 0x00}},
862 {"the", {0xc3, 0xaa, 0x00}},
863 {"tho", {0xc3, 0xae, 0x00}},
864 {"tsa", {0xc2, 0xa7, 0x00}},
865 {"tsi", {0xc2, 0xa8, 0x00}},
866 {"tsu", {0xc2, 0x00}},
867 {"tse", {0xc2, 0xaa, 0x00}},
868 {"tso", {0xc2, 0xab, 0x00}},
869 {"twa", {0xc4, 0xa7, 0x00}},
870 {"twi", {0xc4, 0xa8, 0x00}},
871 {"twu", {0xc4, 0xa9, 0x00}},
872 {"twe", {0xc4, 0xaa, 0x00}},
873 {"two", {0xc4, 0xab, 0x00}},
874 {"tya", {0xc1, 0xac, 0x00}},
875 {"tyi", {0xc1, 0xa8, 0x00}},
876 {"tyu", {0xc1, 0xad, 0x00}},
877 {"tye", {0xc1, 0xaa, 0x00}},
878 {"tyo", {0xc1, 0xae, 0x00}},
879 {"vya", {0xb3, 0xde, 0xac, 0x00}},
880 {"vyi", {0xb3, 0xde, 0xa8, 0x00}},
881 {"vyu", {0xb3, 0xde, 0xad, 0x00}},
882 {"vye", {0xb3, 0xde, 0xaa, 0x00}},
883 {"vyo", {0xb3, 0xde, 0xae, 0x00}},
884 {"wha", {0xb3, 0xa7, 0x00}},
885 {"whi", {0xb3, 0xa8, 0x00}},
886 {"whu", {0xb3, 0x00}},
887 {"whe", {0xb3, 0xaa, 0x00}},
888 {"who", {0xb3, 0xab, 0x00}},
889 {"xya", {0xac, 0x00}},
890 {"xyi", {0xa8, 0x00}},
891 {"xyu", {0xad, 0x00}},
892 {"xye", {0xaa, 0x00}},
893 {"xyo", {0xae, 0x00}},
894 {"zya", {0xbc, 0xde, 0xac, 0x00}},
895 {"zyi", {0xbc, 0xde, 0xa8, 0x00}},
896 {"zyu", {0xbc, 0xde, 0xad, 0x00}},
897 {"zye", {0xbc, 0xde, 0xaa, 0x00}},
898 {"zyo", {0xbc, 0xde, 0xae, 0x00}},
899 {"ba", {0xca, 0xde, 0x00}},
900 {"bi", {0xcb, 0xde, 0x00}},
901 {"bu", {0xcc, 0xde, 0x00}},
902 {"be", {0xcd, 0xde, 0x00}},
903 {"bo", {0xce, 0xde, 0x00}},
904 {"ca", {0xb6, 0x00}},
905 {"ci", {0xbc, 0x00}},
906 {"cu", {0xb8, 0x00}},
907 {"ce", {0xbe, 0x00}},
908 {"co", {0xba, 0x00}},
909 {"da", {0xc0, 0xde, 0x00}},
910 {"di", {0xc1, 0xde, 0x00}},
911 {"du", {0xc2, 0xde, 0x00}},
912 {"de", {0xc3, 0xde, 0x00}},
913 {"do", {0xc4, 0xde, 0x00}},
914 {"fa", {0xcc, 0xa7, 0x00}},
915 {"fi", {0xcc, 0xa8, 0x00}},
916 {"fu", {0xcc, 0x00}},
917 {"fe", {0xcc, 0xaa, 0x00}},
918 {"fo", {0xcc, 0xab, 0x00}},
919 {"ga", {0xb6, 0xde, 0x00}},
920 {"gi", {0xb7, 0xde, 0x00}},
921 {"gu", {0xb8, 0xde, 0x00}},
922 {"ge", {0xb9, 0xde, 0x00}},
923 {"go", {0xba, 0xde, 0x00}},
924 {"ha", {0xca, 0x00}},
925 {"hi", {0xcb, 0x00}},
926 {"hu", {0xcc, 0x00}},
927 {"he", {0xcd, 0x00}},
928 {"ho", {0xce, 0x00}},
929 {"ja", {0xbc, 0xde, 0xac, 0x00}},
930 {"ji", {0xbc, 0xde, 0x00}},
931 {"ju", {0xbc, 0xde, 0xad, 0x00}},
932 {"je", {0xbc, 0xde, 0xaa, 0x00}},
933 {"jo", {0xbc, 0xde, 0xae, 0x00}},
934 {"ka", {0xb6, 0x00}},
935 {"ki", {0xb7, 0x00}},
936 {"ku", {0xb8, 0x00}},
937 {"ke", {0xb9, 0x00}},
938 {"ko", {0xba, 0x00}},
939 {"la", {0xa7, 0x00}},
940 {"li", {0xa8, 0x00}},
941 {"lu", {0xa9, 0x00}},
942 {"le", {0xaa, 0x00}},
943 {"lo", {0xab, 0x00}},
944 {"ma", {0xcf, 0x00}},
945 {"mi", {0xd0, 0x00}},
946 {"mu", {0xd1, 0x00}},
947 {"me", {0xd2, 0x00}},
948 {"mo", {0xd3, 0x00}},
949 {"na", {0xc5, 0x00}},
950 {"ni", {0xc6, 0x00}},
951 {"nu", {0xc7, 0x00}},
952 {"ne", {0xc8, 0x00}},
953 {"no", {0xc9, 0x00}},
954 // {"nn", {0xdd, 0x00}},
955 {"pa", {0xca, 0xdf, 0x00}},
956 {"pi", {0xcb, 0xdf, 0x00}},
957 {"pu", {0xcc, 0xdf, 0x00}},
958 {"pe", {0xcd, 0xdf, 0x00}},
959 {"po", {0xce, 0xdf, 0x00}},
960 {"qa", {0xb8, 0xa7, 0x00}},
961 {"qi", {0xb8, 0xa8, 0x00}},
962 {"qu", {0xb8, 0x00}},
963 {"qe", {0xb8, 0xaa, 0x00}},
964 {"qo", {0xb8, 0xab, 0x00}},
965 {"ra", {0xd7, 0x00}},
966 {"ri", {0xd8, 0x00}},
967 {"ru", {0xd9, 0x00}},
968 {"re", {0xda, 0x00}},
969 {"ro", {0xdb, 0x00}},
970 {"sa", {0xbb, 0x00}},
971 {"si", {0xbc, 0x00}},
972 {"su", {0xbd, 0x00}},
973 {"se", {0xbe, 0x00}},
974 {"so", {0xbf, 0x00}},
975 {"ta", {0xc0, 0x00}},
976 {"ti", {0xc1, 0x00}},
977 {"tu", {0xc2, 0x00}},
978 {"te", {0xc3, 0x00}},
979 {"to", {0xc4, 0x00}},
980 {"va", {0xb3, 0xde, 0xa7, 0x00}},
981 {"vi", {0xb3, 0xde, 0xa8, 0x00}},
982 {"vu", {0xb3, 0xde, 0x00}},
983 {"ve", {0xb3, 0xde, 0xaa, 0x00}},
984 {"vo", {0xb3, 0xde, 0xab, 0x00}},
985 {"wa", {0xdc, 0x00}},
986 {"wi", {0xb3, 0xa8, 0x00}},
987 {"wu", {0xb3, 0x00}},
988 {"we", {0xb3, 0xaa, 0x00}},
989 {"wo", {0xa6, 0x00}},
990 {"xa", {0xa7, 0x00}},
991 {"xi", {0xa8, 0x00}},
992 {"xu", {0xa9, 0x00}},
993 {"xe", {0xaa, 0x00}},
994 {"xo", {0xab, 0x00}},
995 {"ya", {0xd4, 0x00}},
996 {"yi", {0xb2, 0x00}},
997 {"yu", {0xd5, 0x00}},
998 {"ye", {0xb2, 0xaa, 0x00}},
999 {"yo", {0xd6, 0x00}},
1000 {"za", {0xbb, 0xde, 0x00}},
1001 {"zi", {0xbc, 0xde, 0x00}},
1002 {"zu", {0xbd, 0xde, 0x00}},
1003 {"ze", {0xbe, 0xde, 0x00}},
1004 {"zo", {0xbf, 0xde, 0x00}},
1005 {"a", {0xb1, 0x00}},
1006 {"i", {0xb2, 0x00}},
1007 {"u", {0xb3, 0x00}},
1008 {"e", {0xb4, 0x00}},
1009 {"o", {0xb5, 0x00}},
1010 {"[", {0xa2, 0x00}},
1011 {"]", {0xa3, 0x00}},
1012 {"-", {0xb0, 0x00}},
1013 {",", {0xa4, 0x00}},
1014 {".", {0xa1, 0x00}},
1015 {"/", {0xa5, 0x00}},
1019 void EMU::initialize_auto_key()
1021 auto_key_buffer = new FIFO(65536);
1022 auto_key_buffer->clear();
1023 auto_key_phase = auto_key_shift = 0;
1024 shift_pressed = false;
1025 osd->now_auto_key = false;
1028 void EMU::release_auto_key()
1030 if(auto_key_buffer) {
1031 auto_key_buffer->release();
1032 delete auto_key_buffer;
1036 int EMU::get_auto_key_code(int code)
1038 static int auto_key_table[256];
1039 static bool initialized = false;
1040 #ifdef USE_KEYBOARD_TYPE
1041 static int keyboard_type = -1;
1043 if(keyboard_type != config.keyboard_type) {
1044 initialized = false;
1045 keyboard_type = config.keyboard_type;
1049 memset(auto_key_table, 0, sizeof(auto_key_table));
1050 for(int i = 0;; i++) {
1051 if(auto_key_table_base[i][0] == -1) {
1054 auto_key_table[auto_key_table_base[i][0]] = auto_key_table_base[i][1];
1056 #if defined(_X1TURBO) || defined(_X1TURBOZ)
1058 if(config.keyboard_type) {
1059 for(int i = 0;; i++) {
1060 if(auto_key_table_50on_base[i][0] == -1) {
1063 auto_key_table[auto_key_table_50on_base[i][0]] = auto_key_table_50on_base[i][1];
1067 for(int i = 0;; i++) {
1068 if(auto_key_table_kana_base[i][0] == -1) {
1071 auto_key_table[auto_key_table_kana_base[i][0]] = auto_key_table_kana_base[i][1];
1073 #ifdef USE_VM_AUTO_KEY_TABLE
1074 for(int i = 0;; i++) {
1075 if(vm_auto_key_table_base[i][0] == -1) {
1078 auto_key_table[vm_auto_key_table_base[i][0]] = vm_auto_key_table_base[i][1];
1083 return auto_key_table[code];
1086 void EMU::set_auto_key_code(int code)
1088 if(code == 0xf2 || (code = get_auto_key_code(code)) != 0) {
1089 if(code == 0x08 || code == 0x09 || code == 0x0d || code == 0x1b || code == 0x20 || code == 0xf2) {
1090 auto_key_buffer->write(code);
1091 #ifdef USE_AUTO_KEY_NUMPAD
1092 } else if(code >= 0x30 && code <= 0x39) {
1094 auto_key_buffer->write(code - 0x30 + 0x60);
1096 } else if(code & 0x200) {
1098 auto_key_buffer->write(code & 0x1ff);
1100 // ank other than alphabet and kana
1101 auto_key_buffer->write(0xf2); // kana unlock
1102 auto_key_buffer->write(code & 0x1ff);
1103 auto_key_buffer->write(0xf2); // kana lock
1105 if(!is_auto_key_running()) {
1111 void EMU::set_auto_key_list(char *buf, int size)
1113 #if defined(USE_KEY_LOCKED)
1114 bool prev_caps = get_caps_locked();
1115 bool prev_kana = get_kana_locked();
1117 bool prev_caps = false;
1118 bool prev_kana = false;
1120 auto_key_buffer->clear();
1122 for(int i = 0; i < size; i++) {
1123 int code = buf[i] & 0xff;
1124 if((0x81 <= code && code <= 0x9f) || 0xe0 <= code) {
1127 } else if(code == 0x0a) {
1130 if((code = get_auto_key_code(code)) != 0) {
1132 bool kana = ((code & 0x200) != 0);
1133 if(prev_kana != kana) {
1134 auto_key_buffer->write(0xf2);
1137 #if defined(USE_AUTO_KEY_CAPS_LOCK)
1138 // use caps lock key to switch uppercase/lowercase of alphabet
1139 // USE_AUTO_KEY_CAPS_LOCK shows the caps lock key code
1140 bool caps = ((code & 0x400) != 0);
1141 if(prev_caps != caps) {
1142 auto_key_buffer->write(USE_AUTO_KEY_CAPS_LOCK);
1146 #if defined(USE_AUTO_KEY_CAPS_LOCK) || defined(USE_AUTO_KEY_NO_CAPS)
1147 code &= ~(0x400 | 0x800); // don't press shift key for both alphabet and ALPHABET
1148 #elif defined(USE_KEY_LOCKED)
1149 if(get_caps_locked()) {
1150 code &= ~0x400; // don't press shift key for ALPHABET
1152 code &= ~0x800; // don't press shift key for alphabet
1154 #elif defined(USE_AUTO_KEY_CAPS)
1155 code &= ~0x400; // don't press shift key for ALPHABET
1157 code &= ~0x800; // don't press shift key for alphabet
1159 if(code & (0x100 | 0x400 | 0x800)) {
1160 auto_key_buffer->write((code & 0xff) | 0x100);
1162 auto_key_buffer->write(code & 0xff);
1166 // release kana lock
1168 auto_key_buffer->write(0xf2);
1170 #if defined(USE_AUTO_KEY_CAPS_LOCK)
1171 // release caps lock
1173 auto_key_buffer->write(USE_AUTO_KEY_CAPS_LOCK);
1178 bool is_alphabet(char code)
1180 return (code >= 'a' && code <= 'z');
1183 bool is_vowel(char code)
1185 return (code == 'a' || code == 'i' || code == 'u' || code == 'e' || code == 'o');
1188 bool is_consonant(char code)
1190 return (is_alphabet(code) && !is_vowel(code));
1193 void EMU::set_auto_key_char(char code)
1195 static char codes[5] = {0};
1198 #ifdef USE_KEY_LOCKED
1199 if(!get_kana_locked())
1201 set_auto_key_code(0xf2);
1202 memset(codes, 0, sizeof(codes));
1203 } else if(code == 0) {
1205 if(codes[3] == 'n') {
1206 set_auto_key_code(0xdd); // 'Ý'
1208 set_auto_key_code(0xf2);
1209 memset(codes, 0, sizeof(codes));
1210 } else if(code == 0x08 || code == 0x09 || code == 0x0d || code == 0x1b || code == 0x20) {
1211 if(codes[3] == 'n') {
1212 set_auto_key_code(0xdd); // 'Ý'
1214 set_auto_key_code(code);
1215 memset(codes, 0, sizeof(codes));
1216 #ifdef USE_AUTO_KEY_NUMPAD
1217 } else if(code >= 0x30 && code <= 0x39) {
1218 if(codes[3] == 'n') {
1219 set_auto_key_code(0xdd); // 'Ý'
1221 set_auto_key_code(code);
1222 memset(codes, 0, sizeof(codes));
1225 codes[0] = codes[1];
1226 codes[1] = codes[2];
1227 codes[2] = codes[3];
1228 codes[3] = (code >= 'A' && code <= 'Z') ? ('a' + (code - 'A')) : code;
1231 if(codes[2] == 'n' && !is_vowel(codes[3])) {
1232 set_auto_key_code(0xdd); // 'Ý'
1233 if(codes[3] == 'n') {
1234 memset(codes, 0, sizeof(codes));
1237 } else if(codes[2] == codes[3] && is_consonant(codes[3])) {
1238 set_auto_key_code(0xaf); // '¯'
1241 for(int i = 0;; i++) {
1242 int len = strlen(romaji_table[i].romaji), comp = -1;
1245 if(!is_alphabet(codes[3])) {
1246 set_auto_key_code(codes[3]);
1247 memset(codes, 0, sizeof(codes));
1250 } else if(len == 1) {
1251 comp = strcmp(romaji_table[i].romaji, &codes[3]);
1252 } else if(len == 2) {
1253 comp = strcmp(romaji_table[i].romaji, &codes[2]);
1254 } else if(len == 3) {
1255 comp = strcmp(romaji_table[i].romaji, &codes[1]);
1256 } else if(len == 4) {
1257 comp = strcmp(romaji_table[i].romaji, &codes[0]);
1260 for(int j = 0; j < 4; j++) {
1261 if(!romaji_table[i].kana[j]) {
1264 set_auto_key_code(romaji_table[i].kana[j]);
1266 memset(codes, 0, sizeof(codes));
1273 void EMU::start_auto_key()
1277 osd->now_auto_key = true;
1280 void EMU::stop_auto_key()
1282 if(auto_key_shift) {
1283 osd->key_up_native(VK_LSHIFT);
1285 auto_key_phase = auto_key_shift = 0;
1286 osd->now_auto_key = false;
1289 #ifndef USE_AUTO_KEY_SHIFT
1290 #define USE_AUTO_KEY_SHIFT 0
1293 #define VK_LSHIFT 0xA0
1296 void EMU::update_auto_key()
1298 switch(auto_key_phase) {
1300 if(auto_key_buffer && !auto_key_buffer->empty()) {
1301 // update shift key status
1302 int shift = auto_key_buffer->read_not_remove(0) & 0x100;
1303 if(shift && !auto_key_shift) {
1304 osd->key_down_native(VK_LSHIFT, false);
1305 } else if(!shift && auto_key_shift) {
1306 osd->key_up_native(VK_LSHIFT);
1308 auto_key_shift = shift;
1312 case 3 + USE_AUTO_KEY_SHIFT:
1313 if(auto_key_buffer && !auto_key_buffer->empty()) {
1314 osd->key_down_native(auto_key_buffer->read_not_remove(0) & 0xff, false);
1318 case USE_AUTO_KEY + USE_AUTO_KEY_SHIFT:
1319 if(auto_key_buffer && !auto_key_buffer->empty()) {
1320 osd->key_up_native(auto_key_buffer->read_not_remove(0) & 0xff);
1324 case USE_AUTO_KEY_RELEASE + USE_AUTO_KEY_SHIFT:
1325 if(auto_key_buffer && !auto_key_buffer->empty()) {
1326 // wait enough while vm analyzes one line
1327 if(auto_key_buffer->read() == 0xd) {
1333 if(auto_key_buffer && !auto_key_buffer->empty()) {
1340 if(auto_key_phase) {
1348 void EMU::update_joystick()
1350 uint32_t *joy_buffer = osd->get_joy_buffer();
1351 uint8_t *key_buffer = osd->get_key_buffer();
1353 memset(joy_status, 0, sizeof(joy_status));
1355 for(int i = 0; i < 4; i++) {
1356 for(int j = 0; j < 16; j++) {
1357 if(config.joy_buttons[i][j] < 0) {
1358 int code = -config.joy_buttons[i][j];
1359 if(code < 256 && key_buffer[code]) {
1360 joy_status[i] |= (1 << j);
1361 //printf("%d %d %02x %02x\n", i, j, config.joy_buttons[i][j], joy_status[i]);
1364 int stick = config.joy_buttons[i][j] >> 4;
1365 int button = config.joy_buttons[i][j] & 15;
1366 if(stick < 2 && (joy_buffer[stick & 3] & (1 << button))) {
1367 joy_status[i] |= (1 << j);
1368 //printf("%d %d %02x %02x\n", i, j, config.joy_buttons[i][j], joy_status[i]);
1376 const uint8_t* EMU::get_key_buffer()
1378 return (const uint8_t*)osd->get_key_buffer();
1382 const uint32_t* EMU::get_joy_buffer()
1384 return (const uint32_t*)joy_status;
1389 const int32_t* EMU::get_mouse_buffer()
1391 return (const int32_t*)osd->get_mouse_buffer();
1395 // ----------------------------------------------------------------------------
1397 // ----------------------------------------------------------------------------
1399 int EMU::get_window_mode_width(int mode)
1401 return osd->get_window_mode_width(mode);
1404 int EMU::get_window_mode_height(int mode)
1406 return osd->get_window_mode_height(mode);
1409 void EMU::set_host_window_size(int window_width, int window_height, bool window_mode)
1411 osd->set_host_window_size(window_width, window_height, window_mode);
1414 void EMU::set_vm_screen_size(int screen_width, int screen_height, int window_width, int window_height, int window_width_aspect, int window_height_aspect)
1416 osd->set_vm_screen_size(screen_width, screen_height, window_width, window_height, window_width_aspect, window_height_aspect);
1419 void EMU::set_vm_screen_lines(int lines)
1421 osd->set_vm_screen_lines(lines);
1425 int EMU::get_vm_window_width()
1427 return osd->get_vm_window_width();
1430 int EMU::get_vm_window_height()
1432 return osd->get_vm_window_height();
1435 int EMU::get_vm_window_width_aspect()
1437 return osd->get_vm_window_width_aspect();
1440 int EMU::get_vm_window_height_aspect()
1442 return osd->get_vm_window_height_aspect();
1445 #if defined(USE_MINIMUM_RENDERING)
1446 bool EMU::is_screen_changed()
1448 return vm->is_screen_changed();
1452 int EMU::draw_screen()
1454 return osd->draw_screen();
1457 scrntype_t* EMU::get_screen_buffer(int y)
1459 return osd->get_vm_screen_buffer(y);
1462 #ifdef USE_SCREEN_FILTER
1463 void EMU::screen_skip_line(bool skip_line)
1465 osd->screen_skip_line = skip_line;
1469 #ifdef ONE_BOARD_MICRO_COMPUTER
1470 void EMU::get_invalidated_rect(int *left, int *top, int *right, int *bottom)
1472 #ifdef MAX_DRAW_RANGES
1473 for(int i = 0; i < MAX_DRAW_RANGES; i++) {
1475 for(int i = 0; i < vm->max_draw_ranges(); i++) { // for TK-80BS
1477 int x1 = vm_ranges[i].x;
1478 int y1 = vm_ranges[i].y;
1479 int x2 = x1 + vm_ranges[i].width;
1480 int y2 = y1 + vm_ranges[i].height;
1482 *left = (i == 0) ? x1 : min(x1, *left );
1483 *top = (i == 0) ? y1 : min(y1, *top );
1484 *right = (i == 0) ? x2 : max(x2, *right );
1485 *bottom = (i == 0) ? y2 : max(y2, *bottom);
1489 void EMU::reload_bitmap()
1491 osd->reload_bitmap();
1496 void EMU::invalidate_screen()
1498 osd->invalidate_screen();
1501 void EMU::update_screen(HDC hdc)
1503 osd->update_screen(hdc);
1507 void EMU::capture_screen()
1509 osd->capture_screen();
1512 bool EMU::start_record_video(int fps)
1514 return osd->start_record_video(fps);
1517 void EMU::stop_record_video()
1519 osd->stop_record_video();
1522 bool EMU::is_video_recording()
1524 return osd->now_record_video;
1527 // ----------------------------------------------------------------------------
1529 // ----------------------------------------------------------------------------
1531 void EMU::mute_sound()
1536 void EMU::start_record_sound()
1538 osd->start_record_sound();
1541 void EMU::stop_record_sound()
1543 osd->stop_record_sound();
1546 bool EMU::is_sound_recording()
1548 return osd->now_record_sound;
1551 // ----------------------------------------------------------------------------
1553 // ----------------------------------------------------------------------------
1555 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
1556 void EMU::get_video_buffer()
1558 osd->get_video_buffer();
1561 void EMU::mute_video_dev(bool l, bool r)
1563 osd->mute_video_dev(l, r);
1567 #ifdef USE_MOVIE_PLAYER
1568 bool EMU::open_movie_file(const _TCHAR* file_path)
1570 return osd->open_movie_file(file_path);
1573 void EMU::close_movie_file()
1575 osd->close_movie_file();
1578 void EMU::play_movie()
1583 void EMU::stop_movie()
1588 void EMU::pause_movie()
1593 double EMU::get_movie_frame_rate()
1595 return osd->get_movie_frame_rate();
1598 int EMU::get_movie_sound_rate()
1600 return osd->get_movie_sound_rate();
1603 void EMU::set_cur_movie_frame(int frame, bool relative)
1605 osd->set_cur_movie_frame(frame, relative);
1608 uint32_t EMU::get_cur_movie_frame()
1610 return osd->get_cur_movie_frame();
1614 #ifdef USE_VIDEO_CAPTURE
1615 int EMU::get_cur_capture_dev_index()
1617 return osd->get_cur_capture_dev_index();
1620 int EMU::get_num_capture_devs()
1622 return osd->get_num_capture_devs();
1625 _TCHAR* EMU::get_capture_dev_name(int index)
1627 return osd->get_capture_dev_name(index);
1630 void EMU::open_capture_dev(int index, bool pin)
1632 osd->open_capture_dev(index, pin);
1635 void EMU::close_capture_dev()
1637 osd->close_capture_dev();
1640 void EMU::show_capture_dev_filter()
1642 osd->show_capture_dev_filter();
1645 void EMU::show_capture_dev_pin()
1647 osd->show_capture_dev_pin();
1650 void EMU::show_capture_dev_source()
1652 osd->show_capture_dev_source();
1655 void EMU::set_capture_dev_channel(int ch)
1657 osd->set_capture_dev_channel(ch);
1661 // ----------------------------------------------------------------------------
1663 // ----------------------------------------------------------------------------
1666 void EMU::create_bitmap(bitmap_t *bitmap, int width, int height)
1668 osd->create_bitmap(bitmap, width, height);
1671 void EMU::release_bitmap(bitmap_t *bitmap)
1673 osd->release_bitmap(bitmap);
1676 void EMU::create_font(font_t *font, const _TCHAR *family, int width, int height, int rotate, bool bold, bool italic)
1678 osd->create_font(font, family, width, height, rotate, bold, italic);
1681 void EMU::release_font(font_t *font)
1683 osd->release_font(font);
1686 void EMU::create_pen(pen_t *pen, int width, uint8_t r, uint8_t g, uint8_t b)
1688 osd->create_pen(pen, width, r, g, b);
1691 void EMU::release_pen(pen_t *pen)
1693 osd->release_pen(pen);
1696 void EMU::clear_bitmap(bitmap_t *bitmap, uint8_t r, uint8_t g, uint8_t b)
1698 osd->clear_bitmap(bitmap, r, g, b);
1701 int EMU::get_text_width(bitmap_t *bitmap, font_t *font, const char *text)
1703 return osd->get_text_width(bitmap, font, text);
1706 void EMU::draw_text_to_bitmap(bitmap_t *bitmap, font_t *font, int x, int y, const char *text, uint8_t r, uint8_t g, uint8_t b)
1708 osd->draw_text_to_bitmap(bitmap, font, x, y, text, r, g, b);
1711 void EMU::draw_line_to_bitmap(bitmap_t *bitmap, pen_t *pen, int sx, int sy, int ex, int ey)
1713 osd->draw_line_to_bitmap(bitmap, pen, sx, sy, ex, ey);
1716 void EMU::draw_rectangle_to_bitmap(bitmap_t *bitmap, int x, int y, int width, int height, uint8_t r, uint8_t g, uint8_t b)
1718 osd->draw_rectangle_to_bitmap(bitmap, x, y, width, height, r, g, b);
1721 void EMU::draw_point_to_bitmap(bitmap_t *bitmap, int x, int y, uint8_t r, uint8_t g, uint8_t b)
1723 osd->draw_point_to_bitmap(bitmap, x, y, r, g, b);
1726 void EMU::stretch_bitmap(bitmap_t *dest, int dest_x, int dest_y, int dest_width, int dest_height, bitmap_t *source, int source_x, int source_y, int source_width, int source_height)
1728 osd->stretch_bitmap(dest, dest_x, dest_y, dest_width, dest_height, source, source_x, source_y, source_width, source_height);
1731 void EMU::write_bitmap_to_file(bitmap_t *bitmap, const _TCHAR *file_path)
1733 osd->write_bitmap_to_file(bitmap, file_path);
1737 // ----------------------------------------------------------------------------
1739 // ----------------------------------------------------------------------------
1742 int EMU::get_socket(int ch)
1744 return osd->get_socket(ch);
1747 void EMU::notify_socket_connected(int ch)
1749 osd->notify_socket_connected(ch);
1752 void EMU::notify_socket_disconnected(int ch)
1754 osd->notify_socket_disconnected(ch);
1757 bool EMU::initialize_socket_tcp(int ch)
1759 return osd->initialize_socket_tcp(ch);
1762 bool EMU::initialize_socket_udp(int ch)
1764 return osd->initialize_socket_udp(ch);
1767 bool EMU::connect_socket(int ch, uint32_t ipaddr, int port)
1769 return osd->connect_socket(ch, ipaddr, port);
1772 void EMU::disconnect_socket(int ch)
1774 osd->disconnect_socket(ch);
1777 bool EMU::listen_socket(int ch)
1779 return osd->listen_socket(ch);
1782 void EMU::send_socket_data_tcp(int ch)
1784 osd->send_socket_data_tcp(ch);
1787 void EMU::send_socket_data_udp(int ch, uint32_t ipaddr, int port)
1789 osd->send_socket_data_udp(ch, ipaddr, port);
1792 void EMU::send_socket_data(int ch)
1794 osd->send_socket_data(ch);
1797 void EMU::recv_socket_data(int ch)
1799 osd->recv_socket_data(ch);
1803 // ----------------------------------------------------------------------------
1805 // ----------------------------------------------------------------------------
1808 void EMU::initialize_debug_log()
1810 _TCHAR path[_MAX_PATH];
1811 debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
1814 void EMU::release_debug_log()
1824 static _TCHAR prev_buffer[1024] = {0};
1827 void EMU::out_debug_log(const _TCHAR* format, ...)
1831 _TCHAR buffer[1024];
1833 va_start(ap, format);
1834 my_vstprintf_s(buffer, 1024, format, ap);
1837 if(_tcscmp(prev_buffer, buffer) == 0) {
1840 my_tcscpy_s(prev_buffer, 1024, buffer);
1842 #if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
1843 csp_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_EMU, "%s", buffer);
1846 _ftprintf(debug_log, _T("%s"), buffer);
1847 static int size = 0;
1848 if((size += _tcslen(buffer)) > 0x8000000) { // 128MB
1850 debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
1858 void EMU::force_out_debug_log(const _TCHAR* format, ...)
1862 _TCHAR buffer[1024];
1864 va_start(ap, format);
1865 my_vstprintf_s(buffer, 1024, format, ap);
1867 my_tcscpy_s(prev_buffer, 1024, buffer);
1869 #if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
1870 csp_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_EMU, "%s", buffer);
1873 _ftprintf(debug_log, _T("%s"), buffer);
1874 static int size = 0;
1875 if((size += _tcslen(buffer)) > 0x8000000) { // 128MB
1877 debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
1885 void EMU::out_message(const _TCHAR* format, ...)
1887 //#if defined(_USE_QT)
1888 // _TCHAR mes_buf[1024];
1891 va_start(ap, format);
1892 my_vstprintf_s(message, 1024, format, ap); // Security for MSVC:C6386.
1893 //#if defined(_USE_QT)
1894 // memset(mes_buf, 0x00, sizeof(mes_buf));
1895 // my_vstprintf_s(mes_buf, 1024, format, ap); // Security for MSVC:C6386.
1896 // csp_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_EMU, "%s", mes_buf);
1899 message_count = 4; // 4sec
1902 // ----------------------------------------------------------------------------
1904 // ----------------------------------------------------------------------------
1907 void EMU::sleep(uint32_t ms)
1913 // ----------------------------------------------------------------------------
1915 // ----------------------------------------------------------------------------
1917 static uint8_t hex2uint8(char *value)
1920 memset(tmp, 0, sizeof(tmp));
1921 memcpy(tmp, value, 2);
1922 return (uint8_t)strtoul(tmp, NULL, 16);
1925 static uint16_t hex2uint16(char *value)
1928 memset(tmp, 0, sizeof(tmp));
1929 memcpy(tmp, value, 4);
1930 return (uint16_t)strtoul(tmp, NULL, 16);
1933 static bool hex2bin(const _TCHAR* file_path, const _TCHAR* dest_path)
1935 bool result = false;
1936 FILEIO *fio_s = new FILEIO();
1937 if(fio_s->Fopen(file_path, FILEIO_READ_BINARY)) {
1940 uint8_t buffer[0x10000];
1941 memset(buffer, 0xff, sizeof(buffer));
1942 while(fio_s->Fgets(line, sizeof(line)) != NULL) {
1943 if(line[0] != ':') continue;
1944 int bytes = hex2uint8(line + 1);
1945 int offset = hex2uint16(line + 3);
1946 uint8_t record_type = hex2uint8(line + 7);
1947 if(record_type == 0x01) break;
1948 if(record_type != 0x00) continue;
1949 for(int i = 0; i < bytes; i++) {
1950 if((offset + i) < (int)sizeof(buffer)) {
1951 if(length < (offset + i)) {
1952 length = offset + i;
1954 buffer[offset + i] = hex2uint8(line + 9 + 2 * i);
1959 FILEIO *fio_d = new FILEIO();
1960 if(fio_d->Fopen(dest_path, FILEIO_WRITE_BINARY)) {
1961 fio_d->Fwrite(buffer, length, 1);
1973 void EMU::initialize_media()
1976 memset(&cart_status, 0, sizeof(cart_status));
1978 #ifdef USE_FLOPPY_DISK
1979 memset(floppy_disk_status, 0, sizeof(floppy_disk_status));
1981 #ifdef USE_QUICK_DISK
1982 memset(&quick_disk_status, 0, sizeof(quick_disk_status));
1984 #ifdef USE_HARD_DISK
1985 memset(&hard_disk_status, 0, sizeof(hard_disk_status));
1988 memset(&tape_status, 0, sizeof(tape_status));
1990 #ifdef USE_COMPACT_DISC
1991 memset(&compact_disc_status, 0, sizeof(compact_disc_status));
1993 #ifdef USE_LASER_DISC
1994 memset(&laser_disc_status, 0, sizeof(laser_disc_status));
1997 memset(&bubble_casette_status, 0, sizeof(bubble_casette_status));
2002 void EMU::update_media()
2004 #ifdef USE_FLOPPY_DISK
2005 for(int drv = 0; drv < USE_FLOPPY_DISK; drv++) {
2006 if(floppy_disk_status[drv].wait_count != 0 && --floppy_disk_status[drv].wait_count == 0) {
2007 vm->open_floppy_disk(drv, floppy_disk_status[drv].path, floppy_disk_status[drv].bank);
2008 #if USE_FLOPPY_DISK > 1
2009 out_message(_T("FD%d: %s"), drv + BASE_FLOPPY_DISK_NUM, floppy_disk_status[drv].path);
2011 out_message(_T("FD: %s"), floppy_disk_status[drv].path);
2016 #ifdef USE_QUICK_DISK
2017 for(int drv = 0; drv < USE_QUICK_DISK; drv++) {
2018 if(quick_disk_status[drv].wait_count != 0 && --quick_disk_status[drv].wait_count == 0) {
2019 vm->open_quick_disk(drv, quick_disk_status[drv].path);
2020 #if USE_QUICK_DISK > 1
2021 out_message(_T("QD%d: %s"), drv + BASE_QUICK_DISK_NUM, quick_disk_status[drv].path);
2023 out_message(_T("QD: %s"), quick_disk_status[drv].path);
2028 #ifdef USE_HARD_DISK
2029 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
2030 if(hard_disk_status[drv].wait_count != 0 && --hard_disk_status[drv].wait_count == 0) {
2031 vm->open_hard_disk(drv, hard_disk_status[drv].path);
2032 #if USE_HARD_DISK > 1
2033 out_message(_T("HD%d: %s"), drv + BASE_HARD_DISK_NUM, hard_disk_status[drv].path);
2035 out_message(_T("HD: %s"), hard_disk_status[drv].path);
2041 for(int drv = 0; drv < USE_TAPE; drv++) {
2042 if(tape_status[drv].wait_count != 0 && --tape_status[drv].wait_count == 0) {
2043 if(tape_status[drv].play) {
2044 vm->play_tape(drv, tape_status[drv].path);
2046 vm->rec_tape(drv, tape_status[drv].path);
2049 out_message(_T("CMT%d: %s"), drv + BASE_TAPE_NUM, tape_status[drv].path);
2051 out_message(_T("CMT: %s"), tape_status[drv].path);
2056 #ifdef USE_COMPACT_DISC
2057 for(int drv = 0; drv < USE_COMPACT_DISC; drv++) {
2058 if(compact_disc_status[drv].wait_count != 0 && --compact_disc_status[drv].wait_count == 0) {
2059 vm->open_compact_disc(drv, compact_disc_status[drv].path);
2060 #if USE_COMPACT_DISC > 1
2061 out_message(_T("CD%d: %s"), drv + BASE_COMPACT_DISC_NUM, compact_disc_status[drv].path);
2063 out_message(_T("CD: %s"), compact_disc_status[drv].path);
2068 #ifdef USE_LASER_DISC
2069 for(int drv = 0; drv < USE_LASER_DISC; drv++) {
2070 if(laser_disc_status[drv].wait_count != 0 && --laser_disc_status[drv].wait_count == 0) {
2071 vm->open_laser_disc(drv, laser_disc_status[drv].path);
2072 #if USE_LASER_DISC > 1
2073 out_message(_T("LD%d: %s"), drv + BASE_LASER_DISC_NUM, laser_disc_status[drv].path);
2075 out_message(_T("LD: %s"), laser_disc_status[drv].path);
2081 for(int drv = 0; drv < USE_BUBBLE; drv++) {
2082 if(bubble_casette_status[drv].wait_count != 0 && --bubble_casette_status[drv].wait_count == 0) {
2083 vm->open_bubble_casette(drv, bubble_casette_status[drv].path, bubble_casette_status[drv].bank);
2085 out_message(_T("Bubble%d: %s"), drv + BASE_BUBBLE_NUM, bubble_casette_status[drv].path);
2087 out_message(_T("Bubble: %s"), bubble_casette_status[drv].path);
2094 void EMU::restore_media()
2097 for(int drv = 0; drv < USE_CART; drv++) {
2098 if(cart_status[drv].path[0] != _T('\0')) {
2099 if(check_file_extension(cart_status[drv].path, _T(".hex")) && hex2bin(cart_status[drv].path, create_local_path(_T("hex2bin.$$$")))) {
2100 vm->open_cart(drv, create_local_path(_T("hex2bin.$$$")));
2101 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
2103 vm->open_cart(drv, cart_status[drv].path);
2108 #ifdef USE_FLOPPY_DISK
2109 for(int drv = 0; drv < USE_FLOPPY_DISK; drv++) {
2110 if(floppy_disk_status[drv].path[0] != _T('\0')) {
2111 vm->open_floppy_disk(drv, floppy_disk_status[drv].path, floppy_disk_status[drv].bank);
2115 #ifdef USE_QUICK_DISK
2116 for(int drv = 0; drv < USE_QUICK_DISK; drv++) {
2117 if(quick_disk_status[drv].path[0] != _T('\0')) {
2118 vm->open_quick_disk(drv, quick_disk_status[drv].path);
2122 #ifdef USE_HARD_DISK
2123 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
2124 if(hard_disk_status[drv].path[0] != _T('\0')) {
2125 vm->open_hard_disk(drv, hard_disk_status[drv].path);
2130 for(int drv = 0; drv < USE_TAPE; drv++) {
2131 if(tape_status[drv].path[0] != _T('\0')) {
2132 if(tape_status[drv].play) {
2133 vm->play_tape(drv, tape_status[drv].path);
2135 tape_status[drv].path[0] = _T('\0');
2140 #ifdef USE_COMPACT_DISC
2141 for(int drv = 0; drv < USE_COMPACT_DISC; drv++) {
2142 if(compact_disc_status[drv].path[0] != _T('\0')) {
2143 vm->open_compact_disc(drv, compact_disc_status[drv].path);
2147 #ifdef USE_LASER_DISC
2148 for(int drv = 0; drv < USE_LASER_DISC; drv++) {
2149 if(laser_disc_status[drv].path[0] != _T('\0')) {
2150 vm->open_laser_disc(drv, laser_disc_status[drv].path);
2155 for(int drv = 0; drv < USE_BUBBLE; drv++) {
2156 if(bubble_casette_status[drv].path[0] != _T('\0')) {
2157 vm->open_bubble_casette(drv, bubble_casette_status[drv].path, bubble_casette_status[drv].bank);
2164 void EMU::open_cart(int drv, const _TCHAR* file_path)
2166 if(drv < USE_CART) {
2167 if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, create_local_path(_T("hex2bin.$$$")))) {
2168 vm->open_cart(drv, create_local_path(_T("hex2bin.$$$")));
2169 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
2171 vm->open_cart(drv, file_path);
2173 my_tcscpy_s(cart_status[drv].path, _MAX_PATH, file_path);
2174 out_message(_T("Cart%d: %s"), drv + 1, file_path);
2175 #if !defined(_USE_QT)
2176 // restart recording
2177 bool s = osd->now_record_sound;
2178 bool v = osd->now_record_video;
2179 stop_record_sound();
2180 stop_record_video();
2182 if(s) osd->start_record_sound();
2183 if(v) osd->start_record_video(-1);
2188 void EMU::close_cart(int drv)
2190 if(drv < USE_CART) {
2191 vm->close_cart(drv);
2192 clear_media_status(&cart_status[drv]);
2194 out_message(_T("Cart%d: Ejected"), drv + BASE_CART_NUM);
2196 out_message(_T("Cart: Ejected"));
2198 #if !defined(_USE_QT)
2200 stop_record_video();
2201 stop_record_sound();
2206 bool EMU::is_cart_inserted(int drv)
2208 if(drv < USE_CART) {
2209 return vm->is_cart_inserted(drv);
2216 #ifdef USE_FLOPPY_DISK
2217 void EMU::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
2219 if(drv < USE_FLOPPY_DISK) {
2220 if(vm->is_floppy_disk_inserted(drv)) {
2221 vm->close_floppy_disk(drv);
2223 #ifdef SUPPORT_VARIABLE_TIMING
2224 floppy_disk_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2226 floppy_disk_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
2228 #if USE_FLOPPY_DISK > 1
2229 out_message(_T("FD%d: Ejected"), drv + BASE_FLOPPY_DISK_NUM);
2231 out_message(_T("FD: Ejected"));
2233 } else if(floppy_disk_status[drv].wait_count == 0) {
2234 vm->open_floppy_disk(drv, file_path, bank);
2235 #if USE_FLOPPY_DISK > 1
2236 out_message(_T("FD%d: %s"), drv + BASE_FLOPPY_DISK_NUM, file_path);
2238 out_message(_T("FD: %s"), file_path);
2241 my_tcscpy_s(floppy_disk_status[drv].path, _MAX_PATH, file_path);
2242 floppy_disk_status[drv].bank = bank;
2246 void EMU::close_floppy_disk(int drv)
2248 if(drv < USE_FLOPPY_DISK) {
2249 vm->close_floppy_disk(drv);
2250 clear_media_status(&floppy_disk_status[drv]);
2251 #if USE_FLOPPY_DISK > 1
2252 out_message(_T("FD%d: Ejected"), drv + BASE_FLOPPY_DISK_NUM);
2254 out_message(_T("FD: Ejected"));
2259 bool EMU::is_floppy_disk_inserted(int drv)
2261 if(drv < USE_FLOPPY_DISK) {
2262 return vm->is_floppy_disk_inserted(drv);
2268 void EMU::is_floppy_disk_protected(int drv, bool value)
2270 if(drv < USE_FLOPPY_DISK) {
2271 vm->is_floppy_disk_protected(drv, value);
2275 bool EMU::is_floppy_disk_protected(int drv)
2277 if(drv < USE_FLOPPY_DISK) {
2278 return vm->is_floppy_disk_protected(drv);
2284 uint32_t EMU::is_floppy_disk_accessed()
2286 return vm->is_floppy_disk_accessed();
2290 #ifdef USE_QUICK_DISK
2291 void EMU::open_quick_disk(int drv, const _TCHAR* file_path)
2293 if(drv < USE_QUICK_DISK) {
2294 if(vm->is_quick_disk_inserted(drv)) {
2295 vm->close_quick_disk(drv);
2297 #ifdef SUPPORT_VARIABLE_TIMING
2298 quick_disk_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2300 quick_disk_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
2302 #if USE_QUICK_DISK > 1
2303 out_message(_T("QD%d: Ejected"), drv + BASE_QUICK_DISK_NUM);
2305 out_message(_T("QD: Ejected"));
2307 } else if(quick_disk_status[drv].wait_count == 0) {
2308 vm->open_quick_disk(drv, file_path);
2309 #if USE_QUICK_DISK > 1
2310 out_message(_T("QD%d: %s"), drv + BASE_QUICK_DISK_NUM, file_path);
2312 out_message(_T("QD: %s"), file_path);
2315 my_tcscpy_s(quick_disk_status[drv].path, _MAX_PATH, file_path);
2319 void EMU::close_quick_disk(int drv)
2321 if(drv < USE_QUICK_DISK) {
2322 vm->close_quick_disk(drv);
2323 clear_media_status(&quick_disk_status[drv]);
2324 #if USE_QUICK_DISK > 1
2325 out_message(_T("QD%d: Ejected"), drv + BASE_QUICK_DISK_NUM);
2327 out_message(_T("QD: Ejected"));
2332 bool EMU::is_quick_disk_inserted(int drv)
2334 if(drv < USE_QUICK_DISK) {
2335 return vm->is_quick_disk_inserted(drv);
2341 uint32_t EMU::is_quick_disk_accessed()
2343 return vm->is_quick_disk_accessed();
2347 #ifdef USE_HARD_DISK
2348 void EMU::open_hard_disk(int drv, const _TCHAR* file_path)
2350 if(drv < USE_HARD_DISK) {
2351 if(vm->is_hard_disk_inserted(drv)) {
2352 vm->close_hard_disk(drv);
2354 #ifdef SUPPORT_VARIABLE_TIMING
2355 hard_disk_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2357 hard_disk_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
2359 #if USE_HARD_DISK > 1
2360 out_message(_T("HD%d: Ejected"), drv + BASE_HARD_DISK_NUM);
2362 out_message(_T("HD: Ejected"));
2364 } else if(hard_disk_status[drv].wait_count == 0) {
2365 vm->open_hard_disk(drv, file_path);
2366 #if USE_HARD_DISK > 1
2367 out_message(_T("HD%d: %s"), drv + BASE_HARD_DISK_NUM, file_path);
2369 out_message(_T("HD: %s"), file_path);
2372 my_tcscpy_s(hard_disk_status[drv].path, _MAX_PATH, file_path);
2376 void EMU::close_hard_disk(int drv)
2378 if(drv < USE_HARD_DISK) {
2379 vm->close_hard_disk(drv);
2380 clear_media_status(&hard_disk_status[drv]);
2381 #if USE_HARD_DISK > 1
2382 out_message(_T("HD%d: Ejected"), drv + BASE_HARD_DISK_NUM);
2384 out_message(_T("HD: Ejected"));
2389 bool EMU::is_hard_disk_inserted(int drv)
2391 if(drv < USE_HARD_DISK) {
2392 return vm->is_hard_disk_inserted(drv);
2398 uint32_t EMU::is_hard_disk_accessed()
2400 return vm->is_hard_disk_accessed();
2405 void EMU::play_tape(int drv, const _TCHAR* file_path)
2407 if(drv < USE_TAPE) {
2408 if(vm->is_tape_inserted(drv)) {
2409 vm->close_tape(drv);
2411 #ifdef SUPPORT_VARIABLE_TIMING
2412 tape_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2414 tape_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
2417 out_message(_T("CMT%d: Ejected"), drv + BASE_TAPE_NUM);
2419 out_message(_T("CMT: Ejected"));
2421 } else if(tape_status[drv].wait_count == 0) {
2422 vm->play_tape(drv, file_path);
2424 out_message(_T("CMT%d: %s"), drv + BASE_TAPE_NUM, file_path);
2426 out_message(_T("CMT: %s"), file_path);
2429 my_tcscpy_s(tape_status[drv].path, _MAX_PATH, file_path);
2430 tape_status[drv].play = true;
2434 void EMU::rec_tape(int drv, const _TCHAR* file_path)
2436 if(drv < USE_TAPE) {
2437 if(vm->is_tape_inserted(drv)) {
2438 vm->close_tape(drv);
2440 #ifdef SUPPORT_VARIABLE_TIMING
2441 tape_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2443 tape_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
2446 out_message(_T("CMT%d: Ejected"), drv + BASE_TAPE_NUM);
2448 out_message(_T("CMT: Ejected"));
2450 } else if(tape_status[drv].wait_count == 0) {
2451 vm->rec_tape(drv, file_path);
2453 out_message(_T("CMT%d: %s"), drv + BASE_TAPE_NUM, file_path);
2455 out_message(_T("CMT: %s"), file_path);
2458 my_tcscpy_s(tape_status[drv].path, _MAX_PATH, file_path);
2459 tape_status[drv].play = false;
2463 void EMU::close_tape(int drv)
2465 if(drv < USE_TAPE) {
2466 vm->close_tape(drv);
2467 clear_media_status(&tape_status[drv]);
2469 out_message(_T("CMT%d: Ejected"), drv + BASE_TAPE_NUM);
2471 out_message(_T("CMT: Ejected"));
2476 bool EMU::is_tape_inserted(int drv)
2478 if(drv < USE_TAPE) {
2479 return vm->is_tape_inserted(drv);
2485 bool EMU::is_tape_playing(int drv)
2487 #ifndef TAPE_BINARY_ONLY
2488 if(drv < USE_TAPE) {
2489 return vm->is_tape_playing(drv);
2495 bool EMU::is_tape_recording(int drv)
2497 #ifndef TAPE_BINARY_ONLY
2498 if(drv < USE_TAPE) {
2499 return vm->is_tape_recording(drv);
2505 int EMU::get_tape_position(int drv)
2507 #ifndef TAPE_BINARY_ONLY
2508 if(drv < USE_TAPE) {
2509 return vm->get_tape_position(drv);
2515 const _TCHAR* EMU::get_tape_message(int drv)
2517 #ifndef TAPE_BINARY_ONLY
2518 if(drv < USE_TAPE) {
2519 return vm->get_tape_message(drv);
2525 void EMU::push_play(int drv)
2527 #ifdef USE_TAPE_BUTTON
2528 if(drv < USE_TAPE) {
2534 void EMU::push_stop(int drv)
2536 #ifdef USE_TAPE_BUTTON
2537 if(drv < USE_TAPE) {
2543 void EMU::push_fast_forward(int drv)
2545 #ifdef USE_TAPE_BUTTON
2546 if(drv < USE_TAPE) {
2547 vm->push_fast_forward(drv);
2552 void EMU::push_fast_rewind(int drv)
2554 #ifdef USE_TAPE_BUTTON
2555 if(drv < USE_TAPE) {
2556 vm->push_fast_rewind(drv);
2561 void EMU::push_apss_forward(int drv)
2563 #ifdef USE_TAPE_BUTTON
2564 if(drv < USE_TAPE) {
2565 vm->push_apss_forward(drv);
2570 void EMU::push_apss_rewind(int drv)
2572 #ifdef USE_TAPE_BUTTON
2573 if(drv < USE_TAPE) {
2574 vm->push_apss_rewind(drv);
2580 #ifdef USE_COMPACT_DISC
2581 void EMU::open_compact_disc(int drv, const _TCHAR* file_path)
2583 if(vm->is_compact_disc_inserted(drv)) {
2584 vm->close_compact_disc(drv);
2586 #ifdef SUPPORT_VARIABLE_TIMING
2587 compact_disc_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2589 compact_disc_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
2591 #if USE_COMPACT_DISC > 1
2592 out_message(_T("CD%d: Ejected"), drv + BASE_COMPACT_DISC_NUM);
2594 out_message(_T("CD: Ejected"));
2596 } else if(compact_disc_status[drv].wait_count == 0) {
2597 vm->open_compact_disc(drv, file_path);
2598 #if USE_COMPACT_DISC > 1
2599 out_message(_T("CD%d: %s"), drv + BASE_COMPACT_DISC_NUM, file_path);
2601 out_message(_T("CD: %s"), file_path);
2604 my_tcscpy_s(compact_disc_status[drv].path, _MAX_PATH, file_path);
2607 void EMU::close_compact_disc(int drv)
2609 vm->close_compact_disc(drv);
2610 clear_media_status(&compact_disc_status[drv]);
2611 #if USE_COMPACT_DISC > 1
2612 out_message(_T("CD%d: Ejected"), drv + BASE_COMPACT_DISC_NUM);
2614 out_message(_T("CD: Ejected"));
2618 bool EMU::is_compact_disc_inserted(int drv)
2620 return vm->is_compact_disc_inserted(drv);
2623 uint32_t EMU::is_compact_disc_accessed()
2625 return vm->is_compact_disc_accessed();
2629 #ifdef USE_LASER_DISC
2630 void EMU::open_laser_disc(int drv, const _TCHAR* file_path)
2632 if(vm->is_laser_disc_inserted(drv)) {
2633 vm->close_laser_disc(drv);
2635 #ifdef SUPPORT_VARIABLE_TIMING
2636 laser_disc_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2638 laser_disc_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
2640 #if USE_LASER_DISC > 1
2641 out_message(_T("LD%d: Ejected"), drv + BASE_LASER_DISC_NUM);
2643 out_message(_T("LD: Ejected"));
2645 } else if(laser_disc_status[drv].wait_count == 0) {
2646 vm->open_laser_disc(drv, file_path);
2647 #if USE_LASER_DISC > 1
2648 out_message(_T("LD%d: %s"), drv + BASE_LASER_DISC_NUM, file_path);
2650 out_message(_T("LD: %s"), file_path);
2653 my_tcscpy_s(laser_disc_status[drv].path, _MAX_PATH, file_path);
2656 void EMU::close_laser_disc(int drv)
2658 vm->close_laser_disc(drv);
2659 clear_media_status(&laser_disc_status[drv]);
2660 #if USE_LASER_DISC > 1
2661 out_message(_T("LD%d: Ejected"), drv + BASE_LASER_DISC_NUM);
2663 out_message(_T("LD: Ejected"));
2667 bool EMU::is_laser_disc_inserted(int drv)
2669 return vm->is_laser_disc_inserted(drv);
2672 uint32_t EMU::is_laser_disc_accessed()
2674 return vm->is_laser_disc_accessed();
2678 #ifdef USE_BINARY_FILE
2679 void EMU::load_binary(int drv, const _TCHAR* file_path)
2681 if(drv < USE_BINARY_FILE) {
2682 if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, create_local_path(_T("hex2bin.$$$")))) {
2683 vm->load_binary(drv, create_local_path(_T("hex2bin.$$$")));
2684 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
2686 vm->load_binary(drv, file_path);
2688 #if USE_BINARY_FILE > 1
2689 out_message(_T("Load Binary%d: %s"), drv + BASE_BINARY_FILE_NUM, file_path);
2691 out_message(_T("Load Binary: %s"), file_path);
2696 void EMU::save_binary(int drv, const _TCHAR* file_path)
2698 if(drv < USE_BINARY_FILE) {
2699 vm->save_binary(drv, file_path);
2700 #if USE_BINARY_FILE > 1
2701 out_message(_T("Save Binary%d: %s"), drv + BASE_BINARY_FILE_NUM, file_path);
2703 out_message(_T("Save Binary: %s"), file_path);
2710 void EMU::open_bubble_casette(int drv, const _TCHAR* file_path, int bank)
2712 if(drv < USE_BUBBLE) {
2713 if(vm->is_bubble_casette_inserted(drv)) {
2714 vm->close_bubble_casette(drv);
2716 #ifdef SUPPORT_VARIABLE_TIMING
2717 bubble_casette_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2719 bubble_casette_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
2722 out_message(_T("Bubble%d: Ejected"), drv + BASE_BUBBLE_NUM);
2724 out_message(_T("Bubble: Ejected"));
2726 } else if(bubble_casette_status[drv].wait_count == 0) {
2727 vm->open_bubble_casette(drv, file_path, bank);
2729 out_message(_T("Bubble%d: %s"), drv + BASE_BUBBLE_NUM, file_path);
2731 out_message(_T("Bubble: %s"), file_path);
2734 my_tcscpy_s(bubble_casette_status[drv].path, _MAX_PATH, file_path);
2735 bubble_casette_status[drv].bank = bank;
2739 void EMU::close_bubble_casette(int drv)
2741 if(drv < USE_BUBBLE) {
2742 vm->close_bubble_casette(drv);
2743 clear_media_status(&bubble_casette_status[drv]);
2745 out_message(_T("Bubble%d: Ejected"), drv + BASE_BUBBLE_NUM);
2747 out_message(_T("Bubble: Ejected"));
2752 bool EMU::is_bubble_casette_inserted(int drv)
2754 if(drv < USE_BUBBLE) {
2755 return vm->is_bubble_casette_inserted(drv);
2761 bool EMU::is_bubble_casette_protected(int drv)
2763 if(drv < USE_BUBBLE) {
2764 return vm->is_bubble_casette_protected(drv);
2770 void EMU::is_bubble_casette_protected(int drv, bool flag)
2772 if(drv < USE_BUBBLE) {
2773 vm->is_bubble_casette_protected(drv, flag);
2781 #ifdef USE_LED_DEVICE
2782 uint32_t EMU::get_led_status()
2784 return vm->get_led_status();
2789 #ifdef USE_SOUND_VOLUME
2790 void EMU::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
2792 vm->set_sound_device_volume(ch, decibel_l, decibel_r);
2796 void EMU::update_config()
2798 vm->update_config();
2803 void EMU::load_sound_file(int id, const _TCHAR *name, int16_t **data, int *dst_size)
2805 osd->load_sound_file(id, name, data, dst_size);
2808 void EMU::free_sound_file(int id, int16_t **data)
2810 osd->free_sound_file(id, data);
2815 // ----------------------------------------------------------------------------
2817 // ----------------------------------------------------------------------------
2820 #define STATE_VERSION 2
2822 void EMU::save_state(const _TCHAR* file_path)
2824 FILEIO* fio = new FILEIO();
2827 if(config.compress_state) {
2828 fio->Gzopen(file_path, FILEIO_WRITE_BINARY);
2831 if(!fio->IsOpened()) {
2832 fio->Fopen(file_path, FILEIO_WRITE_BINARY);
2834 if(fio->IsOpened()) {
2835 // save state file version
2836 fio->FputUint32(STATE_VERSION);
2838 save_config_state((void *)fio);
2839 // save inserted medias
2841 fio->Fwrite(&cart_status, sizeof(cart_status), 1);
2843 #ifdef USE_FLOPPY_DISK
2844 fio->Fwrite(floppy_disk_status, sizeof(floppy_disk_status), 1);
2845 fio->Fwrite(d88_file, sizeof(d88_file), 1);
2847 #ifdef USE_QUICK_DISK
2848 fio->Fwrite(&quick_disk_status, sizeof(quick_disk_status), 1);
2850 #ifdef USE_HARD_DISK
2851 fio->Fwrite(&hard_disk_status, sizeof(hard_disk_status), 1);
2854 fio->Fwrite(&tape_status, sizeof(tape_status), 1);
2856 #ifdef USE_COMPACT_DISC
2857 fio->Fwrite(&compact_disc_status, sizeof(compact_disc_status), 1);
2859 #ifdef USE_LASER_DISC
2860 fio->Fwrite(&laser_disc_status, sizeof(laser_disc_status), 1);
2863 fio->Fwrite(&bubble_casette_status, sizeof(bubble_casette_status), 1);
2866 vm->save_state(fio);
2867 // end of state file
2875 void EMU::load_state(const _TCHAR* file_path)
2877 if(FILEIO::IsFileExisting(file_path)) {
2880 config.romaji_to_kana = false;
2883 save_state(create_local_path(_T("$temp$.sta")));
2884 if(!load_state_tmp(file_path)) {
2885 out_debug_log(_T("failed to load state file\n"));
2886 load_state_tmp(create_local_path(_T("$temp$.sta")));
2888 FILEIO::RemoveFile(create_local_path(_T("$temp$.sta")));
2892 bool EMU::load_state_tmp(const _TCHAR* file_path)
2894 bool result = false;
2895 FILEIO* fio = new FILEIO();
2898 if(config.compress_state) {
2899 fio->Gzopen(file_path, FILEIO_READ_BINARY);
2902 if(!fio->IsOpened()) {
2903 fio->Fopen(file_path, FILEIO_READ_BINARY);
2905 if(fio->IsOpened()) {
2906 // check state file version
2907 if(fio->FgetUint32() == STATE_VERSION) {
2909 if(load_config_state((void *)fio)) {
2910 // load inserted medias
2912 fio->Fread(&cart_status, sizeof(cart_status), 1);
2914 #ifdef USE_FLOPPY_DISK
2915 fio->Fread(floppy_disk_status, sizeof(floppy_disk_status), 1);
2916 fio->Fread(d88_file, sizeof(d88_file), 1);
2918 #ifdef USE_QUICK_DISK
2919 fio->Fread(&quick_disk_status, sizeof(quick_disk_status), 1);
2921 #ifdef USE_HARD_DISK
2922 fio->Fread(&hard_disk_status, sizeof(hard_disk_status), 1);
2925 fio->Fread(&tape_status, sizeof(tape_status), 1);
2927 #ifdef USE_COMPACT_DISC
2928 fio->Fread(&compact_disc_status, sizeof(compact_disc_status), 1);
2930 #ifdef USE_LASER_DISC
2931 fio->Fread(&laser_disc_status, sizeof(laser_disc_status), 1);
2934 fio->Fread(&bubble_casette_status, sizeof(bubble_casette_status), 1);
2936 // check if virtual machine should be reinitialized
2937 bool reinitialize = false;
2939 reinitialize |= (cpu_type != config.cpu_type);
2940 cpu_type = config.cpu_type;
2942 #ifdef USE_SOUND_TYPE
2943 reinitialize |= (sound_type != config.sound_type);
2944 sound_type = config.sound_type;
2946 #ifdef USE_PRINTER_TYPE
2947 reinitialize |= (printer_type != config.printer_type);
2948 printer_type = config.printer_type;
2950 if(!(0 <= config.sound_frequency && config.sound_frequency < 8)) {
2951 config.sound_frequency = 6; // default: 48KHz
2953 if(!(0 <= config.sound_latency && config.sound_latency < 5)) {
2954 config.sound_latency = 1; // default: 100msec
2956 reinitialize |= (sound_frequency != config.sound_frequency);
2957 reinitialize |= (sound_latency != config.sound_latency);
2958 sound_frequency = config.sound_frequency;
2959 sound_latency = config.sound_latency;
2964 // reinitialize virtual machine
2967 osd->vm = vm = new VM(this);
2968 # if defined(_USE_QT)
2969 osd->reset_vm_node();
2971 vm->initialize_sound(sound_rate, sound_samples);
2972 #ifdef USE_SOUND_VOLUME
2973 for(int i = 0; i < USE_SOUND_VOLUME; i++) {
2974 vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
2980 // restore inserted medias
2983 if(vm->load_state(fio)) {
2984 // check end of state
2985 result = (fio->FgetInt32() == -1);