OSDN Git Service

[VM][FM77AV][WIP] Fixing real-time-key-scanning , WIP.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / fm7_mainio.cpp
index d83a176..5e8cb9f 100644 (file)
 #include "../datarec.h"
 
 // TEST
-//#include <SDL2/SDL.h>
+#include <SDL2/SDL.h>
 
-void FM7_MAINIO::initialize(void)
+void FM7_MAINIO::initialize()
 {
+       int i;
        event_beep = -1;
+       event_beep_oneshot = -1;
        event_timerirq = -1;
        bootmode = config.boot_mode & 3;
 #if defined(_FM77AV_VARIANTS)
        opn_psg_77av = true;
 #else
+       //opn_psg_77av = true;
        opn_psg_77av = false;
 #endif
+#if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
+       boot_ram = false;
+#endif 
+#if defined(_FM77AV_VARIANTS)
+       enable_initiator = true;
+#endif
+#ifdef HAS_MMR
+       mmr_enabled = false;
+       mmr_fast = false;
+       window_enabled = false;
+       mmr_segment = 0x00;
+       for(i = 0x00; i < 0x80; i++) mmr_table[i] = 0;
+       //      for(i = 0x00; i < 0x10; i++) mmr_table[i] = 0x30 + i;
+#endif
+       switch(config.cpu_type){
+               case 0:
+                       clock_fast = true;
+                       break;
+               case 1:
+                       clock_fast = false;
+                       break;
+       }
+       this->write_signal(FM7_MAINIO_CLOCKMODE, clock_fast ? 1 : 0, 1);
+       sub_busy = false;
 }
 
-void FM7_MAINIO::reset(void)
+void FM7_MAINIO::reset()
 {
        int i, j;
        uint8 data;
-       //if(event_beep >= 0) cancel_event(this, event_beep);
-       if(event_timerirq >= 0) cancel_event(this, event_timerirq);
+       if(event_beep >= 0) cancel_event(this, event_beep);
        event_beep = -1;
+       if(event_beep_oneshot >= 0) cancel_event(this, event_beep_oneshot);
+       event_beep_oneshot = -1;
+       if(event_timerirq >= 0) cancel_event(this, event_timerirq);
        beep_snd = true;
        beep_flag = false;
+       if(event_beep < 0) register_event(this, EVENT_BEEP_CYCLE, (1000.0 * 1000.0) / (1200.0 * 2.0), true, &event_beep);
+   
        extdet_neg = false;
    
        stat_romrammode = true;
@@ -48,11 +79,28 @@ void FM7_MAINIO::reset(void)
        } else { // ELSE RAM
                stat_romrammode = false;
        }
-   
+#if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
+       boot_ram = false;
+       kaddress.d = 0;
+#endif 
+#if defined(_FM77AV_VARIANTS)
+       mode320 = false;
+       sub_monitor_type = 0x00;
+       sub_monitor_bak = sub_monitor_type;
+       display->write_signal(SIG_FM7_SUB_BANK, sub_monitor_type, 0x07);
+#endif
+       
+#ifdef HAS_MMR
+       mmr_enabled = false;
+       mmr_fast = false;
+       window_enabled = false;
+#endif
        clock_fast = false;
        if(config.cpu_type == 0) clock_fast = true;
    
        reset_sound();
+       key_irq_req = false;
+       key_irq_bak = key_irq_req;   
        
        irqmask_reg0 = 0x00;
        irqstat_bak = false;
@@ -70,27 +118,38 @@ void FM7_MAINIO::reset(void)
        // FD04
        //firq_break_key = false; // bit1, ON = '0'.
        firq_sub_attention = false; // bit0, ON = '0'.
+       firq_sub_attention_bak = false; // bit0, ON = '0'.
        // FD05
-       sub_busy = false;
        extdet_neg = false;
        sub_cancel = false; // bit6 : '1' Cancel req.
-
+       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.
        nmi_count = 0;
        reset_fdc();
    
        register_event(this, EVENT_TIMERIRQ_ON, 10000.0 / 4.9152, true, &event_timerirq); // TIMER IRQ
