OSDN Git Service

[VM][FM7] Add sounds; FDD Seeking and Relay.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / fm7.cpp
index 8bdcbd1..80ec677 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * FM7 -> VM
  * (C) 2015 K.Ohta <whatisthis.sowhat _at_ gmail.com>
 #ifdef USE_DEBUGGER
 #include "../debugger.h"
 #endif
-#if defined(SUPPORT_DUMMY_DEVICE_LED)
-#include "../dummydevice.h"
-#else
-#define SIG_DUMMYDEVICE_BIT0 0
-#define SIG_DUMMYDEVICE_BIT1 1
-#define SIG_DUMMYDEVICE_BIT2 2
-#endif
 
 #include "../datarec.h"
 #include "../disk.h"
 #if defined(HAS_DMA)
 #include "hd6844.h"
 #endif
+#if defined(_FM8)
+#include "./bubblecasette.h"
+#endif
 
+#if defined(USE_LED_DEVICE)
+#include "./dummydevice.h"
+#else
+#define SIG_DUMMYDEVICE_BIT0 0
+#define SIG_DUMMYDEVICE_BIT1 1
+#define SIG_DUMMYDEVICE_BIT2 2
+#endif
+#if defined(USE_SOUND_FILES)
+#include "../wav_sounder.h"
+#endif
 #include "./fm7_mainio.h"
 #include "./fm7_mainmem.h"
 #include "./fm7_display.h"
@@ -73,22 +78,7 @@ VM::VM(EMU* parent_emu): emu(parent_emu)
        z80cpu = new Z80(this, emu);
 #endif
        // basic devices
-#if defined(_FM8) || defined(_FM7) || defined(_FMNEW7)
-       if((config.dipswitch & FM7_DIPSW_CONNECT_KANJIROM) != 0) {
-               kanjiclass1 = new KANJIROM(this, emu, false);
-       }
-#else
-       kanjiclass1 = new KANJIROM(this, emu, false);
-#endif 
-#ifdef CAPABLE_KANJI_CLASS2
-       kanjiclass2 = new KANJIROM(this, emu, true);
-#endif
-       joystick  = new JOYSTICK(this, emu);
-       
        // I/Os
-       drec = new DATAREC(this, emu);
-       pcm1bit = new PCM1BIT(this, emu);
-       fdc  = new MB8877(this, emu);
 #if defined(HAS_DMA)
        dmac = new HD6844(this, emu);
 #endif   
@@ -102,36 +92,113 @@ VM::VM(EMU* parent_emu): emu(parent_emu)
        psg = new YM2203(this, emu);
 # endif
 #endif
+#if defined(_FM8)
+       for(int i = 0; i < 2; i++) bubble_casette[i] = new BUBBLECASETTE(this, emu);
+#endif 
+       drec = new DATAREC(this, emu);
+       pcm1bit = new PCM1BIT(this, emu);
+
+       connect_320kfdc = connect_1Mfdc = false;
+       fdc = NULL;
+#if defined(_FM8) || defined(_FM7) || defined(_FMNEW7)
+       if(((config.dipswitch & FM7_DIPSW_CONNECT_320KFDC) != 0) ||
+          ((config.dipswitch & FM7_DIPSW_CONNECT_1MFDC) != 0)) {
+#endif         
+               fdc = new MB8877(this, emu);
+#if defined(_FM8) || defined(_FM7) || defined(_FMNEW7)
+               if((config.dipswitch & FM7_DIPSW_CONNECT_320KFDC) != 0) {
+                       connect_320kfdc = true;
+               }
+               if((config.dipswitch & FM7_DIPSW_CONNECT_1MFDC) != 0) {
+                       connect_1Mfdc = true;
+               }
+#elif defined(_FM77_VARIANTS)
+               connect_320kfdc = true;
+               if((config.dipswitch & FM7_DIPSW_CONNECT_1MFDC) != 0) {
+                       connect_1Mfdc = true;
+               }
+#else  // AV or later.
+               connect_320kfdc = true;
+               // 1MFDD??
+#endif         
+#if defined(_FM8) || defined(_FM7) || defined(_FMNEW7)
+       }
+#endif 
+       joystick  = new JOYSTICK(this, emu);
+       printer = new PRNFILE(this, emu);
 #if defined(_FM77AV_VARIANTS)
        alu = new MB61VH010(this, emu);
        keyboard_beep = new BEEP(this, emu);
 #endif 
