OSDN Git Service

[VM] Add vm_template.h . This class, VM_TEMPLATE:: must be mother of VM:: .See fm7...
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / fm7_mainio.cpp
index bc6a9c0..63c71fd 100644 (file)
 #include "../z80.h"
 
 #include "../datarec.h"
+#include "../i8251.h"
 #if defined(HAS_DMA)
 #include "hd6844.h"
 #endif
-#if defined(_FM8)
-#include "bubblecasette.h"
+# if defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
+#include "../and.h"
 #endif
+#include "./fm7_mainmem.h"
+#include "./fm7_display.h"
+#include "./fm7_keyboard.h"
+#include "./kanjirom.h"
+#include "./joystick.h"
+#if defined(CAPABLE_JCOMMCARD)
+#include "./jcommcard.h"
+#endif
+#include "../../statesub.h"
 
-FM7_MAINIO::FM7_MAINIO(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
+FM7_MAINIO::FM7_MAINIO(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
 {
        int i;
-       p_vm = parent_vm;
-       p_emu = parent_emu;
-#if defined(_FM8)
-       opn[0] = NULL;
-#else
-       for(i = 0; i < 4; i++) {
+       for(i = 0; i < 3; i++) {
                opn[i] = NULL;
        }
+       for(i = 0; i < 3; i++) {
+               uart[i] = NULL;
+               uart_enabled[i] = false;
+       }
+# if defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
+       rs232c_enabled = false;
+       rs232c_dtr = NULL;
+# else
+       rs232c_enabled = true;
+       rs232c_dcd = false;
+# endif
+# if !defined(_FM77AV_VARIANTS)
+       psg = NULL;
 #endif
+
        drec = NULL;
        pcm1bit = NULL;
        joystick = NULL;
        fdc = NULL;
+# if defined(HAS_2HD)
+       fdc_2HD = NULL;
+       event_2hd_nmi = -1;
+       nmi_delay = 300;
+# endif
        printer = NULL;
        
        kanjiclass1 = NULL;
@@ -51,10 +75,9 @@ FM7_MAINIO::FM7_MAINIO(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, paren
 #ifdef WITH_Z80
        z80 = NULL;
 #endif 
-#if defined(_FM8)
-       bubble_casette[0] = NULL;
-       bubble_casette[1] = NULL;
-#endif 
+#if defined(CAPABLE_JCOMMCARD)
+       jcommcard = NULL;
+#endif
        // FD00
        clock_fast = true;
        lpt_strobe = false;  // bit6
@@ -73,16 +96,18 @@ FM7_MAINIO::FM7_MAINIO(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, paren
 #elif defined(_FM77_VARIANTS)
        stat_fdmode_2hd = false; //  R/W : bit6, '0' = 2HD, '1' = 2DD. FM-77 Only.
        stat_kanjirom = true;    //  R/W : bit5, '0' = sub, '1' = main. FM-77 Only.
-       stat_400linecard = false;//  R/W : bit4, '0' = connected. FM-77 Only.
 #endif 
        firq_break_key = false; // bit1, ON = '0'.
        firq_sub_attention = false; // bit0, ON = '0'.
        intmode_fdc = false; // bit2, '0' = normal, '1' = SFD.
+#if defined(HAS_2HD)   
+       drqstat_fdc_2hd = false;
+       irqstat_fdc_2hd = false;
+#endif
        // FD05
        extdet_neg = false;
-#ifdef WITH_Z80
-       z80_sel = false;    // bit0 : '1' = Z80. Maybe only FM-7/77.
-#endif
+       req_z80run = false;
+       z80_run = false;
        // FD06,07
        intstat_syndet = false;
        intstat_rxrdy = false;
@@ -94,14 +119,6 @@ FM7_MAINIO::FM7_MAINIO(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, paren
        // FD0D
        // FD0F
        // FD15/ FD46 / FD51
-#if defined(_FM8)
-       connect_psg = false;
-       {
-               opn_address[0] = 0x00;
-               opn_data[0] = 0x00;
-               opn_cmdreg[0] = 0;
-       }
-#else  
        connect_opn = false;
        connect_whg = false;
        connect_thg = false;
@@ -110,6 +127,7 @@ FM7_MAINIO::FM7_MAINIO(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, paren
                opn_address[i] = 0x00;
                opn_data[i] = 0x00;
                opn_cmdreg[i] = 0;
+               opn_prescaler_type[i] = 1;
        }
        intstat_whg = false;
        intstat_thg = false;
@@ -117,7 +135,6 @@ FM7_MAINIO::FM7_MAINIO(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, paren
        intstat_opn = false;
        intstat_mouse = false;
        mouse_enable = false;
-#endif 
        // FD18-FD1F
        connect_fdc = false;
        fdc_statreg = 0x00;
@@ -159,12 +176,20 @@ FM7_MAINIO::FM7_MAINIO(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, paren
 #if defined(HAS_DMA)
        dmac = NULL;
 #endif 
+#if defined(_FM77_VARIANTS) || defined(_FM8)
+       bootmode = config.boot_mode & 7;
+#else
        bootmode = config.boot_mode & 3;
+#endif
        memset(io_w_latch, 0xff, 0x100);
        initialize_output_signals(&clock_status);
        initialize_output_signals(&printer_reset_bus);
        initialize_output_signals(&printer_strobe_bus);
        initialize_output_signals(&printer_select_bus);
+       initialize_output_signals(&irq_bus);
+       initialize_output_signals(&firq_bus);
+       initialize_output_signals(&nmi_bus);
+       
        set_device_name(_T("MAIN I/O"));
 }
 
@@ -179,25 +204,31 @@ void FM7_MAINIO::initialize()
        event_beep_oneshot = -1;
        event_timerirq = -1;
        event_fdc_motor = -1;
-       lpt_type = config.printer_device_type;
+       lpt_type = config.printer_type;
        fdc_cmdreg = 0x00;
-       
+#if defined(HAS_2HD)
+       event_fdc_motor_2HD = -1;
+#endif
 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
        boot_ram = false;
 # if defined(_FM77_VARIANTS)
        stat_fdmode_2hd = false;
        stat_kanjirom = true;
-       stat_400linecard = false;
-#  if defined(_FM77L4)
-       stat_400linecard = true;
-#  endif       
 # endif        
 #endif
 #if defined(_FM77AV_VARIANTS)
        reg_fd12 = 0xbc; // 0b10111100
 #endif         
+#if defined(_FM77_VARIANTS) || defined(_FM8)
+       bootmode = config.boot_mode & 7;
+#else
        bootmode = config.boot_mode & 3;
-       reset_printer();
+#endif
+#if defined(HAS_2HD)
+       event_2hd_nmi = -1;
+       nmi_delay = 300;
+#endif
+       //reset_printer();
 }
 
 void FM7_MAINIO::reset()
@@ -211,6 +242,12 @@ void FM7_MAINIO::reset()
        beep_flag = false;
        register_event(this, EVENT_BEEP_CYCLE, (1000.0 * 1000.0) / (1200.0 * 2.0), true, &event_beep);
        // Sound
+#if defined(HAS_2HD)
+       drqstat_fdc_2hd = false;
+       irqstat_fdc_2hd = false;
+       if(event_2hd_nmi >= 0) cancel_event(this, event_2hd_nmi);
+       event_2hd_nmi = -1;
+#endif
 #if defined(_FM77AV_VARIANTS)
        hotreset = false;
 #endif
@@ -225,14 +262,23 @@ void FM7_MAINIO::reset()
        sub_halt = false; // bit6 : '1' Cancel req.
        sub_cancel_bak = sub_cancel; // bit6 : '1' Cancel req.
        sub_halt_bak = sub_halt; // bit6 : '1' Cancel req.
+       req_z80run = false; // OK?
+       z80_run = false;
+
        // FD02
        cmt_indat = true; // bit7
        cmt_invert = false; // Invert signal
        lpt_det2 = true;
        lpt_det1 = true;
-       lpt_type = config.printer_device_type;
+       lpt_type = config.printer_type;
        reset_printer();
        
+# if defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
+       rs232c_enabled = false;
+# else
+       rs232c_enabled = true;
+# endif
+
 #if defined(_FM77AV_VARIANTS)
        sub_monitor_type = 0x00;
 #endif
@@ -241,7 +287,7 @@ void FM7_MAINIO::reset()
        } else {
                clock_fast = false;
        }
-       this->write_signals(&clock_status, clock_fast ? 0xffffffff : 0);
+       write_signals(&clock_status, clock_fast ? 0xffffffff : 0);
    
        // FD03
        irqmask_syndet = true;
@@ -265,14 +311,21 @@ void FM7_MAINIO::reset()
        irqreq_txrdy = false;
        irqreq_printer = false;
        irqreq_keyboard = false;
+
+       modem_irqmask_rxrdy = modem_irqmask_txrdy = true;
+       modem_syndet = modem_rxrdy = modem_txrdy = false;
+       midi_uart_irqmask = midi_syndet = midi_rxrdy = midi_txrdy = false;
        // FD00
-       drec->write_signal(SIG_DATAREC_MIC, 0x00, 0x01);
-       drec->set_remote(false);
+       if(drec != NULL) {
+               call_write_signal(drec, SIG_DATAREC_MIC, 0x00, 0x01);
+               call_write_signal(drec, SIG_DATAREC_REMOTE, 0x00, 0x02);
+       }
        reset_fdc();
        reset_sound();
        
        // FD04
        firq_break_key = (keyboard->read_signal(SIG_FM7KEY_BREAK_KEY) != 0x00000000); // bit1, ON = '0'.
+       intmode_fdc = false;
        set_sub_attention(false);       
 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
        defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) 
@@ -280,25 +333,31 @@ void FM7_MAINIO::reset()
 #elif defined(_FM77_VARIANTS)
        stat_fdmode_2hd = false; //  R/W : bit6, '0' = 2HD, '1' = 2DD. FM-77 Only.
        stat_kanjirom = true;    //  R/W : bit5, '0' = sub, '1' = main. FM-77 Only.
-#endif 
-       maincpu->write_signal(SIG_CPU_FIRQ, 0, 1);
+#endif
+       write_signals(&firq_bus, 0);
+       
 #if defined(HAS_DMA)
        intstat_dma = false;
        dma_addr = 0;
 #endif
 #if defined(_FM77AV_VARIANTS)
        reg_fd12 = 0xbc; // 0b10111100
-#endif         
-//#if defined(_FM8)
-//     bubble_casette[0]->reset();
-//     bubble_casette[1]->reset();
-//#endif       
-
+#endif
+#if defined(WITH_Z80)
+       if(z80 != NULL) call_write_signal(z80, SIG_CPU_BUSREQ, 0xffffffff, 0xffffffff);
+#endif
+       call_write_signal(maincpu, SIG_CPU_BUSREQ, 0, 0xffffffff);
+       call_write_signal(maincpu, SIG_CPU_HALTREQ, 0, 0xffffffff);
+       do_irq();
 
-#if !defined(_FM8)
+//#if !defined(_FM8)
        register_event(this, EVENT_TIMERIRQ_ON, 10000.0 / 4.9152, true, &event_timerirq); // TIMER IRQ
-#endif
+//#endif
+#if defined(_FM77_VARIANTS) || defined(_FM8)
+       bootmode = config.boot_mode & 7;
+#else
        bootmode = config.boot_mode & 3;
+#endif
        memset(io_w_latch, 0xff, 0x100);
 }
 
@@ -308,9 +367,9 @@ void FM7_MAINIO::reset_printer()
        lpt_strobe = false;
        // FD01
        lpt_outdata = 0x00;
-       this->write_signals(&printer_strobe_bus, 0);
-       this->write_signals(&printer_select_bus, 0xffffffff);
-       this->write_signals(&printer_reset_bus, 0xffffffff);
+       write_signals(&printer_strobe_bus, 0);
+       write_signals(&printer_select_bus, 0xffffffff);
+       write_signals(&printer_reset_bus, 0xffffffff);
        register_event(this, EVENT_PRINTER_RESET_COMPLETED, 5.0 * 1000.0, false, NULL);
        if(lpt_type == 0) {
                printer->write_signal(SIG_PRINTER_STROBE, 0x00, 0xff);
@@ -331,7 +390,7 @@ void FM7_MAINIO::set_clockmode(uint8_t flags)
                clock_fast = true;
        }
        if(f != clock_fast) {
-               this->write_signal(FM7_MAINIO_CLOCKMODE, clock_fast ? 1 : 0, 1);
+               write_signal(FM7_MAINIO_CLOCKMODE, clock_fast ? 1 : 0, 1);
        }
 }
 
@@ -345,23 +404,21 @@ uint8_t FM7_MAINIO::get_clockmode(void)
 uint8_t FM7_MAINIO::get_port_fd00(void)
 {
        uint8_t ret           = 0x7e; //0b01111110;
-#if defined(_FM8)
-       ret = 0xfe;
-#else  
        if(keyboard->read_data8(0x00) != 0) ret |= 0x80; // High bit.
-#endif 
        if(clock_fast) ret |= 0x01; //0b00000001;
        return ret;
 }
   
 void FM7_MAINIO::set_port_fd00(uint8_t data)
 {
-       drec->write_signal(SIG_DATAREC_MIC, data, 0x01);
-       drec->set_remote(((data & 0x02) != 0));
+       if(drec != NULL) {
+               call_write_signal(drec, SIG_DATAREC_MIC, data, 0x01);
+               call_write_signal(drec, SIG_DATAREC_REMOTE, data, 0x02);
+       }       
        lpt_slctin = ((data & 0x80) == 0);
        lpt_strobe = ((data & 0x40) != 0);
-       this->write_signals(&printer_strobe_bus, lpt_strobe ? 0xffffffff : 0);
-       this->write_signals(&printer_select_bus, lpt_slctin ? 0xffffffff : 0);
+       write_signals(&printer_strobe_bus, lpt_strobe ? 0xffffffff : 0);
+       write_signals(&printer_select_bus, lpt_slctin ? 0xffffffff : 0);
        if((lpt_type == 0) && (lpt_slctin)) {
                printer->write_signal(SIG_PRINTER_STROBE, lpt_strobe ? 0xff : 0x00, 0xff);
        }
@@ -401,16 +458,16 @@ uint8_t FM7_MAINIO::get_port_fd02(void)
 
 void FM7_MAINIO::set_port_fd02(uint8_t val)
 {
-#if !defined(_FM8)     
+//#if !defined(_FM8)   
        irqmask_reg0 = val;
        bool syndetirq_bak = irqmask_syndet;
-       bool rxrdyirq_bak = irqmask_rxrdy;
-       bool txrdyirq_bak = irqmask_txrdy;
+       //bool rxrdyirq_bak = irqmask_rxrdy;
+       //bool txrdyirq_bak = irqmask_txrdy;
        
        bool keyirq_bak = irqmask_keyboard;
-       bool timerirq_bak = irqmask_timer;
-       bool printerirq_bak = irqmask_printer;
-       bool mfdirq_bak = irqmask_mfd;
+       //bool timerirq_bak = irqmask_timer;
+       //bool printerirq_bak = irqmask_printer;
+       //bool mfdirq_bak = irqmask_mfd;
        
        //      if((val & 0b00010000) != 0) {
        if((val & 0x80) != 0) {
@@ -468,28 +525,24 @@ void FM7_MAINIO::set_port_fd02(uint8_t val)
                irqmask_keyboard = true;
        }
        if(keyirq_bak != irqmask_keyboard) {
-               display->write_signal(SIG_FM7_SUB_KEY_MASK, irqmask_keyboard ? 1 : 0, 1); 
+               call_write_signal(display, SIG_FM7_SUB_KEY_MASK, irqmask_keyboard ? 1 : 0, 1); 
                set_irq_keyboard(irqreq_keyboard);
        }
-#endif 
-       return;
+//#endif       
+               return;
 }
 
 void FM7_MAINIO::set_irq_syndet(bool flag)
 {
        bool backup = intstat_syndet;
        irqreq_syndet = flag;
-#if defined(_FM8)
-       intstat_syndet = flag;
-#else  
        if(flag && !(irqmask_syndet)) {
-         //irqstat_reg0 &= ~0x80; //~0x20;
+               //irqstat_reg0 &= ~0x80; //~0x20;
                intstat_syndet = true;     
        } else {
-         //    irqstat_reg0 |= 0x80;
+               //      irqstat_reg0 |= 0x80;
                intstat_syndet = false;    
        }
-#endif 
        if(backup != intstat_syndet) do_irq();
 }
 
@@ -498,17 +551,13 @@ void FM7_MAINIO::set_irq_rxrdy(bool flag)
 {
        bool backup = intstat_rxrdy;
        irqreq_rxrdy = flag;
-#if defined(_FM8)
-       intstat_rxrdy = flag;
-#else  
        if(flag && !(irqmask_rxrdy)) {
-         //irqstat_reg0 &= ~0x40; //~0x20;
+               //irqstat_reg0 &= ~0x40; //~0x20;
                intstat_rxrdy = true;      
        } else {
-         //irqstat_reg0 |= 0x40;
+               //irqstat_reg0 |= 0x40;
                intstat_rxrdy = false;     
        }
-#endif 
        if(backup != intstat_rxrdy) do_irq();
 }
 
@@ -518,25 +567,19 @@ void FM7_MAINIO::set_irq_txrdy(bool flag)
 {
        bool backup = intstat_txrdy;
        irqreq_txrdy = flag;
-#if defined(_FM8)
-       intstat_txrdy = flag;
-#else  
        if(flag && !(irqmask_txrdy)) {
-         //irqstat_reg0 &= ~0x20; //~0x20;
+               //irqstat_reg0 &= ~0x20; //~0x20;
                intstat_txrdy = true;      
        } else {
-         //irqstat_reg0 |= 0x20;
+               //irqstat_reg0 |= 0x20;
                intstat_txrdy = false;     
        }
-#endif 
        if(backup != intstat_txrdy) do_irq();
 }
 
 
 void FM7_MAINIO::set_irq_timer(bool flag)
 {
-#if !defined(_FM8)
-       bool backup = irqstat_timer;
        if(flag) {
                irqstat_reg0 &= 0xfb; //~0x04;
                irqstat_timer = true;      
@@ -544,15 +587,11 @@ void FM7_MAINIO::set_irq_timer(bool flag)
                irqstat_reg0 |= 0x04;
                irqstat_timer = false;     
        }
-       //if(backup != irqstat_timer) do_irq();
        do_irq();
-#endif 
 }
 
 void FM7_MAINIO::set_irq_printer(bool flag)
 {
-#if !defined(_FM8)
-       uint8_t backup = irqstat_reg0;
        irqreq_printer = flag;
        if(flag && !(irqmask_printer)) {
                irqstat_reg0 &= ~0x02;
@@ -562,7 +601,6 @@ void FM7_MAINIO::set_irq_printer(bool flag)
                irqstat_printer = false;           
        }
        do_irq();
-#endif 
 }
 
 void FM7_MAINIO::set_irq_keyboard(bool flag)
@@ -584,41 +622,48 @@ void FM7_MAINIO::set_irq_keyboard(bool flag)
 void FM7_MAINIO::do_irq(void)
 {
        bool intstat;
-#if defined(_FM8)
-       intstat = intstat_txrdy | intstat_rxrdy | intstat_syndet;
-#else  
+       uint32_t nval;
+       
        intstat = irqstat_timer | irqstat_keyboard | irqstat_printer;
-       intstat = intstat | irqstat_fdc;
        intstat = intstat | intstat_opn | intstat_whg | intstat_thg;
        intstat = intstat | intstat_txrdy | intstat_rxrdy | intstat_syndet;
        intstat = intstat | intstat_mouse;
+       intstat = intstat | ((modem_irqmask_txrdy & modem_txrdy) | (modem_irqmask_rxrdy & modem_rxrdy) | modem_syndet);
+       intstat = intstat | ((!midi_uart_irqmask) & (midi_syndet | midi_txrdy | midi_rxrdy));
 # if defined(HAS_DMA)
        intstat = intstat | intstat_dma;
 # endif
-#endif 
-       //printf("%08d : IRQ: REG0=%02x FDC=%02x, stat=%d\n", SDL_GetTicks(), irqstat_reg0, irqstat_fdc, intstat);
-       if(intstat) {
-               maincpu->write_signal(SIG_CPU_IRQ, 1, 1);
+# if defined(HAS_2HD)
+       if(intmode_fdc) {
+               intstat = intstat | irqstat_fdc_2hd;
        } else {
-               maincpu->write_signal(SIG_CPU_IRQ, 0, 1);
+               intstat = intstat | irqstat_fdc;
        }
+# else
+       intstat = intstat | irqstat_fdc;
+#endif
+       nval = (intstat) ? 0xffffffff : 0;
+       write_signals(&irq_bus, nval);
 }
 
 void FM7_MAINIO::do_firq(void)
 {
        bool firq_stat;
+       uint32_t nval;
        firq_stat = firq_break_key | firq_sub_attention;
-       if(firq_stat) {
-               maincpu->write_signal(SIG_CPU_FIRQ, 1, 1);
-       } else {
-               maincpu->write_signal(SIG_CPU_FIRQ, 0, 1);
+#if defined(HAS_2HD)
+       if(intmode_fdc) {
+               firq_stat = drqstat_fdc_2hd;  // 20180226 BREAK KEY AND ATTENTION MUST BE MASK IF FIRQ USING FOR FDC's DRQ.Thanks to Haserin.
+                       //}
        }
-       //this->out_debug_log(_T("IO: do_firq(). BREAK=%d ATTN=%d"), firq_break_key ? 1 : 0, firq_sub_attention ? 1 : 0);
+#endif
+       nval = (firq_stat) ? 0xffffffff : 0;
+       write_signals(&firq_bus, nval);
 }
 
 void FM7_MAINIO::do_nmi(bool flag)
 {
-       maincpu->write_signal(SIG_CPU_NMI, flag ? 1 : 0, 1);
+       write_signals(&nmi_bus, (flag) ? 0xffffffff : 0);
 }
 
 
@@ -648,17 +693,34 @@ uint8_t FM7_MAINIO::get_fd04(void)
                val |= 0x01;
        }
 #if defined(_FM77_VARIANTS)
-       if(stat_fdmode_2hd) val |= 0x40;
-       if(stat_kanjirom)   val |= 0x20;
-       if(stat_400linecard) val |= 0x10;
-       if((display->read_signal(SIG_DISPLAY_EXTRA_MODE) & 0x04) != 0x00) val |= 0x04;
+       if(!stat_fdmode_2hd)  val |= 0x40;
+       if(stat_kanjirom)     val |= 0x20;
+       //if(intmode_fdc)      val |= 0x04;  // OK?
+       val |= 0x04;
+# if defined(_FM77L4)
+       val |= (display->read_signal(SIG_DISPLAY_EXTRA_MODE) & 0x18);
+# else
+       val |= 0x18; // For NON-77L4, these bit must be '1'.Thanks to Ryu Takegami.
+# endif
+#elif defined(_FM8)
+       val |= 0x78;
+       // ToDo: MEMORY PARITY ERRO STATUS (if error, bit3 = '1').
+#elif defined(_FM77AV_VARIANTS)
+       val |= 0x6c;
+       val |= 0x10; // ToDo: Hack for OS-9 for 77AV.Really need?
 #else
        val |= 0x7c;
 #endif 
+#if defined(HAS_2HD)
+       if(drqstat_fdc_2hd) {
+               drqstat_fdc_2hd = false;
+               if(!firq_sub_attention) do_firq();
+       }
+#endif
        if(firq_sub_attention) {
                set_sub_attention(false);
                //printf("Attention \n");
-       }
+       } 
 #if defined(_FM77AV_VARIANTS)
        if(hotreset) {
                if(mainmem->read_signal(FM7_MAINIO_INITROM_ENABLED) == 0) {
@@ -674,18 +736,24 @@ void FM7_MAINIO::set_fd04(uint8_t val)
 {
        // NOOP?
 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       display->write_signal(SIG_DISPLAY_EXTRA_MODE, val, 0xff);
+       call_write_signal(display, SIG_DISPLAY_EXTRA_MODE, val, 0xff);
        stat_kanjirom = ((val & 0x20) != 0);
 #elif defined(_FM77_VARIANTS)
-       display->write_signal(SIG_DISPLAY_EXTRA_MODE, val, 0xff);
-       stat_fdmode_2hd  = ((val & 0x40) != 0);
+       call_write_signal(display, SIG_DISPLAY_EXTRA_MODE, val, 0xff);
        stat_kanjirom    = ((val & 0x20) != 0);
-       stat_400linecard = ((val & 0x10) != 0);
+#endif
+#if defined(HAS_2HD)
+       stat_fdmode_2hd  = ((val & 0x40) == 0);
+       intmode_fdc      = ((val & 0x04) == 0); // I/O port definition at Oh!FM 1985-5? is inverted status.
+       bool tmpf        = intmode_fdc;
+       if(tmpf != intmode_fdc) {
+               do_firq();
+       }
 #endif 
 }
 
-  // FD05
- uint8_t FM7_MAINIO::get_fd05(void)
+// FD05
+uint8_t FM7_MAINIO::get_fd05(void)
 {
        uint8_t val = 0x7e;
        if(display->read_signal(SIG_DISPLAY_BUSY) != 0) val |= 0x80;
@@ -693,26 +761,26 @@ void FM7_MAINIO::set_fd04(uint8_t val)
        return val;
 }
 
- void FM7_MAINIO::set_fd05(uint8_t val)
+void FM7_MAINIO::set_fd05(uint8_t val)
 {
        sub_cancel = ((val & 0x40) != 0) ? true : false;
        sub_halt   = ((val & 0x80) != 0) ? true : false;
        //if(sub_halt != sub_halt_bak) {
-               display->write_signal(SIG_DISPLAY_HALT,  (sub_halt) ? 0xff : 0x00, 0xff);
+       call_write_signal(display, SIG_DISPLAY_HALT,  (sub_halt) ? 0xff : 0x00, 0xff);
        //}
        sub_halt_bak = sub_halt;
 
        //if(sub_cancel != sub_cancel_bak) {
-               display->write_signal(SIG_FM7_SUB_CANCEL, (sub_cancel) ? 0xff : 0x00, 0xff); // HACK
+       call_write_signal(display, SIG_FM7_SUB_CANCEL, (sub_cancel) ? 0xff : 0x00, 0xff); // HACK
        //}
        sub_cancel_bak = sub_cancel;
 #ifdef WITH_Z80
        if((val & 0x01) != 0) {
-               maincpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
-               z80->write_signal(SIG_CPU_BUSREQ, 0, 1);
+               call_write_signal(maincpu, SIG_CPU_HALTREQ, 1, 1);
+               req_z80run = true;
        } else {
-               maincpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
-               z80->write_signal(SIG_CPU_BUSREQ, 1, 1);
+               req_z80run = false;
+               if(z80 != NULL) call_write_signal(z80, SIG_CPU_BUSREQ, 1, 1);
        }
 #endif
 }
@@ -724,27 +792,12 @@ void FM7_MAINIO::set_extdet(bool flag)
 
 void FM7_MAINIO::write_fd0f(void)
 {
-#if defined(_FM8)
-       if((config.dipswitch & FM7_DIPSW_FM8_PROTECT_FD0F) != 0) {
-               return;
-       }
-       bootmode = 1; // DOS : Where BUBBLE?
-       mainmem->write_signal(FM7_MAINIO_BOOTMODE, bootmode, 0xffffffff);
-       mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0, 0xffffffff);
-#endif 
-       mainmem->write_signal(FM7_MAINIO_PUSH_FD0F, 0, 0xffffffff);
+       call_write_signal(mainmem, FM7_MAINIO_PUSH_FD0F, 0, 0xffffffff);
 }
+
 uint8_t FM7_MAINIO::read_fd0f(void)
 {
-#if defined(_FM8)
-       if((config.dipswitch & FM7_DIPSW_FM8_PROTECT_FD0F) != 0) {
-               return 0xff;
-       }
-       bootmode = 0; // BASIC
-       mainmem->write_signal(FM7_MAINIO_BOOTMODE, bootmode, 0xffffffff);
-       mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0xffffffff, 0xffffffff);
-#endif 
-       mainmem->write_signal(FM7_MAINIO_PUSH_FD0F, 0xffffffff, 0xffffffff);
+       call_write_signal(mainmem, FM7_MAINIO_PUSH_FD0F, 0xffffffff, 0xffffffff);
        return 0xff;
 }
 
@@ -757,7 +810,15 @@ bool FM7_MAINIO::get_rommode_fd0f(void)
 // Kanji ROM, FD20 AND FD21 (or SUBSYSTEM)
 void FM7_MAINIO::write_kanjiaddr_hi(uint8_t addr)
 {
-       if(!connect_kanjiroml1) return;
+#if defined(CAPABLE_JCOMMCARD) && !(defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS))
+       if(jcommcard != NULL) {
+               jcommcard->write_io8(0, (uint32_t)addr);
+               return;
+       }
+#endif
+       if(!connect_kanjiroml1) {
+               return;
+       }
 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
        if(!stat_kanjirom) return;
@@ -768,7 +829,15 @@ void FM7_MAINIO::write_kanjiaddr_hi(uint8_t addr)
 
 void FM7_MAINIO::write_kanjiaddr_lo(uint8_t addr)
 {
-       if(!connect_kanjiroml1) return;
+#if defined(CAPABLE_JCOMMCARD) && !(defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS))
+       if(jcommcard != NULL) {
+               jcommcard->write_io8(1, (uint32_t)addr);
+               return;
+       }
+#endif
+       if(!connect_kanjiroml1) {
+               return;
+       }
 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
        if(!stat_kanjirom) return;
@@ -779,7 +848,14 @@ void FM7_MAINIO::write_kanjiaddr_lo(uint8_t addr)
 
 uint8_t FM7_MAINIO::read_kanjidata_left(void)
 {
-       if(!connect_kanjiroml1) return 0xff;
+#if defined(CAPABLE_JCOMMCARD) && !(defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS))
+       if(jcommcard != NULL) {
+               return (uint8_t)(jcommcard->read_io8(2));
+       }
+#endif
+       if(!connect_kanjiroml1) {
+               return 0xff;
+       }
 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
        if(!stat_kanjirom) return 0xff;
@@ -794,7 +870,14 @@ uint8_t FM7_MAINIO::read_kanjidata_left(void)
 
 uint8_t FM7_MAINIO::read_kanjidata_right(void)
 {
-       if(!connect_kanjiroml1) return 0xff;
+#if defined(CAPABLE_JCOMMCARD) && !(defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS))
+       if(jcommcard != NULL) {
+               return (uint8_t)(jcommcard->read_io8(3));
+       }
+#endif
+       if(!connect_kanjiroml1) {
+               return 0xff;
+       }
 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
        if(!stat_kanjirom) return 0xff;
@@ -850,17 +933,16 @@ uint8_t FM7_MAINIO::read_kanjidata_right_l2(void)
 }
 #endif
 
-
 uint32_t FM7_MAINIO::read_signal(int id)
 {
        uint32_t retval;
        switch(id) {
-               case FM7_MAINIO_KEYBOARDIRQ_MASK:
-                       retval = (irqmask_keyboard) ? 0xffffffff : 0x00000000;
-                       break;
-               default:
-                       retval = 0xffffffff;
-                       break;
+       case FM7_MAINIO_KEYBOARDIRQ_MASK:
+               retval = (irqmask_keyboard) ? 0xffffffff : 0x00000000;
+               break;
+       default:
+               retval = 0xffffffff;
+               break;
        }
        return retval;
 }
@@ -872,138 +954,209 @@ void FM7_MAINIO::write_signal(int id, uint32_t data, uint32_t mask)
        val_b = ((data & mask) != 0);
   
        switch(id) {
-         //case SIG_FM7_SUB_HALT:
-         //    mainmem->write_signal(SIG_FM7_SUB_HALT, data, mask);
-         //            break;
-               case FM7_MAINIO_CLOCKMODE: // fd00
-                       if(val_b) {
-                               clock_fast = true;
-                       } else {
-                               clock_fast = false;
-                       }
-                       this->write_signals(&clock_status, clock_fast ? 0xffffffff : 0);
-                       break;
-               case FM7_MAINIO_CMT_RECV: // FD02
-                       cmt_indat = val_b ^ cmt_invert;
-                       break;
-               case FM7_MAINIO_CMT_INVERT: // FD02
-                       cmt_invert = val_b;
-                       break;
-               case FM7_MAINIO_TIMERIRQ: //
-                       set_irq_timer(val_b);
-                       break;
-               case FM7_MAINIO_LPTIRQ: //
-                       set_irq_printer(val_b);
-                       break;
-               case FM7_MAINIO_LPT_BUSY:
-                       lpt_busy = val_b;
-                       break;
-               case FM7_MAINIO_LPT_ERROR:
-                       lpt_error_inv = val_b;
-                       break;
-               case FM7_MAINIO_LPT_ACK:
-                       {
-                               bool f = lpt_ackng_inv;
-                               lpt_ackng_inv = val_b;
-                               if((lpt_ackng_inv == true) && (f == false)) set_irq_printer(true);
-                       }
-                       break;
-               case FM7_MAINIO_LPT_PAPER_EMPTY:
-                       lpt_busy = val_b;
-                       break;
-               case FM7_MAINIO_LPT_DET1:
-                       lpt_det1 = val_b;
-                       break;
-               case FM7_MAINIO_LPT_DET2:
-                       lpt_det2 = val_b;
-                       break;
-               case FM7_MAINIO_KEYBOARDIRQ: //
-                       set_irq_keyboard(val_b);
-                       break;
-                       // FD04
-               case FM7_MAINIO_PUSH_BREAK:
-                       set_break_key(val_b);
-                       break;
+               //case SIG_FM7_SUB_HALT:
+               //      mainmem->write_signal(SIG_FM7_SUB_HALT, data, mask);
+               //              break;
+       case FM7_MAINIO_CLOCKMODE: // fd00
+               if(val_b) {
+                       clock_fast = true;
+               } else {
+                       clock_fast = false;
+               }
+               write_signals(&clock_status, clock_fast ? 0xffffffff : 0);
+               break;
+       case FM7_MAINIO_CMT_RECV: // FD02
+               cmt_indat = val_b ^ cmt_invert;
+               break;
+       case FM7_MAINIO_CMT_INVERT: // FD02
+               cmt_invert = val_b;
+               break;
+       case FM7_MAINIO_TIMERIRQ: //
+               set_irq_timer(val_b);
+               break;
+       case FM7_MAINIO_LPTIRQ: //
+               set_irq_printer(val_b);
+               break;
+       case FM7_MAINIO_LPT_BUSY:
+               lpt_busy = val_b;
+               break;
+       case FM7_MAINIO_LPT_ERROR:
+               lpt_error_inv = val_b;
+               break;
+       case FM7_MAINIO_LPT_ACK:
+               {
+                       bool f = lpt_ackng_inv;
+                       lpt_ackng_inv = val_b;
+                       if((lpt_ackng_inv == true) && (f == false)) set_irq_printer(true);
+               }
+               break;
+       case FM7_MAINIO_LPT_PAPER_EMPTY:
+               lpt_busy = val_b;
+               break;
+       case FM7_MAINIO_LPT_DET1:
+               lpt_det1 = val_b;
+               break;
+       case FM7_MAINIO_LPT_DET2:
+               lpt_det2 = val_b;
+               break;
+       case FM7_MAINIO_KEYBOARDIRQ: //
+               set_irq_keyboard(val_b);
+               break;
+               // FD04
+       case FM7_MAINIO_PUSH_BREAK:
+               set_break_key(val_b);
+               break;
 #if defined(FM77AV_VARIANTS)   
-               case FM7_MAINIO_HOT_RESET:
-                       hotreset = val_b;
-                       break;
+       case FM7_MAINIO_HOT_RESET:
+               hotreset = val_b;
+               break;
+#endif
+       case FM7_MAINIO_SUB_ATTENTION:
+               if(val_b) set_sub_attention(true);
+               break;
+               // FD05
+       case FM7_MAINIO_EXTDET:
+               extdet_neg = !val_b;
+               break;
+       case FM7_MAINIO_BEEP:
+               set_beep_oneshot();
+               break;
+       case FM7_MAINIO_PSG_IRQ:
+               break;
+#if defined(WITH_Z80)
+       case FM7_MAINIO_RUN_Z80:
+               if((req_z80run)/*  && (val_b) */) {
+                       if(z80 != NULL) call_write_signal(z80, SIG_CPU_BUSREQ, 0, 1);
+                       z80_run = true;
+                       //z80->reset(); // OK?
+               }
+               break;
+       case FM7_MAINIO_RUN_6809:
+               if(!(req_z80run) /* && (val_b) */ && (z80_run)) {
+                       z80_run = false;
+                       // Wait dead cycle?
+                       call_write_signal(maincpu, SIG_CPU_HALTREQ, 0, 1);
+               }
+               break;
+#endif
+       case FM7_MAINIO_UART0_RXRDY:
+               set_irq_rxrdy(val_b & rs232c_enabled);
+               break;
+       case FM7_MAINIO_UART0_TXRDY:
+               set_irq_txrdy(val_b & rs232c_enabled);
+               break;
+       case FM7_MAINIO_UART0_SYNDET:
+               set_irq_syndet(val_b & rs232c_enabled);
+               break;
+       case FM7_MAINIO_UART0_DCD:
+               rs232c_dcd = val_b;
+               break;
+       case FM7_MAINIO_MODEM_TXRDY:
+               modem_txrdy = val_b;
+               do_irq();
+               break;
+       case FM7_MAINIO_MODEM_RXRDY:
+               modem_rxrdy = val_b;
+               do_irq();
+               break;
+       case FM7_MAINIO_MODEM_SYNDET:
+               modem_syndet = val_b;
+               do_irq();
+               break;
+       case FM7_MAINIO_MIDI_TXRDY:
+               midi_txrdy = val_b;
+               do_irq();
+               break;
+       case FM7_MAINIO_MIDI_RXRDY:
+               midi_rxrdy = val_b;
+               do_irq();
+               break;
+       case FM7_MAINIO_MIDI_SYNDET:
+               midi_syndet = val_b;
+               do_irq();
+               break;
+                       
+//#if !defined(_FM8)                   
+       case FM7_MAINIO_OPN_IRQ:
+               if(!connect_opn) break;
+               intstat_opn = val_b;
+               do_irq();
+               break;
+       case FM7_MAINIO_WHG_IRQ:
+               if(!connect_whg) break;
+               intstat_whg = val_b;
+               do_irq();
+               break;
+       case FM7_MAINIO_THG_IRQ:
+               if(!connect_thg) break;
+               intstat_thg = val_b;
+               do_irq();
+               break;
+//#endif                       
+       case FM7_MAINIO_FDC_DRQ:
+               set_drq_mfd(val_b);
+               break;
+       case FM7_MAINIO_FDC_IRQ:
+               set_irq_mfd(val_b);
+               break;
+#if defined(HAS_2HD)
+       case FM7_MAINIO_FDC_DRQ_2HD:
+               set_drq_mfd_2HD(val_b);
+               break;
+       case FM7_MAINIO_FDC_IRQ_2HD:
+               set_irq_mfd_2HD(val_b);
+               break;
 #endif
-               case FM7_MAINIO_SUB_ATTENTION:
-                       if(val_b) set_sub_attention(true);
-                       break;
-                       // FD05
-               case FM7_MAINIO_EXTDET:
-                       extdet_neg = !val_b;
-                       break;
-               case FM7_MAINIO_BEEP:
-                       set_beep_oneshot();
-                       break;
-               case FM7_MAINIO_PSG_IRQ:
-                       break;
-#if !defined(_FM8)                     
-               case FM7_MAINIO_OPN_IRQ:
-                       if(!connect_opn) break;
-                       intstat_opn = val_b;
-                       do_irq();
-                       break;
-               case FM7_MAINIO_WHG_IRQ:
-                       if(!connect_whg) break;
-                       intstat_whg = val_b;
-                       do_irq();
-                       break;
-               case FM7_MAINIO_THG_IRQ:
-                       if(!connect_thg) break;
-                       intstat_thg = val_b;
-                       do_irq();
-                       break;
-#endif                 
-               case FM7_MAINIO_FDC_DRQ:
-                       set_drq_mfd(val_b);
-                       break;
-               case FM7_MAINIO_FDC_IRQ:
-                       set_irq_mfd(val_b);
-                       break;
 #if defined(HAS_DMA)
-               case FM7_MAINIO_DMA_INT:
-                       intstat_dma = val_b;
-                       do_irq();
-                       break;
+       case FM7_MAINIO_DMA_INT:
+               intstat_dma = val_b;
+               do_irq();
+               break;
 #endif
 #if defined(_FM77AV_VARIANTS)
-               case SIG_DISPLAY_DISPLAY:
-                       if(val_b) {
-                               reg_fd12 |= 0x02;
-                       } else {
-                               reg_fd12 &= ~0x02;
-                       }
-                       break;
-               case SIG_DISPLAY_VSYNC:
-                       if(val_b) {
-                               reg_fd12 |= 0x01;
-                       } else {
-                               reg_fd12 &= ~0x01;
-                       }
-                       break;
-               case SIG_DISPLAY_MODE320:
-                       if(val_b) {
-                               reg_fd12 |= 0x40;
-                       } else {
-                               reg_fd12 &= ~0x40;
-                       }
-                       break;
+       case SIG_DISPLAY_DISPLAY:
+               if(val_b) {
+                       reg_fd12 |= 0x02;
+               } else {
+                       reg_fd12 &= ~0x02;
+               }
+               break;
+       case SIG_DISPLAY_VSYNC:
+               if(val_b) {
+                       reg_fd12 |= 0x01;
+               } else {
+                       reg_fd12 &= ~0x01;
+               }
+               break;
+       case SIG_DISPLAY_MODE320:
+               if(val_b) {
+                       reg_fd12 |= 0x40;
+               } else {
+                       reg_fd12 &= ~0x40;
+               }
+               break;
 #endif                 
        }
 }
 
 
- uint8_t FM7_MAINIO::get_irqstat_fd03(void)
+uint8_t FM7_MAINIO::get_irqstat_fd03(void)
 {
        uint8_t val;
        bool extirq;
-#if !defined(_FM8)     
-       extirq = irqstat_fdc | intstat_opn | intstat_whg | intstat_thg;
+       uint8_t backup = irqstat_reg0;
+   
+       extirq = intstat_opn | intstat_whg | intstat_thg;
        extirq = extirq | intstat_syndet | intstat_rxrdy | intstat_txrdy;
+# if defined(HAS_2HD)
+       if(intmode_fdc) {
+               extirq = extirq | irqstat_fdc_2hd;
+       } else {
+               extirq = extirq | irqstat_fdc;
+       }
+# else
+       extirq = extirq | irqstat_fdc;
+# endif
 # if defined(HAS_DMA)
        extirq = extirq | intstat_dma;
 # endif   
@@ -1017,33 +1170,28 @@ void FM7_MAINIO::write_signal(int id, uint32_t data, uint32_t mask)
        irqstat_timer = false;
        irqstat_printer = false;
        irqstat_reg0 |= 0x06;
-       do_irq();
+       //if(backup != irqstat_reg0) do_irq();
        //this->out_debug_log(_T("IO: Check IRQ Status."));
+       do_irq();
        return val;
-#else
-       return 0xff;
-#endif
+
 }
 
 uint8_t FM7_MAINIO::get_extirq_fd17(void)
 {
        uint8_t val = 0xff;
-#if !defined(_FM8)     
        if(intstat_opn && connect_opn)   val &= ~0x08;
        if(intstat_mouse) val &= ~0x04;
-#endif
        return val;
 }
 
 void FM7_MAINIO::set_ext_fd17(uint8_t data)
 {
-#if !defined(_FM8)
        if((data & 0x04) != 0) {
                mouse_enable = true;
        } else {
                mouse_enable = false;
        }
-#endif
 }
 
 #if defined(_FM77AV_VARIANTS)
@@ -1091,7 +1239,7 @@ uint32_t FM7_MAINIO::read_data8(uint32_t addr)
                if((addr < 0x90) && (addr >= 0x80)) {
                        mmr_segment = mainmem->read_data8(FM7_MAINIO_MMR_SEGMENT);
 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX) || \
-     defined(_FM77AV20) || defined(_FM77AV20SX) || defined(_FM77AV20EX)
+       defined(_FM77AV20) || defined(_FM77AV20SX) || defined(_FM77AV20EX)
                        mmr_segment &= 0x07;
 # else            
                        mmr_segment &= 0x03;
@@ -1099,40 +1247,47 @@ uint32_t FM7_MAINIO::read_data8(uint32_t addr)
                        return mainmem->read_data8(addr - 0x80 + FM7_MAINIO_MMR_BANK + mmr_segment * 16);
                }
 #endif
-       //      if((addr >= 0x0006) && !(addr == 0x1f) && !(addr == 0x0b)) printf("MAINIO: READ: %08x \n", addr);
+               //      if((addr >= 0x0006) && !(addr == 0x1f) && !(addr == 0x0b)) printf("MAINIO: READ: %08x \n", addr);
                switch(addr) {
                case 0x00: // FD00
                        retval = (uint32_t) get_port_fd00();
                        break;
                case 0x01: // FD01
-#if !defined(_FM8)                     
+//#if !defined(_FM8)                   
                        retval = keyboard->read_data8(0x01) & 0xff;
-#endif                 
-                       break;
+//#endif                       
+                               break;
                case 0x02: // FD02
                        retval = (uint32_t) get_port_fd02();
                        break;
                case 0x03: // FD03
-#if !defined(_FM8)
+//#if !defined(_FM8)
                        retval = (uint32_t) get_irqstat_fd03();
-#endif                 
-                       break;
+//#endif                       
+                               break;
                case 0x04: // FD04
                        retval = (uint32_t) get_fd04();
                        break;
                case 0x05: // FD05
-                       retval = (uint32_t) get_fd05();
+                       retval = (uint32_t) get_fd05();
                        break;
                case 0x06: // RS-232C
                case 0x07:
+                       if(uart_enabled[0] && rs232c_enabled) {
+                               if(uart[0] != NULL) retval = uart[0]->read_io8(addr & 1);
+                       }
                        break;
                case 0x08: // Light pen
                case 0x09:
-               case 0x0a:
+               case 0x0a:
                        break;
 #if defined(_FM77AV_VARIANTS)
                case 0x0b:
                        retval = ((config.boot_mode & 3) == 0) ? 0xfe : 0xff;
+#if defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
+                       retval &= (uint32_t)(~0x04);
+                       if(!rs232c_dcd) retval |= 0x04;
+#endif
                        break;
 #endif                 
                case 0x0e: // PSG DATA
@@ -1143,18 +1298,6 @@ uint32_t FM7_MAINIO::read_data8(uint32_t addr)
                        read_fd0f();
                        retval = 0xff;
                        break;
-#if defined(_FM8)
-               case 0x10:
-               case 0x11:
-               case 0x12:
-               case 0x13:
-               case 0x14:
-               case 0x15:
-               case 0x16:
-               case 0x17:
-                       retval = bubble_casette[0]->read_data8(addr);
-                       break;
-#else                  
 #if defined(_FM77AV_VARIANTS)
                case 0x12:
                        retval = subsystem_read_status();  
@@ -1168,9 +1311,75 @@ uint32_t FM7_MAINIO::read_data8(uint32_t addr)
                case 0x17:
                        retval = (uint32_t) get_extirq_fd17();
                        break;
-#endif                 
+
+#if defined(HAS_2HD)
                case 0x18: // FDC: STATUS
-                       retval = (uint32_t) get_fdc_stat();
+                       if(stat_fdmode_2hd) {
+                               retval = (uint32_t) get_fdc_stat_2HD();
+                       } else {
+                               retval = (uint32_t) get_fdc_stat();
+                       }
+                   break;
+                       //printf("FDC: READ STATUS %02x PC=%04x\n", retval, maincpu->get_pc()); 
+                       break;
+               case 0x19: // FDC: Track
+                       if(stat_fdmode_2hd) {
+                               retval = (uint32_t) get_fdc_track_2HD();
+                       } else {
+                               retval = (uint32_t) get_fdc_track();
+                       }
+                       //printf("FDC: READ TRACK REG %02x\n", retval); 
+                       break;
+               case 0x1a: // FDC: Sector
+                       if(stat_fdmode_2hd) {
+                               retval = (uint32_t) get_fdc_sector_2HD();
+                       } else {
+                               retval = (uint32_t) get_fdc_sector();
+                       }
+                       //printf("FDC: READ SECTOR REG %02x\n", retval); 
+                       break;
+               case 0x1b: // FDC: Data
+                       if(stat_fdmode_2hd) {
+                               retval = (uint32_t) get_fdc_data_2HD();
+                       } else {
+                               retval = (uint32_t) get_fdc_data();
+                       }
+                       break;
+               case 0x1c:
+                       if(stat_fdmode_2hd) {
+                               retval = (uint32_t) get_fdc_fd1c_2HD();
+                       } else {
+                               retval = (uint32_t) get_fdc_fd1c();
+                       }
+                       //printf("FDC: READ HEAD REG %02x\n", retval); 
+                       break;
+               case 0x1d:
+                       if(stat_fdmode_2hd) {
+                               retval = (uint32_t) get_fdc_motor_2HD();
+                       } else {
+                               retval = (uint32_t) get_fdc_motor();
+                       }
+                       //printf("FDC: READ MOTOR REG %02x\n", retval); 
+                       break;
+               case 0x1e:
+                       if(stat_fdmode_2hd) {
+                               retval = (uint32_t) get_fdc_fd1e_2HD();
+                       } else {
+                               retval = (uint32_t) get_fdc_fd1e();
+                       }
+                       //printf("FDC: READ MOTOR REG %02x\n", retval); 
+                       break;
+               case 0x1f:
+                       if(stat_fdmode_2hd) {
+                               retval = (uint32_t) fdc_getdrqirq_2HD();
+                       } else {
+                               retval = (uint32_t) fdc_getdrqirq();
+                       }
+                       break;
+#else
+               case 0x18: // FDC: STATUS
+                       retval = (uint32_t) get_fdc_stat();
+                   break;
                        //printf("FDC: READ STATUS %02x PC=%04x\n", retval, maincpu->get_pc()); 
                        break;
                case 0x19: // FDC: Track
@@ -1199,12 +1408,27 @@ uint32_t FM7_MAINIO::read_data8(uint32_t addr)
                case 0x1f:
                        retval = (uint32_t) fdc_getdrqirq();
                        break;
+#endif
                case 0x22: // Kanji ROM
                        retval = (uint32_t) read_kanjidata_left();
                        break;
                case 0x23: // Kanji ROM
                        retval = (uint32_t) read_kanjidata_right();
                        break;
+#if defined(CAPABLE_JCOMMCARD)
+               case 0x28:
+               case 0x29:
+# if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
+               case 0x2a:
+               case 0x2b:
+# endif
+                       if(jcommcard != NULL) {
+                               retval = (uint32_t)(jcommcard->read_io8(addr));
+                       } else {
+                               retval = 0xff;
+                       }
+                       break;
+#endif                 
 #if defined(CAPABLE_KANJI_CLASS2)
                case 0x2e: // Kanji ROM Level2
                        retval = (uint32_t) read_kanjidata_left_l2();
@@ -1213,10 +1437,18 @@ uint32_t FM7_MAINIO::read_data8(uint32_t addr)
                        retval = (uint32_t) read_kanjidata_right_l2();
                        break;
 #endif
-#if !defined(_FM8)                     
+//#if !defined(_FM8)                   
                case 0x37: // Multi page
                        //retval = (uint32_t)display->read_data8(DISPLAY_ADDR_MULTIPAGE);
                        break;
+               case 0x40: // MODEM
+               case 0x41:
+                       if(uart_enabled[1]) {
+                               if(uart[1] != NULL) retval = uart[1]->read_io8(addr & 1);
+                       }
+                       break;
+               case 0x42:
+                       break;
                case 0x45: // WHG CMD
                        break;
                case 0x46: // WHG DATA
@@ -1228,12 +1460,12 @@ uint32_t FM7_MAINIO::read_data8(uint32_t addr)
                case 0x51: // THG CMD
                        break;
                case 0x52: // THG DATA
-                       retval = (uint32_t) get_opn(2);
+                       retval = (uint32_t) get_opn(2);
                        break;
                case 0x53:
                        retval = (uint32_t) get_extirq_thg();
                        break;
-#endif                 
+//#endif                       
 #if defined(HAS_MMR)
                case 0x93:
                        retval = 0x3e;
@@ -1258,17 +1490,23 @@ uint32_t FM7_MAINIO::read_data8(uint32_t addr)
                        retval = dmac->read_data8(dma_addr);
                        break;
 #endif                 
+               case 0xea: // MIDI
+               case 0xeb:
+                       if(uart_enabled[2]) {
+                               if(uart[2] != NULL) retval = uart[2]->read_io8(addr & 1);
+                       }
+                       break;
                default:
                        break;
                }
-#if !defined(_FM8)                     
-               if((addr < 0x40) && (addr >= 0x38)) {
-                       addr = (addr - 0x38) + FM7_SUBMEM_OFFSET_DPALETTE;
-                       return (uint32_t) display->read_data8(addr);
-               }
-#endif         
-               // Another:
-               return retval;
+//#if !defined(_FM8)                   
+                       if((addr < 0x40) && (addr >= 0x38)) {
+                               addr = (addr - 0x38) + FM7_SUBMEM_OFFSET_DPALETTE;
+                               return (uint32_t) display->read_data8(addr);
+                       }
+//#endif               
+                               // Another:
+                       return retval;
        } else if(addr == FM7_MAINIO_CLOCKMODE) {
                return (uint32_t)get_clockmode();
        }
@@ -1287,7 +1525,7 @@ uint32_t FM7_MAINIO::read_data8(uint32_t addr)
        }
 #endif
        //if((addr >= 0x0006) && (addr != 0x1f)) printf("MAINIO: READ: %08x DATA=%08x\n", addr);
-   return 0xff;
+       return 0xff;
 }
 
 void FM7_MAINIO::write_dma_io8(uint32_t addr, uint32_t data)
@@ -1312,7 +1550,7 @@ void FM7_MAINIO::write_data8(uint32_t addr, uint32_t data)
                if((addr < 0x90) && (addr >= 0x80)) {
                        mmr_segment = mainmem->read_data8(FM7_MAINIO_MMR_SEGMENT);
 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX) || \
-     defined(_FM77AV20) || defined(_FM77AV20SX) || defined(_FM77AV20EX)
+       defined(_FM77AV20) || defined(_FM77AV20SX) || defined(_FM77AV20EX)
                        mmr_segment &= 0x07;
 # else            
                        mmr_segment &= 0x03;
@@ -1352,11 +1590,26 @@ void FM7_MAINIO::write_data8(uint32_t addr, uint32_t data)
                        break;
                case 0x06: // RS-232C
                case 0x07:
+                       if(uart_enabled[0] && rs232c_enabled) {
+                               if(uart[0] != NULL) uart[0]->write_io8(addr & 1, data);
+                       }
                        break;
                case 0x08: // Light pen
                case 0x09:
                case 0x0a:
                        break;
+               case 0x0c:
+#if defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
+                       if(rs232c_dtr != NULL) {
+                               if((data & 0x04) != 0) {
+                                       rs232c_dtr->write_signal(SIG_AND_BIT_1, 0, 1);
+                               } else {
+                                       rs232c_dtr->write_signal(SIG_AND_BIT_1, 1, 1);
+                               }
+                       }
+                       rs232c_enabled = ((data & 0x01) != 0) ? true : false;
+#endif
+                       break;
                case 0x0d:
                        //printf("PSG CMD WRITE val=%02x\n", data);
                        set_psg_cmd(data);
@@ -1368,31 +1621,19 @@ void FM7_MAINIO::write_data8(uint32_t addr, uint32_t data)
                case 0x0f: // FD0F
                        write_fd0f();
                        break;
-#if defined(_FM8)
-               case 0x10:
-               case 0x11:
-               case 0x12:
-               case 0x13:
-               case 0x14:
-               case 0x15:
-               case 0x16:
-               case 0x17:
-                       bubble_casette[0]->write_data8(addr, data);
-                       break;
-#else                  
 #if defined(_FM77AV_VARIANTS)
                case 0x10:
                        flag = ((data & 0x02) == 0) ? true : false;
-                       mainmem->write_signal(FM7_MAINIO_INITROM_ENABLED, (flag) ? 0xffffffff : 0 , 0xffffffff);
+                       call_write_signal(mainmem, FM7_MAINIO_INITROM_ENABLED, (flag) ? 0xffffffff : 0 , 0xffffffff);
                        break;
                case 0x12:
-                       display->write_signal(SIG_DISPLAY_MODE320, data,  0x40);
+                       call_write_signal(display, SIG_DISPLAY_MODE320, data,  0x40);
                        reg_fd12 &= ~0x40;
                        reg_fd12 |= (data & 0x40);
                        break;
                case 0x13:
                        sub_monitor_type = data & 0x07;
-                       display->write_signal(SIG_FM7_SUB_BANK, sub_monitor_type, 0x07);
+                       call_write_signal(display, SIG_FM7_SUB_BANK, sub_monitor_type, 0x07);
                        break;
 #endif
                case 0x15: // OPN CMD
@@ -1406,7 +1647,65 @@ void FM7_MAINIO::write_data8(uint32_t addr, uint32_t data)
                case 0x17:
                        set_ext_fd17((uint8_t)data);
                        break;
-#endif                 
+#if defined(HAS_2HD)
+               case 0x18: // FDC: COMMAND
+                       if(stat_fdmode_2hd) {
+                               set_fdc_cmd_2HD((uint8_t)data);
+                       } else {
+                               set_fdc_cmd((uint8_t)data);
+                       }
+                       //printf("FDC: WRITE CMD %02x\n", data); 
+                       break;
+               case 0x19: // FDC: Track
+                       if(stat_fdmode_2hd) {
+                               set_fdc_track_2HD((uint8_t)data);
+                       } else {
+                               set_fdc_track((uint8_t)data);
+                       }
+                       //printf("FDC: WRITE TRACK REG %02x\n", data); 
+                       break;
+               case 0x1a: // FDC: Sector
+                       if(stat_fdmode_2hd) {
+                               set_fdc_sector_2HD((uint8_t)data);
+                       } else {
+                               set_fdc_sector((uint8_t)data);
+                       }
+                       //printf("FDC: WRITE SECTOR REG %02x\n", data); 
+                       break;
+               case 0x1b: // FDC: Data
+                       if(stat_fdmode_2hd) {
+                               set_fdc_data_2HD((uint8_t)data);
+                       } else {
+                               set_fdc_data((uint8_t)data);
+                       }
+                       break;
+               case 0x1c:
+                       if(stat_fdmode_2hd) {
+                               set_fdc_fd1c_2HD((uint8_t)data);
+                       } else {
+                               set_fdc_fd1c((uint8_t)data);
+                       }
+                       //printf("FDC: WRITE HEAD REG %02x\n", data); 
+                       break;
+               case 0x1d:
+                       if(stat_fdmode_2hd) {
+                               set_fdc_fd1d_2HD((uint8_t)data);
+                       } else {
+                               set_fdc_fd1d((uint8_t)data);
+                       }
+                       //printf("FDC: WRITE MOTOR REG %02x\n", data); 
+                       break;
+               case 0x1e:
+                       if(stat_fdmode_2hd) {
+                               set_fdc_fd1e_2HD((uint8_t)data);
+                       } else {
+                               set_fdc_fd1e((uint8_t)data);
+                       }
+                       break;
+               case 0x1f: // ??
+                       return;
+                       break;
+#else
                case 0x18: // FDC: COMMAND
                        set_fdc_cmd((uint8_t)data);
                        //printf("FDC: WRITE CMD %02x\n", data); 
@@ -1436,9 +1735,24 @@ void FM7_MAINIO::write_data8(uint32_t addr, uint32_t data)
                case 0x1f: // ??
                        return;
                        break;
+#endif
                case 0x20: // Kanji ROM
                        write_kanjiaddr_hi((uint8_t)data);
                        break;
+
+               case 0x21: // Kanji ROM
+                       write_kanjiaddr_lo((uint8_t)data);
+                       break;
+#if defined(CAPABLE_JCOMMCARD)
+# if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
+               case 0x28:
+               case 0x29:
+# endif
+               case 0x2a:
+               case 0x2b:
+                       if(jcommcard != NULL) jcommcard->write_io8(addr, data);
+                       break;
+#endif                 
                case 0x2c: // Kanji ROM(DUP)
 #if defined(CAPABLE_KANJI_CLASS2)
                        write_kanjiaddr_hi_l2((uint8_t)data);
@@ -1446,9 +1760,6 @@ void FM7_MAINIO::write_data8(uint32_t addr, uint32_t data)
                        //write_kanjiaddr_hi((uint8_t)data);
 #endif
                        break;
-               case 0x21: // Kanji ROM
-                       write_kanjiaddr_lo((uint8_t)data);
-                       break;
                case 0x2d: // Kanji ROM(DUP)
 #if defined(CAPABLE_KANJI_CLASS2)
                        write_kanjiaddr_lo_l2((uint8_t)data);
@@ -1458,7 +1769,7 @@ void FM7_MAINIO::write_data8(uint32_t addr, uint32_t data)
                        break;
 #if defined(CAPABLE_DICTROM)
                case 0x2e: // 
-                       mainmem->write_signal(FM7_MAINIO_EXTBANK, data, 0xff);
+                       call_write_signal(mainmem, FM7_MAINIO_EXTBANK, data, 0xff);
                        break;
 #endif                 
 #if defined(_FM77AV_VARIANTS)
@@ -1478,10 +1789,22 @@ void FM7_MAINIO::write_data8(uint32_t addr, uint32_t data)
                        display->write_data8(FM7_SUBMEM_OFFSET_APALETTE_G, data);
                        break;
 #endif
-#if !defined(_FM8)                     
+//#if !defined(_FM8)                   
                case 0x37: // Multi page
-                       display->write_signal(SIG_DISPLAY_MULTIPAGE, data, 0x00ff);
+                       call_write_signal(display, SIG_DISPLAY_MULTIPAGE, data, 0x00ff);
+                       break;
+               case 0x40: // MODEM
+               case 0x41:
+                       if(uart_enabled[1]) {
+                               if(uart[1] != NULL) uart[1]->write_io8(addr & 1, data);
+                       }
                        break;
+               case 0x42:
+                       modem_irqmask_txrdy = ((data & 0x20) != 0);
+                       modem_irqmask_rxrdy = ((data & 0x40) != 0);
+                       do_irq();
+                       break;
+                       
                case 0x45: // WHG CMD
                        set_opn_cmd(1, data);
                        break;
@@ -1498,7 +1821,7 @@ void FM7_MAINIO::write_data8(uint32_t addr, uint32_t data)
                        break;
                case 0x53:
                        break;
-#endif                 
+//#endif                       
 #if defined(HAS_MMR)
                case 0x90:
 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX) || \
@@ -1514,26 +1837,26 @@ void FM7_MAINIO::write_data8(uint32_t addr, uint32_t data)
                        mainmem->write_data8(FM7_MAINIO_WINDOW_OFFSET, (uint32_t)(data & 0x00ff));
                        break;
                case 0x93:
-                       mainmem->write_signal(FM7_MAINIO_BOOTRAM_RW, data, 0x01);
-                       mainmem->write_signal(FM7_MAINIO_WINDOW_ENABLED, data , 0x40);
+                       call_write_signal(mainmem, FM7_MAINIO_BOOTRAM_RW, data, 0x01);
+                       call_write_signal(mainmem, FM7_MAINIO_WINDOW_ENABLED, data , 0x40);
                        //this->write_signal(FM7_MAINIO_CLOCKMODE, clock_fast ? 1 : 0, 1);
                        //mainmem->write_signal(FM7_MAINIO_CLOCKMODE, clock_fast ? 1 : 0, 1);
-                       mainmem->write_signal(FM7_MAINIO_MMR_ENABLED, data, 0x80);
+                       call_write_signal(mainmem, FM7_MAINIO_MMR_ENABLED, data, 0x80);
                        //}
                        break;
 #endif
 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX) || \
     defined(_FM77AV20) || defined(_FM77AV20SX) || defined(_FM77AV20EX)
                case 0x94:
