OSDN Git Service

[VM][FM7] Fix state save/load.
[csp-qt/common_source_project-fm7.git] / source / src / emu.cpp
index 7a78fce..4b6e1ae 100644 (file)
@@ -7,24 +7,13 @@
        [ win32 emulation i/f ]
 */
 
+#if defined(_USE_QT)
+#include <string>
+#endif
 #include "emu.h"
 #include "vm/vm.h"
+#include "fifo.h"
 #include "fileio.h"
-#if defined(_USE_AGAR)
-#include <SDL/SDL.h>
-#include "agar_main.h"
-#include "agar_logger.h"
-#include <ctime>
-# elif defined(_USE_QT)
-//#include <SDL/SDL.h>
-
-#include "qt_main.h"
-#include "mainwidget.h"
-#include "qt_gldraw.h"
-
-#include "agar_logger.h"
-#include <ctime>
-# endif
 
 #ifndef FD_BASE_NUMBER
 #define FD_BASE_NUMBER 1
@@ -37,7 +26,8 @@
 // initialize
 // ----------------------------------------------------------------------------
 #if defined(_USE_QT)
-extern void get_long_full_path_name(_TCHAR* src, _TCHAR* dst);
+// Please permit at least them m(.. )m
+//extern void get_long_full_path_name(_TCHAR* src, _TCHAR* dst);
 #include <string>
 #endif
 
@@ -49,49 +39,25 @@ EMU::EMU(HWND hwnd, HINSTANCE hinst)
 EMU::EMU()
 #endif
 {
-#ifdef _DEBUG_LOG
-       initialize_debug_log();
-#endif
        message_count = 0;
-       
        // store main window handle
-#if !defined(_USE_QT)
-       // check os version
-       OSVERSIONINFO os_info;
-       os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-       GetVersionEx(&os_info);
-       vista_or_later = (os_info.dwPlatformId == 2 && os_info.dwMajorVersion >= 6);
-#endif 
-       // get module path
-       // Initialize keymod.
-#if defined(_USE_QT)
-       std::string tmps;
-       _TCHAR tmp_path[PATH_MAX], *ptr;
-       my_procname.copy(tmp_path, PATH_MAX, 0);
-       memset(app_path, 0x00, sizeof(app_path));
-       get_long_full_path_name(tmp_path, app_path);
-       //AGAR_DebugLog("APPPATH=%s\n", app_path);
-       host_cpus = 4;
-#else
-       _TCHAR tmp_path[_MAX_PATH], *ptr;
-       memset(tmp_path, 0x00, _MAX_PATH);
-       GetModuleFileName(NULL, tmp_path, _MAX_PATH);
-       GetFullPathName(tmp_path, _MAX_PATH, app_path, &ptr);
-       *ptr = _T('\0');
-#endif 
 #ifdef USE_FD1
-               // initialize d88 file info
+       // initialize d88 file info
        memset(d88_file, 0, sizeof(d88_file));
 #endif
-               // load sound config
+#ifdef USE_BUBBLE1
+       // initialize d88 file info
+       memset(b77_file, 0, sizeof(b77_file));
+#endif
+       // load sound config
        static const int freq_table[8] = {
-                       2000, 4000, 8000, 11025, 22050, 44100,
+               2000, 4000, 8000, 11025, 22050, 44100,
 #ifdef OVERRIDE_SOUND_FREQ_48000HZ
-                       OVERRIDE_SOUND_FREQ_48000HZ,
+               OVERRIDE_SOUND_FREQ_48000HZ,
 #else
-                       48000,
+               48000,
 #endif
-                       96000,
+               96000,
        };
        static const double late_table[5] = {0.05, 0.1, 0.2, 0.3, 0.4};
        
@@ -103,53 +69,104 @@ EMU::EMU()
        }
        sound_rate = freq_table[config.sound_frequency];
        sound_samples = (int)(sound_rate * late_table[config.sound_latency] + 0.5);
-               
+
 #ifdef USE_CPU_TYPE
        cpu_type = config.cpu_type;
 #endif
 #ifdef USE_SOUND_DEVICE_TYPE
        sound_device_type = config.sound_device_type;
 #endif
+#ifdef USE_PRINTER
+       printer_device_type = config.printer_device_type;
+#endif
+       
+       // initialize osd
        osd = new OSD();
-#if defined(_USE_QT)
+#if defined(OSD_QT)
        osd->main_window_handle = hwnd;
        osd->glv = hinst;
-#endif 
+       osd->host_cpus = 4;
+#elif defined(OSD_WIN32)
+       osd->main_window_handle = hwnd;
+       osd->instance_handle = hinst;
+#endif
        osd->initialize(sound_rate, sound_samples);
-       osd->lock_vm();
+       // initialize vm
        osd->vm = vm = new VM(this);
-       
+       // Below is temporally workaround. I will fix ASAP (or give up): 20160311 K.Ohta
+       // Problems seem to be resolved. See fm7.cpp. 20160319 K.Ohta
+       // Still not resolved with FM-7/77 :-( 20160407 K.Ohta
+#if defined(_FM7) || defined(_FMNEW7) || defined(_FM8) || \
+       defined(_FM77_VARIANTS)
+       delete vm;
+       osd->vm = vm = new VM(this);
+#endif
+#ifdef USE_AUTO_KEY
+       initialize_auto_key();
+#endif
+#ifdef USE_DEBUGGER
+       initialize_debugger();
+#endif
        initialize_media();
-       osd->initialize_printer();
        vm->initialize_sound(sound_rate, sound_samples);
+#ifdef USE_SOUND_VOLUME
+       for(int i = 0; i < USE_SOUND_VOLUME; i++) {
+               vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
+       }
+#endif
        vm->reset();
-       osd->unlock_vm();
-       
        now_suspended = false;
 }
 
 EMU::~EMU()
 {
+#ifdef USE_AUTO_KEY
+       release_auto_key();
+#endif
+#ifdef USE_DEBUGGER
+       release_debugger();
+#endif
+       delete vm;
        osd->release();
        delete osd;
-       delete vm;
-
 #ifdef _DEBUG_LOG
        release_debug_log();
 #endif
 }
 
+#ifdef OSD_QT
+EmuThreadClass *EMU::get_parent_handler()
+{
+       return osd->get_parent_handler();
+}
+
+void EMU::set_parent_handler(EmuThreadClass *p, DrawThreadClass *q)
+{
+       osd->set_parent_thread(p);
+       osd->set_draw_thread(q);
+}
+
+void EMU::set_host_cpus(int v)
+{
+       osd->host_cpus = (v <= 0) ? 1 : v;
+}
+
+int EMU::get_host_cpus()
+{
+       return osd->host_cpus;
+}
+#endif
+
 // ----------------------------------------------------------------------------
 // drive machine
 // ----------------------------------------------------------------------------
 
-int EMU::frame_interval()
+int EMU::get_frame_interval()
 {
-#if 1
 #ifdef SUPPORT_VARIABLE_TIMING
        static int prev_interval = 0;
        static double prev_fps = -1;
-       double fps = vm->frame_rate();
+       double fps = vm->get_frame_rate();
        if(prev_fps != fps) {
                prev_interval = (int)(1024. * 1000. / fps + 0.5);
                prev_fps = fps;
@@ -158,9 +175,11 @@ int EMU::frame_interval()
 #else
        return (int)(1024. * 1000. / FRAMES_PER_SEC + 0.5);
 #endif
-#else
-       return (int)(1024. * 1000. / FRAMES_PER_SEC + 0.5);
-#endif
+}
+
+bool EMU::is_frame_skippable()
+{
+       return vm->is_frame_skippable();
 }
 
 int EMU::run()
@@ -170,15 +189,24 @@ int EMU::run()
                now_suspended = false;
        }
        osd->update_input();
