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 dipswitch = config.dipswitch;
77 sound_type = config.sound_type;
79 #ifdef USE_PRINTER_TYPE
80 printer_type = config.printer_type;
83 // initialize b77 file info
84 memset(b77_file, 0, sizeof(b77_file));
89 osd = new OSD(p, csp_logger);
90 osd->main_window_handle = hwnd;
93 #elif defined(OSD_WIN32)
95 osd->main_window_handle = hwnd;
96 osd->instance_handle = hinst;
98 int presented_rate, presented_samples;
99 osd->initialize(sound_rate, sound_samples, &presented_rate, &presented_samples);
100 sound_rate = presented_rate;
101 sound_samples = presented_samples;
105 # if defined(_USE_QT)
106 osd->reset_vm_node();
109 initialize_auto_key();
112 initialize_debugger();
114 now_waiting_in_debugger = false;
116 vm->initialize_sound(sound_rate, sound_samples);
117 #ifdef USE_SOUND_VOLUME
118 for(int i = 0; i < USE_SOUND_VOLUME; i++) {
119 vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
123 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
124 if(config.last_hard_disk_path[drv][0] != _T('\0') && FILEIO::IsFileExisting(config.last_hard_disk_path[drv])) {
125 vm->open_hard_disk(drv, config.last_hard_disk_path[drv]);
126 my_tcscpy_s(hard_disk_status[drv].path, _MAX_PATH, config.last_hard_disk_path[drv]);
131 now_suspended = false;
153 EmuThreadClass *EMU::get_parent_handler()
155 return osd->get_parent_handler();
158 void EMU::set_parent_handler(EmuThreadClass *p, DrawThreadClass *q)
160 osd->set_parent_thread(p);
161 osd->set_draw_thread(q);
164 void EMU::set_host_cpus(int v)
166 osd->host_cpus = (v <= 0) ? 1 : v;
169 int EMU::get_host_cpus()
171 return osd->host_cpus;
175 // ----------------------------------------------------------------------------
177 // ----------------------------------------------------------------------------
179 double EMU::get_frame_rate()
181 return vm->get_frame_rate();
184 int EMU::get_frame_interval()
186 static int prev_interval = 0;
187 static double prev_fps = -1;
188 double fps = vm->get_frame_rate();
189 if(prev_fps != fps) {
190 prev_interval = (int)(1024. * 1000. / fps + 0.5);
193 return prev_interval;
196 bool EMU::is_frame_skippable()
198 return vm->is_frame_skippable();
205 now_suspended = false;
216 #if !defined(_USE_QT) // Temporally
217 osd->update_socket();
222 // virtual machine may be driven to fill sound buffer
223 int extra_frames = 0;
224 osd->update_sound(&extra_frames);
226 // drive virtual machine
227 if(extra_frames == 0) {
233 osd->add_extra_frames(extra_frames);
241 config.romaji_to_kana = false;
244 // check if virtual machine should be reinitialized
245 bool reinitialize = false;
247 reinitialize |= (cpu_type != config.cpu_type);
248 cpu_type = config.cpu_type;
251 reinitialize |= (dipswitch != config.dipswitch);
252 dipswitch = config.dipswitch;
254 #ifdef USE_SOUND_TYPE
255 reinitialize |= (sound_type != config.sound_type);
256 sound_type = config.sound_type;
258 #ifdef USE_PRINTER_TYPE
259 reinitialize |= (printer_type != config.printer_type);
260 printer_type = config.printer_type;
265 // reinitialize virtual machine
271 osd->reset_vm_node();
274 int presented_samples;
275 sound_rate = sound_frequency_table[config.sound_frequency];
276 sound_samples = (int)(sound_rate * sound_latency_table[config.sound_latency] + 0.5);
277 osd->initialize_sound(sound_rate, sound_samples, &presented_rate, &presented_samples);
278 if((sound_rate != presented_rate) ||
279 (sound_samples != presented_samples)) {
280 sound_rate = presented_rate;
281 sound_samples = presented_samples;
283 vm->initialize_sound(sound_rate, sound_samples);
284 #ifdef USE_SOUND_VOLUME
285 for(int i = 0; i < USE_SOUND_VOLUME; i++) {
286 vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
289 // restore inserted medias
294 // reset virtual machine
300 #if !defined(_USE_QT) // Temporally
302 osd->restart_record_sound();
303 osd->restart_record_video();
307 #ifdef USE_SPECIAL_RESET
308 void EMU::special_reset()
312 config.romaji_to_kana = false;
315 // reset virtual machine
320 #if !defined(_USE_QT) // Temporally
321 restart_record_sound();
322 restart_record_video();
327 #ifdef USE_NOTIFY_POWER_OFF
328 void EMU::notify_power_off()
330 vm->notify_power_off();
334 void EMU::power_off()
343 now_suspended = true;
352 void EMU::unlock_vm()
357 void EMU::force_unlock_vm()
359 osd->force_unlock_vm();
362 bool EMU::is_vm_locked()
364 return osd->is_vm_locked();
367 // ----------------------------------------------------------------------------
369 // ----------------------------------------------------------------------------
372 void EMU::key_down(int code, bool extended, bool repeat)
376 shift_pressed = true;
378 if(config.romaji_to_kana) {
380 // Page Up, Page Down, End, Home, Left, Up, Right, Down, Ins, Del, Help, and F1-F12
381 if((code >= 0x21 && code <= 0x2f) || (code >= 0x70 && code <= 0x7b)) {
383 auto_key_buffer->write(code | 0x100);
385 auto_key_buffer->write(code);
387 if(!is_auto_key_running()) {
392 } else if(!is_auto_key_running())
394 osd->key_down(code, extended, repeat);
397 void EMU::key_up(int code, bool extended)
401 shift_pressed = false;
403 if(config.romaji_to_kana) {
405 } else if(!is_auto_key_running())
407 osd->key_up(code, extended);
410 void EMU::key_char(char code)
413 if(config.romaji_to_kana) {
414 set_auto_key_char(code);
419 #ifdef USE_KEY_LOCKED
420 bool EMU::get_caps_locked()
422 return vm->get_caps_locked();
425 bool EMU::get_kana_locked()
427 return vm->get_kana_locked();
431 void EMU::key_lost_focus()
433 osd->key_lost_focus();
436 #ifdef ONE_BOARD_MICRO_COMPUTER
437 void EMU::press_button(int num)
439 int code = vm_buttons[num].code;
442 osd->key_down_native(code, false);
443 osd->get_key_buffer()[code] = KEY_KEEP_FRAMES;
445 // code=0: reset virtual machine
452 void EMU::enable_mouse()
457 void EMU::disable_mouse()
459 osd->disable_mouse();
462 void EMU::toggle_mouse()
467 bool EMU::is_mouse_enabled()
469 return osd->is_mouse_enabled();
474 static const int auto_key_table_base[][2] = {
479 {0x08, 0x000 | 0x08}, // BS
480 {0x09, 0x000 | 0x09}, // Tab
481 {0x0d, 0x000 | 0x0d}, // Enter
482 {0x1b, 0x000 | 0x1b}, // Escape
483 {0x20, 0x000 | 0x20}, // ' '
485 {0x21, 0x100 | 0x31}, // '!'
486 {0x22, 0x100 | 0xba}, // '"'
487 {0x23, 0x100 | 0x33}, // '#'
488 {0x24, 0x100 | 0x34}, // '$'
489 {0x25, 0x100 | 0x35}, // '%'
490 {0x26, 0x100 | 0x37}, // '&'
491 {0x27, 0x000 | 0xba}, // '''
492 {0x28, 0x100 | 0x39}, // '('
493 {0x29, 0x100 | 0x30}, // ')'
494 {0x2a, 0x100 | 0x38}, // '*'
495 {0x2b, 0x100 | 0xde}, // '+'
496 {0x2c, 0x000 | 0xbc}, // ','
497 {0x2d, 0x000 | 0xbd}, // '-'
498 {0x2e, 0x000 | 0xbe}, // '.'
499 {0x2f, 0x000 | 0xbf}, // '/'
501 {0x21, 0x100 | 0x31}, // '!'
502 {0x22, 0x100 | 0x32}, // '"'
503 {0x23, 0x100 | 0x33}, // '#'
504 {0x24, 0x100 | 0x34}, // '$'
505 {0x25, 0x100 | 0x35}, // '%'
506 {0x26, 0x100 | 0x36}, // '&'
507 {0x27, 0x100 | 0x37}, // '''
508 {0x28, 0x100 | 0x38}, // '('
509 {0x29, 0x100 | 0x39}, // ')'
510 {0x2a, 0x100 | 0xba}, // '*'
511 {0x2b, 0x100 | 0xbb}, // '+'
512 {0x2c, 0x000 | 0xbc}, // ','
513 {0x2d, 0x000 | 0xbd}, // '-'
514 {0x2e, 0x000 | 0xbe}, // '.'
515 {0x2f, 0x000 | 0xbf}, // '/'
517 {0x30, 0x000 | 0x30}, // '0'
518 {0x31, 0x000 | 0x31}, // '1'
519 {0x32, 0x000 | 0x32}, // '2'
520 {0x33, 0x000 | 0x33}, // '3'
521 {0x34, 0x000 | 0x34}, // '4'
522 {0x35, 0x000 | 0x35}, // '5'
523 {0x36, 0x000 | 0x36}, // '6'
524 {0x37, 0x000 | 0x37}, // '7'
525 {0x38, 0x000 | 0x38}, // '8'
526 {0x39, 0x000 | 0x39}, // '9'
528 {0x3a, 0x100 | 0xbb}, // ':'
529 {0x3b, 0x000 | 0xbb}, // ';'
530 {0x3c, 0x100 | 0xbc}, // '<'
531 {0x3d, 0x000 | 0xde}, // '='
532 {0x3e, 0x100 | 0xbe}, // '>'
533 {0x3f, 0x100 | 0xbf}, // '?'
534 {0x40, 0x100 | 0x32}, // '@'
536 {0x3a, 0x000 | 0xba}, // ':'
537 {0x3b, 0x000 | 0xbb}, // ';'
538 {0x3c, 0x100 | 0xbc}, // '<'
539 {0x3d, 0x100 | 0xbd}, // '='
540 {0x3e, 0x100 | 0xbe}, // '>'
541 {0x3f, 0x100 | 0xbf}, // '?'
542 {0x40, 0x000 | 0xc0}, // '@'
544 {0x41, 0x400 | 0x41}, // 'A'
545 {0x42, 0x400 | 0x42}, // 'B'
546 {0x43, 0x400 | 0x43}, // 'C'
547 {0x44, 0x400 | 0x44}, // 'D'
548 {0x45, 0x400 | 0x45}, // 'E'
549 {0x46, 0x400 | 0x46}, // 'F'
550 {0x47, 0x400 | 0x47}, // 'G'
551 {0x48, 0x400 | 0x48}, // 'H'
552 {0x49, 0x400 | 0x49}, // 'I'
553 {0x4a, 0x400 | 0x4a}, // 'J'
554 {0x4b, 0x400 | 0x4b}, // 'K'
555 {0x4c, 0x400 | 0x4c}, // 'L'
556 {0x4d, 0x400 | 0x4d}, // 'M'
557 {0x4e, 0x400 | 0x4e}, // 'N'
558 {0x4f, 0x400 | 0x4f}, // 'O'
559 {0x50, 0x400 | 0x50}, // 'P'
560 {0x51, 0x400 | 0x51}, // 'Q'
561 {0x52, 0x400 | 0x52}, // 'R'
562 {0x53, 0x400 | 0x53}, // 'S'
563 {0x54, 0x400 | 0x54}, // 'T'
564 {0x55, 0x400 | 0x55}, // 'U'
565 {0x56, 0x400 | 0x56}, // 'V'
566 {0x57, 0x400 | 0x57}, // 'W'
567 {0x58, 0x400 | 0x58}, // 'X'
568 {0x59, 0x400 | 0x59}, // 'Y'
569 {0x5a, 0x400 | 0x5a}, // 'Z'
571 {0x5b, 0x000 | 0xc0}, // '['
572 {0x5c, 0x000 | 0xe2}, // '\'
573 {0x5d, 0x000 | 0xdb}, // ']'
574 {0x5e, 0x100 | 0x36}, // '^'
575 {0x5f, 0x100 | 0xbd}, // '_'
576 {0x60, 0x000 | 0xdd}, // '`'
578 {0x5b, 0x000 | 0xdb}, // '['
579 {0x5c, 0x000 | 0xdc}, // '\'
580 {0x5d, 0x000 | 0xdd}, // ']'
581 {0x5e, 0x000 | 0xde}, // '^'
582 {0x5f, 0x100 | 0xe2}, // '_'
583 {0x60, 0x100 | 0xc0}, // '`'
585 {0x61, 0x800 | 0x41}, // 'a'
586 {0x62, 0x800 | 0x42}, // 'b'
587 {0x63, 0x800 | 0x43}, // 'c'
588 {0x64, 0x800 | 0x44}, // 'd'
589 {0x65, 0x800 | 0x45}, // 'e'
590 {0x66, 0x800 | 0x46}, // 'f'
591 {0x67, 0x800 | 0x47}, // 'g'
592 {0x68, 0x800 | 0x48}, // 'h'
593 {0x69, 0x800 | 0x49}, // 'i'
594 {0x6a, 0x800 | 0x4a}, // 'j'
595 {0x6b, 0x800 | 0x4b}, // 'k'
596 {0x6c, 0x800 | 0x4c}, // 'l'
597 {0x6d, 0x800 | 0x4d}, // 'm'
598 {0x6e, 0x800 | 0x4e}, // 'n'
599 {0x6f, 0x800 | 0x4f}, // 'o'
600 {0x70, 0x800 | 0x50}, // 'p'
601 {0x71, 0x800 | 0x51}, // 'q'
602 {0x72, 0x800 | 0x52}, // 'r'
603 {0x73, 0x800 | 0x53}, // 's'
604 {0x74, 0x800 | 0x54}, // 't'
605 {0x75, 0x800 | 0x55}, // 'u'
606 {0x76, 0x800 | 0x56}, // 'v'
607 {0x77, 0x800 | 0x57}, // 'w'
608 {0x78, 0x800 | 0x58}, // 'x'
609 {0x79, 0x800 | 0x59}, // 'y'
610 {0x7a, 0x800 | 0x5a}, // 'z'
612 {0x7b, 0x100 | 0xc0}, // '{'
613 {0x7c, 0x100 | 0xe2}, // '|'
614 {0x7d, 0x100 | 0xdb}, // '}'
615 {0x7e, 0x100 | 0xdd}, // '~'
617 {0x7b, 0x100 | 0xdb}, // '{'
618 {0x7c, 0x100 | 0xdc}, // '|'
619 {0x7d, 0x100 | 0xdd}, // '}'
620 {0x7e, 0x100 | 0xde}, // '~'
625 static const int auto_key_table_kana_base[][2] = {
626 {0xa1, 0x300 | 0xbe}, // '¡'
627 {0xa2, 0x300 | 0xdb}, // '¢'
628 {0xa3, 0x300 | 0xdd}, // '£'
629 {0xa4, 0x300 | 0xbc}, // '¤'
630 {0xa5, 0x300 | 0xbf}, // '¥'
631 {0xa6, 0x300 | 0x30}, // '¦'
632 {0xa7, 0x300 | 0x33}, // '§'
633 {0xa8, 0x300 | 0x45}, // '¨'
634 {0xa9, 0x300 | 0x34}, // '©'
635 {0xaa, 0x300 | 0x35}, // 'ª'
636 {0xab, 0x300 | 0x36}, // '«'
637 {0xac, 0x300 | 0x37}, // '¬'
638 {0xad, 0x300 | 0x38}, // ''
639 {0xae, 0x300 | 0x39}, // '®'
640 {0xaf, 0x300 | 0x5a}, // '¯'
641 {0xb0, 0x200 | 0xdc}, // '°'
642 {0xb1, 0x200 | 0x33}, // '±'
643 {0xb2, 0x200 | 0x45}, // '²'
644 {0xb3, 0x200 | 0x34}, // '³'
645 {0xb4, 0x200 | 0x35}, // '´'
646 {0xb5, 0x200 | 0x36}, // 'µ'
647 {0xb6, 0x200 | 0x54}, // '¶'
648 {0xb7, 0x200 | 0x47}, // '·'
649 {0xb8, 0x200 | 0x48}, // '¸'
650 {0xb9, 0x200 | 0xba}, // '¹'
651 {0xba, 0x200 | 0x42}, // 'º'
652 {0xbb, 0x200 | 0x58}, // '»'
653 {0xbc, 0x200 | 0x44}, // '¼'
654 {0xbd, 0x200 | 0x52}, // '½'
655 {0xbe, 0x200 | 0x50}, // '¾'
656 {0xbf, 0x200 | 0x43}, // '¿'
657 {0xc0, 0x200 | 0x51}, // 'À'
658 {0xc1, 0x200 | 0x41}, // 'Á'
659 {0xc2, 0x200 | 0x5a}, // 'Â'
660 {0xc3, 0x200 | 0x57}, // 'Ã'
661 {0xc4, 0x200 | 0x53}, // 'Ä'
662 {0xc5, 0x200 | 0x55}, // 'Å'
663 {0xc6, 0x200 | 0x49}, // 'Æ'
664 {0xc7, 0x200 | 0x31}, // 'Ç'
665 {0xc8, 0x200 | 0xbc}, // 'È'
666 {0xc9, 0x200 | 0x4b}, // 'É'
667 {0xca, 0x200 | 0x46}, // 'Ê'
668 {0xcb, 0x200 | 0x56}, // 'Ë'
669 {0xcc, 0x200 | 0x32}, // 'Ì'
670 {0xcd, 0x200 | 0xde}, // 'Í'
671 {0xce, 0x200 | 0xbd}, // 'Î'
672 {0xcf, 0x200 | 0x4a}, // 'Ï'
673 {0xd0, 0x200 | 0x4e}, // 'Ð'
674 {0xd1, 0x200 | 0xdd}, // 'Ñ'
675 {0xd2, 0x200 | 0xbf}, // 'Ò'
676 {0xd3, 0x200 | 0x4d}, // 'Ó'
677 {0xd4, 0x200 | 0x37}, // 'Ô'
678 {0xd5, 0x200 | 0x38}, // 'Õ'
679 {0xd6, 0x200 | 0x39}, // 'Ö'
680 {0xd7, 0x200 | 0x4f}, // '×'
681 {0xd8, 0x200 | 0x4c}, // 'Ø'
682 {0xd9, 0x200 | 0xbe}, // 'Ù'
683 {0xda, 0x200 | 0xbb}, // 'Ú'
684 {0xdb, 0x200 | 0xe2}, // 'Û'
685 {0xdc, 0x200 | 0x30}, // 'Ü'
686 {0xdd, 0x200 | 0x59}, // 'Ý'
687 {0xde, 0x200 | 0xc0}, // 'Þ'
688 {0xdf, 0x200 | 0xdb}, // 'ß'
692 static const int auto_key_table_50on_base[][2] = {
693 {0xa1, 0x300 | 0xbf}, // '¡'
694 {0xa2, 0x300 | 0xdb}, // '¢'
695 {0xa3, 0x300 | 0xdd}, // '£'
696 {0xa4, 0x300 | 0xbe}, // '¤'
697 {0xa5, 0x300 | 0xe2}, // '¥'
698 {0xa6, 0x200 | 0xbf}, // '¦'
699 {0xa7, 0x300 | 0x31}, // '§'
700 {0xa8, 0x300 | 0x32}, // '¨'
701 {0xa9, 0x300 | 0x33}, // '©'
702 {0xaa, 0x300 | 0x34}, // 'ª'
703 {0xab, 0x300 | 0x35}, // '«'
704 {0xac, 0x300 | 0x4e}, // '¬'
705 {0xad, 0x300 | 0x4d}, // ''
706 {0xae, 0x300 | 0xbc}, // '®'
707 {0xaf, 0x300 | 0x43}, // '¯'
708 {0xb0, 0x300 | 0xba}, // '°'
709 {0xb1, 0x200 | 0x31}, // '±'
710 {0xb2, 0x200 | 0x32}, // '²'
711 {0xb3, 0x200 | 0x33}, // '³'
712 {0xb4, 0x200 | 0x34}, // '´'
713 {0xb5, 0x200 | 0x35}, // 'µ'
714 {0xb6, 0x200 | 0x51}, // '¶'
715 {0xb7, 0x200 | 0x57}, // '·'
716 {0xb8, 0x200 | 0x45}, // '¸'
717 {0xb9, 0x200 | 0x52}, // '¹'
718 {0xba, 0x200 | 0x54}, // 'º'
719 {0xbb, 0x200 | 0x41}, // '»'
720 {0xbc, 0x200 | 0x53}, // '¼'
721 {0xbd, 0x200 | 0x44}, // '½'
722 {0xbe, 0x200 | 0x46}, // '¾'
723 {0xbf, 0x200 | 0x47}, // '¿'
724 {0xc0, 0x200 | 0x5a}, // 'À'
725 {0xc1, 0x200 | 0x58}, // 'Á'
726 {0xc2, 0x200 | 0x43}, // 'Â'
727 {0xc3, 0x200 | 0x56}, // 'Ã'
728 {0xc4, 0x200 | 0x42}, // 'Ä'
729 {0xc5, 0x200 | 0x36}, // 'Å'
730 {0xc6, 0x200 | 0x37}, // 'Æ'
731 {0xc7, 0x200 | 0x38}, // 'Ç'
732 {0xc8, 0x200 | 0x39}, // 'È'
733 {0xc9, 0x200 | 0x30}, // 'É'
734 {0xca, 0x200 | 0x59}, // 'Ê'
735 {0xcb, 0x200 | 0x55}, // 'Ë'
736 {0xcc, 0x200 | 0x49}, // 'Ì'
737 {0xcd, 0x200 | 0x4f}, // 'Í'
738 {0xce, 0x200 | 0x50}, // 'Î'
739 {0xcf, 0x200 | 0x48}, // 'Ï'
740 {0xd0, 0x200 | 0x4a}, // 'Ð'
741 {0xd1, 0x200 | 0x4b}, // 'Ñ'
742 {0xd2, 0x200 | 0x4c}, // 'Ò'
743 {0xd3, 0x200 | 0xbb}, // 'Ó'
744 {0xd4, 0x200 | 0x4e}, // 'Ô'
745 {0xd5, 0x200 | 0x4d}, // 'Õ'
746 {0xd6, 0x200 | 0xbc}, // 'Ö'
747 {0xd7, 0x200 | 0xbd}, // '×'
748 {0xd8, 0x200 | 0xde}, // 'Ø'
749 {0xd9, 0x200 | 0xdc}, // 'Ù'
750 {0xda, 0x200 | 0xc0}, // 'Ú'
751 {0xdb, 0x200 | 0xdb}, // 'Û'
752 {0xdc, 0x200 | 0xbe}, // 'Ü'
753 {0xdd, 0x200 | 0xe2}, // 'Ý'
754 {0xde, 0x200 | 0xba}, // 'Þ'
755 {0xdf, 0x200 | 0xdd}, // 'ß'
759 static const struct {
761 const uint8_t kana[4];
763 {"ltsu", {0xaf, 0x00}},
764 {"xtsu", {0xaf, 0x00}},
765 {"ltu", {0xaf, 0x00}},
766 {"xtu", {0xaf, 0x00}},
767 {"bya", {0xcb, 0xde, 0xac, 0x00}},
768 {"byi", {0xcb, 0xde, 0xa8, 0x00}},
769 {"byu", {0xcb, 0xde, 0xad, 0x00}},
770 {"bye", {0xcb, 0xde, 0xaa, 0x00}},
771 {"byo", {0xcb, 0xde, 0xae, 0x00}},
772 {"cha", {0xc1, 0xac, 0x00}},
773 {"chi", {0xc1, 0x00}},
774 {"chu", {0xc1, 0xad, 0x00}},
775 {"che", {0xc1, 0xaa, 0x00}},
776 {"cho", {0xc1, 0xae, 0x00}},
777 {"cya", {0xc1, 0xac, 0x00}},
778 {"cyi", {0xc1, 0xa8, 0x00}},
779 {"cyu", {0xc1, 0xad, 0x00}},
780 {"cye", {0xc1, 0xaa, 0x00}},
781 {"cyo", {0xc1, 0xae, 0x00}},
782 {"dha", {0xc3, 0xde, 0xac, 0x00}},
783 {"dhi", {0xc3, 0xde, 0xa8, 0x00}},
784 {"dhu", {0xc3, 0xde, 0xad, 0x00}},
785 {"dhe", {0xc3, 0xde, 0xaa, 0x00}},
786 {"dho", {0xc3, 0xde, 0xae, 0x00}},
787 {"dwa", {0xc4, 0xde, 0xa7, 0x00}},
788 {"dwi", {0xc4, 0xde, 0xa8, 0x00}},
789 {"dwu", {0xc4, 0xde, 0xa9, 0x00}},
790 {"dwe", {0xc4, 0xde, 0xaa, 0x00}},
791 {"dwo", {0xc4, 0xde, 0xab, 0x00}},
792 {"dya", {0xc1, 0xde, 0xac, 0x00}},
793 {"dyi", {0xc1, 0xde, 0xa8, 0x00}},
794 {"dyu", {0xc1, 0xde, 0xad, 0x00}},
795 {"dye", {0xc1, 0xde, 0xaa, 0x00}},
796 {"dyo", {0xc1, 0xde, 0xae, 0x00}},
797 {"fwa", {0xcc, 0xa7, 0x00}},
798 {"fwi", {0xcc, 0xa8, 0x00}},
799 {"fwu", {0xcc, 0xa9, 0x00}},
800 {"fwe", {0xcc, 0xaa, 0x00}},
801 {"fwo", {0xcc, 0xab, 0x00}},
802 {"fya", {0xcc, 0xac, 0x00}},
803 {"fyi", {0xcc, 0xa8, 0x00}},
804 {"fyu", {0xcc, 0xad, 0x00}},
805 {"fye", {0xcc, 0xaa, 0x00}},
806 {"fyo", {0xcc, 0xae, 0x00}},
807 {"gwa", {0xb8, 0xde, 0xa7, 0x00}},
808 {"gwi", {0xb8, 0xde, 0xa8, 0x00}},
809 {"gwu", {0xb8, 0xde, 0xa9, 0x00}},
810 {"gwe", {0xb8, 0xde, 0xaa, 0x00}},
811 {"gwo", {0xb8, 0xde, 0xab, 0x00}},
812 {"gya", {0xb7, 0xde, 0xac, 0x00}},
813 {"gyi", {0xb7, 0xde, 0xa8, 0x00}},
814 {"gyu", {0xb7, 0xde, 0xad, 0x00}},
815 {"gye", {0xb7, 0xde, 0xaa, 0x00}},
816 {"gyo", {0xb7, 0xde, 0xae, 0x00}},
817 {"hya", {0xcb, 0xac, 0x00}},
818 {"hyi", {0xcb, 0xa8, 0x00}},
819 {"hyu", {0xcb, 0xad, 0x00}},
820 {"hye", {0xcb, 0xaa, 0x00}},
821 {"hyo", {0xcb, 0xae, 0x00}},
822 {"jya", {0xbc, 0xde, 0xac, 0x00}},
823 {"jyi", {0xbc, 0xde, 0xa8, 0x00}},
824 {"jyu", {0xbc, 0xde, 0xad, 0x00}},
825 {"jye", {0xbc, 0xde, 0xaa, 0x00}},
826 {"jyo", {0xbc, 0xde, 0xae, 0x00}},
827 {"kya", {0xb7, 0xac, 0x00}},
828 {"kyi", {0xb7, 0xa8, 0x00}},
829 {"kyu", {0xb7, 0xad, 0x00}},
830 {"kye", {0xb7, 0xaa, 0x00}},
831 {"kyo", {0xb7, 0xae, 0x00}},
832 {"lya", {0xac, 0x00}},
833 {"lyi", {0xa8, 0x00}},
834 {"lyu", {0xad, 0x00}},
835 {"lye", {0xaa, 0x00}},
836 {"lyo", {0xae, 0x00}},
837 {"mya", {0xd0, 0xac, 0x00}},
838 {"myi", {0xd0, 0xa8, 0x00}},
839 {"myu", {0xd0, 0xad, 0x00}},
840 {"mye", {0xd0, 0xaa, 0x00}},
841 {"myo", {0xd0, 0xae, 0x00}},
842 {"nya", {0xc6, 0xac, 0x00}},
843 {"nyi", {0xc6, 0xa8, 0x00}},
844 {"nyu", {0xc6, 0xad, 0x00}},
845 {"nye", {0xc6, 0xaa, 0x00}},
846 {"nyo", {0xc6, 0xae, 0x00}},
847 {"pya", {0xcb, 0xdf, 0xac, 0x00}},
848 {"pyi", {0xcb, 0xdf, 0xa8, 0x00}},
849 {"pyu", {0xcb, 0xdf, 0xad, 0x00}},
850 {"pye", {0xcb, 0xdf, 0xaa, 0x00}},
851 {"pyo", {0xcb, 0xdf, 0xae, 0x00}},
852 {"qwa", {0xb8, 0xa7, 0x00}},
853 {"qwi", {0xb8, 0xa8, 0x00}},
854 {"qwu", {0xb8, 0xa9, 0x00}},
855 {"qwe", {0xb8, 0xaa, 0x00}},
856 {"qwo", {0xb8, 0xab, 0x00}},
857 {"qya", {0xb8, 0xac, 0x00}},
858 {"qyi", {0xb8, 0xa8, 0x00}},
859 {"qyu", {0xb8, 0xad, 0x00}},
860 {"qye", {0xb8, 0xaa, 0x00}},
861 {"qyo", {0xb8, 0xae, 0x00}},
862 {"rya", {0xd8, 0xac, 0x00}},
863 {"ryi", {0xd8, 0xa8, 0x00}},
864 {"ryu", {0xd8, 0xad, 0x00}},
865 {"rye", {0xd8, 0xaa, 0x00}},
866 {"ryo", {0xd8, 0xae, 0x00}},
867 {"sha", {0xbc, 0xac, 0x00}},
868 {"shi", {0xbc, 0x00}},
869 {"shu", {0xbc, 0xad, 0x00}},
870 {"she", {0xbc, 0xaa, 0x00}},
871 {"sho", {0xbc, 0xae, 0x00}},
872 {"swa", {0xbd, 0xa7, 0x00}},
873 {"swi", {0xbd, 0xa8, 0x00}},
874 {"swu", {0xbd, 0xa9, 0x00}},
875 {"swe", {0xbd, 0xaa, 0x00}},
876 {"swo", {0xbd, 0xab, 0x00}},
877 {"sya", {0xbc, 0xac, 0x00}},
878 {"syi", {0xbc, 0xa8, 0x00}},
879 {"syu", {0xbc, 0xad, 0x00}},
880 {"sye", {0xbc, 0xaa, 0x00}},
881 {"syo", {0xbc, 0xae, 0x00}},
882 {"tha", {0xc3, 0xac, 0x00}},
883 {"thi", {0xc3, 0xa8, 0x00}},
884 {"thu", {0xc3, 0xad, 0x00}},
885 {"the", {0xc3, 0xaa, 0x00}},
886 {"tho", {0xc3, 0xae, 0x00}},
887 {"tsa", {0xc2, 0xa7, 0x00}},
888 {"tsi", {0xc2, 0xa8, 0x00}},
889 {"tsu", {0xc2, 0x00}},
890 {"tse", {0xc2, 0xaa, 0x00}},
891 {"tso", {0xc2, 0xab, 0x00}},
892 {"twa", {0xc4, 0xa7, 0x00}},
893 {"twi", {0xc4, 0xa8, 0x00}},
894 {"twu", {0xc4, 0xa9, 0x00}},
895 {"twe", {0xc4, 0xaa, 0x00}},
896 {"two", {0xc4, 0xab, 0x00}},
897 {"tya", {0xc1, 0xac, 0x00}},
898 {"tyi", {0xc1, 0xa8, 0x00}},
899 {"tyu", {0xc1, 0xad, 0x00}},
900 {"tye", {0xc1, 0xaa, 0x00}},
901 {"tyo", {0xc1, 0xae, 0x00}},
902 {"vya", {0xb3, 0xde, 0xac, 0x00}},
903 {"vyi", {0xb3, 0xde, 0xa8, 0x00}},
904 {"vyu", {0xb3, 0xde, 0xad, 0x00}},
905 {"vye", {0xb3, 0xde, 0xaa, 0x00}},
906 {"vyo", {0xb3, 0xde, 0xae, 0x00}},
907 {"wha", {0xb3, 0xa7, 0x00}},
908 {"whi", {0xb3, 0xa8, 0x00}},
909 {"whu", {0xb3, 0x00}},
910 {"whe", {0xb3, 0xaa, 0x00}},
911 {"who", {0xb3, 0xab, 0x00}},
912 {"xya", {0xac, 0x00}},
913 {"xyi", {0xa8, 0x00}},
914 {"xyu", {0xad, 0x00}},
915 {"xye", {0xaa, 0x00}},
916 {"xyo", {0xae, 0x00}},
917 {"zya", {0xbc, 0xde, 0xac, 0x00}},
918 {"zyi", {0xbc, 0xde, 0xa8, 0x00}},
919 {"zyu", {0xbc, 0xde, 0xad, 0x00}},
920 {"zye", {0xbc, 0xde, 0xaa, 0x00}},
921 {"zyo", {0xbc, 0xde, 0xae, 0x00}},
922 {"ba", {0xca, 0xde, 0x00}},
923 {"bi", {0xcb, 0xde, 0x00}},
924 {"bu", {0xcc, 0xde, 0x00}},
925 {"be", {0xcd, 0xde, 0x00}},
926 {"bo", {0xce, 0xde, 0x00}},
927 {"ca", {0xb6, 0x00}},
928 {"ci", {0xbc, 0x00}},
929 {"cu", {0xb8, 0x00}},
930 {"ce", {0xbe, 0x00}},
931 {"co", {0xba, 0x00}},
932 {"da", {0xc0, 0xde, 0x00}},
933 {"di", {0xc1, 0xde, 0x00}},
934 {"du", {0xc2, 0xde, 0x00}},
935 {"de", {0xc3, 0xde, 0x00}},
936 {"do", {0xc4, 0xde, 0x00}},
937 {"fa", {0xcc, 0xa7, 0x00}},
938 {"fi", {0xcc, 0xa8, 0x00}},
939 {"fu", {0xcc, 0x00}},
940 {"fe", {0xcc, 0xaa, 0x00}},
941 {"fo", {0xcc, 0xab, 0x00}},
942 {"ga", {0xb6, 0xde, 0x00}},
943 {"gi", {0xb7, 0xde, 0x00}},
944 {"gu", {0xb8, 0xde, 0x00}},
945 {"ge", {0xb9, 0xde, 0x00}},
946 {"go", {0xba, 0xde, 0x00}},
947 {"ha", {0xca, 0x00}},
948 {"hi", {0xcb, 0x00}},
949 {"hu", {0xcc, 0x00}},
950 {"he", {0xcd, 0x00}},
951 {"ho", {0xce, 0x00}},
952 {"ja", {0xbc, 0xde, 0xac, 0x00}},
953 {"ji", {0xbc, 0xde, 0x00}},
954 {"ju", {0xbc, 0xde, 0xad, 0x00}},
955 {"je", {0xbc, 0xde, 0xaa, 0x00}},
956 {"jo", {0xbc, 0xde, 0xae, 0x00}},
957 {"ka", {0xb6, 0x00}},
958 {"ki", {0xb7, 0x00}},
959 {"ku", {0xb8, 0x00}},
960 {"ke", {0xb9, 0x00}},
961 {"ko", {0xba, 0x00}},
962 {"la", {0xa7, 0x00}},
963 {"li", {0xa8, 0x00}},
964 {"lu", {0xa9, 0x00}},
965 {"le", {0xaa, 0x00}},
966 {"lo", {0xab, 0x00}},
967 {"ma", {0xcf, 0x00}},
968 {"mi", {0xd0, 0x00}},
969 {"mu", {0xd1, 0x00}},
970 {"me", {0xd2, 0x00}},
971 {"mo", {0xd3, 0x00}},
972 {"na", {0xc5, 0x00}},
973 {"ni", {0xc6, 0x00}},
974 {"nu", {0xc7, 0x00}},
975 {"ne", {0xc8, 0x00}},
976 {"no", {0xc9, 0x00}},
977 // {"nn", {0xdd, 0x00}},
978 {"pa", {0xca, 0xdf, 0x00}},
979 {"pi", {0xcb, 0xdf, 0x00}},
980 {"pu", {0xcc, 0xdf, 0x00}},
981 {"pe", {0xcd, 0xdf, 0x00}},
982 {"po", {0xce, 0xdf, 0x00}},
983 {"qa", {0xb8, 0xa7, 0x00}},
984 {"qi", {0xb8, 0xa8, 0x00}},
985 {"qu", {0xb8, 0x00}},
986 {"qe", {0xb8, 0xaa, 0x00}},
987 {"qo", {0xb8, 0xab, 0x00}},
988 {"ra", {0xd7, 0x00}},
989 {"ri", {0xd8, 0x00}},
990 {"ru", {0xd9, 0x00}},
991 {"re", {0xda, 0x00}},
992 {"ro", {0xdb, 0x00}},
993 {"sa", {0xbb, 0x00}},
994 {"si", {0xbc, 0x00}},
995 {"su", {0xbd, 0x00}},
996 {"se", {0xbe, 0x00}},
997 {"so", {0xbf, 0x00}},
998 {"ta", {0xc0, 0x00}},
999 {"ti", {0xc1, 0x00}},
1000 {"tu", {0xc2, 0x00}},
1001 {"te", {0xc3, 0x00}},
1002 {"to", {0xc4, 0x00}},
1003 {"va", {0xb3, 0xde, 0xa7, 0x00}},
1004 {"vi", {0xb3, 0xde, 0xa8, 0x00}},
1005 {"vu", {0xb3, 0xde, 0x00}},
1006 {"ve", {0xb3, 0xde, 0xaa, 0x00}},
1007 {"vo", {0xb3, 0xde, 0xab, 0x00}},
1008 {"wa", {0xdc, 0x00}},
1009 {"wi", {0xb3, 0xa8, 0x00}},
1010 {"wu", {0xb3, 0x00}},
1011 {"we", {0xb3, 0xaa, 0x00}},
1012 {"wo", {0xa6, 0x00}},
1013 {"xa", {0xa7, 0x00}},
1014 {"xi", {0xa8, 0x00}},
1015 {"xu", {0xa9, 0x00}},
1016 {"xe", {0xaa, 0x00}},
1017 {"xo", {0xab, 0x00}},
1018 {"ya", {0xd4, 0x00}},
1019 {"yi", {0xb2, 0x00}},
1020 {"yu", {0xd5, 0x00}},
1021 {"ye", {0xb2, 0xaa, 0x00}},
1022 {"yo", {0xd6, 0x00}},
1023 {"za", {0xbb, 0xde, 0x00}},
1024 {"zi", {0xbc, 0xde, 0x00}},
1025 {"zu", {0xbd, 0xde, 0x00}},
1026 {"ze", {0xbe, 0xde, 0x00}},
1027 {"zo", {0xbf, 0xde, 0x00}},
1028 {"a", {0xb1, 0x00}},
1029 {"i", {0xb2, 0x00}},
1030 {"u", {0xb3, 0x00}},
1031 {"e", {0xb4, 0x00}},
1032 {"o", {0xb5, 0x00}},
1033 {"[", {0xa2, 0x00}},
1034 {"]", {0xa3, 0x00}},
1035 {"-", {0xb0, 0x00}},
1036 {",", {0xa4, 0x00}},
1037 {".", {0xa1, 0x00}},
1038 {"/", {0xa5, 0x00}},
1042 void EMU::initialize_auto_key()
1044 auto_key_buffer = new FIFO(65536);
1045 auto_key_buffer->clear();
1046 auto_key_phase = auto_key_shift = 0;
1047 shift_pressed = false;
1048 osd->now_auto_key = false;
1051 void EMU::release_auto_key()
1053 if(auto_key_buffer) {
1054 auto_key_buffer->release();
1055 delete auto_key_buffer;
1059 int EMU::get_auto_key_code(int code)
1061 static int auto_key_table[256];
1062 static bool initialized = false;
1063 #ifdef USE_KEYBOARD_TYPE
1064 static int keyboard_type = -1;
1066 if(keyboard_type != config.keyboard_type) {
1067 initialized = false;
1068 keyboard_type = config.keyboard_type;
1072 memset(auto_key_table, 0, sizeof(auto_key_table));
1073 for(int i = 0;; i++) {
1074 if(auto_key_table_base[i][0] == -1) {
1077 auto_key_table[auto_key_table_base[i][0]] = auto_key_table_base[i][1];
1079 #if defined(_X1TURBO) || defined(_X1TURBOZ)
1081 if(config.keyboard_type) {
1082 for(int i = 0;; i++) {
1083 if(auto_key_table_50on_base[i][0] == -1) {
1086 auto_key_table[auto_key_table_50on_base[i][0]] = auto_key_table_50on_base[i][1];
1090 for(int i = 0;; i++) {
1091 if(auto_key_table_kana_base[i][0] == -1) {
1094 auto_key_table[auto_key_table_kana_base[i][0]] = auto_key_table_kana_base[i][1];
1096 #ifdef USE_VM_AUTO_KEY_TABLE
1097 for(int i = 0;; i++) {
1098 if(vm_auto_key_table_base[i][0] == -1) {
1101 auto_key_table[vm_auto_key_table_base[i][0]] = vm_auto_key_table_base[i][1];
1106 return auto_key_table[code];
1109 void EMU::set_auto_key_code(int code)
1111 if(code == 0xf2 || (code = get_auto_key_code(code)) != 0) {
1112 if(code == 0x08 || code == 0x09 || code == 0x0d || code == 0x1b || code == 0x20 || code == 0xf2) {
1113 auto_key_buffer->write(code);
1114 #ifdef USE_AUTO_KEY_NUMPAD
1115 } else if(code >= 0x30 && code <= 0x39) {
1117 auto_key_buffer->write(code - 0x30 + 0x60);
1119 } else if(code & 0x200) {
1121 auto_key_buffer->write(code & 0x1ff);
1123 // ank other than alphabet and kana
1124 auto_key_buffer->write(0xf2); // kana unlock
1125 auto_key_buffer->write(code & 0x1ff);
1126 auto_key_buffer->write(0xf2); // kana lock
1128 if(!is_auto_key_running()) {
1134 void EMU::set_auto_key_list(char *buf, int size)
1136 #if defined(USE_KEY_LOCKED)
1137 bool prev_caps = get_caps_locked();
1138 bool prev_kana = get_kana_locked();
1140 bool prev_caps = false;
1141 bool prev_kana = false;
1143 auto_key_buffer->clear();
1145 for(int i = 0; i < size; i++) {
1146 int code = buf[i] & 0xff;
1147 if((0x81 <= code && code <= 0x9f) || 0xe0 <= code) {
1150 } else if(code == 0x0a) {
1153 if((code = get_auto_key_code(code)) != 0) {
1155 bool kana = ((code & 0x200) != 0);
1156 if(prev_kana != kana) {
1157 auto_key_buffer->write(0xf2);
1160 #if defined(USE_AUTO_KEY_CAPS_LOCK)
1161 // use caps lock key to switch uppercase/lowercase of alphabet
1162 // USE_AUTO_KEY_CAPS_LOCK shows the caps lock key code
1163 bool caps = ((code & 0x400) != 0);
1164 if(prev_caps != caps) {
1165 auto_key_buffer->write(USE_AUTO_KEY_CAPS_LOCK);
1169 #if defined(USE_AUTO_KEY_CAPS_LOCK) || defined(USE_AUTO_KEY_NO_CAPS)
1170 code &= ~(0x400 | 0x800); // don't press shift key for both alphabet and ALPHABET
1171 #elif defined(USE_KEY_LOCKED)
1172 if(get_caps_locked()) {
1173 code &= ~0x400; // don't press shift key for ALPHABET
1175 code &= ~0x800; // don't press shift key for alphabet
1177 #elif defined(USE_AUTO_KEY_CAPS)
1178 code &= ~0x400; // don't press shift key for ALPHABET
1180 code &= ~0x800; // don't press shift key for alphabet
1182 if(code & (0x100 | 0x400 | 0x800)) {
1183 auto_key_buffer->write((code & 0xff) | 0x100);
1185 auto_key_buffer->write(code & 0xff);
1189 // release kana lock
1191 auto_key_buffer->write(0xf2);
1193 #if defined(USE_AUTO_KEY_CAPS_LOCK)
1194 // release caps lock
1196 auto_key_buffer->write(USE_AUTO_KEY_CAPS_LOCK);
1201 bool is_alphabet(char code)
1203 return (code >= 'a' && code <= 'z');
1206 bool is_vowel(char code)
1208 return (code == 'a' || code == 'i' || code == 'u' || code == 'e' || code == 'o');
1211 bool is_consonant(char code)
1213 return (is_alphabet(code) && !is_vowel(code));
1216 void EMU::set_auto_key_char(char code)
1218 static char codes[5] = {0};
1221 #ifdef USE_KEY_LOCKED
1222 if(!get_kana_locked())
1224 set_auto_key_code(0xf2);
1225 memset(codes, 0, sizeof(codes));
1226 } else if(code == 0) {
1228 if(codes[3] == 'n') {
1229 set_auto_key_code(0xdd); // 'Ý'
1231 set_auto_key_code(0xf2);
1232 memset(codes, 0, sizeof(codes));
1233 } else if(code == 0x08 || code == 0x09 || code == 0x0d || code == 0x1b || code == 0x20) {
1234 if(codes[3] == 'n') {
1235 set_auto_key_code(0xdd); // 'Ý'
1237 set_auto_key_code(code);
1238 memset(codes, 0, sizeof(codes));
1239 #ifdef USE_AUTO_KEY_NUMPAD
1240 } else if(code >= 0x30 && code <= 0x39) {
1241 if(codes[3] == 'n') {
1242 set_auto_key_code(0xdd); // 'Ý'
1244 set_auto_key_code(code);
1245 memset(codes, 0, sizeof(codes));
1248 codes[0] = codes[1];
1249 codes[1] = codes[2];
1250 codes[2] = codes[3];
1251 codes[3] = (code >= 'A' && code <= 'Z') ? ('a' + (code - 'A')) : code;
1254 if(codes[2] == 'n' && !is_vowel(codes[3])) {
1255 set_auto_key_code(0xdd); // 'Ý'
1256 if(codes[3] == 'n') {
1257 memset(codes, 0, sizeof(codes));
1260 } else if(codes[2] == codes[3] && is_consonant(codes[3])) {
1261 set_auto_key_code(0xaf); // '¯'
1264 for(int i = 0;; i++) {
1265 int len = strlen(romaji_table[i].romaji), comp = -1;
1268 if(!is_alphabet(codes[3])) {
1269 set_auto_key_code(codes[3]);
1270 memset(codes, 0, sizeof(codes));
1273 } else if(len == 1) {
1274 comp = strcmp(romaji_table[i].romaji, &codes[3]);
1275 } else if(len == 2) {
1276 comp = strcmp(romaji_table[i].romaji, &codes[2]);
1277 } else if(len == 3) {
1278 comp = strcmp(romaji_table[i].romaji, &codes[1]);
1279 } else if(len == 4) {
1280 comp = strcmp(romaji_table[i].romaji, &codes[0]);
1283 for(int j = 0; j < 4; j++) {
1284 if(!romaji_table[i].kana[j]) {
1287 set_auto_key_code(romaji_table[i].kana[j]);
1289 memset(codes, 0, sizeof(codes));
1296 void EMU::start_auto_key()
1300 osd->now_auto_key = true;
1303 void EMU::stop_auto_key()
1305 if(auto_key_shift) {
1306 osd->key_up_native(VK_LSHIFT);
1308 auto_key_phase = auto_key_shift = 0;
1309 osd->now_auto_key = false;
1312 #ifndef USE_AUTO_KEY_SHIFT
1313 #define USE_AUTO_KEY_SHIFT 0
1316 #define VK_LSHIFT 0xA0
1319 void EMU::update_auto_key()
1321 switch(auto_key_phase) {
1323 if(auto_key_buffer && !auto_key_buffer->empty()) {
1324 // update shift key status
1325 int shift = auto_key_buffer->read_not_remove(0) & 0x100;
1326 if(shift && !auto_key_shift) {
1327 osd->key_down_native(VK_LSHIFT, false);
1328 } else if(!shift && auto_key_shift) {
1329 osd->key_up_native(VK_LSHIFT);
1331 auto_key_shift = shift;
1335 case 3 + USE_AUTO_KEY_SHIFT:
1336 if(auto_key_buffer && !auto_key_buffer->empty()) {
1337 osd->key_down_native(auto_key_buffer->read_not_remove(0) & 0xff, false);
1341 case USE_AUTO_KEY + USE_AUTO_KEY_SHIFT:
1342 if(auto_key_buffer && !auto_key_buffer->empty()) {
1343 osd->key_up_native(auto_key_buffer->read_not_remove(0) & 0xff);
1347 case USE_AUTO_KEY_RELEASE + USE_AUTO_KEY_SHIFT:
1348 if(auto_key_buffer && !auto_key_buffer->empty()) {
1349 // wait enough while vm analyzes one line
1350 if(auto_key_buffer->read() == 0xd) {
1356 if(auto_key_buffer && !auto_key_buffer->empty()) {
1363 if(auto_key_phase) {
1371 void EMU::update_joystick()
1373 uint32_t *joy_buffer = osd->get_joy_buffer();
1374 uint8_t *key_buffer = osd->get_key_buffer();
1376 memset(joy_status, 0, sizeof(joy_status));
1378 for(int i = 0; i < 4; i++) {
1379 for(int j = 0; j < 16; j++) {
1380 if(config.joy_buttons[i][j] < 0) {
1381 int code = -config.joy_buttons[i][j];
1382 if(code < 256 && key_buffer[code]) {
1383 joy_status[i] |= (1 << j);
1384 //printf("%d %d %02x %02x\n", i, j, config.joy_buttons[i][j], joy_status[i]);
1387 int stick = config.joy_buttons[i][j] >> 5;
1388 int button = config.joy_buttons[i][j] & 0x1f;
1389 if(stick < 4 && (joy_buffer[stick & 3] & (1 << button))) {
1390 joy_status[i] |= (1 << j);
1391 //printf("%d %d %02x %02x\n", i, j, config.joy_buttons[i][j], joy_status[i]);
1399 const uint8_t* EMU::get_key_buffer()
1401 return (const uint8_t*)osd->get_key_buffer();
1405 const uint32_t* EMU::get_joy_buffer()
1407 return (const uint32_t*)joy_status;
1412 const int32_t* EMU::get_mouse_buffer()
1414 return (const int32_t*)osd->get_mouse_buffer();
1418 // ----------------------------------------------------------------------------
1420 // ----------------------------------------------------------------------------
1422 double EMU::get_window_mode_power(int mode)
1424 return osd->get_window_mode_power(mode);
1427 int EMU::get_window_mode_width(int mode)
1429 return osd->get_window_mode_width(mode);
1432 int EMU::get_window_mode_height(int mode)
1434 return osd->get_window_mode_height(mode);
1437 void EMU::set_host_window_size(int window_width, int window_height, bool window_mode)
1439 osd->set_host_window_size(window_width, window_height, window_mode);
1442 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)
1444 osd->set_vm_screen_size(screen_width, screen_height, window_width, window_height, window_width_aspect, window_height_aspect);
1447 void EMU::set_vm_screen_lines(int lines)
1449 osd->set_vm_screen_lines(lines);
1453 int EMU::get_vm_window_width()
1455 return osd->get_vm_window_width();
1458 int EMU::get_vm_window_height()
1460 return osd->get_vm_window_height();
1463 int EMU::get_vm_window_width_aspect()
1465 return osd->get_vm_window_width_aspect();
1468 int EMU::get_vm_window_height_aspect()
1470 return osd->get_vm_window_height_aspect();
1473 #if defined(USE_MINIMUM_RENDERING)
1474 bool EMU::is_screen_changed()
1476 return vm->is_screen_changed();
1480 int EMU::draw_screen()
1482 #ifdef ONE_BOARD_MICRO_COMPUTER
1483 if(now_waiting_in_debugger) {
1484 osd->reload_bitmap();
1487 return osd->draw_screen();
1490 scrntype_t* EMU::get_screen_buffer(int y)
1492 return osd->get_vm_screen_buffer(y);
1495 #ifdef USE_SCREEN_FILTER
1496 void EMU::screen_skip_line(bool skip_line)
1498 osd->screen_skip_line = skip_line;
1502 #ifdef ONE_BOARD_MICRO_COMPUTER
1503 void EMU::get_invalidated_rect(int *left, int *top, int *right, int *bottom)
1505 #ifdef MAX_DRAW_RANGES
1506 for(int i = 0; i < MAX_DRAW_RANGES; i++) {
1508 for(int i = 0; i < vm->max_draw_ranges(); i++) { // for TK-80BS
1510 int x1 = vm_ranges[i].x;
1511 int y1 = vm_ranges[i].y;
1512 int x2 = x1 + vm_ranges[i].width;
1513 int y2 = y1 + vm_ranges[i].height;
1515 *left = (i == 0) ? x1 : min(x1, *left );
1516 *top = (i == 0) ? y1 : min(y1, *top );
1517 *right = (i == 0) ? x2 : max(x2, *right );
1518 *bottom = (i == 0) ? y2 : max(y2, *bottom);
1522 void EMU::reload_bitmap()
1524 osd->reload_bitmap();
1529 void EMU::invalidate_screen()
1531 osd->invalidate_screen();
1534 void EMU::update_screen(HDC hdc)
1536 osd->update_screen(hdc);
1540 void EMU::capture_screen()
1542 osd->capture_screen();
1545 bool EMU::start_record_video(int fps)
1547 return osd->start_record_video(fps);
1550 void EMU::stop_record_video()
1552 osd->stop_record_video();
1555 bool EMU::is_video_recording()
1557 return osd->now_record_video;
1560 // ----------------------------------------------------------------------------
1562 // ----------------------------------------------------------------------------
1564 void EMU::mute_sound()
1569 void EMU::start_record_sound()
1571 osd->start_record_sound();
1574 void EMU::stop_record_sound()
1576 osd->stop_record_sound();
1579 bool EMU::is_sound_recording()
1581 return osd->now_record_sound;
1584 // ----------------------------------------------------------------------------
1586 // ----------------------------------------------------------------------------
1588 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
1589 void EMU::get_video_buffer()
1591 osd->get_video_buffer();
1594 void EMU::mute_video_dev(bool l, bool r)
1596 osd->mute_video_dev(l, r);
1600 #ifdef USE_MOVIE_PLAYER
1601 bool EMU::open_movie_file(const _TCHAR* file_path)
1603 return osd->open_movie_file(file_path);
1606 void EMU::close_movie_file()
1608 osd->close_movie_file();
1611 void EMU::play_movie()
1616 void EMU::stop_movie()
1621 void EMU::pause_movie()
1626 double EMU::get_movie_frame_rate()
1628 return osd->get_movie_frame_rate();
1631 int EMU::get_movie_sound_rate()
1633 return osd->get_movie_sound_rate();
1636 void EMU::set_cur_movie_frame(int frame, bool relative)
1638 osd->set_cur_movie_frame(frame, relative);
1641 uint32_t EMU::get_cur_movie_frame()
1643 return osd->get_cur_movie_frame();
1647 #ifdef USE_VIDEO_CAPTURE
1648 int EMU::get_cur_capture_dev_index()
1650 return osd->get_cur_capture_dev_index();
1653 int EMU::get_num_capture_devs()
1655 return osd->get_num_capture_devs();
1658 _TCHAR* EMU::get_capture_dev_name(int index)
1660 return osd->get_capture_dev_name(index);
1663 void EMU::open_capture_dev(int index, bool pin)
1665 osd->open_capture_dev(index, pin);
1668 void EMU::close_capture_dev()
1670 osd->close_capture_dev();
1673 void EMU::show_capture_dev_filter()
1675 osd->show_capture_dev_filter();
1678 void EMU::show_capture_dev_pin()
1680 osd->show_capture_dev_pin();
1683 void EMU::show_capture_dev_source()
1685 osd->show_capture_dev_source();
1688 void EMU::set_capture_dev_channel(int ch)
1690 osd->set_capture_dev_channel(ch);
1694 // ----------------------------------------------------------------------------
1696 // ----------------------------------------------------------------------------
1699 void EMU::create_bitmap(bitmap_t *bitmap, int width, int height)
1701 osd->create_bitmap(bitmap, width, height);
1704 void EMU::release_bitmap(bitmap_t *bitmap)
1706 osd->release_bitmap(bitmap);
1709 void EMU::create_font(font_t *font, const _TCHAR *family, int width, int height, int rotate, bool bold, bool italic)
1711 osd->create_font(font, family, width, height, rotate, bold, italic);
1714 void EMU::release_font(font_t *font)
1716 osd->release_font(font);
1719 void EMU::create_pen(pen_t *pen, int width, uint8_t r, uint8_t g, uint8_t b)
1721 osd->create_pen(pen, width, r, g, b);
1724 void EMU::release_pen(pen_t *pen)
1726 osd->release_pen(pen);
1729 void EMU::clear_bitmap(bitmap_t *bitmap, uint8_t r, uint8_t g, uint8_t b)
1731 osd->clear_bitmap(bitmap, r, g, b);
1734 int EMU::get_text_width(bitmap_t *bitmap, font_t *font, const char *text)
1736 return osd->get_text_width(bitmap, font, text);
1739 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)
1741 osd->draw_text_to_bitmap(bitmap, font, x, y, text, r, g, b);
1744 void EMU::draw_line_to_bitmap(bitmap_t *bitmap, pen_t *pen, int sx, int sy, int ex, int ey)
1746 osd->draw_line_to_bitmap(bitmap, pen, sx, sy, ex, ey);
1749 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)
1751 osd->draw_rectangle_to_bitmap(bitmap, x, y, width, height, r, g, b);
1754 void EMU::draw_point_to_bitmap(bitmap_t *bitmap, int x, int y, uint8_t r, uint8_t g, uint8_t b)
1756 osd->draw_point_to_bitmap(bitmap, x, y, r, g, b);
1759 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)
1761 osd->stretch_bitmap(dest, dest_x, dest_y, dest_width, dest_height, source, source_x, source_y, source_width, source_height);
1764 void EMU::write_bitmap_to_file(bitmap_t *bitmap, const _TCHAR *file_path)
1766 osd->write_bitmap_to_file(bitmap, file_path);
1770 // ----------------------------------------------------------------------------
1772 // ----------------------------------------------------------------------------
1775 int EMU::get_socket(int ch)
1777 return osd->get_socket(ch);
1780 void EMU::notify_socket_connected(int ch)
1782 osd->notify_socket_connected(ch);
1785 void EMU::notify_socket_disconnected(int ch)
1787 osd->notify_socket_disconnected(ch);
1790 bool EMU::initialize_socket_tcp(int ch)
1792 return osd->initialize_socket_tcp(ch);
1795 bool EMU::initialize_socket_udp(int ch)
1797 return osd->initialize_socket_udp(ch);
1800 bool EMU::connect_socket(int ch, uint32_t ipaddr, int port)
1802 return osd->connect_socket(ch, ipaddr, port);
1805 void EMU::disconnect_socket(int ch)
1807 osd->disconnect_socket(ch);
1810 bool EMU::listen_socket(int ch)
1812 return osd->listen_socket(ch);
1815 void EMU::send_socket_data_tcp(int ch)
1817 osd->send_socket_data_tcp(ch);
1820 void EMU::send_socket_data_udp(int ch, uint32_t ipaddr, int port)
1822 osd->send_socket_data_udp(ch, ipaddr, port);
1825 void EMU::send_socket_data(int ch)
1827 osd->send_socket_data(ch);
1830 void EMU::recv_socket_data(int ch)
1832 osd->recv_socket_data(ch);
1836 // ---------------------------------------------------------------------------
1837 // debugger (some functions needed by libCSPcommon_vm 20190221 K.O)
1838 // ---------------------------------------------------------------------------
1840 void EMU::start_waiting_in_debugger()
1843 now_waiting_in_debugger = true;
1847 osd->start_waiting_in_debugger();
1851 void EMU::finish_waiting_in_debugger()
1854 osd->finish_waiting_in_debugger();
1855 now_waiting_in_debugger = false;
1859 void EMU::process_waiting_in_debugger()
1862 osd->process_waiting_in_debugger();
1868 // ----------------------------------------------------------------------------
1870 // ----------------------------------------------------------------------------
1873 void EMU::initialize_debug_log()
1875 _TCHAR path[_MAX_PATH];
1876 debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
1879 void EMU::release_debug_log()
1889 static _TCHAR prev_buffer[1024] = {0};
1892 void EMU::out_debug_log(const _TCHAR* format, ...)
1894 common_initialize();
1898 _TCHAR buffer[1024];
1900 va_start(ap, format);
1901 my_vstprintf_s(buffer, 1024, format, ap);
1904 if(_tcscmp(prev_buffer, buffer) == 0) {
1907 my_tcscpy_s(prev_buffer, 1024, buffer);
1909 #if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
1910 csp_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_EMU, "%s", buffer);
1913 _ftprintf(debug_log, _T("%s"), buffer);
1914 static int size = 0;
1915 if((size += _tcslen(buffer)) > 0x8000000) { // 128MB
1917 debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
1925 void EMU::force_out_debug_log(const _TCHAR* format, ...)
1929 _TCHAR buffer[1024];
1931 va_start(ap, format);
1932 my_vstprintf_s(buffer, 1024, format, ap);
1934 my_tcscpy_s(prev_buffer, 1024, buffer);
1936 #if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
1937 csp_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_EMU, "%s", buffer);
1940 _ftprintf(debug_log, _T("%s"), buffer);
1941 static int size = 0;
1942 if((size += _tcslen(buffer)) > 0x8000000) { // 128MB
1944 debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
1952 void EMU::out_message(const _TCHAR* format, ...)
1954 //#if defined(_USE_QT)
1955 // _TCHAR mes_buf[1024];
1958 va_start(ap, format);
1959 my_vstprintf_s(message, 1024, format, ap); // Security for MSVC:C6386.
1960 //#if defined(_USE_QT)
1961 // memset(mes_buf, 0x00, sizeof(mes_buf));
1962 // my_vstprintf_s(mes_buf, 1024, format, ap); // Security for MSVC:C6386.
1963 // csp_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_EMU, "%s", mes_buf);
1966 message_count = 4; // 4sec
1969 // ----------------------------------------------------------------------------
1971 // ----------------------------------------------------------------------------
1974 void EMU::sleep(uint32_t ms)
1980 // ----------------------------------------------------------------------------
1982 // ----------------------------------------------------------------------------
1984 static uint8_t hex2uint8(char *value)
1987 memset(tmp, 0, sizeof(tmp));
1988 memcpy(tmp, value, 2);
1989 return (uint8_t)strtoul(tmp, NULL, 16);
1992 static uint16_t hex2uint16(char *value)
1995 memset(tmp, 0, sizeof(tmp));
1996 memcpy(tmp, value, 4);
1997 return (uint16_t)strtoul(tmp, NULL, 16);
2000 static bool hex2bin(const _TCHAR* file_path, const _TCHAR* dest_path)
2002 bool result = false;
2003 FILEIO *fio_s = new FILEIO();
2004 if(fio_s->Fopen(file_path, FILEIO_READ_BINARY)) {
2007 uint8_t buffer[0x10000];
2008 memset(buffer, 0xff, sizeof(buffer));
2009 while(fio_s->Fgets(line, sizeof(line)) != NULL) {
2010 if(line[0] != ':') continue;
2011 int bytes = hex2uint8(line + 1);
2012 int offset = hex2uint16(line + 3);
2013 uint8_t record_type = hex2uint8(line + 7);
2014 if(record_type == 0x01) break;
2015 if(record_type != 0x00) continue;
2016 for(int i = 0; i < bytes; i++) {
2017 if((offset + i) < (int)sizeof(buffer)) {
2018 if(length < (offset + i)) {
2019 length = offset + i;
2021 buffer[offset + i] = hex2uint8(line + 9 + 2 * i);
2026 FILEIO *fio_d = new FILEIO();
2027 if(fio_d->Fopen(dest_path, FILEIO_WRITE_BINARY)) {
2028 fio_d->Fwrite(buffer, length, 1);
2040 void EMU::initialize_media()
2043 memset(&cart_status, 0, sizeof(cart_status));
2045 #ifdef USE_FLOPPY_DISK
2046 memset(floppy_disk_status, 0, sizeof(floppy_disk_status));
2048 #ifdef USE_QUICK_DISK
2049 memset(&quick_disk_status, 0, sizeof(quick_disk_status));
2051 #ifdef USE_HARD_DISK
2052 memset(&hard_disk_status, 0, sizeof(hard_disk_status));
2055 memset(&tape_status, 0, sizeof(tape_status));
2057 #ifdef USE_COMPACT_DISC
2058 memset(&compact_disc_status, 0, sizeof(compact_disc_status));
2060 #ifdef USE_LASER_DISC
2061 memset(&laser_disc_status, 0, sizeof(laser_disc_status));
2064 memset(&bubble_casette_status, 0, sizeof(bubble_casette_status));
2069 void EMU::update_media()
2071 #ifdef USE_FLOPPY_DISK
2072 for(int drv = 0; drv < USE_FLOPPY_DISK; drv++) {
2073 if(floppy_disk_status[drv].wait_count != 0 && --floppy_disk_status[drv].wait_count == 0) {
2074 vm->open_floppy_disk(drv, floppy_disk_status[drv].path, floppy_disk_status[drv].bank);
2075 #if USE_FLOPPY_DISK > 1
2076 out_message(_T("FD%d: %s"), drv + BASE_FLOPPY_DISK_NUM, floppy_disk_status[drv].path);
2078 out_message(_T("FD: %s"), floppy_disk_status[drv].path);
2083 #ifdef USE_QUICK_DISK
2084 for(int drv = 0; drv < USE_QUICK_DISK; drv++) {
2085 if(quick_disk_status[drv].wait_count != 0 && --quick_disk_status[drv].wait_count == 0) {
2086 vm->open_quick_disk(drv, quick_disk_status[drv].path);
2087 #if USE_QUICK_DISK > 1
2088 out_message(_T("QD%d: %s"), drv + BASE_QUICK_DISK_NUM, quick_disk_status[drv].path);
2090 out_message(_T("QD: %s"), quick_disk_status[drv].path);
2095 #ifdef USE_HARD_DISK
2096 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
2097 if(hard_disk_status[drv].wait_count != 0 && --hard_disk_status[drv].wait_count == 0) {
2098 vm->open_hard_disk(drv, hard_disk_status[drv].path);
2099 #if USE_HARD_DISK > 1
2100 out_message(_T("HD%d: %s"), drv + BASE_HARD_DISK_NUM, hard_disk_status[drv].path);
2102 out_message(_T("HD: %s"), hard_disk_status[drv].path);
2108 for(int drv = 0; drv < USE_TAPE; drv++) {
2109 if(tape_status[drv].wait_count != 0 && --tape_status[drv].wait_count == 0) {
2110 if(tape_status[drv].play) {
2111 vm->play_tape(drv, tape_status[drv].path);
2113 vm->rec_tape(drv, tape_status[drv].path);
2116 out_message(_T("CMT%d: %s"), drv + BASE_TAPE_NUM, tape_status[drv].path);
2118 out_message(_T("CMT: %s"), tape_status[drv].path);
2123 #ifdef USE_COMPACT_DISC
2124 for(int drv = 0; drv < USE_COMPACT_DISC; drv++) {
2125 if(compact_disc_status[drv].wait_count != 0 && --compact_disc_status[drv].wait_count == 0) {
2126 vm->open_compact_disc(drv, compact_disc_status[drv].path);
2127 #if USE_COMPACT_DISC > 1
2128 out_message(_T("CD%d: %s"), drv + BASE_COMPACT_DISC_NUM, compact_disc_status[drv].path);
2130 out_message(_T("CD: %s"), compact_disc_status[drv].path);
2135 #ifdef USE_LASER_DISC
2136 for(int drv = 0; drv < USE_LASER_DISC; drv++) {
2137 if(laser_disc_status[drv].wait_count != 0 && --laser_disc_status[drv].wait_count == 0) {
2138 vm->open_laser_disc(drv, laser_disc_status[drv].path);
2139 #if USE_LASER_DISC > 1
2140 out_message(_T("LD%d: %s"), drv + BASE_LASER_DISC_NUM, laser_disc_status[drv].path);
2142 out_message(_T("LD: %s"), laser_disc_status[drv].path);
2148 for(int drv = 0; drv < USE_BUBBLE; drv++) {
2149 if(bubble_casette_status[drv].wait_count != 0 && --bubble_casette_status[drv].wait_count == 0) {
2150 vm->open_bubble_casette(drv, bubble_casette_status[drv].path, bubble_casette_status[drv].bank);
2152 out_message(_T("Bubble%d: %s"), drv + BASE_BUBBLE_NUM, bubble_casette_status[drv].path);
2154 out_message(_T("Bubble: %s"), bubble_casette_status[drv].path);
2161 void EMU::restore_media()
2164 for(int drv = 0; drv < USE_CART; drv++) {
2165 if(cart_status[drv].path[0] != _T('\0')) {
2166 if(check_file_extension(cart_status[drv].path, _T(".hex")) && hex2bin(cart_status[drv].path, create_local_path(_T("hex2bin.$$$")))) {
2167 vm->open_cart(drv, create_local_path(_T("hex2bin.$$$")));
2168 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
2170 vm->open_cart(drv, cart_status[drv].path);
2175 #ifdef USE_FLOPPY_DISK
2176 for(int drv = 0; drv < USE_FLOPPY_DISK; drv++) {
2177 if(floppy_disk_status[drv].path[0] != _T('\0')) {
2178 vm->open_floppy_disk(drv, floppy_disk_status[drv].path, floppy_disk_status[drv].bank);
2182 #ifdef USE_QUICK_DISK
2183 for(int drv = 0; drv < USE_QUICK_DISK; drv++) {
2184 if(quick_disk_status[drv].path[0] != _T('\0')) {
2185 vm->open_quick_disk(drv, quick_disk_status[drv].path);
2189 #ifdef USE_HARD_DISK
2190 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
2191 if(hard_disk_status[drv].path[0] != _T('\0')) {
2192 vm->open_hard_disk(drv, hard_disk_status[drv].path);
2197 for(int drv = 0; drv < USE_TAPE; drv++) {
2198 if(tape_status[drv].path[0] != _T('\0')) {
2199 if(tape_status[drv].play) {
2200 vm->play_tape(drv, tape_status[drv].path);
2202 tape_status[drv].path[0] = _T('\0');
2207 #ifdef USE_COMPACT_DISC
2208 for(int drv = 0; drv < USE_COMPACT_DISC; drv++) {
2209 if(compact_disc_status[drv].path[0] != _T('\0')) {
2210 vm->open_compact_disc(drv, compact_disc_status[drv].path);
2214 #ifdef USE_LASER_DISC
2215 for(int drv = 0; drv < USE_LASER_DISC; drv++) {
2216 if(laser_disc_status[drv].path[0] != _T('\0')) {
2217 vm->open_laser_disc(drv, laser_disc_status[drv].path);
2222 for(int drv = 0; drv < USE_BUBBLE; drv++) {
2223 if(bubble_casette_status[drv].path[0] != _T('\0')) {
2224 vm->open_bubble_casette(drv, bubble_casette_status[drv].path, bubble_casette_status[drv].bank);
2231 void EMU::open_cart(int drv, const _TCHAR* file_path)
2233 if(drv < USE_CART) {
2234 if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, create_local_path(_T("hex2bin.$$$")))) {
2235 vm->open_cart(drv, create_local_path(_T("hex2bin.$$$")));
2236 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
2238 vm->open_cart(drv, file_path);
2240 my_tcscpy_s(cart_status[drv].path, _MAX_PATH, file_path);
2241 out_message(_T("Cart%d: %s"), drv + 1, file_path);
2242 #if !defined(_USE_QT)
2243 // restart recording
2244 bool s = osd->now_record_sound;
2245 bool v = osd->now_record_video;
2246 stop_record_sound();
2247 stop_record_video();
2249 if(s) osd->start_record_sound();
2250 if(v) osd->start_record_video(-1);
2255 void EMU::close_cart(int drv)
2257 if(drv < USE_CART) {
2258 vm->close_cart(drv);
2259 clear_media_status(&cart_status[drv]);
2261 out_message(_T("Cart%d: Ejected"), drv + BASE_CART_NUM);
2263 out_message(_T("Cart: Ejected"));
2265 #if !defined(_USE_QT)
2267 stop_record_video();
2268 stop_record_sound();
2273 bool EMU::is_cart_inserted(int drv)
2275 if(drv < USE_CART) {
2276 return vm->is_cart_inserted(drv);
2283 #ifdef USE_FLOPPY_DISK
2284 void EMU::create_bank_floppy_disk(const _TCHAR* file_path, uint8_t type)
2287 type: 0x00 = 2D, 0x10 = 2DD, 0x20 = 2HD
2295 uint32_t trkptr[164];
2298 memset(&d88_hdr, 0, sizeof(d88_hdr));
2299 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "BLANK");
2300 d88_hdr.type = type;
2301 d88_hdr.size = sizeof(d88_hdr);
2303 FILEIO *fio = new FILEIO();
2304 if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
2305 fio->Fwrite(&d88_hdr, sizeof(d88_hdr), 1);
2311 void EMU::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
2313 if(drv < USE_FLOPPY_DISK) {
2314 if(vm->is_floppy_disk_inserted(drv)) {
2315 vm->close_floppy_disk(drv);
2317 floppy_disk_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2318 #if USE_FLOPPY_DISK > 1
2319 out_message(_T("FD%d: Ejected"), drv + BASE_FLOPPY_DISK_NUM);
2321 out_message(_T("FD: Ejected"));
2323 } else if(floppy_disk_status[drv].wait_count == 0) {
2324 vm->open_floppy_disk(drv, file_path, bank);
2325 #if USE_FLOPPY_DISK > 1
2326 out_message(_T("FD%d: %s"), drv + BASE_FLOPPY_DISK_NUM, file_path);
2328 out_message(_T("FD: %s"), file_path);
2331 my_tcscpy_s(floppy_disk_status[drv].path, _MAX_PATH, file_path);
2332 floppy_disk_status[drv].bank = bank;
2336 void EMU::close_floppy_disk(int drv)
2338 if(drv < USE_FLOPPY_DISK) {
2339 vm->close_floppy_disk(drv);
2340 clear_media_status(&floppy_disk_status[drv]);
2341 #if USE_FLOPPY_DISK > 1
2342 out_message(_T("FD%d: Ejected"), drv + BASE_FLOPPY_DISK_NUM);
2344 out_message(_T("FD: Ejected"));
2349 bool EMU::is_floppy_disk_inserted(int drv)
2351 if(drv < USE_FLOPPY_DISK) {
2352 return vm->is_floppy_disk_inserted(drv);
2358 void EMU::is_floppy_disk_protected(int drv, bool value)
2360 if(drv < USE_FLOPPY_DISK) {
2361 vm->is_floppy_disk_protected(drv, value);
2365 bool EMU::is_floppy_disk_protected(int drv)
2367 if(drv < USE_FLOPPY_DISK) {
2368 return vm->is_floppy_disk_protected(drv);
2374 uint32_t EMU::is_floppy_disk_accessed()
2376 return vm->is_floppy_disk_accessed();
2380 #ifdef USE_QUICK_DISK
2381 void EMU::open_quick_disk(int drv, const _TCHAR* file_path)
2383 if(drv < USE_QUICK_DISK) {
2384 if(vm->is_quick_disk_inserted(drv)) {
2385 vm->close_quick_disk(drv);
2387 quick_disk_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2388 #if USE_QUICK_DISK > 1
2389 out_message(_T("QD%d: Ejected"), drv + BASE_QUICK_DISK_NUM);
2391 out_message(_T("QD: Ejected"));
2393 } else if(quick_disk_status[drv].wait_count == 0) {
2394 vm->open_quick_disk(drv, file_path);
2395 #if USE_QUICK_DISK > 1
2396 out_message(_T("QD%d: %s"), drv + BASE_QUICK_DISK_NUM, file_path);
2398 out_message(_T("QD: %s"), file_path);
2401 my_tcscpy_s(quick_disk_status[drv].path, _MAX_PATH, file_path);
2405 void EMU::close_quick_disk(int drv)
2407 if(drv < USE_QUICK_DISK) {
2408 vm->close_quick_disk(drv);
2409 clear_media_status(&quick_disk_status[drv]);
2410 #if USE_QUICK_DISK > 1
2411 out_message(_T("QD%d: Ejected"), drv + BASE_QUICK_DISK_NUM);
2413 out_message(_T("QD: Ejected"));
2418 bool EMU::is_quick_disk_inserted(int drv)
2420 if(drv < USE_QUICK_DISK) {
2421 return vm->is_quick_disk_inserted(drv);
2427 uint32_t EMU::is_quick_disk_accessed()
2429 return vm->is_quick_disk_accessed();
2433 #ifdef USE_HARD_DISK
2434 void EMU::open_hard_disk(int drv, const _TCHAR* file_path)
2436 if(drv < USE_HARD_DISK) {
2437 if(vm->is_hard_disk_inserted(drv)) {
2438 vm->close_hard_disk(drv);
2440 hard_disk_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2441 #if USE_HARD_DISK > 1
2442 out_message(_T("HD%d: Unmounted"), drv + BASE_HARD_DISK_NUM);
2444 out_message(_T("HD: Unmounted"));
2446 } else if(hard_disk_status[drv].wait_count == 0) {
2447 vm->open_hard_disk(drv, file_path);
2448 #if USE_HARD_DISK > 1
2449 out_message(_T("HD%d: %s"), drv + BASE_HARD_DISK_NUM, file_path);
2451 out_message(_T("HD: %s"), file_path);
2454 my_tcscpy_s(hard_disk_status[drv].path, _MAX_PATH, file_path);
2455 my_tcscpy_s(config.last_hard_disk_path[drv], _MAX_PATH, file_path);
2459 void EMU::close_hard_disk(int drv)
2461 if(drv < USE_HARD_DISK) {
2462 vm->close_hard_disk(drv);
2463 clear_media_status(&hard_disk_status[drv]);
2464 #if USE_HARD_DISK > 1
2465 out_message(_T("HD%d: Unmounted"), drv + BASE_HARD_DISK_NUM);
2467 out_message(_T("HD: Unmounted"));
2469 config.last_hard_disk_path[drv][0] = '\0';
2473 bool EMU::is_hard_disk_inserted(int drv)
2475 if(drv < USE_HARD_DISK) {
2476 return vm->is_hard_disk_inserted(drv);
2482 uint32_t EMU::is_hard_disk_accessed()
2484 return vm->is_hard_disk_accessed();
2489 void EMU::play_tape(int drv, const _TCHAR* file_path)
2491 if(drv < USE_TAPE) {
2492 if(vm->is_tape_inserted(drv)) {
2493 vm->close_tape(drv);
2495 tape_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2497 out_message(_T("CMT%d: Ejected"), drv + BASE_TAPE_NUM);
2499 out_message(_T("CMT: Ejected"));
2501 } else if(tape_status[drv].wait_count == 0) {
2502 vm->play_tape(drv, file_path);
2504 out_message(_T("CMT%d: %s"), drv + BASE_TAPE_NUM, file_path);
2506 out_message(_T("CMT: %s"), file_path);
2509 my_tcscpy_s(tape_status[drv].path, _MAX_PATH, file_path);
2510 tape_status[drv].play = true;
2514 void EMU::rec_tape(int drv, const _TCHAR* file_path)
2516 if(drv < USE_TAPE) {
2517 if(vm->is_tape_inserted(drv)) {
2518 vm->close_tape(drv);
2520 tape_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2522 out_message(_T("CMT%d: Ejected"), drv + BASE_TAPE_NUM);
2524 out_message(_T("CMT: Ejected"));
2526 } else if(tape_status[drv].wait_count == 0) {
2527 vm->rec_tape(drv, file_path);
2529 out_message(_T("CMT%d: %s"), drv + BASE_TAPE_NUM, file_path);
2531 out_message(_T("CMT: %s"), file_path);
2534 my_tcscpy_s(tape_status[drv].path, _MAX_PATH, file_path);
2535 tape_status[drv].play = false;
2539 void EMU::close_tape(int drv)
2541 if(drv < USE_TAPE) {
2542 vm->close_tape(drv);
2543 clear_media_status(&tape_status[drv]);
2545 out_message(_T("CMT%d: Ejected"), drv + BASE_TAPE_NUM);
2547 out_message(_T("CMT: Ejected"));
2552 bool EMU::is_tape_inserted(int drv)
2554 if(drv < USE_TAPE) {
2555 return vm->is_tape_inserted(drv);
2561 bool EMU::is_tape_playing(int drv)
2563 if(drv < USE_TAPE) {
2564 return vm->is_tape_playing(drv);
2570 bool EMU::is_tape_recording(int drv)
2572 if(drv < USE_TAPE) {
2573 return vm->is_tape_recording(drv);
2579 int EMU::get_tape_position(int drv)
2581 if(drv < USE_TAPE) {
2582 return vm->get_tape_position(drv);
2588 const _TCHAR* EMU::get_tape_message(int drv)
2590 if(drv < USE_TAPE) {
2591 return vm->get_tape_message(drv);
2597 void EMU::push_play(int drv)
2599 if(drv < USE_TAPE) {
2604 void EMU::push_stop(int drv)
2606 if(drv < USE_TAPE) {
2611 void EMU::push_fast_forward(int drv)
2613 if(drv < USE_TAPE) {
2614 vm->push_fast_forward(drv);
2618 void EMU::push_fast_rewind(int drv)
2620 if(drv < USE_TAPE) {
2621 vm->push_fast_rewind(drv);
2625 void EMU::push_apss_forward(int drv)
2627 if(drv < USE_TAPE) {
2628 vm->push_apss_forward(drv);
2632 void EMU::push_apss_rewind(int drv)
2634 if(drv < USE_TAPE) {
2635 vm->push_apss_rewind(drv);
2640 #ifdef USE_COMPACT_DISC
2641 void EMU::open_compact_disc(int drv, const _TCHAR* file_path)
2643 if(vm->is_compact_disc_inserted(drv)) {
2644 vm->close_compact_disc(drv);
2646 compact_disc_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2647 #if USE_COMPACT_DISC > 1
2648 out_message(_T("CD%d: Ejected"), drv + BASE_COMPACT_DISC_NUM);
2650 out_message(_T("CD: Ejected"));
2652 } else if(compact_disc_status[drv].wait_count == 0) {
2653 vm->open_compact_disc(drv, file_path);
2654 #if USE_COMPACT_DISC > 1
2655 out_message(_T("CD%d: %s"), drv + BASE_COMPACT_DISC_NUM, file_path);
2657 out_message(_T("CD: %s"), file_path);
2660 my_tcscpy_s(compact_disc_status[drv].path, _MAX_PATH, file_path);
2663 void EMU::close_compact_disc(int drv)
2665 vm->close_compact_disc(drv);
2666 clear_media_status(&compact_disc_status[drv]);
2667 #if USE_COMPACT_DISC > 1
2668 out_message(_T("CD%d: Ejected"), drv + BASE_COMPACT_DISC_NUM);
2670 out_message(_T("CD: Ejected"));
2674 bool EMU::is_compact_disc_inserted(int drv)
2676 return vm->is_compact_disc_inserted(drv);
2679 uint32_t EMU::is_compact_disc_accessed()
2681 return vm->is_compact_disc_accessed();
2685 #ifdef USE_LASER_DISC
2686 void EMU::open_laser_disc(int drv, const _TCHAR* file_path)
2688 if(vm->is_laser_disc_inserted(drv)) {
2689 vm->close_laser_disc(drv);
2691 laser_disc_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2692 #if USE_LASER_DISC > 1
2693 out_message(_T("LD%d: Ejected"), drv + BASE_LASER_DISC_NUM);
2695 out_message(_T("LD: Ejected"));
2697 } else if(laser_disc_status[drv].wait_count == 0) {
2698 vm->open_laser_disc(drv, file_path);
2699 #if USE_LASER_DISC > 1
2700 out_message(_T("LD%d: %s"), drv + BASE_LASER_DISC_NUM, file_path);
2702 out_message(_T("LD: %s"), file_path);
2705 my_tcscpy_s(laser_disc_status[drv].path, _MAX_PATH, file_path);
2708 void EMU::close_laser_disc(int drv)
2710 vm->close_laser_disc(drv);
2711 clear_media_status(&laser_disc_status[drv]);
2712 #if USE_LASER_DISC > 1
2713 out_message(_T("LD%d: Ejected"), drv + BASE_LASER_DISC_NUM);
2715 out_message(_T("LD: Ejected"));
2719 bool EMU::is_laser_disc_inserted(int drv)
2721 return vm->is_laser_disc_inserted(drv);
2724 uint32_t EMU::is_laser_disc_accessed()
2726 return vm->is_laser_disc_accessed();
2730 #ifdef USE_BINARY_FILE
2731 void EMU::load_binary(int drv, const _TCHAR* file_path)
2733 if(drv < USE_BINARY_FILE) {
2734 if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, create_local_path(_T("hex2bin.$$$")))) {
2735 vm->load_binary(drv, create_local_path(_T("hex2bin.$$$")));
2736 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
2738 vm->load_binary(drv, file_path);
2740 #if USE_BINARY_FILE > 1
2741 out_message(_T("Load Binary%d: %s"), drv + BASE_BINARY_FILE_NUM, file_path);
2743 out_message(_T("Load Binary: %s"), file_path);
2748 void EMU::save_binary(int drv, const _TCHAR* file_path)
2750 if(drv < USE_BINARY_FILE) {
2751 vm->save_binary(drv, file_path);
2752 #if USE_BINARY_FILE > 1
2753 out_message(_T("Save Binary%d: %s"), drv + BASE_BINARY_FILE_NUM, file_path);
2755 out_message(_T("Save Binary: %s"), file_path);
2762 void EMU::open_bubble_casette(int drv, const _TCHAR* file_path, int bank)
2764 if(drv < USE_BUBBLE) {
2765 if(vm->is_bubble_casette_inserted(drv)) {
2766 vm->close_bubble_casette(drv);
2768 bubble_casette_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2770 out_message(_T("Bubble%d: Ejected"), drv + BASE_BUBBLE_NUM);
2772 out_message(_T("Bubble: Ejected"));
2774 } else if(bubble_casette_status[drv].wait_count == 0) {
2775 vm->open_bubble_casette(drv, file_path, bank);
2777 out_message(_T("Bubble%d: %s"), drv + BASE_BUBBLE_NUM, file_path);
2779 out_message(_T("Bubble: %s"), file_path);
2782 my_tcscpy_s(bubble_casette_status[drv].path, _MAX_PATH, file_path);
2783 bubble_casette_status[drv].bank = bank;
2787 void EMU::close_bubble_casette(int drv)
2789 if(drv < USE_BUBBLE) {
2790 vm->close_bubble_casette(drv);
2791 clear_media_status(&bubble_casette_status[drv]);
2793 out_message(_T("Bubble%d: Ejected"), drv + BASE_BUBBLE_NUM);
2795 out_message(_T("Bubble: Ejected"));
2800 bool EMU::is_bubble_casette_inserted(int drv)
2802 if(drv < USE_BUBBLE) {
2803 return vm->is_bubble_casette_inserted(drv);
2809 bool EMU::is_bubble_casette_protected(int drv)
2811 if(drv < USE_BUBBLE) {
2812 return vm->is_bubble_casette_protected(drv);
2818 void EMU::is_bubble_casette_protected(int drv, bool flag)
2820 if(drv < USE_BUBBLE) {
2821 vm->is_bubble_casette_protected(drv, flag);
2829 #ifdef USE_LED_DEVICE
2830 uint32_t EMU::get_led_status()
2832 return vm->get_led_status();
2837 #ifdef USE_SOUND_VOLUME
2838 void EMU::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
2840 vm->set_sound_device_volume(ch, decibel_l, decibel_r);
2844 void EMU::update_config()
2846 vm->update_config();
2851 void EMU::load_sound_file(int id, const _TCHAR *name, int16_t **data, int *dst_size)
2853 osd->load_sound_file(id, name, data, dst_size);
2856 void EMU::free_sound_file(int id, int16_t **data)
2858 osd->free_sound_file(id, data);
2863 // ----------------------------------------------------------------------------
2865 // ----------------------------------------------------------------------------
2868 #define STATE_VERSION 2
2870 void EMU::save_state(const _TCHAR* file_path)
2872 FILEIO* fio = new FILEIO();
2875 if(config.compress_state) {
2876 fio->Gzopen(file_path, FILEIO_WRITE_BINARY);
2879 if(!fio->IsOpened()) {
2880 fio->Fopen(file_path, FILEIO_WRITE_BINARY);
2882 if(fio->IsOpened()) {
2883 // save state file version
2884 fio->FputUint32(STATE_VERSION);
2886 process_config_state((void *)fio, false);
2887 // save inserted medias
2889 fio->Fwrite(&cart_status, sizeof(cart_status), 1);
2891 #ifdef USE_FLOPPY_DISK
2892 fio->Fwrite(floppy_disk_status, sizeof(floppy_disk_status), 1);
2893 fio->Fwrite(d88_file, sizeof(d88_file), 1);
2895 #ifdef USE_QUICK_DISK
2896 fio->Fwrite(&quick_disk_status, sizeof(quick_disk_status), 1);
2898 #ifdef USE_HARD_DISK
2899 fio->Fwrite(&hard_disk_status, sizeof(hard_disk_status), 1);
2902 fio->Fwrite(&tape_status, sizeof(tape_status), 1);
2904 #ifdef USE_COMPACT_DISC
2905 fio->Fwrite(&compact_disc_status, sizeof(compact_disc_status), 1);
2907 #ifdef USE_LASER_DISC
2908 fio->Fwrite(&laser_disc_status, sizeof(laser_disc_status), 1);
2911 fio->Fwrite(&bubble_casette_status, sizeof(bubble_casette_status), 1);
2914 vm->process_state(fio, false);
2915 // end of state file
2916 fio->FputInt32_LE(-1);
2923 void EMU::load_state(const _TCHAR* file_path)
2925 if(FILEIO::IsFileExisting(file_path)) {
2928 config.romaji_to_kana = false;
2931 save_state(create_local_path(_T("$temp$.sta")));
2932 if(!load_state_tmp(file_path)) {
2933 out_debug_log(_T("failed to load state file\n"));
2934 load_state_tmp(create_local_path(_T("$temp$.sta")));
2936 FILEIO::RemoveFile(create_local_path(_T("$temp$.sta")));
2940 bool EMU::load_state_tmp(const _TCHAR* file_path)
2942 bool result = false;
2943 FILEIO* fio = new FILEIO();
2946 if(config.compress_state) {
2947 fio->Gzopen(file_path, FILEIO_READ_BINARY);
2950 if(!fio->IsOpened()) {
2951 fio->Fopen(file_path, FILEIO_READ_BINARY);
2953 if(fio->IsOpened()) {
2954 // check state file version
2955 if(fio->FgetUint32() == STATE_VERSION) {
2957 if(process_config_state((void *)fio, true)) {
2958 // load inserted medias
2960 fio->Fread(&cart_status, sizeof(cart_status), 1);
2962 #ifdef USE_FLOPPY_DISK
2963 fio->Fread(floppy_disk_status, sizeof(floppy_disk_status), 1);
2964 fio->Fread(d88_file, sizeof(d88_file), 1);
2966 #ifdef USE_QUICK_DISK
2967 fio->Fread(&quick_disk_status, sizeof(quick_disk_status), 1);
2969 #ifdef USE_HARD_DISK
2970 fio->Fread(&hard_disk_status, sizeof(hard_disk_status), 1);
2973 fio->Fread(&tape_status, sizeof(tape_status), 1);
2975 #ifdef USE_COMPACT_DISC
2976 fio->Fread(&compact_disc_status, sizeof(compact_disc_status), 1);
2978 #ifdef USE_LASER_DISC
2979 fio->Fread(&laser_disc_status, sizeof(laser_disc_status), 1);
2982 fio->Fread(&bubble_casette_status, sizeof(bubble_casette_status), 1);
2984 // check if virtual machine should be reinitialized
2985 bool reinitialize = false;
2987 reinitialize |= (cpu_type != config.cpu_type);
2988 cpu_type = config.cpu_type;
2990 #ifdef USE_DIPSWITCH
2991 reinitialize |= (dipswitch != config.dipswitch);
2992 dipswitch = config.dipswitch;
2994 #ifdef USE_SOUND_TYPE
2995 reinitialize |= (sound_type != config.sound_type);
2996 sound_type = config.sound_type;
2998 #ifdef USE_PRINTER_TYPE
2999 reinitialize |= (printer_type != config.printer_type);
3000 printer_type = config.printer_type;
3002 if(!(0 <= config.sound_frequency && config.sound_frequency < 8)) {
3003 config.sound_frequency = 6; // default: 48KHz
3005 if(!(0 <= config.sound_latency && config.sound_latency < 5)) {
3006 config.sound_latency = 1; // default: 100msec
3008 reinitialize |= (sound_frequency != config.sound_frequency);
3009 reinitialize |= (sound_latency != config.sound_latency);
3010 sound_frequency = config.sound_frequency;
3011 sound_latency = config.sound_latency;
3016 // reinitialize virtual machine
3021 # if defined(_USE_QT)
3022 osd->reset_vm_node();
3024 vm->initialize_sound(sound_rate, sound_samples);
3025 #ifdef USE_SOUND_VOLUME
3026 for(int i = 0; i < USE_SOUND_VOLUME; i++) {
3027 vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
3034 // restore inserted medias
3038 if(vm->process_state(fio, true)) {
3039 // check end of state
3040 result = (fio->FgetInt32_LE() == -1);