-                       mainmem->write_signal(FM7_MAINIO_MMR_EXTENDED, data, 0x80);
-                       mainmem->write_signal(FM7_MAINMEM_REFRESH_FAST, data, 0x04);
-                       mainmem->write_signal(FM7_MAINIO_WINDOW_FAST , data, 0x01);
+                       call_write_signal(mainmem, FM7_MAINIO_MMR_EXTENDED, data, 0x80);
+                       call_write_signal(mainmem, FM7_MAINIO_MEM_REFRESH_FAST, data, 0x04);
+                       call_write_signal(mainmem, FM7_MAINIO_WINDOW_FAST , data, 0x01);
 
                        break;
 # if defined(_FM77AV40SX) || defined(_FM77AV40EX)
                case 0x95:
-                       mainmem->write_signal(FM7_MAINIO_FASTMMR_ENABLED, data, 0x08);
-                       mainmem->write_signal(FM7_MAINIO_EXTROM, data , 0x80);
+                       call_write_signal(mainmem, FM7_MAINIO_FASTMMR_ENABLED, data, 0x08);
+                       call_write_signal(mainmem, FM7_MAINIO_EXTROM, data , 0x80);
                        break;
 # endif
 #endif                 
@@ -1545,18 +1868,23 @@ void FM7_MAINIO::write_data8(uint32_t addr, uint32_t data)
                        dmac->write_data8(dma_addr, data);
                        //this->out_debug_log(_T("IO: Wrote DMA %02x to reg %02x\n"), data, dma_addr);
                        break;
