OSDN Git Service

[WIP][Qt][MOVIE_LOADER] Constructing MOVIE_LOADER class.
[csp-qt/common_source_project-fm7.git] / source / src / emu.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2006.08.18 -
6
7         [ win32 emulation i/f ]
8 */
9
10 #if defined(_USE_QT)
11 #include <string>
12 #endif
13 #include "emu.h"
14 #include "vm/vm.h"
15 #include "fifo.h"
16 #include "fileio.h"
17
18 #ifndef FD_BASE_NUMBER
19 #define FD_BASE_NUMBER 1
20 #endif
21 #ifndef QD_BASE_NUMBER
22 #define QD_BASE_NUMBER 1
23 #endif
24
25 // ----------------------------------------------------------------------------
26 // initialize
27 // ----------------------------------------------------------------------------
28 #if defined(_USE_QT)
29 // Please permit at least them m(.. )m
30 //extern void get_long_full_path_name(_TCHAR* src, _TCHAR* dst);
31 #include <string>
32 #endif
33
34 #if defined(_USE_QT)
35 EMU::EMU(class Ui_MainWindow *hwnd, GLDrawClass *hinst, USING_FLAGS *p)
36 #elif defined(OSD_WIN32)
37 EMU::EMU(HWND hwnd, HINSTANCE hinst)
38 #else
39 EMU::EMU()
40 #endif
41 {
42         message_count = 0;
43         // store main window handle
44 #ifdef USE_FD1
45         // initialize d88 file info
46         memset(d88_file, 0, sizeof(d88_file));
47 #endif
48 #ifdef USE_BUBBLE1
49         // initialize d88 file info
50         memset(b77_file, 0, sizeof(b77_file));
51 #endif
52         // load sound config
53         static const int freq_table[8] = {
54                 2000, 4000, 8000, 11025, 22050, 44100,
55 #ifdef OVERRIDE_SOUND_FREQ_48000HZ
56                 OVERRIDE_SOUND_FREQ_48000HZ,
57 #else
58                 48000,
59 #endif
60                 96000,
61         };
62         static const double late_table[5] = {0.05, 0.1, 0.2, 0.3, 0.4};
63         
64         if(!(0 <= config.sound_frequency && config.sound_frequency < 8)) {
65                 config.sound_frequency = 6;     // default: 48KHz
66         }
67         if(!(0 <= config.sound_latency && config.sound_latency < 5)) {
68                 config.sound_latency = 1;       // default: 100msec
69         }
70         sound_rate = freq_table[config.sound_frequency];
71         sound_samples = (int)(sound_rate * late_table[config.sound_latency] + 0.5);
72
73 #ifdef USE_CPU_TYPE
74         cpu_type = config.cpu_type;
75 #endif
76 #ifdef USE_SOUND_DEVICE_TYPE
77         sound_device_type = config.sound_device_type;
78 #endif
79 #ifdef USE_PRINTER
80         printer_device_type = config.printer_device_type;
81 #endif
82         
83         // initialize osd
84 #if defined(OSD_QT)
85         osd = new OSD(p);
86         osd->main_window_handle = hwnd;
87         osd->glv = hinst;
88         osd->host_cpus = 4;
89 #elif defined(OSD_WIN32)
90         osd = new OSD();
91         osd->main_window_handle = hwnd;
92         osd->instance_handle = hinst;
93 #endif
94         osd->initialize(sound_rate, sound_samples);
95         // initialize vm
96         osd->vm = vm = new VM(this);
97         // Below is temporally workaround. I will fix ASAP (or give up): 20160311 K.Ohta
98         // Problems seem to be resolved. See fm7.cpp. 20160319 K.Ohta
99         // Still not resolved with FM-7/77 :-( 20160407 K.Ohta
100 #if defined(_FM7) || defined(_FMNEW7) || defined(_FM8) || \
101         defined(_FM77_VARIANTS)
102         delete vm;
103         osd->vm = vm = new VM(this);
104 #endif
105 #ifdef USE_AUTO_KEY
106         initialize_auto_key();
107 #endif
108 #ifdef USE_DEBUGGER
109         initialize_debugger();
110 #endif
111         initialize_media();
112         vm->initialize_sound(sound_rate, sound_samples);
113 #ifdef USE_SOUND_VOLUME
114         for(int i = 0; i < USE_SOUND_VOLUME; i++) {
115                 vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
116         }
117 #endif
118         vm->reset();
119         now_suspended = false;
120 }
121
122 EMU::~EMU()
123 {
124 #ifdef USE_AUTO_KEY
125         release_auto_key();
126 #endif
127 #ifdef USE_DEBUGGER
128         release_debugger();
129 #endif
130         delete vm;
131         osd->release();
132         delete osd;
133 #ifdef _DEBUG_LOG
134         release_debug_log();
135 #endif
136 }
137
138 #ifdef OSD_QT
139 EmuThreadClass *EMU::get_parent_handler()
140 {
141         return osd->get_parent_handler();
142 }
143
144 void EMU::set_parent_handler(EmuThreadClass *p, DrawThreadClass *q)
145 {
146         osd->set_parent_thread(p);
147         osd->set_draw_thread(q);
148 }
149
150 void EMU::set_host_cpus(int v)
151 {
152         osd->host_cpus = (v <= 0) ? 1 : v;
153 }
154
155 int EMU::get_host_cpus()
156 {
157         return osd->host_cpus;
158 }
159 #endif
160
161 // ----------------------------------------------------------------------------
162 // drive machine
163 // ----------------------------------------------------------------------------
164
165 int EMU::get_frame_interval()
166 {
167 #ifdef SUPPORT_VARIABLE_TIMING
168         static int prev_interval = 0;
169         static double prev_fps = -1;
170         double fps = vm->get_frame_rate();
171         if(prev_fps != fps) {
172                 prev_interval = (int)(1024. * 1000. / fps + 0.5);
173                 prev_fps = fps;
174         }
175         return prev_interval;
176 #else
177         return (int)(1024. * 1000. / FRAMES_PER_SEC + 0.5);
178 #endif
179 }
180
181 bool EMU::is_frame_skippable()
182 {
183         return vm->is_frame_skippable();
184 }
185
186 int EMU::run()
187 {
188         if(now_suspended) {
189                 osd->restore();
190                 now_suspended = false;
191         }
192         osd->update_input();
193 #ifdef USE_AUTO_KEY
194         update_auto_key();
195 #endif
196 #ifdef USE_JOYSTICK
197         update_joystick();
198 #endif
199         
200 #ifdef USE_SOCKET
201 #if !defined(_USE_QT) // Temporally
202         osd->update_socket();
203 #endif
204 #endif
205         update_media();
206         
207         // virtual machine may be driven to fill sound buffer
208         int extra_frames = 0;
209         osd->update_sound(&extra_frames);
210         
211         // drive virtual machine
212         if(extra_frames == 0) {
213                 osd->lock_vm();
214                 vm->run();
215                 extra_frames = 1;
216                 osd->unlock_vm();
217         }
218         osd->add_extra_frames(extra_frames);
219         return extra_frames;
220 }
221
222 void EMU::reset()
223 {
224         // check if virtual machine should be reinitialized
225         bool reinitialize = false;
226 #ifdef USE_CPU_TYPE
227         reinitialize |= (cpu_type != config.cpu_type);
228         cpu_type = config.cpu_type;
229 #endif
230 #ifdef USE_SOUND_DEVICE_TYPE
231         reinitialize |= (sound_device_type != config.sound_device_type);
232         sound_device_type = config.sound_device_type;
233 #endif
234 #ifdef USE_PRINTER
235         reinitialize |= (printer_device_type != config.printer_device_type);
236         printer_device_type = config.printer_device_type;
237 #endif
238         if(reinitialize) {
239                 // stop sound
240                 osd->stop_sound();
241                 // reinitialize virtual machine
242                 osd->lock_vm();         
243                 delete vm;
244                 osd->vm = vm = new VM(this);
245                 vm->initialize_sound(sound_rate, sound_samples);
246 #ifdef USE_SOUND_VOLUME
247                 for(int i = 0; i < USE_SOUND_VOLUME; i++) {
248                         vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
249                 }
250 #endif
251                 vm->reset();
252                 osd->unlock_vm();
253                 // restore inserted medias
254                 restore_media();
255         } else {
256                 // reset virtual machine
257                 osd->lock_vm();         
258                 vm->reset();
259                 osd->unlock_vm();               
260         }
261         
262         // restart recording
263 #if !defined(_USE_QT) // Temporally
264         osd->restart_record_sound();
265         osd->restart_record_video();
266 #endif  
267 }
268
269 #ifdef USE_SPECIAL_RESET
270 void EMU::special_reset()
271 {
272         // reset virtual machine
273         osd->lock_vm();         
274         vm->special_reset();
275         osd->unlock_vm();
276         // restart recording
277 #if !defined(_USE_QT) // Temporally
278         restart_record_sound();
279         restart_record_video();
280 #endif  
281 }
282 #endif
283
284 #ifdef USE_NOTIFY_POWER_OFF
285 void EMU::notify_power_off()
286 {
287         vm->notify_power_off();
288 }
289 #endif
290
291 void EMU::power_off()
292 {
293         osd->power_off();
294 }
295
296 void EMU::suspend()
297 {
298         if(!now_suspended) {
299                 osd->suspend();
300                 now_suspended = true;
301         }
302 }
303
304 void EMU::lock_vm()
305 {
306         osd->lock_vm();
307 }
308
309 void EMU::unlock_vm()
310 {
311         osd->unlock_vm();
312 }
313
314 void EMU::force_unlock_vm()
315 {
316         osd->force_unlock_vm();
317 }
318
319
320 bool EMU::is_vm_locked()
321 {
322         return osd->is_vm_locked();
323 }
324
325 // ----------------------------------------------------------------------------
326 // input
327 // ----------------------------------------------------------------------------
328
329 #ifdef OSD_QT
330 void EMU::key_modifiers(uint32_t mod)
331 {
332         osd->key_modifiers(mod);
333 }
334
335         # ifdef USE_MOUSE
336 void EMU::set_mouse_pointer(int x, int y)
337 {
338         osd->set_mouse_pointer(x, y);
339 }
340
341 void EMU::set_mouse_button(int button)
342 {
343         osd->set_mouse_button(button);
344 }
345
346 int EMU::get_mouse_button()
347 {
348         return osd->get_mouse_button();
349 }
350         #endif
351 #endif
352
353 void EMU::key_down(int code, bool repeat)
354 {
355         osd->key_down(code, repeat);
356 }
357
358 void EMU::key_up(int code)
359 {
360         osd->key_up(code);
361 }
362
363 void EMU::key_lost_focus()
364 {
365         osd->key_lost_focus();
366 }
367
368 #ifdef ONE_BOARD_MICRO_COMPUTER
369 void EMU::press_button(int num)
370 {
371         int code = vm_buttons[num].code;
372         
373         if(code) {
374                 osd->key_down_native(code, false);
375                 osd->get_key_buffer()[code] = KEY_KEEP_FRAMES;
376         } else {
377                 // code=0: reset virtual machine
378                 vm->reset();
379         }
380 }
381 #endif
382
383 #ifdef USE_MOUSE
384 void EMU::enable_mouse()
385 {
386         osd->enable_mouse();
387 }
388
389 void EMU::disable_mouse()
390 {
391         osd->disable_mouse();
392 }
393
394 void EMU::toggle_mouse()
395 {
396         osd->toggle_mouse();
397 }
398
399 bool EMU::is_mouse_enabled()
400 {
401         return osd->is_mouse_enabled();
402 }
403 #endif
404
405 #ifdef USE_AUTO_KEY
406 void EMU::initialize_auto_key()
407 {
408         auto_key_buffer = new FIFO(65536);
409         auto_key_buffer->clear();
410         auto_key_phase = auto_key_shift = 0;
411         osd->now_auto_key = false;
412 }
413
414 void EMU::release_auto_key()
415 {
416         if(auto_key_buffer) {
417                 auto_key_buffer->release();
418                 delete auto_key_buffer;
419         }
420 }
421
422 void EMU::start_auto_key()
423 {
424         auto_key_phase = 1;
425         auto_key_shift = 0;
426         osd->now_auto_key = true;
427 }
428
429 void EMU::stop_auto_key()
430 {
431         if(auto_key_shift) {
432                 osd->key_up_native(VK_LSHIFT);
433         }
434         auto_key_phase = auto_key_shift = 0;
435         osd->now_auto_key = false;
436 }
437
438 #ifndef USE_AUTO_KEY_SHIFT
439 #define USE_AUTO_KEY_SHIFT 0
440 #endif
441 #ifndef VK_LSHIFT
442 #define VK_LSHIFT 0xA0
443 #endif
444
445 void EMU::update_auto_key()
446 {
447         switch(auto_key_phase) {
448         case 1:
449                 if(auto_key_buffer && !auto_key_buffer->empty()) {
450                         // update shift key status
451                         int shift = auto_key_buffer->read_not_remove(0) & 0x100;
452                         if(shift && !auto_key_shift) {
453                                 osd->key_down_native(VK_LSHIFT, false);
454                         } else if(!shift && auto_key_shift) {
455                                 osd->key_up_native(VK_LSHIFT);
456                         }
457                         auto_key_shift = shift;
458                         auto_key_phase++;
459                         break;
460                 }
461         case 3 + USE_AUTO_KEY_SHIFT:
462                 if(auto_key_buffer && !auto_key_buffer->empty()) {
463                         osd->key_down_native(auto_key_buffer->read_not_remove(0) & 0xff, false);
464                 }
465                 auto_key_phase++;
466                 break;
467         case USE_AUTO_KEY + USE_AUTO_KEY_SHIFT:
468                 if(auto_key_buffer && !auto_key_buffer->empty()) {
469                         osd->key_up_native(auto_key_buffer->read_not_remove(0) & 0xff);
470                 }
471                 auto_key_phase++;
472                 break;
473         case USE_AUTO_KEY_RELEASE + USE_AUTO_KEY_SHIFT:
474                 if(auto_key_buffer && !auto_key_buffer->empty()) {
475                         // wait enough while vm analyzes one line
476                         if(auto_key_buffer->read() == 0xd) {
477                                 auto_key_phase++;
478                                 break;
479                         }
480                 }
481         case 30:
482                 if(auto_key_buffer && !auto_key_buffer->empty()) {
483                         auto_key_phase = 1;
484                 } else {
485                         stop_auto_key();
486                 }
487                 break;
488         default:
489                 if(auto_key_phase) {
490                         auto_key_phase++;
491                 }
492         }
493 }
494 #endif
495
496 #ifdef USE_JOYSTICK
497 void EMU::update_joystick()
498 {
499         uint32_t *joy_buffer = osd->get_joy_buffer();
500         uint8_t *key_buffer = osd->get_key_buffer();
501         
502         memset(joy_status, 0, sizeof(joy_status));
503         
504         for(int i = 0; i < 4; i++) {
505                 for(int j = 0; j < 16; j++) {
506                         if(config.joy_buttons[i][j] < 0) {
507                                 int code = -config.joy_buttons[i][j];
508                                 if(code < 256 && key_buffer[code]) {
509                                         joy_status[i] |= (1 << j);
510                                 }
511                         } else {
512                                 int stick = config.joy_buttons[i][j] >> 4;
513                                 int button = config.joy_buttons[i][j] & 15;
514                                 if(stick < 2 && (joy_buffer[stick & 3] & (1 << button))) {
515                                         joy_status[i] |= (1 << j);
516                                 }
517                         }
518                 }
519         }
520 }
521 #endif
522
523 const uint8_t* EMU::get_key_buffer()
524 {
525         return (const uint8_t*)osd->get_key_buffer();
526 }
527
528 #ifdef USE_JOYSTICK
529 const uint32_t* EMU::get_joy_buffer()
530 {
531         return (const uint32_t*)joy_status;
532 }
533 #endif
534
535 #ifdef USE_MOUSE
536 const int32_t* EMU::get_mouse_buffer()
537 {
538         return (const int32_t*)osd->get_mouse_buffer();
539 }
540 #endif
541
542 // ----------------------------------------------------------------------------
543 // screen
544 // ----------------------------------------------------------------------------
545
546 int EMU::get_window_mode_width(int mode)
547 {
548         return osd->get_window_mode_width(mode);
549 }
550
551 int EMU::get_window_mode_height(int mode)
552 {
553         return osd->get_window_mode_height(mode);
554 }
555
556 void EMU::set_host_window_size(int window_width, int window_height, bool window_mode)
557 {
558         osd->set_host_window_size(window_width, window_height, window_mode);
559 }
560
561 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)
562 {
563         osd->set_vm_screen_size(screen_width, screen_height, window_width, window_height, window_width_aspect, window_height_aspect);
564 }
565
566 int EMU::get_vm_window_width()
567 {
568         return osd->get_vm_window_width();
569 }
570
571 int EMU::get_vm_window_height()
572 {
573         return osd->get_vm_window_height();
574 }
575
576 int EMU::get_vm_window_width_aspect()
577 {
578         return osd->get_vm_window_width_aspect();
579 }
580
581 int EMU::get_vm_window_height_aspect()
582 {
583         return osd->get_vm_window_height_aspect();
584 }
585
586 #if defined(USE_MINIMUM_RENDERING)
587 bool EMU::is_screen_changed()
588 {
589         return vm->is_screen_changed();
590 }
591 #endif
592
593 int EMU::draw_screen()
594 {
595         return osd->draw_screen();
596 }
597
598 scrntype_t* EMU::get_screen_buffer(int y)
599 {
600         return osd->get_vm_screen_buffer(y);
601 }
602
603 #ifdef USE_CRT_FILTER
604 void EMU::screen_skip_line(bool skip_line)
605 {
606         osd->screen_skip_line = skip_line;
607 }
608 #endif
609
610 #ifdef ONE_BOARD_MICRO_COMPUTER
611 void EMU::reload_bitmap()
612 {
613         osd->reload_bitmap();
614 }
615 #endif
616
617 #ifdef OSD_WIN32
618 void EMU::update_screen(HDC hdc)
619 {
620         osd->update_screen(hdc);
621 }
622 #endif
623
624 void EMU::capture_screen()
625 {
626         osd->capture_screen();
627 }
628
629 bool EMU::start_record_video(int fps)
630 {
631         return osd->start_record_video(fps);
632 }
633
634 void EMU::stop_record_video()
635 {
636         osd->stop_record_video();
637 }
638
639 bool EMU::is_video_recording()
640 {
641         return osd->now_record_video;
642 }
643
644 // ----------------------------------------------------------------------------
645 // sound
646 // ----------------------------------------------------------------------------
647
648 void EMU::mute_sound()
649 {
650         osd->mute_sound();
651 }
652
653 void EMU::start_record_sound()
654 {
655         osd->start_record_sound();
656 }
657
658 void EMU::stop_record_sound()
659 {
660         osd->stop_record_sound();
661 }
662
663 bool EMU::is_sound_recording()
664 {
665         return osd->now_record_sound;
666 }
667
668 // ----------------------------------------------------------------------------
669 // video
670 // ----------------------------------------------------------------------------
671
672 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
673 void EMU::get_video_buffer()
674 {
675         osd->get_video_buffer();
676 }
677
678 void EMU::mute_video_dev(bool l, bool r)
679 {
680         osd->mute_video_dev(l, r);
681 }
682 #endif
683
684 #ifdef USE_MOVIE_PLAYER
685 bool EMU::open_movie_file(const _TCHAR* file_path)
686 {
687         return osd->open_movie_file(file_path);
688 }
689
690 void EMU::close_movie_file()
691 {
692         osd->close_movie_file();
693 }
694
695 void EMU::play_movie()
696 {
697         osd->play_movie();
698 }
699
700 void EMU::stop_movie()
701 {
702         osd->stop_movie();
703 }
704
705 void EMU::pause_movie()
706 {
707         osd->pause_movie();
708 }
709
710 double EMU::get_movie_frame_rate()
711 {
712         return osd->get_movie_frame_rate();
713 }
714
715 int EMU::get_movie_sound_rate()
716 {
717         return osd->get_movie_sound_rate();
718 }
719
720 void EMU::set_cur_movie_frame(int frame, bool relative)
721 {
722         osd->set_cur_movie_frame(frame, relative);
723 }
724
725 uint32_t EMU::get_cur_movie_frame()
726 {
727         return osd->get_cur_movie_frame();
728 }
729 #endif
730
731 #ifdef USE_VIDEO_CAPTURE
732 int EMU::get_cur_capture_dev_index()
733 {
734         return osd->get_cur_capture_dev_index();
735 }
736
737 int EMU::get_num_capture_devs()
738 {
739         return osd->get_num_capture_devs();
740 }
741
742 _TCHAR* EMU::get_capture_dev_name(int index)
743 {
744         return osd->get_capture_dev_name(index);
745 }
746
747 void EMU::open_capture_dev(int index, bool pin)
748 {
749         osd->open_capture_dev(index, pin);
750 }
751
752 void EMU::close_capture_dev()
753 {
754         osd->close_capture_dev();
755 }
756
757 void EMU::show_capture_dev_filter()
758 {
759         osd->show_capture_dev_filter();
760 }
761
762 void EMU::show_capture_dev_pin()
763 {
764         osd->show_capture_dev_pin();
765 }
766
767 void EMU::show_capture_dev_source()
768 {
769         osd->show_capture_dev_source();
770 }
771
772 void EMU::set_capture_dev_channel(int ch)
773 {
774         osd->set_capture_dev_channel(ch);
775 }
776 #endif
777
778 // ----------------------------------------------------------------------------
779 // printer
780 // ----------------------------------------------------------------------------
781
782 #ifdef USE_PRINTER
783 void EMU::create_bitmap(bitmap_t *bitmap, int width, int height)
784 {
785         osd->create_bitmap(bitmap, width, height);
786 }
787
788 void EMU::release_bitmap(bitmap_t *bitmap)
789 {
790         osd->release_bitmap(bitmap);
791 }
792
793 void EMU::create_font(font_t *font, const _TCHAR *family, int width, int height, int rotate, bool bold, bool italic)
794 {
795         osd->create_font(font, family, width, height, rotate, bold, italic);
796 }
797
798 void EMU::release_font(font_t *font)
799 {
800         osd->release_font(font);
801 }
802
803 void EMU::create_pen(pen_t *pen, int width, uint8_t r, uint8_t g, uint8_t b)
804 {
805         osd->create_pen(pen, width, r, g, b);
806 }
807
808 void EMU::release_pen(pen_t *pen)
809 {
810         osd->release_pen(pen);
811 }
812
813 void EMU::clear_bitmap(bitmap_t *bitmap, uint8_t r, uint8_t g, uint8_t b)
814 {
815         osd->clear_bitmap(bitmap, r, g, b);
816 }
817
818 int EMU::get_text_width(bitmap_t *bitmap, font_t *font, const char *text)
819 {
820         return osd->get_text_width(bitmap, font, text);
821 }
822
823 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)
824 {
825         osd->draw_text_to_bitmap(bitmap, font, x, y, text, r, g, b);
826 }
827
828 void EMU::draw_line_to_bitmap(bitmap_t *bitmap, pen_t *pen, int sx, int sy, int ex, int ey)
829 {
830         osd->draw_line_to_bitmap(bitmap, pen, sx, sy, ex, ey);
831 }
832
833 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)
834 {
835         osd->draw_rectangle_to_bitmap(bitmap, x, y, width, height, r, g, b);
836 }
837
838 void EMU::draw_point_to_bitmap(bitmap_t *bitmap, int x, int y, uint8_t r, uint8_t g, uint8_t b)
839 {
840         osd->draw_point_to_bitmap(bitmap, x, y, r, g, b);
841 }
842
843 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)
844 {
845         osd->stretch_bitmap(dest, dest_x, dest_y, dest_width, dest_height, source, source_x, source_y, source_width, source_height);
846 }
847
848 void EMU::write_bitmap_to_file(bitmap_t *bitmap, const _TCHAR *file_path)
849 {
850         osd->write_bitmap_to_file(bitmap, file_path);
851 }
852 #endif
853
854 // ----------------------------------------------------------------------------
855 // socket
856 // ----------------------------------------------------------------------------
857
858 #ifdef USE_SOCKET
859 int EMU::get_socket(int ch)
860 {
861         return osd->get_socket(ch);
862 }
863
864 void EMU::notify_socket_connected(int ch)
865 {
866         osd->notify_socket_connected(ch);
867 }
868
869 void EMU::notify_socket_disconnected(int ch)
870 {
871         osd->notify_socket_disconnected(ch);
872 }
873
874 bool EMU::initialize_socket_tcp(int ch)
875 {
876         return osd->initialize_socket_tcp(ch);
877 }
878
879 bool EMU::initialize_socket_udp(int ch)
880 {
881         return osd->initialize_socket_udp(ch);
882 }
883
884 bool EMU::connect_socket(int ch, uint32_t ipaddr, int port)
885 {
886         return osd->connect_socket(ch, ipaddr, port);
887 }
888
889 void EMU::disconnect_socket(int ch)
890 {
891         osd->disconnect_socket(ch);
892 }
893  
894 bool EMU::listen_socket(int ch)
895 {
896         return osd->listen_socket(ch);
897 }
898
899 void EMU::send_socket_data_tcp(int ch)
900 {
901         osd->send_socket_data_tcp(ch);
902 }
903
904 void EMU::send_socket_data_udp(int ch, uint32_t ipaddr, int port)
905 {
906         osd->send_socket_data_udp(ch, ipaddr, port);
907 }
908
909 void EMU::send_socket_data(int ch)
910 {
911         osd->send_socket_data(ch);
912 }
913
914 void EMU::recv_socket_data(int ch)
915 {
916         osd->recv_socket_data(ch);
917 }
918 #endif
919
920 // ----------------------------------------------------------------------------
921 // debug log
922 // ----------------------------------------------------------------------------
923
924 #ifdef _DEBUG_LOG
925 void EMU::initialize_debug_log()
926 {
927         _TCHAR path[_MAX_PATH];
928         debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
929 }
930
931 void EMU::release_debug_log()
932 {
933         if(debug_log) {
934                 fclose(debug_log);
935                 debug_log = NULL;
936         }
937 }
938 #endif
939
940 #ifdef _DEBUG_LOG
941 static _TCHAR prev_buffer[1024] = {0};
942 #endif
943
944 void EMU::out_debug_log(const _TCHAR* format, ...)
945 {
946 #ifdef _DEBUG_LOG
947         va_list ap;
948         _TCHAR buffer[1024];
949         
950         va_start(ap, format);
951         my_vstprintf_s(buffer, 1024, format, ap);
952         va_end(ap);
953         
954         if(_tcscmp(prev_buffer, buffer) == 0) {
955                 return;
956         }
957         my_tcscpy_s(prev_buffer, 1024, buffer);
958         
959 #if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
960         AGAR_DebugLog(AGAR_LOG_DEBUG, "%s", buffer);
961 #else
962         if(debug_log) {
963                 _ftprintf(debug_log, _T("%s"), buffer);
964                 static int size = 0;
965                 if((size += _tcslen(buffer)) > 0x8000000) { // 128MB
966                         fclose(debug_log);
967                         debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
968                         size = 0;
969                 }
970         }
971 #endif
972 #endif
973 }
974
975 void EMU::force_out_debug_log(const _TCHAR* format, ...)
976 {
977 #ifdef _DEBUG_LOG
978         va_list ap;
979         _TCHAR buffer[1024];
980         
981         va_start(ap, format);
982         my_vstprintf_s(buffer, 1024, format, ap);
983         va_end(ap);
984         my_tcscpy_s(prev_buffer, 1024, buffer);
985         
986 #if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
987         AGAR_DebugLog(AGAR_LOG_DEBUG, "%s", buffer);
988 #else
989         if(debug_log) {
990                 _ftprintf(debug_log, _T("%s"), buffer);
991                 static int size = 0;
992                 if((size += _tcslen(buffer)) > 0x8000000) { // 128MB
993                         fclose(debug_log);
994                         debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
995                         size = 0;
996                 }
997         }
998 #endif
999 #endif
1000 }
1001
1002 void EMU::out_message(const _TCHAR* format, ...)
1003 {
1004         va_list ap;
1005         va_start(ap, format);
1006         my_vstprintf_s(message, 1024, format, ap); // Security for MSVC:C6386.
1007         va_end(ap);
1008         message_count = 4; // 4sec
1009 }
1010
1011 // ----------------------------------------------------------------------------
1012 // misc
1013 // ----------------------------------------------------------------------------
1014
1015
1016 void EMU::sleep(uint32_t ms)
1017 {
1018         osd->sleep(ms);
1019 }
1020
1021
1022 // ----------------------------------------------------------------------------
1023 // user interface
1024 // ----------------------------------------------------------------------------
1025
1026 static uint8_t hex2uint8(char *value)
1027 {
1028         char tmp[3];
1029         memset(tmp, 0, sizeof(tmp));
1030         memcpy(tmp, value, 2);
1031         return (uint8_t)strtoul(tmp, NULL, 16);
1032 }
1033
1034 static uint16_t hex2uint16(char *value)
1035 {
1036         char tmp[5];
1037         memset(tmp, 0, sizeof(tmp));
1038         memcpy(tmp, value, 4);
1039         return (uint16_t)strtoul(tmp, NULL, 16);
1040 }
1041
1042 static bool hex2bin(const _TCHAR* file_path, const _TCHAR* dest_path)
1043 {
1044         bool result = false;
1045         FILEIO *fio_s = new FILEIO();
1046         if(fio_s->Fopen(file_path, FILEIO_READ_BINARY)) {
1047                 int length = 0;
1048                 char line[1024];
1049                 uint8_t buffer[0x10000];
1050                 memset(buffer, 0xff, sizeof(buffer));
1051                 while(fio_s->Fgets(line, sizeof(line)) != NULL) {
1052                         if(line[0] != ':') continue;
1053                         int bytes = hex2uint8(line + 1);
1054                         int offset = hex2uint16(line + 3);
1055                         uint8_t record_type = hex2uint8(line + 7);
1056                         if(record_type == 0x01) break;
1057                         if(record_type != 0x00) continue;
1058                         for(int i = 0; i < bytes; i++) {
1059                                 if(offset + i < sizeof(buffer)) {
1060                                         if(length < offset + i) {
1061                                                 length = offset + i;
1062                                         }
1063                                         buffer[offset + i] = hex2uint8(line + 9 + 2 * i);
1064                                 }
1065                         }
1066                 }
1067                 if(length > 0) {
1068                         FILEIO *fio_d = new FILEIO();
1069                         if(fio_d->Fopen(dest_path, FILEIO_WRITE_BINARY)) {
1070                                 fio_d->Fwrite(buffer, length, 1);
1071                                 fio_d->Fclose();
1072                                 result = true;
1073                         }
1074                         delete fio_d;
1075                 }
1076                 fio_s->Fclose();
1077         }
1078         delete fio_s;
1079         return result;
1080 }
1081
1082 void EMU::initialize_media()
1083 {
1084 #ifdef USE_CART1
1085         memset(&cart_status, 0, sizeof(cart_status));
1086 #endif
1087 #ifdef USE_FD1
1088         memset(floppy_disk_status, 0, sizeof(floppy_disk_status));
1089 #endif
1090 #ifdef USE_QD1
1091         memset(&quick_disk_status, 0, sizeof(quick_disk_status));
1092 #endif
1093 #ifdef USE_TAPE
1094         memset(&tape_status, 0, sizeof(tape_status));
1095 #endif
1096 #ifdef USE_COMPACT_DISC
1097         memset(&compact_disc_status, 0, sizeof(compact_disc_status));
1098 #endif
1099 #ifdef USE_LASER_DISC
1100         memset(&laser_disc_status, 0, sizeof(laser_disc_status));
1101 #endif
1102 }
1103
1104
1105 void EMU::update_media()
1106 {
1107 #ifdef USE_FD1
1108         for(int drv = 0; drv < MAX_FD; drv++) {
1109                 if(floppy_disk_status[drv].wait_count != 0 && --floppy_disk_status[drv].wait_count == 0) {
1110                         vm->open_floppy_disk(drv, floppy_disk_status[drv].path, floppy_disk_status[drv].bank);
1111                         out_message(_T("FD%d: %s"), drv + FD_BASE_NUMBER, floppy_disk_status[drv].path);
1112                 }
1113         }
1114 #endif
1115 #ifdef USE_QD1
1116         for(int drv = 0; drv < MAX_QD; drv++) {
1117                 if(quick_disk_status[drv].wait_count != 0 && --quick_disk_status[drv].wait_count == 0) {
1118                         vm->open_quick_disk(drv, quick_disk_status[drv].path);
1119                         out_message(_T("QD%d: %s"), drv + QD_BASE_NUMBER, quick_disk_status[drv].path);
1120                 }
1121         }
1122 #endif
1123 #ifdef USE_TAPE
1124         if(tape_status.wait_count != 0 && --tape_status.wait_count == 0) {
1125                 if(tape_status.play) {
1126                         vm->play_tape(tape_status.path);
1127                 } else {
1128                         vm->rec_tape(tape_status.path);
1129                 }
1130                 out_message(_T("CMT: %s"), tape_status.path);
1131         }
1132 #endif
1133 #ifdef USE_COMPACT_DISC
1134         if(compact_disc_status.wait_count != 0 && --compact_disc_status.wait_count == 0) {
1135                 vm->open_compact_disc(compact_disc_status.path);
1136                 out_message(_T("CD: %s"), compact_disc_status.path);
1137         }
1138 #endif
1139 #ifdef USE_LASER_DISC
1140         if(laser_disc_status.wait_count != 0 && --laser_disc_status.wait_count == 0) {
1141                 vm->open_laser_disc(laser_disc_status.path);
1142                 out_message(_T("LD: %s"), laser_disc_status.path);
1143         }
1144 #endif
1145 #ifdef USE_BUBBLE1
1146         for(int drv = 0; drv < MAX_BUBBLE; drv++) {
1147                 if(bubble_casette_status[drv].wait_count != 0 && --bubble_casette_status[drv].wait_count == 0) {
1148                         vm->open_bubble_casette(drv, bubble_casette_status[drv].path, bubble_casette_status[drv].bank);
1149                         out_message(_T("Bubble%d: %s"), drv, bubble_casette_status[drv].path);
1150                 }
1151         }
1152 #endif
1153 }
1154
1155 void EMU::restore_media()
1156 {
1157 #ifdef USE_CART1
1158         for(int drv = 0; drv < MAX_CART; drv++) {
1159                 if(cart_status[drv].path[0] != _T('\0')) {
1160                         if(check_file_extension(cart_status[drv].path, _T(".hex")) && hex2bin(cart_status[drv].path, create_local_path(_T("hex2bin.$$$")))) {
1161                                 vm->open_cart(drv, create_local_path(_T("hex2bin.$$$")));
1162                                 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
1163                         } else {
1164                                 vm->open_cart(drv, cart_status[drv].path);
1165                         }
1166                 }
1167         }
1168 #endif
1169 #ifdef USE_FD1
1170         for(int drv = 0; drv < MAX_FD; drv++) {
1171                 if(floppy_disk_status[drv].path[0] != _T('\0')) {
1172                         vm->open_floppy_disk(drv, floppy_disk_status[drv].path, floppy_disk_status[drv].bank);
1173                 }
1174         }
1175 #endif
1176 #ifdef USE_QD1
1177         for(int drv = 0; drv < MAX_QD; drv++) {
1178                 if(quick_disk_status[drv].path[0] != _T('\0')) {
1179                         vm->open_quick_disk(drv, quick_disk_status[drv].path);
1180                 }
1181         }
1182 #endif
1183 #ifdef USE_TAPE
1184         if(tape_status.path[0] != _T('\0')) {
1185                 if(tape_status.play) {
1186                         vm->play_tape(tape_status.path);
1187                 } else {
1188                         tape_status.path[0] = _T('\0');
1189                 }
1190         }
1191 #endif
1192 #ifdef USE_COMPACT_DISC
1193         if(compact_disc_status.path[0] != _T('\0')) {
1194                 vm->open_compact_disc(compact_disc_status.path);
1195         }
1196 #endif
1197 #ifdef USE_LASER_DISC
1198         if(laser_disc_status.path[0] != _T('\0')) {
1199                 vm->open_laser_disc(laser_disc_status.path);
1200         }
1201 #endif
1202 #ifdef USE_BUBBLE1
1203         for(int drv = 0; drv < MAX_BUBBLE; drv++) {
1204                 if(bubble_casette_status[drv].path[0] != _T('\0')) {
1205                         vm->open_bubble_casette(drv, bubble_casette_status[drv].path, bubble_casette_status[drv].bank);
1206                 }
1207         }
1208 #endif
1209 }
1210
1211 #ifdef USE_CART1
1212 void EMU::open_cart(int drv, const _TCHAR* file_path)
1213 {
1214         if(drv < MAX_CART) {
1215                 if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, create_local_path(_T("hex2bin.$$$")))) {
1216                         vm->open_cart(drv, create_local_path(_T("hex2bin.$$$")));
1217                         FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
1218                 } else {
1219                         vm->open_cart(drv, file_path);
1220                 }
1221                 my_tcscpy_s(cart_status[drv].path, _MAX_PATH, file_path);
1222                 out_message(_T("Cart%d: %s"), drv + 1, file_path);
1223 #if !defined(_USE_QT)           
1224                 // restart recording
1225                 bool s = osd->now_record_sound;
1226                 bool v = osd->now_record_video;
1227                 stop_record_sound();
1228                 stop_record_video();
1229
1230                 if(s) osd->start_record_sound();
1231                 if(v) osd->start_record_video(-1);
1232 #endif          
1233         }
1234 }
1235
1236 void EMU::close_cart(int drv)
1237 {
1238         if(drv < MAX_CART) {
1239                 vm->close_cart(drv);
1240                 clear_media_status(&cart_status[drv]);
1241                 out_message(_T("Cart%d: Ejected"), drv + 1);
1242 #if !defined(_USE_QT)           
1243                 // stop recording
1244                 stop_record_video();
1245                 stop_record_sound();
1246 #endif          
1247         }
1248 }
1249
1250 bool EMU::is_cart_inserted(int drv)
1251 {
1252         if(drv < MAX_CART) {
1253                 return vm->is_cart_inserted(drv);
1254         } else {
1255                 return false;
1256         }
1257 }
1258 #endif
1259
1260 #ifdef USE_FD1
1261 void EMU::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
1262 {
1263         if(drv < MAX_FD) {
1264                 if(vm->is_floppy_disk_inserted(drv)) {
1265                         vm->close_floppy_disk(drv);
1266                         // wait 0.5sec
1267 #ifdef SUPPORT_VARIABLE_TIMING
1268                         floppy_disk_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
1269 #else
1270                         floppy_disk_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
1271 #endif
1272                         out_message(_T("FD%d: Ejected"), drv + FD_BASE_NUMBER);
1273                 } else if(floppy_disk_status[drv].wait_count == 0) {
1274                         vm->open_floppy_disk(drv, file_path, bank);
1275                         out_message(_T("FD%d: %s"), drv + FD_BASE_NUMBER, file_path);
1276                 }
1277                 my_tcscpy_s(floppy_disk_status[drv].path, _MAX_PATH, file_path);
1278                 floppy_disk_status[drv].bank = bank;
1279         }
1280 }
1281
1282 void EMU::close_floppy_disk(int drv)
1283 {
1284         if(drv < MAX_FD) {
1285                 vm->close_floppy_disk(drv);
1286                 clear_media_status(&floppy_disk_status[drv]);
1287                 out_message(_T("FD%d: Ejected"), drv + FD_BASE_NUMBER);
1288         }
1289 }
1290
1291 bool EMU::is_floppy_disk_inserted(int drv)
1292 {
1293         if(drv < MAX_FD) {
1294                 return vm->is_floppy_disk_inserted(drv);
1295         } else {
1296                 return false;
1297         }
1298 }
1299
1300 void EMU::is_floppy_disk_protected(int drv, bool value)
1301 {
1302         if(drv < MAX_FD) {
1303                 vm->is_floppy_disk_protected(drv, value);
1304         }
1305 }
1306
1307 bool EMU::is_floppy_disk_protected(int drv)
1308 {
1309         if(drv < MAX_FD) {
1310                 return vm->is_floppy_disk_protected(drv);
1311         } else {
1312                 return false;
1313         }
1314 }
1315 #endif
1316
1317 #ifdef USE_QD1
1318 void EMU::open_quick_disk(int drv, const _TCHAR* file_path)
1319 {
1320         if(drv < MAX_QD) {
1321                 if(vm->is_quick_disk_inserted(drv)) {
1322                         vm->close_quick_disk(drv);
1323                         // wait 0.5sec
1324 #ifdef SUPPORT_VARIABLE_TIMING
1325                         quick_disk_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
1326 #else
1327                         quick_disk_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
1328 #endif
1329                         out_message(_T("QD%d: Ejected"), drv + QD_BASE_NUMBER);
1330                 } else if(quick_disk_status[drv].wait_count == 0) {
1331                         vm->open_quick_disk(drv, file_path);
1332                         out_message(_T("QD%d: %s"), drv + QD_BASE_NUMBER, file_path);
1333                 }
1334                 my_tcscpy_s(quick_disk_status[drv].path, _MAX_PATH, file_path);
1335         }
1336 }
1337
1338 void EMU::close_quick_disk(int drv)
1339 {
1340         if(drv < MAX_QD) {
1341                 vm->close_quick_disk(drv);
1342                 clear_media_status(&quick_disk_status[drv]);
1343                 out_message(_T("QD%d: Ejected"), drv + QD_BASE_NUMBER);
1344         }
1345 }
1346
1347 bool EMU::is_quick_disk_inserted(int drv)
1348 {
1349         if(drv < MAX_QD) {
1350                 return vm->is_quick_disk_inserted(drv);
1351         } else {
1352                 return false;
1353         }
1354 }
1355 #endif
1356
1357 #ifdef USE_TAPE
1358 void EMU::play_tape(const _TCHAR* file_path)
1359 {
1360         if(vm->is_tape_inserted()) {
1361                 vm->close_tape();
1362                 // wait 0.5sec
1363 #ifdef SUPPORT_VARIABLE_TIMING
1364                 tape_status.wait_count = (int)(vm->get_frame_rate() / 2);
1365 #else
1366                 tape_status.wait_count = (int)(FRAMES_PER_SEC / 2);
1367 #endif
1368                 out_message(_T("CMT: Ejected"));
1369         } else if(tape_status.wait_count == 0) {
1370                 vm->play_tape(file_path);
1371                 out_message(_T("CMT: %s"), file_path);
1372         }
1373         my_tcscpy_s(tape_status.path, _MAX_PATH, file_path);
1374         tape_status.play = true;
1375 }
1376
1377 void EMU::rec_tape(const _TCHAR* file_path)
1378 {
1379         if(vm->is_tape_inserted()) {
1380                 vm->close_tape();
1381                 // wait 0.5sec
1382 #ifdef SUPPORT_VARIABLE_TIMING
1383                 tape_status.wait_count = (int)(vm->get_frame_rate() / 2);
1384 #else
1385                 tape_status.wait_count = (int)(FRAMES_PER_SEC / 2);
1386 #endif
1387                 out_message(_T("CMT: Ejected"));
1388         } else if(tape_status.wait_count == 0) {
1389                 vm->rec_tape(file_path);
1390                 out_message(_T("CMT: %s"), file_path);
1391         }
1392         my_tcscpy_s(tape_status.path, _MAX_PATH, file_path);
1393         tape_status.play = false;
1394 }
1395
1396 void EMU::close_tape()
1397 {
1398         vm->close_tape();
1399         clear_media_status(&tape_status);
1400         out_message(_T("CMT: Ejected"));
1401 }
1402
1403 bool EMU::is_tape_inserted()
1404 {
1405         return vm->is_tape_inserted();
1406 }
1407
1408 #ifndef TAPE_BINARY_ONLY
1409 bool EMU::is_tape_playing()
1410 {
1411         return vm->is_tape_playing();
1412 }
1413
1414 bool EMU::is_tape_recording()
1415 {
1416         return vm->is_tape_recording();
1417 }
1418
1419 int EMU::get_tape_position()
1420 {
1421         return vm->get_tape_position();
1422 }
1423 #endif
1424
1425 #ifdef USE_TAPE_BUTTON
1426 void EMU::push_play()
1427 {
1428         vm->push_play();
1429 }
1430
1431 void EMU::push_stop()
1432 {
1433         vm->push_stop();
1434 }
1435
1436 void EMU::push_fast_forward()
1437 {
1438         vm->push_fast_forward();
1439 }
1440
1441 void EMU::push_fast_rewind()
1442 {
1443         vm->push_fast_rewind();
1444 }
1445
1446 void EMU::push_apss_forward()
1447 {
1448         vm->push_apss_forward();
1449 }
1450
1451 void EMU::push_apss_rewind()
1452 {
1453         vm->push_apss_rewind();
1454 }
1455 #endif
1456 #endif
1457
1458 #ifdef USE_COMPACT_DISC
1459 void EMU::open_compact_disc(const _TCHAR* file_path)
1460 {
1461         if(vm->is_compact_disc_inserted()) {
1462                 vm->close_compact_disc();
1463                 // wait 0.5sec
1464 #ifdef SUPPORT_VARIABLE_TIMING
1465                 compact_disc_status.wait_count = (int)(vm->get_frame_rate() / 2);
1466 #else
1467                 compact_disc_status.wait_count = (int)(FRAMES_PER_SEC / 2);
1468 #endif
1469                 out_message(_T("CD: Ejected"));
1470         } else if(compact_disc_status.wait_count == 0) {
1471                 vm->open_compact_disc(file_path);
1472                 out_message(_T("CD: %s"), file_path);
1473         }
1474         my_tcscpy_s(compact_disc_status.path, _MAX_PATH, file_path);
1475 }
1476
1477 void EMU::close_compact_disc()
1478 {
1479         vm->close_compact_disc();
1480         clear_media_status(&compact_disc_status);
1481         out_message(_T("CD: Ejected"));
1482 }
1483
1484 bool EMU::is_compact_disc_inserted()
1485 {
1486         return vm->is_compact_disc_inserted();
1487 }
1488 #endif
1489
1490 #ifdef USE_LASER_DISC
1491 void EMU::open_laser_disc(const _TCHAR* file_path)
1492 {
1493         if(vm->is_laser_disc_inserted()) {
1494                 vm->close_laser_disc();
1495                 // wait 0.5sec
1496 #ifdef SUPPORT_VARIABLE_TIMING
1497                 laser_disc_status.wait_count = (int)(vm->get_frame_rate() / 2);
1498 #else
1499                 laser_disc_status.wait_count = (int)(FRAMES_PER_SEC / 2);
1500 #endif
1501                 out_message(_T("LD: Ejected"));
1502         } else if(laser_disc_status.wait_count == 0) {
1503                 vm->open_laser_disc(file_path);
1504                 out_message(_T("LD: %s"), file_path);
1505         }
1506         my_tcscpy_s(laser_disc_status.path, _MAX_PATH, file_path);
1507 }
1508
1509 void EMU::close_laser_disc()
1510 {
1511         vm->close_laser_disc();
1512         clear_media_status(&laser_disc_status);
1513         out_message(_T("LD: Ejected"));
1514 }
1515
1516 bool EMU::is_laser_disc_inserted()
1517 {
1518         return vm->is_laser_disc_inserted();
1519 }
1520 #endif
1521
1522 #ifdef USE_BINARY_FILE1
1523 void EMU::load_binary(int drv, const _TCHAR* file_path)
1524 {
1525         if(drv < MAX_BINARY) {
1526                 if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, create_local_path(_T("hex2bin.$$$")))) {
1527                         vm->load_binary(drv, create_local_path(_T("hex2bin.$$$")));
1528                         FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
1529                 } else {
1530                         vm->load_binary(drv, file_path);
1531                 }
1532                 out_message(_T("Load: %s"), file_path);
1533         }
1534 }
1535
1536 void EMU::save_binary(int drv, const _TCHAR* file_path)
1537 {
1538         if(drv < MAX_BINARY) {
1539                 vm->save_binary(drv, file_path);
1540                 out_message(_T("Save: %s"), file_path);
1541         }
1542 }
1543 #endif
1544 #ifdef USE_BUBBLE1
1545 void EMU::open_bubble_casette(int drv, const _TCHAR* file_path, int bank)
1546 {
1547         if(drv < MAX_BUBBLE) {
1548                 if(vm->is_bubble_casette_inserted(drv)) {
1549                         vm->close_bubble_casette(drv);
1550                         // wait 0.5sec
1551 #ifdef SUPPORT_VARIABLE_TIMING
1552                         bubble_casette_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
1553 #else
1554                         bubble_casette_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
1555 #endif
1556                         out_message(_T("Bubble%d: Ejected"), drv + 1);
1557                 } else if(bubble_casette_status[drv].wait_count == 0) {
1558                         vm->open_bubble_casette(drv, file_path, bank);
1559                         out_message(_T("Bubble%d: %s"), drv + 1, file_path);
1560                 }
1561                 my_tcscpy_s(bubble_casette_status[drv].path, _MAX_PATH, file_path);
1562                 bubble_casette_status[drv].bank = bank;
1563         }
1564 }
1565
1566 void EMU::close_bubble_casette(int drv)
1567 {
1568         if(drv < MAX_BUBBLE) {
1569                 vm->close_bubble_casette(drv);
1570                 clear_media_status(&bubble_casette_status[drv]);
1571                 out_message(_T("Bubble%d: Ejected"), drv + 1);
1572         }
1573 }
1574
1575 bool EMU::is_bubble_casette_inserted(int drv)
1576 {
1577         if(drv < MAX_BUBBLE) {
1578                 return vm->is_bubble_casette_inserted(drv);
1579         } else {
1580                 return false;
1581         }
1582 }
1583
1584 bool EMU::is_bubble_casette_protected(int drv)
1585 {
1586         if(drv < MAX_BUBBLE) {
1587                 return vm->is_bubble_casette_protected(drv);
1588         } else {
1589                 return false;
1590         }
1591 }
1592
1593 void EMU::is_bubble_casette_protected(int drv, bool flag)
1594 {
1595         if(drv < MAX_BUBBLE) {
1596                 return vm->is_bubble_casette_protected(drv, flag);
1597         } else {
1598                 return false;
1599         }
1600 }
1601 #endif
1602
1603 #ifdef USE_ACCESS_LAMP
1604 uint32_t EMU::get_access_lamp_status()
1605 {
1606         return vm->get_access_lamp_status();
1607 }
1608 #endif
1609
1610 #ifdef USE_LED_DEVICE
1611 uint32_t EMU::get_led_status()
1612 {
1613         return vm->get_led_status();
1614 }
1615 #endif
1616
1617 #ifdef USE_SOUND_VOLUME
1618 void EMU::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
1619 {
1620         vm->set_sound_device_volume(ch, decibel_l, decibel_r);
1621 }
1622 #endif
1623
1624 void EMU::update_config()
1625 {
1626         vm->update_config();
1627 }
1628
1629
1630
1631 // ----------------------------------------------------------------------------
1632 // state
1633 // ----------------------------------------------------------------------------
1634
1635 #ifdef USE_STATE
1636 #define STATE_VERSION   2
1637
1638 void EMU::save_state()
1639 {
1640         save_state_tmp(create_local_path(_T("%s.sta"), _T(CONFIG_NAME)));
1641 }
1642
1643 void EMU::load_state()
1644 {
1645         if(FILEIO::IsFileExisting(create_local_path(_T("%s.sta"), _T(CONFIG_NAME)))) {
1646                 save_state_tmp(create_local_path(_T("$temp$.sta")));
1647                 if(!load_state_tmp(create_local_path(_T("%s.sta"), _T(CONFIG_NAME)))) {
1648                         out_debug_log(_T("failed to load state file\n"));
1649                         load_state_tmp(create_local_path(_T("$temp$.sta")));
1650                 }
1651                 FILEIO::RemoveFile(create_local_path(_T("$temp$.sta")));
1652         }
1653 }
1654
1655 void EMU::save_state_tmp(const _TCHAR* file_path)
1656 {
1657         FILEIO* fio = new FILEIO();
1658         osd->lock_vm();
1659         if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
1660                 // save state file version
1661                 fio->FputUint32(STATE_VERSION);
1662                 // save config
1663                 save_config_state((void *)fio);
1664                 // save inserted medias
1665 #ifdef USE_CART1
1666                 fio->Fwrite(&cart_status, sizeof(cart_status), 1);
1667 #endif
1668 #ifdef USE_FD1
1669                 fio->Fwrite(floppy_disk_status, sizeof(floppy_disk_status), 1);
1670                 fio->Fwrite(d88_file, sizeof(d88_file), 1);
1671 #endif
1672 #ifdef USE_QD1
1673                 fio->Fwrite(&quick_disk_status, sizeof(quick_disk_status), 1);
1674 #endif
1675 #ifdef USE_TAPE
1676                 fio->Fwrite(&tape_status, sizeof(tape_status), 1);
1677 #endif
1678 #ifdef USE_COMPACT_DISC
1679                 fio->Fwrite(&compact_disc_status, sizeof(compact_disc_status), 1);
1680 #endif
1681 #ifdef USE_LASER_DISC
1682                 fio->Fwrite(&laser_disc_status, sizeof(laser_disc_status), 1);
1683 #endif
1684                 // save vm state
1685                 vm->save_state(fio);
1686                 // end of state file
1687                 fio->FputInt32(-1);
1688                 fio->Fclose();
1689         }
1690         osd->unlock_vm();
1691         delete fio;
1692 }
1693
1694 bool EMU::load_state_tmp(const _TCHAR* file_path)
1695 {
1696         bool result = false;
1697         FILEIO* fio = new FILEIO();
1698         osd->lock_vm();
1699         if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
1700                 // check state file version
1701                 if(fio->FgetUint32() == STATE_VERSION) {
1702                         // load config
1703                         if(load_config_state((void *)fio)) {
1704                                 // load inserted medias
1705 #ifdef USE_CART1
1706                                 fio->Fread(&cart_status, sizeof(cart_status), 1);
1707 #endif
1708 #ifdef USE_FD1
1709                                 fio->Fread(floppy_disk_status, sizeof(floppy_disk_status), 1);
1710                                 fio->Fread(d88_file, sizeof(d88_file), 1);
1711 #endif
1712 #ifdef USE_QD1
1713                                 fio->Fread(&quick_disk_status, sizeof(quick_disk_status), 1);
1714 #endif
1715 #ifdef USE_TAPE
1716                                 fio->Fread(&tape_status, sizeof(tape_status), 1);
1717 #endif
1718 #ifdef USE_COMPACT_DISC
1719                                 fio->Fread(&compact_disc_status, sizeof(compact_disc_status), 1);
1720 #endif
1721 #ifdef USE_LASER_DISC
1722                                 fio->Fread(&laser_disc_status, sizeof(laser_disc_status), 1);
1723 #endif
1724                                 // check if virtual machine should be reinitialized
1725                                 bool reinitialize = false;
1726 #ifdef USE_CPU_TYPE
1727                                 reinitialize |= (cpu_type != config.cpu_type);
1728                                 cpu_type = config.cpu_type;
1729 #endif
1730 #ifdef USE_SOUND_DEVICE_TYPE
1731                                 reinitialize |= (sound_device_type != config.sound_device_type);
1732                                 sound_device_type = config.sound_device_type;
1733 #endif
1734 #ifdef USE_PRINTER
1735                                 reinitialize |= (printer_device_type != config.printer_device_type);
1736                                 printer_device_type = config.printer_device_type;
1737 #endif
1738                                 if(reinitialize) {
1739                                         // stop sound
1740                                         //osd->lock_vm();
1741                                         // reinitialize virtual machine
1742                                         osd->stop_sound();
1743                                         delete vm;
1744                                         osd->vm = vm = new VM(this);
1745                                         vm->initialize_sound(sound_rate, sound_samples);
1746 #ifdef USE_SOUND_VOLUME
1747                                         for(int i = 0; i < USE_SOUND_VOLUME; i++) {
1748                                                 vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
1749                                         }
1750 #endif
1751                                         vm->reset();
1752                                         //osd->unlock_vm();
1753                                 }
1754                                 // restore inserted medias
1755                                 restore_media();
1756                                 // load vm state
1757                                 if(vm->load_state(fio)) {
1758                                         // check end of state
1759                                         result = (fio->FgetInt32() == -1);
1760                                 }
1761                         }
1762                 }
1763                 fio->Fclose();
1764         }
1765         osd->unlock_vm();
1766         delete fio;
1767         return result;
1768 }
1769 #endif