OSDN Git Service

[VM] TRY:Use namespace {VMNAME} to separate around VMs. This feature still apply...
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / display.cpp
index 2fcb663..e2a336e 100644 (file)
 #if defined(_FM77AV_VARIANTS)
 # include "mb61vh010.h"
 #endif
+#if defined(_FM77L4)
+#include "../hd46505.h"
+#endif
+
+#include "fm7_mainio.h"
+#include "./fm7_keyboard.h"
+#include "./kanjirom.h"
 
-DISPLAY::DISPLAY(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
+namespace FM7 {
+       
+DISPLAY::DISPLAY(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
 {
-       p_vm = parent_vm;
-       p_emu = parent_emu;
        ins_led = NULL;
        kana_led = NULL;
        caps_led = NULL;
@@ -51,6 +58,10 @@ DISPLAY::DISPLAY(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
        }
        displine = 0;
        active_page = 0;
+#if defined(USE_GREEN_DISPLAY)
+       use_green_monitor = false;
+#endif
+       force_update = true;
        set_device_name(_T("DISPLAY SUBSYSTEM"));
 }
 
@@ -59,12 +70,12 @@ DISPLAY::~DISPLAY()
 
 }
 
-void DISPLAY::reset_cpuonly()
+void DISPLAY::reset_some_devices()
 {
        int i;
        double usec;
-       keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
-       mainio->write_signal(SIG_FM7_SUB_HALT, 0x00, 0xff);
+       call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
+       call_write_signal(mainio, SIG_FM7_SUB_HALT, 0x00, 0xff);
        sub_busy = true;
        
        palette_changed = true;
@@ -74,8 +85,9 @@ void DISPLAY::reset_cpuonly()
                multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
                multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
        }
-       firq_mask = false;
+       //firq_mask = false; // 20180215 Thanks to Ryu takegami.
        //cancel_request = false;
+       is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
        switch(config.cpu_type){
                case 0:
                        clock_fast = true;
@@ -103,35 +115,41 @@ void DISPLAY::reset_cpuonly()
        displine = 0;
        active_page = 0;
        
-#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
+//#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
+#if 1
        vsync = true;
        vblank = true;
        hblank = false;
        vblank_count = 0;
-       
+
        if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
        if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
+
        if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
        if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
        hblank_event_id = -1;
        hdisp_event_id = -1;
        vsync_event_id = -1;
        vstart_event_id = -1;
-       if(display_mode == DISPLAY_MODE_8_400L) {
+#endif
+       if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
                usec = 0.33 * 1000.0; 
+               vm->set_vm_frame_rate(55.40);
        } else {
                usec = 0.51 * 1000.0;
+               vm->set_vm_frame_rate(FRAMES_PER_SEC);
        }
        //usec = 16.0;
-       register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
-       mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
-       mainio->write_signal(SIG_DISPLAY_VSYNC, 0xff, 0xff);
-#endif
+       //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
+       call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
+       call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0xff, 0xff);
+//#endif
+       display_page = 0;
+       display_page_bak = 0;
+
 #if defined(_FM77AV_VARIANTS)
        offset_77av = false;
        offset_point_bank1 = 0;
-       display_page = 0;
-       display_page_bak = 0;
        
        subcpu_resetreq = false;
        subrom_bank_using = subrom_bank;
@@ -155,20 +173,23 @@ void DISPLAY::reset_cpuonly()
        
        alu->reset();
 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
-       alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400: 200, 0xffff);
-       alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xffffffff : 0, 0xffffffff);
+       call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
+       call_write_signal(alu, SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400: 200, 0xffff);
+       call_write_signal(alu, SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xffffffff : 0, 0xffffffff);
 # else
-       alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
-       alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
-       alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
+       call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
+       call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
+       call_write_signal(alu, SIG_ALU_400LINE, 0, 0xffffffff);
 # endif
-       alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
-       alu->write_signal(SIG_ALU_PLANES, 3, 3);
-       
+       call_write_signal(alu, SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
+       call_write_signal(alu, SIG_ALU_PLANES, 3, 3);
 #endif
        for(i = 0; i < 8; i++) set_dpalette(i, i);
-       do_firq(!firq_mask && key_firq_req);
+#if defined(USE_GREEN_DISPLAY)
+       memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
+#endif
+       memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
+       //do_firq(!firq_mask && key_firq_req);
 
 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
        //kanjisub = false; // Fixed by Ryu takegami
@@ -179,18 +200,19 @@ void DISPLAY::reset_cpuonly()
 # endif        
 #endif
        vram_wrote = true;
-       clr_count = 0;
+       delay_busy = false;
        frame_skip_count_draw = 3;
        frame_skip_count_transfer = 3;
        need_transfer_line = true;
        setup_display_mode();
+
 }
 
 
 void DISPLAY::reset()
 {
        int i;
-       memset(io_w_latch, 0xff, sizeof(io_w_latch));
+       //printf("RESET\n");
        halt_flag = false;
        vram_accessflag = true;
        display_mode = DISPLAY_MODE_8_200L;
@@ -198,7 +220,6 @@ void DISPLAY::reset()
        crt_flag = false; // Fixed by Ryu Takegami
        screen_update_flag = true;
        crt_flag_bak = false;
-       
        cancel_request = false;
 #if defined(_FM77AV_VARIANTS)
        mode320 = false;
@@ -208,6 +229,7 @@ void DISPLAY::reset()
                analog_palette_g[i] = (i & 0xf00) >> 4;
                analog_palette_b[i] = (i & 0x00f) << 4;
                calc_apalette(i);
+               memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
        }
        subrom_bank = 0;
        cgrom_bank = 0;
@@ -220,16 +242,58 @@ void DISPLAY::reset()
 # endif
 #elif defined(_FM77L4)
        mode400line = false;
+       stat_400linecard = false;
+       
+       workram_l4 = false;
+       cursor_lsb = false;
+    text_width40 = false;
+       
+       text_blink = true;
+       cursor_blink = true;
+       
+       text_start_addr.d = 0x0000;
+       text_lines = 64;
+       text_xmax = 80;
+       
+       cursor_addr.d = 0;
+       cursor_start = 0;
+       cursor_end = 0;
+       cursor_type = 0;
+       text_scroll_count = 0;
+
+       cursor_blink = true;
+       {
+               // OK?
+               double usec;
+               uint8_t *regs = l4crtc->get_regs();
+               display_mode = DISPLAY_MODE_1_400L;
+               if(event_id_l4_cursor_blink >= 0) {
+                       cancel_event(this, event_id_l4_cursor_blink);
+               }
+               if(event_id_l4_text_blink >= 0) {
+                       cancel_event(this, event_id_l4_text_blink);
+               }
+               event_id_l4_cursor_blink = -1;
+               event_id_l4_text_blink = -1;
+               if(regs != NULL) {
+                       usec = ((regs[10] & 0x20) == 0) ? 160.0 : 320.0;
+                       usec = usec * 1000.0;
+                       register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
+                       usec = 160.0 * 1000.0;
+                       register_event(this, EVENT_FM7SUB_TEXT_BLINK, true, usec, &event_id_l4_cursor_blink);
+               }                                               
+       }
+       //memset(crtc_regs, 0x00, sizeof(crtc_regs));
 #endif
+
 #if !defined(FIXED_FRAMEBUFFER_SIZE)
        emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
 #else
        emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
 #endif 
-       is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
-       key_firq_req = false;   //firq_mask = true;
-       firq_mask = false;
-       reset_cpuonly();
+       emu->set_vm_screen_lines(200);
+       
+       reset_some_devices();
        
 #if defined(_FM77AV_VARIANTS)
        power_on_reset = false;
@@ -238,23 +302,45 @@ void DISPLAY::reset()
 #else
 # if defined(_FM8)
        for(i = 0; i < 8; i++) set_dpalette(i, i);
-       //multimode_accessmask = 0x00;
-       //multimode_dispmask = 0x00;
-       //for(i = 0; i < 4; i++) {
-       //      multimode_accessflags[i] = ((multimode_accessmask & (1 << color)) != 0) ? true : false;
-       //      multimode_dispflags[i] = ((multimode_dispmask & (1 << color)) != 0) ? true : false;
-       //}
 # endif
 #endif 
+#if defined(USE_GREEN_DISPLAY) && defined(USE_MONITOR_TYPE)
+       memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
+       switch(config.monitor_type) {
+       case FM7_MONITOR_GREEN:
+               use_green_monitor = true;
+               break;
+       case FM7_MONITOR_STANDARD:
+       default:
+               use_green_monitor = false;
+               break;
+       }
+#else
+       //use_green_monitor = false;
+#endif
+       force_update = true;
+       
+       memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
        //enter_display();
        
        if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
        register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
-       subcpu->write_signal(SIG_CPU_HALTREQ, 0, 1);
-       subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
-       subcpu->reset();
+       
+       firq_mask = false;
+       key_firq_req = false;
+       do_firq(false);
+       reset_subcpu(true);
 }
 
+void DISPLAY::reset_subcpu(bool _check_firq)
+{
+       call_write_signal(subcpu, SIG_CPU_HALTREQ, 0, 1);
+       call_write_signal(subcpu, SIG_CPU_BUSREQ, 0, 1);
+       subcpu->reset();
+       if(_check_firq) {
+               do_firq(!firq_mask && key_firq_req);
+       }
+}
 void DISPLAY::setup_display_mode(void)
 {
 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
@@ -304,12 +390,14 @@ void DISPLAY::setup_display_mode(void)
                page_offset = 0x0000;
        }
 #elif defined(_FM77L4)
-       if(display_mode == DISPLAY_MODE_8_400L) {
-               page_mask = 0x1fff;
-               pagemod_mask = 0xe000;
+       if(display_mode == DISPLAY_MODE_1_400L) {
+               page_mask = 0x7fff;
+               pagemod_mask = 0x0000;
+               page_offset = 0x0000;
        } else { // 640x200, 8colors
                page_mask = 0x3fff;
                pagemod_mask = 0xc000;
+               page_offset = 0x0000;
        }
        page_offset = 0x0000;
 #else
@@ -318,9 +406,12 @@ void DISPLAY::setup_display_mode(void)
        page_mask = 0x3fff;
 #endif
 }
+
 void DISPLAY::update_config()
 {
        vram_wrote = true;
+
+               
 #if !defined(_FM8)
        is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
 #endif 
@@ -333,12 +424,12 @@ void DISPLAY::update_config()
 
 void DISPLAY::do_irq(bool flag)
 {
-       subcpu->write_signal(SIG_CPU_IRQ, flag ? 1: 0, 1);
+       call_write_signal(subcpu, SIG_CPU_IRQ, flag ? 1: 0, 1);
 }
 
 void DISPLAY::do_firq(bool flag)
 {
-       subcpu->write_signal(SIG_CPU_FIRQ, flag ? 1: 0, 1);
+       call_write_signal(subcpu, SIG_CPU_FIRQ, flag ? 1: 0, 1);
 }
 
 void DISPLAY::do_nmi(bool flag)
@@ -346,7 +437,7 @@ void DISPLAY::do_nmi(bool flag)
 #if defined(_FM77AV_VARIANTS)
        if(!nmi_enable) flag = false;
 #endif
-       subcpu->write_signal(SIG_CPU_NMI, flag ? 1 : 0, 1);
+       call_write_signal(subcpu, SIG_CPU_NMI, flag ? 1 : 0, 1);
 }
 
 void DISPLAY::set_multimode(uint8_t val)
@@ -360,7 +451,7 @@ void DISPLAY::set_multimode(uint8_t val)
        }
        vram_wrote = true;
 # if defined(_FM77AV_VARIANTS)
-       alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
+       call_write_signal(alu, SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
 # endif
 #endif 
 }
@@ -392,7 +483,13 @@ void DISPLAY::set_dpalette(uint32_t addr, uint8_t val)
        r =  ((val & 0x02) != 0x00)? 255 : 0x00;
        g =  ((val & 0x04) != 0x00)? 255 : 0x00;
        
-       dpalette_pixel[addr] = RGB_COLOR(r, g, b);
+       dpalette_pixel_tmp[addr] = RGB_COLOR(r, g, b);
+#if defined(USE_GREEN_DISPLAY)
+       static const scrntype_t colortable[8] = {0, 48, 70, 100, 140, 175, 202, 255};
+       g = colortable[val & 0x07];
+       b = r = ((val & 0x07) > 4) ? 48 : 0;
+       dpalette_green_tmp[addr] = RGB_COLOR(r, g, b);
+#endif 
        palette_changed = true;
 }
 