-       osd->update_printer();
+#ifdef USE_AUTO_KEY
+       update_auto_key();
+#endif
+#ifdef USE_JOYSTICK
+       update_joystick();
+#endif
+       
 #ifdef USE_SOCKET
-       //osd->update_socket();
+#if !defined(_USE_QT) // Temporally
+       osd->update_socket();
+#endif
 #endif
        update_media();
        
        // virtual machine may be driven to fill sound buffer
        int extra_frames = 0;
        osd->update_sound(&extra_frames);
+       
        // drive virtual machine
        if(extra_frames == 0) {
                osd->lock_vm();
@@ -202,6 +230,10 @@ void EMU::reset()
        reinitialize |= (sound_device_type != config.sound_device_type);
        sound_device_type = config.sound_device_type;
 #endif
+#ifdef USE_PRINTER
+       reinitialize |= (printer_device_type != config.printer_device_type);
+       printer_device_type = config.printer_device_type;
+#endif
        if(reinitialize) {
                // stop sound
                osd->stop_sound();
@@ -210,24 +242,26 @@ void EMU::reset()
                delete vm;
                osd->vm = vm = new VM(this);
                vm->initialize_sound(sound_rate, sound_samples);
+#ifdef USE_SOUND_VOLUME
+               for(int i = 0; i < USE_SOUND_VOLUME; i++) {
+                       vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
+               }
+#endif
                vm->reset();
                osd->unlock_vm();
                // restore inserted medias
                restore_media();
        } else {
-          // reset virtual machine
+               // reset virtual machine
                osd->lock_vm();         
                vm->reset();
                osd->unlock_vm();               
        }
        
-       // reset printer
-       osd->reset_printer();
-
-#if !defined(_USE_QT) // Temporally
        // restart recording
-       osd->restart_rec_sound();
-       osd->restart_rec_video();
+#if !defined(_USE_QT) // Temporally
+       osd->restart_record_sound();
+       osd->restart_record_video();
 #endif 
 }
 
@@ -238,13 +272,10 @@ void EMU::special_reset()
        osd->lock_vm();         
        vm->special_reset();
        osd->unlock_vm();
-       // reset printer
-       osd->reset_printer();
-       
        // restart recording
 #if !defined(_USE_QT) // Temporally
-       restart_rec_sound();
-       restart_rec_video();
+       restart_record_sound();
+       restart_record_video();
 #endif 
 }
 #endif
@@ -279,9 +310,45 @@ void EMU::unlock_vm()
        osd->unlock_vm();
 }
 
+void EMU::force_unlock_vm()
+{
+       osd->force_unlock_vm();
+}
+
+
+bool EMU::is_vm_locked()
+{
+       return osd->is_vm_locked();
+}
+
 // ----------------------------------------------------------------------------
 // input
 // ----------------------------------------------------------------------------
+
+#ifdef OSD_QT
+void EMU::key_modifiers(uint32_t mod)
+{
+       osd->key_modifiers(mod);
+}
+
+       # ifdef USE_MOUSE
+void EMU::set_mouse_pointer(int x, int y)
+{
+       osd->set_mouse_pointer(x, y);
+}
+
+void EMU::set_mouse_button(int button)
+{
+       osd->set_mouse_button(button);
+}
+
+int EMU::get_mouse_button()
+{
+       return osd->get_mouse_button();
+}
+       #endif
+#endif
+
 void EMU::key_down(int code, bool repeat)
 {
        osd->key_down(code, repeat);
@@ -300,18 +367,27 @@ void EMU::key_lost_focus()
 #ifdef ONE_BOARD_MICRO_COMPUTER
 void EMU::press_button(int num)
 {
-       osd->press_button(num);
+       int code = vm_buttons[num].code;
+       
+       if(code) {
+               osd->key_down_native(code, false);
+               osd->get_key_buffer()[code] = KEY_KEEP_FRAMES;
+       } else {
+               // code=0: reset virtual machine
+               vm->reset();
+       }
 }
 #endif
 
+#ifdef USE_MOUSE
 void EMU::enable_mouse()
 {
        osd->enable_mouse();
 }
 
-void EMU::disenable_mouse()
+void EMU::disable_mouse()
 {
-       osd->disenable_mouse();
+       osd->disable_mouse();
 }
 
 void EMU::toggle_mouse()
@@ -319,72 +395,206 @@ void EMU::toggle_mouse()
        osd->toggle_mouse();
 }
 
-bool EMU::get_mouse_enabled()
+bool EMU::is_mouse_enabled()
 {
-       return osd->get_mouse_enabled();
+       return osd->is_mouse_enabled();
 }
+#endif
 
 #ifdef USE_AUTO_KEY
+void EMU::initialize_auto_key()
+{
+       auto_key_buffer = new FIFO(65536);
+       auto_key_buffer->clear();
+       auto_key_phase = auto_key_shift = 0;
+       osd->now_auto_key = false;
+}
+
+void EMU::release_auto_key()
+{
+       if(auto_key_buffer) {
+               auto_key_buffer->release();
+               delete auto_key_buffer;
+       }
+}
+
 void EMU::start_auto_key()
 {
-       osd->start_auto_key();
+       auto_key_phase = 1;
+       auto_key_shift = 0;
+       osd->now_auto_key = true;
 }
 
 void EMU::stop_auto_key()
 {
-       osd->stop_auto_key();
+       if(auto_key_shift) {
+               osd->key_up_native(VK_LSHIFT);
+       }
+       auto_key_phase = auto_key_shift = 0;
+       osd->now_auto_key = false;
 }
 
-bool EMU::now_auto_key()
+#ifndef USE_AUTO_KEY_SHIFT
+#define USE_AUTO_KEY_SHIFT 0
+#endif
+#ifndef VK_LSHIFT
+#define VK_LSHIFT 0xA0
+#endif
+
+void EMU::update_auto_key()
 {
-       return osd->now_auto_key();
+       switch(auto_key_phase) {
+       case 1:
+               if(auto_key_buffer && !auto_key_buffer->empty()) {
+                       // update shift key status
+                       int shift = auto_key_buffer->read_not_remove(0) & 0x100;
+                       if(shift && !auto_key_shift) {
+                               osd->key_down_native(VK_LSHIFT, false);
+                       } else if(!shift && auto_key_shift) {
+                               osd->key_up_native(VK_LSHIFT);
+                       }
+                       auto_key_shift = shift;
+                       auto_key_phase++;
+                       break;
+               }
+       case 3 + USE_AUTO_KEY_SHIFT:
+               if(auto_key_buffer && !auto_key_buffer->empty()) {
+                       osd->key_down_native(auto_key_buffer->read_not_remove(0) & 0xff, false);
+               }
+               auto_key_phase++;
+               break;
+       case USE_AUTO_KEY + USE_AUTO_KEY_SHIFT:
+               if(auto_key_buffer && !auto_key_buffer->empty()) {
+                       osd->key_up_native(auto_key_buffer->read_not_remove(0) & 0xff);
+               }
+               auto_key_phase++;
+               break;
+       case USE_AUTO_KEY_RELEASE + USE_AUTO_KEY_SHIFT:
+               if(auto_key_buffer && !auto_key_buffer->empty()) {
+                       // wait enough while vm analyzes one line
+                       if(auto_key_buffer->read() == 0xd) {
+                               auto_key_phase++;
+                               break;
+                       }
+               }
+       case 30:
+               if(auto_key_buffer && !auto_key_buffer->empty()) {
+                       auto_key_phase = 1;
+               } else {
+                       stop_auto_key();
+               }
+               break;
+       default:
+               if(auto_key_phase) {
+                       auto_key_phase++;
+               }
+       }
 }
 #endif
 