-
-       maincpu->reset();
+       mainmem->reset();
+       memset(io_w_latch, 0x00, 0x100);
+       sub_busy = (read_signal(SIG_DISPLAY_BUSY) == 0) ? false : true;
+       keycode_7 = 0x00;
+       keycode = 0x00;
+       //register_event_by_clock(this, EVENT_FM7SUB_PROC, 16, true, NULL); // 2uS / 8MHz 
+       //maincpu->reset();
 }
 
 
 void FM7_MAINIO::set_clockmode(uint8 flags)
 {
-       if(flags == FM7_MAINCLOCK_SLOW) {
+       uint f = clock_fast;
+       if((flags & FM7_MAINCLOCK_SLOW) != 0) {
                clock_fast = false;
        } else {
                clock_fast = true;
        }
+       if(f != clock_fast) {
+               this->write_signal(FM7_MAINIO_CLOCKMODE, clock_fast ? 1 : 0, 1);
+       }
 }
 
 uint8 FM7_MAINIO::get_clockmode(void)
@@ -102,9 +161,9 @@ uint8 FM7_MAINIO::get_clockmode(void)
 
 uint8 FM7_MAINIO::get_port_fd00(void)
 {
-       uint8 ret           = 0b01111110;
-       if(kbd_bit8)   ret |= 0b10000000;
-       if(clock_fast) ret |= 0b00000001;
+       uint8 ret           = 0x7e; //0b01111110;
+       if((keycode & 0x100) != 0) ret |= 0x80; // High bit.
+       if(clock_fast) ret |= 0x01; //0b00000001;
        return ret;
 }
   
@@ -130,8 +189,9 @@ void FM7_MAINIO::set_port_fd02(uint8 val)
        bool printerirq_bak = irqmask_printer;
        bool mfdirq_bak = irqmask_mfd;
        bool flag;
-       if((val & 0b00010000) != 0) {
-               irqmask_mfd = false;
+       //      if((val & 0b00010000) != 0) {
+       if((val & 0x10) != 0) {
+       irqmask_mfd = false;
        } else {
                irqmask_mfd = true;
        }
@@ -139,7 +199,8 @@ void FM7_MAINIO::set_port_fd02(uint8 val)
                flag = irqstat_fdc;
                set_irq_mfd(flag);
        }
-       if((val & 0b00000100) != 0) {
+       //if((val & 0b00000100) != 0) {
+       if((val & 0x04) != 0) {
                irqmask_timer = false;
        } else {
                irqmask_timer = true;
@@ -148,7 +209,8 @@ void FM7_MAINIO::set_port_fd02(uint8 val)
                flag = irqstat_timer;
                set_irq_timer(flag);
        }
-       if((val & 0b00000010) != 0) {
+       //if((val & 0b00000010) != 0) {
+       if((val & 0x02) != 0) {
                irqmask_printer = false;
        } else {
                irqmask_printer = true;
@@ -158,7 +220,8 @@ void FM7_MAINIO::set_port_fd02(uint8 val)
                set_irq_printer(flag);
        }
    
-       if((val & 0b00000001) != 0) {
+       //if((val & 0b00000001) != 0) {
+       if((val & 0x01) != 0) {
                irqmask_keyboard = false;
        } else {
                irqmask_keyboard = true;
@@ -166,39 +229,27 @@ void FM7_MAINIO::set_port_fd02(uint8 val)
        if(keyirq_bak != irqmask_keyboard) {
                flag = irqstat_keyboard;
                flag = flag & !irqmask_keyboard;
-               display->write_signal(SIG_FM7_SUB_KEY_FIRQ, flag ? 1 : 0, 1);
+               display->write_signal(SIG_FM7_SUB_KEY_MASK, flag ? 1 : 0, 1); 
+               display->write_signal(SIG_FM7_SUB_KEY_FIRQ, flag ? keycode : 0, 0xffffffff);
                //printf("KEYBOARD: Interrupted %d\n", flag);
                irqmask_keyboard = flag;
-               do_irq(flag);
+               do_irq();
        }
    
        return;
 }
 
-
-uint32 FM7_MAINIO::get_keyboard(void)
-{
-       uint32 kbd_data = (uint32) kbd_bit7_0;
-       kbd_data &= 0x0ff;
-       if(kbd_bit8) kbd_data |= 0x0100;
-       return kbd_data;
-}
-
-
-
 void FM7_MAINIO::set_irq_timer(bool flag)
 {
        uint8 backup = irqstat_reg0;
        if(flag && !(irqmask_timer)) {
-               //irqstat_reg0 |= 0b00000100;
-               irqstat_reg0 &= 0b11111011;
+               irqstat_reg0 &= 0xfb; //~0x04;
                irqstat_timer = true;      
-               if(backup != irqstat_reg0) do_irq(true);
+               if(backup != irqstat_reg0) do_irq();
        } else {
-               irqstat_reg0 |= 0b00000100;
-               //irqstat_reg0 &= 0b11111011;
+               irqstat_reg0 |= 0x04;
                irqstat_timer = false;     
-               if(backup != irqstat_reg0) do_irq(false);
+               if(backup != irqstat_reg0) do_irq();
        }
        //printf("IRQ TIMER: %02x MASK=%d\n", irqstat_reg0, irqmask_timer);
 }
@@ -207,46 +258,36 @@ void FM7_MAINIO::set_irq_printer(bool flag)
 {
        uint8 backup = irqstat_reg0;
        if(flag && !(irqmask_printer)) {
-               irqstat_reg0 &= 0b111111101;
+               irqstat_reg0 &= ~0x02;
                irqstat_printer = true;    
-               if(backup != irqstat_reg0) do_irq(true);
+               if(backup != irqstat_reg0) do_irq();
        } else {
-               irqstat_reg0 |= 0b000000010;
+               irqstat_reg0 |= 0x02;
                irqstat_printer = false;           
-               if(backup != irqstat_reg0) do_irq(false);
+               if(backup != irqstat_reg0) do_irq();
        }
-//     if(!irqmask_printer || !flag) do_irq(flag);
+//     if(!irqmask_printer || !flag) do_irq();
 }
 
 void FM7_MAINIO::set_irq_keyboard(bool flag)
 {
        uint8 backup = irqstat_reg0;
+       //printf("MAIN: KEYBOARD: IRQ=%d MASK=%d\n", flag ,irqmask_keyboard);
        if(irqmask_keyboard) return;
        if(flag) {
-               irqstat_reg0 &= 0b11111110;
+               irqstat_reg0 &= 0xfe;
                irqstat_keyboard = true;
-               if(backup != irqstat_reg0) do_irq(true);
+       //      if(backup != irqstat_reg0) do_irq();
        } else {
-               //irqstat_reg0 &= 0b11111110;
-               irqstat_reg0 |= 0b00000001;
+               irqstat_reg0 |= 0x01;
                irqstat_keyboard = false;          
-               if(backup != irqstat_reg0) do_irq(false);
+       //      if(backup != irqstat_reg0) do_irq();
        }
-       //printf("MAIN: KEYBOARD: IRQ=%d\n", flag && !(irqmask_keyboard));
-}
-
-void FM7_MAINIO::set_keyboard(uint32 data)
-{
-       if((data & 0x100) != 0){
-               kbd_bit8 = true;
-       } else {
-               kbd_bit8 = false;
-       }
-       kbd_bit7_0 = (data & 0xff);
+       do_irq();
 }
 
 
-void FM7_MAINIO::do_irq(bool flag)
+void FM7_MAINIO::do_irq(void)
 {
        bool intstat;
        intstat = irqstat_timer | irqstat_keyboard | irqstat_printer;
@@ -254,7 +295,7 @@ void FM7_MAINIO::do_irq(bool flag)
                intstat = intstat | intstat_opn | intstat_whg | intstat_thg;
                intstat = intstat | intstat_mouse;
    
-       if(irqstat_bak == intstat) return;
+       //if(irqstat_bak == intstat) return;
        //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);
@@ -264,12 +305,12 @@ void FM7_MAINIO::do_irq(bool flag)
        irqstat_bak = intstat;
 }
 
-void FM7_MAINIO::do_firq(bool flag)
+void FM7_MAINIO::do_firq(void)
 {
        bool firq_stat;
-       firq_stat = firq_break_key || firq_sub_attention; 
+       firq_stat = firq_break_key | firq_sub_attention; 
        //printf("%08d : FIRQ: break=%d attn=%d stat = %d\n", SDL_GetTicks(), firq_break_key, firq_sub_attention, firq_stat);
-       //if(firqstat_bak == firq_stat) return;
+       if(firqstat_bak == firq_stat) return;
        if(firq_stat) {
                maincpu->write_signal(SIG_CPU_FIRQ, 1, 1);
        } else {
@@ -301,51 +342,61 @@ void FM7_MAINIO::do_nmi(bool flag)
 void FM7_MAINIO::set_break_key(bool pressed)
 {
        firq_break_key = pressed;
-       do_firq(pressed);
+       do_firq();
 }
 
 void FM7_MAINIO::set_sub_attention(bool flag)
 {
        firq_sub_attention = flag;
-       do_firq(flag); 
+       //register_event_by_clock(this, EVENT_FM7SUB_PROC, 8, false, NULL); // 1uS / 8MHz 
+//     do_firq();
+       do_sync_main_sub();
 }
   
 
 uint8 FM7_MAINIO::get_fd04(void)
 {
-       uint8 val = 0b11111100;
-       //if(!sub_busy)           val &= 0b01111111;
-       if(!firq_break_key)     val |= 0b00000010;
-       if(!firq_sub_attention) val |= 0b00000001;
-       //if(firq_sub_attention) {
-               //firq_sub_attention = false;
-       //printf("MAINIO : ATTENTION OFF\n");
+       uint8 val = 0x7c;
+       if(sub_busy) val |= 0x80;
+       if(!firq_break_key)     val |= 0x02;
+       if(!firq_sub_attention) {
+               val |= 0x01;
+       }
        set_sub_attention(false);   
-       //}
        return val;
 }
 
 void FM7_MAINIO::set_fd04(uint8 val)
 {
        // NOOP?
+#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
+       display->write_signal(SIG_DISPLAY_EXTRA_MODE, val, 0xff);
+#endif
 }
 
   // FD05
  uint8 FM7_MAINIO::get_fd05(void)
 {
-       uint8 val = 0b01111110;
-       if(sub_busy)    val |= 0b10000000;
-       if(!extdet_neg) val |= 0b00000001;
+       uint8 val;
+       val = (sub_busy) ? 0xfe : 0x7e;
+       if(!extdet_neg) val |= 0x01;
+       //printf("FD05: READ: %d VAL=%02x\n", SDL_GetTicks(), val);
        return val;
 }
 
  void FM7_MAINIO::set_fd05(uint8 val)
 {
-//     subcpu->write_signal(SIG_CPU_BUSREQ, val, 0b10000000);
-       display->write_signal(SIG_FM7_SUB_CANCEL, val, 0b01000000); // HACK
-       display->write_signal(SIG_DISPLAY_HALT,   val, 0b10000000);
+       sub_cancel = ((val & 0x40) != 0) ? true : false;
+       sub_halt   = ((val & 0x80) != 0) ? true : false;
+       //register_event_by_clock(this, EVENT_FM7SUB_PROC, 8, false, NULL); // 1uS / 8MHz
+       do_sync_main_sub();
+
+       if(sub_cancel != sub_cancel_bak) {
+               display->write_signal(SIG_FM7_SUB_CANCEL, (sub_cancel) ? 0xff : 0x00, 0xff); // HACK
+       }
+       sub_cancel_bak = sub_cancel;
 #ifdef WITH_Z80
-       if((val & 0b00000001) != 0) {
+       if((val & 0x01) != 0) {
                //maincpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
                //z80->write_signal(SIG_CPU_BUSREQ, 0, 1);
        } else {
@@ -364,14 +415,14 @@ void FM7_MAINIO::set_extdet(bool flag)
 void FM7_MAINIO::write_kanjiaddr_hi(uint8 addr)
 {
        if(!connect_kanjiroml1) return;
-       kaddress_hi = addr;
+       kaddress.b.h = addr;
        return;
 }
 
 void FM7_MAINIO::write_kanjiaddr_lo(uint8 addr)
 {
        if(!connect_kanjiroml1) return;
-       kaddress_lo = addr;
+       kaddress.b.l = addr;
        return;
 }
 
@@ -380,8 +431,9 @@ uint8 FM7_MAINIO::read_kanjidata_left(void)
        uint32 addr;
     
        if(!connect_kanjiroml1) return 0xff;
-       addr = ((uint32)kaddress_hi << 8) | (uint32)kaddress_lo;
+       addr = kaddress.w.l;
        addr = addr << 1;
+       //printf("KANJI MAIN CLASS1 ADDR: %05x\n", kaddress.w.l);
        if(kanjiclass1) {
                return kanjiclass1->read_data8(addr);
        } else {
@@ -394,8 +446,8 @@ uint8 FM7_MAINIO::read_kanjidata_right(void)
        uint32 addr;
     
        if(!connect_kanjiroml1) return 0xff;
-       addr = ((uint32)kaddress_hi << 8) | (uint32)kaddress_lo;
-       addr = (addr << 1) | 1;
+       addr = kaddress.w.l;
+       addr = (addr << 1) + 1;
        if(kanjiclass1) {
                return kanjiclass1->read_data8(addr);
        } else {
@@ -403,19 +455,19 @@ uint8 FM7_MAINIO::read_kanjidata_right(void)
        }
 }
 
-#ifdef _FM77AV_VARIANTS
+#ifdef CAPABLE_KANJICLASS2
 // Kanji ROM, FD20 AND FD21 (or SUBSYSTEM)
 void FM7_MAINIO::write_kanjiaddr_hi_l2(uint8 addr)
 {
        if(!connect_kanjiroml2) return;
-       kaddress_hi_l2 = addr;
+       kaddress_l2.b.h = addr;
        return;
 }
 
 void FM7_MAINIO::write_kanjiaddr_lo_l2(uint8 addr)
 {
        if(!connect_kanjiroml2) return;
-       kaddress_lo_l2 = addr;
+       kaddress_l2.b.l = addr;
        return;
 }
 
@@ -424,7 +476,7 @@ uint8 FM7_MAINIO::read_kanjidata_left_l2(void)
        uint32 addr;
     
        if(!connect_kanjiroml2) return 0xff;
-       addr = ((uint32)kaddress_hi_l2 << 8) | (uint32)kaddress_lo_l2;
+       addr = kaddress.w.l;
        addr = addr << 1;
        if(kanjiclass2) {
                return kanjiclass2->read_data8(addr);
@@ -438,8 +490,8 @@ uint8 FM7_MAINIO::read_kanjidata_right_l2(void)
        uint32 addr;
     
        if(!connect_kanjiroml2) return 0xff;
-       addr = ((uint32)kaddress_hi_l2 << 8) | (uint32)kaddress_lo_l2;
-       addr = (addr << 1) | 0x01;
+       addr = kaddress_l2.w.l;
+       addr = (addr << 1) + 0x01;
        if(kanjiclass2) {
                return kanjiclass2->read_data8(addr);
        } else {
@@ -456,6 +508,9 @@ void FM7_MAINIO::write_signal(int id, uint32 data, uint32 mask)
        val_b = ((data & mask) != 0);
   
        switch(id) {
+               case FM7_MAINIO_SUB_BUSY:
+                       sub_busy = val_b;
+                       break;
                case FM7_MAINIO_CLOCKMODE: // fd00
                        if(val_b) {
                                clock_fast = true;
@@ -494,13 +549,8 @@ void FM7_MAINIO::write_signal(int id, uint32 data, uint32 mask)
                                        clocks = 1095000; // Hz
                                }
 #endif
-                               if(clock_fast) {
-                                       subclocks = 2000000; // Hz
-                               } else {
-                                       subclocks =  999000; // Hz
-                               }
                                p_vm->set_cpu_clock(this->maincpu, clocks);
-                               p_vm->set_cpu_clock(this->subcpu,  subclocks);
+                               display->write_signal(SIG_DISPLAY_CLOCK, clock_fast ? 1 : 0, 1);
                        }
                        break;
                case FM7_MAINIO_CMT_RECV: // FD02
@@ -516,22 +566,19 @@ void FM7_MAINIO::write_signal(int id, uint32 data, uint32 mask)
                        set_irq_printer(val_b);
                        break;
                case FM7_MAINIO_KEYBOARDIRQ: //
-                       set_irq_keyboard(val_b);
-                       break;
-               case FM7_MAINIO_PUSH_KEYBOARD:
-                       set_keyboard(data & 0x1ff);
+                       key_irq_req = val_b;
+                       if(val_b) keycode_7 = data & 0x3ff;
+                       set_irq_keyboard(key_irq_req);
+                       keycode = keycode_7;
                        break;
                        // FD04
                case FM7_MAINIO_PUSH_BREAK:
                        set_break_key(val_b);
                        break;
                case FM7_MAINIO_SUB_ATTENTION:
-                       set_sub_attention(val_b);
+                       if(val_b) set_sub_attention(true);
                        break;
                        // FD05
-               case FM7_MAINIO_SUB_BUSY:
-                       sub_busy = val_b;
-                       break;
                case FM7_MAINIO_EXTDET:
                        extdet_neg = !val_b;
                        break;
@@ -549,17 +596,17 @@ void FM7_MAINIO::write_signal(int id, uint32 data, uint32 mask)
                case FM7_MAINIO_OPN_IRQ:
                        if(!connect_opn) break;
                        intstat_opn = val_b;
-                       do_irq(val_b);
+                       do_irq();
                                break;
                case FM7_MAINIO_WHG_IRQ:
                        if(!connect_whg) break;
                        intstat_whg = val_b;
-                       do_irq(val_b);
+                       do_irq();
                                break;
                case FM7_MAINIO_THG_IRQ:
                        if(!connect_thg) break;
                        intstat_thg = val_b;
-                       do_irq(val_b);
+                       do_irq();
                                break;
                case FM7_MAINIO_FDC_DRQ:
                        set_drq_mfd(val_b);
@@ -567,6 +614,20 @@ void FM7_MAINIO::write_signal(int id, uint32 data, uint32 mask)
                case FM7_MAINIO_FDC_IRQ:
                        set_irq_mfd(val_b);
                        break;
+               case FM7_MAINIO_KANJI1_ADDR_HIGH:
+                       kaddress.b.h = data;
+                       break;
+               case FM7_MAINIO_KANJI1_ADDR_LOW:
+                       kaddress.b.l = data;
+                       break;
+#if defined(CAPABLE_KANJI_CLASS2)
+               case FM7_MAINIO_KANJI2_ADDR_HIGH:
+                       kaddress_l2.b.h = data;
+                       break;
+               case FM7_MAINIO_KANJI2_ADDR_LOW:
+                       kaddress_l2.b.l = data;
+                       break;
+#endif
        }
        
 }
@@ -581,13 +642,11 @@ void FM7_MAINIO::write_signal(int id, uint32 data, uint32 mask)
        
        //extirq = extirq | intstat_syndet | intstat_rxrdy | intstat_txrdy;
        if(extirq) {
-               irqstat_reg0 &= 0b11110111;
-               //irqstat_reg0 |= 0b00001000;
+               irqstat_reg0 &= ~0x08;
        } else {
-               irqstat_reg0 |= 0b00001000;
-               //irqstat_reg0 &= 0b11110111;
+               irqstat_reg0 |= 0x08;
        }
-       val = irqstat_reg0;
+       val = irqstat_reg0 | 0xf0;
        set_irq_timer(false);
        set_irq_printer(false);
        return val;
@@ -596,23 +655,35 @@ void FM7_MAINIO::write_signal(int id, uint32 data, uint32 mask)
 uint8 FM7_MAINIO::get_extirq_fd17(void)
 {
        uint8 val = 0xff;
-       if(intstat_opn)   val &= 0b11110111;
-       if(intstat_mouse) val &= 0b11111011;
+       if(intstat_opn)   val &= ~0x08;
+       if(intstat_mouse) val &= ~0x04;
        //if(!intstat_opn && !intstat_mouse) do_irq(false);
        return val;
 }
 
 void FM7_MAINIO::set_ext_fd17(uint8 data)
 {
-       if((data & 0b00000100) != 0) {
+       if((data & 0x04) != 0) {
                mouse_enable = true;
        } else {
                mouse_enable = false;
        }
    
 }
+#if defined(_FM77AV_VARIANTS)
+// FD12
+uint8 FM7_MAINIO::subsystem_read_status(void)
+{
+       uint8 retval;
+       //retval = (display->read_signal(SIG_DISPLAY_MODE320) != 0) ? 0x40 : 0;
+       retval = (mode320) ? 0x40 : 0;
+       retval |= display->read_signal(SIG_DISPLAY_VSYNC);
+       retval |= display->read_signal(SIG_DISPLAY_DISPLAY);
+       retval |= ~0x43;
+       return retval;
+}
+#endif
 
-   
 uint32 FM7_MAINIO::read_signal(uint32 addr)
 {
        uint32 retval = 0xffffffff;
@@ -624,7 +695,6 @@ uint32 FM7_MAINIO::read_signal(uint32 addr)
 uint32 FM7_MAINIO::read_data8(uint32 addr)
 {
        uint32 retval;
-
        if(addr == FM7_MAINIO_IS_BASICROM) {
                retval = 0;
                if(stat_bootsw_basic) retval = 0xffffffff;
@@ -632,7 +702,7 @@ uint32 FM7_MAINIO::read_data8(uint32 addr)
        } else if(addr == FM7_MAINIO_BOOTMODE) {
                retval = bootmode & 0x03;
 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4) || defined(_FM77AV_VARIANTS)
-               if(bootram) retval = 4;
+               if(boot_ram) retval = 4;
 #endif
                return retval;
        } else if(addr == FM7_MAINIO_READ_FD0F) {
@@ -648,16 +718,38 @@ uint32 FM7_MAINIO::read_data8(uint32 addr)
        } else if(addr == FM7_MAINIO_WINDOW_ENABLED) {
                retval = (window_enabled) ? 0xffffffff:0x00000000;
                return retval;
+       } else if(addr == FM7_MAINIO_WINDOW_OFFSET) {
+               retval = (uint32)window_offset;
+               return retval;
        } else if(addr == FM7_MAINIO_MMR_SEGMENT) {
                retval = (uint32) mmr_segment;
                return retval;
-       } else if((addr >= FM7_MAINIO_MMR_BANK) &&  (addr < (FM7_MAINIO_MMR_BANK + 64))) {
-               retval = (uint32)mmr_table[addr - FM7_MAINIO_MMR_BANK];
+       } else if((addr >= FM7_MAINIO_MMR_BANK) &&  (addr < (FM7_MAINIO_MMR_BANK + 16))) {
+#if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
+               retval = (uint32)mmr_table[(addr - FM7_MAINIO_MMR_BANK) | (mmr_segment & 7) * 16];
+#else  
+               retval = (uint32)mmr_table[(addr - FM7_MAINIO_MMR_BANK) | (mmr_segment & 3)  * 16] & 0x3f;
+#endif
                return retval;
        }
 #endif
 #if defined(_FM77AV_VARIANTS)
        else if(addr == FM7_MAINIO_INITROM_ENABLED) {
+               retval = (enable_initiator) ? 0xffffffff : 0x00000000;
+               return retval;
+       } else if(addr == FM7_MAINIO_MODE320) {
+               retval = (mode320) ? 0xffffffff : 0x00000000;
+               return retval;
+       } else if(addr == FM7_MAINIO_SUBMONITOR_ROM) {
+               retval = sub_monitor_type & 0x03;
+               return retval;
+       }  else if(addr == FM7_MAINIO_SUBMONITOR_RAM) {
+#if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
+               retval = ((sub_monitor_type & 0x04) != 0) ? 0xffffffff : 0x00000000;
+#else
+               retval = 0;
+#endif
+               return retval;
        }
 #endif
 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
@@ -665,16 +757,28 @@ uint32 FM7_MAINIO::read_data8(uint32 addr)
        } else if(addr == FM7_MAINIO_EXTROM) {
        }
 #endif
+       //if((addr >= 0x0006) && (addr != 0x1f)) printf("MAINIO: READ: %08x DATA=%08x\n", addr);
        addr = addr & 0xff;
        retval = 0xff;
+#if defined(HAS_MMR)
+       if((addr < 0x90) && (addr >= 0x80)) {
+#if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
+               return mmr_table[addr - 0x80 + mmr_segment * 16];
+#else
+               return mmr_table[addr - 0x80 + (mmr_segment & 0x03) * 16];
+#endif   
+       }
+#endif
+       //      if((addr >= 0x0006) && !(addr == 0x1f) && !(addr == 0x0b)) printf("MAINIO: READ: %08x \n", addr);
        switch(addr) {
                case 0x00: // FD00
                        retval = (uint32) get_port_fd00();
                        break;
                case 0x01: // FD01
+                       retval = keycode & 0xff;
+                       key_irq_req = false;
                        display->write_signal(SIG_FM7_SUB_KEY_FIRQ, 0, 1);
-                       set_irq_keyboard(false);
-                       retval = (uint32) kbd_bit7_0;
+                       set_irq_keyboard(key_irq_req);
                        break;
                case 0x02: // FD02
                        retval = (uint32) get_port_fd02();
@@ -695,37 +799,56 @@ uint32 FM7_MAINIO::read_data8(uint32 addr)
                case 0x09:
                case 0x0a:
                        break;
+#if defined(_FM77AV_VARIANTS)
+               case 0x0b:
+                       retval = (bootmode == 0) ? 0xfe : 0xff;
+                       break;
+#endif                 
                case 0x0e: // PSG DATA
                        retval = (uint32) get_psg();
+                       //printf("PSG DATA READ val=%02x\n", retval);
                        break;
                case 0x0f: // FD0F
                        read_fd0f();
+                       retval = 0xff;
+                       break;
+#if defined(_FM77AV_VARIANTS)
+               case 0x12:
+                       retval = subsystem_read_status();  
                        break;
+#endif
                case 0x15: // OPN CMD
+                       //printf("OPN CMD READ \n");
                        break;
                case 0x16: // OPN DATA
                        retval = (uint32) get_opn(0);
+                       //printf("OPN DATA READ val=%02x\n", retval);
                        break;
                case 0x17:
                        retval = (uint32) get_extirq_fd17();
                        break;
                case 0x18: // FDC: STATUS
                        retval = (uint32) get_fdc_stat();
+                       //printf("FDC: READ STATUS %02x PC=%04x\n", retval, maincpu->get_pc()); 
                        break;
                case 0x19: // FDC: Track
                        retval = (uint32) get_fdc_track();
+                       //printf("FDC: READ TRACK REG %02x\n", retval); 
                        break;
                case 0x1a: // FDC: Sector
                        retval = (uint32) get_fdc_sector();
+                       //printf("FDC: READ SECTOR REG %02x\n", retval); 
                        break;
                case 0x1b: // FDC: Data
                        retval = (uint32) get_fdc_data();
                        break;
                case 0x1c:
                        retval = (uint32) get_fdc_fd1c();
+                       //printf("FDC: READ HEAD REG %02x\n", retval); 
                        break;
                case 0x1d:
                        retval = (uint32) get_fdc_motor();
+                       //printf("FDC: READ MOTOR REG %02x\n", retval); 
                        break;
                case 0x1f:
                        retval = (uint32) fdc_getdrqirq();
@@ -736,7 +859,7 @@ uint32 FM7_MAINIO::read_data8(uint32 addr)
                case 0x23: // Kanji ROM
                        retval = (uint32) read_kanjidata_right();
                        break;
-#if defined(_FM77AV_VARIANTS)
+#if defined(CAPABLE_KANJI_CLASS2)
                case 0x2e: // Kanji ROM Level2
                        retval = (uint32) read_kanjidata_left_l2();
                        break;
@@ -763,6 +886,14 @@ uint32 FM7_MAINIO::read_data8(uint32 addr)
                case 0x53:
                        retval = (uint32) get_extirq_thg();
                        break;
+#if defined(HAS_MMR)
+               case 0x93:
+                       retval = 0x3e;
+                       if(boot_ram) retval |= 0x01;
+                       if(window_enabled) retval |= 0x40;
+                       if(mmr_enabled) retval |= 0x80;
+                       break;
+#endif
                default:
                        //printf("MAIN: Read another I/O Addr=%08x\n", addr); 
                        break;
@@ -777,6 +908,7 @@ uint32 FM7_MAINIO::read_data8(uint32 addr)
 
 void FM7_MAINIO::write_data8(uint32 addr, uint32 data)
 {
+       bool flag;
        if(addr == FM7_MAINIO_BOOTMODE) {
                bootmode = data & 0x03;
                return;
@@ -784,9 +916,22 @@ void FM7_MAINIO::write_data8(uint32 addr, uint32 data)
                set_clockmode((uint8)data);
                return;
        }
+       //if((addr >= 0x0006) && !(addr == 0x1f)) printf("MAINIO: WRITE: %08x DATA=%08x\n", addr, data);
        
        data = data & 0xff;
        addr = addr & 0xff;
+       io_w_latch[addr] = data;
+#if defined(HAS_MMR)
+        if((addr < 0x90) && (addr >= 0x80)) {
+#if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
+               mmr_table[addr - 0x80 + mmr_segment * 16] = data;
+#else
+               mmr_table[addr - 0x80 + (mmr_segment & 0x03) * 16] = data & 0x3f;
+#endif
+               //printf("MMR: Write access segment=%02x addr=%02x page=%02x\n", mmr_segment, addr - 0x80, data);
+               return;
+       }
+#endif
        switch(addr) {
                case 0x00: // FD00
                        set_port_fd00((uint8)data);
@@ -815,18 +960,42 @@ void FM7_MAINIO::write_data8(uint32 addr, uint32 data)
                case 0x0a:
                        break;
                case 0x0d:
+                       //printf("PSG CMD WRITE val=%02x\n", data);
                        set_psg_cmd(data);
                        break;
                case 0x0e:
+                       //printf("PSG DATA WRITE val=%02x\n", data);
                        set_psg(data);
                        break;
                case 0x0f: // FD0F
                        write_fd0f();
                        break;
+#if defined(_FM77AV_VARIANTS)
+               case 0x10:
+                       flag = enable_initiator;
+                       //printf("INITIATOR ENABLE = %02x\n", data);
+                       enable_initiator = ((data & 0x02) == 0) ? true : false;
+                       if(flag != enable_initiator) {
+                         mainmem->reset();
+                         //this->reset();
+                       }
+                       break;
+               case 0x12:
+                       mode320 = ((data & 0x40) != 0);
+                       display->write_signal(SIG_DISPLAY_MODE320, data,  0x40);
+                       break;
+               case 0x13:
+                       sub_monitor_type = data & 0x07;
+                       //register_event_by_clock(this, EVENT_FM7SUB_PROC, 8, false, NULL); // 1uS / 8MHz
+                       do_sync_main_sub();
+                       break;
+#endif
                case 0x15: // OPN CMD
+                       //printf("OPN CMD WRITE val=%02x\n", data);
                        set_opn_cmd(0, data);
                        break;
                case 0x16: // OPN DATA
+                       //printf("OPN DATA WRITE val=%02x\n", data);
                        set_opn(0, data);
                        break;
                case 0x17:
@@ -834,41 +1003,63 @@ void FM7_MAINIO::write_data8(uint32 addr, uint32 data)
                        break;
                case 0x18: // FDC: COMMAND
                        set_fdc_cmd((uint8)data);
+                       //printf("FDC: WRITE CMD %02x\n", data); 
                        break;
                case 0x19: // FDC: Track
                        set_fdc_track((uint8)data);
+                       //printf("FDC: WRITE TRACK REG %02x\n", data); 
                        break;
                case 0x1a: // FDC: Sector
                        set_fdc_sector((uint8)data);
+                       //printf("FDC: WRITE SECTOR REG %02x\n", data); 
                        break;
                case 0x1b: // FDC: Data
                        set_fdc_data((uint8)data);
                        break;
                case 0x1c:
                        set_fdc_fd1c((uint8)data);
+                       //printf("FDC: WRITE HEAD REG %02x\n", data); 
                        break;
                case 0x1d:
                        set_fdc_fd1d((uint8)data);
+                       //printf("FDC: WRITE MOTOR REG %02x\n", data); 
                        break;
                case 0x1f: // ??
                        return;
                        break;
                case 0x20: // Kanji ROM
+               case 0x2c: // Kanji ROM(DUP)
                        write_kanjiaddr_hi((uint8)data);
+#if defined(CAPABLE_KANJI_CLASS2)
+                       write_kanjiaddr_hi_l2((uint8)data);
+#endif
                        break;
                case 0x21: // Kanji ROM
+               case 0x2d: // Kanji ROM(DUP)
                        write_kanjiaddr_lo((uint8)data);
+#if defined(CAPABLE_KANJI_CLASS2)
+                       write_kanjiaddr_lo_l2((uint8)data);
+#endif
                        break;
 #if defined(_FM77AV_VARIANTS)
-               case 0x2c: // Kanji ROM
-                       write_kanjiaddr_hi_l2((uint8)data);
+               case 0x30:
+                       display->write_data8(FM7_SUBMEM_OFFSET_APALETTE_HI, data);
                        break;
-               case 0x2d: // Kanji ROM
-                       write_kanjiaddr_lo_l2((uint8)data);
+               case 0x31:
+                       display->write_data8(FM7_SUBMEM_OFFSET_APALETTE_LO, data);
+                       break;
+               case 0x32:
+                       display->write_data8(FM7_SUBMEM_OFFSET_APALETTE_B, data);
+                       break;
+               case 0x33:
+                       display->write_data8(FM7_SUBMEM_OFFSET_APALETTE_R, data);
+                       break;
+               case 0x34:
+                       display->write_data8(FM7_SUBMEM_OFFSET_APALETTE_G, data);
                        break;
 #endif
                case 0x37: // Multi page
-                       display->write_signal(SIG_FM7_SUB_MULTIPAGE, data, 0x00ff);
+                       display->write_signal(SIG_DISPLAY_MULTIPAGE, data, 0x00ff);
                        break;
                case 0x45: // WHG CMD
                        set_opn_cmd(1, data);
@@ -886,7 +1077,18 @@ void FM7_MAINIO::write_data8(uint32 addr, uint32 data)
                        break;
                case 0x53:
                        break;
-#if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4) || defined(_FM77AV_VARIANTS)
+#if defined(HAS_MMR)
+               case 0x90:
+#if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
+                       mmr_segment = data & 7;
+#else
+                       //                      printf("MMR SEGMENT: %02x\n", data & 3);
+                       mmr_segment = data & 3;
+#endif                 
+                       break;
+               case 0x92:
+                       window_offset = data & 0x00ff;
+                       break;
                case 0x93:
                        if((data & 0x01) == 0) {
                                boot_ram = false;
@@ -897,12 +1099,16 @@ void FM7_MAINIO::write_data8(uint32 addr, uint32 data)
                                window_enabled = false;
                        } else {
                                window_enabled = true;
-                       }         
+                       }
+                       flag = mmr_enabled;
                        if((data & 0x80) == 0) {
                                mmr_enabled = false;
                        } else {
                                mmr_enabled = true;
                        }
+                       if(flag != mmr_enabled) {
+                               this->write_signal(FM7_MAINIO_CLOCKMODE, clock_fast ? 1 : 0, 1);
+                       }
                        break;
 #endif
                default:
@@ -932,7 +1138,7 @@ void FM7_MAINIO::event_callback(int event_id, int err)
                        break;
                case EVENT_TIMERIRQ_ON:
                        if(!irqmask_timer) set_irq_timer(true);
-                       register_event(this, EVENT_TIMERIRQ_OFF, 10000.0 / (4.9152 * 2.0) , false, NULL); // TIMER IRQ
+                       //register_event(this, EVENT_TIMERIRQ_OFF, 10000.0 / (4.9152 * 2.0) , false, NULL); // TIMER IRQ
                        break;
                case EVENT_TIMERIRQ_OFF:
                        if(!irqmask_timer) set_irq_timer(false);
@@ -944,9 +1150,61 @@ void FM7_MAINIO::event_callback(int event_id, int err)
                case EVENT_FD_MOTOR_OFF:
                        set_fdc_motor(false);
                        break;
+               case EVENT_FM7SUB_PROC:
+                       proc_sync_to_sub();
+                       break;
                default:
                        break;
        }
 }
 
 
+void FM7_MAINIO::update_config()
+{
+       switch(config.cpu_type){
+               case 0:
+                       clock_fast = true;
+                       break;
+               case 1:
+                       clock_fast = false;
+                       break;
+       }
+       //      this->write_signal(FM7_MAINIO_CLOCKMODE, clock_fast ? 1 : 0, 1);
+}
+
+void FM7_MAINIO::event_vline(int v, int clock)
+{
+}
+
+void FM7_MAINIO::do_sync_main_sub(void)
+{
+       register_event_by_clock(this, EVENT_FM7SUB_PROC, 8, false, NULL); // 1uS
+       register_event_by_clock(display, EVENT_FM7SUB_PROC, 8, false, NULL); // 1uS
+}      
+
+
+void FM7_MAINIO::proc_sync_to_sub(void)
+{
+       if(sub_halt != sub_halt_bak) {
+               display->write_signal(SIG_DISPLAY_HALT,  (sub_halt) ? 0xff : 0x00, 0xff);
+       }
+       sub_halt_bak = sub_halt;
+       if(firq_sub_attention != firq_sub_attention_bak){
+               do_firq();
+       }
+       firq_sub_attention_bak = firq_sub_attention;
+       //sub_cancel_bak = sub_cancel;
+       //if(key_irq_req != key_irq_bak) {
+       //      set_irq_keyboard(key_irq_req);
+       //}
+       //key_irq_bak = key_irq_req;
+       //keycode = keycode_7;
+#if defined(_FM77AV_VARIANTS)
+       if(sub_monitor_type != sub_monitor_bak) {
+               display->write_signal(SIG_FM7_SUB_BANK, sub_monitor_type, 0x07);
+       }
+       sub_monitor_bak = sub_monitor_type;
+#endif
+}
+
+