@@ -411,52 +508,53 @@ uint8_t DISPLAY::get_dpalette(uint32_t addr)
 
 void DISPLAY::halt_subcpu(void)
 {
-       //subcpu->write_signal(SIG_CPU_BUSREQ, 0x01, 0x01);
-       subcpu->write_signal(SIG_CPU_HALTREQ, 0x01, 0x01);
+       //call_write_signal(subcpu, SIG_CPU_BUSREQ, 0x01, 0x01);
+       call_write_signal(subcpu, SIG_CPU_HALTREQ, 0x01, 0x01);
 }
 
 void DISPLAY::go_subcpu(void)
 {
-       subcpu->write_signal(SIG_CPU_HALTREQ, 0x00, 0x01);
+       call_write_signal(subcpu, SIG_CPU_HALTREQ, 0x00, 0x01);
 }
 
 void DISPLAY::enter_display(void)
 {
        uint32_t subclock;
+       
        if(clock_fast) {
                subclock = SUBCLOCK_NORMAL;
        } else {
                subclock = SUBCLOCK_SLOW;
        }
-       if(!is_cyclesteal && vram_accessflag) {
+       if(!(is_cyclesteal) && (vram_accessflag)) {
                subclock = subclock / 3;
        }
-       if(prev_clock != subclock) p_vm->set_cpu_clock(subcpu, subclock);
+       if(prev_clock != subclock) {
+               vm->set_cpu_clock(subcpu, subclock);
+       }
        prev_clock = subclock;
 }
 
+
 void DISPLAY::leave_display(void)
 {
 }
 
 void DISPLAY::halt_subsystem(void)
 {
-       halt_flag = false;
+       //halt_flag = false;
        halt_subcpu();
 }
 
 void DISPLAY::restart_subsystem(void)
 {
-       halt_flag = false;
+       //halt_flag = false;
 #if defined(_FM77AV_VARIANTS)
        if(subcpu_resetreq) {
-               firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
-               reset_cpuonly();
+               //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
+               reset_some_devices();
                power_on_reset = true;
-               subcpu->write_signal(SIG_CPU_HALTREQ, 0, 1);
-               subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
-               subcpu->reset();
-               do_firq(!firq_mask && key_firq_req);
+               reset_subcpu(true);
        }
 #endif
        go_subcpu();
@@ -487,7 +585,7 @@ uint8_t DISPLAY::acknowledge_irq(void)
 //SUB:D403:R
 uint8_t DISPLAY::beep(void)
 {
-       mainio->write_signal(FM7_MAINIO_BEEP, 0x01, 0x01);
+       call_write_signal(mainio, FM7_MAINIO_BEEP, 0x01, 0x01);
        return 0xff; // True?
 }
 
@@ -495,7 +593,7 @@ uint8_t DISPLAY::beep(void)
 // SUB:D404 : R 
 uint8_t DISPLAY::attention_irq(void)
 {
-       mainio->write_signal(FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
+       call_write_signal(mainio, FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
        return 0xff;
 }
 
@@ -511,15 +609,64 @@ void DISPLAY::set_cyclesteal(uint8_t val)
        } else {
                is_cyclesteal = false;
        }
-       enter_display();
-# endif        
+   enter_display();
+# endif
 #endif
 }
 
+void DISPLAY::setup_400linemode(uint8_t val)
+{
+#if defined(_FM77L4)
+       // 400Line board.
+       cursor_lsb = ((val & 0x10) != 0);
+       text_width40 = ((val & 0x08) != 0);
+       workram_l4 = ((val & 0x04) != 0);
+       bool tmpmode = ((val & 0x02) != 0);
+       if(tmpmode != mode400line) {
+               int oldmode = display_mode;
+               mode400line = tmpmode;
+               if(mode400line && stat_400linecard) {
+                       display_mode = DISPLAY_MODE_1_400L;
+               } else {
+                       display_mode = DISPLAY_MODE_8_200L;
+               }
+               if(oldmode != display_mode) {
+                       scrntype_t *pp;
+                       if(display_mode == DISPLAY_MODE_1_400L) {
+                               emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
+                               for(int y = 0; y < 400; y++) {
+                                       pp = emu->get_screen_buffer(y);
+                                       if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
+                               }
+                       } else { // 200Line
+                               
+                               vm->set_vm_frame_rate(FRAMES_PER_SEC);
+#if !defined(FIXED_FRAMEBUFFER_SIZE)
+                               emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
+                               for(int y = 0; y < 200; y++) {
+                                       pp = emu->get_screen_buffer(y);
+                                       if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
+                               }
+#else
+                               for(int y = 0; y < 400; y++) {
+                                       pp = emu->get_screen_buffer(y);
+                                       if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
+                               }
+#endif
+                       }
+                       vram_wrote = true;
+                       setup_display_mode();
+                       
+               }
+       }
+#endif 
+}
+
 //SUB:D409:R
 uint8_t DISPLAY::set_vramaccess(void)
 {
        vram_accessflag = true;
+       //enter_display();
        return 0xff;
 }
 
@@ -527,6 +674,7 @@ uint8_t DISPLAY::set_vramaccess(void)
 void DISPLAY::reset_vramaccess(void)
 {
        vram_accessflag = false;
+       //enter_display();
 }
 
 //SUB:D40A:R
@@ -547,7 +695,7 @@ void DISPLAY::set_subbusy(void)
 // D410
 void DISPLAY::alu_write_cmdreg(uint32_t val)
 {
-       alu->write_data8(ALU_CMDREG, val);
+       call_write_data8(alu, ALU_CMDREG, val);
        if((val & 0x80) != 0) {
                use_alu = true;
        } else {
@@ -559,14 +707,14 @@ void DISPLAY::alu_write_cmdreg(uint32_t val)
 void DISPLAY::alu_write_logical_color(uint8_t val)
 {
        uint32_t data = (uint32_t)val;
-       alu->write_data8(ALU_LOGICAL_COLOR, data);
+       call_write_data8(alu, ALU_LOGICAL_COLOR, data);
 }
 
 // D412
 void DISPLAY::alu_write_mask_reg(uint8_t val)
 {
        uint32_t data = (uint32_t)val;
-       alu->write_data8(ALU_WRITE_MASKREG, data);
+       call_write_data8(alu, ALU_WRITE_MASKREG, data);
 }
 
 // D413 - D41A
@@ -574,14 +722,14 @@ void DISPLAY::alu_write_cmpdata_reg(int addr, uint8_t val)
 {
        uint32_t data = (uint32_t)val;
        addr = addr & 7;
-       alu->write_data8(ALU_CMPDATA_REG + addr, data);
+       call_write_data8(alu, ALU_CMPDATA_REG + addr, data);
 }
 
 // D41B
 void DISPLAY::alu_write_disable_reg(uint8_t val)
 {
        uint32_t data = (uint32_t)val;
-       alu->write_data8(ALU_BANK_DISABLE, data);
+       call_write_data8(alu, ALU_BANK_DISABLE, data);
 }
 
 // D41C - D41F
@@ -590,16 +738,16 @@ void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
        uint32_t data = (uint32_t)val;
        switch(addr & 3) {
                case 0: // $D41C
-                       alu->write_data8(ALU_TILEPAINT_B, data);
+                       call_write_data8(alu, ALU_TILEPAINT_B, data);
                        break;
                case 1: // $D41D
-                       alu->write_data8(ALU_TILEPAINT_R, data);
+                       call_write_data8(alu, ALU_TILEPAINT_R, data);
                        break;
                case 2: // $D41E
-                       alu->write_data8(ALU_TILEPAINT_G, data);
+                       call_write_data8(alu, ALU_TILEPAINT_G, data);
                        break;
                case 3: // xxxx
-                       //alu->write_data8(ALU_TILEPAINT_L, 0xff);
+                       //call_write_data8(alu, ALU_TILEPAINT_L, 0xff);
                        break;
        }
 }
@@ -607,25 +755,25 @@ void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
 // D420
 void DISPLAY::alu_write_offsetreg_hi(uint8_t val)
 {
-       alu->write_data8(ALU_OFFSET_REG_HIGH, val & 0x7f);
+       call_write_data8(alu, ALU_OFFSET_REG_HIGH, val & 0x7f);
 }
  
 // D421
 void DISPLAY::alu_write_offsetreg_lo(uint8_t val)
 {
-       alu->write_data8(ALU_OFFSET_REG_LO, val);
+       call_write_data8(alu, ALU_OFFSET_REG_LO, val);
 }
 
 // D422
 void DISPLAY::alu_write_linepattern_hi(uint8_t val)
 {
-       alu->write_data8(ALU_LINEPATTERN_REG_HIGH, val);
+       call_write_data8(alu, ALU_LINEPATTERN_REG_HIGH, val);
 }
 
 // D423
 void DISPLAY::alu_write_linepattern_lo(uint8_t val)
 {
-       alu->write_data8(ALU_LINEPATTERN_REG_LO, val);
+       call_write_data8(alu, ALU_LINEPATTERN_REG_LO, val);
 }
 
 // D424-D42B
@@ -634,28 +782,28 @@ void DISPLAY::alu_write_line_position(int addr, uint8_t val)
        uint32_t data = (uint32_t)val;
        switch(addr) {
                case 0:  
-                       alu->write_data8(ALU_LINEPOS_START_X_HIGH, data & 0x03); 
+                       call_write_data8(alu, ALU_LINEPOS_START_X_HIGH, data & 0x03); 
                        break;
                case 1:  
-                       alu->write_data8(ALU_LINEPOS_START_X_LOW, data); 
+                       call_write_data8(alu, ALU_LINEPOS_START_X_LOW, data); 
                        break;
                case 2:  
-                       alu->write_data8(ALU_LINEPOS_START_Y_HIGH, data & 0x01); 
+                       call_write_data8(alu, ALU_LINEPOS_START_Y_HIGH, data & 0x01); 
                        break;
                case 3:  
-                       alu->write_data8(ALU_LINEPOS_START_Y_LOW, data); 
+                       call_write_data8(alu, ALU_LINEPOS_START_Y_LOW, data); 
                        break;
                case 4:  
-                       alu->write_data8(ALU_LINEPOS_END_X_HIGH, data & 0x03); 
+                       call_write_data8(alu, ALU_LINEPOS_END_X_HIGH, data & 0x03); 
                        break;
                case 5:  
-                       alu->write_data8(ALU_LINEPOS_END_X_LOW, data); 
+                       call_write_data8(alu, ALU_LINEPOS_END_X_LOW, data); 
                        break;
                case 6:  
-                       alu->write_data8(ALU_LINEPOS_END_Y_HIGH, data & 0x01); 
+                       call_write_data8(alu, ALU_LINEPOS_END_Y_HIGH, data & 0x01); 
                        break;
                case 7:  
-                       alu->write_data8(ALU_LINEPOS_END_Y_LOW, data);
+                       call_write_data8(alu, ALU_LINEPOS_END_Y_LOW, data);
                        break;
        }
 }
@@ -687,7 +835,7 @@ void DISPLAY::set_miscreg(uint8_t val)
                display_page = 1;
        }
        if(display_page != old_display_page) {
-                       vram_wrote = true;
+               vram_wrote = true;
        }
        active_page = ((val & 0x20) == 0) ? 0 : 1;
        if((val & 0x04) == 0) {
@@ -714,12 +862,9 @@ void DISPLAY::set_monitor_bank(uint8_t var)
        if(!halt_flag) {
                subcpu_resetreq = false;
                power_on_reset = true;
-               firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
-               reset_cpuonly();
-               subcpu->write_signal(SIG_CPU_HALTREQ, 0, 1);
-               subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1); // Is needed?
-               subcpu->reset();
-               do_firq(!firq_mask && key_firq_req);
+               //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
+               reset_some_devices();
+               reset_subcpu(true);
        } else {
                subcpu_resetreq = true;
        }
@@ -748,7 +893,7 @@ void DISPLAY::calc_apalette(uint16_t idx)
        if(g != 0) g |= 0x0f; 
        if(r != 0) r |= 0x0f; 
        if(b != 0) b |= 0x0f; 
-       analog_palette_pixel[idx] = RGB_COLOR(r, g, b);
+       analog_palette_pixel_tmp[idx] = RGB_COLOR(r, g, b);
 }
 
 // FD32
@@ -830,7 +975,7 @@ void DISPLAY::copy_vram_per_line(int begin, int end)
        
        sectors = end - begin + 1;
        
