2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
7 [ win32 emulation i/f ]
15 #if defined(USE_DEBUGGER)
16 #include "vm/debugger.h"
22 #include "osdcall_types.h"
24 // ----------------------------------------------------------------------------
26 // ----------------------------------------------------------------------------
27 static const int sound_frequency_table[8] = {
28 2000, 4000, 8000, 11025, 22050, 44100,
29 #ifdef OVERRIDE_SOUND_FREQ_48000HZ
30 OVERRIDE_SOUND_FREQ_48000HZ,
36 static const double sound_latency_table[5] = {0.05, 0.1, 0.2, 0.3, 0.4};
39 // Please permit at least them m(.. )m
40 //extern void get_long_full_path_name(_TCHAR* src, _TCHAR* dst);
46 EMU::EMU(class Ui_MainWindow *hwnd, GLDrawClass *hinst, std::shared_ptr<CSP_Logger> p_logger, std::shared_ptr<USING_FLAGS> p) : EMU_TEMPLATE(hwnd, hinst, p_logger, p)
47 #elif defined(OSD_WIN32)
48 EMU::EMU(HWND hwnd, HINSTANCE hinst) : EMU_TEMPLATE(hwnd, hinst)
54 // store main window handle
55 #ifdef USE_FLOPPY_DISK
56 // initialize d88 file info
57 memset(d88_file, 0, sizeof(d88_file));
60 // initialize d88 file info
61 memset(b77_file, 0, sizeof(b77_file));
65 if(!(0 <= config.sound_frequency && config.sound_frequency < 8)) {
66 config.sound_frequency = 6; // default: 48KHz
68 if(!(0 <= config.sound_latency && config.sound_latency < 5)) {
69 config.sound_latency = 1; // default: 100msec
71 sound_frequency = config.sound_frequency;
72 sound_latency = config.sound_latency;
73 sound_rate = sound_frequency_table[config.sound_frequency];
74 sound_samples = (int)(sound_rate * sound_latency_table[config.sound_latency] + 0.5);
77 cpu_type = config.cpu_type;
80 dipswitch = config.dipswitch;
83 sound_type = config.sound_type;
85 #ifdef USE_PRINTER_TYPE
86 printer_type = config.printer_type;
88 #ifdef USE_SERIAL_TYPE
89 serial_type = config.serial_type;
92 // initialize b77 file info
93 memset(b77_file, 0, sizeof(b77_file));
98 osd = new OSD(p, csp_logger);
99 osd->main_window_handle = hwnd;
100 //osd->p_glv = hinst;
102 #elif defined(OSD_WIN32)
104 osd->main_window_handle = hwnd;
105 osd->instance_handle = hinst;
107 int presented_rate, presented_samples;
108 osd->initialize(sound_rate, sound_samples, &presented_rate, &presented_samples);
109 sound_rate = presented_rate;
110 sound_samples = presented_samples;
114 # if defined(_USE_QT)
115 osd->reset_vm_node();
116 osd->update_keyname_table();
119 initialize_auto_key();
122 initialize_debugger();
124 now_waiting_in_debugger = false;
126 vm->initialize_sound(sound_rate, sound_samples);
127 #ifdef USE_SOUND_VOLUME
128 for(int i = 0; i < USE_SOUND_VOLUME; i++) {
129 vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
133 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
134 if(config.last_hard_disk_path[drv][0] != _T('\0') && FILEIO::IsFileExisting(config.last_hard_disk_path[drv])) {
135 vm->open_hard_disk(drv, config.last_hard_disk_path[drv]);
136 my_tcscpy_s(hard_disk_status[drv].path, _MAX_PATH, config.last_hard_disk_path[drv]);
141 now_suspended = false;
164 // messaging proxies.
165 // These are mostly used for replying mounting virtual media.
167 void EMU::osdcall_string(EMU_MEDIA_TYPE::type_t media_type, int drive,EMU_MESSAGE_TYPE::type_t message_type, _TCHAR* message)
169 __LIKELY_IF(osd != nullptr) {
170 osd->string_message_from_emu(media_type, drive, message_type, message);
174 void EMU::osdcall_int(EMU_MEDIA_TYPE::type_t media_type, int drive, EMU_MESSAGE_TYPE::type_t message_type, int64_t data)
176 __LIKELY_IF(osd != nullptr) {
177 osd->int_message_from_emu(media_type, drive, message_type, data);
183 EmuThreadClass *EMU::get_parent_handler()
185 return osd->get_parent_handler();
188 void EMU::set_parent_handler(EmuThreadClass *p, DrawThreadClass *q)
190 osd->set_parent_thread(p);
191 osd->set_draw_thread(q);
194 void EMU::set_host_cpus(int v)
196 osd->host_cpus = (v <= 0) ? 1 : v;
199 int EMU::get_host_cpus()
201 return osd->host_cpus;
205 // ----------------------------------------------------------------------------
207 // ----------------------------------------------------------------------------
209 double EMU::get_frame_rate()
211 return vm->get_frame_rate();
214 int EMU::get_frame_interval()
216 static int prev_interval = 0;
217 static double prev_fps = -1;
218 double fps = vm->get_frame_rate();
219 if(prev_fps != fps) {
220 prev_interval = (int)(1024. * 1000. / fps + 0.5);
223 return prev_interval;
226 bool EMU::is_frame_skippable()
228 return vm->is_frame_skippable();
231 const bool EMU::is_use_state()
241 #if defined(USE_DEBUGGER) && defined(USE_STATE)
242 if(request_save_state >= 0 || request_load_state >= 0) {
243 if(request_save_state >= 0) {
244 save_state(state_file_path(request_save_state));
246 load_state(state_file_path(request_load_state));
248 // NOTE: vm instance may be reinitialized in load_state
249 // ToDo: Support multiple debuggers. 20230110 K.O
250 if(!is_debugger_enabled(debugger_cpu_index)) {
251 for(int i = 0; i < 8; i++) {
252 if(is_debugger_enabled(i)) {
253 debugger_cpu_index = i;
254 debugger_target_id = vm->get_cpu(debugger_cpu_index)->this_device_id;
259 if(is_debugger_enabled(debugger_cpu_index)) {
260 if(!(vm->get_device(debugger_target_id) != NULL && vm->get_device(debugger_target_id)->get_debugger() != NULL)) {
261 debugger_target_id = vm->get_cpu(debugger_cpu_index)->this_device_id;
263 DEBUGGER *cpu_debugger = (DEBUGGER *)vm->get_cpu(debugger_cpu_index)->get_debugger();
264 cpu_debugger->now_going = false;
265 cpu_debugger->now_debugging = true;
266 debugger_thread_param.vm = vm;
268 close_debugger(debugger_cpu_index);
270 request_save_state = request_load_state = -1;
275 now_suspended = false;
281 //#ifdef USE_JOYSTICK
282 // update_joystick();
286 #if !defined(_USE_QT) // Temporally
287 osd->update_socket();
292 // virtual machine may be driven to fill sound buffer
293 int extra_frames = 0;
294 osd->update_sound(&extra_frames);
296 // drive virtual machine
297 if(extra_frames == 0) {
303 osd->add_extra_frames(extra_frames);
311 config.romaji_to_kana = false;
314 // check if virtual machine should be reinitialized
315 bool reinitialize = false;
317 reinitialize |= (cpu_type != config.cpu_type);
318 cpu_type = config.cpu_type;
321 reinitialize |= (dipswitch != config.dipswitch);
322 dipswitch = config.dipswitch;
324 #ifdef USE_SOUND_TYPE
325 reinitialize |= (sound_type != config.sound_type);
326 sound_type = config.sound_type;
328 #ifdef USE_PRINTER_TYPE
329 reinitialize |= (printer_type != config.printer_type);
330 printer_type = config.printer_type;
332 #ifdef USE_SERIAL_TYPE
333 reinitialize |= (serial_type != config.serial_type);
334 serial_type = config.serial_type;
339 // reinitialize virtual machine
347 osd->reset_vm_node();
348 osd->update_keyname_table();
349 osd->reset_screen_buffer();
352 int presented_samples;
353 sound_rate = sound_frequency_table[config.sound_frequency];
354 sound_samples = (int)(sound_rate * sound_latency_table[config.sound_latency] + 0.5);
355 osd->initialize_sound(sound_rate, sound_samples, &presented_rate, &presented_samples);
356 if((sound_rate != presented_rate) ||
357 (sound_samples != presented_samples)) {
358 sound_rate = presented_rate;
359 sound_samples = presented_samples;
361 vm->initialize_sound(sound_rate, sound_samples);
362 #ifdef USE_SOUND_VOLUME
363 for(int i = 0; i < USE_SOUND_VOLUME; i++) {
364 vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
367 // restore inserted medias
372 // reset virtual machine
378 #if !defined(_USE_QT) // Temporally
380 osd->restart_record_sound();
381 osd->restart_record_video();
385 #ifdef USE_SPECIAL_RESET
386 void EMU::special_reset(int num)
389 if(num >= USE_SPECIAL_RESET) return;
392 config.romaji_to_kana = false;
395 // reset virtual machine
397 vm->special_reset(num);
400 #if !defined(_USE_QT) // Temporally
401 restart_record_sound();
402 restart_record_video();
407 #ifdef USE_NOTIFY_POWER_OFF
408 void EMU::notify_power_off()
410 vm->notify_power_off();
411 osd->notify_power_off(); // To GUI 20230120 K.O
415 void EMU::power_off()
424 now_suspended = true;
433 void EMU::unlock_vm()
438 void EMU::force_unlock_vm()
440 osd->force_unlock_vm();
443 bool EMU::is_vm_locked()
445 return osd->is_vm_locked();
448 // ----------------------------------------------------------------------------
450 // ----------------------------------------------------------------------------
453 void EMU::key_down(int code, bool extended, bool repeat)
457 shift_pressed = true;
459 if(config.romaji_to_kana) {
461 // Page Up, Page Down, End, Home, Left, Up, Right, Down, Ins, Del, Help, and F1-F12
462 if((code >= 0x21 && code <= 0x2f) || (code >= 0x70 && code <= 0x7b)) {
464 auto_key_buffer->write(code | 0x100);
466 auto_key_buffer->write(code);
468 if(!is_auto_key_running()) {
473 } else if(!is_auto_key_running())
475 osd->key_down(code, extended, repeat);
476 // printf("KEY DOWN: %04X EXT=%d REPEAT=%d\n", code, extended, repeat);
479 void EMU::key_up(int code, bool extended)
483 shift_pressed = false;
485 if(config.romaji_to_kana) {
487 } else if(!is_auto_key_running())
489 osd->key_up(code, extended);
490 // printf("KEY UP: %04X EXT=%d\n", code, extended);
493 void EMU::key_char(char code)
496 if(config.romaji_to_kana) {
497 set_auto_key_char(code);
502 #ifdef USE_KEY_LOCKED
503 bool EMU::get_caps_locked()
505 return vm->get_caps_locked();
508 bool EMU::get_kana_locked()
510 return vm->get_kana_locked();
514 void EMU::key_lost_focus()
516 osd->key_lost_focus();
519 #ifdef ONE_BOARD_MICRO_COMPUTER
520 void EMU::press_button(int num)
522 int code = vm_buttons[num].code;
525 osd->key_down_native(code, false);
526 osd->get_key_buffer()[code] = KEY_KEEP_FRAMES;
528 // code=0: reset virtual machine
535 void EMU::enable_mouse()
540 void EMU::disable_mouse()
542 osd->disable_mouse();
545 void EMU::toggle_mouse()
550 bool EMU::is_mouse_enabled()
552 return osd->is_mouse_enabled();
557 static const int auto_key_table_base[][2] = {
564 {0x08, 0x000 | 0x08}, // BS
565 {0x09, 0x000 | 0x09}, // Tab
566 {0x0d, 0x000 | 0x0d}, // Enter
567 {0x1b, 0x000 | 0x1b}, // Escape
568 {0x20, 0x000 | 0x20}, // ' '
570 {0x21, 0x100 | 0x31}, // '!'
571 {0x22, 0x100 | 0xba}, // '"'
572 {0x23, 0x100 | 0x33}, // '#'
573 {0x24, 0x100 | 0x34}, // '$'
574 {0x25, 0x100 | 0x35}, // '%'
575 {0x26, 0x100 | 0x37}, // '&'
576 {0x27, 0x000 | 0xba}, // '''
577 {0x28, 0x100 | 0x39}, // '('
578 {0x29, 0x100 | 0x30}, // ')'
579 {0x2a, 0x100 | 0x38}, // '*'
580 {0x2b, 0x100 | 0xde}, // '+'
581 {0x2c, 0x000 | 0xbc}, // ','
582 {0x2d, 0x000 | 0xbd}, // '-'
583 {0x2e, 0x000 | 0xbe}, // '.'
584 {0x2f, 0x000 | 0xbf}, // '/'
586 {0x21, 0x100 | 0x31}, // '!'
587 {0x22, 0x100 | 0x32}, // '"'
588 {0x23, 0x100 | 0x33}, // '#'
589 {0x24, 0x100 | 0x34}, // '$'
590 {0x25, 0x100 | 0x35}, // '%'
591 {0x26, 0x100 | 0x36}, // '&'
592 {0x27, 0x100 | 0x37}, // '''
593 {0x28, 0x100 | 0x38}, // '('
594 {0x29, 0x100 | 0x39}, // ')'
595 {0x2a, 0x100 | 0xba}, // '*'
596 {0x2b, 0x100 | 0xbb}, // '+'
597 {0x2c, 0x000 | 0xbc}, // ','
598 {0x2d, 0x000 | 0xbd}, // '-'
599 {0x2e, 0x000 | 0xbe}, // '.'
600 {0x2f, 0x000 | 0xbf}, // '/'
602 {0x30, 0x000 | 0x30}, // '0'
603 {0x31, 0x000 | 0x31}, // '1'
604 {0x32, 0x000 | 0x32}, // '2'
605 {0x33, 0x000 | 0x33}, // '3'
606 {0x34, 0x000 | 0x34}, // '4'
607 {0x35, 0x000 | 0x35}, // '5'
608 {0x36, 0x000 | 0x36}, // '6'
609 {0x37, 0x000 | 0x37}, // '7'
610 {0x38, 0x000 | 0x38}, // '8'
611 {0x39, 0x000 | 0x39}, // '9'
613 {0x3a, 0x100 | 0xbb}, // ':'
614 {0x3b, 0x000 | 0xbb}, // ';'
615 {0x3c, 0x100 | 0xbc}, // '<'
616 {0x3d, 0x000 | 0xde}, // '='
617 {0x3e, 0x100 | 0xbe}, // '>'
618 {0x3f, 0x100 | 0xbf}, // '?'
619 {0x40, 0x100 | 0x32}, // '@'
621 {0x3a, 0x000 | 0xba}, // ':'
622 {0x3b, 0x000 | 0xbb}, // ';'
623 {0x3c, 0x100 | 0xbc}, // '<'
624 {0x3d, 0x100 | 0xbd}, // '='
625 {0x3e, 0x100 | 0xbe}, // '>'
626 {0x3f, 0x100 | 0xbf}, // '?'
627 {0x40, 0x000 | 0xc0}, // '@'
629 {0x41, 0x400 | 0x41}, // 'A'
630 {0x42, 0x400 | 0x42}, // 'B'
631 {0x43, 0x400 | 0x43}, // 'C'
632 {0x44, 0x400 | 0x44}, // 'D'
633 {0x45, 0x400 | 0x45}, // 'E'
634 {0x46, 0x400 | 0x46}, // 'F'
635 {0x47, 0x400 | 0x47}, // 'G'
636 {0x48, 0x400 | 0x48}, // 'H'
637 {0x49, 0x400 | 0x49}, // 'I'
638 {0x4a, 0x400 | 0x4a}, // 'J'
639 {0x4b, 0x400 | 0x4b}, // 'K'
640 {0x4c, 0x400 | 0x4c}, // 'L'
641 {0x4d, 0x400 | 0x4d}, // 'M'
642 {0x4e, 0x400 | 0x4e}, // 'N'
643 {0x4f, 0x400 | 0x4f}, // 'O'
644 {0x50, 0x400 | 0x50}, // 'P'
645 {0x51, 0x400 | 0x51}, // 'Q'
646 {0x52, 0x400 | 0x52}, // 'R'
647 {0x53, 0x400 | 0x53}, // 'S'
648 {0x54, 0x400 | 0x54}, // 'T'
649 {0x55, 0x400 | 0x55}, // 'U'
650 {0x56, 0x400 | 0x56}, // 'V'
651 {0x57, 0x400 | 0x57}, // 'W'
652 {0x58, 0x400 | 0x58}, // 'X'
653 {0x59, 0x400 | 0x59}, // 'Y'
654 {0x5a, 0x400 | 0x5a}, // 'Z'
656 {0x5b, 0x000 | 0xc0}, // '['
657 {0x5c, 0x000 | 0xe2}, // '\'
658 {0x5d, 0x000 | 0xdb}, // ']'
659 {0x5e, 0x100 | 0x36}, // '^'
660 {0x5f, 0x100 | 0xbd}, // '_'
661 {0x60, 0x000 | 0xdd}, // '`'
663 {0x5b, 0x000 | 0xdb}, // '['
664 {0x5c, 0x000 | 0xdc}, // '\'
665 {0x5d, 0x000 | 0xdd}, // ']'
666 {0x5e, 0x000 | 0xde}, // '^'
667 {0x5f, 0x100 | 0xe2}, // '_'
668 {0x60, 0x100 | 0xc0}, // '`'
670 {0x61, 0x800 | 0x41}, // 'a'
671 {0x62, 0x800 | 0x42}, // 'b'
672 {0x63, 0x800 | 0x43}, // 'c'
673 {0x64, 0x800 | 0x44}, // 'd'
674 {0x65, 0x800 | 0x45}, // 'e'
675 {0x66, 0x800 | 0x46}, // 'f'
676 {0x67, 0x800 | 0x47}, // 'g'
677 {0x68, 0x800 | 0x48}, // 'h'
678 {0x69, 0x800 | 0x49}, // 'i'
679 {0x6a, 0x800 | 0x4a}, // 'j'
680 {0x6b, 0x800 | 0x4b}, // 'k'
681 {0x6c, 0x800 | 0x4c}, // 'l'
682 {0x6d, 0x800 | 0x4d}, // 'm'
683 {0x6e, 0x800 | 0x4e}, // 'n'
684 {0x6f, 0x800 | 0x4f}, // 'o'
685 {0x70, 0x800 | 0x50}, // 'p'
686 {0x71, 0x800 | 0x51}, // 'q'
687 {0x72, 0x800 | 0x52}, // 'r'
688 {0x73, 0x800 | 0x53}, // 's'
689 {0x74, 0x800 | 0x54}, // 't'
690 {0x75, 0x800 | 0x55}, // 'u'
691 {0x76, 0x800 | 0x56}, // 'v'
692 {0x77, 0x800 | 0x57}, // 'w'
693 {0x78, 0x800 | 0x58}, // 'x'
694 {0x79, 0x800 | 0x59}, // 'y'
695 {0x7a, 0x800 | 0x5a}, // 'z'
697 {0x7b, 0x100 | 0xc0}, // '{'
698 {0x7c, 0x100 | 0xe2}, // '|'
699 {0x7d, 0x100 | 0xdb}, // '}'
700 {0x7e, 0x100 | 0xdd}, // '~'
702 {0x7b, 0x100 | 0xdb}, // '{'
703 {0x7c, 0x100 | 0xdc}, // '|'
704 {0x7d, 0x100 | 0xdd}, // '}'
705 {0x7e, 0x100 | 0xde}, // '~'
710 static const int auto_key_table_kana_base[][2] = {
711 {0xa1, 0x300 | 0xbe}, // '。'
712 {0xa2, 0x300 | 0xdb}, // '「'
713 {0xa3, 0x300 | 0xdd}, // '」'
714 {0xa4, 0x300 | 0xbc}, // '、'
715 {0xa5, 0x300 | 0xbf}, // '・'
716 {0xa6, 0x300 | 0x30}, // 'ヲ'
717 {0xa7, 0x300 | 0x33}, // 'ァ'
718 {0xa8, 0x300 | 0x45}, // 'ィ'
719 {0xa9, 0x300 | 0x34}, // 'ゥ'
720 {0xaa, 0x300 | 0x35}, // 'ェ'
721 {0xab, 0x300 | 0x36}, // 'ォ'
722 {0xac, 0x300 | 0x37}, // 'ャ'
723 {0xad, 0x300 | 0x38}, // 'ュ'
724 {0xae, 0x300 | 0x39}, // 'ョ'
725 {0xaf, 0x300 | 0x5a}, // 'ッ'
726 {0xb0, 0x200 | 0xdc}, // 'ー'
727 {0xb1, 0x200 | 0x33}, // 'ア'
728 {0xb2, 0x200 | 0x45}, // 'イ'
729 {0xb3, 0x200 | 0x34}, // 'ウ'
730 {0xb4, 0x200 | 0x35}, // 'エ'
731 {0xb5, 0x200 | 0x36}, // 'オ'
732 {0xb6, 0x200 | 0x54}, // 'カ'
733 {0xb7, 0x200 | 0x47}, // 'キ'
734 {0xb8, 0x200 | 0x48}, // 'ク'
735 {0xb9, 0x200 | 0xba}, // 'ケ'
736 {0xba, 0x200 | 0x42}, // 'コ'
737 {0xbb, 0x200 | 0x58}, // 'サ'
738 {0xbc, 0x200 | 0x44}, // 'シ'
739 {0xbd, 0x200 | 0x52}, // 'ス'
740 {0xbe, 0x200 | 0x50}, // 'セ'
741 {0xbf, 0x200 | 0x43}, // 'ソ'
742 {0xc0, 0x200 | 0x51}, // 'タ'
743 {0xc1, 0x200 | 0x41}, // 'チ'
744 {0xc2, 0x200 | 0x5a}, // 'ツ'
745 {0xc3, 0x200 | 0x57}, // 'テ'
746 {0xc4, 0x200 | 0x53}, // 'ト'
747 {0xc5, 0x200 | 0x55}, // 'ナ'
748 {0xc6, 0x200 | 0x49}, // 'ニ'
749 {0xc7, 0x200 | 0x31}, // 'ヌ'
750 {0xc8, 0x200 | 0xbc}, // 'ネ'
751 {0xc9, 0x200 | 0x4b}, // 'ノ'
752 {0xca, 0x200 | 0x46}, // 'ハ'
753 {0xcb, 0x200 | 0x56}, // 'ヒ'
754 {0xcc, 0x200 | 0x32}, // 'フ'
755 {0xcd, 0x200 | 0xde}, // 'ヘ'
756 {0xce, 0x200 | 0xbd}, // 'ホ'
757 {0xcf, 0x200 | 0x4a}, // 'マ'
758 {0xd0, 0x200 | 0x4e}, // 'ミ'
759 {0xd1, 0x200 | 0xdd}, // 'ム'
760 {0xd2, 0x200 | 0xbf}, // 'メ'
761 {0xd3, 0x200 | 0x4d}, // 'モ'
762 {0xd4, 0x200 | 0x37}, // 'ヤ'
763 {0xd5, 0x200 | 0x38}, // 'ユ'
764 {0xd6, 0x200 | 0x39}, // 'ヨ'
765 {0xd7, 0x200 | 0x4f}, // 'ラ'
766 {0xd8, 0x200 | 0x4c}, // 'リ'
767 {0xd9, 0x200 | 0xbe}, // 'ル'
768 {0xda, 0x200 | 0xbb}, // 'レ'
769 {0xdb, 0x200 | 0xe2}, // 'ロ'
770 {0xdc, 0x200 | 0x30}, // 'ワ'
771 {0xdd, 0x200 | 0x59}, // 'ン'
772 {0xde, 0x200 | 0xc0}, // '゙'
773 {0xdf, 0x200 | 0xdb}, // '゚'
777 static const int auto_key_table_50on_base[][2] = {
778 {0xa1, 0x300 | 0xbf}, // '。'
779 {0xa2, 0x300 | 0xdb}, // '「'
780 {0xa3, 0x300 | 0xdd}, // '」'
781 {0xa4, 0x300 | 0xbe}, // '、'
782 {0xa5, 0x300 | 0xe2}, // '・'
783 {0xa6, 0x200 | 0xbf}, // 'ヲ'
784 {0xa7, 0x300 | 0x31}, // 'ァ'
785 {0xa8, 0x300 | 0x32}, // 'ィ'
786 {0xa9, 0x300 | 0x33}, // 'ゥ'
787 {0xaa, 0x300 | 0x34}, // 'ェ'
788 {0xab, 0x300 | 0x35}, // 'ォ'
789 {0xac, 0x300 | 0x4e}, // 'ャ'
790 {0xad, 0x300 | 0x4d}, // 'ュ'
791 {0xae, 0x300 | 0xbc}, // 'ョ'
792 {0xaf, 0x300 | 0x43}, // 'ッ'
793 {0xb0, 0x300 | 0xba}, // 'ー'
794 {0xb1, 0x200 | 0x31}, // 'ア'
795 {0xb2, 0x200 | 0x32}, // 'イ'
796 {0xb3, 0x200 | 0x33}, // 'ウ'
797 {0xb4, 0x200 | 0x34}, // 'エ'
798 {0xb5, 0x200 | 0x35}, // 'オ'
799 {0xb6, 0x200 | 0x51}, // 'カ'
800 {0xb7, 0x200 | 0x57}, // 'キ'
801 {0xb8, 0x200 | 0x45}, // 'ク'
802 {0xb9, 0x200 | 0x52}, // 'ケ'
803 {0xba, 0x200 | 0x54}, // 'コ'
804 {0xbb, 0x200 | 0x41}, // 'サ'
805 {0xbc, 0x200 | 0x53}, // 'シ'
806 {0xbd, 0x200 | 0x44}, // 'ス'
807 {0xbe, 0x200 | 0x46}, // 'セ'
808 {0xbf, 0x200 | 0x47}, // 'ソ'
809 {0xc0, 0x200 | 0x5a}, // 'タ'
810 {0xc1, 0x200 | 0x58}, // 'チ'
811 {0xc2, 0x200 | 0x43}, // 'ツ'
812 {0xc3, 0x200 | 0x56}, // 'テ'
813 {0xc4, 0x200 | 0x42}, // 'ト'
814 {0xc5, 0x200 | 0x36}, // 'ナ'
815 {0xc6, 0x200 | 0x37}, // 'ニ'
816 {0xc7, 0x200 | 0x38}, // 'ヌ'
817 {0xc8, 0x200 | 0x39}, // 'ネ'
818 {0xc9, 0x200 | 0x30}, // 'ノ'
819 {0xca, 0x200 | 0x59}, // 'ハ'
820 {0xcb, 0x200 | 0x55}, // 'ヒ'
821 {0xcc, 0x200 | 0x49}, // 'フ'
822 {0xcd, 0x200 | 0x4f}, // 'ヘ'
823 {0xce, 0x200 | 0x50}, // 'ホ'
824 {0xcf, 0x200 | 0x48}, // 'マ'
825 {0xd0, 0x200 | 0x4a}, // 'ミ'
826 {0xd1, 0x200 | 0x4b}, // 'ム'
827 {0xd2, 0x200 | 0x4c}, // 'メ'
828 {0xd3, 0x200 | 0xbb}, // 'モ'
829 {0xd4, 0x200 | 0x4e}, // 'ヤ'
830 {0xd5, 0x200 | 0x4d}, // 'ユ'
831 {0xd6, 0x200 | 0xbc}, // 'ヨ'
832 {0xd7, 0x200 | 0xbd}, // 'ラ'
833 {0xd8, 0x200 | 0xde}, // 'リ'
834 {0xd9, 0x200 | 0xdc}, // 'ル'
835 {0xda, 0x200 | 0xc0}, // 'レ'
836 {0xdb, 0x200 | 0xdb}, // 'ロ'
837 {0xdc, 0x200 | 0xbe}, // 'ワ'
838 {0xdd, 0x200 | 0xe2}, // 'ン'
839 {0xde, 0x200 | 0xba}, // '゙'
840 {0xdf, 0x200 | 0xdd}, // '゚'
844 static const struct {
846 const uint8_t kana[4];
848 {"ltsu", {0xaf, 0x00}},
849 {"xtsu", {0xaf, 0x00}},
850 {"ltu", {0xaf, 0x00}},
851 {"xtu", {0xaf, 0x00}},
852 {"bya", {0xcb, 0xde, 0xac, 0x00}},
853 {"byi", {0xcb, 0xde, 0xa8, 0x00}},
854 {"byu", {0xcb, 0xde, 0xad, 0x00}},
855 {"bye", {0xcb, 0xde, 0xaa, 0x00}},
856 {"byo", {0xcb, 0xde, 0xae, 0x00}},
857 {"cha", {0xc1, 0xac, 0x00}},
858 {"chi", {0xc1, 0x00}},
859 {"chu", {0xc1, 0xad, 0x00}},
860 {"che", {0xc1, 0xaa, 0x00}},
861 {"cho", {0xc1, 0xae, 0x00}},
862 {"cya", {0xc1, 0xac, 0x00}},
863 {"cyi", {0xc1, 0xa8, 0x00}},
864 {"cyu", {0xc1, 0xad, 0x00}},
865 {"cye", {0xc1, 0xaa, 0x00}},
866 {"cyo", {0xc1, 0xae, 0x00}},
867 {"dha", {0xc3, 0xde, 0xac, 0x00}},
868 {"dhi", {0xc3, 0xde, 0xa8, 0x00}},
869 {"dhu", {0xc3, 0xde, 0xad, 0x00}},
870 {"dhe", {0xc3, 0xde, 0xaa, 0x00}},
871 {"dho", {0xc3, 0xde, 0xae, 0x00}},
872 {"dwa", {0xc4, 0xde, 0xa7, 0x00}},
873 {"dwi", {0xc4, 0xde, 0xa8, 0x00}},
874 {"dwu", {0xc4, 0xde, 0xa9, 0x00}},
875 {"dwe", {0xc4, 0xde, 0xaa, 0x00}},
876 {"dwo", {0xc4, 0xde, 0xab, 0x00}},
877 {"dya", {0xc1, 0xde, 0xac, 0x00}},
878 {"dyi", {0xc1, 0xde, 0xa8, 0x00}},
879 {"dyu", {0xc1, 0xde, 0xad, 0x00}},
880 {"dye", {0xc1, 0xde, 0xaa, 0x00}},
881 {"dyo", {0xc1, 0xde, 0xae, 0x00}},
882 {"fwa", {0xcc, 0xa7, 0x00}},
883 {"fwi", {0xcc, 0xa8, 0x00}},
884 {"fwu", {0xcc, 0xa9, 0x00}},
885 {"fwe", {0xcc, 0xaa, 0x00}},
886 {"fwo", {0xcc, 0xab, 0x00}},
887 {"fya", {0xcc, 0xac, 0x00}},
888 {"fyi", {0xcc, 0xa8, 0x00}},
889 {"fyu", {0xcc, 0xad, 0x00}},
890 {"fye", {0xcc, 0xaa, 0x00}},
891 {"fyo", {0xcc, 0xae, 0x00}},
892 {"gwa", {0xb8, 0xde, 0xa7, 0x00}},
893 {"gwi", {0xb8, 0xde, 0xa8, 0x00}},
894 {"gwu", {0xb8, 0xde, 0xa9, 0x00}},
895 {"gwe", {0xb8, 0xde, 0xaa, 0x00}},
896 {"gwo", {0xb8, 0xde, 0xab, 0x00}},
897 {"gya", {0xb7, 0xde, 0xac, 0x00}},
898 {"gyi", {0xb7, 0xde, 0xa8, 0x00}},
899 {"gyu", {0xb7, 0xde, 0xad, 0x00}},
900 {"gye", {0xb7, 0xde, 0xaa, 0x00}},
901 {"gyo", {0xb7, 0xde, 0xae, 0x00}},
902 {"hya", {0xcb, 0xac, 0x00}},
903 {"hyi", {0xcb, 0xa8, 0x00}},
904 {"hyu", {0xcb, 0xad, 0x00}},
905 {"hye", {0xcb, 0xaa, 0x00}},
906 {"hyo", {0xcb, 0xae, 0x00}},
907 {"jya", {0xbc, 0xde, 0xac, 0x00}},
908 {"jyi", {0xbc, 0xde, 0xa8, 0x00}},
909 {"jyu", {0xbc, 0xde, 0xad, 0x00}},
910 {"jye", {0xbc, 0xde, 0xaa, 0x00}},
911 {"jyo", {0xbc, 0xde, 0xae, 0x00}},
912 {"kya", {0xb7, 0xac, 0x00}},
913 {"kyi", {0xb7, 0xa8, 0x00}},
914 {"kyu", {0xb7, 0xad, 0x00}},
915 {"kye", {0xb7, 0xaa, 0x00}},
916 {"kyo", {0xb7, 0xae, 0x00}},
917 {"lya", {0xac, 0x00}},
918 {"lyi", {0xa8, 0x00}},
919 {"lyu", {0xad, 0x00}},
920 {"lye", {0xaa, 0x00}},
921 {"lyo", {0xae, 0x00}},
922 {"mya", {0xd0, 0xac, 0x00}},
923 {"myi", {0xd0, 0xa8, 0x00}},
924 {"myu", {0xd0, 0xad, 0x00}},
925 {"mye", {0xd0, 0xaa, 0x00}},
926 {"myo", {0xd0, 0xae, 0x00}},
927 {"nya", {0xc6, 0xac, 0x00}},
928 {"nyi", {0xc6, 0xa8, 0x00}},
929 {"nyu", {0xc6, 0xad, 0x00}},
930 {"nye", {0xc6, 0xaa, 0x00}},
931 {"nyo", {0xc6, 0xae, 0x00}},
932 {"pya", {0xcb, 0xdf, 0xac, 0x00}},
933 {"pyi", {0xcb, 0xdf, 0xa8, 0x00}},
934 {"pyu", {0xcb, 0xdf, 0xad, 0x00}},
935 {"pye", {0xcb, 0xdf, 0xaa, 0x00}},
936 {"pyo", {0xcb, 0xdf, 0xae, 0x00}},
937 {"qwa", {0xb8, 0xa7, 0x00}},
938 {"qwi", {0xb8, 0xa8, 0x00}},
939 {"qwu", {0xb8, 0xa9, 0x00}},
940 {"qwe", {0xb8, 0xaa, 0x00}},
941 {"qwo", {0xb8, 0xab, 0x00}},
942 {"qya", {0xb8, 0xac, 0x00}},
943 {"qyi", {0xb8, 0xa8, 0x00}},
944 {"qyu", {0xb8, 0xad, 0x00}},
945 {"qye", {0xb8, 0xaa, 0x00}},
946 {"qyo", {0xb8, 0xae, 0x00}},
947 {"rya", {0xd8, 0xac, 0x00}},
948 {"ryi", {0xd8, 0xa8, 0x00}},
949 {"ryu", {0xd8, 0xad, 0x00}},
950 {"rye", {0xd8, 0xaa, 0x00}},
951 {"ryo", {0xd8, 0xae, 0x00}},
952 {"sha", {0xbc, 0xac, 0x00}},
953 {"shi", {0xbc, 0x00}},
954 {"shu", {0xbc, 0xad, 0x00}},
955 {"she", {0xbc, 0xaa, 0x00}},
956 {"sho", {0xbc, 0xae, 0x00}},
957 {"swa", {0xbd, 0xa7, 0x00}},
958 {"swi", {0xbd, 0xa8, 0x00}},
959 {"swu", {0xbd, 0xa9, 0x00}},
960 {"swe", {0xbd, 0xaa, 0x00}},
961 {"swo", {0xbd, 0xab, 0x00}},
962 {"sya", {0xbc, 0xac, 0x00}},
963 {"syi", {0xbc, 0xa8, 0x00}},
964 {"syu", {0xbc, 0xad, 0x00}},
965 {"sye", {0xbc, 0xaa, 0x00}},
966 {"syo", {0xbc, 0xae, 0x00}},
967 {"tha", {0xc3, 0xac, 0x00}},
968 {"thi", {0xc3, 0xa8, 0x00}},
969 {"thu", {0xc3, 0xad, 0x00}},
970 {"the", {0xc3, 0xaa, 0x00}},
971 {"tho", {0xc3, 0xae, 0x00}},
972 {"tsa", {0xc2, 0xa7, 0x00}},
973 {"tsi", {0xc2, 0xa8, 0x00}},
974 {"tsu", {0xc2, 0x00}},
975 {"tse", {0xc2, 0xaa, 0x00}},
976 {"tso", {0xc2, 0xab, 0x00}},
977 {"twa", {0xc4, 0xa7, 0x00}},
978 {"twi", {0xc4, 0xa8, 0x00}},
979 {"twu", {0xc4, 0xa9, 0x00}},
980 {"twe", {0xc4, 0xaa, 0x00}},
981 {"two", {0xc4, 0xab, 0x00}},
982 {"tya", {0xc1, 0xac, 0x00}},
983 {"tyi", {0xc1, 0xa8, 0x00}},
984 {"tyu", {0xc1, 0xad, 0x00}},
985 {"tye", {0xc1, 0xaa, 0x00}},
986 {"tyo", {0xc1, 0xae, 0x00}},
987 {"vya", {0xb3, 0xde, 0xac, 0x00}},
988 {"vyi", {0xb3, 0xde, 0xa8, 0x00}},
989 {"vyu", {0xb3, 0xde, 0xad, 0x00}},
990 {"vye", {0xb3, 0xde, 0xaa, 0x00}},
991 {"vyo", {0xb3, 0xde, 0xae, 0x00}},
992 {"wha", {0xb3, 0xa7, 0x00}},
993 {"whi", {0xb3, 0xa8, 0x00}},
994 {"whu", {0xb3, 0x00}},
995 {"whe", {0xb3, 0xaa, 0x00}},
996 {"who", {0xb3, 0xab, 0x00}},
997 {"xya", {0xac, 0x00}},
998 {"xyi", {0xa8, 0x00}},
999 {"xyu", {0xad, 0x00}},
1000 {"xye", {0xaa, 0x00}},
1001 {"xyo", {0xae, 0x00}},
1002 {"zya", {0xbc, 0xde, 0xac, 0x00}},
1003 {"zyi", {0xbc, 0xde, 0xa8, 0x00}},
1004 {"zyu", {0xbc, 0xde, 0xad, 0x00}},
1005 {"zye", {0xbc, 0xde, 0xaa, 0x00}},
1006 {"zyo", {0xbc, 0xde, 0xae, 0x00}},
1007 {"ba", {0xca, 0xde, 0x00}},
1008 {"bi", {0xcb, 0xde, 0x00}},
1009 {"bu", {0xcc, 0xde, 0x00}},
1010 {"be", {0xcd, 0xde, 0x00}},
1011 {"bo", {0xce, 0xde, 0x00}},
1012 {"ca", {0xb6, 0x00}},
1013 {"ci", {0xbc, 0x00}},
1014 {"cu", {0xb8, 0x00}},
1015 {"ce", {0xbe, 0x00}},
1016 {"co", {0xba, 0x00}},
1017 {"da", {0xc0, 0xde, 0x00}},
1018 {"di", {0xc1, 0xde, 0x00}},
1019 {"du", {0xc2, 0xde, 0x00}},
1020 {"de", {0xc3, 0xde, 0x00}},
1021 {"do", {0xc4, 0xde, 0x00}},
1022 {"fa", {0xcc, 0xa7, 0x00}},
1023 {"fi", {0xcc, 0xa8, 0x00}},
1024 {"fu", {0xcc, 0x00}},
1025 {"fe", {0xcc, 0xaa, 0x00}},
1026 {"fo", {0xcc, 0xab, 0x00}},
1027 {"ga", {0xb6, 0xde, 0x00}},
1028 {"gi", {0xb7, 0xde, 0x00}},
1029 {"gu", {0xb8, 0xde, 0x00}},
1030 {"ge", {0xb9, 0xde, 0x00}},
1031 {"go", {0xba, 0xde, 0x00}},
1032 {"ha", {0xca, 0x00}},
1033 {"hi", {0xcb, 0x00}},
1034 {"hu", {0xcc, 0x00}},
1035 {"he", {0xcd, 0x00}},
1036 {"ho", {0xce, 0x00}},
1037 {"ja", {0xbc, 0xde, 0xac, 0x00}},
1038 {"ji", {0xbc, 0xde, 0x00}},
1039 {"ju", {0xbc, 0xde, 0xad, 0x00}},
1040 {"je", {0xbc, 0xde, 0xaa, 0x00}},
1041 {"jo", {0xbc, 0xde, 0xae, 0x00}},
1042 {"ka", {0xb6, 0x00}},
1043 {"ki", {0xb7, 0x00}},
1044 {"ku", {0xb8, 0x00}},
1045 {"ke", {0xb9, 0x00}},
1046 {"ko", {0xba, 0x00}},
1047 {"la", {0xa7, 0x00}},
1048 {"li", {0xa8, 0x00}},
1049 {"lu", {0xa9, 0x00}},
1050 {"le", {0xaa, 0x00}},
1051 {"lo", {0xab, 0x00}},
1052 {"ma", {0xcf, 0x00}},
1053 {"mi", {0xd0, 0x00}},
1054 {"mu", {0xd1, 0x00}},
1055 {"me", {0xd2, 0x00}},
1056 {"mo", {0xd3, 0x00}},
1057 {"na", {0xc5, 0x00}},
1058 {"ni", {0xc6, 0x00}},
1059 {"nu", {0xc7, 0x00}},
1060 {"ne", {0xc8, 0x00}},
1061 {"no", {0xc9, 0x00}},
1062 // {"nn", {0xdd, 0x00}},
1063 {"pa", {0xca, 0xdf, 0x00}},
1064 {"pi", {0xcb, 0xdf, 0x00}},
1065 {"pu", {0xcc, 0xdf, 0x00}},
1066 {"pe", {0xcd, 0xdf, 0x00}},
1067 {"po", {0xce, 0xdf, 0x00}},
1068 {"qa", {0xb8, 0xa7, 0x00}},
1069 {"qi", {0xb8, 0xa8, 0x00}},
1070 {"qu", {0xb8, 0x00}},
1071 {"qe", {0xb8, 0xaa, 0x00}},
1072 {"qo", {0xb8, 0xab, 0x00}},
1073 {"ra", {0xd7, 0x00}},
1074 {"ri", {0xd8, 0x00}},
1075 {"ru", {0xd9, 0x00}},
1076 {"re", {0xda, 0x00}},
1077 {"ro", {0xdb, 0x00}},
1078 {"sa", {0xbb, 0x00}},
1079 {"si", {0xbc, 0x00}},
1080 {"su", {0xbd, 0x00}},
1081 {"se", {0xbe, 0x00}},
1082 {"so", {0xbf, 0x00}},
1083 {"ta", {0xc0, 0x00}},
1084 {"ti", {0xc1, 0x00}},
1085 {"tu", {0xc2, 0x00}},
1086 {"te", {0xc3, 0x00}},
1087 {"to", {0xc4, 0x00}},
1088 {"va", {0xb3, 0xde, 0xa7, 0x00}},
1089 {"vi", {0xb3, 0xde, 0xa8, 0x00}},
1090 {"vu", {0xb3, 0xde, 0x00}},
1091 {"ve", {0xb3, 0xde, 0xaa, 0x00}},
1092 {"vo", {0xb3, 0xde, 0xab, 0x00}},
1093 {"wa", {0xdc, 0x00}},
1094 {"wi", {0xb3, 0xa8, 0x00}},
1095 {"wu", {0xb3, 0x00}},
1096 {"we", {0xb3, 0xaa, 0x00}},
1097 {"wo", {0xa6, 0x00}},
1098 {"xa", {0xa7, 0x00}},
1099 {"xi", {0xa8, 0x00}},
1100 {"xu", {0xa9, 0x00}},
1101 {"xe", {0xaa, 0x00}},
1102 {"xo", {0xab, 0x00}},
1103 {"ya", {0xd4, 0x00}},
1104 {"yi", {0xb2, 0x00}},
1105 {"yu", {0xd5, 0x00}},
1106 {"ye", {0xb2, 0xaa, 0x00}},
1107 {"yo", {0xd6, 0x00}},
1108 {"za", {0xbb, 0xde, 0x00}},
1109 {"zi", {0xbc, 0xde, 0x00}},
1110 {"zu", {0xbd, 0xde, 0x00}},
1111 {"ze", {0xbe, 0xde, 0x00}},
1112 {"zo", {0xbf, 0xde, 0x00}},
1113 {"a", {0xb1, 0x00}},
1114 {"i", {0xb2, 0x00}},
1115 {"u", {0xb3, 0x00}},
1116 {"e", {0xb4, 0x00}},
1117 {"o", {0xb5, 0x00}},
1118 {"[", {0xa2, 0x00}},
1119 {"]", {0xa3, 0x00}},
1120 {"-", {0xb0, 0x00}},
1121 {",", {0xa4, 0x00}},
1122 {".", {0xa1, 0x00}},
1123 {"/", {0xa5, 0x00}},
1124 // Pass through kana key codes.
1125 {"\x0bc", {0xa4, 0x00}},
1126 {"\x0bd", {0xb0, 0x00}},
1127 {"\x0be", {0xa1, 0x00}},
1128 {"\x0bf", {0xa5, 0x00}},
1129 {"\x0db", {0xa2, 0x00}},
1130 {"\x0dd", {0xa3, 0x00}},
1134 void EMU::initialize_auto_key()
1136 auto_key_buffer = new FIFO(65536);
1137 auto_key_buffer->clear();
1138 auto_key_phase = auto_key_shift = 0;
1139 shift_pressed = false;
1140 osd->now_auto_key = false;
1143 void EMU::release_auto_key()
1145 if(auto_key_buffer) {
1146 auto_key_buffer->release();
1147 delete auto_key_buffer;
1151 int EMU::get_auto_key_code(int code)
1153 static int auto_key_table[256];
1154 static bool initialized = false;
1155 #ifdef USE_KEYBOARD_TYPE
1156 static int keyboard_type = -1;
1158 if(keyboard_type != config.keyboard_type) {
1159 initialized = false;
1160 keyboard_type = config.keyboard_type;
1164 memset(auto_key_table, 0, sizeof(auto_key_table));
1165 for(int i = 0;; i++) {
1166 if(auto_key_table_base[i][0] == -1) {
1169 auto_key_table[auto_key_table_base[i][0]] = auto_key_table_base[i][1];
1171 #if defined(_X1TURBO) || defined(_X1TURBOZ)
1173 if(config.keyboard_type) {
1174 for(int i = 0;; i++) {
1175 if(auto_key_table_50on_base[i][0] == -1) {
1178 auto_key_table[auto_key_table_50on_base[i][0]] = auto_key_table_50on_base[i][1];
1182 for(int i = 0;; i++) {
1183 if(auto_key_table_kana_base[i][0] == -1) {
1186 auto_key_table[auto_key_table_kana_base[i][0]] = auto_key_table_kana_base[i][1];
1188 #ifdef USE_VM_AUTO_KEY_TABLE
1189 for(int i = 0;; i++) {
1190 if(vm_auto_key_table_base[i][0] == -1) {
1193 auto_key_table[vm_auto_key_table_base[i][0]] = vm_auto_key_table_base[i][1];
1198 return auto_key_table[code];
1201 void EMU::set_auto_key_code(int code)
1203 if(code == 0xf2 || (code = get_auto_key_code(code)) != 0) {
1204 if(code == 0x08 || code == 0x09 || code == 0x0d || code == 0x1b || code == 0x20 || code == 0xf2) {
1205 // VK_BACK, VK_TAB, VK_RETURN, VK_ESCAPE, VK_SPACE, VK_OEM_COPY(Katakana/Hiragana)
1206 auto_key_buffer->write(code);
1207 #ifdef USE_AUTO_KEY_NUMPAD
1208 } else if(code >= 0x30 && code <= 0x39) {
1210 auto_key_buffer->write(code - 0x30 + 0x60);
1212 } else if(code & 0x200) {
1214 auto_key_buffer->write(code & 0x1ff);
1216 // ank other than alphabet and kana
1217 auto_key_buffer->write(0xf2); // kana unlock
1218 auto_key_buffer->write(code & 0x1ff);
1219 auto_key_buffer->write(0xf2); // kana lock
1221 if(!is_auto_key_running()) {
1227 void EMU::set_auto_key_list(char *buf, int size)
1229 #if defined(USE_KEY_LOCKED)
1230 bool prev_caps = get_caps_locked();
1231 bool prev_kana = get_kana_locked();
1233 bool prev_caps = false;
1234 bool prev_kana = false;
1236 auto_key_buffer->clear();
1238 for(int i = 0; i < size; i++) {
1239 int code = buf[i] & 0xff;
1240 if((0x81 <= code && code <= 0x9f) || 0xe0 <= code) {
1243 } else if(code == 0x0a) {
1246 if((code = get_auto_key_code(code)) != 0) {
1248 bool kana = ((code & 0x200) != 0);
1249 if(prev_kana != kana) {
1250 auto_key_buffer->write(0xf2);
1254 if(i < (size - 1)) {
1255 bool dakuon_lock = false;
1256 bool handakuon_lock = false;
1257 #if defined(USE_TWO_STROKE_AUTOKEY_HANDAKUON)
1258 if((buf[i + 1] & 0xff) == 0xdf) { // Is Handakuon
1259 for(int jj = 0; ; jj++) {
1260 if(kana_handakuon_keyboard_table[jj][0] == -1) break;
1261 if(kana_handakuon_keyboard_table[jj][0] == (buf[i] & 0xff)) { // Found
1262 handakuon_lock = true;
1263 for(int l = 1; l < 6; l++) {
1264 int n_code = kana_handakuon_keyboard_table[jj][l];
1265 if(n_code == 0x00) break;
1266 if(n_code & (0x100 | 0x400 | 0x800)) {
1267 auto_key_buffer->write((n_code & 0x30ff)| 0x100);
1269 auto_key_buffer->write(n_code & 0x30ff);
1275 if(handakuon_lock) {
1281 #if defined(USE_TWO_STROKE_AUTOKEY_DAKUON)
1282 if((buf[i + 1] & 0xff) == 0xde) { // Is Dakuon
1283 for(int jj = 0; ; jj++) {
1284 if(kana_dakuon_keyboard_table[jj][0] == -1) break;
1285 if(kana_dakuon_keyboard_table[jj][0] == (buf[i] & 0xff)) { // Found
1287 for(int l = 1; l < 6; l++) {
1288 int n_code = kana_dakuon_keyboard_table[jj][l];
1289 if(n_code == 0x00) break;
1290 if(n_code & (0x100 | 0x400 | 0x800)) {
1291 auto_key_buffer->write((n_code & 0x30ff)| 0x100);
1293 auto_key_buffer->write(n_code & 0x30ff);
1306 #if defined(USE_AUTO_KEY_CAPS_LOCK)
1307 // use caps lock key to switch uppercase/lowercase of alphabet
1308 // USE_AUTO_KEY_CAPS_LOCK shows the caps lock key code
1309 bool caps = ((code & 0x400) != 0);
1310 if(prev_caps != caps) {
1311 auto_key_buffer->write(USE_AUTO_KEY_CAPS_LOCK);
1315 #if defined(USE_AUTO_KEY_CAPS_LOCK) || defined(USE_AUTO_KEY_NO_CAPS)
1316 code &= ~(0x400 | 0x800); // don't press shift key for both alphabet and ALPHABET
1317 #elif defined(USE_KEY_LOCKED)
1318 if(get_caps_locked()) {
1319 code &= ~0x400; // don't press shift key for ALPHABET
1321 code &= ~0x800; // don't press shift key for alphabet
1323 #elif defined(USE_AUTO_KEY_CAPS)
1324 code &= ~0x400; // don't press shift key for ALPHABET
1326 code &= ~0x800; // don't press shift key for alphabet
1328 if(code & (0x100 | 0x400 | 0x800)) {
1329 auto_key_buffer->write((code & 0xff) | 0x100);
1331 auto_key_buffer->write(code & 0xff);
1335 // release kana lock
1337 auto_key_buffer->write(0xf2);
1339 #if defined(USE_AUTO_KEY_CAPS_LOCK)
1340 // release caps lock
1342 auto_key_buffer->write(USE_AUTO_KEY_CAPS_LOCK);
1347 bool is_alphabet(char code)
1349 return (code >= 'a' && code <= 'z');
1352 bool is_vowel(char code)
1354 return (code == 'a' || code == 'i' || code == 'u' || code == 'e' || code == 'o');
1357 bool is_consonant(char code)
1359 return (is_alphabet(code) && !is_vowel(code));
1362 void EMU::set_auto_key_char(char code)
1364 static char codes[5] = {0};
1367 #ifdef USE_KEY_LOCKED
1368 if(!get_kana_locked())
1370 set_auto_key_code(0xf2);
1371 memset(codes, 0, sizeof(codes));
1372 } else if(code == 0) {
1374 if(codes[3] == 'n') {
1375 set_auto_key_code(0xdd); // 'ン'
1377 set_auto_key_code(0xf2);
1378 memset(codes, 0, sizeof(codes));
1379 } else if(code == 0x08 || code == 0x09 || code == 0x0d || code == 0x1b || code == 0x20) {
1380 if(codes[3] == 'n') {
1381 set_auto_key_code(0xdd); // 'ン'
1383 set_auto_key_code(code);
1384 memset(codes, 0, sizeof(codes));
1385 #ifdef USE_AUTO_KEY_NUMPAD
1386 } else if(code >= 0x30 && code <= 0x39) {
1387 if(codes[3] == 'n') {
1388 set_auto_key_code(0xdd); // 'ン'
1390 set_auto_key_code(code);
1391 memset(codes, 0, sizeof(codes));
1394 codes[0] = codes[1];
1395 codes[1] = codes[2];
1396 codes[2] = codes[3];
1397 codes[3] = (code >= 'A' && code <= 'Z') ? ('a' + (code - 'A')) : code & 0xff;
1400 if(codes[2] == 'n' && !is_vowel(codes[3])) {
1401 set_auto_key_code(0xdd); // 'ン'
1402 if(codes[3] == 'n') {
1403 memset(codes, 0, sizeof(codes));
1406 } else if(codes[2] == codes[3] && is_consonant(codes[3])) {
1407 set_auto_key_code(0xaf); // 'ッ'
1410 for(int i = 0;; i++) {
1411 size_t len = strlen(romaji_table[i].romaji);
1415 if(!(is_alphabet(codes[3])) /*&& !((codes[3] >= 0x2c) && (codes[3] <= 0x2e)) && !((codes[3] == 0x5b) || (codes[3] == 0x5d))*/) {
1416 set_auto_key_code(codes[3]);
1417 memset(codes, 0, sizeof(codes));
1420 } else if(len == 1) {
1421 comp = strcmp(romaji_table[i].romaji, &codes[3]);
1422 } else if(len == 2) {
1423 comp = strcmp(romaji_table[i].romaji, &codes[2]);
1424 } else if(len == 3) {
1425 comp = strcmp(romaji_table[i].romaji, &codes[1]);
1426 } else if(len == 4) {
1427 comp = strcmp(romaji_table[i].romaji, &codes[0]);
1430 for(int j = 0; j < 4; j++) {
1431 if(!romaji_table[i].kana[j]) {
1435 bool handakuon_found = false;
1436 bool dakuon_found = false;
1437 #if defined(USE_TWO_STROKE_AUTOKEY_HANDAKUON)
1438 if(romaji_table[i].kana[1] == 0xdf) {
1440 for(int jj = 0;;jj++) {
1441 if(kana_handakuon_keyboard_table[jj][0] == -1) break;
1442 if(kana_handakuon_keyboard_table[jj][0] == romaji_table[i].kana[0]) {
1443 for(int l = 1; l < 6; l++) {
1444 if(kana_handakuon_keyboard_table[jj][l] == 0x00) break;
1445 auto_key_buffer->write(kana_handakuon_keyboard_table[jj][l] & 0x31ff);
1446 if(!is_auto_key_running()) {
1450 handakuon_found = true;
1457 #if defined(USE_TWO_STROKE_AUTOKEY_DAKUON)
1458 if(romaji_table[i].kana[1] == 0xde) {
1460 for(int jj = 0;;jj++) {
1461 if(kana_dakuon_keyboard_table[jj][0] == -1) break;
1462 if(kana_dakuon_keyboard_table[jj][0] == romaji_table[i].kana[0]) {
1463 for(int l = 1; l < 6; l++) {
1464 if(kana_dakuon_keyboard_table[jj][l] == 0x00) break;
1465 auto_key_buffer->write(kana_dakuon_keyboard_table[jj][l] & 0x31ff);
1467 if(!is_auto_key_running()) {
1471 dakuon_found = true;
1477 if((handakuon_found) || (dakuon_found)) {
1481 set_auto_key_code(romaji_table[i].kana[j]);
1483 memset(codes, 0, sizeof(codes));
1490 void EMU::start_auto_key()
1494 osd->now_auto_key = true;
1497 void EMU::stop_auto_key()
1499 if(auto_key_shift) {
1500 osd->key_up_native(VK_LSHIFT);
1502 auto_key_phase = auto_key_shift = 0;
1503 osd->now_auto_key = false;
1506 #ifndef USE_AUTO_KEY_SHIFT
1507 #define USE_AUTO_KEY_SHIFT 0
1510 #define VK_LSHIFT 0xA0
1513 void EMU::update_auto_key()
1515 switch(auto_key_phase) {
1517 if(auto_key_buffer && !auto_key_buffer->empty()) {
1518 // update shift key status
1519 int shift = auto_key_buffer->read_not_remove(0) & 0x100;
1520 if(shift && !auto_key_shift) {
1521 osd->key_down_native(VK_LSHIFT, false);
1522 } else if(!shift && auto_key_shift) {
1523 osd->key_up_native(VK_LSHIFT);
1525 auto_key_shift = shift;
1529 case 3 + USE_AUTO_KEY_SHIFT:
1530 if(auto_key_buffer && !auto_key_buffer->empty()) {
1531 if(!(auto_key_buffer->read_not_remove(0) & 0x2000)) {
1532 osd->key_down_native(auto_key_buffer->read_not_remove(0) & 0xff, false);
1533 // printf("Press key: %04X\n", auto_key_buffer->read_not_remove(0));
1538 case USE_AUTO_KEY + USE_AUTO_KEY_SHIFT:
1539 if(auto_key_buffer && !auto_key_buffer->empty()) {
1540 if(!(auto_key_buffer->read_not_remove(0) & 0x1000)) {
1541 osd->key_up_native(auto_key_buffer->read_not_remove(0) & 0xff);
1542 // printf("Release key: %04X\n", auto_key_buffer->read_not_remove(0));
1547 case USE_AUTO_KEY_RELEASE + USE_AUTO_KEY_SHIFT:
1548 if(auto_key_buffer && !auto_key_buffer->empty()) {
1549 // wait enough while vm analyzes one line
1550 if(auto_key_buffer->read() == 0xd) {
1556 if(auto_key_buffer && !auto_key_buffer->empty()) {
1563 if(auto_key_phase) {
1571 void EMU::update_joystick()
1573 uint8_t *key_buffer = osd->get_key_buffer();
1575 uint32_t *joyp = osd->get_joy_buffer();
1576 uint32_t joy_buffer[4];
1577 memset(joy_status, 0, sizeof(joy_status));
1578 for(int i = 0; i < 4; i++) {
1579 joy_buffer[i] = joyp[i];
1581 osd->release_joy_buffer(joyp);
1583 for(int i = 0; i < 4; i++) {
1584 for(int j = 0; j < 16; j++) {
1585 if(config.joy_buttons[i][j] < 0) {
1586 int code = -config.joy_buttons[i][j];
1587 if(code < 256 && key_buffer[code]) {
1588 joy_status[i] |= (1 << j);
1589 //printf("%d %d %02x %02x\n", i, j, config.joy_buttons[i][j], joy_status[i]);
1592 int stick = config.joy_buttons[i][j] >> 5;
1593 int button = config.joy_buttons[i][j] & 0x1f;
1594 if(stick < 4 && (joy_buffer[stick & 3] & (1 << button))) {
1595 joy_status[i] |= (1 << j);
1596 //printf("%d %d %02x %02x\n", i, j, config.joy_buttons[i][j], joy_status[i]);
1604 const uint8_t* EMU::get_key_buffer()
1606 return (const uint8_t*)osd->get_key_buffer();
1610 const uint32_t* EMU::get_joy_buffer()
1612 // Update joystick data per query joystick buffer.
1614 return (const uint32_t*)joy_status;
1616 void EMU::release_joy_buffer(const uint32_t* ptr)
1618 // ToDo: Unlock buffer.
1623 const int32_t* EMU::get_mouse_buffer()
1625 return (const int32_t*)osd->get_mouse_buffer();
1627 void EMU::release_mouse_buffer(const int32_t* ptr)
1629 // ToDo: Unlock buffer.
1630 osd->release_mouse_buffer((int32_t*)ptr);
1632 const int32_t EMU::get_mouse_button()
1634 return (const int32_t)osd->get_mouse_button();
1639 // ----------------------------------------------------------------------------
1641 // ----------------------------------------------------------------------------
1643 double EMU::get_window_mode_power(int mode)
1645 return osd->get_window_mode_power(mode);
1648 int EMU::get_window_mode_width(int mode)
1650 return osd->get_window_mode_width(mode);
1653 int EMU::get_window_mode_height(int mode)
1655 return osd->get_window_mode_height(mode);
1658 void EMU::set_host_window_size(int window_width, int window_height, bool window_mode)
1660 osd->set_host_window_size(window_width, window_height, window_mode);
1663 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)
1665 osd->set_vm_screen_size(screen_width, screen_height, window_width, window_height, window_width_aspect, window_height_aspect);
1668 void EMU::set_vm_screen_lines(int lines)
1670 osd->set_vm_screen_lines(lines);
1674 int EMU::get_vm_window_width()
1676 return osd->get_vm_window_width();
1679 int EMU::get_vm_window_height()
1681 return osd->get_vm_window_height();
1684 int EMU::get_vm_window_width_aspect()
1686 return osd->get_vm_window_width_aspect();
1689 int EMU::get_vm_window_height_aspect()
1691 return osd->get_vm_window_height_aspect();
1694 #if defined(USE_MINIMUM_RENDERING)
1695 bool EMU::is_screen_changed()
1697 return vm->is_screen_changed();
1701 int EMU::draw_screen()
1703 #ifdef ONE_BOARD_MICRO_COMPUTER
1704 if(now_waiting_in_debugger) {
1705 osd->reload_bitmap();
1708 return osd->draw_screen();
1711 scrntype_t* EMU::get_screen_buffer(int y)
1713 return osd->get_vm_screen_buffer(y);
1716 #ifdef USE_SCREEN_FILTER
1717 void EMU::screen_skip_line(bool skip_line)
1719 osd->screen_skip_line = skip_line;
1723 #ifdef ONE_BOARD_MICRO_COMPUTER
1724 void EMU::get_invalidated_rect(int *left, int *top, int *right, int *bottom)
1726 #ifdef MAX_DRAW_RANGES
1727 for(int i = 0; i < MAX_DRAW_RANGES; i++) {
1729 for(int i = 0; i < vm->max_draw_ranges(); i++) { // for TK-80BS
1731 int x1 = vm_ranges[i].x;
1732 int y1 = vm_ranges[i].y;
1733 int x2 = x1 + vm_ranges[i].width;
1734 int y2 = y1 + vm_ranges[i].height;
1736 *left = (i == 0) ? x1 : min(x1, *left );
1737 *top = (i == 0) ? y1 : min(y1, *top );
1738 *right = (i == 0) ? x2 : max(x2, *right );
1739 *bottom = (i == 0) ? y2 : max(y2, *bottom);
1743 void EMU::reload_bitmap()
1745 osd->reload_bitmap();
1750 void EMU::invalidate_screen()
1752 osd->invalidate_screen();
1755 void EMU::update_screen(HDC hdc)
1757 osd->update_screen(hdc);
1761 void EMU::capture_screen()
1763 osd->capture_screen();
1766 bool EMU::start_record_video(int fps)
1768 return osd->start_record_video(fps);
1771 void EMU::stop_record_video()
1773 osd->stop_record_video();
1776 bool EMU::is_video_recording()
1778 return osd->now_record_video;
1781 // ----------------------------------------------------------------------------
1783 // ----------------------------------------------------------------------------
1785 void EMU::mute_sound()
1790 void EMU::start_record_sound()
1792 osd->start_record_sound();
1795 void EMU::stop_record_sound()
1797 osd->stop_record_sound();
1800 bool EMU::is_sound_recording()
1802 return osd->now_record_sound;
1805 // ----------------------------------------------------------------------------
1807 // ----------------------------------------------------------------------------
1809 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
1810 void EMU::get_video_buffer()
1812 osd->get_video_buffer();
1815 void EMU::mute_video_dev(bool l, bool r)
1817 osd->mute_video_dev(l, r);
1821 #ifdef USE_MOVIE_PLAYER
1822 bool EMU::open_movie_file(const _TCHAR* file_path)
1824 return osd->open_movie_file(file_path);
1827 void EMU::close_movie_file()
1829 osd->close_movie_file();
1832 void EMU::play_movie()
1837 void EMU::stop_movie()
1842 void EMU::pause_movie()
1847 double EMU::get_movie_frame_rate()
1849 return osd->get_movie_frame_rate();
1852 int EMU::get_movie_sound_rate()
1854 return osd->get_movie_sound_rate();
1857 void EMU::set_cur_movie_frame(int frame, bool relative)
1859 osd->set_cur_movie_frame(frame, relative);
1862 uint32_t EMU::get_cur_movie_frame()
1864 return osd->get_cur_movie_frame();
1868 #ifdef USE_VIDEO_CAPTURE
1869 int EMU::get_cur_capture_dev_index()
1871 return osd->get_cur_capture_dev_index();
1874 int EMU::get_num_capture_devs()
1876 return osd->get_num_capture_devs();
1879 _TCHAR* EMU::get_capture_dev_name(int index)
1881 return osd->get_capture_dev_name(index);
1884 void EMU::open_capture_dev(int index, bool pin)
1886 osd->open_capture_dev(index, pin);
1889 void EMU::close_capture_dev()
1891 osd->close_capture_dev();
1894 void EMU::show_capture_dev_filter()
1896 osd->show_capture_dev_filter();
1899 void EMU::show_capture_dev_pin()
1901 osd->show_capture_dev_pin();
1904 void EMU::show_capture_dev_source()
1906 osd->show_capture_dev_source();
1909 void EMU::set_capture_dev_channel(int ch)
1911 osd->set_capture_dev_channel(ch);
1915 // ----------------------------------------------------------------------------
1917 // ----------------------------------------------------------------------------
1920 void EMU::create_bitmap(bitmap_t *bitmap, int width, int height)
1922 osd->create_bitmap(bitmap, width, height);
1925 void EMU::release_bitmap(bitmap_t *bitmap)
1927 osd->release_bitmap(bitmap);
1930 void EMU::create_font(font_t *font, const _TCHAR *family, int width, int height, int rotate, bool bold, bool italic)
1932 osd->create_font(font, family, width, height, rotate, bold, italic);
1935 void EMU::release_font(font_t *font)
1937 osd->release_font(font);
1940 void EMU::create_pen(pen_t *pen, int width, uint8_t r, uint8_t g, uint8_t b)
1942 osd->create_pen(pen, width, r, g, b);
1945 void EMU::release_pen(pen_t *pen)
1947 osd->release_pen(pen);
1950 void EMU::clear_bitmap(bitmap_t *bitmap, uint8_t r, uint8_t g, uint8_t b)
1952 osd->clear_bitmap(bitmap, r, g, b);
1955 int EMU::get_text_width(bitmap_t *bitmap, font_t *font, const char *text)
1957 return osd->get_text_width(bitmap, font, text);
1960 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)
1962 osd->draw_text_to_bitmap(bitmap, font, x, y, text, r, g, b);
1965 void EMU::draw_line_to_bitmap(bitmap_t *bitmap, pen_t *pen, int sx, int sy, int ex, int ey)
1967 osd->draw_line_to_bitmap(bitmap, pen, sx, sy, ex, ey);
1970 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)
1972 osd->draw_rectangle_to_bitmap(bitmap, x, y, width, height, r, g, b);
1975 void EMU::draw_point_to_bitmap(bitmap_t *bitmap, int x, int y, uint8_t r, uint8_t g, uint8_t b)
1977 osd->draw_point_to_bitmap(bitmap, x, y, r, g, b);
1980 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)
1982 osd->stretch_bitmap(dest, dest_x, dest_y, dest_width, dest_height, source, source_x, source_y, source_width, source_height);
1985 void EMU::write_bitmap_to_file(bitmap_t *bitmap, const _TCHAR *file_path)
1987 osd->write_bitmap_to_file(bitmap, file_path);
1991 // ----------------------------------------------------------------------------
1993 // ----------------------------------------------------------------------------
1996 SOCKET EMU::get_socket(int ch)
1998 return osd->get_socket(ch);
2001 void EMU::notify_socket_connected(int ch)
2003 osd->notify_socket_connected(ch);
2006 void EMU::notify_socket_disconnected(int ch)
2008 osd->notify_socket_disconnected(ch);
2011 bool EMU::initialize_socket_tcp(int ch)
2013 return osd->initialize_socket_tcp(ch);
2016 bool EMU::initialize_socket_udp(int ch)
2018 return osd->initialize_socket_udp(ch);
2021 bool EMU::connect_socket(int ch, uint32_t ipaddr, int port)
2023 return osd->connect_socket(ch, ipaddr, port);
2026 void EMU::disconnect_socket(int ch)
2028 osd->disconnect_socket(ch);
2031 bool EMU::listen_socket(int ch)
2033 return osd->listen_socket(ch);
2036 void EMU::send_socket_data_tcp(int ch)
2038 osd->send_socket_data_tcp(ch);
2041 void EMU::send_socket_data_udp(int ch, uint32_t ipaddr, int port)
2043 osd->send_socket_data_udp(ch, ipaddr, port);
2046 void EMU::send_socket_data(int ch)
2048 osd->send_socket_data(ch);
2051 void EMU::recv_socket_data(int ch)
2053 osd->recv_socket_data(ch);
2057 // ----------------------------------------------------------------------------
2059 // ----------------------------------------------------------------------------
2062 void EMU::send_to_midi(uint8_t data, int ch, double timestamp_usec)
2064 osd->send_to_midi(data, ch, timestamp_usec);
2067 bool EMU::recv_from_midi(uint8_t *data, int ch, double timestamp_usec)
2069 return osd->recv_from_midi(data, ch, timestamp_usec);
2071 // ToDo: Will implement timeout function.
2072 bool EMU::send_to_midi_timeout(uint8_t data, int ch, uint64_t timeout_ms, double timestamp_usec)
2074 // ToDo: will implement handshake.
2075 // Q: Need to check VM's timeout status?
2076 return osd->send_to_midi_timeout(data, ch, timeout_ms, timestamp_usec);
2079 bool EMU::recv_from_midi_timeout(uint8_t* data, int ch, uint64_t timeout_ms, double timestamp_usec)
2081 // ToDo: will implement handshake.
2082 // Q: Need to check VM's timeout status?
2083 return osd->recv_from_midi_timeout(data, ch, timeout_ms, timestamp_usec);
2086 //void EMU::notify_timeout_sending_to_midi(int ch)
2088 // vm->notify_timeout_sending_to_midi(ch);
2090 //void EMU::notify_timeout_receiving_from_midi(int ch)
2092 // vm->notify_timeout_receiving_from_midi(ch);
2095 void EMU::reset_to_midi(int ch, double timestamp_usec)
2097 osd->reset_to_midi(ch, timestamp_usec);
2100 void EMU::initialize_midi_device(bool handshake_from_midi, bool handshake_to_midi, int ch)
2102 osd->initialize_midi_device(handshake_from_midi, handshake_to_midi, ch);
2105 //void EMU::ready_receive_from_midi(int ch, double timestamp_usec)
2107 // vm->ready_receive_from_midi(ch, timestamp_usec);
2110 void EMU::ready_send_to_midi(int ch, double timestamp_usec)
2112 osd->ready_send_to_midi(ch,timestamp_usec);
2115 void EMU::request_stop_to_receive_from_midi(int ch, double timestamp_usec)
2117 osd->request_stop_to_receive_from_midi(ch, timestamp_usec);
2120 //void EMU::request_stop_to_send_to_midi(int ch, double timestamp_usec)
2122 // vm->request_stop_to_send_to_midi(ch, timestamp_usec);
2127 // ---------------------------------------------------------------------------
2128 // debugger (some functions needed by libCSPcommon_vm 20190221 K.O)
2129 // ---------------------------------------------------------------------------
2131 void EMU::start_waiting_in_debugger()
2134 now_waiting_in_debugger = true;
2138 osd->start_waiting_in_debugger();
2142 void EMU::finish_waiting_in_debugger()
2145 osd->finish_waiting_in_debugger();
2146 now_waiting_in_debugger = false;
2147 osd->unmute_sound();
2151 void EMU::process_waiting_in_debugger()
2154 osd->process_waiting_in_debugger();
2160 // ----------------------------------------------------------------------------
2162 // ----------------------------------------------------------------------------
2165 void EMU::initialize_debug_log()
2167 _TCHAR path[_MAX_PATH];
2168 debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
2171 void EMU::release_debug_log()
2181 static _TCHAR prev_buffer[2048] = {0};
2184 void EMU::out_debug_log(const _TCHAR* format, ...)
2186 common_initialize();
2190 _TCHAR buffer[2048];
2192 va_start(ap, format);
2193 my_vstprintf_s(buffer, 2048, format, ap);
2196 if(_tcscmp(prev_buffer, buffer) == 0) {
2199 my_tcscpy_s(prev_buffer, 2048, buffer);
2201 #if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
2202 std::shared_ptr<CSP_Logger> lp = csp_logger;
2203 lp->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_EMU, "%s", buffer);
2206 _ftprintf(debug_log, _T("(%f uS) %s"), vm->get_current_usec(), buffer);
2207 static int size = 0;
2208 if((size += _tcslen(buffer)) > 0x8000000) { // 128MB
2210 debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
2218 void EMU::force_out_debug_log(const _TCHAR* format, ...)
2222 _TCHAR buffer[1024];
2224 va_start(ap, format);
2225 my_vstprintf_s(buffer, 1024, format, ap);
2227 my_tcscpy_s(prev_buffer, 1024, buffer);
2229 #if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
2230 std::shared_ptr<CSP_Logger> lp = csp_logger;
2231 lp->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_EMU, "%s", buffer);
2234 _ftprintf(debug_log, _T("%s"), buffer);
2235 static int size = 0;
2236 if((size += _tcslen(buffer)) > 0x8000000) { // 128MB
2238 debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
2246 void EMU::out_message(const _TCHAR* format, ...)
2248 //#if defined(_USE_QT)
2249 // _TCHAR mes_buf[1024];
2252 va_start(ap, format);
2253 my_vstprintf_s(message, 1024, format, ap); // Security for MSVC:C6386.
2254 //#if defined(_USE_QT)
2255 // memset(mes_buf, 0x00, sizeof(mes_buf));
2256 // my_vstprintf_s(mes_buf, 1024, format, ap); // Security for MSVC:C6386.
2257 // csp_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_EMU, "%s", mes_buf);
2260 message_count = 4; // 4sec
2263 // ----------------------------------------------------------------------------
2265 // ----------------------------------------------------------------------------
2268 void EMU::sleep(uint32_t ms)
2274 // ----------------------------------------------------------------------------
2276 // ----------------------------------------------------------------------------
2278 static uint8_t hex2uint8(char *value)
2281 memset(tmp, 0, sizeof(tmp));
2282 memcpy(tmp, value, 2);
2283 return (uint8_t)strtoul(tmp, NULL, 16);
2286 static uint16_t hex2uint16(char *value)
2289 memset(tmp, 0, sizeof(tmp));
2290 memcpy(tmp, value, 4);
2291 return (uint16_t)strtoul(tmp, NULL, 16);
2294 static bool hex2bin(const _TCHAR* file_path, const _TCHAR* dest_path)
2296 bool result = false;
2297 FILEIO *fio_s = new FILEIO();
2298 if(fio_s->Fopen(file_path, FILEIO_READ_BINARY)) {
2301 uint8_t buffer[0x10000];
2302 memset(buffer, 0xff, sizeof(buffer));
2303 while(fio_s->Fgets(line, sizeof(line)) != NULL) {
2304 if(line[0] != ':') continue;
2305 int bytes = hex2uint8(line + 1);
2306 int offset = hex2uint16(line + 3);
2307 uint8_t record_type = hex2uint8(line + 7);
2308 if(record_type == 0x01) break;
2309 if(record_type != 0x00) continue;
2310 for(int i = 0; i < bytes; i++) {
2311 if((offset + i) < (int)sizeof(buffer)) {
2312 if(length < (offset + i)) {
2313 length = offset + i;
2315 buffer[offset + i] = hex2uint8(line + 9 + 2 * i);
2320 FILEIO *fio_d = new FILEIO();
2321 if(fio_d->Fopen(dest_path, FILEIO_WRITE_BINARY)) {
2322 fio_d->Fwrite(buffer, length, 1);
2334 void EMU::initialize_media()
2337 memset(&cart_status, 0, sizeof(cart_status));
2339 #ifdef USE_FLOPPY_DISK
2340 memset(floppy_disk_status, 0, sizeof(floppy_disk_status));
2342 #ifdef USE_QUICK_DISK
2343 memset(&quick_disk_status, 0, sizeof(quick_disk_status));
2345 #ifdef USE_HARD_DISK
2346 memset(&hard_disk_status, 0, sizeof(hard_disk_status));
2349 memset(&tape_status, 0, sizeof(tape_status));
2351 #ifdef USE_COMPACT_DISC
2352 memset(&compact_disc_status, 0, sizeof(compact_disc_status));
2354 #ifdef USE_LASER_DISC
2355 memset(&laser_disc_status, 0, sizeof(laser_disc_status));
2358 memset(&bubble_casette_status, 0, sizeof(bubble_casette_status));
2362 #if defined(_USE_QT)
2363 extern void DLL_PREFIX_I Convert_CP932_to_UTF8(char *dst, char *src, int n_limit, int i_limit);
2366 void EMU::update_media()
2368 #ifdef USE_FLOPPY_DISK
2369 for(int drv = 0; drv < USE_FLOPPY_DISK; drv++) {
2370 if(floppy_disk_status[drv].wait_count != 0 && --floppy_disk_status[drv].wait_count == 0) {
2371 vm->open_floppy_disk(drv, floppy_disk_status[drv].path, floppy_disk_status[drv].bank & EMU_MEDIA_TYPE::EMU_SLOT_MASK);
2372 #if USE_FLOPPY_DISK > 1
2373 out_message(_T("FD%d: %s"), drv + BASE_FLOPPY_DISK_NUM, floppy_disk_status[drv].path);
2375 out_message(_T("FD: %s"), floppy_disk_status[drv].path);
2377 EMU_MESSAGE_TYPE::type_t mess = EMU_MESSAGE_TYPE::MEDIA_MOUNTED;
2378 mess |= ((is_floppy_disk_protected(drv)) ? EMU_MESSAGE_TYPE::WRITE_PROTECT : 0);
2379 osdcall_string(EMU_MEDIA_TYPE::FLOPPY_DISK | (floppy_disk_status[drv].bank & EMU_MEDIA_TYPE::EMU_SLOT_MASK),
2382 floppy_disk_status[drv].path);
2386 #ifdef USE_QUICK_DISK
2387 for(int drv = 0; drv < USE_QUICK_DISK; drv++) {
2388 if(quick_disk_status[drv].wait_count != 0 && --quick_disk_status[drv].wait_count == 0) {
2389 vm->open_quick_disk(drv, quick_disk_status[drv].path);
2390 #if USE_QUICK_DISK > 1
2391 out_message(_T("QD%d: %s"), drv + BASE_QUICK_DISK_NUM, quick_disk_status[drv].path);
2393 out_message(_T("QD: %s"), quick_disk_status[drv].path);
2395 // ToDo: Write Protect
2396 osdcall_string(EMU_MEDIA_TYPE::QUICK_DISK,
2398 EMU_MESSAGE_TYPE::MEDIA_MOUNTED,
2399 (_TCHAR *)quick_disk_status[drv].path);
2403 #ifdef USE_HARD_DISK
2404 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
2405 if(hard_disk_status[drv].wait_count != 0 && --hard_disk_status[drv].wait_count == 0) {
2406 vm->open_hard_disk(drv, hard_disk_status[drv].path);
2407 #if USE_HARD_DISK > 1
2408 out_message(_T("HD%d: %s"), drv + BASE_HARD_DISK_NUM, hard_disk_status[drv].path);
2410 out_message(_T("HD: %s"), hard_disk_status[drv].path);
2412 osdcall_string(EMU_MEDIA_TYPE::HARD_DISK,
2414 EMU_MESSAGE_TYPE::MEDIA_MOUNTED,
2415 (_TCHAR *)hard_disk_status[drv].path);
2420 for(int drv = 0; drv < USE_TAPE; drv++) {
2421 if(tape_status[drv].wait_count != 0 && --tape_status[drv].wait_count == 0) {
2422 if(tape_status[drv].play) {
2423 vm->play_tape(drv, tape_status[drv].path);
2425 vm->rec_tape(drv, tape_status[drv].path);
2428 out_message(_T("CMT%d: %s"), drv + BASE_TAPE_NUM, tape_status[drv].path);
2430 out_message(_T("CMT: %s"), tape_status[drv].path);
2432 // ToDo: Write protect.
2433 EMU_MESSAGE_TYPE::type_t mess;
2434 mess = (tape_status[drv].play) ? EMU_MESSAGE_TYPE::PLAY : EMU_MESSAGE_TYPE::RECORD;
2435 mess |= EMU_MESSAGE_TYPE::MEDIA_MOUNTED;
2436 osdcall_string(EMU_MEDIA_TYPE::TAPE,
2439 (_TCHAR *)tape_status[drv].path);
2443 #ifdef USE_COMPACT_DISC
2444 for(int drv = 0; drv < USE_COMPACT_DISC; drv++) {
2445 if(compact_disc_status[drv].wait_count != 0 && --compact_disc_status[drv].wait_count == 0) {
2446 vm->open_compact_disc(drv, compact_disc_status[drv].path);
2447 //printf(_T("update_media(): LOAD CDROM: %s\n"), compact_disc_status[drv].path);
2448 #if USE_COMPACT_DISC > 1
2449 out_message(_T("CD%d: %s"), drv + BASE_COMPACT_DISC_NUM, compact_disc_status[drv].path);
2451 out_message(_T("CD: %s"), compact_disc_status[drv].path);
2453 osdcall_string(EMU_MEDIA_TYPE::COMPACT_DISC,
2455 EMU_MESSAGE_TYPE::MEDIA_MOUNTED,
2456 (_TCHAR *)compact_disc_status[drv].path);
2460 #ifdef USE_LASER_DISC
2461 for(int drv = 0; drv < USE_LASER_DISC; drv++) {
2462 if(laser_disc_status[drv].wait_count != 0 && --laser_disc_status[drv].wait_count == 0) {
2463 vm->open_laser_disc(drv, laser_disc_status[drv].path);
2464 #if USE_LASER_DISC > 1
2465 out_message(_T("LD%d: %s"), drv + BASE_LASER_DISC_NUM, laser_disc_status[drv].path);
2467 out_message(_T("LD: %s"), laser_disc_status[drv].path);
2469 osdcall_string(EMU_MEDIA_TYPE::LASER_DISC,
2471 EMU_MESSAGE_TYPE::MEDIA_MOUNTED,
2472 (_TCHAR *)laser_disc_status[drv].path);
2477 for(int drv = 0; drv < USE_BUBBLE; drv++) {
2478 if(bubble_casette_status[drv].wait_count != 0 && --bubble_casette_status[drv].wait_count == 0) {
2479 vm->open_bubble_casette(drv, bubble_casette_status[drv].path, bubble_casette_status[drv].bank & EMU_MEDIA_TYPE::EMU_SLOT_MASK);
2481 out_message(_T("Bubble%d: %s"), drv + BASE_BUBBLE_NUM, bubble_casette_status[drv].path);
2483 out_message(_T("Bubble: %s"), bubble_casette_status[drv].path);
2485 // ToDo: Write protect.
2486 EMU_MESSAGE_TYPE::type_t mess = EMU_MESSAGE_TYPE::MEDIA_MOUNTED;
2487 mess |= ((is_bubble_casette_protected(drv)) ? EMU_MESSAGE_TYPE::WRITE_PROTECT : 0);
2489 osdcall_string(EMU_MEDIA_TYPE::BUBBLE_CASETTE | (bubble_casette_status[drv].bank & EMU_MEDIA_TYPE::EMU_SLOT_MASK),
2492 (_TCHAR *)bubble_casette_status[drv].path);
2498 void EMU::restore_media()
2501 for(int drv = 0; drv < USE_CART; drv++) {
2502 if(cart_status[drv].path[0] != _T('\0')) {
2503 if(check_file_extension(cart_status[drv].path, _T(".hex")) && hex2bin(cart_status[drv].path, create_local_path(_T("hex2bin.$$$")))) {
2504 vm->open_cart(drv, create_local_path(_T("hex2bin.$$$")));
2505 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
2507 vm->open_cart(drv, cart_status[drv].path);
2509 EMU_MESSAGE_TYPE::type_t mess = EMU_MESSAGE_TYPE::MEDIA_MOUNTED;
2510 // ToDo: write protect
2511 osdcall_string(EMU_MEDIA_TYPE::CARTRIDGE,
2514 cart_status[drv].path);
2519 #ifdef USE_FLOPPY_DISK
2520 for(int drv = 0; drv < USE_FLOPPY_DISK; drv++) {
2521 if(floppy_disk_status[drv].path[0] != _T('\0')) {
2522 vm->open_floppy_disk(drv, floppy_disk_status[drv].path, floppy_disk_status[drv].bank & EMU_MEDIA_TYPE::EMU_SLOT_MASK);
2523 EMU_MESSAGE_TYPE::type_t mess = EMU_MESSAGE_TYPE::MEDIA_MOUNTED;
2524 mess |= ((is_floppy_disk_protected(drv)) ? EMU_MESSAGE_TYPE::WRITE_PROTECT : 0);
2525 osdcall_string(EMU_MEDIA_TYPE::FLOPPY_DISK | (floppy_disk_status[drv].bank & EMU_MEDIA_TYPE::EMU_SLOT_MASK),
2528 floppy_disk_status[drv].path);
2532 #ifdef USE_QUICK_DISK
2533 for(int drv = 0; drv < USE_QUICK_DISK; drv++) {
2534 if(quick_disk_status[drv].path[0] != _T('\0')) {
2535 vm->open_quick_disk(drv, quick_disk_status[drv].path);
2537 EMU_MESSAGE_TYPE::type_t mess = EMU_MESSAGE_TYPE::MEDIA_MOUNTED;
2538 // ToDo: write protect
2539 osdcall_string(EMU_MEDIA_TYPE::QUICK_DISK,
2542 quick_disk_status[drv].path);
2546 #ifdef USE_HARD_DISK
2547 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
2548 if(hard_disk_status[drv].path[0] != _T('\0')) {
2549 vm->open_hard_disk(drv, hard_disk_status[drv].path);
2550 EMU_MESSAGE_TYPE::type_t mess = EMU_MESSAGE_TYPE::MEDIA_MOUNTED;
2551 osdcall_string(EMU_MEDIA_TYPE::HARD_DISK,
2554 quick_disk_status[drv].path);
2559 for(int drv = 0; drv < USE_TAPE; drv++) {
2560 if(tape_status[drv].path[0] != _T('\0')) {
2561 if(tape_status[drv].play) {
2562 vm->play_tape(drv, tape_status[drv].path);
2563 EMU_MESSAGE_TYPE::type_t mess = EMU_MESSAGE_TYPE::MEDIA_MOUNTED;
2564 osdcall_string(EMU_MEDIA_TYPE::TAPE,
2567 tape_status[drv].path);
2569 tape_status[drv].path[0] = _T('\0');
2574 #ifdef USE_COMPACT_DISC
2575 for(int drv = 0; drv < USE_COMPACT_DISC; drv++) {
2576 if(compact_disc_status[drv].path[0] != _T('\0')) {
2577 vm->open_compact_disc(drv, compact_disc_status[drv].path);
2578 //printf(_T("restore_media(): LOAD CDROM: %s\n"), compact_disc_status[drv].path);
2579 osdcall_string(EMU_MEDIA_TYPE::COMPACT_DISC,
2581 EMU_MESSAGE_TYPE::MEDIA_MOUNTED,
2582 (_TCHAR*)compact_disc_status[drv].path);
2586 #ifdef USE_LASER_DISC
2587 for(int drv = 0; drv < USE_LASER_DISC; drv++) {
2588 if(laser_disc_status[drv].path[0] != _T('\0')) {
2589 vm->open_laser_disc(drv, laser_disc_status[drv].path);
2590 osdcall_string(EMU_MEDIA_TYPE::LASER_DISC,
2592 EMU_MESSAGE_TYPE::MEDIA_MOUNTED,
2593 laser_disc_status[drv].path);
2598 for(int drv = 0; drv < USE_BUBBLE; drv++) {
2599 if(bubble_casette_status[drv].path[0] != _T('\0')) {
2600 vm->open_bubble_casette(drv, bubble_casette_status[drv].path, bubble_casette_status[drv].bank);
2601 EMU_MESSAGE_TYPE::type_t mess = EMU_MESSAGE_TYPE::MEDIA_MOUNTED;
2602 mess |= ((is_bubble_casette_protected(drv)) ? EMU_MESSAGE_TYPE::WRITE_PROTECT : 0);
2604 osdcall_string(EMU_MEDIA_TYPE::BUBBLE_CASETTE | (bubble_casette_status[drv].bank & EMU_MEDIA_TYPE::EMU_SLOT_MASK),
2607 (_TCHAR *)bubble_casette_status[drv].path);
2614 void EMU::open_cart(int drv, const _TCHAR* file_path)
2616 if(drv < USE_CART) {
2617 if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, create_local_path(_T("hex2bin.$$$")))) {
2618 vm->open_cart(drv, create_local_path(_T("hex2bin.$$$")));
2619 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
2621 vm->open_cart(drv, file_path);
2623 my_tcscpy_s(cart_status[drv].path, _MAX_PATH, file_path);
2624 out_message(_T("Cart%d: %s"), drv + 1, file_path);
2625 osdcall_string(EMU_MEDIA_TYPE::CARTRIDGE,
2627 EMU_MESSAGE_TYPE::MEDIA_MOUNTED,
2628 (_TCHAR *)file_path);
2629 #if !defined(_USE_QT)
2630 // restart recording
2631 bool s = osd->now_record_sound;
2632 bool v = osd->now_record_video;
2633 stop_record_sound();
2634 stop_record_video();
2636 if(s) osd->start_record_sound();
2637 if(v) osd->start_record_video(-1);
2642 void EMU::close_cart(int drv)
2644 if(drv < USE_CART) {
2645 vm->close_cart(drv);
2646 clear_media_status(&cart_status[drv]);
2648 out_message(_T("Cart%d: Ejected"), drv + BASE_CART_NUM);
2650 out_message(_T("Cart: Ejected"));
2652 osdcall_int(EMU_MEDIA_TYPE::CARTRIDGE,
2654 EMU_MESSAGE_TYPE::MEDIA_REMOVED,
2656 #if !defined(_USE_QT)
2658 stop_record_video();
2659 stop_record_sound();
2664 bool EMU::is_cart_inserted(int drv)
2666 if(drv < USE_CART) {
2667 return vm->is_cart_inserted(drv);
2674 #ifdef USE_FLOPPY_DISK
2675 bool EMU::create_blank_floppy_disk(const _TCHAR* file_path, uint8_t type)
2678 type: 0x00 = 2D, 0x10 = 2DD, 0x20 = 2HD
2686 uint32_t trkptr[164];
2689 memset(&d88_hdr, 0, sizeof(d88_hdr));
2690 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "BLANK");
2691 d88_hdr.type = type;
2692 d88_hdr.size = sizeof(d88_hdr);
2694 FILEIO *fio = new FILEIO();
2695 if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
2696 fio->Fwrite(&d88_hdr, sizeof(d88_hdr), 1);
2703 void EMU::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
2705 if(drv < USE_FLOPPY_DISK) {
2706 d88_file[drv].bank_num = 0;
2707 d88_file[drv].cur_bank = -1;
2708 if(check_file_extension(file_path, _T(".d88")) || check_file_extension(file_path, _T(".d77")) || check_file_extension(file_path, _T(".1dd"))) {
2709 FILEIO *fio = new FILEIO();
2710 if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
2712 fio->Fseek(0, FILEIO_SEEK_END);
2713 uint32_t file_size = fio->Ftell(), file_offset = 0;
2714 while(file_offset + 0x2b0 <= file_size && d88_file[drv].bank_num < MAX_D88_BANKS) {
2715 fio->Fseek(file_offset, FILEIO_SEEK_SET);
2718 fio->Fread(tmp, 17, 1);
2720 #if defined(_USE_QT)
2721 memset(d88_file[drv].disk_name[d88_file[drv].bank_num], 0x00, 128);
2722 if(strlen(tmp) > 0) {
2723 Convert_CP932_to_UTF8(d88_file[drv].disk_name[d88_file[drv].bank_num], tmp, 127, 17);
2725 #else /* not _USE_QT */
2726 MultiByteToWideChar(CP_ACP, 0, tmp, -1, d88_file[drv].disk_name[d88_file[drv].bank_num], 18);
2729 fio->Fread(d88_file[drv].disk_name[d88_file[drv].bank_num], 17, 1);
2730 d88_file[drv].disk_name[d88_file[drv].bank_num][17] = 0;
2732 fio->Fseek(file_offset + 0x1c, FILEIO_SEEK_SET);
2733 file_offset += fio->FgetUint32_LE();
2734 d88_file[drv].bank_num++;
2736 my_tcscpy_s(d88_file[drv].path, _MAX_PATH, file_path);
2737 d88_file[drv].cur_bank = bank & EMU_MEDIA_TYPE::EMU_SLOT_MASK;
2739 d88_file[drv].bank_num = 0;
2746 if(vm->is_floppy_disk_inserted(drv)) {
2747 vm->close_floppy_disk(drv);
2749 floppy_disk_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2750 #if USE_FLOPPY_DISK > 1
2751 out_message(_T("FD%d: Ejected"), drv + BASE_FLOPPY_DISK_NUM);
2753 out_message(_T("FD: Ejected"));
2755 osdcall_int(EMU_MEDIA_TYPE::FLOPPY_DISK,
2757 EMU_MESSAGE_TYPE::MEDIA_REMOVED,
2759 } else if(floppy_disk_status[drv].wait_count == 0) {
2760 vm->open_floppy_disk(drv, file_path, bank & EMU_MEDIA_TYPE::EMU_SLOT_MASK);
2761 #if USE_FLOPPY_DISK > 1
2762 out_message(_T("FD%d: %s"), drv + BASE_FLOPPY_DISK_NUM, file_path);
2764 out_message(_T("FD: %s"), file_path);
2766 EMU_MESSAGE_TYPE::type_t mess = EMU_MESSAGE_TYPE::MEDIA_MOUNTED;
2767 mess |= ((is_floppy_disk_protected(drv)) ? EMU_MESSAGE_TYPE::WRITE_PROTECT : 0);
2768 osdcall_string(EMU_MEDIA_TYPE::FLOPPY_DISK | (bank & EMU_MEDIA_TYPE::MULTIPLE_SLOT_MASK),
2771 (_TCHAR *)file_path);
2773 my_tcscpy_s(floppy_disk_status[drv].path, _MAX_PATH, file_path);
2774 floppy_disk_status[drv].bank = bank;
2779 void EMU::close_floppy_disk(int drv)
2781 if(drv < USE_FLOPPY_DISK) {
2782 d88_file[drv].bank_num = 0;
2783 d88_file[drv].cur_bank = -1;
2785 vm->close_floppy_disk(drv);
2786 clear_media_status(&floppy_disk_status[drv]);
2787 #if USE_FLOPPY_DISK > 1
2788 out_message(_T("FD%d: Ejected"), drv + BASE_FLOPPY_DISK_NUM);
2790 out_message(_T("FD: Ejected"));
2792 osdcall_int(EMU_MEDIA_TYPE::FLOPPY_DISK,
2794 EMU_MESSAGE_TYPE::MEDIA_REMOVED,
2799 bool EMU::is_floppy_disk_connected(int drv)
2801 if(drv < USE_FLOPPY_DISK) {
2802 return vm->is_floppy_disk_connected(drv);
2808 bool EMU::is_floppy_disk_inserted(int drv)
2810 if(drv < USE_FLOPPY_DISK) {
2811 return vm->is_floppy_disk_inserted(drv);
2817 void EMU::is_floppy_disk_protected(int drv, bool value)
2819 if(drv < USE_FLOPPY_DISK) {
2820 vm->is_floppy_disk_protected(drv, value);
2822 EMU_MESSAGE_TYPE::type_t mess =
2824 (EMU_MESSAGE_TYPE::WRITE_PROTECT | EMU_MESSAGE_TYPE::MEDIA_OTHERS)
2825 : EMU_MESSAGE_TYPE::MEDIA_OTHERS;
2826 osdcall_int(EMU_MEDIA_TYPE::FLOPPY_DISK,
2832 bool EMU::is_floppy_disk_protected(int drv)
2834 if(drv < USE_FLOPPY_DISK) {
2835 return vm->is_floppy_disk_protected(drv);
2841 uint32_t EMU::is_floppy_disk_accessed()
2843 return vm->is_floppy_disk_accessed();
2846 uint32_t EMU::floppy_disk_indicator_color()
2848 return vm->floppy_disk_indicator_color();
2853 #ifdef USE_QUICK_DISK
2854 void EMU::open_quick_disk(int drv, const _TCHAR* file_path)
2856 if(drv < USE_QUICK_DISK) {
2857 if(vm->is_quick_disk_inserted(drv)) {
2858 vm->close_quick_disk(drv);
2860 quick_disk_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2861 #if USE_QUICK_DISK > 1
2862 out_message(_T("QD%d: Ejected"), drv + BASE_QUICK_DISK_NUM);
2864 out_message(_T("QD: Ejected"));
2866 osdcall_int(EMU_MEDIA_TYPE::QUICK_DISK,
2868 EMU_MESSAGE_TYPE::MEDIA_REMOVED,
2870 } else if(quick_disk_status[drv].wait_count == 0) {
2871 vm->open_quick_disk(drv, file_path);
2872 #if USE_QUICK_DISK > 1
2873 out_message(_T("QD%d: %s"), drv + BASE_QUICK_DISK_NUM, file_path);
2875 out_message(_T("QD: %s"), file_path);
2877 osdcall_string(EMU_MEDIA_TYPE::QUICK_DISK,
2879 EMU_MESSAGE_TYPE::MEDIA_MOUNTED,
2880 (_TCHAR*)file_path);
2882 my_tcscpy_s(quick_disk_status[drv].path, _MAX_PATH, file_path);
2886 void EMU::close_quick_disk(int drv)
2888 if(drv < USE_QUICK_DISK) {
2889 vm->close_quick_disk(drv);
2890 clear_media_status(&quick_disk_status[drv]);
2891 #if USE_QUICK_DISK > 1
2892 out_message(_T("QD%d: Ejected"), drv + BASE_QUICK_DISK_NUM);
2894 out_message(_T("QD: Ejected"));
2896 osdcall_int(EMU_MEDIA_TYPE::QUICK_DISK,
2898 EMU_MESSAGE_TYPE::MEDIA_REMOVED,
2903 bool EMU::is_quick_disk_inserted(int drv)
2905 if(drv < USE_QUICK_DISK) {
2906 return vm->is_quick_disk_inserted(drv);
2912 bool EMU::is_quick_disk_connected(int drv)
2914 if(drv < USE_QUICK_DISK) {
2915 return vm->is_quick_disk_connected(drv);
2921 uint32_t EMU::is_quick_disk_accessed()
2923 return vm->is_quick_disk_accessed();
2927 #ifdef USE_HARD_DISK
2928 bool EMU::create_blank_hard_disk(const _TCHAR* file_path, int sector_size, int sectors, int surfaces, int cylinders)
2930 if(check_file_extension(file_path, _T(".nhd"))) {
2932 const char sig_nhd[] = "T98HDDIMAGE.R0";
2933 typedef struct nhd_header_s {
2936 int32_t header_size; // +272
2937 int32_t cylinders; // +276
2938 int16_t surfaces; // +280
2939 int16_t sectors; // +282
2940 int16_t sector_size; // +284
2941 uint8_t reserved[0xe2];
2943 nhd_header_t header;
2945 memset(&header, 0, sizeof(header));
2946 strcpy(header.sig, "T98HDDIMAGE.R0");
2947 header.header_size = sizeof(header);
2948 header.cylinders = cylinders;
2949 header.surfaces = surfaces;
2950 header.sectors = sectors;
2951 header.sector_size = sector_size;
2953 FILEIO *fio = new FILEIO();
2954 if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
2955 fio->Fwrite(&header, sizeof(header), 1);
2956 void *empty = calloc(sector_size, 1);
2958 fio->Fwrite(empty, sector_size, sectors * surfaces * cylinders);
2960 for(int i = 0; i < sectors * surfaces * cylinders; i++) {
2961 fio->Fwrite(empty, sector_size, 1);
2969 } else if(check_file_extension(file_path, _T(".hdi"))) {
2971 typedef struct hdi_header_s {
2972 int32_t dummy; // + 0
2973 int32_t hdd_type; // + 4
2974 int32_t header_size; // + 8
2975 int32_t hdd_size; // +12
2976 int32_t sector_size; // +16
2977 int32_t sectors; // +20
2978 int32_t surfaces; // +24
2979 int32_t cylinders; // +28
2980 uint8_t padding[0x1000 - sizeof(int32_t) * 8];
2982 hdi_header_t header;
2984 memset(&header, 0, sizeof(header));
2985 header.hdd_type = 0; // ???
2986 header.header_size = sizeof(header);
2987 header.hdd_size = sector_size * sectors * surfaces * cylinders;
2988 header.sector_size = sector_size;
2989 header.sectors = sectors;
2990 header.surfaces = surfaces;
2991 header.cylinders = cylinders;
2993 FILEIO *fio = new FILEIO();
2994 if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
2995 fio->Fwrite(&header, sizeof(header), 1);
2996 void *empty = calloc(sector_size, 1);
2998 fio->Fwrite(empty, sector_size, sectors * surfaces * cylinders);
3000 for(int i = 0; i < sectors * surfaces * cylinders; i++) {
3001 fio->Fwrite(empty, sector_size, 1);
3010 // unknown extension
3014 void EMU::open_hard_disk(int drv, const _TCHAR* file_path)
3016 if(drv < USE_HARD_DISK) {
3017 if(vm->is_hard_disk_inserted(drv)) {
3018 vm->close_hard_disk(drv);
3020 hard_disk_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
3021 #if USE_HARD_DISK > 1
3022 out_message(_T("HD%d: Unmounted"), drv + BASE_HARD_DISK_NUM);
3024 out_message(_T("HD: Unmounted"));
3026 osdcall_int(EMU_MEDIA_TYPE::HARD_DISK,
3028 EMU_MESSAGE_TYPE::MEDIA_REMOVED,
3030 } else if(hard_disk_status[drv].wait_count == 0) {
3031 vm->open_hard_disk(drv, file_path);
3032 #if USE_HARD_DISK > 1
3033 out_message(_T("HD%d: %s"), drv + BASE_HARD_DISK_NUM, file_path);
3035 out_message(_T("HD: %s"), file_path);
3037 osdcall_string(EMU_MEDIA_TYPE::HARD_DISK,
3039 EMU_MESSAGE_TYPE::MEDIA_MOUNTED,
3040 (_TCHAR*)file_path);
3042 my_tcscpy_s(hard_disk_status[drv].path, _MAX_PATH, file_path);
3043 my_tcscpy_s(config.last_hard_disk_path[drv], _MAX_PATH, file_path);
3047 void EMU::close_hard_disk(int drv)
3049 if(drv < USE_HARD_DISK) {
3050 vm->close_hard_disk(drv);
3051 clear_media_status(&hard_disk_status[drv]);
3052 #if USE_HARD_DISK > 1
3053 out_message(_T("HD%d: Unmounted"), drv + BASE_HARD_DISK_NUM);
3055 out_message(_T("HD: Unmounted"));
3057 osdcall_int(EMU_MEDIA_TYPE::HARD_DISK,
3059 EMU_MESSAGE_TYPE::MEDIA_REMOVED,
3061 config.last_hard_disk_path[drv][0] = '\0';
3065 bool EMU::is_hard_disk_inserted(int drv)
3067 if(drv < USE_HARD_DISK) {
3068 return vm->is_hard_disk_inserted(drv);
3074 uint32_t EMU::is_hard_disk_accessed()
3076 return vm->is_hard_disk_accessed();
3082 void EMU::play_tape(int drv, const _TCHAR* file_path)
3084 if(drv < USE_TAPE) {
3085 if(vm->is_tape_inserted(drv)) {
3086 vm->close_tape(drv);
3088 tape_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
3090 out_message(_T("CMT%d: Ejected"), drv + BASE_TAPE_NUM);
3092 out_message(_T("CMT: Ejected"));
3094 osdcall_int(EMU_MEDIA_TYPE::TAPE,
3096 EMU_MESSAGE_TYPE::MEDIA_REMOVED,
3098 } else if(tape_status[drv].wait_count == 0) {
3099 vm->play_tape(drv, file_path);
3101 out_message(_T("CMT%d: %s"), drv + BASE_TAPE_NUM, file_path);
3103 out_message(_T("CMT: %s"), file_path);
3105 osdcall_string(EMU_MEDIA_TYPE::TAPE,
3107 EMU_MESSAGE_TYPE::MEDIA_MOUNTED,
3108 (_TCHAR*)file_path);
3110 my_tcscpy_s(tape_status[drv].path, _MAX_PATH, file_path);
3111 tape_status[drv].play = true;
3115 void EMU::rec_tape(int drv, const _TCHAR* file_path)
3117 if(drv < USE_TAPE) {
3118 if(vm->is_tape_inserted(drv)) {
3119 vm->close_tape(drv);
3121 tape_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
3123 out_message(_T("CMT%d: Ejected"), drv + BASE_TAPE_NUM);
3125 out_message(_T("CMT: Ejected"));
3127 osdcall_int(EMU_MEDIA_TYPE::TAPE,
3129 EMU_MESSAGE_TYPE::MEDIA_REMOVED,
3131 } else if(tape_status[drv].wait_count == 0) {
3132 vm->rec_tape(drv, file_path);
3134 out_message(_T("CMT%d: %s"), drv + BASE_TAPE_NUM, file_path);
3136 out_message(_T("CMT: %s"), file_path);
3138 osdcall_string(EMU_MEDIA_TYPE::TAPE,
3140 EMU_MESSAGE_TYPE::MEDIA_MOUNTED | EMU_MESSAGE_TYPE::RECORD,
3141 (_TCHAR*)file_path);
3143 my_tcscpy_s(tape_status[drv].path, _MAX_PATH, file_path);
3144 tape_status[drv].play = false;
3148 void EMU::close_tape(int drv)
3150 if(drv < USE_TAPE) {
3151 vm->close_tape(drv);
3152 clear_media_status(&tape_status[drv]);
3154 out_message(_T("CMT%d: Ejected"), drv + BASE_TAPE_NUM);
3156 out_message(_T("CMT: Ejected"));
3158 osdcall_int(EMU_MEDIA_TYPE::TAPE,
3160 EMU_MESSAGE_TYPE::MEDIA_REMOVED,
3165 bool EMU::is_tape_inserted(int drv)
3167 if(drv < USE_TAPE) {
3168 return vm->is_tape_inserted(drv);
3174 bool EMU::is_tape_playing(int drv)
3176 if(drv < USE_TAPE) {
3177 return vm->is_tape_playing(drv);
3183 bool EMU::is_tape_recording(int drv)
3185 if(drv < USE_TAPE) {
3186 return vm->is_tape_recording(drv);
3192 int EMU::get_tape_position(int drv)
3194 if(drv < USE_TAPE) {
3195 return vm->get_tape_position(drv);
3201 const _TCHAR* EMU::get_tape_message(int drv)
3203 if(drv < USE_TAPE) {
3204 return vm->get_tape_message(drv);
3210 void EMU::push_play(int drv)
3212 if(drv < USE_TAPE) {
3214 osdcall_int(EMU_MEDIA_TYPE::TAPE,
3216 EMU_MESSAGE_TYPE::TAPE_PLAY,
3221 void EMU::push_stop(int drv)
3223 if(drv < USE_TAPE) {
3225 osdcall_int(EMU_MEDIA_TYPE::TAPE,
3227 EMU_MESSAGE_TYPE::TAPE_STOP,
3232 void EMU::push_fast_forward(int drv)
3234 if(drv < USE_TAPE) {
3235 vm->push_fast_forward(drv);
3236 osdcall_int(EMU_MEDIA_TYPE::TAPE,
3238 EMU_MESSAGE_TYPE::TAPE_FF,
3243 void EMU::push_fast_rewind(int drv)
3245 if(drv < USE_TAPE) {
3246 vm->push_fast_rewind(drv);
3247 osdcall_int(EMU_MEDIA_TYPE::TAPE,
3249 EMU_MESSAGE_TYPE::TAPE_REW,
3254 void EMU::push_apss_forward(int drv)
3256 if(drv < USE_TAPE) {
3257 vm->push_apss_forward(drv);
3258 osdcall_int(EMU_MEDIA_TYPE::TAPE,
3260 EMU_MESSAGE_TYPE::TAPE_APSS_FF,
3265 void EMU::push_apss_rewind(int drv)
3267 if(drv < USE_TAPE) {
3268 vm->push_apss_rewind(drv);
3269 osdcall_int(EMU_MEDIA_TYPE::TAPE,
3271 EMU_MESSAGE_TYPE::TAPE_APSS_REW,
3277 #ifdef USE_COMPACT_DISC
3278 void EMU::open_compact_disc(int drv, const _TCHAR* file_path)
3280 if(drv < USE_COMPACT_DISC) {
3281 //printf(_T("open_compact_disc(): CALLED: %s\n"), file_path);
3282 if(vm->is_compact_disc_inserted(drv)) {
3283 vm->close_compact_disc(drv);
3285 clear_media_status(&compact_disc_status[drv]);
3286 compact_disc_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
3287 #if USE_COMPACT_DISC > 1
3288 out_message(_T("CD%d: Ejected"), drv + BASE_COMPACT_DISC_NUM);
3290 out_message(_T("CD: Ejected"));
3292 osdcall_int(EMU_MEDIA_TYPE::COMPACT_DISC,
3294 EMU_MESSAGE_TYPE::MEDIA_REMOVED,
3296 } else if(compact_disc_status[drv].wait_count == 0) {
3297 vm->open_compact_disc(drv, file_path);
3298 //printf(_T("open_compact_disc(): LOAD CDROM: %s\n"), file_path);
3299 #if USE_COMPACT_DISC > 1
3300 out_message(_T("CD%d: %s"), drv + BASE_COMPACT_DISC_NUM, file_path);
3302 out_message(_T("CD: %s"), file_path);
3304 osdcall_string(EMU_MEDIA_TYPE::COMPACT_DISC,
3306 EMU_MESSAGE_TYPE::MEDIA_MOUNTED,
3307 (_TCHAR*)file_path);
3309 my_tcscpy_s(compact_disc_status[drv].path, _MAX_PATH, file_path);
3313 void EMU::close_compact_disc(int drv)
3315 if(drv < USE_COMPACT_DISC) {
3316 vm->close_compact_disc(drv);
3317 clear_media_status(&compact_disc_status[drv]);
3318 compact_disc_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
3319 #if USE_COMPACT_DISC > 1
3320 out_message(_T("CD%d: Ejected"), drv + BASE_COMPACT_DISC_NUM);
3322 out_message(_T("CD: Ejected"));
3324 osdcall_int(EMU_MEDIA_TYPE::COMPACT_DISC,
3326 EMU_MESSAGE_TYPE::MEDIA_REMOVED,
3331 bool EMU::is_compact_disc_inserted(int drv)
3333 if(drv < USE_COMPACT_DISC) {
3334 return vm->is_compact_disc_inserted(drv);
3340 uint32_t EMU::is_compact_disc_accessed()
3342 return vm->is_compact_disc_accessed();
3346 #ifdef USE_LASER_DISC
3347 void EMU::open_laser_disc(int drv, const _TCHAR* file_path)
3349 if(drv < USE_LASER_DISC) {
3350 if(vm->is_laser_disc_inserted(drv)) {
3351 vm->close_laser_disc(drv);
3353 laser_disc_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
3354 #if USE_LASER_DISC > 1
3355 out_message(_T("LD%d: Ejected"), drv + BASE_LASER_DISC_NUM);
3357 out_message(_T("LD: Ejected"));
3359 osdcall_int(EMU_MEDIA_TYPE::LASER_DISC,
3361 EMU_MESSAGE_TYPE::MEDIA_REMOVED,
3363 } else if(laser_disc_status[drv].wait_count == 0) {
3364 vm->open_laser_disc(drv, file_path);
3365 #if USE_LASER_DISC > 1
3366 out_message(_T("LD%d: %s"), drv + BASE_LASER_DISC_NUM, file_path);
3368 out_message(_T("LD: %s"), file_path);
3370 osdcall_string(EMU_MEDIA_TYPE::LASER_DISC,
3372 EMU_MESSAGE_TYPE::MEDIA_MOUNTED,
3373 (_TCHAR*)file_path);
3375 my_tcscpy_s(laser_disc_status[drv].path, _MAX_PATH, file_path);
3379 void EMU::close_laser_disc(int drv)
3381 if(drv < USE_LASER_DISC) {
3382 vm->close_laser_disc(drv);
3383 clear_media_status(&laser_disc_status[drv]);
3384 #if USE_LASER_DISC > 1
3385 out_message(_T("LD%d: Ejected"), drv + BASE_LASER_DISC_NUM);
3387 out_message(_T("LD: Ejected"));
3389 osdcall_int(EMU_MEDIA_TYPE::LASER_DISC,
3391 EMU_MESSAGE_TYPE::MEDIA_REMOVED,
3396 bool EMU::is_laser_disc_inserted(int drv)
3398 if(drv < USE_LASER_DISC) {
3399 return vm->is_laser_disc_inserted(drv);
3405 uint32_t EMU::is_laser_disc_accessed()
3407 return vm->is_laser_disc_accessed();
3412 #ifdef USE_BINARY_FILE
3413 void EMU::load_binary(int drv, const _TCHAR* file_path)
3415 if(drv < USE_BINARY_FILE) {
3416 if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, create_local_path(_T("hex2bin.$$$")))) {
3417 vm->load_binary(drv, create_local_path(_T("hex2bin.$$$")));
3418 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
3420 vm->load_binary(drv, file_path);
3422 osdcall_string(EMU_MEDIA_TYPE::BINARY,
3424 EMU_MESSAGE_TYPE::MEDIA_MOUNTED | EMU_MESSAGE_TYPE::LOAD,
3425 (_TCHAR*)file_path);
3426 #if USE_BINARY_FILE > 1
3427 out_message(_T("Load Binary%d: %s"), drv + BASE_BINARY_FILE_NUM, file_path);
3429 out_message(_T("Load Binary: %s"), file_path);
3434 void EMU::save_binary(int drv, const _TCHAR* file_path)
3436 if(drv < USE_BINARY_FILE) {
3437 vm->save_binary(drv, file_path);
3438 #if USE_BINARY_FILE > 1
3439 out_message(_T("Save Binary%d: %s"), drv + BASE_BINARY_FILE_NUM, file_path);
3441 out_message(_T("Save Binary: %s"), file_path);
3443 osdcall_string(EMU_MEDIA_TYPE::BINARY,
3445 EMU_MESSAGE_TYPE::MEDIA_MOUNTED | EMU_MESSAGE_TYPE::SAVE,
3446 (_TCHAR*)file_path);
3452 void EMU::open_bubble_casette(int drv, const _TCHAR* file_path, int bank)
3454 if(drv < USE_BUBBLE) {
3455 if(vm->is_bubble_casette_inserted(drv)) {
3456 vm->close_bubble_casette(drv);
3458 bubble_casette_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
3460 out_message(_T("Bubble%d: Ejected"), drv + BASE_BUBBLE_NUM);
3462 out_message(_T("Bubble: Ejected"));
3464 osdcall_int(EMU_MEDIA_TYPE::BUBBLE_CASETTE,
3466 EMU_MESSAGE_TYPE::MEDIA_REMOVED,
3468 } else if(bubble_casette_status[drv].wait_count == 0) {
3469 vm->open_bubble_casette(drv, file_path, bank);
3471 out_message(_T("Bubble%d: %s"), drv + BASE_BUBBLE_NUM, file_path);
3473 out_message(_T("Bubble: %s"), file_path);
3475 EMU_MESSAGE_TYPE::type_t mess = EMU_MESSAGE_TYPE::MEDIA_MOUNTED;
3476 mess |= ((is_bubble_casette_protected(drv)) ? EMU_MESSAGE_TYPE::WRITE_PROTECT : 0);
3477 osdcall_string(EMU_MEDIA_TYPE::BUBBLE_CASETTE | (bank & EMU_MEDIA_TYPE::MULTIPLE_SLOT_MASK),
3480 (_TCHAR*)file_path);
3482 my_tcscpy_s(bubble_casette_status[drv].path, _MAX_PATH, file_path);
3483 bubble_casette_status[drv].bank = bank;
3487 void EMU::close_bubble_casette(int drv)
3489 if(drv < USE_BUBBLE) {
3490 vm->close_bubble_casette(drv);
3491 clear_media_status(&bubble_casette_status[drv]);
3493 out_message(_T("Bubble%d: Ejected"), drv + BASE_BUBBLE_NUM);
3495 out_message(_T("Bubble: Ejected"));
3497 osdcall_int(EMU_MEDIA_TYPE::BUBBLE_CASETTE,
3499 EMU_MESSAGE_TYPE::MEDIA_REMOVED,
3504 bool EMU::is_bubble_casette_inserted(int drv)
3506 if(drv < USE_BUBBLE) {
3507 return vm->is_bubble_casette_inserted(drv);
3513 bool EMU::is_bubble_casette_protected(int drv)
3515 if(drv < USE_BUBBLE) {
3516 return vm->is_bubble_casette_protected(drv);
3522 void EMU::is_bubble_casette_protected(int drv, bool flag)
3524 if(drv < USE_BUBBLE) {
3525 vm->is_bubble_casette_protected(drv, flag);
3526 EMU_MESSAGE_TYPE::type_t mess = EMU_MESSAGE_TYPE::MEDIA_OTHERS;
3527 mess |= ((flag) ? EMU_MESSAGE_TYPE::WRITE_PROTECT : 0);
3528 osdcall_int(EMU_MEDIA_TYPE::BUBBLE_CASETTE,
3539 #ifdef USE_LED_DEVICE
3540 uint32_t EMU::get_led_status()
3542 return vm->get_led_status();
3547 #ifdef USE_SOUND_VOLUME
3548 void EMU::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
3550 vm->set_sound_device_volume(ch, decibel_l, decibel_r);
3554 void EMU::update_config()
3556 vm->update_config();
3560 // ----------------------------------------------------------------------------
3562 // ----------------------------------------------------------------------------
3565 #define STATE_VERSION 2
3567 void EMU::save_state(const _TCHAR* file_path)
3569 FILEIO* fio = new FILEIO();
3572 if(config.compress_state) {
3573 fio->Gzopen(file_path, FILEIO_WRITE_BINARY);
3576 if(!fio->IsOpened()) {
3577 fio->Fopen(file_path, FILEIO_WRITE_BINARY);
3579 if(fio->IsOpened()) {
3580 // save state file version
3581 fio->FputUint32(STATE_VERSION);
3583 process_config_state((void *)fio, false);
3584 // save inserted medias
3586 fio->Fwrite(&cart_status, sizeof(cart_status), 1);
3588 #ifdef USE_FLOPPY_DISK
3589 fio->Fwrite(floppy_disk_status, sizeof(floppy_disk_status), 1);
3590 fio->Fwrite(d88_file, sizeof(d88_file), 1);
3592 #ifdef USE_QUICK_DISK
3593 fio->Fwrite(&quick_disk_status, sizeof(quick_disk_status), 1);
3595 #ifdef USE_HARD_DISK
3596 fio->Fwrite(&hard_disk_status, sizeof(hard_disk_status), 1);
3599 fio->Fwrite(&tape_status, sizeof(tape_status), 1);
3601 #ifdef USE_COMPACT_DISC
3602 fio->Fwrite(&compact_disc_status, sizeof(compact_disc_status), 1);
3604 #ifdef USE_LASER_DISC
3605 fio->Fwrite(&laser_disc_status, sizeof(laser_disc_status), 1);
3608 fio->Fwrite(&bubble_casette_status, sizeof(bubble_casette_status), 1);
3611 vm->process_state(fio, false);
3612 // end of state file
3613 fio->FputInt32_LE(-1);
3620 void EMU::load_state(const _TCHAR* file_path)
3622 if(FILEIO::IsFileExisting(file_path)) {
3625 config.romaji_to_kana = false;
3628 save_state(create_local_path(_T("$temp$.sta")));
3629 if(!load_state_tmp(file_path)) {
3630 out_debug_log(_T("failed to load state file\n"));
3631 load_state_tmp(create_local_path(_T("$temp$.sta")));
3633 FILEIO::RemoveFile(create_local_path(_T("$temp$.sta")));
3637 bool EMU::load_state_tmp(const _TCHAR* file_path)
3639 bool result = false;
3640 FILEIO* fio = new FILEIO();
3643 if(config.compress_state) {
3644 fio->Gzopen(file_path, FILEIO_READ_BINARY);
3647 if(!fio->IsOpened()) {
3648 fio->Fopen(file_path, FILEIO_READ_BINARY);
3650 if(fio->IsOpened()) {
3651 // check state file version
3652 if(fio->FgetUint32() == STATE_VERSION) {
3654 if(process_config_state((void *)fio, true)) {
3655 // load inserted medias
3657 fio->Fread(&cart_status, sizeof(cart_status), 1);
3659 #ifdef USE_FLOPPY_DISK
3660 fio->Fread(floppy_disk_status, sizeof(floppy_disk_status), 1);
3661 fio->Fread(d88_file, sizeof(d88_file), 1);
3663 #ifdef USE_QUICK_DISK
3664 fio->Fread(&quick_disk_status, sizeof(quick_disk_status), 1);
3666 #ifdef USE_HARD_DISK
3667 fio->Fread(&hard_disk_status, sizeof(hard_disk_status), 1);
3670 fio->Fread(&tape_status, sizeof(tape_status), 1);
3672 #ifdef USE_COMPACT_DISC
3673 fio->Fread(&compact_disc_status, sizeof(compact_disc_status), 1);
3675 #ifdef USE_LASER_DISC
3676 fio->Fread(&laser_disc_status, sizeof(laser_disc_status), 1);
3679 fio->Fread(&bubble_casette_status, sizeof(bubble_casette_status), 1);
3681 // check if virtual machine should be reinitialized
3682 bool reinitialize = false;
3684 reinitialize |= (cpu_type != config.cpu_type);
3685 cpu_type = config.cpu_type;
3687 #ifdef USE_DIPSWITCH
3688 reinitialize |= (dipswitch != config.dipswitch);
3689 dipswitch = config.dipswitch;
3691 #ifdef USE_SOUND_TYPE
3692 reinitialize |= (sound_type != config.sound_type);
3693 sound_type = config.sound_type;
3695 #ifdef USE_PRINTER_TYPE
3696 reinitialize |= (printer_type != config.printer_type);
3697 printer_type = config.printer_type;
3699 #ifdef USE_SERIAL_TYPE
3700 reinitialize |= (serial_type != config.serial_type);
3701 serial_type = config.serial_type;
3703 if(!(0 <= config.sound_frequency && config.sound_frequency < 8)) {
3704 config.sound_frequency = 6; // default: 48KHz
3706 if(!(0 <= config.sound_latency && config.sound_latency < 5)) {
3707 config.sound_latency = 1; // default: 100msec
3709 reinitialize |= (sound_frequency != config.sound_frequency);
3710 reinitialize |= (sound_latency != config.sound_latency);
3711 sound_frequency = config.sound_frequency;
3712 sound_latency = config.sound_latency;
3717 // reinitialize virtual machine
3723 # if defined(_USE_QT)
3724 osd->reset_vm_node();
3725 osd->update_keyname_table();
3726 osd->reset_screen_buffer();
3728 vm->initialize_sound(sound_rate, sound_samples);
3729 #ifdef USE_SOUND_VOLUME
3730 for(int i = 0; i < USE_SOUND_VOLUME; i++) {
3731 vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
3738 // restore inserted medias
3742 if(vm->process_state(fio, true)) {
3743 // check end of state
3744 result = (fio->FgetInt32_LE() == -1);
3755 const _TCHAR *EMU::state_file_path(int num)
3757 return create_local_path(_T("%s.sta%d"), _T(CONFIG_NAME), num);