2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
7 [ win32 emulation i/f ]
14 #ifndef FD_BASE_NUMBER
15 #define FD_BASE_NUMBER 1
17 #ifndef QD_BASE_NUMBER
18 #define QD_BASE_NUMBER 1
21 // ----------------------------------------------------------------------------
23 // ----------------------------------------------------------------------------
25 // Please permit at least them m(.. )m
26 extern void get_long_full_path_name(_TCHAR* src, _TCHAR* dst);
31 EMU::EMU(class Ui_MainWindow *hwnd, GLDrawClass *hinst)
32 #elif defined(OSD_WIN32)
33 EMU::EMU(HWND hwnd, HINSTANCE hinst)
39 // store main window handle
41 // initialize d88 file info
42 memset(d88_file, 0, sizeof(d88_file));
45 static const int freq_table[8] = {
46 2000, 4000, 8000, 11025, 22050, 44100,
47 #ifdef OVERRIDE_SOUND_FREQ_48000HZ
48 OVERRIDE_SOUND_FREQ_48000HZ,
54 static const double late_table[5] = {0.05, 0.1, 0.2, 0.3, 0.4};
56 if(!(0 <= config.sound_frequency && config.sound_frequency < 8)) {
57 config.sound_frequency = 6; // default: 48KHz
59 if(!(0 <= config.sound_latency && config.sound_latency < 5)) {
60 config.sound_latency = 1; // default: 100msec
62 sound_rate = freq_table[config.sound_frequency];
63 sound_samples = (int)(sound_rate * late_table[config.sound_latency] + 0.5);
66 cpu_type = config.cpu_type;
68 #ifdef USE_SOUND_DEVICE_TYPE
69 sound_device_type = config.sound_device_type;
72 printer_device_type = config.printer_device_type;
78 osd->main_window_handle = hwnd;
81 #elif defined(OSD_WIN32)
82 osd->main_window_handle = hwnd;
83 osd->instance_handle = hinst;
85 osd->initialize(sound_rate, sound_samples);
86 osd->vm = vm = new VM(this);
88 initialize_debugger();
91 vm->initialize_sound(sound_rate, sound_samples);
94 now_suspended = false;
111 EmuThreadClass *EMU::get_parent_handler()
113 return osd->get_parent_handler();
116 void EMU::set_parent_handler(EmuThreadClass *p, DrawThreadClass *q)
118 osd->set_parent_thread(p);
119 osd->set_draw_thread(q);
122 void EMU::set_host_cpus(int v)
124 osd->host_cpus = (v <= 0) ? 1 : v;
127 int EMU::get_host_cpus()
129 return osd->host_cpus;
133 // ----------------------------------------------------------------------------
135 // ----------------------------------------------------------------------------
137 int EMU::frame_interval()
139 #ifdef SUPPORT_VARIABLE_TIMING
140 static int prev_interval = 0;
141 static double prev_fps = -1;
142 double fps = vm->frame_rate();
143 if(prev_fps != fps) {
144 prev_interval = (int)(1024. * 1000. / fps + 0.5);
147 return prev_interval;
149 return (int)(1024. * 1000. / FRAMES_PER_SEC + 0.5);
155 return vm->now_skip();
162 now_suspended = false;
166 //osd->update_socket();
170 // virtual machine may be driven to fill sound buffer
171 int extra_frames = 0;
172 osd->update_sound(&extra_frames);
174 // drive virtual machine
175 if(extra_frames == 0) {
181 osd->add_extra_frames(extra_frames);
187 // check if virtual machine should be reinitialized
188 bool reinitialize = false;
190 reinitialize |= (cpu_type != config.cpu_type);
191 cpu_type = config.cpu_type;
193 #ifdef USE_SOUND_DEVICE_TYPE
194 reinitialize |= (sound_device_type != config.sound_device_type);
195 sound_device_type = config.sound_device_type;
198 reinitialize |= (printer_device_type != config.printer_device_type);
199 printer_device_type = config.printer_device_type;
204 // reinitialize virtual machine
207 osd->vm = vm = new VM(this);
208 vm->initialize_sound(sound_rate, sound_samples);
211 // restore inserted medias
214 // reset virtual machine
220 #if !defined(_USE_QT) // Temporally
222 osd->restart_rec_sound();
223 osd->restart_rec_video();
227 #ifdef USE_SPECIAL_RESET
228 void EMU::special_reset()
230 // reset virtual machine
235 #if !defined(_USE_QT) // Temporally
242 #ifdef USE_NOTIFY_POWER_OFF
243 void EMU::notify_power_off()
245 vm->notify_power_off();
249 void EMU::power_off()
258 now_suspended = true;
267 void EMU::unlock_vm()
272 void EMU::force_unlock_vm()
274 osd->force_unlock_vm();
278 // ----------------------------------------------------------------------------
280 // ----------------------------------------------------------------------------
283 void EMU::key_modifiers(uint32 mod)
285 osd->key_modifiers(mod);
288 void EMU::set_mouse_pointer(int x, int y)
290 osd->set_mouse_pointer(x, y);
293 void EMU::set_mouse_button(int button)
295 osd->set_mouse_button(button);
298 int EMU::get_mouse_button()
300 return osd->get_mouse_button();
305 void EMU::key_down(int code, bool repeat)
307 osd->key_down(code, repeat);
310 void EMU::key_up(int code)
315 void EMU::key_lost_focus()
317 osd->key_lost_focus();
320 #ifdef ONE_BOARD_MICRO_COMPUTER
321 void EMU::press_button(int num)
323 osd->press_button(num);
327 void EMU::enable_mouse()
332 void EMU::disenable_mouse()
334 osd->disenable_mouse();
337 void EMU::toggle_mouse()
342 bool EMU::get_mouse_enabled()
344 return osd->get_mouse_enabled();
348 void EMU::start_auto_key()
350 osd->start_auto_key();
353 void EMU::stop_auto_key()
355 osd->stop_auto_key();
358 bool EMU::now_auto_key()
360 return osd->now_auto_key();
364 uint8* EMU::key_buffer()
366 return osd->key_buffer();
369 uint32* EMU::joy_buffer()
371 return osd->joy_buffer();
373 int* EMU::mouse_buffer()
375 return osd->mouse_buffer();
378 // ----------------------------------------------------------------------------
380 // ----------------------------------------------------------------------------
382 int EMU::get_window_width(int mode)
384 return osd->get_window_width(mode);
387 int EMU::get_window_height(int mode)
389 return osd->get_window_height(mode);
392 void EMU::set_window_size(int width, int height, bool window_mode)
394 osd->set_window_size(width, height, window_mode);
397 void EMU::set_vm_screen_size(int sw, int sh, int swa, int sha, int ww, int wh)
399 osd->set_vm_screen_size(sw, sh, swa, sha, ww, wh);
402 #if defined(USE_MINIMUM_RENDERING)
403 bool EMU::screen_changed()
405 return vm->screen_changed();
409 int EMU::draw_screen()
411 return osd->draw_screen();
414 scrntype* EMU::screen_buffer(int y)
416 return osd->get_vm_screen_buffer(y);
419 #ifdef USE_CRT_FILTER
420 void EMU::screen_skip_line(bool skip_line)
422 osd->screen_skip_line = skip_line;
426 #ifdef ONE_BOARD_MICRO_COMPUTER
427 void EMU::reload_bitmap()
429 osd->reload_bitmap();
434 void EMU::update_screen(HDC hdc)
436 osd->update_screen(hdc);
440 void EMU::capture_screen()
442 osd->capture_screen();
445 bool EMU::start_rec_video(int fps)
447 return osd->start_rec_video(fps);
450 void EMU::stop_rec_video()
452 osd->stop_rec_video();
455 bool EMU::now_rec_video()
457 return osd->now_rec_video;
460 // ----------------------------------------------------------------------------
462 // ----------------------------------------------------------------------------
464 void EMU::mute_sound()
469 void EMU::start_rec_sound()
471 osd->start_rec_sound();
474 void EMU::stop_rec_sound()
476 osd->stop_rec_sound();
479 bool EMU::now_rec_sound()
481 return osd->now_rec_sound;
484 // ----------------------------------------------------------------------------
486 // ----------------------------------------------------------------------------
488 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
489 void EMU::get_video_buffer()
491 osd->get_video_buffer();
494 void EMU::mute_video_dev(bool l, bool r)
496 osd->mute_video_dev(l, r);
500 #ifdef USE_MOVIE_PLAYER
501 bool EMU::open_movie_file(const _TCHAR* file_path)
503 return osd->open_movie_file(file_path);
506 void EMU::close_movie_file()
508 osd->close_movie_file();
511 void EMU::play_movie()
516 void EMU::stop_movie()
521 void EMU::pause_movie()
526 double EMU::get_movie_frame_rate()
528 return osd->get_movie_frame_rate();
531 int EMU::get_movie_sound_rate()
533 return osd->get_movie_sound_rate();
536 void EMU::set_cur_movie_frame(int frame, bool relative)
538 osd->set_cur_movie_frame(frame, relative);
541 uint32 EMU::get_cur_movie_frame()
543 return osd->get_cur_movie_frame();
547 #ifdef USE_VIDEO_CAPTURE
548 int EMU::get_cur_capture_dev_index()
550 return osd->get_cur_capture_dev_index();
553 int EMU::get_num_capture_devs()
555 return osd->get_num_capture_devs();
558 _TCHAR* EMU::get_capture_dev_name(int index)
560 return osd->get_capture_dev_name(index);
563 void EMU::open_capture_dev(int index, bool pin)
565 osd->open_capture_dev(index, pin);
568 void EMU::close_capture_dev()
570 osd->close_capture_dev();
573 void EMU::show_capture_dev_filter()
575 osd->show_capture_dev_filter();
578 void EMU::show_capture_dev_pin()
580 osd->show_capture_dev_pin();
583 void EMU::show_capture_dev_source()
585 osd->show_capture_dev_source();
588 void EMU::set_capture_dev_channel(int ch)
590 osd->set_capture_dev_channel(ch);
594 // ----------------------------------------------------------------------------
596 // ----------------------------------------------------------------------------
599 void EMU::create_bitmap(bitmap_t *bitmap, int width, int height)
601 osd->create_bitmap(bitmap, width, height);
604 void EMU::release_bitmap(bitmap_t *bitmap)
606 osd->release_bitmap(bitmap);
609 void EMU::create_font(font_t *font, const _TCHAR *family, int width, int height, int rotate, bool bold, bool italic)
611 osd->create_font(font, family, width, height, rotate, bold, italic);
614 void EMU::release_font(font_t *font)
616 osd->release_font(font);
619 void EMU::create_pen(pen_t *pen, int width, uint8 r, uint8 g, uint8 b)
621 osd->create_pen(pen, width, r, g, b);
624 void EMU::release_pen(pen_t *pen)
626 osd->release_pen(pen);
629 void EMU::clear_bitmap(bitmap_t *bitmap, uint8 r, uint8 g, uint8 b)
631 osd->clear_bitmap(bitmap, r, g, b);
634 int EMU::get_text_width(bitmap_t *bitmap, font_t *font, const char *text)
636 return osd->get_text_width(bitmap, font, text);
639 void EMU::draw_text_to_bitmap(bitmap_t *bitmap, font_t *font, int x, int y, const char *text, uint8 r, uint8 g, uint8 b)
641 osd->draw_text_to_bitmap(bitmap, font, x, y, text, r, g, b);
644 void EMU::draw_line_to_bitmap(bitmap_t *bitmap, pen_t *pen, int sx, int sy, int ex, int ey)
646 osd->draw_line_to_bitmap(bitmap, pen, sx, sy, ex, ey);
649 void EMU::draw_rectangle_to_bitmap(bitmap_t *bitmap, int x, int y, int width, int height, uint8 r, uint8 g, uint8 b)
651 osd->draw_rectangle_to_bitmap(bitmap, x, y, width, height, r, g, b);
654 void EMU::draw_point_to_bitmap(bitmap_t *bitmap, int x, int y, uint8 r, uint8 g, uint8 b)
656 osd->draw_point_to_bitmap(bitmap, x, y, r, g, b);
659 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)
661 osd->stretch_bitmap(dest, dest_x, dest_y, dest_width, dest_height, source, source_x, source_y, source_width, source_height);
664 void EMU::write_bitmap_to_file(bitmap_t *bitmap, const _TCHAR *file_path)
666 osd->write_bitmap_to_file(bitmap, file_path);
670 // ----------------------------------------------------------------------------
672 // ----------------------------------------------------------------------------
675 int EMU::get_socket(int ch)
677 return osd->get_socket(ch);
680 void EMU::socket_connected(int ch)
682 osd->socket_connected(ch);
685 void EMU::socket_disconnected(int ch)
687 osd->socket_disconnected(ch);
690 bool EMU::init_socket_tcp(int ch)
692 return osd->init_socket_tcp(ch);
695 bool EMU::init_socket_udp(int ch)
697 return osd->init_socket_udp(ch);
700 bool EMU::connect_socket(int ch, uint32 ipaddr, int port)
702 return osd->connect_socket(ch, ipaddr, port);
705 void EMU::disconnect_socket(int ch)
707 osd->disconnect_socket(ch);
710 bool EMU::listen_socket(int ch)
712 return osd->listen_socket(ch);
715 void EMU::send_data_tcp(int ch)
717 osd->send_data_tcp(ch);
720 void EMU::send_data_udp(int ch, uint32 ipaddr, int port)
722 osd->send_data_udp(ch, ipaddr, port);
725 void EMU::send_data(int ch)
730 void EMU::recv_data(int ch)
736 // ----------------------------------------------------------------------------
738 // ----------------------------------------------------------------------------
741 void EMU::initialize_debug_log()
743 _TCHAR path[_MAX_PATH];
744 debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
747 void EMU::release_debug_log()
756 void EMU::out_debug_log(const _TCHAR* format, ...)
761 static _TCHAR prev_buffer[1024] = {0};
763 va_start(ap, format);
764 my_vstprintf_s(buffer, 1024, format, ap);
767 #if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
768 AGAR_DebugLog(AGAR_LOG_DEBUG, "%s", buffer);
770 if(my_tcscmp(prev_buffer, buffer) == 0) {
773 my_tcscpy_s(prev_buffer, 1024, buffer);
775 _ftprintf(debug_log, _T("%s"), buffer);
777 if((size += _tcslen(buffer)) > 0x8000000) { // 128MB
779 debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
787 void EMU::out_message(const _TCHAR* format, ...)
790 va_start(ap, format);
791 my_vstprintf_s(message, 1024, format, ap); // Security for MSVC:C6386.
793 message_count = 4; // 4sec
796 // ----------------------------------------------------------------------------
798 // ----------------------------------------------------------------------------
801 void EMU::sleep(uint32 ms)
807 // ----------------------------------------------------------------------------
809 // ----------------------------------------------------------------------------
811 static uint8 hex2uint8(char *value)
814 memset(tmp, 0, sizeof(tmp));
815 memcpy(tmp, value, 2);
816 return (uint8)strtoul(tmp, NULL, 16);
819 static uint16 hex2uint16(char *value)
822 memset(tmp, 0, sizeof(tmp));
823 memcpy(tmp, value, 4);
824 return (uint16)strtoul(tmp, NULL, 16);
827 static bool hex2bin(const _TCHAR* file_path, const _TCHAR* dest_path)
830 FILEIO *fio_s = new FILEIO();
831 if(fio_s->Fopen(file_path, FILEIO_READ_BINARY)) {
834 uint8 buffer[0x10000];
835 memset(buffer, 0xff, sizeof(buffer));
836 while(fio_s->Fgets(line, sizeof(line)) != NULL) {
837 if(line[0] != ':') continue;
838 int bytes = hex2uint8(line + 1);
839 int offset = hex2uint16(line + 3);
840 uint8 record_type = hex2uint8(line + 7);
841 if(record_type == 0x01) break;
842 if(record_type != 0x00) continue;
843 for(int i = 0; i < bytes; i++) {
844 if(offset + i < sizeof(buffer)) {
845 if(length < offset + i) {
848 buffer[offset + i] = hex2uint8(line + 9 + 2 * i);
853 FILEIO *fio_d = new FILEIO();
854 if(fio_d->Fopen(dest_path, FILEIO_WRITE_BINARY)) {
855 fio_d->Fwrite(buffer, length, 1);
867 void EMU::initialize_media()
870 memset(&cart_status, 0, sizeof(cart_status));
873 memset(disk_status, 0, sizeof(disk_status));
876 memset(&quickdisk_status, 0, sizeof(quickdisk_status));
879 memset(&tape_status, 0, sizeof(tape_status));
881 #ifdef USE_LASER_DISC
882 memset(&laser_disc_status, 0, sizeof(laser_disc_status));
887 void EMU::update_media()
890 for(int drv = 0; drv < MAX_FD; drv++) {
891 if(disk_status[drv].wait_count != 0 && --disk_status[drv].wait_count == 0) {
892 vm->open_disk(drv, disk_status[drv].path, disk_status[drv].bank);
893 out_message(_T("FD%d: %s"), drv + FD_BASE_NUMBER, disk_status[drv].path);
898 for(int drv = 0; drv < MAX_QD; drv++) {
899 if(quickdisk_status[drv].wait_count != 0 && --quickdisk_status[drv].wait_count == 0) {
900 vm->open_quickdisk(drv, quickdisk_status[drv].path);
901 out_message(_T("QD%d: %s"), drv + QD_BASE_NUMBER, quickdisk_status[drv].path);
906 if(tape_status.wait_count != 0 && --tape_status.wait_count == 0) {
907 if(tape_status.play) {
908 vm->play_tape(tape_status.path);
910 vm->rec_tape(tape_status.path);
912 out_message(_T("CMT: %s"), tape_status.path);
915 #ifdef USE_LASER_DISC
916 if(laser_disc_status.wait_count != 0 && --laser_disc_status.wait_count == 0) {
917 vm->open_laser_disc(laser_disc_status.path);
918 out_message(_T("LD: %s"), laser_disc_status.path);
923 void EMU::restore_media()
926 for(int drv = 0; drv < MAX_CART; drv++) {
927 if(cart_status[drv].path[0] != _T('\0')) {
928 if(check_file_extension(cart_status[drv].path, _T(".hex")) && hex2bin(cart_status[drv].path, create_local_path(_T("hex2bin.$$$")))) {
929 vm->open_cart(drv, create_local_path(_T("hex2bin.$$$")));
930 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
932 vm->open_cart(drv, cart_status[drv].path);
938 for(int drv = 0; drv < MAX_FD; drv++) {
939 if(disk_status[drv].path[0] != _T('\0')) {
940 vm->open_disk(drv, disk_status[drv].path, disk_status[drv].bank);
945 for(int drv = 0; drv < MAX_QD; drv++) {
946 if(quickdisk_status[drv].path[0] != _T('\0')) {
947 vm->open_quickdisk(drv, quickdisk_status[drv].path);
952 if(tape_status.path[0] != _T('\0')) {
953 if(tape_status.play) {
954 vm->play_tape(tape_status.path);
956 tape_status.path[0] = _T('\0');
960 #ifdef USE_LASER_DISC
961 if(laser_disc_status.path[0] != _T('\0')) {
962 vm->open_laser_disc(laser_disc_status.path);
968 void EMU::open_cart(int drv, const _TCHAR* file_path)
971 if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, create_local_path(_T("hex2bin.$$$")))) {
972 vm->open_cart(drv, create_local_path(_T("hex2bin.$$$")));
973 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
975 vm->open_cart(drv, file_path);
977 my_tcscpy_s(cart_status[drv].path, _MAX_PATH, file_path);
978 out_message(_T("Cart%d: %s"), drv + 1, file_path);
981 bool s = osd->now_rec_sound;
982 bool v = osd->now_rec_video;
985 if(s) osd->start_rec_sound();
986 if(v) osd->start_rec_video(-1);
990 void EMU::close_cart(int drv)
994 clear_media_status(&cart_status[drv]);
995 out_message(_T("Cart%d: Ejected"), drv + 1);
1003 bool EMU::cart_inserted(int drv)
1005 if(drv < MAX_CART) {
1006 return vm->cart_inserted(drv);
1014 void EMU::open_disk(int drv, const _TCHAR* file_path, int bank)
1017 if(vm->disk_inserted(drv)) {
1018 vm->close_disk(drv);
1020 #ifdef SUPPORT_VARIABLE_TIMING
1021 disk_status[drv].wait_count = (int)(vm->frame_rate() / 2);
1023 disk_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
1025 out_message(_T("FD%d: Ejected"), drv + FD_BASE_NUMBER);
1026 } else if(disk_status[drv].wait_count == 0) {
1027 vm->open_disk(drv, file_path, bank);
1028 out_message(_T("FD%d: %s"), drv + FD_BASE_NUMBER, file_path);
1030 my_tcscpy_s(disk_status[drv].path, _MAX_PATH, file_path);
1031 disk_status[drv].bank = bank;
1035 void EMU::close_disk(int drv)
1038 vm->close_disk(drv);
1039 clear_media_status(&disk_status[drv]);
1040 out_message(_T("FD%d: Ejected"), drv + FD_BASE_NUMBER);
1044 bool EMU::disk_inserted(int drv)
1047 return vm->disk_inserted(drv);
1053 void EMU::set_disk_protected(int drv, bool value)
1056 vm->set_disk_protected(drv, value);
1060 bool EMU::get_disk_protected(int drv)
1063 return vm->get_disk_protected(drv);
1070 int EMU::get_access_lamp(void)
1076 void EMU::open_quickdisk(int drv, const _TCHAR* file_path)
1079 if(vm->quickdisk_inserted(drv)) {
1080 vm->close_quickdisk(drv);
1082 #ifdef SUPPORT_VARIABLE_TIMING
1083 quickdisk_status[drv].wait_count = (int)(vm->frame_rate() / 2);
1085 quickdisk_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
1087 out_message(_T("QD%d: Ejected"), drv + QD_BASE_NUMBER);
1088 } else if(quickdisk_status[drv].wait_count == 0) {
1089 vm->open_quickdisk(drv, file_path);
1090 out_message(_T("QD%d: %s"), drv + QD_BASE_NUMBER, file_path);
1092 my_tcscpy_s(quickdisk_status[drv].path, _MAX_PATH, file_path);
1096 void EMU::close_quickdisk(int drv)
1099 vm->close_quickdisk(drv);
1100 clear_media_status(&quickdisk_status[drv]);
1101 out_message(_T("QD%d: Ejected"), drv + QD_BASE_NUMBER);
1105 bool EMU::quickdisk_inserted(int drv)
1108 return vm->quickdisk_inserted(drv);
1116 void EMU::play_tape(const _TCHAR* file_path)
1118 if(vm->tape_inserted()) {
1121 #ifdef SUPPORT_VARIABLE_TIMING
1122 tape_status.wait_count = (int)(vm->frame_rate() / 2);
1124 tape_status.wait_count = (int)(FRAMES_PER_SEC / 2);
1126 out_message(_T("CMT: Ejected"));
1127 } else if(tape_status.wait_count == 0) {
1128 vm->play_tape(file_path);
1129 out_message(_T("CMT: %s"), file_path);
1131 my_tcscpy_s(tape_status.path, _MAX_PATH, file_path);
1132 tape_status.play = true;
1135 void EMU::rec_tape(const _TCHAR* file_path)
1137 if(vm->tape_inserted()) {
1140 #ifdef SUPPORT_VARIABLE_TIMING
1141 tape_status.wait_count = (int)(vm->frame_rate() / 2);
1143 tape_status.wait_count = (int)(FRAMES_PER_SEC / 2);
1145 out_message(_T("CMT: Ejected"));
1146 } else if(tape_status.wait_count == 0) {
1147 vm->rec_tape(file_path);
1148 out_message(_T("CMT: %s"), file_path);
1150 my_tcscpy_s(tape_status.path, _MAX_PATH, file_path);
1151 tape_status.play = false;
1154 void EMU::close_tape()
1157 clear_media_status(&tape_status);
1158 out_message(_T("CMT: Ejected"));
1161 bool EMU::tape_inserted()
1163 return vm->tape_inserted();
1166 #ifndef TAPE_BINARY_ONLY
1167 bool EMU::tape_playing()
1169 return vm->tape_playing();
1172 bool EMU::tape_recording()
1174 return vm->tape_recording();
1177 int EMU::tape_position()
1179 return vm->tape_position();
1183 #ifdef USE_TAPE_BUTTON
1184 void EMU::push_play()
1189 void EMU::push_stop()
1194 void EMU::push_fast_forward()
1196 vm->push_fast_forward();
1199 void EMU::push_fast_rewind()
1201 vm->push_fast_rewind();
1204 void EMU::push_apss_forward()
1206 vm->push_apss_forward();
1209 void EMU::push_apss_rewind()
1211 vm->push_apss_rewind();
1216 #ifdef USE_LASER_DISC
1217 void EMU::open_laser_disc(const _TCHAR* file_path)
1219 if(vm->laser_disc_inserted()) {
1220 vm->close_laser_disc();
1222 #ifdef SUPPORT_VARIABLE_TIMING
1223 laser_disc_status.wait_count = (int)(vm->frame_rate() / 2);
1225 laser_disc_status.wait_count = (int)(FRAMES_PER_SEC / 2);
1227 out_message(_T("LD: Ejected"));
1228 } else if(laser_disc_status.wait_count == 0) {
1229 vm->open_laser_disc(file_path);
1230 out_message(_T("LD: %s"), file_path);
1232 my_tcscpy_s(laser_disc_status.path, _MAX_PATH, file_path);
1235 void EMU::close_laser_disc()
1237 vm->close_laser_disc();
1238 clear_media_status(&laser_disc_status);
1239 out_message(_T("LD: Ejected"));
1242 bool EMU::laser_disc_inserted()
1244 return vm->laser_disc_inserted();
1248 #ifdef USE_BINARY_FILE1
1249 void EMU::load_binary(int drv, const _TCHAR* file_path)
1251 if(drv < MAX_BINARY) {
1252 if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, create_local_path(_T("hex2bin.$$$")))) {
1253 vm->load_binary(drv, create_local_path(_T("hex2bin.$$$")));
1254 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
1256 vm->load_binary(drv, file_path);
1258 out_message(_T("Load: %s"), file_path);
1262 void EMU::save_binary(int drv, const _TCHAR* file_path)
1264 if(drv < MAX_BINARY) {
1265 vm->save_binary(drv, file_path);
1266 out_message(_T("Save: %s"), file_path);
1271 // I will decide to move this to osd?
1272 #ifdef SUPPORT_DUMMY_DEVICE_LED
1273 uint32 EMU::get_led_status(void)
1275 return vm->get_led_status();
1279 void EMU::update_config()
1281 vm->update_config();
1286 // ----------------------------------------------------------------------------
1288 // ----------------------------------------------------------------------------
1291 #define STATE_VERSION 2
1293 void EMU::save_state()
1295 save_state_tmp(create_local_path(_T("%s.sta"), _T(CONFIG_NAME)));
1298 void EMU::load_state()
1300 if(FILEIO::IsFileExists(create_local_path(_T("%s.sta"), _T(CONFIG_NAME)))) {
1301 save_state_tmp(create_local_path(_T("$temp$.sta")));
1302 if(!load_state_tmp(create_local_path(_T("%s.sta"), _T(CONFIG_NAME)))) {
1303 out_debug_log(_T("failed to load state file\n"));
1304 load_state_tmp(create_local_path(_T("$temp$.sta")));
1306 FILEIO::RemoveFile(create_local_path(_T("$temp$.sta")));
1310 void EMU::save_state_tmp(const _TCHAR* file_path)
1312 FILEIO* fio = new FILEIO();
1314 if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
1315 // save state file version
1316 fio->FputUint32(STATE_VERSION);
1318 save_config_state((void *)fio);
1319 // save inserted medias
1321 fio->Fwrite(&cart_status, sizeof(cart_status), 1);
1324 fio->Fwrite(disk_status, sizeof(disk_status), 1);
1325 fio->Fwrite(d88_file, sizeof(d88_file), 1);
1328 fio->Fwrite(&quickdisk_status, sizeof(quickdisk_status), 1);
1331 fio->Fwrite(&tape_status, sizeof(tape_status), 1);
1333 #ifdef USE_LASER_DISC
1334 fio->Fwrite(&laser_disc_status, sizeof(laser_disc_status), 1);
1337 vm->save_state(fio);
1338 // end of state file
1346 bool EMU::load_state_tmp(const _TCHAR* file_path)
1348 bool result = false;
1349 FILEIO* fio = new FILEIO();
1351 if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
1352 // check state file version
1353 if(fio->FgetUint32() == STATE_VERSION) {
1355 if(load_config_state((void *)fio)) {
1356 // load inserted medias
1358 fio->Fread(&cart_status, sizeof(cart_status), 1);
1361 fio->Fread(disk_status, sizeof(disk_status), 1);
1362 fio->Fread(d88_file, sizeof(d88_file), 1);
1365 fio->Fread(&quickdisk_status, sizeof(quickdisk_status), 1);
1368 fio->Fread(&tape_status, sizeof(tape_status), 1);
1370 #ifdef USE_LASER_DISC
1371 fio->Fread(&laser_disc_status, sizeof(laser_disc_status), 1);
1373 // check if virtual machine should be reinitialized
1374 bool reinitialize = false;
1376 reinitialize |= (cpu_type != config.cpu_type);
1377 cpu_type = config.cpu_type;
1379 #ifdef USE_SOUND_DEVICE_TYPE
1380 reinitialize |= (sound_device_type != config.sound_device_type);
1381 sound_device_type = config.sound_device_type;
1384 reinitialize |= (printer_device_type != config.printer_device_type);
1385 printer_device_type = config.printer_device_type;
1390 // reinitialize virtual machine
1393 osd->vm = vm = new VM(this);
1394 vm->initialize_sound(sound_rate, sound_samples);
1398 // restore inserted medias
1401 if(vm->load_state(fio)) {
1402 // check end of state
1403 result = (fio->FgetInt32() == -1);