-#endif                 
+#endif
+                       // MIDI
+               case 0xea: 
+               case 0xeb:
+                       if(uart_enabled[2]) {
+                               if(uart[2] != NULL) uart[2]->write_io8(addr & 1, data);
+                       }
+                       break;
                default:
                        //printf("MAIN: Write I/O Addr=%08x DATA=%02x\n", addr, data); 
                        break;
                }
-#if !defined(_FM8)                     
                if((addr < 0x40) && (addr >= 0x38)) {
                        addr = (addr - 0x38) | FM7_SUBMEM_OFFSET_DPALETTE;
                        display->write_data8(addr, (uint8_t)data);
                        return;
                }// Another:
-#endif         
                return;
        } else if(addr == FM7_MAINIO_CLOCKMODE) {
                set_clockmode((uint8_t)data);
@@ -1569,34 +1897,49 @@ void FM7_MAINIO::event_callback(int event_id, int err)
 {
 //     printf("MAIN EVENT id=%d\n", event_id);
        switch(event_id) {
-               case EVENT_BEEP_OFF:
-                       event_beep_off();
-                       break;
-               case EVENT_BEEP_CYCLE:
-                       event_beep_cycle();
-                       break;
-               case EVENT_UP_BREAK:
-                       set_break_key(false);
-                       break;
-#if !defined(_FM8)
-               case EVENT_TIMERIRQ_ON:
-                       //if(!irqmask_timer) set_irq_timer(true);
-                       set_irq_timer(!irqmask_timer);
-                       break;
-#endif                 
-               case EVENT_FD_MOTOR_ON:
-                       set_fdc_motor(true);
-                       event_fdc_motor = -1;
-                       break;
-               case EVENT_FD_MOTOR_OFF:
-                       set_fdc_motor(false);
-                       event_fdc_motor = -1;
-                       break;
-               case EVENT_PRINTER_RESET_COMPLETED:                     
-                       this->write_signals(&printer_reset_bus, 0x00);
-                       break;
-               default:
-                       break;
+       case EVENT_BEEP_OFF:
+               event_beep_off();
+               break;
+       case EVENT_BEEP_CYCLE:
+               event_beep_cycle();
+               break;
+       case EVENT_UP_BREAK:
+               call_write_signal(keyboard, SIG_FM7KEY_OVERRIDE_PRESS_BREAK, 0, 0xffffffff);
+               set_break_key(false);
+               break;
+//#if !defined(_FM8)
+       case EVENT_TIMERIRQ_ON:
+               //if(!irqmask_timer) set_irq_timer(true);
+               set_irq_timer(!irqmask_timer);
+               break;
+//#endif                       
+       case EVENT_FD_MOTOR_ON:
+               set_fdc_motor(true);
+               event_fdc_motor = -1;
+               break;
+       case EVENT_FD_MOTOR_OFF:
+               set_fdc_motor(false);
+               event_fdc_motor = -1;
+               break;
+#if defined(HAS_2HD)
+       case EVENT_FD_MOTOR_ON_2HD:
+               set_fdc_motor_2HD(true);
+               event_fdc_motor_2HD = -1;
+               break;
+       case EVENT_FD_MOTOR_OFF_2HD:
+               set_fdc_motor_2HD(false);
+               event_fdc_motor_2HD = -1;
+               break;
+       case EVENT_FD_NMI_2HD:
+               do_nmi(true);
+               event_2hd_nmi = -1;
+               break;
+#endif
+       case EVENT_PRINTER_RESET_COMPLETED:                     
+               write_signals(&printer_reset_bus, 0x00);
+               break;
+       default:
+               break;
        }
 }
 
@@ -1604,187 +1947,200 @@ void FM7_MAINIO::event_callback(int event_id, int err)
 void FM7_MAINIO::update_config()
 {
        switch(config.cpu_type){
-               case 0:
-                       clock_fast = true;
-                       break;
-               case 1:
-                       clock_fast = false;
-                       break;
-       }
-       this->write_signals(&clock_status, clock_fast ? 0xffffffff : 0);
-#if defined(_FM8)      
-       // BASIC
-       if(config.boot_mode == 0) {
-               mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0xffffffff, 0xffffffff);
-       } else {
-               mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0, 0xffffffff);
+       case 0:
+               clock_fast = true;
+               break;
+       case 1:
+               clock_fast = false;
+               break;
        }
