2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
7 [ win32 emulation i/f ]
13 #if defined(_USE_AGAR)
15 #include "agar_main.h"
16 #include "agar_logger.h"
18 # elif defined(_USE_QT)
19 //#include <SDL/SDL.h>
22 #include "mainwidget.h"
23 #include "qt_gldraw.h"
25 #include "agar_logger.h"
29 #ifndef FD_BASE_NUMBER
30 #define FD_BASE_NUMBER 1
32 #ifndef QD_BASE_NUMBER
33 #define QD_BASE_NUMBER 1
36 // ----------------------------------------------------------------------------
38 // ----------------------------------------------------------------------------
40 extern void get_long_full_path_name(_TCHAR* src, _TCHAR* dst);
45 EMU::EMU(class Ui_MainWindow *hwnd, GLDrawClass *hinst)
46 #elif defined(OSD_WIN32)
47 EMU::EMU(HWND hwnd, HINSTANCE hinst)
53 initialize_debug_log();
57 // store main window handle
60 OSVERSIONINFO os_info;
61 os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
62 GetVersionEx(&os_info);
63 vista_or_later = (os_info.dwPlatformId == 2 && os_info.dwMajorVersion >= 6);
69 _TCHAR tmp_path[PATH_MAX], *ptr;
70 my_procname.copy(tmp_path, PATH_MAX, 0);
71 memset(app_path, 0x00, sizeof(app_path));
72 get_long_full_path_name(tmp_path, app_path);
73 //AGAR_DebugLog("APPPATH=%s\n", app_path);
76 _TCHAR tmp_path[_MAX_PATH], *ptr;
77 memset(tmp_path, 0x00, _MAX_PATH);
78 GetModuleFileName(NULL, tmp_path, _MAX_PATH);
79 GetFullPathName(tmp_path, _MAX_PATH, app_path, &ptr);
83 // initialize d88 file info
84 memset(d88_file, 0, sizeof(d88_file));
87 static const int freq_table[8] = {
88 2000, 4000, 8000, 11025, 22050, 44100,
89 #ifdef OVERRIDE_SOUND_FREQ_48000HZ
90 OVERRIDE_SOUND_FREQ_48000HZ,
96 static const double late_table[5] = {0.05, 0.1, 0.2, 0.3, 0.4};
98 if(!(0 <= config.sound_frequency && config.sound_frequency < 8)) {
99 config.sound_frequency = 6; // default: 48KHz
101 if(!(0 <= config.sound_latency && config.sound_latency < 5)) {
102 config.sound_latency = 1; // default: 100msec
104 sound_rate = freq_table[config.sound_frequency];
105 sound_samples = (int)(sound_rate * late_table[config.sound_latency] + 0.5);
108 cpu_type = config.cpu_type;
110 #ifdef USE_SOUND_DEVICE_TYPE
111 sound_device_type = config.sound_device_type;
115 osd->main_window_handle = hwnd;
118 osd->initialize(sound_rate, sound_samples);
120 osd->vm = vm = new VM(this);
123 osd->initialize_printer();
124 vm->initialize_sound(sound_rate, sound_samples);
128 now_suspended = false;
143 EmuThreadClass *EMU::get_parent_handler()
145 return osd->get_parent_handler();
148 void EMU::set_parent_handler(EmuThreadClass *p, DrawThreadClass *q)
150 osd->set_parent_thread(p);
151 osd->set_draw_thread(q);
154 void EMU::set_host_cpus(int v)
156 osd->host_cpus = (v <= 0) ? 1 : v;
159 int EMU::get_host_cpus()
161 return osd->host_cpus;
165 // ----------------------------------------------------------------------------
167 // ----------------------------------------------------------------------------
169 int EMU::frame_interval()
172 #ifdef SUPPORT_VARIABLE_TIMING
173 static int prev_interval = 0;
174 static double prev_fps = -1;
175 double fps = vm->frame_rate();
176 if(prev_fps != fps) {
177 prev_interval = (int)(1024. * 1000. / fps + 0.5);
180 return prev_interval;
182 return (int)(1024. * 1000. / FRAMES_PER_SEC + 0.5);
185 return (int)(1024. * 1000. / FRAMES_PER_SEC + 0.5);
193 now_suspended = false;
196 osd->update_printer();
198 //osd->update_socket();
202 // virtual machine may be driven to fill sound buffer
203 int extra_frames = 0;
204 osd->update_sound(&extra_frames);
205 // drive virtual machine
206 if(extra_frames == 0) {
212 osd->add_extra_frames(extra_frames);
218 // check if virtual machine should be reinitialized
219 bool reinitialize = false;
221 reinitialize |= (cpu_type != config.cpu_type);
222 cpu_type = config.cpu_type;
224 #ifdef USE_SOUND_DEVICE_TYPE
225 reinitialize |= (sound_device_type != config.sound_device_type);
226 sound_device_type = config.sound_device_type;
231 // reinitialize virtual machine
234 osd->vm = vm = new VM(this);
235 vm->initialize_sound(sound_rate, sound_samples);
238 // restore inserted medias
241 // reset virtual machine
248 osd->reset_printer();
250 #if !defined(_USE_QT) // Temporally
252 osd->restart_rec_sound();
253 osd->restart_rec_video();
257 #ifdef USE_SPECIAL_RESET
258 void EMU::special_reset()
260 // reset virtual machine
265 osd->reset_printer();
268 #if !defined(_USE_QT) // Temporally
275 #ifdef USE_NOTIFY_POWER_OFF
276 void EMU::notify_power_off()
278 vm->notify_power_off();
282 void EMU::power_off()
291 now_suspended = true;
300 void EMU::unlock_vm()
305 void EMU::force_unlock_vm()
307 osd->force_unlock_vm();
311 // ----------------------------------------------------------------------------
313 // ----------------------------------------------------------------------------
316 void EMU::key_modifiers(uint32 mod)
318 osd->key_modifiers(mod);
322 void EMU::key_down(int code, bool repeat)
324 osd->key_down(code, repeat);
327 void EMU::key_up(int code)
332 void EMU::key_lost_focus()
334 osd->key_lost_focus();
337 #ifdef ONE_BOARD_MICRO_COMPUTER
338 void EMU::press_button(int num)
340 osd->press_button(num);
344 void EMU::enable_mouse()
349 void EMU::disenable_mouse()
351 osd->disenable_mouse();
354 void EMU::toggle_mouse()
359 bool EMU::get_mouse_enabled()
361 return osd->get_mouse_enabled();
365 void EMU::start_auto_key()
367 osd->start_auto_key();
370 void EMU::stop_auto_key()
372 osd->stop_auto_key();
375 bool EMU::now_auto_key()
377 return osd->now_auto_key();
381 uint8* EMU::key_buffer()
383 return osd->key_buffer();
386 uint32* EMU::joy_buffer()
388 return osd->joy_buffer();
390 int* EMU::mouse_buffer()
392 return osd->mouse_buffer();
395 // ----------------------------------------------------------------------------
397 // ----------------------------------------------------------------------------
399 int EMU::get_window_width(int mode)
401 return osd->get_window_width(mode);
404 int EMU::get_window_height(int mode)
406 return osd->get_window_height(mode);
409 void EMU::set_window_size(int width, int height, bool window_mode)
411 osd->set_window_size(width, height, window_mode);
414 void EMU::set_vm_screen_size(int sw, int sh, int swa, int sha, int ww, int wh)
416 osd->set_vm_screen_size(sw, sh, swa, sha, ww, wh);
419 #if defined(USE_MINIMUM_RENDERING)
420 bool EMU::screen_changed()
422 return vm->screen_changed();
426 int EMU::draw_screen()
428 return osd->draw_screen();
431 scrntype* EMU::screen_buffer(int y)
433 return osd->get_vm_screen_buffer(y);
436 #ifdef USE_CRT_FILTER
437 void EMU::screen_skip_line(bool skip_line)
439 osd->screen_skip_line = skip_line;
443 #ifdef ONE_BOARD_MICRO_COMPUTER
444 void EMU::reload_bitmap()
446 osd->reload_bitmap();
451 void EMU::update_screen(HDC hdc)
453 osd->update_screen(hdc);
457 void EMU::capture_screen()
459 osd->capture_screen();
462 bool EMU::start_rec_video(int fps)
464 return osd->start_rec_video(fps);
467 void EMU::stop_rec_video()
469 osd->stop_rec_video();
472 bool EMU::now_rec_video()
474 return osd->now_rec_video;
477 // ----------------------------------------------------------------------------
479 // ----------------------------------------------------------------------------
481 void EMU::mute_sound()
486 void EMU::start_rec_sound()
488 osd->start_rec_sound();
491 void EMU::stop_rec_sound()
493 osd->stop_rec_sound();
496 bool EMU::now_rec_sound()
498 return osd->now_rec_sound;
501 // ----------------------------------------------------------------------------
503 // ----------------------------------------------------------------------------
505 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
506 void EMU::get_video_buffer()
508 osd->get_video_buffer();
511 void EMU::mute_video_dev(bool l, bool r)
513 osd->mute_video_dev(l, r);
517 #ifdef USE_MOVIE_PLAYER
518 bool EMU::open_movie_file(const _TCHAR* file_path)
520 return osd->open_movie_file(file_path);
523 void EMU::close_movie_file()
525 osd->close_movie_file();
528 void EMU::play_movie()
533 void EMU::stop_movie()
538 void EMU::pause_movie()
543 double EMU::get_movie_frame_rate()
545 return osd->get_movie_frame_rate();
548 int EMU::get_movie_sound_rate()
550 return osd->get_movie_sound_rate();
553 void EMU::set_cur_movie_frame(int frame, bool relative)
555 osd->set_cur_movie_frame(frame, relative);
558 uint32 EMU::get_cur_movie_frame()
560 return osd->get_cur_movie_frame();
564 #ifdef USE_VIDEO_CAPTURE
565 int EMU::get_cur_capture_dev_index()
567 return osd->get_cur_capture_dev_index();
570 int EMU::get_num_capture_devs()
572 return osd->get_num_capture_devs();
575 _TCHAR* EMU::get_capture_dev_name(int index)
577 return osd->get_capture_dev_name(index);
580 void EMU::open_capture_dev(int index, bool pin)
582 osd->open_capture_dev(index, pin);
585 void EMU::close_capture_dev()
587 osd->close_capture_dev();
590 void EMU::show_capture_dev_filter()
592 osd->show_capture_dev_filter();
595 void EMU::show_capture_dev_pin()
597 osd->show_capture_dev_pin();
600 void EMU::show_capture_dev_source()
602 osd->show_capture_dev_source();
605 void EMU::set_capture_dev_channel(int ch)
607 osd->set_capture_dev_channel(ch);
611 // ----------------------------------------------------------------------------
613 // ----------------------------------------------------------------------------
615 void EMU::printer_out(uint8 value)
617 osd->printer_out(value);
620 void EMU::printer_strobe(bool value)
622 osd->printer_strobe(value);
625 // ----------------------------------------------------------------------------
627 // ----------------------------------------------------------------------------
630 int EMU::get_socket(int ch)
632 return osd->get_socket(ch);
635 void EMU::socket_connected(int ch)
637 osd->socket_connected(ch);
640 void EMU::socket_disconnected(int ch)
642 osd->socket_disconnected(ch);
645 bool EMU::init_socket_tcp(int ch)
647 return osd->init_socket_tcp(ch);
650 bool EMU::init_socket_udp(int ch)
652 return osd->init_socket_udp(ch);
655 bool EMU::connect_socket(int ch, uint32 ipaddr, int port)
657 return osd->connect_socket(ch, ipaddr, port);
660 void EMU::disconnect_socket(int ch)
662 osd->disconnect_socket(ch);
665 bool EMU::listen_socket(int ch)
667 return osd->listen_socket(ch);
670 void EMU::send_data_tcp(int ch)
672 osd->send_data_tcp(ch);
675 void EMU::send_data_udp(int ch, uint32 ipaddr, int port)
677 osd->send_data_udp(ch, ipaddr, port);
680 void EMU::send_data(int ch)
685 void EMU::recv_data(int ch)
691 // ----------------------------------------------------------------------------
693 // ----------------------------------------------------------------------------
696 void EMU::initialize_debug_log()
698 #if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
701 TCHAR path[_MAX_PATH];
702 debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
706 void EMU::release_debug_log()
708 #if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
719 void EMU::out_debug_log(const _TCHAR* format, ...)
724 static _TCHAR prev_buffer[1024] = {0};
726 va_start(ap, format);
727 my_vstprintf_s(buffer, 1024, format, ap);
730 #if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
731 AGAR_DebugLog(AGAR_LOG_DEBUG, "%s", buffer);
733 if(my_tcscmp(prev_buffer, buffer) == 0) {
736 my_tcscpy_s(prev_buffer, 1024, buffer);
738 _ftprintf(debug_log, _T("%s"), buffer);
740 if((size += _tcslen(buffer)) > 0x8000000) { // 128MB
742 debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
750 void EMU::out_message(const _TCHAR* format, ...)
753 va_start(ap, format);
754 my_vstprintf_s(message, 260, format, ap); // Security for MSVC:C6386.
756 message_count = 4; // 4sec
759 // ----------------------------------------------------------------------------
761 // ----------------------------------------------------------------------------
764 void EMU::sleep(uint32 ms)
770 // ----------------------------------------------------------------------------
772 // ----------------------------------------------------------------------------
774 static uint8 hex2uint8(char *value)
777 memset(tmp, 0, sizeof(tmp));
778 memcpy(tmp, value, 2);
779 return (uint8)strtoul(tmp, NULL, 16);
782 static uint16 hex2uint16(char *value)
785 memset(tmp, 0, sizeof(tmp));
786 memcpy(tmp, value, 4);
787 return (uint16)strtoul(tmp, NULL, 16);
790 static bool hex2bin(const _TCHAR* file_path, const _TCHAR* dest_path)
793 FILEIO *fio_s = new FILEIO();
794 if(fio_s->Fopen(file_path, FILEIO_READ_BINARY)) {
797 uint8 buffer[0x10000];
798 memset(buffer, 0xff, sizeof(buffer));
799 while(fio_s->Fgets(line, sizeof(line)) != NULL) {
800 if(line[0] != ':') continue;
801 int bytes = hex2uint8(line + 1);
802 int offset = hex2uint16(line + 3);
803 uint8 record_type = hex2uint8(line + 7);
804 if(record_type == 0x01) break;
805 if(record_type != 0x00) continue;
806 for(int i = 0; i < bytes; i++) {
807 if(offset + i < sizeof(buffer)) {
808 if(length < offset + i) {
811 buffer[offset + i] = hex2uint8(line + 9 + 2 * i);
816 FILEIO *fio_d = new FILEIO();
817 if(fio_d->Fopen(dest_path, FILEIO_WRITE_BINARY)) {
818 fio_d->Fwrite(buffer, length, 1);
830 void EMU::initialize_media()
833 memset(&cart_status, 0, sizeof(cart_status));
836 memset(disk_status, 0, sizeof(disk_status));
839 memset(&quickdisk_status, 0, sizeof(quickdisk_status));
842 memset(&tape_status, 0, sizeof(tape_status));
844 #ifdef USE_LASER_DISC
845 memset(&laser_disc_status, 0, sizeof(laser_disc_status));
850 void EMU::update_media()
853 for(int drv = 0; drv < MAX_FD; drv++) {
854 if(disk_status[drv].wait_count != 0 && --disk_status[drv].wait_count == 0) {
855 vm->open_disk(drv, disk_status[drv].path, disk_status[drv].bank);
856 out_message(_T("FD%d: %s"), drv + FD_BASE_NUMBER, disk_status[drv].path);
861 for(int drv = 0; drv < MAX_QD; drv++) {
862 if(quickdisk_status[drv].wait_count != 0 && --quickdisk_status[drv].wait_count == 0) {
863 vm->open_quickdisk(drv, quickdisk_status[drv].path);
864 out_message(_T("QD%d: %s"), drv + QD_BASE_NUMBER, quickdisk_status[drv].path);
869 if(tape_status.wait_count != 0 && --tape_status.wait_count == 0) {
870 if(tape_status.play) {
871 vm->play_tape(tape_status.path);
873 vm->rec_tape(tape_status.path);
875 out_message(_T("CMT: %s"), tape_status.path);
878 #ifdef USE_LASER_DISC
879 if(laser_disc_status.wait_count != 0 && --laser_disc_status.wait_count == 0) {
880 vm->open_laser_disc(laser_disc_status.path);
881 out_message(_T("LD: %s"), laser_disc_status.path);
886 void EMU::restore_media()
889 for(int drv = 0; drv < MAX_CART; drv++) {
890 if(cart_status[drv].path[0] != _T('\0')) {
891 if(check_file_extension(cart_status[drv].path, _T(".hex")) && hex2bin(cart_status[drv].path, create_local_path(_T("hex2bin.$$$")))) {
892 vm->open_cart(drv, create_local_path(_T("hex2bin.$$$")));
893 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
895 vm->open_cart(drv, cart_status[drv].path);
901 for(int drv = 0; drv < MAX_FD; drv++) {
902 if(disk_status[drv].path[0] != _T('\0')) {
903 vm->open_disk(drv, disk_status[drv].path, disk_status[drv].bank);
908 for(int drv = 0; drv < MAX_QD; drv++) {
909 if(quickdisk_status[drv].path[0] != _T('\0')) {
910 vm->open_quickdisk(drv, quickdisk_status[drv].path);
915 if(tape_status.path[0] != _T('\0')) {
916 if(tape_status.play) {
917 vm->play_tape(tape_status.path);
919 tape_status.path[0] = _T('\0');
923 #ifdef USE_LASER_DISC
924 if(laser_disc_status.path[0] != _T('\0')) {
925 vm->open_laser_disc(laser_disc_status.path);
931 void EMU::open_cart(int drv, const _TCHAR* file_path)
934 if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, create_local_path(_T("hex2bin.$$$")))) {
935 vm->open_cart(drv, create_local_path(_T("hex2bin.$$$")));
936 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
938 vm->open_cart(drv, file_path);
940 my_tcscpy_s(cart_status[drv].path, _MAX_PATH, file_path);
941 out_message(_T("Cart%d: %s"), drv + 1, file_path);
944 bool s = osd->now_rec_sound;
945 bool v = osd->now_rec_video;
948 if(s) osd->start_rec_sound();
949 if(v) osd->start_rec_video(-1);
953 void EMU::close_cart(int drv)
957 clear_media_status(&cart_status[drv]);
958 out_message(_T("Cart%d: Ejected"), drv + 1);
966 bool EMU::cart_inserted(int drv)
969 return vm->cart_inserted(drv);
977 void EMU::open_disk(int drv, const _TCHAR* file_path, int bank)
980 if(vm->disk_inserted(drv)) {
983 #ifdef SUPPORT_VARIABLE_TIMING
984 disk_status[drv].wait_count = (int)(vm->frame_rate() / 2);
986 disk_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
988 out_message(_T("FD%d: Ejected"), drv + FD_BASE_NUMBER);
989 } else if(disk_status[drv].wait_count == 0) {
990 vm->open_disk(drv, file_path, bank);
991 out_message(_T("FD%d: %s"), drv + FD_BASE_NUMBER, file_path);
993 my_tcscpy_s(disk_status[drv].path, _MAX_PATH, file_path);
994 disk_status[drv].bank = bank;
998 void EMU::close_disk(int drv)
1001 vm->close_disk(drv);
1002 clear_media_status(&disk_status[drv]);
1003 out_message(_T("FD%d: Ejected"), drv + FD_BASE_NUMBER);
1007 bool EMU::disk_inserted(int drv)
1010 return vm->disk_inserted(drv);
1016 void EMU::set_disk_protected(int drv, bool value)
1019 vm->set_disk_protected(drv, value);
1023 bool EMU::get_disk_protected(int drv)
1026 return vm->get_disk_protected(drv);
1033 int EMU::get_access_lamp(void)
1036 #if defined(USE_ACCESS_LAMP)
1037 # if defined(USE_FD1) || defined(USE_QD1)
1038 # if !defined(_MSC_VER)
1042 stat = vm->access_lamp(); // Return accessing drive number.
1043 # if !defined(_MSC_VER)
1053 void EMU::open_quickdisk(int drv, const _TCHAR* file_path)
1056 if(vm->quickdisk_inserted(drv)) {
1057 vm->close_quickdisk(drv);
1059 #ifdef SUPPORT_VARIABLE_TIMING
1060 quickdisk_status[drv].wait_count = (int)(vm->frame_rate() / 2);
1062 quickdisk_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
1064 out_message(_T("QD%d: Ejected"), drv + QD_BASE_NUMBER);
1065 } else if(quickdisk_status[drv].wait_count == 0) {
1066 vm->open_quickdisk(drv, file_path);
1067 out_message(_T("QD%d: %s"), drv + QD_BASE_NUMBER, file_path);
1069 my_tcscpy_s(quickdisk_status[drv].path, _MAX_PATH, file_path);
1073 void EMU::close_quickdisk(int drv)
1076 vm->close_quickdisk(drv);
1077 clear_media_status(&quickdisk_status[drv]);
1078 out_message(_T("QD%d: Ejected"), drv + QD_BASE_NUMBER);
1082 bool EMU::quickdisk_inserted(int drv)
1085 return vm->quickdisk_inserted(drv);
1093 void EMU::play_tape(const _TCHAR* file_path)
1095 if(vm->tape_inserted()) {
1098 #ifdef SUPPORT_VARIABLE_TIMING
1099 tape_status.wait_count = (int)(vm->frame_rate() / 2);
1101 tape_status.wait_count = (int)(FRAMES_PER_SEC / 2);
1103 out_message(_T("CMT: Ejected"));
1104 } else if(tape_status.wait_count == 0) {
1105 vm->play_tape(file_path);
1106 out_message(_T("CMT: %s"), file_path);
1108 my_tcscpy_s(tape_status.path, _MAX_PATH, file_path);
1109 tape_status.play = true;
1112 void EMU::rec_tape(const _TCHAR* file_path)
1114 if(vm->tape_inserted()) {
1117 #ifdef SUPPORT_VARIABLE_TIMING
1118 tape_status.wait_count = (int)(vm->frame_rate() / 2);
1120 tape_status.wait_count = (int)(FRAMES_PER_SEC / 2);
1122 out_message(_T("CMT: Ejected"));
1123 } else if(tape_status.wait_count == 0) {
1124 vm->rec_tape(file_path);
1125 out_message(_T("CMT: %s"), file_path);
1127 my_tcscpy_s(tape_status.path, _MAX_PATH, file_path);
1128 tape_status.play = false;
1131 void EMU::close_tape()
1134 clear_media_status(&tape_status);
1135 out_message(_T("CMT: Ejected"));
1138 bool EMU::tape_inserted()
1140 return vm->tape_inserted();
1143 #ifndef TAPE_BINARY_ONLY
1144 bool EMU::tape_playing()
1146 return vm->tape_playing();
1149 bool EMU::tape_recording()
1151 return vm->tape_recording();
1154 int EMU::tape_position()
1156 return vm->tape_position();
1160 #ifdef USE_TAPE_BUTTON
1161 void EMU::push_play()
1166 void EMU::push_stop()
1171 void EMU::push_fast_forward()
1173 vm->push_fast_forward();
1176 void EMU::push_fast_rewind()
1178 vm->push_fast_rewind();
1181 void EMU::push_apss_forward()
1183 vm->push_apss_forward();
1186 void EMU::push_apss_rewind()
1188 vm->push_apss_rewind();
1193 #ifdef USE_LASER_DISC
1194 void EMU::open_laser_disc(const _TCHAR* file_path)
1196 if(vm->laser_disc_inserted()) {
1197 vm->close_laser_disc();
1199 #ifdef SUPPORT_VARIABLE_TIMING
1200 laser_disc_status.wait_count = (int)(vm->frame_rate() / 2);
1202 laser_disc_status.wait_count = (int)(FRAMES_PER_SEC / 2);
1204 out_message(_T("LD: Ejected"));
1205 } else if(laser_disc_status.wait_count == 0) {
1206 vm->open_laser_disc(file_path);
1207 out_message(_T("LD: %s"), file_path);
1209 my_tcscpy_s(laser_disc_status.path, _MAX_PATH, file_path);
1212 void EMU::close_laser_disc()
1214 vm->close_laser_disc();
1215 clear_media_status(&laser_disc_status);
1216 out_message(_T("LD: Ejected"));
1219 bool EMU::laser_disc_inserted()
1221 return vm->laser_disc_inserted();
1225 #ifdef USE_BINARY_FILE1
1226 void EMU::load_binary(int drv, const _TCHAR* file_path)
1228 if(drv < MAX_BINARY) {
1229 if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, create_local_path(_T("hex2bin.$$$")))) {
1230 vm->load_binary(drv, create_local_path(_T("hex2bin.$$$")));
1231 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
1233 vm->load_binary(drv, file_path);
1235 out_message(_T("Load: %s"), file_path);
1239 void EMU::save_binary(int drv, const _TCHAR* file_path)
1241 if(drv < MAX_BINARY) {
1242 vm->save_binary(drv, file_path);
1243 out_message(_T("Save: %s"), file_path);
1247 #ifdef SUPPORT_DUMMY_DEVICE_LED
1248 uint32 EMU::get_led_status(void)
1250 return vm->get_led_status();
1254 bool EMU::now_skip()
1256 return vm->now_skip();
1259 void EMU::update_config()
1261 vm->update_config();
1266 // ----------------------------------------------------------------------------
1268 // ----------------------------------------------------------------------------
1271 #define STATE_VERSION 2
1273 void EMU::save_state()
1275 save_state_tmp(create_local_path(_T("%s.sta"), _T(CONFIG_NAME)));
1278 void EMU::load_state()
1280 const _TCHAR *file_name = create_local_path(_T("%s.sta"), _T(CONFIG_NAME));
1281 if(FILEIO::IsFileExists(file_name)) {
1282 save_state_tmp(create_local_path(_T("$temp$.sta")));
1283 if(!load_state_tmp(file_name)) {
1284 out_debug_log("failed to load state file\n");
1285 load_state_tmp(create_local_path(_T("$temp$.sta")));
1287 FILEIO::RemoveFile(create_local_path(_T("$temp$.sta")));
1291 void EMU::save_state_tmp(const _TCHAR* file_path)
1293 FILEIO* fio = new FILEIO();
1295 if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
1296 // save state file version
1297 fio->FputUint32(STATE_VERSION);
1299 save_config_state((void *)fio);
1300 // save inserted medias
1302 fio->Fwrite(&cart_status, sizeof(cart_status), 1);
1305 fio->Fwrite(disk_status, sizeof(disk_status), 1);
1306 fio->Fwrite(d88_file, sizeof(d88_file), 1);
1309 fio->Fwrite(&quickdisk_status, sizeof(quickdisk_status), 1);
1312 fio->Fwrite(&tape_status, sizeof(tape_status), 1);
1314 #ifdef USE_LASER_DISC
1315 fio->Fwrite(&laser_disc_status, sizeof(laser_disc_status), 1);
1318 vm->save_state(fio);
1319 // end of state file
1327 bool EMU::load_state_tmp(const _TCHAR* file_path)
1329 bool result = false;
1330 FILEIO* fio = new FILEIO();
1332 if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
1333 // check state file version
1334 if(fio->FgetUint32() == STATE_VERSION) {
1336 if(load_config_state((void *)fio)) {
1337 // load inserted medias
1339 fio->Fread(&cart_status, sizeof(cart_status), 1);
1342 fio->Fread(disk_status, sizeof(disk_status), 1);
1343 fio->Fread(d88_file, sizeof(d88_file), 1);
1346 fio->Fread(&quickdisk_status, sizeof(quickdisk_status), 1);
1349 fio->Fread(&tape_status, sizeof(tape_status), 1);
1351 #ifdef USE_LASER_DISC
1352 fio->Fread(&laser_disc_status, sizeof(laser_disc_status), 1);
1354 // check if virtual machine should be reinitialized
1355 bool reinitialize = false;
1357 reinitialize |= (cpu_type != config.cpu_type);
1358 cpu_type = config.cpu_type;
1360 #ifdef USE_SOUND_DEVICE_TYPE
1361 reinitialize |= (sound_device_type != config.sound_device_type);
1362 sound_device_type = config.sound_device_type;
1367 // reinitialize virtual machine
1370 osd->vm = vm = new VM(this);
1371 vm->initialize_sound(sound_rate, sound_samples);
1375 // restore inserted medias
1378 if(vm->load_state(fio)) {
1379 // check end of state
1380 result = (fio->FgetInt32() == -1);
1392 #if defined(USE_DIG_RESOLUTION)
1393 void EMU::get_screen_resolution(int *w, int *h)
1395 vm->get_screen_resolution(w, h);