-       if(display_mode == DISPLAY_MODE_8_400L) {
+       if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)){
                if(dline >= 400) return;
        } else {
                if(dline >= 200) return;
@@ -1018,6 +1163,32 @@ void DISPLAY::copy_vram_per_line(int begin, int end)
                //vram_wrote_table[dline] = false;
        }
 #else // FM-8/7/77
+#if defined(_FM77L4)
+       if(display_mode == DISPLAY_MODE_1_400L) {
+               src_offset = dline * 80 + begin * 16;
+               sectors = sectors * 16;
+               yoff_d = (yoff_d1 << 1) & 0x7fff;
+               src_offset_d = (src_offset + yoff_d) & 0x7fff;
+               bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
+               if(bytes_d < sectors) {
+                       if(bytes_d > 0) {
+                               my_memcpy(&gvram_shadow[src_offset],
+                                                 &gvram[src_offset_d],
+                                                 bytes_d);
+                       }
+                       my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
+                                         &gvram[0],
+                                         sectors - bytes_d);
+               } else {
+                       my_memcpy(&gvram_shadow[src_offset +  poff],
+                                         &gvram[src_offset_d ],
+                                         sectors);
+               }
+               vram_draw_table[dline] = true;
+               for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
+               return;
+       }
+#endif
        { // 200line
                src_offset = dline * 80 + begin * 16;
                sectors = sectors * 16;
@@ -1150,6 +1321,15 @@ void DISPLAY::copy_vram_all()
                }
        }
 #else // FM-8/7/77
+#  if defined(_FM77L4)
+       if(display_mode == DISPLAY_MODE_1_400L) {
+               uint32_t yoff_d = offset_point & 0x7fff;
+               uint32_t bytes_d = 0x8000 - (offset_point & 0x7fff);
+               my_memcpy(&gvram_shadow[0], &gvram[0 + yoff_d], bytes_d);
+               my_memcpy(&gvram_shadow[0 + bytes_d], &gvram[0], 0x8000 - bytes_d);
+               return;
+       }
+#  endif
     { // 200line
                uint32_t yoff_d = offset_point & 0x3fff;
                uint32_t bytes_d = 0x4000 - (offset_point & 0x3fff);
@@ -1164,223 +1344,381 @@ void DISPLAY::copy_vram_all()
 }
 
 // Timing values from XM7 . Thanks Ryu.
-void DISPLAY::event_callback(int event_id, int err)
+//#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
+void DISPLAY::event_callback_hdisp(void)
 {
+       bool f = false;
        double usec;
-       bool f;
-       switch(event_id) {
-               case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
-#if defined(_FM77AV_VARIANTS)
-                       if(nmi_enable) {
-                               do_nmi(true);
-                       } else {
-                               //do_nmi(false);
-                       }
-#else
-                       do_nmi(true);
-#endif
-                       break;
-               case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
-                       do_nmi(false);
-                       break;
-#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
-               case EVENT_FM7SUB_HDISP:
-                       hblank = false;
-                       f = false;
-                       mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x02, 0xff);
-                       if(display_mode == DISPLAY_MODE_8_400L) {
-                               if(displine < 400) f = true;
-                       } else {
-                               if(displine < 200) f = true;
-                       }
-                       if(f) {
-                               if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
-                                       if(vram_wrote) {
-                                               //copy_vram_per_line(0, 4);
-                                       } else if(need_transfer_line) {
-                                               int begin = -1;
-                                               int end = -1;
-                                               for(int iii = 0; iii < 5 ; iii++) {
-                                                       if(vram_wrote_table[iii + displine * 5]) {
-                                                               if(begin < 0) begin = iii;
-                                                       } else {
-                                                               if(begin >= 0) {
-                                                                       end = iii - 1;
-                                                                       if(end < begin) end = begin;
-                                                                       copy_vram_per_line(begin, end);
-                                                                       begin = -1;
-                                                                       end = -1;
-                                                               }
-                                                       }
+       hblank = false;
+       call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x02, 0xff);
+       if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
+               if(displine < 400) f = true;
+       } else {
+               if(displine < 200) f = true;
+       }
+
+       hdisp_event_id = -1;
+       if(f) {
+               // DO ONLY WHEN SYNC-TO-HSYNC.
+               if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
+                       if(vram_wrote) {
+                               //copy_vram_per_line(0, 4);
+                       } else if(need_transfer_line) { // Not frame skip.
+                               int begin = -1;
+                               int end = -1;
+                               for(int iii = 0; iii < 5 ; iii++) {
+                                       if(vram_wrote_table[iii + displine * 5]) {
+                                               if(begin < 0) begin = iii; // Check first.
+                                       } else {
+                                               // Check end.
+                                               if(begin >= 0) {
+                                                       end = iii - 1;
+                                                       if(end < begin) end = begin;
+                                                       // Do transfer.
+                                                       copy_vram_per_line(begin, end);
+                                                       // Prepare to next block.
+                                                       begin = -1;
+                                                       end = -1;
                                                }
-                                               if(begin >= 0) end = 4;
-                                               copy_vram_per_line(begin, end);
                                        }
                                }
-                               if(display_mode == DISPLAY_MODE_8_400L) {
-                                       register_event(this, EVENT_FM7SUB_HBLANK, 30.0, false, &hblank_event_id); // NEXT CYCLE_
-                               } else {
-                                       register_event(this, EVENT_FM7SUB_HBLANK, 39.5, false, &hblank_event_id); // NEXT CYCLE_
-                               }
-                               vsync = false;
-                               vblank = false;
-                               enter_display();
-                       }
-                       f = false;
-                       break;
-               case EVENT_FM7SUB_HBLANK:
-                       hblank = true;
-                       mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
-                       f = false;
-                       if(display_mode == DISPLAY_MODE_8_400L) {
-                               if((displine < 400)) f = true;
-                       } else {
-                               if((displine < 200)) f = true;
-                       }
-                       if(f) {
-                               if(display_mode == DISPLAY_MODE_8_400L) {
-                                       usec = 11.0;
-                               } else {
-                                       usec = 24.0;
+                               // Tail of this line.
+                               if(begin >= 0) {
+                                       end = 4;
+                                       copy_vram_per_line(begin, end);
                                }
-                               register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
                        }
-                       displine++;
-                       break;
-               case EVENT_FM7SUB_VSTART: // Call first.
-                       vblank = true;
-                       vsync = false;
-                       hblank = false;
-                       displine = 0;
-                       display_page_bak = display_page;
-                       // Parameter from XM7/VM/display.c , thanks, Ryu.
-                       mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
-                       mainio->write_signal(SIG_DISPLAY_VSYNC, 0x00, 0xff);
-                       if(vblank_count != 0) {
-                               if(display_mode == DISPLAY_MODE_8_400L) {
-                                       usec = (0.98 + 16.4) * 1000.0;
-                               } else {
-                                       usec = (1.91 + 12.7) * 1000.0;
-                               }
-                               register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
+               }
+               if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
+                       register_event(this, EVENT_FM7SUB_HBLANK, 30.0, false, &hblank_event_id); // NEXT CYCLE_
+               } else {
+                       register_event(this, EVENT_FM7SUB_HBLANK, 39.5, false, &hblank_event_id); // NEXT CYCLE_
+               }
+               vsync = false;
+               vblank = false;
+               enter_display();
+       }
+       f = false;      
+}
+void DISPLAY::event_callback_hblank(void)
+{
+       bool f = false;
+       bool ff = false;
+       double usec;
+       
+       hblank = true;
+       hblank_event_id = -1;
+       
+       call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
+       if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
+               if((displine < 400)) f = true;
+               usec = 11.0;
+       } else {
+               if((displine < 200)) f = true;
+               usec = 24.0;
+       }
+       if(f) {
+               register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
+       }
+       displine++;
+}
 
-                               if(display_mode == DISPLAY_MODE_8_400L) {
-                                       usec = 930.0; // 939.0
-                               } else {
-                                       usec = 1840.0; // 1846.5
-                               }
-                               register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
-                               vblank_count = 0;
-                               return;
-                       } else {
-                               if(display_mode == DISPLAY_MODE_8_400L) {
-                                       usec = 0.34 * 1000.0;
-                               } else {
-                                       usec = 1.52 * 1000.0;
-                               }
-                               register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
-                               vblank_count++;
-                               //break;
-                       }
-                       break;
-       case EVENT_FM7SUB_VSYNC:
-               vblank = true;
-               hblank = false;
-               vsync = true;
-               //write_access_page = (write_access_page + 1) & 1;
-               displine = 0;
-               if(display_mode == DISPLAY_MODE_8_400L) {
-                       usec = 0.33 * 1000.0; 
+void DISPLAY::event_callback_vstart(void)
+{
+       double usec; 
+       vblank = true;
+       vsync = false;
+       hblank = false;
+       displine = 0;
+       display_page_bak = display_page;
+       
+       // Parameter from XM7/VM/display.c , thanks, Ryu.
+       call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
+       call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x00, 0xff);
+       
+       if(vblank_count != 0) {
+               if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
+                       usec = (0.98 + 16.4) * 1000.0;
                } else {
-                       usec = 0.51 * 1000.0;
+                       usec = (1.91 + 12.7) * 1000.0;
                }
-               mainio->write_signal(SIG_DISPLAY_VSYNC, 0x01, 0xff);
-               mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
+               register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
+
+               if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
+                       usec = 930.0; // 939.0
+               } else {
+                       usec = 1840.0; // 1846.5
+               }
+               vstart_event_id = -1;
+               register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
+               //register_event(this, EVENT_FM7SUB_HBLANK, usec, false, &hdisp_event_id); // NEXT CYCLE_
+               vblank_count = 0;
+       } else {
+               if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
+                       usec = 0.34 * 1000.0;
+               } else {
+                       usec = 1.52 * 1000.0;
+               }
+               vsync_event_id = -1;
+               hblank_event_id = -1;
+               hdisp_event_id = -1;
                register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