-       mainmem->write_signal(FM7_MAINIO_PUSH_FD0F, (config.boot_mode == 0) ? 1 : 0, 0x01);
-       mainmem->write_signal(FM7_MAINIO_BOOTMODE, bootmode, 0xffffffff);
-#endif 
+       write_signals(&clock_status, clock_fast ? 0xffffffff : 0);
 }
 
 void FM7_MAINIO::event_vline(int v, int clock)
 {
 }
 
-#define STATE_VERSION 6
-void FM7_MAINIO::save_state(FILEIO *state_fio)
+
+#define STATE_VERSION 16
+#include "../../statesub.h"
+
+void FM7_MAINIO::decl_state(void)
 {
-       int ch;
-       int addr;
-       state_fio->FputUint32_BE(STATE_VERSION);
-       state_fio->FputInt32_BE(this_device_id);
-       this->out_debug_log("Save State: MAINIO: id=%d ver=%d\n", this_device_id, STATE_VERSION);
+       enter_decl_state(STATE_VERSION);
 
-       // Version 1
-       {
-               for(addr = 0; addr < 0x100; addr++) state_fio->FputUint8(io_w_latch[addr]);
-               // FD00
-               state_fio->FputBool(clock_fast);
-               state_fio->FputBool(lpt_strobe);
-               state_fio->FputBool(lpt_slctin);
-               state_fio->FputBool(beep_flag);
-               state_fio->FputBool(beep_snd);
+       DECL_STATE_ENTRY_MULTI(void, io_w_latch, sizeof(io_w_latch));
+       
+       DECL_STATE_ENTRY_BOOL(clock_fast);
+       DECL_STATE_ENTRY_BOOL(lpt_strobe);
+       DECL_STATE_ENTRY_BOOL(lpt_slctin);
+       DECL_STATE_ENTRY_BOOL(beep_flag);
+       DECL_STATE_ENTRY_BOOL(beep_snd);
        
                // FD01
-               state_fio->FputUint8(lpt_outdata);
-               // FD02
-               state_fio->FputBool(cmt_indat);
-               state_fio->FputBool(cmt_invert);
-               state_fio->FputBool(lpt_det2);
-               state_fio->FputBool(lpt_det1);
-               state_fio->FputBool(lpt_pe);
-               state_fio->FputBool(lpt_ackng_inv);
-               state_fio->FputBool(lpt_error_inv);
-               state_fio->FputUint8(irqmask_reg0);
-               
-               state_fio->FputBool(irqmask_syndet);
-               state_fio->FputBool(irqmask_rxrdy);
-               state_fio->FputBool(irqmask_txrdy);
-               state_fio->FputBool(irqmask_mfd);
-               state_fio->FputBool(irqmask_timer);
-               state_fio->FputBool(irqmask_printer);
-               state_fio->FputBool(irqmask_keyboard);
-
-               state_fio->FputBool(irqreq_syndet);
-               state_fio->FputBool(irqreq_rxrdy);
-               state_fio->FputBool(irqreq_txrdy);
-               state_fio->FputBool(irqreq_printer);
-               state_fio->FputBool(irqreq_keyboard);
-               // FD03
-               state_fio->FputUint8(irqstat_reg0);
+       DECL_STATE_ENTRY_UINT8(lpt_outdata);
+       // FD02
+       DECL_STATE_ENTRY_BOOL(cmt_indat);
+       DECL_STATE_ENTRY_BOOL(cmt_invert);
+       DECL_STATE_ENTRY_BOOL(lpt_det2);
+       DECL_STATE_ENTRY_BOOL(lpt_det1);
+       DECL_STATE_ENTRY_BOOL(lpt_pe);
+       DECL_STATE_ENTRY_BOOL(lpt_ackng_inv);
+       DECL_STATE_ENTRY_BOOL(lpt_error_inv);
+       DECL_STATE_ENTRY_UINT8(irqmask_reg0);
+       
+       DECL_STATE_ENTRY_BOOL(irqmask_syndet);
+       DECL_STATE_ENTRY_BOOL(irqmask_rxrdy);
+       DECL_STATE_ENTRY_BOOL(irqmask_txrdy);
+       DECL_STATE_ENTRY_BOOL(irqmask_mfd);
+       DECL_STATE_ENTRY_BOOL(irqmask_timer);
+       DECL_STATE_ENTRY_BOOL(irqmask_printer);
+       DECL_STATE_ENTRY_BOOL(irqmask_keyboard);
+
+       DECL_STATE_ENTRY_BOOL(irqreq_syndet);
+       DECL_STATE_ENTRY_BOOL(irqreq_rxrdy);
+       DECL_STATE_ENTRY_BOOL(irqreq_txrdy);
+       DECL_STATE_ENTRY_BOOL(irqreq_printer);
+       DECL_STATE_ENTRY_BOOL(irqreq_keyboard);
+       DECL_STATE_ENTRY_UINT8(irqstat_reg0);
                
-               state_fio->FputBool(irqstat_timer);
-               state_fio->FputBool(irqstat_printer);
-               state_fio->FputBool(irqstat_keyboard);
+       DECL_STATE_ENTRY_BOOL(irqstat_timer);
+       DECL_STATE_ENTRY_BOOL(irqstat_printer);
+       DECL_STATE_ENTRY_BOOL(irqstat_keyboard);
                
                // FD04
 #if defined(_FM77_VARIANTS)
-               state_fio->FputBool(stat_fdmode_2hd);
-               state_fio->FputBool(stat_kanjirom);
-               state_fio->FputBool(stat_400linecard);
+       DECL_STATE_ENTRY_BOOL(stat_fdmode_2hd);
+       DECL_STATE_ENTRY_BOOL(stat_kanjirom);
 #elif defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
-      defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
-               state_fio->FputBool(stat_kanjirom);
+       defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
+       DECL_STATE_ENTRY_BOOL(stat_kanjirom);
 #endif
-               state_fio->FputBool(firq_break_key);
-               state_fio->FputBool(firq_sub_attention);
-               
-               state_fio->FputBool(intmode_fdc);
-               // FD05
-               state_fio->FputBool(extdet_neg);
-               state_fio->FputBool(sub_halt);
-               state_fio->FputBool(sub_cancel);
-#if defined(WITH_Z80)  
-               state_fio->FputBool(z80_sel);
-#endif 
-               // FD06, 07
-               state_fio->FputBool(intstat_syndet);
-               state_fio->FputBool(intstat_rxrdy);
-               state_fio->FputBool(intstat_txrdy);
-
-       // FD0B
-       // FD0F
-#if defined(_FM8)
-               state_fio->FputBool(connect_psg);
-#else  
-               state_fio->FputBool(connect_opn);
-               state_fio->FputBool(connect_whg);
-               state_fio->FputBool(connect_thg);
-               
-               state_fio->FputBool(opn_psg_77av);
-#endif 
-#if defined(_FM8)
-               {
-                       state_fio->FputUint32_BE(opn_address[0]);
-                       state_fio->FputUint32_BE(opn_data[0]);
-                       state_fio->FputUint32_BE(opn_stat[0]);
-                       state_fio->FputUint32_BE(opn_cmdreg[0]);
-                       state_fio->FputUint32_BE(opn_ch3mode[0]);
-               }
-#else          
-               for(ch = 0; ch < 4; ch++) {
-                       state_fio->FputUint32_BE(opn_address[ch]);
-                       state_fio->FputUint32_BE(opn_data[ch]);
-                       state_fio->FputUint32_BE(opn_stat[ch]);
-                       state_fio->FputUint32_BE(opn_cmdreg[ch]);
-                       state_fio->FputUint32_BE(opn_ch3mode[ch]);
-               }
-#endif         
-
-               state_fio->FputBool(intstat_opn);
-               state_fio->FputBool(intstat_mouse);
-               state_fio->FputBool(mouse_enable);
+       DECL_STATE_ENTRY_BOOL(firq_break_key);
+       DECL_STATE_ENTRY_BOOL(firq_sub_attention);
+       
+       DECL_STATE_ENTRY_BOOL(intmode_fdc);
+       // FD05
+       DECL_STATE_ENTRY_BOOL(extdet_neg);
+       DECL_STATE_ENTRY_BOOL(sub_halt);
+       DECL_STATE_ENTRY_BOOL(sub_cancel);
+       // FD06, 07
+       DECL_STATE_ENTRY_BOOL(intstat_syndet);
+       DECL_STATE_ENTRY_BOOL(intstat_rxrdy);
+       DECL_STATE_ENTRY_BOOL(intstat_txrdy);
+       
+       
+       DECL_STATE_ENTRY_BOOL(intstat_opn);
+       DECL_STATE_ENTRY_BOOL(intstat_mouse);
+       DECL_STATE_ENTRY_BOOL(mouse_enable);
+       
+       DECL_STATE_ENTRY_BOOL(intstat_whg);
+       DECL_STATE_ENTRY_BOOL(intstat_thg);
        
-               state_fio->FputBool(intstat_whg);
-               state_fio->FputBool(intstat_thg);
-
        // FDC
-               state_fio->FputBool(connect_fdc);
-               state_fio->FputUint8(fdc_statreg);
-               state_fio->FputUint8(fdc_cmdreg);
-               state_fio->FputUint8(fdc_trackreg);
-               state_fio->FputUint8(fdc_sectreg);
-               state_fio->FputUint8(fdc_datareg);
-               state_fio->FputUint8(fdc_headreg);
-               state_fio->FputUint8(fdc_drvsel);
-               state_fio->FputUint8(irqreg_fdc);
-               state_fio->FputBool(fdc_motor);
-               state_fio->FputBool(irqstat_fdc);
-               // KANJI ROM
-               state_fio->FputBool(connect_kanjiroml1);
+       DECL_STATE_ENTRY_BOOL(connect_fdc);
+       DECL_STATE_ENTRY_UINT8(fdc_statreg);
+       DECL_STATE_ENTRY_UINT8(fdc_cmdreg);
+       DECL_STATE_ENTRY_UINT8(fdc_trackreg);
+       DECL_STATE_ENTRY_UINT8(fdc_sectreg);
+       DECL_STATE_ENTRY_UINT8(fdc_datareg);
+       DECL_STATE_ENTRY_UINT8(fdc_headreg);
+       DECL_STATE_ENTRY_UINT8(fdc_drvsel);
+       DECL_STATE_ENTRY_UINT8(irqreg_fdc);
+       DECL_STATE_ENTRY_BOOL(fdc_motor);
+       DECL_STATE_ENTRY_BOOL(irqstat_fdc);
+       // KANJI ROM
+       DECL_STATE_ENTRY_BOOL(connect_kanjiroml1);
 #if defined(_FM77AV_VARIANTS)
-               state_fio->FputBool(connect_kanjiroml2);
+       DECL_STATE_ENTRY_BOOL(connect_kanjiroml2);
        
-               state_fio->FputBool(boot_ram);
-               state_fio->FputBool(hotreset);
+       DECL_STATE_ENTRY_BOOL(boot_ram);
+       DECL_STATE_ENTRY_BOOL(hotreset);
                // FD13
-               state_fio->FputUint8(sub_monitor_type);
+       DECL_STATE_ENTRY_UINT8(sub_monitor_type);
 #endif 
                // MMR
-       }
        //V2
        {
-               state_fio->FputInt32_BE(event_beep);
-               state_fio->FputInt32_BE(event_beep_oneshot);
-               state_fio->FputInt32_BE(event_timerirq);
+               DECL_STATE_ENTRY_INT(event_beep);
+               DECL_STATE_ENTRY_INT(event_beep_oneshot);
+               DECL_STATE_ENTRY_INT(event_timerirq);
        }               
        { // V3
-               state_fio->FputInt32_BE(event_fdc_motor);
+               DECL_STATE_ENTRY_INT(event_fdc_motor);
 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)|| \
     defined(_FM77AV20) || defined(_FM77AV20SX) || defined(_FM77AV20EX)
-               for(ch = 0; ch < 4; ch++) state_fio->FputUint8(fdc_drive_table[ch]);
-               state_fio->FputUint8(fdc_reg_fd1e);
+               DECL_STATE_ENTRY_UINT8_ARRAY(fdc_drive_table, 4);
+               DECL_STATE_ENTRY_UINT8(fdc_reg_fd1e);
 #endif 
 #if defined(HAS_DMA)
-               state_fio->FputBool(intstat_dma);
-               state_fio->FputUint8(dma_addr & 0x1f);
+               DECL_STATE_ENTRY_BOOL(intstat_dma);
+               DECL_STATE_ENTRY_UINT8(dma_addr);
 #endif                 
 #if defined(_FM77AV_VARIANTS)
-               state_fio->FputUint8(reg_fd12);
+               DECL_STATE_ENTRY_UINT8(reg_fd12);
 #endif         
-       }               
+       }
+// FD05
+       DECL_STATE_ENTRY_BOOL(req_z80run);
+       DECL_STATE_ENTRY_BOOL(z80_run);
+
+       // UART
+       DECL_STATE_ENTRY_BOOL(rs232c_enabled);
+       DECL_STATE_ENTRY_BOOL(rs232c_dcd);
+       DECL_STATE_ENTRY_BOOL_ARRAY(uart_enabled, 3);
+       
+       DECL_STATE_ENTRY_BOOL(modem_irqmask_rxrdy);
+       DECL_STATE_ENTRY_BOOL(modem_irqmask_txrdy);
+       DECL_STATE_ENTRY_BOOL(modem_syndet);
+       DECL_STATE_ENTRY_BOOL(modem_rxrdy);
+       DECL_STATE_ENTRY_BOOL(modem_txrdy);
+
+       DECL_STATE_ENTRY_BOOL(midi_uart_irqmask);
+       DECL_STATE_ENTRY_BOOL(midi_syndet);
+       DECL_STATE_ENTRY_BOOL(midi_rxrdy);
+       DECL_STATE_ENTRY_BOOL(midi_txrdy);
+#if defined(HAS_2HD)
+       DECL_STATE_ENTRY_INT(event_fdc_motor_2HD);
+       DECL_STATE_ENTRY_BOOL(connect_fdc_2HD);
+       DECL_STATE_ENTRY_UINT8(fdc_2HD_statreg);
+       DECL_STATE_ENTRY_UINT8(fdc_2HD_cmdreg);
+       DECL_STATE_ENTRY_UINT8(fdc_2HD_trackreg);
+       DECL_STATE_ENTRY_UINT8(fdc_2HD_sectreg);
+       DECL_STATE_ENTRY_UINT8(fdc_2HD_datareg);
+       DECL_STATE_ENTRY_UINT8(fdc_2HD_headreg);
+       DECL_STATE_ENTRY_UINT8(fdc_2HD_drvsel);
+       DECL_STATE_ENTRY_UINT8(irqreg_fdc_2HD);
+       DECL_STATE_ENTRY_BOOL(fdc_2HD_motor);
+       //state_fio->FputBool(irqstat_fdc);
+       DECL_STATE_ENTRY_INT(event_2hd_nmi);
+       DECL_STATE_ENTRY_UINT32(nmi_delay);
+       DECL_STATE_ENTRY_BOOL(irqstat_fdc_2hd);
+       DECL_STATE_ENTRY_BOOL(drqstat_fdc_2hd);
+#endif
+       
+       decl_state_opn();
+       
+       leave_decl_state();
+}
+void FM7_MAINIO::save_state(FILEIO *state_fio)
+{
+       if(state_entry != NULL) state_entry->save_state(state_fio);
+#if 0
+       // Debug
+       for(int i = 0; i < 3; i++) {
+               out_debug_log("OPN#%d registers (to Save)", i);
+               out_debug_log("ADDR: +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f");
+               for(int ladr = 0; ladr < 0x100; ladr += 0x10) {
+                       out_debug_log("+%02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
+                                                 ladr,
+                                                 opn_regs[i][ladr + 0],  opn_regs[i][ladr + 1],  opn_regs[i][ladr + 2],  opn_regs[i][ladr + 3],
+                                                 opn_regs[i][ladr + 4],  opn_regs[i][ladr + 5],  opn_regs[i][ladr + 6],  opn_regs[i][ladr + 7],
+                                                 opn_regs[i][ladr + 8],  opn_regs[i][ladr + 9],  opn_regs[i][ladr + 10], opn_regs[i][ladr + 11],
+                                                 opn_regs[i][ladr + 12], opn_regs[i][ladr + 13], opn_regs[i][ladr + 14], opn_regs[i][ladr + 15]);
+               }
+       }
+#endif 
 }
 
 bool FM7_MAINIO::load_state(FILEIO *state_fio)