-uint8* EMU::key_buffer()
+#ifdef USE_JOYSTICK
+void EMU::update_joystick()
 {
-       return osd->key_buffer();
+       uint32_t *joy_buffer = osd->get_joy_buffer();
+       uint8_t *key_buffer = osd->get_key_buffer();
+       
+       memset(joy_status, 0, sizeof(joy_status));
+       
+       for(int i = 0; i < 4; i++) {
+               for(int j = 0; j < 16; j++) {
+                       if(config.joy_buttons[i][j] < 0) {
+                               int code = -config.joy_buttons[i][j];
+                               if(code < 256 && key_buffer[code]) {
+                                       joy_status[i] |= (1 << j);
+                               }
+                       } else {
+                               int stick = config.joy_buttons[i][j] >> 4;
+                               int button = config.joy_buttons[i][j] & 15;
+                               if(stick < 2 && (joy_buffer[stick & 3] & (1 << button))) {
+                                       joy_status[i] |= (1 << j);
+                               }
+                       }
+               }
+       }
 }
+#endif
 
-uint32* EMU::joy_buffer()
+const uint8_t* EMU::get_key_buffer()
 {
-       return osd->joy_buffer();
+       return (const uint8_t*)osd->get_key_buffer();
 }
-int* EMU::mouse_buffer()
+
+#ifdef USE_JOYSTICK
+const uint32_t* EMU::get_joy_buffer()
 {
-       return osd->mouse_buffer();
+       return (const uint32_t*)joy_status;
 }
+#endif
+
+#ifdef USE_MOUSE
+const int32_t* EMU::get_mouse_buffer()
+{
+       return (const int32_t*)osd->get_mouse_buffer();
+}
+#endif
 
 // ----------------------------------------------------------------------------
 // screen
 // ----------------------------------------------------------------------------
 
-int EMU::get_window_width(int mode)
+int EMU::get_window_mode_width(int mode)
+{
+       return osd->get_window_mode_width(mode);
+}
+
+int EMU::get_window_mode_height(int mode)
+{
+       return osd->get_window_mode_height(mode);
+}
+
+void EMU::set_host_window_size(int window_width, int window_height, bool window_mode)
 {
-       return osd->get_window_width(mode);
+       osd->set_host_window_size(window_width, window_height, window_mode);
 }
 
-int EMU::get_window_height(int mode)
+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)
 {
-       return osd->get_window_height(mode);
+       osd->set_vm_screen_size(screen_width, screen_height, window_width, window_height, window_width_aspect, window_height_aspect);
 }
 
-void EMU::set_window_size(int width, int height, bool window_mode)
+int EMU::get_vm_window_width()
 {
-       osd->set_window_size(width, height, window_mode);
+       return osd->get_vm_window_width();
 }
 
-void EMU::set_vm_screen_size(int sw, int sh, int swa, int sha, int ww, int wh)
+int EMU::get_vm_window_height()
 {
-       osd->set_vm_screen_size(sw, sh, swa, sha, ww, wh);
+       return osd->get_vm_window_height();
 }
 
+int EMU::get_vm_window_width_aspect()
+{
+       return osd->get_vm_window_width_aspect();
+}
+
+int EMU::get_vm_window_height_aspect()
+{
+       return osd->get_vm_window_height_aspect();
+}
+
+#if defined(USE_MINIMUM_RENDERING)
+bool EMU::is_screen_changed()
+{
+       return vm->is_screen_changed();
+}
+#endif
+
 int EMU::draw_screen()
 {
        return osd->draw_screen();
 }
 
-scrntype* EMU::screen_buffer(int y)
+scrntype_t* EMU::get_screen_buffer(int y)
 {
        return osd->get_vm_screen_buffer(y);
 }
@@ -415,19 +625,19 @@ void EMU::capture_screen()
        osd->capture_screen();
 }
 
-bool EMU::start_rec_video(int fps)
+bool EMU::start_record_video(int fps)
 {
-       return osd->start_rec_video(fps);
+       return osd->start_record_video(fps);
 }
 
-void EMU::stop_rec_video()
+void EMU::stop_record_video()
 {
-       osd->stop_rec_video();
+       osd->stop_record_video();
 }
 
-bool EMU::now_rec_video()
+bool EMU::is_video_recording()
 {
-       return osd->now_rec_video;
+       return osd->now_record_video;
 }
 
 // ----------------------------------------------------------------------------
@@ -439,19 +649,19 @@ void EMU::mute_sound()
        osd->mute_sound();
 }
 
-void EMU::start_rec_sound()
+void EMU::start_record_sound()
 {
-       osd->start_rec_sound();
+       osd->start_record_sound();
 }
 
-void EMU::stop_rec_sound()
+void EMU::stop_record_sound()
 {
-       osd->stop_rec_sound();
+       osd->stop_record_sound();
 }
 
-bool EMU::now_rec_sound()
+bool EMU::is_sound_recording()
 {
-       return osd->now_rec_sound;
+       return osd->now_record_sound;
 }
 
 // ----------------------------------------------------------------------------
@@ -511,7 +721,7 @@ void EMU::set_cur_movie_frame(int frame, bool relative)
        osd->set_cur_movie_frame(frame, relative);
 }
 
-uint32 EMU::get_cur_movie_frame()
+uint32_t EMU::get_cur_movie_frame()
 {
        return osd->get_cur_movie_frame();
 }
@@ -568,16 +778,78 @@ void EMU::set_capture_dev_channel(int ch)
 // printer
 // ----------------------------------------------------------------------------
 
-void EMU::printer_out(uint8 value)
+#ifdef USE_PRINTER
+void EMU::create_bitmap(bitmap_t *bitmap, int width, int height)
+{
+       osd->create_bitmap(bitmap, width, height);
+}
+
+void EMU::release_bitmap(bitmap_t *bitmap)
+{
+       osd->release_bitmap(bitmap);
+}
+
+void EMU::create_font(font_t *font, const _TCHAR *family, int width, int height, int rotate, bool bold, bool italic)
+{
+       osd->create_font(font, family, width, height, rotate, bold, italic);
+}
+
+void EMU::release_font(font_t *font)
 {
-       osd->printer_out(value);
+       osd->release_font(font);
 }
 
-void EMU::printer_strobe(bool value)
+void EMU::create_pen(pen_t *pen, int width, uint8_t r, uint8_t g, uint8_t b)
 {
-       osd->printer_strobe(value);
+       osd->create_pen(pen, width, r, g, b);
 }
 