-               if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
-                       bool ff = false;
-                       int lines = 200;
-                       if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
-                       if(need_transfer_line) {
-                               if(vram_wrote) ff = true;
-                               //if(need_transfer_line) ff = true;
-                               //}
+               vblank_count++;
+       }
+}
+void DISPLAY::event_callback_vsync(void)
+{
+       double usec; 
+       vblank = true;
+       hblank = false;
+       vsync = true;
+       //write_access_page = (write_access_page + 1) & 1;
+       //displine = 0;
+       
+       if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
+               usec = 0.33 * 1000.0; 
+       } else {
+               usec = 0.51 * 1000.0;
+       }
+       call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x01, 0xff);
+       call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
+       //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
+
+       if(palette_changed) {
+#if defined(_FM77AV_VARIANTS)
+               memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
+#endif
+#if defined(USE_GREEN_DISPLAY)
+               memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
+#endif
+               memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
+               vram_wrote_shadow = true;
+               for(int yy = 0; yy < 400; yy++) {
+                       vram_draw_table[yy] = true;
+               }
+               palette_changed = false;
+       }
+       // Transfer on VSYNC
+       if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
+               bool ff = false;
+               int lines = 200;
+               
+               if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L))lines = 400;
+               if(need_transfer_line) {
+                       if(vram_wrote) { // transfer all line
+                               for(displine = 0; displine < lines; displine++) {
+                                       //if(!vram_draw_table[displine]) {
+                                       copy_vram_per_line(0, 4);
+                                               //}
+                               }
+                               vram_wrote = false;
+                       } else { // transfer wrote line
+                               int begin = -1;
+                               int end = -1;
                                for(displine = 0; displine < lines; displine++) {
-                                       if(ff) break;
+                                       //if(!vram_draw_table[displine]) {
                                        for(int iii = 0; iii < 5 ; iii++) {
                                                if(vram_wrote_table[iii + displine * 5]) {
-                                                       ff = true;
-                                                       break;
+                                                       if(begin < 0) {
+                                                               begin = iii;
+                                                       }
+                                               } else {
+                                                       if(begin >= 0) {
+                                                               end = iii - 1;
+                                                               if(end < begin) end = begin;
+                                                               copy_vram_per_line(begin, end);
+                                                               begin = -1;
+                                                               end = -1;
+                                                       }
                                                }
                                        }
+                                       if(begin >= 0) {
+                                               if(end < 0) end = 4;
+                                               copy_vram_per_line(begin, end);
+                                       }
+                                       begin = -1;
+                                       end = -1;
+                               //}
                                }
-                               displine = 0;
                        }
-                       if(ff) {
+               }
+               for(int yy = 0; yy < lines; yy++) {
+                       if(vram_draw_table[yy]) {
+                               vram_wrote_shadow = true;
+                               screen_update_flag = true;
+                               break;
+                       }
+               }
+       } else {
+               // TRANSFER per HSYNC a.k.a SYNC-TO-HSYNC.
+               int lines = 200;
+               if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) lines = 400;
+               
+               if(need_transfer_line) {
+                       if(vram_wrote) { // Transfer all line.
                                for(int yy = 0; yy < lines; yy++) {
-                                       if(!vram_draw_table[yy]) {
-                                               displine = yy;
-                                               copy_vram_per_line(0, 4);
-                                               vram_draw_table[yy] = true;
-                                       }
+                                       displine = yy;
+                                       copy_vram_per_line(0, 4);
                                }
-                               //copy_vram_all();
+                               //displine = 0;
+                               vram_wrote = false;
+                       }
+               }
+               for(int yy = 0; yy < lines; yy++) {
+                       if(vram_draw_table[yy]) {
                                vram_wrote_shadow = true;
                                screen_update_flag = true;
-                               vram_wrote = false;
+                               break;
                        }
+               }
+               //vram_wrote = false;
+       }
+       frame_skip_count_transfer++;
+       {
+               // Check frame skip for next frame.
+               uint32_t factor = ((config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28) & 3;
+               if((frame_skip_count_transfer > factor) /* || (vram_wrote) */) {
+                       frame_skip_count_transfer = 0;
+                       need_transfer_line = true;
                } else {
-                       int lines = 200;
-                       if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
-                       if(need_transfer_line) {
-                               if(vram_wrote) {
-                                       for(int yy = 0; yy < lines; yy++) {
-                                               //if(!vram_draw_table[yy]) {
-                                               displine = yy;
-                                               copy_vram_per_line(0, 4);
-                                                       //}
-                                       }
-                                       displine = 0;
-                                       vram_wrote = false;
-                               }
+                       need_transfer_line = false;
+               }
+       }
+}
+
+//#endif
+#if defined(_FM77L4)
+void DISPLAY::cursor_blink_77l4()
+{
+       if(!(mode400line && stat_400linecard)) return;
+       uint8_t *regs = l4crtc->get_regs();
+       uint32_t naddr;
+       if(regs != NULL) {
+               int x, y;
+               if((regs[10] & 0x40) != 0) {
+                       cursor_blink = !cursor_blink;
+                       uint16_t addr = cursor_addr.w.l;
+                       if(text_width40) {
+                               x = ((addr / 2) % 40) / 8;
+                               y = (addr / 2) / 40;
+                       } else { // Width 80
+                               x = ((addr / 2) % 80) / 8;
+                               y = (addr / 2) / 80;
                        }
-                       for(int yy = 0; yy < lines; yy++) {
-                               if(vram_draw_table[yy]) {
-                                       vram_wrote_shadow = true;
-                                       screen_update_flag = true;
-                                       break;
-                               }
+                       for(int yy = 0; yy < 8; yy++) {
+                               naddr = (y + yy) * 5 + x;
+                               vram_wrote_table[naddr] = true;
                        }
-                       //vram_wrote = false;
                }
-               frame_skip_count_transfer++;
-               {
-                       uint32_t factor = ((config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28) & 3;
-                       if((frame_skip_count_transfer > factor) /* || (vram_wrote) */) {
-                               frame_skip_count_transfer = 0;
-                               need_transfer_line = true;
-                       } else {
-                               need_transfer_line = false;
+       }
+}
+
+void DISPLAY::text_blink_77l4()
+{
+       uint16_t addr;
+       uint16_t offset = text_start_addr.w.l;
+       uint32_t naddr;
+       int x, y;
+       if(!(mode400line && stat_400linecard)) return;
+       text_blink = !text_blink;
+       for(addr = 0; addr < (80 * 50); addr++) {
+               naddr = ((addr + offset) & 0x0ffe) + 1;
+               if((text_vram[naddr] & 0x10) != 0) { // ATTR BLINK
+                       if(text_width40) {
+                               x = ((naddr / 2) % 40) / 8;
+                               y = (naddr / 2) / 40;
+                       } else { // Width 80
+                               x = ((naddr / 2) % 80) / 8;
+                               y = (naddr / 2) / 80;
+                       }
+                       for(int yy = 0; yy < 8; yy++) {
+                               naddr = (y + yy) * 5 + x;
+                               vram_wrote_table[naddr] = true;
                        }
                }
-               break;
+       }
+}
+#endif //#if defined(_FM77L4)
+
+void DISPLAY::event_callback(int event_id, int err)
+{
+       double usec;
+       bool f;
+       switch(event_id) {
+               case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
+#if defined(_FM77AV_VARIANTS)
+                       if(nmi_enable) {
+                               do_nmi(true);
+                       }
+#else
+                       do_nmi(true);
+#endif
+                       break;
+               case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
+                       do_nmi(false);
+                       break;
+//#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
+               case EVENT_FM7SUB_HDISP:
+                       event_callback_hdisp();
+                       break;
+               case EVENT_FM7SUB_HBLANK:
+                       event_callback_hblank();
+                       break;
+               case EVENT_FM7SUB_VSTART: // Call first.
+                       event_callback_vstart();
+                       break;
+               case EVENT_FM7SUB_VSYNC:
+                       event_callback_vsync();
+                       break;
+//#endif                       
+               case EVENT_FM7SUB_DELAY_BUSY:
+                       delay_busy = false;
+                       set_subbusy();
+                       break;
+               case EVENT_FM7SUB_CLEAR_DELAY:
+                       delay_busy = false;
+                       break;
+               case EVENT_FM7SUB_CLR_CRTFLAG:
+                       reset_crtflag();
+                       break;
+#if defined(_FM77L4)
+               case EVENT_FM7SUB_CURSOR_BLINK:
+                       cursor_blink_77l4();
+                       break;
+               case EVENT_FM7SUB_TEXT_BLINK:
+                       text_blink_77l4();
+                       break;
 #endif                 
-       case EVENT_FM7SUB_CLR_BUSY:
-               set_subbusy();
-               break;
-       case EVENT_FM7SUB_CLR_CRTFLAG:
-               reset_crtflag();
-               break;
        }
 }
 
 void DISPLAY::event_frame()
 {
+#if 1
+       double usec; 
+       vblank = true;
+       hblank = false;
+       vsync = true;
+       //write_access_page = (write_access_page + 1) & 1;
+       //out_debug_log(_T("DISPLINE=%d"), displine);
+       displine = 0;
+       if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
+               usec = 0.34 * 1000.0; 
+       } else {
+               usec = 1.52 * 1000.0;
+       }
+       call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x01, 0xff);
+       call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
+       register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
+       vblank_count = 1;
+#endif
+#if 0
 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
        int yy;
        bool f = false;
        int lines = 200;
-       if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
+       if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) lines = 400;
+#if 0  
        if(need_transfer_line && vram_wrote) {
                for(yy = 0; yy < lines; yy++) {
                        //if(!vram_draw_table[yy]) {
@@ -1391,6 +1729,7 @@ void DISPLAY::event_frame()
                vram_wrote = false;
                displine = 0;
        }
+#endif
        {
                for(yy = 0; yy < lines; yy++) {
                        if(vram_draw_table[yy]) {
@@ -1417,17 +1756,19 @@ void DISPLAY::event_frame()
                }
        }
        
-#endif 
+#endif
+#endif
 }
 
 void DISPLAY::event_vline(int v, int clock)
 {
 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
+       bool ff = false;
        if(need_transfer_line == false) return;
        displine = v;
-       bool ff = false;
        if(vram_wrote) {
-               //copy_vram_per_line(0, 4);
+               // Not transfer, will transfer at event_frame.
+               copy_vram_per_line(0, 4);
        } else {
                int begin = -1;
                int end = -1;
@@ -1444,8 +1785,10 @@ void DISPLAY::event_vline(int v, int clock)
                                }
                        }
                }
-               if(begin >= 0) end = 4;
-               copy_vram_per_line(begin, end);
+               if(begin >= 0) {
+                       end = 4;
+                       copy_vram_per_line(begin, end);
+               }
        }
        enter_display();
 #endif 
@@ -1489,11 +1832,30 @@ uint32_t DISPLAY::read_signal(int id)
                        break;
 #endif
                case SIG_DISPLAY_Y_HEIGHT:
+#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77L4)
+                       retval = ((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) ? 400 : 200;
+#else
+                       retval = 200;
+#endif           
+                       break;
+               case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
+                       retval = 0;
 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
-                       retval = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
+                       retval |= (kanjisub) ? 0x00 : 0x20;
+                       retval |= (mode256k) ? 0x10 : 0x00;
+                       retval |= (mode400line) ? 0x00 : 0x08;
+                       retval |= (ram_protect) ? 0x00 : 0x04;
+#elif defined(_FM77_VARIANTS)
+                       retval = 0x04;
+                       retval |= (kanjisub) ? 0x00 : 0x20;
+#  if defined(_FM77L4)
+                       retval |= (stat_400linecard) ? 0x00 : 0x08;
+#  else
+                       retval |= 0x18;
+#  endif
 #else
-                       retval = 200;
-#endif           
+                       retval = 0x2c;
+#endif
                        break;
                case SIG_DISPLAY_X_WIDTH:
 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
@@ -1521,7 +1883,7 @@ void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
                                sub_busy = true;
                        }
                        halt_flag = flag;
-                       //mainio->write_signal(SIG_FM7_SUB_HALT, data, mask);
+                       //call_write_signal(mainio, SIG_FM7_SUB_HALT, data, mask);
                        break;
                case SIG_DISPLAY_HALT:
                        if(flag) {
@@ -1555,7 +1917,7 @@ void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
                                mode256k = (((data & 0x10) != 0) && ((data & 0x08) != 0) ) ? true : false;
                                mode400line = ((data & 0x08) == 0) ? true : false;
                                ram_protect = ((data & 0x04) == 0) ? true : false;
-                               if(mode400line && !mode320) {
+                               if((mode400line) && !(mode320)) {
                                        display_mode = DISPLAY_MODE_8_400L;
                                } else if(mode256k) {
                                        display_mode = DISPLAY_MODE_256k;
@@ -1565,6 +1927,7 @@ void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
                                if(oldmode != display_mode) {
                                        scrntype_t *pp;
                                        if(mode320 || mode256k) {
+                                               if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
 #if !defined(FIXED_FRAMEBUFFER_SIZE)
                                                emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
                                                for(y = 0; y < 200; y++) {
@@ -1572,20 +1935,21 @@ void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
                                                        if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
                                                }
 #else
-                                               emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
                                                for(y = 0; y < 400; y++) {
                                                        pp = emu->get_screen_buffer(y);
                                                        if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
                                                }
 #endif 
+                                               //emu->set_vm_screen_lines(200);
                                        } else if(display_mode == DISPLAY_MODE_8_400L) {
                                                emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
+                                               if(oldmode != DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(55.40);
                                                for(y = 0; y < 400; y++) {
                                                        pp = emu->get_screen_buffer(y);
                                                        if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
                                                }
                                        } else {
-
+                                               if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
 #if !defined(FIXED_FRAMEBUFFER_SIZE)
                                                emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
                                                for(y = 0; y < 200; y++) {
@@ -1593,17 +1957,17 @@ void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
                                                        if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
                                                }
 #else
-                                               emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
                                                for(y = 0; y < 400; y++) {
                                                        pp = emu->get_screen_buffer(y);
                                                        if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
                                                }
 #endif 
+                                               //emu->set_vm_screen_lines(200);
                                        }
                                        vram_wrote = true;
-                                       alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 :  80, 0xffff);
-                                       alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
-                                       alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
+                                       call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 :  80, 0xffff);
+                                       call_write_signal(alu, SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
+                                       call_write_signal(alu, SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
                                        frame_skip_count_draw = 3;
                                        frame_skip_count_transfer = 3;
                                        setup_display_mode();
@@ -1614,18 +1978,59 @@ void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
                                int oldmode = display_mode;
                                kanjisub = ((data & 0x20) == 0) ? true : false;
 # if defined(_FM77L4)                          
-                               stat_400linecard = ((data & 0x20) != 0) ? true : false;
-                               mode400line = ((data & 0x08) != 0) ? false : true;
+                               stat_400linecard = ((data & 0x08) != 0) ? false : true;
                                if(mode400line && stat_400linecard) {
-                                       display_mode = DISPLAY_MODE_8_400L_TEXT;
-                               } else if(stat_400linecard) {
-                                       display_mode = DISPLAY_MODE_8_200L_TEXT;
+                                       double usec;
+                                       uint8_t *regs = l4crtc->get_regs();
+                                       display_mode = DISPLAY_MODE_1_400L;
+                                       if(event_id_l4_cursor_blink >= 0) {
+                                               cancel_event(this, event_id_l4_cursor_blink);
+                                       }
+                                       if(event_id_l4_text_blink >= 0) {
+                                               cancel_event(this, event_id_l4_text_blink);
+                                       }
+                                       event_id_l4_cursor_blink = -1;
+                                       event_id_l4_text_blink = -1;
+                                       if(regs != NULL) {
+                                               usec = ((regs[10] & 0x20) == 0) ? 160.0 : 320.0;
+                                               usec = usec * 1000.0;
+                                               register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
+                                               usec = 160.0 * 1000.0;
+                                               register_event(this, EVENT_FM7SUB_TEXT_BLINK, true, usec, &event_id_l4_cursor_blink);
+                                       }                                               
                                } else {
                                        display_mode = DISPLAY_MODE_8_200L;
                                }
+                               if(oldmode != display_mode) {
+                                       scrntype_t *pp;
+                                       if(display_mode == DISPLAY_MODE_1_400L) {
+                                               emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
+                                               for(int y = 0; y < 400; y++) {
+                                                       pp = emu->get_screen_buffer(y);
+                                                       if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
+                                               }
+                                       } else { // 200Line
+                               
+                                               vm->set_vm_frame_rate(FRAMES_PER_SEC);
+#if !defined(FIXED_FRAMEBUFFER_SIZE)
+                                               emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
+                                               for(int y = 0; y < 200; y++) {
+                                                       pp = emu->get_screen_buffer(y);
+                                                       if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
+                                               }
+#else
+                                               for(int y = 0; y < 400; y++) {
+                                                       pp = emu->get_screen_buffer(y);
+                                                       if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
+                                               }
+#endif
+                                       }
+                                       vram_wrote = true;
+                                       setup_display_mode();
+                                       
+                               }
 # endif                                
-                               setup_display_mode();
-                       }                       
+                       }
 #endif
                        break;
 #if defined(_FM77AV_VARIANTS)
@@ -1635,7 +2040,11 @@ void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
                                //printf("Wrote $FD12: %02x\n", data);
                                int oldmode = display_mode;
                                mode320 = flag;
-                               if(!mode320 && !mode256k) {
+                               if(mode400line) {
+                                       display_mode = DISPLAY_MODE_8_400L;
+                               } else if(mode256k) {
+                                       display_mode = DISPLAY_MODE_256k;
+                               } else  if(!(mode320) && !(mode256k)) {
                                        //display_mode = (mode400line) ? DISPLAY_MODE_8_400L : DISPLAY_MODE_8_200L;
                                        display_mode = DISPLAY_MODE_8_200L;
                                } else {
@@ -1644,6 +2053,7 @@ void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
                                if(oldmode != display_mode) {
                                        scrntype_t *pp;
                                        if(mode320 || mode256k) {
+                                               if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
 #if !defined(FIXED_FRAMEBUFFER_SIZE)
                                                emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
                                                for(y = 0; y < 200; y++) {
@@ -1651,32 +2061,38 @@ void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
                                                        if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
                                                }
 #else
-                                               emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
                                                for(y = 0; y < 400; y++) {
                                                        pp = emu->get_screen_buffer(y);
                                                        if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
                                                }
 #endif 
+                                               //emu->set_vm_screen_lines(200);
                                        } else { // 200 lines, 8 colors.
+                                               if(display_mode == DISPLAY_MODE_8_400L) {
+                                                       if(oldmode != DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(55.40);
+                                               } else {
+                                                       if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
+                                               }
 #if !defined(FIXED_FRAMEBUFFER_SIZE)
-                                               emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
-                                               for(y = 0; y < 200; y++) {
+                                               int ymax =      (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
+
+                                               emu->set_vm_screen_size(640, ymax, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
+                                               for(y = 0; y < ymax; y++) {
                                                        pp = emu->get_screen_buffer(y);
                                                        if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
                                                }
 #else
-                                               emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
                                                for(y = 0; y < 400; y++) {
                                                        pp = emu->get_screen_buffer(y);
                                                        if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
                                                }
 #endif 
-
+                                               //emu->set_vm_screen_lines(200);
                                        }
                                        vram_wrote = true;
-                                       alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 :  80, 0xffff);
-                                       alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
-                                       alu->write_signal(SIG_ALU_400LINE, 0x00, 0xff);
+                                       call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 :  80, 0xffff);
+                                       call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
+                                       call_write_signal(alu, SIG_ALU_400LINE, 0x00, 0xff);
                                        setup_display_mode();
                                        //frame_skip_count = 3;
                                }
@@ -1684,33 +2100,33 @@ void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
 # else /* FM77AV/20/20EX */
                        oldflag = mode320;
                        mode320 = flag;
-                       {
+                       if(oldflag != mode320) {
                
                                if(mode320) {
 #if !defined(FIXED_FRAMEBUFFER_SIZE)
                                                emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
                                                for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype_t));
 #else
-                                               emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
                                                for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
 #endif 
+                                               //emu->set_vm_screen_lines(200);
                                } else {
 #if !defined(FIXED_FRAMEBUFFER_SIZE)
                                                emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
                                                for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
 #else
-                                               emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
                                                for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
 #endif 
+                                               //emu->set_vm_screen_lines(200);
 
                                }
+                               display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
+                               call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 :  80, 0xffff);
+                               call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
+                               call_write_signal(alu, SIG_ALU_400LINE, 0, 0xffffffff);
+                               vram_wrote = true;
+                               setup_display_mode();
                        }
-                       display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
-                       alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 :  80, 0xffff);
-                       alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
-                       alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
-                       vram_wrote = true;
-                       if(mode320 != oldflag) setup_display_mode();
 # endif
 #endif                 
                        break;
@@ -1727,13 +2143,6 @@ void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
                        do_firq(flag & !(firq_mask));
                        key_firq_req = flag;
                        break;
-               case SIG_FM7_SUB_USE_CLR:
-                       if(flag) {
-                               clr_count = data & 0x03;
-                       } else {
-                               clr_count = 0;
-                       }
-                       break;
                default:
                        break;
        }
@@ -1758,10 +2167,10 @@ uint32_t DISPLAY::read_mmio(uint32_t addr)
 #endif
        switch(raddr) {
                case 0x00: // Read keyboard
-                       retval = (keyboard->read_data8(0x00) != 0) ? 0xff : 0x7f;
+                       retval = (call_read_data8(keyboard, 0x00) != 0) ? 0xff : 0x7f;
                        break;
                case 0x01: // Read keyboard
-                       retval = keyboard->read_data8(0x01) & 0xff;
+                       retval = call_read_data8(keyboard, 0x01) & 0xff;
                        break;
                case 0x02: // Acknowledge
                        acknowledge_irq();
@@ -1778,19 +2187,19 @@ uint32_t DISPLAY::read_mmio(uint32_t addr)
                        if(!kanjisub) return 0xff;
 # if !defined(_FM77_VARIANTS)
                        if(kanji_level2) {
-                               return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
+                               return (uint8_t)call_read_data8(kanjiclass2, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
                        }
 # endif
-                       if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
+                       if(kanjiclass1 != NULL) retval = call_read_data8(kanjiclass1, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
                        break;
                case 0x07:
                        if(!kanjisub) return 0xff;
 # if !defined(_FM77_VARIANTS)
                        if(kanji_level2) {
-                               return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
+                               return (uint8_t)call_read_data8(kanjiclass2, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
                        }
 # endif
-                       if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
+                       if(kanjiclass1 != NULL) retval = call_read_data8(kanjiclass1, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
                        break;
 #endif
                case 0x08:
@@ -1800,27 +2209,51 @@ uint32_t DISPLAY::read_mmio(uint32_t addr)
                        retval = set_vramaccess();
                        break;
                case 0x0a:
+                       { // If use CLR insn to set busy flag, clear flag at first, then delay and set flag. 
+                               double usec;
+                               // Delay at least 3+ clocks (CLR <$0A )
+                               delay_busy = true;
+                               if(clock_fast) {
+                                       usec = (4000.0 * 1000.0) / 2000000.0;
+                               } else {
+                                       usec = (4000.0 * 1000.0) / 999000.0;
+                               }
+                               register_event(this, EVENT_FM7SUB_CLEAR_DELAY, usec, false, NULL); // NEXT CYCLE_
+                       }
                        reset_subbusy();
                        break;
+#if defined(_FM77L4)
+               case 0x0b:
+                       if(stat_400linecard) {
+                               retval = l4crtc->read_io8(0);
+                       }
+                       break;
+               case 0x0c:
+                       if(stat_400linecard) {
+                               retval = l4crtc->read_io8(1);
+                               // Update parameters.
+                       }
+                       break;
+#endif                 
                case 0x0d:
-                       keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
+                       call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
                        break;
 #if defined(_FM77AV_VARIANTS)
                // ALU
                case 0x10:
-                       retval = alu->read_data8(ALU_CMDREG);
+                       retval = call_read_data8(alu, ALU_CMDREG);
                        break;
                case 0x11:
-                       retval = alu->read_data8(ALU_LOGICAL_COLOR);
+                       retval = call_read_data8(alu, ALU_LOGICAL_COLOR);
                        break;
                case 0x12:
-                       retval = alu->read_data8(ALU_WRITE_MASKREG);
+                       retval = call_read_data8(alu, ALU_WRITE_MASKREG);
                        break;
                case 0x13:
-                       retval = alu->read_data8(ALU_CMP_STATUS_REG);
+                       retval = call_read_data8(alu, ALU_CMP_STATUS_REG);
                        break;
                case 0x1b:
-                       retval = alu->read_data8(ALU_BANK_DISABLE);
+                       retval = call_read_data8(alu, ALU_BANK_DISABLE);
                        break;
 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
                case 0x2f: // VRAM BANK
@@ -1833,10 +2266,10 @@ uint32_t DISPLAY::read_mmio(uint32_t addr)
                        break;
                // KEY ENCODER.
                case 0x31:
-                       retval = keyboard->read_data8(0x31);
+                       retval = call_read_data8(keyboard, 0x31);
                        break;
                case 0x32:
-                       retval = keyboard->read_data8(0x32);
+                       retval = call_read_data8(keyboard, 0x32);
                        break;
 #endif                         
                default:
@@ -1850,7 +2283,25 @@ uint32_t DISPLAY::read_vram_data8(uint32_t addr)
        uint32_t offset;
        uint32_t vramaddr;
        uint32_t color = (addr >> 14) & 0x03;
-       
+#if defined(_FM77L4)
+       if(mode400line) {
+               if(addr < 0x8000) {
+                       offset = offset_point;
+                       if(workram_l4) {
+                               if(multimode_accessflags[2]) return 0xff;
+                               vramaddr = ((addr + offset) & 0x3fff) + 0x8000; 
+                               return gvram[vramaddr];
+                       }
+               } else {
+                       if(addr < 0x9800) {
+                               return text_vram[addr & 0x0fff];
+                       } else if(addr < 0xc000) {
+                               return subsys_l4[addr - 0x9800];
+                       }
+                       return 0xff;
+               }
+       }
+#endif
 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
        if(display_mode == DISPLAY_MODE_8_400L) {
                color = vram_bank & 0x03;
@@ -1872,7 +2323,11 @@ uint32_t DISPLAY::read_vram_data8(uint32_t addr)
 #else
        offset = offset_point;
 #endif
-               
+# if defined(_FM77AV40EX) || defined(_FM77AV40SX)
+       if(vram_active_block != 0) {
+               if(display_mode != DISPLAY_MODE_256k) offset = 0; // Don't scroll at BLOCK 1.
+       }
+# endif
 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
                if(display_mode == DISPLAY_MODE_8_400L) {
                        uint32_t pagemod;
@@ -1914,8 +2369,9 @@ uint32_t DISPLAY::read_vram_data8(uint32_t addr)
                }
 #elif defined(_FM77L4) //_FM77L4
                {
-                       if(display_mode == DISPLAY_MODE_8_400L) {
-                               return (uint32_t)read_vram_l4_400l(addr, offset);
+                       if(mode400line) {
+                               vramaddr = (addr + offset) & 0x7fff;
+                               return gvram[vramaddr];
                        } else {
                                vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
                                return gvram[vramaddr];
@@ -1952,6 +2408,9 @@ void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
 #else
        offset = offset_point;
 #endif
+# if defined(_FM77AV40EX) || defined(_FM77AV40SX)
+       if(vram_active_block != 0) offset = 0; // Don't scroll at BLOCK 1.
+# endif
 
 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
                if(display_mode == DISPLAY_MODE_8_400L) {
@@ -2036,18 +2495,32 @@ void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
                        }
                }
 #elif defined(_FM77L4) //_FM77L4
-               {
-                       uint32_t naddr;
-                       if(display_mode == DISPLAY_MODE_8_400L) {
-                               write_vram_l4_400l(addr, data, offset);
-                       } else {
-                               vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
-                               tdata = gvram[vramaddr];
-                               if(data != tdata) {
-                                       naddr = (addr & 0x3fff) >> 4;
+               if(display_mode == DISPLAY_MODE_1_400L) {
+                       if(addr < 0x8000) {
+                               if(workram_l4) {
+                                       //if(multimode_accessflags[2]) return;
+                                       vramaddr = ((addr + offset) & 0x3fff) + 0x8000; 
                                        gvram[vramaddr] = data;
-                                       vram_wrote_table[naddr] = true;
+                               } else {
+                                       uint32_t naddr;
+                                       vramaddr = (addr + offset) & 0x7fff;
+                                       tdata = gvram[vramaddr];
+                                       if(tdata != data) {
+                                               naddr = (addr & 0x7fff) >> 4;
+                                               gvram[vramaddr] = data;
+                                               vram_wrote_table[naddr] = true;
+                                       }
                                }
+                               return;
+                       }
+               } else {
+                       uint32_t naddr;
+                       vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
+                       tdata = gvram[vramaddr];
+                       if(tdata != data) {
+                               naddr = (addr & 0x3fff) >> 4;
+                               gvram[vramaddr] = data;
+                               vram_wrote_table[naddr] = true;
                        }
                }
 #else // Others (77/7/8)
@@ -2069,7 +2542,7 @@ uint32_t DISPLAY::read_cpu_vram_data8(uint32_t addr)
        uint8_t color;
 #if defined(_FM77AV_VARIANTS)
        if(use_alu) {
-               alu->read_data8(addr);
+               call_read_data8(alu, addr);
        }
 #endif
        return read_vram_data8(addr);
@@ -2156,6 +2629,7 @@ uint32_t DISPLAY::read_hidden_ram(uint32_t addr)
        if(addr >= 0xd500) {
                return submem_hidden[addr - 0xd500];
        }
+       return 0xff;
 }
 #endif
 
@@ -2195,6 +2669,11 @@ uint32_t DISPLAY::read_subsys_monitor(uint32_t addr)
                return subsys_cg[addr - 0xe000];
                break;
        }
+#elif defined(_FM77L4)
+       if(mode400line) {
+               return subsys_l4[addr - 0xb800];
+       }
+       return subsys_c[addr - 0xd800];
 #else
        return subsys_c[addr - 0xd800];
 #endif
@@ -2229,12 +2708,14 @@ uint32_t DISPLAY::read_data8(uint32_t addr)
        // ACCESS VIA ALU.
        else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
                addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
+# if defined(_FM77AV40EX) || defined(_FM77AV40SX)
+               if(vram_active_block != 0) {
+                       offset = 0;
+               }
+# endif                
 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)                
                if(display_mode == DISPLAY_MODE_8_400L) {
                        uint32_t page_offset_alt = 0;
-# if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-                       if(vram_active_block != 0) page_offset_alt = 0x18000;
-# endif                
                        uint32_t color;
                        uint32_t pagemod;
                        color = (addr & 0x18000) >> 15;
@@ -2245,6 +2726,12 @@ uint32_t DISPLAY::read_data8(uint32_t addr)
                        } else {
                                offset = offset_point << 1;
                        }
+# if defined(_FM77AV40EX) || defined(_FM77AV40SX)
+                       if(vram_active_block != 0) {
+                               page_offset_alt = 0x18000;
+                               offset = 0;
+                       }
+# endif                
                        return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset_alt];
                }
 # endif                
@@ -2278,6 +2765,9 @@ void DISPLAY::write_mmio(uint32_t addr, uint8_t data)
                // FM77 SPECIFIED
                case 0x05:
                        set_cyclesteal((uint8_t)data);
+#  if defined(_FM77L4)
+                       setup_400linemode((uint8_t)data);
+#  endif
                        break;
 #endif
 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
@@ -2304,25 +2794,93 @@ void DISPLAY::write_mmio(uint32_t addr, uint8_t data)
                        break;
                // BUSY
                case 0x0a:
-                       if(clr_count <= 0) {
-                               set_subbusy();
-                       } else { // Read once when using clr_foo() to set busy flag.
+                       if(delay_busy) { // If WRITE after READ immediately.Perhaps use CLR insn.
                                double usec;
+                               // Delay at least 5+ clocks (CLR $D40A or CLR (INDEX = $D40A))
                                if(clock_fast) {
-                                       usec = (1000.0 * 1000.0) / 2000000.0;
+                                       usec = (6000.0 * 1000.0) / 2000000.0;
                                } else {
-                                       usec = (1000.0 * 1000.0) / 999000.0;
+                                       usec = (6000.0 * 1000.0) / 999000.0;
                                }
-                               if(!is_cyclesteal && vram_accessflag)  usec = usec * 3.0;
-                               usec = (double)clr_count * usec;
-                               register_event(this, EVENT_FM7SUB_CLR_BUSY, usec, false, NULL); // NEXT CYCLE_
+                               register_event(this, EVENT_FM7SUB_DELAY_BUSY, usec, false, NULL); // NEXT CYCLE_
                                reset_subbusy();
-                               clr_count = 0;
-                       }
+                               delay_busy = false;
+                       } else {
+                               set_subbusy();
+                       } 
                        break;
                // LED
+#if defined(_FM77L4)
+               case 0x0b:
+                       if(stat_400linecard) {
+                               l4crtc->write_io8(0, data & 0x1f);
+                       }
+                       break;
+               case 0x0c:
+                       if(stat_400linecard) {
+                               l4crtc->write_io8(1, data);
+                               // Update parameters.
+                               uint8_t crtc_addr = l4crtc->read_io8(0);
+                               const uint8_t *regs = l4crtc->get_regs();
+                               switch(crtc_addr & 0x1f) {
+                               case 10:
+                               case 11:
+                                       cursor_addr.w.l &= 0x0ffc;
+                                       cursor_addr.w.l |= (((uint16_t)regs[14]) << 10);
+                                       cursor_addr.w.l |= (((uint16_t)regs[15]) << 2);
+                                       if(cursor_lsb) {
+                                               cursor_addr.w.l += 2;
+                                       }
+                                       cursor_addr.w.l &= 0xfff;
+                                       // Redraw request
+                                       if((crtc_addr & 0x1f) == 10) {
+                                               double usec;
+                                               if(event_id_l4_cursor_blink >= 0) {
+                                                       cancel_event(this, event_id_l4_cursor_blink);
+                                               }
+                                               usec = ((data & 0x20) == 0) ? 160.0 : 320.0;
+                                               usec = usec * 1000.0;
+                                               register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
+                                       }
+                                       break;
+                               case 12:
+                                       text_start_addr.w.l &= 0x03fc;
+                                       text_start_addr.w.l |= (((uint16_t)data & 3) << 10);
+                                       text_scroll_count++;
+                                       if((text_scroll_count & 1) == 0) {
+                                               // Redraw request
+                                       }
+                                       break;
+                               case 13:
+                                       text_start_addr.w.l &= 0xfc00;
+                                       text_start_addr.w.l |= ((uint16_t)data << 2);
+                                       text_scroll_count++;
+                                       if((text_scroll_count & 1) == 0) {
+                                               // Redraw request
+                                       }
+                               case 14:
+                               case 15:
+                                       text_scroll_count++;
+                                       if((text_scroll_count & 1) == 0) {
+                                               // Redraw request
+                                               cursor_addr.w.l &= 0x0ffc;
+                                               cursor_addr.w.l |= (((uint16_t)regs[14]) << 10);
+                                               cursor_addr.w.l |= (((uint16_t)regs[15]) << 2);
+                                               if(cursor_lsb) {
+                                                       cursor_addr.w.l += 2;
+                                               }
+                                               cursor_addr.w.l &= 0xfff;
+                                       }
+                                       break;
+                               default:
+                                       break;
+                               }
+                                       
+                       }
+                       break;
+#endif                 
                case 0x0d:
-                       keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
+                       call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
                        break;
                // OFFSET
                case 0x0e:
@@ -2412,7 +2970,7 @@ void DISPLAY::write_mmio(uint32_t addr, uint8_t data)
                        break;
                // KEYBOARD ENCODER
                case 0x31:
-                       keyboard->write_data8(0x31, data);
+                       call_write_data8(keyboard, 0x31, data);
                        break;
 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
                case 0x33: //
@@ -2620,7 +3178,7 @@ void DISPLAY::write_cpu_vram_data8(uint32_t addr, uint8_t data)
        uint32_t color = (addr & 0xc000) >> 14;
 #if defined(_FM77AV_VARIANTS)
        if(use_alu) {
-               alu->read_data8(addr);
+               call_read_data8(alu, addr);
                return;
        }
 #endif 
@@ -2630,6 +3188,37 @@ void DISPLAY::write_cpu_vram_data8(uint32_t addr, uint8_t data)
                if(color > 2) color = 0;
        }
 #endif
+#if defined(_FM77L4)
+       if(mode400line) {
+               if(addr < 0x8000) {
+                       if(workram_l4) {
+                               if(!(multimode_accessflags[2])) write_vram_data8(addr & 0x7fff, data);
+                               return;
+                       }
+               } else if(addr < 0x9800) {
+                       uint32_t naddr;
+                       uint32_t x, y;
+                       addr = addr & 0x0fff;
+                       if(text_vram[addr] != data) {
+                               text_vram[addr] = data;
+                               if(text_width40) {
+                                       x = ((addr / 2) % 40) / 8;
+                                       y = (addr / 2) / 40;
+                               } else { // Width 80
+                                       x = ((addr / 2) % 80) / 8;
+                                       y = (addr / 2) / 80;
+                               }
+                               for(int yy = 0; yy < 8; yy++) {
+                                       naddr = (y + yy) * 5 + x;
+                                       vram_wrote_table[naddr] = true;
+                               }
+                       }
+                       return;
+               } else {
+                       return;
+               }
+       }
+#endif
 #if !defined(_FM8)
        //if((multimode_accessmask & (1 << color)) != 0) return;
        if(multimode_accessflags[color]) return;
@@ -2708,9 +3297,6 @@ void DISPLAY::write_data8(uint32_t addr, uint32_t data)
                        uint32_t naddr;
                        uint32_t page_offset_alt = 0;
                        uint32_t pagemod;
-# if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-                       if(vram_active_block != 0) page_offset_alt = 0x18000;
-# endif                
                        color = (addr & 0x18000) >> 15;
                        if(color > 2) color = 0;
                        if (active_page != 0) {
@@ -2718,6 +3304,12 @@ void DISPLAY::write_data8(uint32_t addr, uint32_t data)
                        } else {
                                offset = offset_point << 1;
                        }
+# if defined(_FM77AV40EX) || defined(_FM77AV40SX)
+                       if(vram_active_block != 0) {
+                               page_offset_alt = 0x18000;
+                               offset = 0;
+                       }
+# endif                
                        naddr = (addr & 0x7fff) >> 4;
                        pagemod = 0x8000 * color;
                        vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
@@ -2761,12 +3353,14 @@ void DISPLAY::initialize()
 {
        int i;
 
+       memset(io_w_latch, 0xff, sizeof(io_w_latch));
        screen_update_flag = true;
        memset(gvram, 0x00, sizeof(gvram));
        vram_wrote_shadow = false;
        memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
        for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
        for(i = 0; i < 411; i++) vram_draw_table[i] = false;
+       force_update = false;
 
        memset(console_ram, 0x00, sizeof(console_ram));
        memset(work_ram, 0x00, sizeof(work_ram));
@@ -2778,10 +3372,10 @@ void DISPLAY::initialize()
        
        diag_load_subrom_c = false;
 #if defined(_FM8)      
-       if(read_bios(_T("SUBSYS_8.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
+       if(read_bios(_T(ROM_FM8_SUBSYSTEM), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
        this->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
 #else
-       if(read_bios(_T("SUBSYS_C.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
+       if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_C), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
        this->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
 #endif
 #if defined(_FM77AV_VARIANTS)
@@ -2791,15 +3385,15 @@ void DISPLAY::initialize()
        memset(submem_hidden, 0x00, sizeof(submem_hidden));
    
        diag_load_subrom_a = false;
-       if(read_bios(_T("SUBSYS_A.ROM"), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
+       if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_A), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
        this->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
 
        diag_load_subrom_b = false;
-       if(read_bios(_T("SUBSYS_B.ROM"), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
+       if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_B), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
        this->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
 
        diag_load_subrom_cg = false;
-       if(read_bios(_T("SUBSYSCG.ROM"), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
+       if(read_bios(_T(ROM_FM7_SUBSYSTEM_CG), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
        this->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
@@ -2809,6 +3403,36 @@ void DISPLAY::initialize()
        ram_protect = true;
 # endif
 #endif
+#if defined(_FM77L4)
+       memset(subsys_cg_l4, 0xff, sizeof(subsys_cg_l4));
+       memset(subsys_l4, 0xff, sizeof(subsys_l4));
+       
+       read_bios(_T(ROM_FM77_400LINE_ANKCG), subsys_cg_l4, sizeof(subsys_cg_l4));
+       read_bios(_T(ROM_FM77_400LINE_SUBSYS), subsys_l4, sizeof(subsys_l4));
+       memset(text_vram, 0x00, sizeof(text_vram));
+       //memset(crtc_regs, 0x00, sizeof(crtc_regs));
+       
+       workram_l4 = false;
+       cursor_lsb = false;
+    text_width40 = false;
+       
+       text_blink = true;
+       cursor_blink = true;
+       
+       text_start_addr.d = 0x0000;
+       text_lines = 64;
+       text_xmax = 80;
+       
+       cursor_addr.d = 0;
+       cursor_start = 0;
+       cursor_end = 15;
+       cursor_type = 0;
+       text_scroll_count = 0;
+       
+       event_id_l4_cursor_blink = -1;
+       event_id_l4_text_blink = -1;
+#endif
+       
        init_read_table();
        init_write_table();
        
@@ -2820,14 +3444,22 @@ void DISPLAY::initialize()
                analog_palette_g[i] = (i & 0xf00) >> 4;
                analog_palette_b[i] = (i & 0x00f) << 4;
                calc_apalette(i);
+               memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
        }
 #endif
-#if defined(_FM77AV_VARIANTS)
+       for(i = 0; i < 8; i++) set_dpalette(i, i);
+#if defined(USE_GREEN_DISPLAY)
+       memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
+       use_green_monitor = false;
+#endif
+       
+       memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
+//#if defined(_FM77AV_VARIANTS)
        hblank_event_id = -1;
        hdisp_event_id = -1;
        vsync_event_id = -1;
        vstart_event_id = -1;
-#endif
+//#endif
 #if defined(_FM8)
        clock_fast = false;
 #else
@@ -2844,11 +3476,6 @@ void DISPLAY::initialize()
                multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
        }
 
-#if !defined(FIXED_FRAMEBUFFER_SIZE)
-       emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
-#else
-       emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
-#endif
        prev_clock = SUBCLOCK_NORMAL;
        //enter_display();
        nmi_event_id = -1;
@@ -2861,12 +3488,19 @@ void DISPLAY::initialize()
 #else
        emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
 #endif
-
+       emu->set_vm_screen_lines(200);
+#if defined(_FM77AV40SX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
+       mode400line = false;
+       mode256k = false;
+#elif defined(_FM77L4)
+       mode400line = false;
+#endif
+       
        palette_changed = true;
-#if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
+//#if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
        //register_vline_event(this);
-       //register_frame_event(this);
-#endif 
+       register_frame_event(this);
+//#endif       
        setup_display_mode();
 }
 
@@ -2874,310 +3508,219 @@ void DISPLAY::release()
 {
 }
 
-#define STATE_VERSION 8
-void DISPLAY::save_state(FILEIO *state_fio)
-{
-       state_fio->FputUint32_BE(STATE_VERSION);
-       state_fio->FputInt32_BE(this_device_id);
-       this->out_debug_log(_T("Save State: DISPLAY : id=%d ver=%d\n"), this_device_id, STATE_VERSION);
+#define STATE_VERSION 12
 
-       {
-               int i;
-               state_fio->FputInt32_BE(clr_count);
-               state_fio->FputBool(halt_flag);
-               state_fio->FputInt32_BE(active_page);
-               state_fio->FputBool(sub_busy);
-               state_fio->FputBool(crt_flag);
-               state_fio->FputBool(vram_wrote);
-               state_fio->FputBool(is_cyclesteal);
-               
-               state_fio->FputBool(clock_fast);
-               
+bool DISPLAY::process_state(FILEIO *state_fio, bool loading)
+{
+       if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+               return false;
+       }
+       if(!state_fio->StateCheckInt32(this_device_id)) {
+               return false;
+       }
+       {
+               int i;
+               state_fio->StateBool(delay_busy);
+               state_fio->StateBool(halt_flag);
+               state_fio->StateInt32(active_page);
+               state_fio->StateBool(sub_busy);
+               state_fio->StateBool(crt_flag);
+               state_fio->StateBool(vram_wrote);
+               state_fio->StateBool(is_cyclesteal);
+               
+               state_fio->StateBool(clock_fast);
+               
 #if defined(_FM77AV_VARIANTS)
-               state_fio->FputBool(subcpu_resetreq);
-               state_fio->FputBool(power_on_reset);
+               state_fio->StateBool(subcpu_resetreq);
+               state_fio->StateBool(power_on_reset);
 #endif 
-               state_fio->FputBool(cancel_request);
-               state_fio->FputBool(key_firq_req);
-
-               state_fio->FputInt32_BE(display_mode);
-               state_fio->FputUint32_BE(prev_clock);
-
+               state_fio->StateBool(cancel_request);
+               state_fio->StateBool(key_firq_req);
+               state_fio->StateInt32(display_mode);
+               state_fio->StateUint32(prev_clock);
 #if !defined(_FM8)     
-               state_fio->Fwrite(dpalette_data, sizeof(dpalette_data), 1);
-               state_fio->FputUint8(multimode_accessmask);
-               state_fio->FputUint8(multimode_dispmask);
+               state_fio->StateBuffer(dpalette_data, sizeof(dpalette_data), 1);
+               state_fio->StateUint8(multimode_accessmask);
+               state_fio->StateUint8(multimode_dispmask);
 #endif         
-               state_fio->FputUint32_BE(offset_point);
+               state_fio->StateUint32(offset_point);
 #if defined(_FM77AV_VARIANTS)
-               state_fio->FputUint32_BE(offset_point_bank1);
+               state_fio->StateUint32(offset_point_bank1);
 #endif         
-               for(i = 0; i < 2; i++) {
-                       state_fio->FputUint32_BE(tmp_offset_point[i].d);
-                       state_fio->FputBool(offset_changed[i]);
-               }
-               state_fio->FputBool(offset_77av);
-               state_fio->FputBool(diag_load_subrom_c);
-               
-       
-               state_fio->Fwrite(io_w_latch, sizeof(io_w_latch), 1);
-               state_fio->Fwrite(console_ram, sizeof(console_ram), 1);
-               state_fio->Fwrite(work_ram, sizeof(work_ram), 1);
-               state_fio->Fwrite(shared_ram, sizeof(shared_ram), 1);
-               state_fio->Fwrite(subsys_c, sizeof(subsys_c), 1);
-               state_fio->Fwrite(gvram, sizeof(gvram), 1);
-               state_fio->Fwrite(gvram_shadow, sizeof(gvram_shadow), 1);
-       
+               //for(i = 0; i < 2; i++) {
+               state_fio->StateBuffer(tmp_offset_point, sizeof(tmp_offset_point), 1);
+               state_fio->StateBuffer(offset_changed, sizeof(offset_changed), 1);
+               //}
+               state_fio->StateBool(offset_77av);
+               state_fio->StateBool(diag_load_subrom_c);
+               state_fio->StateBuffer(io_w_latch, sizeof(io_w_latch), 1);
+               state_fio->StateBuffer(console_ram, sizeof(console_ram), 1);
+               state_fio->StateBuffer(work_ram, sizeof(work_ram), 1);
+               state_fio->StateBuffer(shared_ram, sizeof(shared_ram), 1);
+               state_fio->StateBuffer(subsys_c, sizeof(subsys_c), 1);
+               state_fio->StateBuffer(gvram, sizeof(gvram), 1);
+               state_fio->StateBuffer(gvram_shadow, sizeof(gvram_shadow), 1);
 #if defined(_FM77_VARIANTS)
-               state_fio->FputBool(kanjisub);
-               state_fio->FputUint16_BE(kanjiaddr.w.l);
+               state_fio->StateBool(kanjisub);
+               state_fio->StateUint32(kanjiaddr.d);
 # if defined(_FM77L4)
-               state_fio->FputBool(mode400line);
-               state_fio->FputBool(stat_400linecard);
+               state_fio->StateBool(mode400line);
+               state_fio->StateBool(stat_400linecard);
 # endif
 #elif defined(_FM77AV_VARIANTS)
-               state_fio->FputBool(kanjisub);
-               state_fio->FputUint16_BE(kanjiaddr.w.l);
-
-               state_fio->FputBool(vblank);
-               state_fio->FputBool(vsync);
-               state_fio->FputBool(hblank);
-               state_fio->FputInt32_BE(vblank_count);
-               
-               state_fio->FputBool(mode320);
-               state_fio->FputInt8(display_page);
-               state_fio->FputInt8(display_page_bak);
-               state_fio->FputInt32_BE(cgrom_bank);
+               state_fio->StateBool(kanjisub);
+               state_fio->StateUint32(kanjiaddr.d);
+               state_fio->StateBool(mode320);
+               state_fio->StateInt32(cgrom_bank);
 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
-    defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
-               state_fio->FputInt32_BE(vram_bank);
+       defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
+               state_fio->StateInt32(vram_bank);
 #endif 
+               state_fio->StateUint32(displine);
+               state_fio->StateUint8(subrom_bank);
+               state_fio->StateUint8(subrom_bank_using);
+               state_fio->StateBool(nmi_enable);
+               state_fio->StateBool(use_alu);
+               state_fio->StateUint32(apalette_index.d);
+               state_fio->StateBuffer(analog_palette_r, sizeof(analog_palette_r), 1);
+               state_fio->StateBuffer(analog_palette_g, sizeof(analog_palette_g), 1);
+               state_fio->StateBuffer(analog_palette_b, sizeof(analog_palette_b), 1);
+               state_fio->StateBool(diag_load_subrom_a);
+               state_fio->StateBool(diag_load_subrom_b);
+               state_fio->StateBool(diag_load_subrom_cg);
        
-               state_fio->FputUint32_BE(displine);
-               state_fio->FputUint8(subrom_bank);
-               state_fio->FputUint8(subrom_bank_using);
-       
-               state_fio->FputBool(nmi_enable);
-               state_fio->FputBool(use_alu);
-               
-               state_fio->FputUint8(apalette_index.b.l);
-               state_fio->FputUint8(apalette_index.b.h);
-               state_fio->Fwrite(analog_palette_r, sizeof(analog_palette_r), 1);
-               state_fio->Fwrite(analog_palette_g, sizeof(analog_palette_g), 1);
-               state_fio->Fwrite(analog_palette_b, sizeof(analog_palette_b), 1);
-               
-
-               state_fio->FputBool(diag_load_subrom_a);
-               state_fio->FputBool(diag_load_subrom_b);
-               state_fio->FputBool(diag_load_subrom_cg);
-       
-               state_fio->Fwrite(subsys_a, sizeof(subsys_a), 1);
-               state_fio->Fwrite(subsys_b, sizeof(subsys_b), 1);
-               state_fio->Fwrite(subsys_cg, sizeof(subsys_cg), 1);
-               state_fio->Fwrite(submem_hidden, sizeof(submem_hidden), 1);
+               state_fio->StateBuffer(subsys_a, sizeof(subsys_a), 1);
+               state_fio->StateBuffer(subsys_b, sizeof(subsys_b), 1);
+               state_fio->StateBuffer(subsys_cg, sizeof(subsys_cg), 1);
+               state_fio->StateBuffer(submem_hidden, sizeof(submem_hidden), 1);
 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
-               state_fio->FputBool(mode400line);
-               state_fio->FputBool(mode256k);
-               
-               state_fio->FputBool(monitor_ram);
+               state_fio->StateBool(mode400line);
+               state_fio->StateBool(mode256k);
+               state_fio->StateBool(monitor_ram);
 #  if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-               state_fio->FputUint16_BE(window_low);
-               state_fio->FputUint16_BE(window_high);
-               state_fio->FputUint16_BE(window_xbegin);
-               state_fio->FputUint16_BE(window_xend);
-               state_fio->FputBool(window_opened);
+               state_fio->StateUint16(window_low);
+               state_fio->StateUint16(window_high);
+               state_fio->StateUint16(window_xbegin);
+               state_fio->StateUint16(window_xend);
+               state_fio->StateBool(window_opened);
 #  endif       
-               state_fio->FputBool(kanji_level2);
-
-               state_fio->FputUint8(vram_active_block);
-               state_fio->FputUint8(vram_display_block);
-               state_fio->FputUint8(console_ram_bank);
-               state_fio->FputBool(ram_protect);
-               
-               state_fio->FputUint32_BE(cgram_bank);
-               state_fio->Fwrite(subsys_ram, sizeof(subsys_ram), 1);
-               state_fio->Fwrite(submem_cgram, sizeof(submem_cgram), 1);
-               state_fio->Fwrite(submem_console_av40, sizeof(submem_console_av40), 1);
+               state_fio->StateBool(kanji_level2);
+               state_fio->StateUint8(vram_active_block);
+               state_fio->StateUint8(vram_display_block);
+               state_fio->StateUint8(console_ram_bank);
+               state_fio->StateBool(ram_protect);
+               state_fio->StateUint8(cgram_bank);
+               state_fio->StateBuffer(subsys_ram, sizeof(subsys_ram), 1);
+               state_fio->StateBuffer(submem_cgram, sizeof(submem_cgram), 1);
+               state_fio->StateBuffer(submem_console_av40, sizeof(submem_console_av40), 1);
 # endif
 #endif
-       }
-       // V2
-       {
-               state_fio->FputInt32_BE(nmi_event_id);
-#if defined(_FM77AV_VARIANTS)
-               state_fio->FputInt32_BE(hblank_event_id);
-               state_fio->FputInt32_BE(hdisp_event_id);
-               state_fio->FputInt32_BE(vsync_event_id);
-               state_fio->FputInt32_BE(vstart_event_id);
+       }
+       // V2
+       {
+               state_fio->StateInt32(nmi_event_id);
+//#if defined(_FM77AV_VARIANTS)
+               state_fio->StateInt32(hblank_event_id);
+               state_fio->StateInt32(hdisp_event_id);
+               state_fio->StateInt32(vsync_event_id);
+               state_fio->StateInt32(vstart_event_id);
+//#endif
+               state_fio->StateBool(firq_mask);
+               state_fio->StateBool(vram_accessflag);
+               state_fio->StateInt8(display_page);
+               state_fio->StateInt8(display_page_bak);
+               state_fio->StateBool(vblank);
+               state_fio->StateBool(vsync);
+               state_fio->StateBool(hblank);
+               state_fio->StateInt32(vblank_count);
+       }                       
+#if defined(_FM77L4)
+       state_fio->StateBuffer(subsys_cg_l4, sizeof(subsys_cg_l4), 1);
+       state_fio->StateBuffer(subsys_l4, sizeof(subsys_l4), 1);
+       state_fio->StateBuffer(text_vram, sizeof(text_vram), 1);
+       //state_fio->Fwrite(crtc_regs, sizeof(crtc_regs), 1);
+       state_fio->StateBool(workram_l4);
+       state_fio->StateBool(cursor_lsb);
+       state_fio->StateBool(text_width40);
+       
+       state_fio->StateBool(text_blink);
+       state_fio->StateBool(cursor_blink);
+       
+       state_fio->StateUint32(text_start_addr.d);
+       state_fio->StateUint32(text_lines);
+       state_fio->StateUint32(text_xmax);
+       
+       state_fio->StateUint32(cursor_addr.d);
+       state_fio->StateInt32(cursor_start);
+       state_fio->StateInt32(cursor_end);
+       state_fio->StateUint8(cursor_type);
+       state_fio->StateUint8(text_scroll_count);
+       state_fio->StateInt32(event_id_l4_cursor_blink);
+       state_fio->StateInt32(event_id_l4_text_blink);
 #endif
-               state_fio->FputBool(firq_mask);
-               state_fio->FputBool(vram_accessflag);
-       }                       
-}
 
-bool DISPLAY::load_state(FILEIO *state_fio)
-{
-
-       uint32_t version = state_fio->FgetUint32_BE();
-       if(this_device_id != state_fio->FgetInt32_BE()) {
-               return false;
-       }
-       this->out_debug_log(_T("Load State: DISPLAY : id=%d ver=%d\n"), this_device_id, version);
-   
-       if(version >= 1) {
+       if(loading) {   
                int addr;
                int i;
-               clr_count = state_fio->FgetInt32_BE();
-               halt_flag = state_fio->FgetBool();
-               active_page = state_fio->FgetInt32_BE();
-               sub_busy = state_fio->FgetBool();
-               crt_flag = state_fio->FgetBool();
-               vram_wrote = state_fio->FgetBool();
                crt_flag_bak = true;
                for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
                for(i = 0; i < 411; i++) vram_draw_table[i] = true;
-               is_cyclesteal = state_fio->FgetBool();
-       
-               clock_fast = state_fio->FgetBool();
-
-#if defined(_FM77AV_VARIANTS)
-               subcpu_resetreq = state_fio->FgetBool();
-               power_on_reset = state_fio->FgetBool();
-#endif         
-               cancel_request = state_fio->FgetBool();
-               key_firq_req = state_fio->FgetBool();
-
-               display_mode = state_fio->FgetInt32_BE();
-               prev_clock = state_fio->FgetUint32_BE();
-       
 #if defined(_FM8)
                for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
+               memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
+  #if defined(USE_GREEN_DISPLAY)
+               memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
+  #endif
 #else
-               state_fio->Fread(dpalette_data, sizeof(dpalette_data), 1);
+       
                for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
-               multimode_accessmask = state_fio->FgetUint8();
-               multimode_dispmask = state_fio->FgetUint8();
+               memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
+#if defined(USE_GREEN_DISPLAY)
+               memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
+#endif
                for(i = 0; i < 4; i++) {
                        multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
                        multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
                }
 #endif
-               offset_point = state_fio->FgetUint32_BE();
-#if defined(_FM77AV_VARIANTS)
-               offset_point_bank1     = state_fio->FgetUint32_BE();
-#endif         
-               for(i = 0; i < 2; i++) {
-                       tmp_offset_point[i].d = state_fio->FgetUint32_BE();
-                       offset_changed[i] = state_fio->FgetBool();
-               }
-               offset_77av = state_fio->FgetBool();
-               diag_load_subrom_c = state_fio->FgetBool();
-               
-               state_fio->Fread(io_w_latch, sizeof(io_w_latch), 1);
-               state_fio->Fread(console_ram, sizeof(console_ram), 1);
-               state_fio->Fread(work_ram, sizeof(work_ram), 1);
-               state_fio->Fread(shared_ram, sizeof(shared_ram), 1);
-               state_fio->Fread(subsys_c, sizeof(subsys_c), 1);
-               state_fio->Fread(gvram, sizeof(gvram), 1);
-               state_fio->Fread(gvram_shadow, sizeof(gvram_shadow), 1);
 #if defined(_FM77_VARIANTS)
-               kanjisub = state_fio->FgetBool();
-               kanjiaddr.d = 0;
-               kanjiaddr.w.l = state_fio->FgetUint16_BE();
 # if defined(_FM77L4)          
-               mode400line = state_fio->FgetBool();
-               stat_400linecard = state_fio->FgetBool();
 # endif                
 #elif defined(_FM77AV_VARIANTS)
-               kanjisub = state_fio->FgetBool();
-               kanjiaddr.d = 0;
-               kanjiaddr.w.l = state_fio->FgetUint16_BE();
-               
-               vblank = state_fio->FgetBool();
-               vsync = state_fio->FgetBool();
-               hblank = state_fio->FgetBool();
-               vblank_count = state_fio->FgetInt32_BE();
-
-               mode320 = state_fio->FgetBool();
-               display_page = state_fio->FgetInt8();
-               display_page_bak = state_fio->FgetInt8();
-               cgrom_bank = state_fio->FgetInt32_BE();
 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
-               vram_bank = state_fio->FgetInt32_BE();
 #endif         
                screen_update_flag = true;
-               displine = state_fio->FgetUint32_BE();
-               subrom_bank = state_fio->FgetUint8();
-               subrom_bank_using = state_fio->FgetUint8();
-       
-               nmi_enable = state_fio->FgetBool();
-               use_alu = state_fio->FgetBool();
-
-               apalette_index.b.l = state_fio->FgetUint8();
-               apalette_index.b.h = state_fio->FgetUint8();
-       
-               state_fio->Fread(analog_palette_r, sizeof(analog_palette_r), 1);
-               state_fio->Fread(analog_palette_g, sizeof(analog_palette_g), 1);
-               state_fio->Fread(analog_palette_b, sizeof(analog_palette_b), 1);
                for(i = 0; i < 4096; i++) calc_apalette(i);
+               memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
                
-               diag_load_subrom_a = state_fio->FgetBool();
-               diag_load_subrom_b = state_fio->FgetBool();
-               diag_load_subrom_cg = state_fio->FgetBool();
-       
-               state_fio->Fread(subsys_a, sizeof(subsys_a), 1);
-               state_fio->Fread(subsys_b, sizeof(subsys_b), 1);
-               state_fio->Fread(subsys_cg, sizeof(subsys_cg), 1);
-               state_fio->Fread(submem_hidden, sizeof(submem_hidden), 1);
-          
-# if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
-               mode400line = state_fio->FgetBool();
-               mode256k = state_fio->FgetBool();
-
-               monitor_ram = state_fio->FgetBool();
-#  if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-               window_low = state_fio->FgetUint16_BE();
-               window_high = state_fio->FgetUint16_BE();
-               window_xbegin = state_fio->FgetUint16_BE();
-               window_xend = state_fio->FgetUint16_BE();
-               window_opened = state_fio->FgetBool();
-# endif        
-               kanji_level2 = state_fio->FgetBool();
-               
-               vram_active_block = state_fio->FgetUint8();
-               vram_display_block = state_fio->FgetUint8();
-               console_ram_bank = state_fio->FgetUint8();
-               ram_protect = state_fio->FgetBool();
-
-               cgram_bank = state_fio->FgetUint32_BE();
-               state_fio->Fread(subsys_ram, sizeof(subsys_ram), 1);
-               state_fio->Fread(submem_cgram, sizeof(submem_cgram), 1);
-               state_fio->Fread(submem_console_av40, sizeof(submem_console_av40), 1);
-# endif
 #endif
                palette_changed = true;
                vram_wrote_shadow = true; // Force Draw
                this->draw_screen();
-               if(version == 1) return true;
-       }
-       if(version >= 2) {      //V2
-               nmi_event_id = state_fio->FgetInt32_BE();
-#if defined(_FM77AV_VARIANTS)
-               hblank_event_id = state_fio->FgetInt32_BE();
-               hdisp_event_id = state_fio->FgetInt32_BE();
-               vsync_event_id = state_fio->FgetInt32_BE();
-               vstart_event_id = state_fio->FgetInt32_BE();
-#endif
-               firq_mask = state_fio->FgetBool();
-               vram_accessflag = state_fio->FgetBool();
+               
                frame_skip_count_draw = 3;
                frame_skip_count_transfer = 3;
                need_transfer_line = true;
-       }                       
-       if(version == STATE_VERSION) return true;
-       setup_display_mode();
-       return false;
-}
+#if defined(USE_GREEN_DISPLAY) && defined(USE_MONITOR_TYPE)
+               memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
+               switch(config.monitor_type) {
+               case FM7_MONITOR_GREEN:
+                       use_green_monitor = true;
+                       break;
+               case FM7_MONITOR_STANDARD:
+               default:
+                       use_green_monitor = false;
+                       break;
+               }
+#else
+               //use_green_monitor = false;
+#endif
+               force_update = true;
+               setup_display_mode();
+       }
+       return true;
+}      
 
-       
+}