+       keyboard = new KEYBOARD(this, emu);
        display = new DISPLAY(this, emu);       
-       printer = new PRNFILE(this, emu);
+
        mainio  = new FM7_MAINIO(this, emu);
        mainmem = new FM7_MAINMEM(this, emu);
-       keyboard = new KEYBOARD(this, emu);
-
-#if defined(SUPPORT_DUMMY_DEVICE_LED)
+       
+#if defined(_FM8) || defined(_FM7) || defined(_FMNEW7)
+       if((config.dipswitch & FM7_DIPSW_CONNECT_KANJIROM) != 0) {
+               kanjiclass1 = new KANJIROM(this, emu, false);
+       } else {
+               kanjiclass1 = NULL;
+       }
+#else
+       kanjiclass1 = new KANJIROM(this, emu, false);
+#endif 
+#ifdef CAPABLE_KANJI_CLASS2
+       kanjiclass2 = new KANJIROM(this, emu, true);
+#endif
+#if defined(USE_LED_DEVICE)
        led_terminate = new DUMMYDEVICE(this, emu);
 #else
        led_terminate = new DEVICE(this, emu);
 #endif
-       // MEMORIES must set before initialize().
-       maincpu->set_context_mem(mainmem);
-       subcpu->set_context_mem(display);
-#ifdef WITH_Z80
-       z80cpu->set_context_mem(mainmem);
-#endif
-#ifdef USE_DEBUGGER
-       maincpu->set_context_debugger(new DEBUGGER(this, emu));
-       subcpu->set_context_debugger(new DEBUGGER(this, emu));
+#if defined(USE_SOUND_FILES)
+       fdd_seek = new WAV_SOUNDER(this, emu);
+       cmt_relay_on = new WAV_SOUNDER(this, emu);
+       cmt_relay_off = new WAV_SOUNDER(this, emu);
+#endif 
+#if defined(_USE_QT)
+       event->set_device_name(_T("EVENT"));
+       dummy->set_device_name(_T("1st Dummy"));
+       
+       maincpu->set_device_name(_T("MAINCPU(MC6809)"));
+       subcpu->set_device_name(_T("SUBCPU(MC6809)"));
+       dummycpu->set_device_name(_T("DUMMY CPU"));
 # ifdef WITH_Z80
-       z80cpu->set_context_debugger(new DEBUGGER(this, emu));
+       z80cpu->set_device_name(_T("Z80 CPU"));
 # endif
+       led_terminate->set_device_name(_T("LEDs"));
+       if(fdc != NULL) fdc->set_device_name(_T("MB8877 FDC(320KB)"));
+                                               
+       // basic devices
+       // I/Os
+# if defined(_FM8)
+       psg->set_device_name(_T("AY-3-8910 PSG"));
+# else 
+       opn[0]->set_device_name(_T("YM2203 OPN"));
+       opn[1]->set_device_name(_T("YM2203 WHG"));
+       opn[2]->set_device_name(_T("YM2203 THG"));
+#  if !defined(_FM77AV_VARIANTS)
+       psg->set_device_name(_T("AY-3-8910 PSG"));
+#  endif
+# endif
+       pcm1bit->set_device_name(_T("BEEP"));
+       printer->set_device_name(_T("PRINTER I/F"));
+# if defined(_FM77AV_VARIANTS)
+       keyboard_beep->set_device_name(_T("BEEP(KEYBOARD)"));
+# endif        
+       if(kanjiclass1 != NULL) kanjiclass1->set_device_name(_T("KANJI ROM CLASS1"));
+# ifdef CAPABLE_KANJI_CLASS2
+       if(kanjiclass2 != NULL) kanjiclass2->set_device_name(_T("KANJI ROM CLASS2"));
+# endif
+# if defined(_FM8)
+       bubble_casette[0]->set_device_name(_T("BUBBLE CASETTE #0"));
+       bubble_casette[1]->set_device_name(_T("BUBBLE CASETTE #1"));
+# endif        
 #endif
-       connect_bus();
-       initialize();
+       this->connect_bus();
+       
 }
 
 VM::~VM()
@@ -155,18 +222,10 @@ DEVICE* VM::get_device(int id)
        return NULL;
 }
 