+void EMU::release_pen(pen_t *pen)
+{
+       osd->release_pen(pen);
+}
+
+void EMU::clear_bitmap(bitmap_t *bitmap, uint8_t r, uint8_t g, uint8_t b)
+{
+       osd->clear_bitmap(bitmap, r, g, b);
+}
+
+int EMU::get_text_width(bitmap_t *bitmap, font_t *font, const char *text)
+{
+       return osd->get_text_width(bitmap, font, text);
+}
+
+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)
+{
+       osd->draw_text_to_bitmap(bitmap, font, x, y, text, r, g, b);
+}
+
+void EMU::draw_line_to_bitmap(bitmap_t *bitmap, pen_t *pen, int sx, int sy, int ex, int ey)
+{
+       osd->draw_line_to_bitmap(bitmap, pen, sx, sy, ex, ey);
+}
+
+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)
+{
+       osd->draw_rectangle_to_bitmap(bitmap, x, y, width, height, r, g, b);
+}
+
+void EMU::draw_point_to_bitmap(bitmap_t *bitmap, int x, int y, uint8_t r, uint8_t g, uint8_t b)
+{
+       osd->draw_point_to_bitmap(bitmap, x, y, r, g, b);
+}
+
+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)
+{
+       osd->stretch_bitmap(dest, dest_x, dest_y, dest_width, dest_height, source, source_x, source_y, source_width, source_height);
+}
+
+void EMU::write_bitmap_to_file(bitmap_t *bitmap, const _TCHAR *file_path)
+{
+       osd->write_bitmap_to_file(bitmap, file_path);
+}
+#endif
+
 // ----------------------------------------------------------------------------
 // socket
 // ----------------------------------------------------------------------------
@@ -588,27 +860,27 @@ int EMU::get_socket(int ch)
        return osd->get_socket(ch);
 }
 
-void EMU::socket_connected(int ch)
+void EMU::notify_socket_connected(int ch)
 {
-       osd->socket_connected(ch);
+       osd->notify_socket_connected(ch);
 }
 
-void EMU::socket_disconnected(int ch)
+void EMU::notify_socket_disconnected(int ch)
 {
-       osd->socket_disconnected(ch);
+       osd->notify_socket_disconnected(ch);
 }
 
-bool EMU::init_socket_tcp(int ch)
+bool EMU::initialize_socket_tcp(int ch)
 {
-       return osd->init_socket_tcp(ch);
+       return osd->initialize_socket_tcp(ch);
 }
 
-bool EMU::init_socket_udp(int ch)
+bool EMU::initialize_socket_udp(int ch)
 {
-       return osd->init_socket_udp(ch);
+       return osd->initialize_socket_udp(ch);
 }
 
-bool EMU::connect_socket(int ch, uint32 ipaddr, int port)
+bool EMU::connect_socket(int ch, uint32_t ipaddr, int port)
 {
        return osd->connect_socket(ch, ipaddr, port);
 }
@@ -623,24 +895,24 @@ bool EMU::listen_socket(int ch)
        return osd->listen_socket(ch);
 }
 
-void EMU::send_data_tcp(int ch)
+void EMU::send_socket_data_tcp(int ch)
 {
-       osd->send_data_tcp(ch);
+       osd->send_socket_data_tcp(ch);
 }
 
-void EMU::send_data_udp(int ch, uint32 ipaddr, int port)
+void EMU::send_socket_data_udp(int ch, uint32_t ipaddr, int port)
 {
-       osd->send_data_udp(ch, ipaddr, port);
+       osd->send_socket_data_udp(ch, ipaddr, port);
 }
 
-void EMU::send_data(int ch)
+void EMU::send_socket_data(int ch)
 {
-       osd->send_data(ch);
+       osd->send_socket_data(ch);
 }
 
-void EMU::recv_data(int ch)
+void EMU::recv_socket_data(int ch)
 {
-       osd->recv_data(ch);
+       osd->recv_socket_data(ch);
 }
 #endif
 
@@ -651,54 +923,74 @@ void EMU::recv_data(int ch)
 #ifdef _DEBUG_LOG
 void EMU::initialize_debug_log()
 {
-#if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
-       
-#else // Window
-       TCHAR path[_MAX_PATH];
-       osd->create_date_file_name(path, _MAX_PATH, _T("log"));
-       debug_log = _tfopen(path, _T("w"));
-#endif
+       _TCHAR path[_MAX_PATH];
+       debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
 }
 
 void EMU::release_debug_log()
 {
-#if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
-
-#else
        if(debug_log) {
                fclose(debug_log);
                debug_log = NULL;
        }
-#endif
 }
 #endif
 