@@ -1793,157 +2149,30 @@ bool FM7_MAINIO::load_state(FILEIO *state_fio)
        int addr;
        //bool stat = false;
        uint32_t version;
-       
-       version = state_fio->FgetUint32_BE();
-       if(this_device_id != state_fio->FgetInt32_BE()) return false;
-       this->out_debug_log("Load State: MAINIO: id=%d ver=%d\n", this_device_id, version);
-
-       if(version >= 1) {
-               for(addr = 0; addr < 0x100; addr++) io_w_latch[addr] = state_fio->FgetUint8();
-               // FD00
-               clock_fast = state_fio->FgetBool();
-               lpt_strobe = state_fio->FgetBool();
-               lpt_slctin = state_fio->FgetBool();
-               beep_flag  = state_fio->FgetBool();
-               beep_snd = state_fio->FgetBool();
-       
-               // FD01
-               lpt_outdata = state_fio->FgetUint8();
-               // FD02
-               cmt_indat = state_fio->FgetBool();
-               cmt_invert = state_fio->FgetBool();
-               lpt_det2 = state_fio->FgetBool();
-               lpt_det1 = state_fio->FgetBool();
-               lpt_pe = state_fio->FgetBool();
-               lpt_ackng_inv = state_fio->FgetBool();
-               lpt_error_inv = state_fio->FgetBool();
-               irqmask_reg0 = state_fio->FgetUint8();
-
-               irqmask_syndet = state_fio->FgetBool();
-               irqmask_rxrdy = state_fio->FgetBool();
-               irqmask_txrdy = state_fio->FgetBool();
-               irqmask_mfd = state_fio->FgetBool();
-               irqmask_timer = state_fio->FgetBool();
-               irqmask_printer = state_fio->FgetBool();
-               irqmask_keyboard = state_fio->FgetBool();
-
-               irqreq_syndet = state_fio->FgetBool();
-               irqreq_rxrdy = state_fio->FgetBool();
-               irqreq_txrdy = state_fio->FgetBool();
-               irqreq_printer = state_fio->FgetBool();
-               irqreq_keyboard = state_fio->FgetBool();
-               // FD03
-               irqstat_reg0 = state_fio->FgetUint8();
-
-               irqstat_timer = state_fio->FgetBool();
-               irqstat_printer = state_fio->FgetBool();
-               irqstat_keyboard = state_fio->FgetBool();
-       
-               // FD04
-#if defined(_FM77_VARIANTS)
-               stat_fdmode_2hd = state_fio->FgetBool();
-               stat_kanjirom = state_fio->FgetBool();
-               stat_400linecard = state_fio->FgetBool();
-#elif defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
-      defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
-               stat_kanjirom = state_fio->FgetBool();
-#endif
-               firq_break_key = state_fio->FgetBool();
-               firq_sub_attention = state_fio->FgetBool();
-               
-               intmode_fdc = state_fio->FgetBool();
-               // FD05
-               extdet_neg = state_fio->FgetBool();
-               sub_halt = state_fio->FgetBool();
-               sub_cancel = state_fio->FgetBool();
-#if defined(WITH_Z80)  
-               z80_sel = state_fio->FgetBool();
-#endif 
-               // FD06, 07
-               intstat_syndet = state_fio->FgetBool();
-               intstat_rxrdy = state_fio->FgetBool();
-               intstat_txrdy = state_fio->FgetBool();
-
-               // FD0B
-               // FD0F
-#if defined(_FM8)
-               connect_psg = state_fio->FgetBool();
-#else          
-               connect_opn = state_fio->FgetBool();
-               connect_whg = state_fio->FgetBool();
-               connect_thg = state_fio->FgetBool();
-
-               opn_psg_77av = state_fio->FgetBool();
+       bool mb = false;
+       if(state_entry != NULL) {
+               mb = state_entry->load_state(state_fio);
+               if(mb) {
+#if defined(HAS_DMA)
+                       dma_addr = dma_addr & 0x1f;
 #endif
-#if defined(_FM8)
-               {
-                       opn_address[0] = state_fio->FgetUint32_BE();
-                       opn_data[0] = state_fio->FgetUint32_BE();
-                       opn_stat[0] = state_fio->FgetUint32_BE();
-                       opn_cmdreg[0] = state_fio->FgetUint32_BE();
-                       opn_ch3mode[0] = state_fio->FgetUint32_BE();
-               }
-#else          
-               for(ch = 0; ch < 4; ch++) {
-                       opn_address[ch] = state_fio->FgetUint32_BE();
-                       opn_data[ch] = state_fio->FgetUint32_BE();
-                       opn_stat[ch] = state_fio->FgetUint32_BE();
-                       opn_cmdreg[ch] = state_fio->FgetUint32_BE();
-                       opn_ch3mode[ch] = state_fio->FgetUint32_BE();
                }
-#endif
-               intstat_opn = state_fio->FgetBool();
-               intstat_mouse = state_fio->FgetBool();
-               mouse_enable = state_fio->FgetBool();
-       
-               intstat_whg = state_fio->FgetBool();
-               intstat_thg = state_fio->FgetBool();
-
-               // FDC
-               connect_fdc = state_fio->FgetBool();
-               fdc_statreg = state_fio->FgetUint8();
-               fdc_cmdreg = state_fio->FgetUint8();
-               fdc_trackreg = state_fio->FgetUint8();
-               fdc_sectreg = state_fio->FgetUint8();
-               fdc_datareg = state_fio->FgetUint8();
-               fdc_headreg = state_fio->FgetUint8();
-               fdc_drvsel = state_fio->FgetUint8();
-               irqreg_fdc = state_fio->FgetUint8();
-               fdc_motor = state_fio->FgetBool();
-               irqstat_fdc = state_fio->FgetBool();
-
-               // KANJI ROM
-               connect_kanjiroml1 = state_fio->FgetBool();
-#if defined(_FM77AV_VARIANTS)
-               connect_kanjiroml2 = state_fio->FgetBool();
-               boot_ram = state_fio->FgetBool();
-               hotreset = state_fio->FgetBool();
-               // FD13
-               sub_monitor_type = state_fio->FgetUint8();
-#endif 
-       }
-       if(version >= 2) {
-               event_beep = state_fio->FgetInt32_BE();
-               event_beep_oneshot = state_fio->FgetInt32_BE();
-               event_timerirq = state_fio->FgetInt32_BE();
        }
-       // V2
-       if(version >= 3) { // V3
-               event_fdc_motor = state_fio->FgetInt32_BE();
-#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)|| \
-    defined(_FM77AV20) || defined(_FM77AV20SX) || defined(_FM77AV20EX)
-               for(ch = 0; ch < 4; ch++) fdc_drive_table[ch] = state_fio->FgetUint8();
-               fdc_reg_fd1e = state_fio->FgetUint8();
-#endif 
-#if defined(HAS_DMA)
-               intstat_dma = state_fio->FgetBool();
-               dma_addr = (uint32_t)(state_fio->FgetUint8() & 0x1f);
-#endif                 
-#if defined(_FM77AV_VARIANTS)
-               reg_fd12 = state_fio->FgetUint8();
-#endif         
+#if 0
+       for(int i = 0; i < 3; i++) {
+               out_debug_log("OPN#%d registers (Loaded)", i);
+               out_debug_log("ADDR: +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f");
+               for(int ladr = 0; ladr < 0x100; ladr += 0x10) {
+                       out_debug_log("+%02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
+                                                 ladr,
+                                                 opn_regs[i][ladr + 0],  opn_regs[i][ladr + 1],  opn_regs[i][ladr + 2],  opn_regs[i][ladr + 3],
+                                                 opn_regs[i][ladr + 4],  opn_regs[i][ladr + 5],  opn_regs[i][ladr + 6],  opn_regs[i][ladr + 7],
+                                                 opn_regs[i][ladr + 8],  opn_regs[i][ladr + 9],  opn_regs[i][ladr + 10], opn_regs[i][ladr + 11],
+                                                 opn_regs[i][ladr + 12], opn_regs[i][ladr + 13], opn_regs[i][ladr + 14], opn_regs[i][ladr + 15]);
+               }
        }
-       if(version != STATE_VERSION) return false;
-       return true;
+#endif
+       this->out_debug_log(_T("Load State: MAINIO: id=%d stat=%s\n"), this_device_id, (mb) ? _T("OK") : _T("NG"));
+       return mb;
 }