-
-void VM::initialize(void)
-{
-       clock_low = false;
-       
-}
-
-
 void VM::connect_bus(void)
 {
-       uint32 mainclock;
-       uint32 subclock;
+       uint32_t mainclock;
+       uint32_t subclock;
 
        /*
         * CLASS CONSTRUCTION
@@ -188,9 +247,11 @@ void VM::connect_bus(void)
         */
        event->set_frames_per_sec(FRAMES_PER_SEC);
        event->set_lines_per_frame(LINES_PER_FRAME);
-       event->set_context_cpu(dummycpu, (CPU_CLOCKS * 3) / 8); // MAYBE FIX With eFM77AV40/20.
-       //event->set_context_cpu(dummycpu, (int)(4.9152 * 1000.0 * 1000.0 / 4.0));
-       
+       //event->set_context_cpu(dummycpu, (CPU_CLOCKS * 3) / 8); // MAYBE FIX With eFM77AV40/20.
+       // With slow clock (for dummycpu), some softwares happen troubles,
+       // Use faster clock for dummycpu. 20160319 K.Ohta
+       event->set_context_cpu(dummycpu, SUBCLOCK_NORMAL);
+
 #if defined(_FM8)
        mainclock = MAINCLOCK_SLOW;
        subclock = SUBCLOCK_SLOW;
@@ -226,11 +287,21 @@ void VM::connect_bus(void)
        event->set_context_sound(psg);
 # endif
        event->set_context_sound(drec);
+#if defined(USE_SOUND_FILES)
+       fdd_seek->load_data(_T("FDDSEEK.WAV"));
+       event->set_context_sound(fdd_seek);
+       
+       cmt_relay_on->load_data(_T("RELAY_ON.WAV"));
+       cmt_relay_off->load_data(_T("RELAYOFF.WAV"));
+       event->set_context_sound(cmt_relay_on);
+       event->set_context_sound(cmt_relay_off);
+#endif
 # if defined(_FM77AV_VARIANTS)
        event->set_context_sound(keyboard_beep);
 # endif
 #endif   
 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
+       event->register_vline_event(display);
        event->register_frame_event(display);
 #endif 
        mainio->set_context_maincpu(maincpu);
@@ -247,11 +318,15 @@ void VM::connect_bus(void)
        mainio->set_context_mainmem(mainmem);
        mainio->set_context_keyboard(keyboard);
        mainio->set_context_printer(printer);
-   
+       mainio->set_context_printer_reset(printer, SIG_PRINTER_RESET, 0xffffffff);
+       mainio->set_context_printer_strobe(printer, SIG_PRINTER_STROBE, 0xffffffff);
+       mainio->set_context_printer_select(printer, SIG_PRINTER_SELECT, 0xffffffff);
 #if defined(CAPABLE_KANJI_CLASS2)
        mainio->set_context_kanjirom_class2(kanjiclass2);
 #endif
-
+#if defined(_FM8)
+       for(int i = 0; i < 2; i++) mainio->set_context_bubble(bubble_casette[i], i);
+#endif 
        keyboard->set_context_break_line(mainio, FM7_MAINIO_PUSH_BREAK, 0xffffffff);
        keyboard->set_context_int_line(mainio, FM7_MAINIO_KEYBOARDIRQ, 0xffffffff);
        keyboard->set_context_int_line(display, SIG_FM7_SUB_KEY_FIRQ, 0xffffffff);
@@ -296,11 +371,21 @@ void VM::connect_bus(void)
 #endif 
        // Palette, VSYNC, HSYNC, Multi-page, display mode. 
        mainio->set_context_display(display);
-       
-       //FDC
-       mainio->set_context_fdc(fdc);
-       fdc->set_context_irq(mainio, FM7_MAINIO_FDC_IRQ, 0x1);
-       fdc->set_context_drq(mainio, FM7_MAINIO_FDC_DRQ, 0x1);
+#if defined(_FM8) || (_FM7) || (_FMNEW7)
+       if(connect_320kfdc || connect_1Mfdc) {
+#endif         
+               //FDC
+               fdc->set_context_irq(mainio, FM7_MAINIO_FDC_IRQ, 0x1);
+               fdc->set_context_drq(mainio, FM7_MAINIO_FDC_DRQ, 0x1);
+               mainio->set_context_fdc(fdc);
+#if defined(USE_SOUND_FILES)
+               fdc->set_context_seek(fdd_seek);
+               mainio->set_context_relay_on(cmt_relay_on);
+               mainio->set_context_relay_off(cmt_relay_off);
+#endif
+#if defined(_FM8) || (_FM7) || (_FMNEW7)
+       }
+#endif 
        // SOUND
        mainio->set_context_beep(pcm1bit);
 #if defined(_FM8)      
@@ -331,93 +416,63 @@ void VM::connect_bus(void)
        dmac->set_context_drq_line(maincpu, 1, SIG_CPU_BUSREQ, 0xffffffff);
        mainio->set_context_dmac(dmac);
 #endif
+       
+       // MEMORIES must set before initialize().
+       maincpu->set_context_mem(mainmem);
+       subcpu->set_context_mem(display);
+#ifdef WITH_Z80
+       z80cpu->set_context_mem(mainmem);
+#endif
+#ifdef USE_DEBUGGER
+       maincpu->set_context_debugger(new DEBUGGER(this, emu));
+       subcpu->set_context_debugger(new DEBUGGER(this, emu));
+# ifdef WITH_Z80
+       z80cpu->set_context_debugger(new DEBUGGER(this, emu));
+# endif
+#endif
        for(DEVICE* device = first_device; device; device = device->next_device) {
                device->initialize();
        }
-       for(int i = 0; i < 2; i++) {
-#if defined(_FM77AV20) || defined(_FM77AV40SX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
-               fdc->set_drive_type(i, DRIVE_TYPE_2DD);
+
+       // Disks
+#if defined(_FM8) || (_FM7) || (_FMNEW7)
+       if(connect_320kfdc) {
+#endif         
+               for(int i = 0; i < 4; i++) {
+#if defined(_FM77AV20) || defined(_FM77AV20EX) || \
+       defined(_FM77AV40SX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
+                       fdc->set_drive_type(i, DRIVE_TYPE_2DD);
 #else
-               fdc->set_drive_type(i, DRIVE_TYPE_2D);
+                       fdc->set_drive_type(i, DRIVE_TYPE_2D);
 #endif
-#if defined(_FM77AV_VARIANTS)
-               fdc->set_drive_rpm(i, 360);
-#else          
-               fdc->set_drive_rpm(i, 360);
-#endif         
-               fdc->set_drive_mfm(i, true);
-       }
-#if defined(_FM77) || defined(_FM77L4)
-       for(int i = 2; i < 4; i++) {
-               fdc->set_drive_type(i, DRIVE_TYPE_2HD);
-               fdc->set_drive_rpm(i, 360);
-               fdc->set_drive_mfm(i, true);
+                       fdc->set_drive_rpm(i, 360);
+                       fdc->set_drive_mfm(i, true);
+               }
+#if defined(_FM8) || (_FM7) || (_FMNEW7)
        }
-#endif
+#endif 
        
+#if defined(_FM8) || (_FM7) || (_FMNEW7)
+       if(connect_1Mfdc) {
+#endif
+// ToDo: Implement another FDC for 1MB (2HD or 8''), this is used by FM-8 to FM-77? Not FM77AV or later? I still know this.
+//#if defined(_FM77) || defined(_FM77L4)
+//             for(int i = 0; i < 4; i++) {
+//                     fdc->set_drive_type(i, DRIVE_TYPE_2HD);
+//                     fdc->set_drive_rpm(i, 360);
+//                     fdc->set_drive_mfm(i, true);
+//             }
+//#endif
+#if defined(_FM8) || (_FM7) || (_FMNEW7)
+       }
+#endif 
 }  
 
 void VM::update_config()
 {
-       uint32 vol1, vol2, tmpv;
+       uint32_t vol1, vol2, tmpv;
        int ii, i_limit;
 
-#if defined(SIG_YM2203_LVOLUME) && defined(SIG_YM2203_RVOLUME)
-# if defined(USE_MULTIPLE_SOUNDCARDS)
-       i_limit = USE_MULTIPLE_SOUNDCARDS - 1;
-# else
-#  if !defined(_FM77AV_VARIANTS) && !defined(_FM8)
-       i_limit = 4;
-#  elif defined(_FM8)
-       i_limit = 1; // PSG Only
-#  else
-       i_limit = 3;
-#  endif
-# endif
-       for(ii = 0; ii < i_limit; ii++) {
-               if(config.multiple_speakers) { //
-                       vol1 = 256;
-                       vol2 = vol1 >> 2;
-               } else {
-                       vol1 = vol2 = 256;
-               }
-               switch(ii) {
-               case 0: // OPN
-                       break;
-               case 1: // WHG
-                       tmpv = vol1;
-                       vol1 = vol2;
-                       vol2 = tmpv;
-                       break;
-               case 2: // THG
-               case 3: // PSG
-                       vol2 = vol1;
-                       break;
-               default:
-                       break;
-               }
-#if defined(_FM8)
-               psg->write_signal(SIG_YM2203_LVOLUME, vol1, 0xffffffff); // OPN: LEFT
-               psg->write_signal(SIG_YM2203_RVOLUME, vol1, 0xffffffff); // OPN: RIGHT
-# elif defined(_FM7) || defined(_FMNEW7) || defined(_FM77_VARIANTS)
-               if(ii < 3) {
-                       opn[ii]->write_signal(SIG_YM2203_LVOLUME, vol1, 0xffffffff); // OPN: LEFT
-                       opn[ii]->write_signal(SIG_YM2203_RVOLUME, vol2, 0xffffffff); // OPN: RIGHT
-               } else {
-                       psg->write_signal(SIG_YM2203_LVOLUME, vol1, 0xffffffff); // OPN: LEFT
-                       psg->write_signal(SIG_YM2203_RVOLUME, vol2, 0xffffffff); // OPN: RIGHT
-               }                       
-# else // FM77AV
-               if(ii < 3) {
-                       opn[ii]->write_signal(SIG_YM2203_LVOLUME, vol1, 0xffffffff); // OPN: LEFT
-                       opn[ii]->write_signal(SIG_YM2203_RVOLUME, vol2, 0xffffffff); // OPN: RIGHT
-               }
-# endif                
-       }
-#endif   
-#if defined(USE_MULTIPLE_SOUNDCARDS) && defined(DATAREC_SOUND)
-       drec->write_signal(SIG_DATAREC_VOLUME, (config.sound_device_level[USE_MULTIPLE_SOUNDCARDS - 1] + 32768) >> 3, 0xffffffff); 
-#endif
        for(DEVICE* device = first_device; device; device = device->next_device) {
                device->update_config();
        }
@@ -430,6 +485,18 @@ void VM::reset()
        for(DEVICE* device = first_device; device; device = device->next_device) {
                device->reset();
        }
+#if !defined(_FM77AV_VARIANTS) || defined(_FM8)
+       psg->set_reg(0x27, 0); // stop timer
+       psg->set_reg(0x2e, 0);  // set prescaler
+       psg->write_signal(SIG_YM2203_MUTE, 0x00, 0x01); // Okay?
+#endif
+#if !defined(_FM8)
+       for(int i = 0; i < 3; i++) {
+               opn[i]->set_reg(0x27, 0); // stop timer
+               opn[i]->set_reg(0x2e, 0);       // set prescaler
+               opn[i]->write_signal(SIG_YM2203_MUTE, 0x00, 0x01); // Okay?
+       }
+#endif
 }
 
 void VM::special_reset()
@@ -454,17 +521,17 @@ void VM::run()
        event->drive();
 }
 
-double VM::frame_rate()
+double VM::get_frame_rate()
 {
-       return event->frame_rate();
+       return event->get_frame_rate();
 }
 
-#if defined(SUPPORT_DUMMY_DEVICE_LED)
-uint32 VM::get_led_status()
+#if defined(USE_LED_DEVICE)
+uint32_t VM::get_led_status()
 {
        return led_terminate->read_signal(SIG_DUMMYDEVICE_READWRITE);
 }
-#endif // SUPPORT_DUMMY_DEVICE_LED
+#endif // USE_LED_DEVICE
 
 
 // ----------------------------------------------------------------------------
@@ -497,10 +564,19 @@ void VM::draw_screen()
        display->draw_screen();
 }
 