+#ifdef _DEBUG_LOG
+static _TCHAR prev_buffer[1024] = {0};
+#endif
+
 void EMU::out_debug_log(const _TCHAR* format, ...)
 {
 #ifdef _DEBUG_LOG
        va_list ap;
        _TCHAR buffer[1024];
-       static _TCHAR prev_buffer[1024] = {0};
        
        va_start(ap, format);
        my_vstprintf_s(buffer, 1024, format, ap);
        va_end(ap);
-
+       
+       if(_tcscmp(prev_buffer, buffer) == 0) {
+               return;
+       }
+       my_tcscpy_s(prev_buffer, 1024, buffer);
+       
 #if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
        AGAR_DebugLog(AGAR_LOG_DEBUG, "%s", buffer);
 #else
-       if(my_tcscmp(prev_buffer, buffer) == 0) {
-               return;
+       if(debug_log) {
+               _ftprintf(debug_log, _T("%s"), buffer);
+               static int size = 0;
+               if((size += _tcslen(buffer)) > 0x8000000) { // 128MB
+                       fclose(debug_log);
+                       debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
+                       size = 0;
+               }
        }
+#endif
+#endif
+}
+
+void EMU::force_out_debug_log(const _TCHAR* format, ...)
+{
+#ifdef _DEBUG_LOG
+       va_list ap;
+       _TCHAR buffer[1024];
+       
+       va_start(ap, format);
+       my_vstprintf_s(buffer, 1024, format, ap);
+       va_end(ap);
        my_tcscpy_s(prev_buffer, 1024, buffer);
+       
+#if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
+       AGAR_DebugLog(AGAR_LOG_DEBUG, "%s", buffer);
+#else
        if(debug_log) {
                _ftprintf(debug_log, _T("%s"), buffer);
                static int size = 0;
                if((size += _tcslen(buffer)) > 0x8000000) { // 128MB
-                       TCHAR path[_MAX_PATH];
-                       osd->create_date_file_name(path, _MAX_PATH, _T("log"));
                        fclose(debug_log);
-                       debug_log = _tfopen(path, _T("w"));
+                       debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
                        size = 0;
                }
        }
@@ -710,7 +1002,7 @@ void EMU::out_message(const _TCHAR* format, ...)
 {
        va_list ap;
        va_start(ap, format);
-       my_vstprintf_s(message, 260, format, ap); // Security for MSVC:C6386.
+       my_vstprintf_s(message, 1024, format, ap); // Security for MSVC:C6386.
        va_end(ap);
        message_count = 4; // 4sec
 }
@@ -719,45 +1011,31 @@ void EMU::out_message(const _TCHAR* format, ...)
 // misc
 // ----------------------------------------------------------------------------
 
-_TCHAR* EMU::application_path()
-{
-       return osd->application_path();
-}
 
-_TCHAR* EMU::bios_path(const _TCHAR* file_name)
-{
-       return osd->bios_path(file_name);
-}
-
-void EMU::sleep(uint32 ms)
+void EMU::sleep(uint32_t ms)
 {
        osd->sleep(ms);
 }
 
-void EMU::get_host_time(cur_time_t* time)
-{
-       osd->get_host_time(time);
-}
-
 
 // ----------------------------------------------------------------------------
 // user interface
 // ----------------------------------------------------------------------------
 
-static uint8 hex2uint8(char *value)
+static uint8_t hex2uint8(char *value)
 {
        char tmp[3];
        memset(tmp, 0, sizeof(tmp));
        memcpy(tmp, value, 2);
-       return (uint8)strtoul(tmp, NULL, 16);
+       return (uint8_t)strtoul(tmp, NULL, 16);
 }
 
-static uint16 hex2uint16(char *value)
+static uint16_t hex2uint16(char *value)
 {
        char tmp[5];
        memset(tmp, 0, sizeof(tmp));
        memcpy(tmp, value, 4);
-       return (uint16)strtoul(tmp, NULL, 16);
+       return (uint16_t)strtoul(tmp, NULL, 16);
 }
 
 static bool hex2bin(const _TCHAR* file_path, const _TCHAR* dest_path)
@@ -767,13 +1045,13 @@ static bool hex2bin(const _TCHAR* file_path, const _TCHAR* dest_path)
        if(fio_s->Fopen(file_path, FILEIO_READ_BINARY)) {
                int length = 0;
                char line[1024];
-               uint8 buffer[0x10000];
+               uint8_t buffer[0x10000];
                memset(buffer, 0xff, sizeof(buffer));
                while(fio_s->Fgets(line, sizeof(line)) != NULL) {
                        if(line[0] != ':') continue;
                        int bytes = hex2uint8(line + 1);
                        int offset = hex2uint16(line + 3);
-                       uint8 record_type = hex2uint8(line + 7);
+                       uint8_t record_type = hex2uint8(line + 7);
                        if(record_type == 0x01) break;
                        if(record_type != 0x00) continue;
                        for(int i = 0; i < bytes; i++) {
@@ -806,14 +1084,17 @@ void EMU::initialize_media()
        memset(&cart_status, 0, sizeof(cart_status));
 #endif
 #ifdef USE_FD1
-       memset(disk_status, 0, sizeof(disk_status));
+       memset(floppy_disk_status, 0, sizeof(floppy_disk_status));
 #endif
 #ifdef USE_QD1
-       memset(&quickdisk_status, 0, sizeof(quickdisk_status));
+       memset(&quick_disk_status, 0, sizeof(quick_disk_status));
 #endif
 #ifdef USE_TAPE
        memset(&tape_status, 0, sizeof(tape_status));
 #endif
+#ifdef USE_COMPACT_DISC
+       memset(&compact_disc_status, 0, sizeof(compact_disc_status));
+#endif
 #ifdef USE_LASER_DISC
        memset(&laser_disc_status, 0, sizeof(laser_disc_status));
 #endif
@@ -824,17 +1105,17 @@ void EMU::update_media()
 {
 #ifdef USE_FD1
        for(int drv = 0; drv < MAX_FD; drv++) {
-               if(disk_status[drv].wait_count != 0 && --disk_status[drv].wait_count == 0) {
-                       vm->open_disk(drv, disk_status[drv].path, disk_status[drv].bank);
-                       out_message(_T("FD%d: %s"), drv + FD_BASE_NUMBER, disk_status[drv].path);
+               if(floppy_disk_status[drv].wait_count != 0 && --floppy_disk_status[drv].wait_count == 0) {
+                       vm->open_floppy_disk(drv, floppy_disk_status[drv].path, floppy_disk_status[drv].bank);
+                       out_message(_T("FD%d: %s"), drv + FD_BASE_NUMBER, floppy_disk_status[drv].path);
                }
        }
 #endif
 #ifdef USE_QD1
        for(int drv = 0; drv < MAX_QD; drv++) {
-               if(quickdisk_status[drv].wait_count != 0 && --quickdisk_status[drv].wait_count == 0) {
-                       vm->open_quickdisk(drv, quickdisk_status[drv].path);
-                       out_message(_T("QD%d: %s"), drv + QD_BASE_NUMBER, quickdisk_status[drv].path);
+               if(quick_disk_status[drv].wait_count != 0 && --quick_disk_status[drv].wait_count == 0) {
+                       vm->open_quick_disk(drv, quick_disk_status[drv].path);
+                       out_message(_T("QD%d: %s"), drv + QD_BASE_NUMBER, quick_disk_status[drv].path);
                }
        }
 #endif
@@ -848,12 +1129,26 @@ void EMU::update_media()
                out_message(_T("CMT: %s"), tape_status.path);
        }
 #endif
+#ifdef USE_COMPACT_DISC
+       if(compact_disc_status.wait_count != 0 && --compact_disc_status.wait_count == 0) {
+               vm->open_compact_disc(compact_disc_status.path);
+               out_message(_T("CD: %s"), compact_disc_status.path);
+       }
+#endif
 #ifdef USE_LASER_DISC
        if(laser_disc_status.wait_count != 0 && --laser_disc_status.wait_count == 0) {
                vm->open_laser_disc(laser_disc_status.path);
                out_message(_T("LD: %s"), laser_disc_status.path);
        }
 #endif
+#ifdef USE_BUBBLE1
+       for(int drv = 0; drv < MAX_BUBBLE; drv++) {
+               if(bubble_casette_status[drv].wait_count != 0 && --bubble_casette_status[drv].wait_count == 0) {
+                       vm->open_bubble_casette(drv, bubble_casette_status[drv].path, bubble_casette_status[drv].bank);
+                       out_message(_T("Bubble%d: %s"), drv, bubble_casette_status[drv].path);
+               }
+       }
+#endif
 }
 
 void EMU::restore_media()
@@ -861,9 +1156,9 @@ void EMU::restore_media()
 #ifdef USE_CART1
        for(int drv = 0; drv < MAX_CART; drv++) {
                if(cart_status[drv].path[0] != _T('\0')) {
-                       if(check_file_extension(cart_status[drv].path, _T(".hex")) && hex2bin(cart_status[drv].path, osd->bios_path(_T("hex2bin.$$$")))) {
-                               vm->open_cart(drv, osd->bios_path(_T("hex2bin.$$$")));
-                               FILEIO::RemoveFile(osd->bios_path(_T("hex2bin.$$$")));
+                       if(check_file_extension(cart_status[drv].path, _T(".hex")) && hex2bin(cart_status[drv].path, create_local_path(_T("hex2bin.$$$")))) {
+                               vm->open_cart(drv, create_local_path(_T("hex2bin.$$$")));
+                               FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
                        } else {
                                vm->open_cart(drv, cart_status[drv].path);
                        }
@@ -872,15 +1167,15 @@ void EMU::restore_media()
 #endif
 #ifdef USE_FD1
        for(int drv = 0; drv < MAX_FD; drv++) {
-               if(disk_status[drv].path[0] != _T('\0')) {
-                       vm->open_disk(drv, disk_status[drv].path, disk_status[drv].bank);
+               if(floppy_disk_status[drv].path[0] != _T('\0')) {
+                       vm->open_floppy_disk(drv, floppy_disk_status[drv].path, floppy_disk_status[drv].bank);
                }
        }
 #endif
 #ifdef USE_QD1
        for(int drv = 0; drv < MAX_QD; drv++) {
-               if(quickdisk_status[drv].path[0] != _T('\0')) {
-                       vm->open_quickdisk(drv, quickdisk_status[drv].path);
+               if(quick_disk_status[drv].path[0] != _T('\0')) {
+                       vm->open_quick_disk(drv, quick_disk_status[drv].path);
                }
        }
 #endif
@@ -893,20 +1188,32 @@ void EMU::restore_media()
                }
        }
 #endif
+#ifdef USE_COMPACT_DISC
+       if(compact_disc_status.path[0] != _T('\0')) {
+               vm->open_compact_disc(compact_disc_status.path);
+       }
+#endif
 #ifdef USE_LASER_DISC
        if(laser_disc_status.path[0] != _T('\0')) {
                vm->open_laser_disc(laser_disc_status.path);
        }
 #endif
+#ifdef USE_BUBBLE1
+       for(int drv = 0; drv < MAX_BUBBLE; drv++) {
+               if(bubble_casette_status[drv].path[0] != _T('\0')) {
+                       vm->open_bubble_casette(drv, bubble_casette_status[drv].path, bubble_casette_status[drv].bank);
+               }
+       }
+#endif
 }
 
 #ifdef USE_CART1
 void EMU::open_cart(int drv, const _TCHAR* file_path)
 {
        if(drv < MAX_CART) {
-               if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, osd->bios_path(_T("hex2bin.$$$")))) {
-                       vm->open_cart(drv, osd->bios_path(_T("hex2bin.$$$")));
-                       FILEIO::RemoveFile(osd->bios_path(_T("hex2bin.$$$")));
+               if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, create_local_path(_T("hex2bin.$$$")))) {
+                       vm->open_cart(drv, create_local_path(_T("hex2bin.$$$")));
+                       FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
                } else {
                        vm->open_cart(drv, file_path);
                }
@@ -914,12 +1221,12 @@ void EMU::open_cart(int drv, const _TCHAR* file_path)
                out_message(_T("Cart%d: %s"), drv + 1, file_path);
                
                // restart recording
-               bool s = osd->now_rec_sound;
-               bool v = osd->now_rec_video;
-               stop_rec_sound();
-               stop_rec_video();
-               if(s) osd->start_rec_sound();
-               if(v) osd->start_rec_video(-1);
+               bool s = osd->now_record_sound;
+               bool v = osd->now_record_video;
+               stop_record_sound();
+               stop_record_video();
+               if(s) osd->start_record_sound();
+               if(v) osd->start_record_video(-1);
        }
 }
 
@@ -931,15 +1238,15 @@ void EMU::close_cart(int drv)
                out_message(_T("Cart%d: Ejected"), drv + 1);
                
                // stop recording
-               stop_rec_video();
-               stop_rec_sound();
+               stop_record_video();
+               stop_record_sound();
        }
 }
 
-bool EMU::cart_inserted(int drv)
+bool EMU::is_cart_inserted(int drv)
 {
        if(drv < MAX_CART) {
-               return vm->cart_inserted(drv);
+               return vm->is_cart_inserted(drv);
        } else {
                return false;
        }
@@ -947,115 +1254,96 @@ bool EMU::cart_inserted(int drv)
 #endif
 
 #ifdef USE_FD1
-void EMU::open_disk(int drv, const _TCHAR* file_path, int bank)
+void EMU::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
 {
        if(drv < MAX_FD) {
-               if(vm->disk_inserted(drv)) {
-                       vm->close_disk(drv);
+               if(vm->is_floppy_disk_inserted(drv)) {
+                       vm->close_floppy_disk(drv);
                        // wait 0.5sec
 #ifdef SUPPORT_VARIABLE_TIMING
-                       disk_status[drv].wait_count = (int)(vm->frame_rate() / 2);
+                       floppy_disk_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
 #else
-                       disk_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
+                       floppy_disk_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
 #endif
                        out_message(_T("FD%d: Ejected"), drv + FD_BASE_NUMBER);
-               } else if(disk_status[drv].wait_count == 0) {
-                       vm->open_disk(drv, file_path, bank);
+               } else if(floppy_disk_status[drv].wait_count == 0) {
+                       vm->open_floppy_disk(drv, file_path, bank);
                        out_message(_T("FD%d: %s"), drv + FD_BASE_NUMBER, file_path);
                }
-               my_tcscpy_s(disk_status[drv].path, _MAX_PATH, file_path);
-               disk_status[drv].bank = bank;
+               my_tcscpy_s(floppy_disk_status[drv].path, _MAX_PATH, file_path);
+               floppy_disk_status[drv].bank = bank;
        }
 }
 
-void EMU::close_disk(int drv)
+void EMU::close_floppy_disk(int drv)
 {
        if(drv < MAX_FD) {
-               vm->close_disk(drv);
-               clear_media_status(&disk_status[drv]);
+               vm->close_floppy_disk(drv);
+               clear_media_status(&floppy_disk_status[drv]);
                out_message(_T("FD%d: Ejected"), drv + FD_BASE_NUMBER);
        }
 }
 
-bool EMU::disk_inserted(int drv)
+bool EMU::is_floppy_disk_inserted(int drv)
 {
        if(drv < MAX_FD) {
-               return vm->disk_inserted(drv);
+               return vm->is_floppy_disk_inserted(drv);
        } else {
                return false;
        }
 }
 
-void EMU::set_disk_protected(int drv, bool value)
+void EMU::is_floppy_disk_protected(int drv, bool value)
 {
        if(drv < MAX_FD) {
-               vm->set_disk_protected(drv, value);
+               vm->is_floppy_disk_protected(drv, value);
        }
 }
 
-bool EMU::get_disk_protected(int drv)
+bool EMU::is_floppy_disk_protected(int drv)
 {
        if(drv < MAX_FD) {
-               return vm->get_disk_protected(drv);
+               return vm->is_floppy_disk_protected(drv);
        } else {
                return false;
        }
 }
 #endif
 
-int EMU::get_access_lamp(void)
-{
-   int stat = 0;
-#if defined(USE_ACCESS_LAMP)
-# if defined(USE_FD1) || defined(USE_QD1)
-#  if !defined(_MSC_VER)
-//   LockVM();
-#  endif
-
-   stat = vm->access_lamp(); // Return accessing drive number.
-#  if !defined(_MSC_VER)
-//   UnlockVM();
-#  endif
-# endif
-#endif
-   return stat;
-}
-
-
 #ifdef USE_QD1
-void EMU::open_quickdisk(int drv, const _TCHAR* file_path)
+void EMU::open_quick_disk(int drv, const _TCHAR* file_path)
 {
        if(drv < MAX_QD) {
-               if(vm->quickdisk_inserted(drv)) {
-                       vm->close_quickdisk(drv);
+               if(vm->is_quick_disk_inserted(drv)) {
+                       vm->close_quick_disk(drv);
                        // wait 0.5sec
 #ifdef SUPPORT_VARIABLE_TIMING
-                       quickdisk_status[drv].wait_count = (int)(vm->frame_rate() / 2);
+                       quick_disk_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
 #else
-                       quickdisk_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
+                       quick_disk_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
 #endif
                        out_message(_T("QD%d: Ejected"), drv + QD_BASE_NUMBER);
-               } else if(quickdisk_status[drv].wait_count == 0) {
-                       vm->open_quickdisk(drv, file_path);
+               } else if(quick_disk_status[drv].wait_count == 0) {
+                       vm->open_quick_disk(drv, file_path);
                        out_message(_T("QD%d: %s"), drv + QD_BASE_NUMBER, file_path);
                }
-               my_tcscpy_s(quickdisk_status[drv].path, _MAX_PATH, file_path);
+               my_tcscpy_s(quick_disk_status[drv].path, _MAX_PATH, file_path);
        }
 }
 
-void EMU::close_quickdisk(int drv)
+void EMU::close_quick_disk(int drv)
 {
        if(drv < MAX_QD) {
-               vm->close_quickdisk(drv);
-               clear_media_status(&quickdisk_status[drv]);
+               vm->close_quick_disk(drv);
+               clear_media_status(&quick_disk_status[drv]);
                out_message(_T("QD%d: Ejected"), drv + QD_BASE_NUMBER);
        }
 }
 
-bool EMU::quickdisk_inserted(int drv)
+bool EMU::is_quick_disk_inserted(int drv)
 {
        if(drv < MAX_QD) {
-               return vm->quickdisk_inserted(drv);
+               return vm->is_quick_disk_inserted(drv);
        } else {
                return false;
        }
@@ -1065,11 +1353,11 @@ bool EMU::quickdisk_inserted(int drv)
 #ifdef USE_TAPE
 void EMU::play_tape(const _TCHAR* file_path)
 {
-       if(vm->tape_inserted()) {
+       if(vm->is_tape_inserted()) {
                vm->close_tape();
                // wait 0.5sec
 #ifdef SUPPORT_VARIABLE_TIMING
-               tape_status.wait_count = (int)(vm->frame_rate() / 2);
+               tape_status.wait_count = (int)(vm->get_frame_rate() / 2);
 #else
                tape_status.wait_count = (int)(FRAMES_PER_SEC / 2);
 #endif
@@ -1084,11 +1372,11 @@ void EMU::play_tape(const _TCHAR* file_path)
 
 void EMU::rec_tape(const _TCHAR* file_path)
 {
-       if(vm->tape_inserted()) {
+       if(vm->is_tape_inserted()) {
                vm->close_tape();
                // wait 0.5sec
 #ifdef SUPPORT_VARIABLE_TIMING
-               tape_status.wait_count = (int)(vm->frame_rate() / 2);
+               tape_status.wait_count = (int)(vm->get_frame_rate() / 2);
 #else
                tape_status.wait_count = (int)(FRAMES_PER_SEC / 2);
 #endif
@@ -1108,25 +1396,25 @@ void EMU::close_tape()
        out_message(_T("CMT: Ejected"));
 }
 
-bool EMU::tape_inserted()
+bool EMU::is_tape_inserted()
 {
-       return vm->tape_inserted();
+       return vm->is_tape_inserted();
 }
 
 #ifndef TAPE_BINARY_ONLY
-bool EMU::tape_playing()
+bool EMU::is_tape_playing()
 {
-       return vm->tape_playing();
+       return vm->is_tape_playing();
 }
 
-bool EMU::tape_recording()
+bool EMU::is_tape_recording()
 {
-       return vm->tape_recording();
+       return vm->is_tape_recording();
 }
 
-int EMU::tape_position()
+int EMU::get_tape_position()
 {
-       return vm->tape_position();
+       return vm->get_tape_position();
 }
 #endif
 
@@ -1163,14 +1451,46 @@ void EMU::push_apss_rewind()
 #endif
 #endif
 
+#ifdef USE_COMPACT_DISC
+void EMU::open_compact_disc(const _TCHAR* file_path)
+{
+       if(vm->is_compact_disc_inserted()) {
+               vm->close_compact_disc();
+               // wait 0.5sec
+#ifdef SUPPORT_VARIABLE_TIMING
+               compact_disc_status.wait_count = (int)(vm->get_frame_rate() / 2);
+#else
+               compact_disc_status.wait_count = (int)(FRAMES_PER_SEC / 2);
+#endif
+               out_message(_T("CD: Ejected"));
+       } else if(compact_disc_status.wait_count == 0) {
+               vm->open_compact_disc(file_path);
+               out_message(_T("CD: %s"), file_path);
+       }
+       my_tcscpy_s(compact_disc_status.path, _MAX_PATH, file_path);
+}
+
+void EMU::close_compact_disc()
+{
+       vm->close_compact_disc();
+       clear_media_status(&compact_disc_status);
+       out_message(_T("CD: Ejected"));
+}
+
+bool EMU::is_compact_disc_inserted()
+{
+       return vm->is_compact_disc_inserted();
+}
+#endif
+
 #ifdef USE_LASER_DISC
 void EMU::open_laser_disc(const _TCHAR* file_path)
 {
-       if(vm->laser_disc_inserted()) {
+       if(vm->is_laser_disc_inserted()) {
                vm->close_laser_disc();
                // wait 0.5sec
 #ifdef SUPPORT_VARIABLE_TIMING
-               laser_disc_status.wait_count = (int)(vm->frame_rate() / 2);
+               laser_disc_status.wait_count = (int)(vm->get_frame_rate() / 2);
 #else
                laser_disc_status.wait_count = (int)(FRAMES_PER_SEC / 2);
 #endif
@@ -1189,9 +1509,9 @@ void EMU::close_laser_disc()
        out_message(_T("LD: Ejected"));
 }
 
-bool EMU::laser_disc_inserted()
+bool EMU::is_laser_disc_inserted()
 {
-       return vm->laser_disc_inserted();
+       return vm->is_laser_disc_inserted();
 }
 #endif
 
@@ -1199,9 +1519,9 @@ bool EMU::laser_disc_inserted()
 void EMU::load_binary(int drv, const _TCHAR* file_path)
 {
        if(drv < MAX_BINARY) {
-               if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, osd->bios_path(_T("hex2bin.$$$")))) {
-                       vm->load_binary(drv, osd->bios_path(_T("hex2bin.$$$")));
-                       FILEIO::RemoveFile(osd->bios_path(_T("hex2bin.$$$")));
+               if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, create_local_path(_T("hex2bin.$$$")))) {
+                       vm->load_binary(drv, create_local_path(_T("hex2bin.$$$")));
+                       FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
                } else {
                        vm->load_binary(drv, file_path);
                }
@@ -1217,17 +1537,85 @@ void EMU::save_binary(int drv, const _TCHAR* file_path)
        }
 }
 #endif
-#ifdef SUPPORT_DUMMY_DEVICE_LED
-uint32 EMU::get_led_status(void)
+#ifdef USE_BUBBLE1
+void EMU::open_bubble_casette(int drv, const _TCHAR* file_path, int bank)
+{
+       if(drv < MAX_BUBBLE) {
+               if(vm->is_bubble_casette_inserted(drv)) {
+                       vm->close_bubble_casette(drv);
+                       // wait 0.5sec
+#ifdef SUPPORT_VARIABLE_TIMING
+                       bubble_casette_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
+#else
+                       bubble_casette_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2);
+#endif
+                       out_message(_T("Bubble%d: Ejected"), drv + 1);
+               } else if(bubble_casette_status[drv].wait_count == 0) {
+                       vm->open_bubble_casette(drv, file_path, bank);
+                       out_message(_T("Bubble%d: %s"), drv + 1, file_path);
+               }
+               my_tcscpy_s(bubble_casette_status[drv].path, _MAX_PATH, file_path);
+               bubble_casette_status[drv].bank = bank;
+       }
+}
+
+void EMU::close_bubble_casette(int drv)
+{
+       if(drv < MAX_BUBBLE) {
+               vm->close_bubble_casette(drv);
+               clear_media_status(&bubble_casette_status[drv]);
+               out_message(_T("Bubble%d: Ejected"), drv + 1);
+       }
+}
+
+bool EMU::is_bubble_casette_inserted(int drv)
+{
+       if(drv < MAX_BUBBLE) {
+               return vm->is_bubble_casette_inserted(drv);
+       } else {
+               return false;
+       }
+}
+
+bool EMU::is_bubble_casette_protected(int drv)
+{
+       if(drv < MAX_BUBBLE) {
+               return vm->is_bubble_casette_protected(drv);
+       } else {
+               return false;
+       }
+}
+
+void EMU::is_bubble_casette_protected(int drv, bool flag)
+{
+       if(drv < MAX_BUBBLE) {
+               return vm->is_bubble_casette_protected(drv, flag);
+       } else {
+               return false;
+       }
+}
+#endif
+
+#ifdef USE_ACCESS_LAMP
+uint32_t EMU::get_access_lamp_status()
+{
+       return vm->get_access_lamp_status();
+}
+#endif
+
+#ifdef USE_LED_DEVICE
+uint32_t EMU::get_led_status()
 {
        return vm->get_led_status();
 }
 #endif
 
-bool EMU::now_skip()
+#ifdef USE_SOUND_VOLUME
+void EMU::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
 {
-       return vm->now_skip();
+       vm->set_sound_device_volume(ch, decibel_l, decibel_r);
 }
+#endif
 
 void EMU::update_config()
 {
@@ -1245,23 +1633,18 @@ void EMU::update_config()
 
 void EMU::save_state()
 {
-       _TCHAR file_name[_MAX_PATH];
-       my_stprintf_s(file_name, _MAX_PATH, _T("%s.sta"), _T(CONFIG_NAME));
-       save_state_tmp(osd->bios_path(file_name));
+       save_state_tmp(create_local_path(_T("%s.sta"), _T(CONFIG_NAME)));
 }
 
 void EMU::load_state()
 {
-       _TCHAR file_name[_MAX_PATH];
-       my_stprintf_s(file_name, _MAX_PATH, _T("%s.sta"), _T(CONFIG_NAME));
-       FILEIO ffp;
-       if(ffp.IsFileExists(osd->bios_path(file_name))) {
-               save_state_tmp(bios_path(_T("$temp$.sta")));
-               if(!load_state_tmp(osd->bios_path(file_name))) {
-                       out_debug_log("failed to load state file\n");
-                       load_state_tmp(osd->bios_path(_T("$temp$.sta")));
+       if(FILEIO::IsFileExisting(create_local_path(_T("%s.sta"), _T(CONFIG_NAME)))) {
+               save_state_tmp(create_local_path(_T("$temp$.sta")));
+               if(!load_state_tmp(create_local_path(_T("%s.sta"), _T(CONFIG_NAME)))) {
+                       out_debug_log(_T("failed to load state file\n"));
+                       load_state_tmp(create_local_path(_T("$temp$.sta")));
                }
-               DeleteFile(osd->bios_path(_T("$temp$.sta")));
+               FILEIO::RemoveFile(create_local_path(_T("$temp$.sta")));
        }
 }
 
@@ -1279,15 +1662,18 @@ void EMU::save_state_tmp(const _TCHAR* file_path)
                fio->Fwrite(&cart_status, sizeof(cart_status), 1);
 #endif
 #ifdef USE_FD1
-               fio->Fwrite(disk_status, sizeof(disk_status), 1);
+               fio->Fwrite(floppy_disk_status, sizeof(floppy_disk_status), 1);
                fio->Fwrite(d88_file, sizeof(d88_file), 1);
 #endif
 #ifdef USE_QD1
-               fio->Fwrite(&quickdisk_status, sizeof(quickdisk_status), 1);
+               fio->Fwrite(&quick_disk_status, sizeof(quick_disk_status), 1);
 #endif
 #ifdef USE_TAPE
                fio->Fwrite(&tape_status, sizeof(tape_status), 1);
 #endif
+#ifdef USE_COMPACT_DISC
+               fio->Fwrite(&compact_disc_status, sizeof(compact_disc_status), 1);
+#endif
 #ifdef USE_LASER_DISC
                fio->Fwrite(&laser_disc_status, sizeof(laser_disc_status), 1);
 #endif
@@ -1305,6 +1691,7 @@ bool EMU::load_state_tmp(const _TCHAR* file_path)
 {
        bool result = false;
        FILEIO* fio = new FILEIO();
+       osd->lock_vm();
        if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
                // check state file version
                if(fio->FgetUint32() == STATE_VERSION) {
@@ -1315,15 +1702,18 @@ bool EMU::load_state_tmp(const _TCHAR* file_path)
                                fio->Fread(&cart_status, sizeof(cart_status), 1);
 #endif
 #ifdef USE_FD1
-                               fio->Fread(disk_status, sizeof(disk_status), 1);
+                               fio->Fread(floppy_disk_status, sizeof(floppy_disk_status), 1);
                                fio->Fread(d88_file, sizeof(d88_file), 1);
 #endif
 #ifdef USE_QD1
-                               fio->Fread(&quickdisk_status, sizeof(quickdisk_status), 1);
+                               fio->Fread(&quick_disk_status, sizeof(quick_disk_status), 1);
 #endif
 #ifdef USE_TAPE
                                fio->Fread(&tape_status, sizeof(tape_status), 1);
 #endif
+#ifdef USE_COMPACT_DISC
+                               fio->Fread(&compact_disc_status, sizeof(compact_disc_status), 1);
+#endif
 #ifdef USE_LASER_DISC
                                fio->Fread(&laser_disc_status, sizeof(laser_disc_status), 1);
 #endif
@@ -1337,16 +1727,25 @@ bool EMU::load_state_tmp(const _TCHAR* file_path)
                                reinitialize |= (sound_device_type != config.sound_device_type);
                                sound_device_type = config.sound_device_type;
 #endif
+#ifdef USE_PRINTER
+                               reinitialize |= (printer_device_type != config.printer_device_type);
+                               printer_device_type = config.printer_device_type;
+#endif
                                if(reinitialize) {
                                        // stop sound
-                                       osd->lock_vm();
+                                       //osd->lock_vm();
                                        // reinitialize virtual machine
                                        osd->stop_sound();
                                        delete vm;
                                        osd->vm = vm = new VM(this);
                                        vm->initialize_sound(sound_rate, sound_samples);
+#ifdef USE_SOUND_VOLUME
+                                       for(int i = 0; i < USE_SOUND_VOLUME; i++) {
+                                               vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
+                                       }
+#endif
                                        vm->reset();
-                                       osd->unlock_vm();
+                                       //osd->unlock_vm();
                                }
                                // restore inserted medias
                                restore_media();
@@ -1364,10 +1763,3 @@ bool EMU::load_state_tmp(const _TCHAR* file_path)
        return result;
 }
 #endif
-
-#if defined(USE_DIG_RESOLUTION)
-void EMU::get_screen_resolution(int *w, int *h)
-{
-       vm->get_screen_resolution(w, h);
-}
-#endif