-int VM::access_lamp()
+uint32_t VM::get_access_lamp_status()
 {
-       uint32 status = fdc->read_signal(0);
-       return (status & (1 | 4)) ? 1 : (status & (2 | 8)) ? 2 : 0;
+       // WILLFIX : Multiple FDC for 1M FD.
+#if defined(_FM8) || (_FM7) || (_FMNEW7)
+       if(connect_320kfdc || connect_1Mfdc) {
+#endif         
+               uint32_t status = fdc->read_signal(0xff);
+               return (status & (1 | 4)) ? 1 : (status & (2 | 8)) ? 2 : 0;
+#if defined(_FM8) || (_FM7) || (_FMNEW7)
+       } else {
+               return 0x00000000;
+       }
+#endif         
 }
 
 void VM::initialize_sound(int rate, int samples)
@@ -509,31 +585,31 @@ void VM::initialize_sound(int rate, int samples)
        event->initialize_sound(rate, samples);
        // init sound gen
 #if defined(_FM8)
-       psg->init(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
+       psg->initialize_sound(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
 #else  
-       opn[0]->init(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
-       opn[1]->init(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
-       opn[2]->init(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
+       opn[0]->initialize_sound(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
+       opn[1]->initialize_sound(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
+       opn[2]->initialize_sound(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
 # if !defined(_FM77AV_VARIANTS)   
-       psg->init(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
+       psg->initialize_sound(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
 # endif
 # if defined(_FM77AV_VARIANTS)
-       keyboard_beep->init(rate, 2400.0, 512);
+       keyboard_beep->initialize_sound(rate, 2400.0, 512);
 # endif
 #endif 
-       pcm1bit->init(rate, 2000);
-       //drec->init_pcm(rate, 0);
+       pcm1bit->initialize_sound(rate, 2000);
+       //drec->initialize_sound(rate, 0);
 }
 
-uint16* VM::create_sound(int* extra_frames)
+uint16_t* VM::create_sound(int* extra_frames)
 {
-       uint16* p = event->create_sound(extra_frames);
+       uint16_t* p = event->create_sound(extra_frames);
        return p;
 }
 
-int VM::sound_buffer_ptr()
+int VM::get_sound_buffer_ptr()
 {
-       int pos = event->sound_buffer_ptr();
+       int pos = event->get_sound_buffer_ptr();
        return pos; 
 }
 
@@ -566,6 +642,19 @@ void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
        } else if(ch-- == 0) {
                drec->set_volume(0, decibel_l, decibel_r);
        }
+#if defined(_FM77AV_VARIANTS)
+        else if(ch-- == 0) {
+               keyboard_beep->set_volume(0, decibel_l, decibel_r);
+       }
+#endif
+#if defined(USE_SOUND_FILES)
+        else if(ch-- == 0) {
+                fdd_seek->set_volume(0, decibel_l, decibel_r);
+        } else if(ch-- == 0) {
+                cmt_relay_on->set_volume(0, decibel_l, decibel_r);
+                cmt_relay_off->set_volume(0, decibel_l, decibel_r);
+        }
+#endif
 }
 #endif
 
@@ -589,29 +678,43 @@ void VM::key_up(int code)
 // user interface
 // ----------------------------------------------------------------------------
 
-void VM::open_disk(int drv, const _TCHAR* file_path, int bank)
+void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
 {
-       fdc->open_disk(drv, file_path, bank);
+       if(fdc != NULL) {
+               fdc->open_disk(drv, file_path, bank);
+       }
 }
 
-void VM::close_disk(int drv)
+void VM::close_floppy_disk(int drv)
 {
-       fdc->close_disk(drv);
+       if(fdc != NULL) {
+               fdc->close_disk(drv);
+       }
 }
 
-bool VM::disk_inserted(int drv)
+bool VM::is_floppy_disk_inserted(int drv)
 {
-       return fdc->disk_inserted(drv);
+       if(fdc != NULL) {
+               return fdc->is_disk_inserted(drv);
+       } else {
+               return false;
+       }
 }
 
-void VM::set_disk_protected(int drv, bool value)
+void VM::is_floppy_disk_protected(int drv, bool value)
 {
-       fdc->set_disk_protected(drv, value);
+       if(fdc != NULL) {
+               fdc->is_disk_protected(drv, value);
+       }
 }
 
-bool VM::get_disk_protected(int drv)
+bool VM::is_floppy_disk_protected(int drv)
 {
-       return fdc->get_disk_protected(drv);
+       if(fdc != NULL) {
+               return fdc->is_disk_protected(drv);
+       } else {
+               return false;
+       }
 }
 
 void VM::play_tape(const _TCHAR* file_path)
@@ -629,24 +732,24 @@ void VM::close_tape()
        drec->close_tape();
 }
 
-bool VM::tape_inserted()
+bool VM::is_tape_inserted()
 {
-       return drec->tape_inserted();
+       return drec->is_tape_inserted();
 }
 
-bool VM::tape_playing()
+bool VM::is_tape_playing()
 {
-       return drec->tape_playing();
+       return drec->is_tape_playing();
 }
 
-bool VM::tape_recording()
+bool VM::is_tape_recording()
 {
-       return drec->tape_recording();
+       return drec->is_tape_recording();
 }
 
-int VM::tape_position()
+int VM::get_tape_position()
 {
-       return drec->tape_position();
+       return drec->get_tape_position();
 }
 
 void VM::push_play()
@@ -683,9 +786,9 @@ void VM::push_apss_rewind()
        drec->do_apss(-1);
 }
 
-bool VM::now_skip()
+bool VM::is_frame_skippable()
 {
-       return event->now_skip();
+       return event->is_frame_skippable();
 }
 
 void VM::update_dipswitch()
@@ -695,41 +798,75 @@ void VM::update_dipswitch()
   //   io->set_iovalue_single_r(0x1ff0, (config.monitor_type & 1) | ((config.drive_type & 1) << 2));
 }
 
-void VM::set_cpu_clock(DEVICE *cpu, uint32 clocks) {
+void VM::set_cpu_clock(DEVICE *cpu, uint32_t clocks) {
        event->set_secondary_cpu_clock(cpu, clocks);
 }
 
-#define STATE_VERSION  2
+#if defined(USE_BUBBLE1)
+void VM::open_bubble_casette(int drv, _TCHAR *path, int bank)
+{
+       if((drv >= 2) || (drv < 0)) return;
+       if(bubble_casette[drv] == NULL) return;
+       bubble_casette[drv]->open(path, bank);
+}
+
+void VM::close_bubble_casette(int drv)
+{
+       if((drv >= 2) || (drv < 0)) return;
+       if(bubble_casette[drv] == NULL) return;
+       bubble_casette[drv]->close();
+}
+
+bool VM::is_bubble_casette_inserted(int drv)
+{
+       if((drv >= 2) || (drv < 0)) return false;
+       if(bubble_casette[drv] == NULL) return false;
+       return bubble_casette[drv]->is_bubble_inserted();
+}
+
+bool VM::is_bubble_casette_protected(int drv)
+{
+       if((drv >= 2) || (drv < 0)) return false;
+       if(bubble_casette[drv] == NULL) return false;
+       return bubble_casette[drv]->is_bubble_protected();
+}
+
+void VM::is_bubble_casette_protected(int drv, bool flag)
+{
+       if((drv >= 2) || (drv < 0)) return;
+       if(bubble_casette[drv] == NULL) return;
+       bubble_casette[drv]->set_bubble_protect(flag);
+}
+#endif
+
+
+#define STATE_VERSION  4
 void VM::save_state(FILEIO* state_fio)
 {
        state_fio->FputUint32_BE(STATE_VERSION);
-       
+       state_fio->FputBool(connect_320kfdc);
+       state_fio->FputBool(connect_1Mfdc);
        for(DEVICE* device = first_device; device; device = device->next_device) {
                device->save_state(state_fio);
        }
-       { // V1
-               state_fio->FputBool(clock_low);
-       }
 }
 
 bool VM::load_state(FILEIO* state_fio)
 {
-       uint32 version = state_fio->FgetUint32_BE();
+       uint32_t version = state_fio->FgetUint32_BE();
        int i = 1;
-       if(version > STATE_VERSION) {
+       if(version != STATE_VERSION) {
                return false;
        }
+       connect_320kfdc = state_fio->FgetBool();
+       connect_1Mfdc = state_fio->FgetBool();
        for(DEVICE* device = first_device; device; device = device->next_device) {
                if(!device->load_state(state_fio)) {
                        printf("Load Error: DEVID=%d\n", device->this_device_id);
                        return false;
                }
        }
-       if(version >= 1) {// V1 
-               clock_low   = state_fio->FgetBool();
-               if(version == 2) return true;
-       }
-       return false;
+       return true;
 }
 
 #ifdef USE_DIG_RESOLUTION
@@ -759,7 +896,7 @@ void VM::get_screen_resolution(int *w, int *h)
 }
 #endif
 
-bool VM::screen_changed()
+bool VM::is_screen_changed()
 {
        bool f = true;
 #if defined(USE_MINIMUM_RENDERING)