OSDN Git Service

[General] Merge Upstream 2018-12-27.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / vram.cpp
index a6de86c..9b804e1 100644 (file)
  *  Sep 27, 2015 : Split from display.cpp .
  */
 
+#include "vm.h"
+#include "emu.h"
 #include "fm7_display.h"
+#if defined(_FM77L4)
+#include "../hd46505.h"
+#endif
+
+extern config_t config;
+
+namespace FM7 {
 
-uint8 DISPLAY::read_vram_8_200l(uint32 addr, uint32 offset)
+void DISPLAY::draw_screen()
 {
-       uint32 page_offset = 0;
-       uint32 pagemod;
-#if defined(_FM77AV_VARIANTS)
-       if(active_page != 0) {
-               page_offset = 0xc000;
-       }
-#endif
-# if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       if(vram_active_block != 0) page_offset += 0x18000;
-# endif
-       pagemod = addr & 0xc000;
-       return gvram[(((addr + offset) & 0x3fff) | pagemod) + page_offset];
+//#if !defined(_FM77AV_VARIANTS)
+       this->draw_screen2();
+//#endif       
 }
 
-uint8 DISPLAY::read_vram_l4_400l(uint32 addr, uint32 offset)
+void DISPLAY::draw_screen2()
 {
-#if defined(_FM77L4)
-       if(addr < 0x8000) {
-               if(workram) {
-                       uint32 raddr = addr & 0x3fff;
-                       if((multimode_accessmask & 0x04) == 0) {
-                               return gvram[0x8000 + (raddr + offset) & 0x7fff];
-                       }
-                       return 0xff;
+       int y;
+       int x;
+       scrntype_t *p, *pp, *p2;
+       int yoff;
+       int yy;
+       int k;
+       //uint32_t rgbmask;
+       uint32_t yoff_d1, yoff_d2;
+       uint16_t wx_begin, wx_end, wy_low, wy_high;
+       bool scan_line = config.scan_line;
+       bool ff = force_update;
+
+#if defined(_FM77AV40EX) || defined(_FM77AV40SX)
+       {
+               wx_begin = window_xbegin;
+               wx_end   = window_xend;
+               wy_low   = window_low;
+               wy_high  = window_high;
+               bool _flag = window_opened; 
+               if((wx_begin < wx_end) && (wy_low < wy_high)) {
+                       window_opened = true;
+               } else {
+                       window_opened = false;
+               }
+               if(_flag != window_opened) {
+                       vram_wrote_shadow = true;
                }
-               pagemod = addr & 0x4000;
-               return gvram[((addr + offset) & mask) | pagemod];
-       } else if(addr < 0x9800) {
-               return textvram[addr & 0x0fff];
-       } else { // $9800-$bfff
-               return subrom_l4[addr - 0x9800];
        }
 #endif
-       return 0xff;
-}
-
-uint8 DISPLAY::read_vram_8_400l(uint32 addr, uint32 offset)
-{
-#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       uint32 color = vram_bank & 0x03;
-       uint32 pagemod;
-       uint32 page_offset = 0;
-       uint32 raddr;
-       if(addr >= 0x8000) return 0xff;
-# if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       if(vram_active_block != 0) page_offset += 0x18000;
-# endif
-       if(color > 2) color = 0;
-       pagemod = 0x8000 * color;
-       return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
+//     frame_skip_count_draw++;
+#if defined(_FM77AV_VARIANTS)
+       yoff_d2 = 0;
+       yoff_d1 = 0;
+#else
+       //if(!(vram_wrote_shadow)) return;
+       yoff_d1 = yoff_d2 = offset_point;
 #endif
-       return 0xff;
-}
-
-uint8 DISPLAY::read_vram_8_400l_direct(uint32 addr, uint32 offset)
-{
-#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       uint32 pagemod;
-       uint32 page_offset = 0;
-       pagemod = addr & 0x18000;
-# if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       //addr = addr % 0x18000;
-       if(vram_active_block != 0) page_offset += 0x18000;
+       // Set blank
+       int ylines;
+       int xpixels;
+       switch(display_mode) {
+       case DISPLAY_MODE_8_200L:
+               xpixels = 640;
+               ylines = 200;
+               break;
+       case DISPLAY_MODE_8_400L:
+               xpixels = 640;
+               ylines = 400;
+               break;
+       default:
+               xpixels = 320;
+               ylines = 200;
+               break;
+       }
+# if !defined(FIXED_FRAMEBUFFER_SIZE)
+       emu->set_vm_screen_size(xpixels, ylines, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
 # endif
-       return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
+       emu->set_vm_screen_lines(ylines);
+       if(!crt_flag) {
+               if(crt_flag_bak) {
+                       scrntype_t *ppp;
+#if !defined(FIXED_FRAMEBUFFER_SIZE)
+                       for(y = 0; y < ylines; y += 8) {
+                               for(yy = 0; yy < 8; yy++) {
+                                       vram_draw_table[y + yy] = false;
+                                       ppp = emu->get_screen_buffer(y + yy);
+                                       if(ppp != NULL) memset(ppp, 0x00, xpixels * sizeof(scrntype_t));
+                               }
+                       }
+#else
+                       for(y = 0; y < 400; y += 8) {
+                               for(yy = 0; yy < 8; yy++) {
+                                       vram_draw_table[y + yy] = false;
+                                       ppp = emu->get_screen_buffer(y + yy);
+                                       if(ppp != NULL) memset(ppp, 0x00, 640 * sizeof(scrntype_t));
+                               }
+                       }
 #endif
-       return 0xff;
-}
-
-uint8 DISPLAY::read_vram_4096(uint32 addr, uint32 offset)
-{
-#if defined(_FM77AV_VARIANTS)
-       uint32 page_offset = 0;
-       uint32 pagemod;
-       if(active_page != 0) {
-               page_offset = 0xc000;
+                       
+               }
+               crt_flag_bak = crt_flag;
+               return;
        }
-       pagemod = addr & 0xe000;
+       crt_flag_bak = crt_flag;
+       if(!(vram_wrote_shadow | ff)) return;
+       vram_wrote_shadow = false;
+       if(display_mode == DISPLAY_MODE_8_200L) {
+               _render_command_data_t cmd;
+               uint32_t yoff_d = 0;
+               int ii;
+               yoff = 0;
+#if defined(USE_GREEN_DISPLAY)
+               if(use_green_monitor) {
+                       cmd.palette = dpalette_pixel_green;
+               } else {
+                       cmd.palette = dpalette_pixel;
+               }
+#else
+               cmd.palette = dpalette_pixel;
+#endif                         
+               for(int i = 0; i < 3; i++) {
+                       cmd.data[i] = gvram_shadow;
+                       cmd.baseaddress[i] = i * 0x4000;
+                       cmd.voffset[i] = yoff;
+                       cmd.is_render[i] = false;
+               }
+               if(!multimode_dispflags[0]) cmd.is_render[0] = true;
+               if(!multimode_dispflags[1]) cmd.is_render[1] = true;
+               if(!multimode_dispflags[2]) cmd.is_render[2] = true;
+               cmd.bit_trans_table[0] = (_bit_trans_table_t*)(&(bit_trans_table_2[0][0])); // B
+               cmd.bit_trans_table[1] = (_bit_trans_table_t*)(&(bit_trans_table_1[0][0])); // R
+               cmd.bit_trans_table[2] = (_bit_trans_table_t*)(&(bit_trans_table_0[0][0])); // G
+               cmd.xzoom = 1;
+               cmd.addrmask = 0x3fff;
+               cmd.addrmask2 = 0x3fff;
+               cmd.begin_pos = 0;
+               cmd.shift = 5;
+               cmd.render_width = 80;
+               for(y = 0; y < 200; y += 8) {
+                       for(yy = 0; yy < 8; yy++) {
+                       
+                               if(!(vram_draw_table[y + yy] | ff)) continue;
+                               vram_draw_table[y + yy] = false;
+#if !defined(FIXED_FRAMEBUFFER_SIZE)
+                               p = emu->get_screen_buffer(y + yy);
+                               p2 = NULL;
+#else
+                               p = emu->get_screen_buffer((y + yy) * 2);
+                               p2 = emu->get_screen_buffer((y + yy) * 2 + 1);
+#endif
+                               if(p == NULL) continue;
+                               yoff = (y + yy) * 80;
+                               for(int i = 0; i < 3; i++) {
+                                       cmd.voffset[i] = yoff;
+                               }
+                               
 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       if(vram_active_block != 0) page_offset += 0x18000;
-# endif
-       return gvram[(((addr + offset) & 0x1fff) | pagemod) + page_offset];
+                               int dpage;
+                               dpage = vram_display_block;
+                               bool window_inv = false;
+                               if(window_opened && (wy_low <= (y + yy)) && (wy_high > (y + yy))) {
+                                       if((wx_begin > 0) && (wx_begin < wx_end) && (wx_begin < 80)) {
+                                               // Window : left
+                                               cmd.begin_pos = 0;
+                                               window_inv = false;
+                                               int _wend = wx_end;
+                                               if(_wend >= 80) _wend = 80;
+                                               cmd.render_width = wx_begin;
+                                               yoff_d = (dpage != 0) ? 0x18000 : 0x00000;
+#if defined(_FM77AV_VARIANTS)
+                                               if(display_page_bak == 1) yoff_d += 0xc000;
 #endif
-       return 0xff;
-}
+                                               for(int i = 0; i < 3; i++) {
+                                                       cmd.baseaddress[i] = yoff_d + (i * 0x4000);
+                                               }
+                                               if(cmd.render_width > 0) {
+                                                       if(cmd.render_width > 80) cmd.render_width = 80;
+                                               }
+                                               Render8Colors_Line(&cmd, p, p2, scan_line);
 
-uint8 DISPLAY::read_vram_256k(uint32 addr, uint32 offset)
-{
-#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       uint32 page_offset;
-       uint32 pagemod;
-       page_offset = 0xc000 * (vram_bank & 0x03);
-       pagemod = addr & 0xe000;
-       return gvram[(((addr + offset) & 0x1fff) | pagemod) + page_offset];
+                                               // Center
+                                               cmd.begin_pos = wx_begin;
+                                               cmd.render_width = _wend - wx_begin;
+                                               yoff_d = (dpage != 0) ? 0x00000 : 0x18000;
+#if defined(_FM77AV_VARIANTS)
+                                               if(display_page_bak == 1) yoff_d += 0xc000;
 #endif
-       return 0xff;
-}
-
-
-void DISPLAY::write_vram_8_200l(uint32 addr, uint32 offset, uint32 data)
-{
-       uint32 page_offset = 0;
-       uint32 pagemod;
-       uint8 val8 = data & 0xff;
+                                               for(int i = 0; i < 3; i++) {
+                                                       cmd.baseaddress[i] = yoff_d + (i * 0x4000);
+                                               }
+                                               if(cmd.render_width > 0) {
+                                                       if(cmd.render_width > 80) cmd.render_width = 80;
+                                               }
+                                               Render8Colors_Line(&cmd, &(p[cmd.begin_pos * 8]), &(p2[cmd.begin_pos * 8]) , scan_line);
+                                               // Right
+                                               if(wx_end < 80) {
+                                                       cmd.begin_pos = wx_end;
+                                                       cmd.render_width = 80 - wx_end;
+                                                       yoff_d = (dpage != 0) ? 0x18000 : 0x00000;
 #if defined(_FM77AV_VARIANTS)
-       if(active_page != 0) {
-               page_offset = 0xc000;
-       }
+                                                       if(display_page_bak == 1) yoff_d += 0xc000;
 #endif
-#if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       if(vram_active_block) page_offset += 0x18000;
+                                                       for(int i = 0; i < 3; i++) {
+                                                               cmd.baseaddress[i] = yoff_d + (i * 0x4000);
+                                                       }
+                                                       if(cmd.render_width > 0) {
+                                                               if(cmd.render_width > 80) cmd.render_width = 80;
+                                                       }
+                                                       Render8Colors_Line(&cmd, &(p[cmd.begin_pos * 8]), &(p2[cmd.begin_pos * 8]), scan_line);
+                                               }
+#if defined(FIXED_FRAMEBUFFER_SIZE)
+                                               //CopyDrawnData(p, p2, 80, scan_line);
 #endif
-       pagemod = addr & 0xc000;
-       gvram[(((addr + offset) & 0x3fff) | pagemod) + page_offset] = val8;
-# if defined(_FM77AV_VARIANTS) 
-       if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
-# else
-       vram_wrote = true;
-# endif        
-}
-
-void DISPLAY::write_vram_l4_400l(uint32 addr, uint32 offset, uint32 data)
-{
+                                               continue;
+                                       } else if((wx_begin <= 0) && (wx_begin < wx_end) && (wx_end >= 0)) {
+                                               // Left
+                                               cmd.begin_pos = 0;
+                                               cmd.render_width = wx_end;
+                                               yoff_d = (dpage != 0) ? 0x00000 : 0x18000;
+#if defined(_FM77AV_VARIANTS)
+                                               if(display_page_bak == 1) yoff_d += 0xc000;
+#endif
+                                               for(int i = 0; i < 3; i++) {
+                                                       cmd.baseaddress[i] = yoff_d + (i * 0x4000);
+                                               }
+                                               if(cmd.render_width > 0) {
+                                                       if(cmd.render_width > 80) cmd.render_width = 80;
+                                               }
+                                               if(cmd.render_width > 0) Render8Colors_Line(&cmd, &(p[cmd.begin_pos * 8]), &(p2[cmd.begin_pos * 8]), scan_line);
+                                               // Right
+                                               if(wx_end < 80) {
+                                                       cmd.begin_pos = wx_end;
+                                                       cmd.render_width = 80 - wx_end;
+                                                       yoff_d = (dpage != 0) ? 0x18000 : 0x00000;
+#if defined(_FM77AV_VARIANTS)
+                                                       if(display_page_bak == 1) yoff_d += 0xc000;
+#endif
+                                                       for(int i = 0; i < 3; i++) {
+                                                               cmd.baseaddress[i] = yoff_d + (i * 0x4000);
+                                                       }
+                                                       if(cmd.render_width > 0) {
+                                                               if(cmd.render_width > 80) cmd.render_width = 80;
+                                                       }
+                                                       Render8Colors_Line(&cmd, &(p[cmd.begin_pos * 8]), &(p2[cmd.begin_pos * 8]), scan_line);
+                                               }
+#if defined(FIXED_FRAMEBUFFER_SIZE)
+//                                             CopyDrawnData(p, p2, 80, scan_line);
+#endif
+                                               continue;
+                                       }
+                               }
+#endif
+                               //cmd.begin_pos = 0;
+                               //cmd.render_width = 80;
+# if defined(_FM77AV40EX) || defined(_FM77AV40SX)
+                               yoff_d = (dpage != 0) ? 0x18000 : 0x00000;
+#else
+//                             yoff_d = 0;
+#endif
+#if defined(_FM77AV_VARIANTS)
+                               if(display_page_bak == 1) yoff_d += 0xc000;
+                               for(int i = 0; i < 3; i++) {
+                                       cmd.baseaddress[i] = yoff_d + (i * 0x4000);
+                               }
+#else
+//                             for(int i = 0; i < 3; i++) {
+//                                     cmd.baseaddress[i] = i * 0x4000;
+//                             }
+#endif
+                               
+                               Render8Colors_Line(&cmd, p, p2, scan_line);
+#if defined(FIXED_FRAMEBUFFER_SIZE)
+                               //CopyDrawnData(p, p2, 80, scan_line);
+#endif
+                       }
+               }
+               if(ff) force_update = false;
+               return;
+       }
 #if defined(_FM77L4)
-       if(addr < 0x8000) {
-               if(workram) {
-                       uint32 raddr = addr & 0x3fff;
-                       if((multimode_accessmask & 0x04) == 0) {
-                               gvram[0x8000 + (raddr + offset) & 0x7fff] = (uint8)data;
+       if(display_mode == DISPLAY_MODE_1_400L) {
+               int ii;
+               uint8_t *regs = l4crtc->get_regs();
+               cursor_start = (int)(regs[10] & 0x1f);
+               cursor_end = (int)(regs[11] & 0x1f);
+               cursor_type = (int)((regs[10] & 0x60) >> 5);
+               text_xmax = (int)((uint16_t)regs[1] << 1);
+               text_lines = (int)((regs[9] & 0x1f) + 1);
+               text_ymax = (int)(regs[6] & 0x7f);
+               yoff = 0;
+               // Green display had only connected to FM-8, FM-7/NEW7 and FM-77.
+               for(y = 0; y < 400; y += 8) {
+                       bool renderf = false;
+                       uint32_t naddr;
+                       uint8_t bitcode;
+                       uint8_t charcode;
+                       uint8_t attr_code;
+                       scrntype_t on_color;
+                       int xlim, ylim;
+                       bool do_green;
+                       if((y & 0x0f) == 0) {
+                               for(yy = 0; yy < 16; yy++) renderf |= vram_draw_table[y + yy];
+                               renderf = renderf | ff;
+                               if(renderf) {
+                                       for(yy = 0; yy < 16; yy++) vram_draw_table[y + yy] = true;
+                               }
+                       }
+                       if(use_green_monitor) {
+                               for(yy = 0; yy < 8; yy++) {
+                                       if(!(vram_draw_table[y + yy] | ff)) continue;
+                                       vram_draw_table[y + yy] = false;
+                                       p = emu->get_screen_buffer(y + yy);
+                                       if(p == NULL) continue;
+                                       yoff = (y + yy) * 80;
+                                       for(x = 0; x < 10; x++) {
+                                               for(ii = 0; ii < 8; ii++) {
+                                                       GETVRAM_1_400L_GREEN(yoff + ii, p);
+                                                       p += 8;
+                                               }
+                                               yoff += 8;
+                                       }
+                               }
+                               do_green = true;
+                       } else {
+                               for(yy = 0; yy < 8; yy++) {
+                                       if(!(vram_draw_table[y + yy] | ff)) continue;
+                                       vram_draw_table[y + yy] = false;
+                                       p = emu->get_screen_buffer(y + yy);
+                                       if(p == NULL) continue;
+                                       yoff = (y + yy) * 80;
+                                       for(x = 0; x < 10; x++) {
+                                               for(ii = 0; ii < 8; ii++) {
+                                                       GETVRAM_1_400L(yoff + ii, p);
+                                                       p += 8;
+                                               }
+                                               yoff += 8;
+                                       }
+                               }
+                               do_green = false;
+                       }
+                       // Draw Text
+                       if(renderf) {
+                               bool reverse;
+                               bool display_char;
+                               int raster;
+                               bool cursor_rev;
+                               uint8_t bitdata;
+                               if(text_width40) {
+                                       xlim = 40;
+                               } else {
+                                       xlim = 80;
+                               }
+                               
+                               for(x = 0; x < xlim; x++) {
+                                       naddr = (text_start_addr.w.l + ((y / text_lines) * text_xmax + x) * 2) & 0x0ffe;
+                                       charcode = text_vram[naddr];
+                                       attr_code = text_vram[naddr + 1];
+                                               
+                                       on_color = GETVRAM_TEXTCOLOR(attr_code, do_green);
+                                       
+                                       display_char = ((attr_code & 0x10) == 0);
+                                       reverse = ((attr_code & 0x08) != 0);
+                                       
+                                       for(yy = 0; yy < 16; yy++) {
+                                               raster = y % text_lines;
+                                               bitdata = 0x00;
+                                               p = emu->get_screen_buffer(y + yy);
+                                               if(p == NULL) continue;
+                                               if((raster < 16) && (display_char || text_blink)) {
+                                                       bitdata = subsys_cg_l4[(uint32_t)charcode * 16 + (uint32_t)raster];
+                                               }
+                                               cursor_rev = false;
+                                               if((naddr == (uint32_t)(cursor_addr.w.l)) && (cursor_type != 1) &&
+                                                  (text_blink || (cursor_type == 0))) {
+                                                       if((raster >= cursor_start) && (raster <= cursor_end)) {
+                                                               cursor_rev = true;
+                                                       }
+                                               }
+                                               bitdata = GETVRAM_TEXTPIX(bitdata, reverse, cursor_rev);
+                                               if(bitdata != 0) {
+                                                       if(text_width40) {
+                                                                       scrntype_t *pp = &(p[x * 2]); 
+                                                                       for(ii = 0; ii < 8; ii++) {
+                                                                               if((bitdata & 0x80) != 0) {
+                                                                                       p[0] = on_color;
+                                                                                       p[1] = on_color;
+                                                                               }
+                                                                               bitdata <<= 1;
+                                                                               p += 2;
+                                                                       }                                                                               
+                                                       } else {
+                                                               scrntype_t *pp = &(p[x * 2]); 
+                                                               for(ii = 0; ii < 8; ii++) {
+                                                                       if((bitdata & 0x80) != 0) {
+                                                                               p[0] = on_color;
+                                                                       }
+                                                                       bitdata <<= 1;
+                                                                       p += 1;
+                                                               }                                                                               
+                                                       }
+                                               }
+                                       }
+                               }
                        }
-                       return;
                }
-               pagemod = addr & 0x4000;
-               gvram[((addr + offset) & mask) | pagemod] = (uint8)data;
-       } else if(addr < 0x9800) {
-         textvram[addr & 0x0fff] = (uint8)data;
-       } else { // $9800-$bfff
-               //return subrom_l4[addr - 0x9800];
+               if(ff) force_update = false;
+               return;
        }
-       return;
-#endif 
-}
+#endif
+# if defined(_FM77AV_VARIANTS)
+       if(display_mode == DISPLAY_MODE_4096) {
+               uint32_t mask = 0;
+               int ii;
+               yoff = 0;
+               if(!multimode_dispflags[0]) mask = 0x00f;
+               if(!multimode_dispflags[1]) mask = mask | 0x0f0;
+               if(!multimode_dispflags[2]) mask = mask | 0xf00;
+               for(y = 0; y < 200; y += 4) {
+                       for(yy = 0; yy < 4; yy++) {
+                               if(!(vram_draw_table[y + yy] | ff)) continue;
+                               vram_draw_table[y + yy] = false;
 
-void DISPLAY::write_vram_8_400l(uint32 addr, uint32 offset, uint32 data)
-{
-#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       uint32 color = vram_bank & 0x03;
-       uint32 pagemod;
-       uint32 page_offset = 0;
-       uint8 val8 = (uint8)(data & 0x00ff);
-       if(addr >= 0x8000) return;
-# if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       if(vram_active_block != 0) page_offset += 0x18000;
-# endif   
-       if(color > 2) color = 0;
-       pagemod = 0x8000 * color;
-       //offset = (offset & 0x3fff) << 1;
-       gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset] = val8;
-
-       if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
+#if !defined(FIXED_FRAMEBUFFER_SIZE)
+                               p = emu->get_screen_buffer(y + yy);
+                               p2 = NULL;
+#else
+                               p = emu->get_screen_buffer((y + yy) * 2 );
+                               p2 = emu->get_screen_buffer((y + yy) * 2 + 1);
 #endif
-}
+                               if(p == NULL) continue;
+                               yoff = (y + yy) * 40;
+#  if defined(_FM77AV40EX) || defined(_FM77AV40SX)
+                               if(window_opened && (wy_low <= (y + yy)) && (wy_high > (y + yy))) {
+                                       for(x = 0; x < 40; x++) {
+                                               if((x >= wx_begin) && (x < wx_end)) {
+                                                       GETVRAM_4096(yoff, p, p2, mask, true, scan_line);
+                                               } else {
+                                                       GETVRAM_4096(yoff, p, p2, mask, false, scan_line);
+                                               }
+#if defined(FIXED_FRAMEBUFFER_SIZE)
+                                               p2 += 16;
+                                               p += 16;
+#else
+                                               p += 8;
+#endif
+                                               yoff++;
+                                       }
+                               } else
+#  endif
+                               {
+                                       for(x = 0; x < 5; x++) {
+                                               for(ii = 0; ii < 8; ii++) {
+                                                       GETVRAM_4096(yoff + ii, p, p2, mask, false, scan_line);
+#if defined(FIXED_FRAMEBUFFER_SIZE)
+                                                       p2 += 16;
+                                                       p += 16;
+#else
+                                                       p += 8;
+#endif
+                                               }
+                                               yoff += 8;
+                                       }
+                               }
+                       }
+                  
+               }
+               if(ff) force_update = false;
+               return;
+       }
+#  if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
+       else if(display_mode == DISPLAY_MODE_8_400L) {
+               _render_command_data_t cmd;
+               int ii;
+               yoff = 0;
+               cmd.palette = dpalette_pixel;
+               for(int i = 0; i < 3; i++) {
+                       cmd.data[i] = gvram_shadow;
+                       cmd.baseaddress[i] = i * 0x8000;
+                       cmd.voffset[i] = yoff;
+                       cmd.is_render[i] = false;
+               }
+               if(!multimode_dispflags[0]) cmd.is_render[0] = true;
+               if(!multimode_dispflags[1]) cmd.is_render[1] = true;
+               if(!multimode_dispflags[2]) cmd.is_render[2] = true;
+               cmd.bit_trans_table[0] = (_bit_trans_table_t*)(&(bit_trans_table_2[0][0])); // B
+               cmd.bit_trans_table[1] = (_bit_trans_table_t*)(&(bit_trans_table_1[0][0])); // R
+               cmd.bit_trans_table[2] = (_bit_trans_table_t*)(&(bit_trans_table_0[0][0])); // G
+               cmd.xzoom = 1;
+               cmd.addrmask = 0x7fff;
+               cmd.addrmask2 = 0x7fff;
+               cmd.begin_pos = 0;
+               cmd.shift = 5;
+               cmd.render_width = 80;
+               for(y = 0; y < 400; y += 8) {
+                       for(yy = 0; yy < 8; yy++) {
+                               if(!(vram_draw_table[y + yy] | ff)) continue;
+                               vram_draw_table[y + yy] = false;
 
-void DISPLAY::write_vram_8_400l_direct(uint32 addr, uint32 offset, uint32 data)
-{
-#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       uint32 pagemod;
-       uint32 page_offset = 0;
-       uint8 val8 = (uint8)(data & 0x00ff);
-       //offset = offset & 0x7fff;
-       pagemod = addr & 0x18000;
-# if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       //addr = addr % 0x18000;
-       if(vram_active_block != 0) page_offset += 0x18000;
-# endif 
-       gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset] = val8;
-       if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
+                               p = emu->get_screen_buffer(y + yy);
+                               if(p == NULL) continue;
+                               pp = p;
+                               yoff = (y + yy) * 80;
+                               for(int i = 0; i < 3; i++) {
+                                       cmd.voffset[i] = yoff;
+                               }
+                               int dpage;
+                               bool window_inv = false;
+                               uint32_t yoff_d;
+                               dpage = vram_display_block;
+#    if defined(_FM77AV40EX) || defined(_FM77AV40SX)
+                               if(window_opened && (wy_low <= (y + yy)) && (wy_high > (y + yy))) {
+                                       if((wx_begin > 0) && (wx_begin < wx_end) && (wx_begin < 80)) {
+                                               // Window : left
+                                               cmd.begin_pos = 0;
+                                               window_inv = false;
+                                               int _wend = wx_end;
+                                               if(_wend >= 80) _wend = 80;
+                                               cmd.render_width = wx_begin;
+                                               yoff_d = (dpage != 0) ? 0x18000 : 0x00000;
+                                               for(int i = 0; i < 3; i++) {
+                                                       cmd.baseaddress[i] = yoff_d + (i * 0x8000);
+                                               }
+                                               if(cmd.render_width > 0) {
+                                                       if(cmd.render_width > 80) cmd.render_width = 80;
+                                               }
+                                               Render8Colors_Line(&cmd, p, NULL, false);
+
+                                               // Center
+                                               cmd.begin_pos = wx_begin;
+                                               cmd.render_width = _wend - wx_begin;
+                                               yoff_d = (dpage != 0) ? 0x00000 : 0x18000;
+                                               if(display_page_bak == 1) yoff_d += 0xc000;
+                                               for(int i = 0; i < 3; i++) {
+                                                       cmd.baseaddress[i] = yoff_d + (i * 0x8000);
+                                               }
+                                               if(cmd.render_width > 0) {
+                                                       if(cmd.render_width > 80) cmd.render_width = 80;
+                                               }
+                                               Render8Colors_Line(&cmd, &(p[cmd.begin_pos * 8]), NULL, false);
+                                               // Right
+                                               if(wx_end < 80) {
+                                                       cmd.begin_pos = wx_end;
+                                                       cmd.render_width = 80 - wx_end;
+                                                       yoff_d = (dpage != 0) ? 0x18000 : 0x00000;
+                                                       for(int i = 0; i < 3; i++) {
+                                                               cmd.baseaddress[i] = yoff_d + (i * 0x8000);
+                                                       }
+                                                       if(cmd.render_width > 0) {
+                                                               if(cmd.render_width > 80) cmd.render_width = 80;
+                                                       }
+                                                       Render8Colors_Line(&cmd, &(p[cmd.begin_pos * 8]), NULL, false);
+                                               }
+                                               continue;
+                                       } else if((wx_begin <= 0) && (wx_begin < wx_end) && (wx_end >= 0)) {
+                                               // Left
+                                               cmd.begin_pos = 0;
+                                               cmd.render_width = wx_end;
+                                               yoff_d = (dpage != 0) ? 0x00000 : 0x18000;
+                                               for(int i = 0; i < 3; i++) {
+                                                       cmd.baseaddress[i] = yoff_d + (i * 0x8000);
+                                               }
+                                               if(cmd.render_width > 0) {
+                                                       if(cmd.render_width > 80) cmd.render_width = 80;
+                                               }
+                                               if(cmd.render_width > 0) Render8Colors_Line(&cmd, &(p[cmd.begin_pos * 8]), NULL, false);
+                                               // Right
+                                               if(wx_end < 80) {
+                                                       cmd.begin_pos = wx_end;
+                                                       cmd.render_width = 80 - wx_end;
+                                                       yoff_d = (dpage != 0) ? 0x18000 : 0x00000;
+                                                       for(int i = 0; i < 3; i++) {
+                                                               cmd.baseaddress[i] = yoff_d + (i * 0x8000);
+                                                       }
+                                                       if(cmd.render_width > 0) {
+                                                               if(cmd.render_width > 80) cmd.render_width = 80;
+                                                       }
+                                                       Render8Colors_Line(&cmd, &(p[cmd.begin_pos * 8]), NULL, false);
+                                               }
+                                               continue;
+                                       } 
+                               }
+#    endif
+                               // Not Opened
+                               cmd.begin_pos = 0;
+                               cmd.render_width = 80;
+                               yoff_d = (dpage != 0) ? 0x18000 : 0x00000;
+                               for(int i = 0; i < 3; i++) {
+                                       cmd.baseaddress[i] = yoff_d + (i * 0x8000);
+                               }
+                               if(cmd.render_width > 0) {
+                                       if(cmd.render_width > 80) cmd.render_width = 80;
+                               }
+                               Render8Colors_Line(&cmd, &(p[cmd.begin_pos * 8]), NULL, false);
+                       }
+               }
+               if(ff) force_update = false;
+               return;
+       } else if(display_mode == DISPLAY_MODE_256k) {
+               int ii;
+               //rgbmask = ~multimode_dispmask;
+               //
+               for(y = 0; y < 200; y += 4) {
+                       for(yy = 0; yy < 4; yy++) {
+                               if(!(vram_draw_table[y + yy] | ff)) continue;
+                               vram_draw_table[y + yy] = false;
+#if !defined(FIXED_FRAMEBUFFER_SIZE)
+                               p = emu->get_screen_buffer(y + yy);
+                               p2 = NULL;
+#else
+                               p = emu->get_screen_buffer((y + yy) * 2 );
+                               p2 = emu->get_screen_buffer((y + yy) * 2 + 1);
+#endif
+                               if(p == NULL) continue;
+                               pp = p;
+                               yoff = (y + yy) * 40;
+                               {
+                                       for(x = 0; x < 5; x++) {
+                                               for(ii = 0; ii < 8; ii++) {
+                                                       GETVRAM_256k(yoff + ii, p, p2, scan_line);
+#if !defined(FIXED_FRAMEBUFFER_SIZE)
+                                                       p += 8;
+#else
+                                                       p += 16;
+                                                       p2 += 16;
 #endif
+                                               }
+                                               yoff += 8;
+                                       }
+                               }
+                       }
+               }
+               if(ff) force_update = false;
+               return;
+       }
+#  endif // _FM77AV40
+# endif //_FM77AV_VARIANTS
 }
 
-void DISPLAY::write_vram_4096(uint32 addr, uint32 offset, uint32 data)
+bool DISPLAY::screen_update(void)
 {
-#if defined(_FM77AV_VARIANTS)
-       uint32 page_offset = 0;
-       uint32 pagemod;
-       if(active_page != 0) {
-               page_offset = 0xc000;
+       if(crt_flag) {
+               bool f = screen_update_flag;
+               screen_update_flag = false;
+               return f;
+       } else {
+               if(crt_flag_bak) return true;
        }
-       pagemod = addr & 0xe000;
-#if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       if(vram_active_block != 0) page_offset += 0x18000;
-#endif
-       gvram[(((addr + offset) & 0x1fff) | pagemod) + page_offset] = (uint8)data;
-       if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
-#endif
+       return false;
 }
 
-void DISPLAY::write_vram_256k(uint32 addr, uint32 offset, uint32 data)
+void DISPLAY::reset_screen_update(void)
 {
-#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       uint32 page_offset = 0;
-       uint32 pagemod;
-       page_offset = 0xc000 * (vram_bank & 0x03);
-       pagemod = addr & 0xe000;
-       gvram[(((addr + offset) & 0x1fff) | pagemod) + page_offset] = (uint8)(data & 0xff);
-       if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
-       return;
-#endif
+       screen_update_flag = false;
 }
 
-inline void DISPLAY::GETVRAM_8_200L(int yoff, scrntype *p, uint32 mask, bool window_inv = false)
+void DISPLAY::CopyDrawnData(scrntype_t* src, scrntype_t* dst, int width, bool scan_line)
 {
-       register uint8 b, r, g;
-       register uint32 dot;
-       uint32 yoff_d;
-#if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       int dpage = vram_display_block;
+       if(dst == NULL) return;
+       if(src == NULL) return;
+#if defined(_RGB555) || defined(_RGBA565)
+       static const int shift_factor = 2;
+#else // 24bit
+       static const int shift_factor = 3;
 #endif
-#if defined(_FM77AV_VARIANTS)
-       if(display_page == 1) { // Is this dirty?
-               yoff_d = offset_point_bank1_bak;
-       } else {
-               yoff_d = offset_point_bak;
-       }
-#else
-       yoff_d = offset_point;
-#endif 
-       yoff_d = (yoff + yoff_d) & 0x3fff;
-#if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       if(window_inv) {
-               if(dpage == 0) {
-                       dpage = 1;
-               } else {
-                       dpage = 0;
+       scrntype_vec8_t* vsrc = (scrntype_vec8_t*)__builtin_assume_aligned(src, sizeof(scrntype_vec8_t));
+       scrntype_vec8_t* vdst = (scrntype_vec8_t*)__builtin_assume_aligned(dst, sizeof(scrntype_vec8_t));
+       scrntype_vec8_t tmp_dd;
+       scrntype_vec8_t sline;
+       
+       if(scan_line) {
+__DECL_VECTORIZED_LOOP
+               for(int i = 0; i < 8; i++) {
+                       sline.w[i] = (scrntype_t)RGBA_COLOR(31, 31, 31, 255);
+               }
+__DECL_VECTORIZED_LOOP
+               for(int i = 0; i < width; i++) {
+                       tmp_dd.v = vsrc[i].v;
+                       tmp_dd.v = tmp_dd.v >> shift_factor;
+                       tmp_dd.v = tmp_dd.v & sline.v;
+                       vdst[i].v = tmp_dd.v;
                }
-       }
-       if(dpage != 0) yoff_d += 0x18000;
-#endif
-       b = r = g = 0;
-#if defined(_FM77AV_VARIANTS)
-       if(display_page == 1) {
-               if(mask & 0x01) b = gvram_shadow[yoff_d + 0x0c000];
-               if(mask & 0x02) r = gvram_shadow[yoff_d + 0x10000];
-               if(mask & 0x04) g = gvram_shadow[yoff_d + 0x14000];
        } else {
-               if(mask & 0x01) b = gvram_shadow[yoff_d + 0x00000];
-               if(mask & 0x02) r = gvram_shadow[yoff_d + 0x04000];
-               if(mask & 0x04) g = gvram_shadow[yoff_d + 0x08000];
+__DECL_VECTORIZED_LOOP
+               for(int i = 0; i < width; i++) {
+                       tmp_dd.v = vsrc[i].v;
+                       vdst[i].v = tmp_dd.v;
+               }
        }
-#else
-       if(mask & 0x01) b = gvram[yoff_d + 0x00000];
-       if(mask & 0x02) r = gvram[yoff_d + 0x04000];
-       if(mask & 0x04) g = gvram[yoff_d + 0x08000];
-#endif 
-       dot = ((g & 0x80) >> 5) | ((r & 0x80) >> 6) | ((b & 0x80) >> 7);
-       p[0] = dpalette_pixel[dot];
-       dot = ((g & 0x40) >> 4) | ((r & 0x40) >> 5) | ((b & 0x40) >> 6);
-       p[1] = dpalette_pixel[dot];
-       dot = ((g & 0x20) >> 3) | ((r & 0x20) >> 4) | ((b & 0x20) >> 5);
-       p[2] = dpalette_pixel[dot];
-       dot = ((g & 0x10) >> 2) | ((r & 0x10) >> 3) | ((b & 0x10) >> 4);
-       p[3] = dpalette_pixel[dot];
-                                       
-       dot = ((g & 0x8) >> 1) | ((r & 0x8) >> 2) | ((b & 0x8) >> 3);
-       p[4] = dpalette_pixel[dot];
-       dot = (g & 0x4) | ((r & 0x4) >> 1) | ((b & 0x4) >> 2);
-       p[5] = dpalette_pixel[dot];
-       dot = ((g & 0x2) << 1) | (r & 0x2) | ((b & 0x2) >> 1);
-       p[6] = dpalette_pixel[dot];
-       dot = ((g & 0x1) << 2) | ((r & 0x1) << 1) | (b & 0x1);
-       p[7] = dpalette_pixel[dot];
 }
 
-#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
-inline void DISPLAY::GETVRAM_8_400L(int yoff, scrntype *p, uint32 mask, bool window_inv = false)
+
+#if defined(_FM77L4)
+scrntype_t DISPLAY::GETVRAM_TEXTCOLOR(uint8_t attr, bool do_green)
 {
-       register uint8 b, r, g;
-       register uint32 dot;
-       uint32 yoff_d;
-# if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       int dpage = vram_display_block;
-# endif
-       
-       if(display_page == 1) { // Is this dirty?
-               yoff_d = offset_point_bank1_bak;
+       int color = attr & 0x07;
+       int r, g, b;
+
+       static const int green_g_table[16] = {0, 24, 48, 64, 80, 96, 112, 128,
+                                                                                 140, 155, 175, 186, 210, 220, 240, 255};
+       if(do_green) {
+               if((attr & 0x20) != 0) color += 8;
+               r = b = 0;
+               g = green_g_table[color];
+               if(color >= 10) {
+                       r = (color - 9) * 16;
+                       b = (color - 9) * 16;
+               }
        } else {
-               yoff_d = offset_point_bak;
-       }
-       yoff_d = (yoff + (yoff_d << 1)) & 0x7fff;
-# if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       if(window_inv) {
-               if(dpage == 0) {
-                       dpage = 1;
+               if((attr & 0x20) != 0) {
+                       g = ((color & 4) != 0) ? 255 : 0;
+                       r = ((color & 2) != 0) ? 255 : 0;
+                       b = ((color & 1) != 0) ? 255 : 0;
                } else {
-                       dpage = 0;
+                       g = ((color & 4) != 0) ? 128 : 0;
+                       r = ((color & 2) != 0) ? 128 : 0;
+                       b = ((color & 1) != 0) ? 128 : 0;
                }
        }
-       if(dpage != 0) yoff_d += 0x18000;
-# endif
-       b = r = g = 0;
-       if(mask & 0x01) b = gvram_shadow[yoff_d + 0x00000];
-       if(mask & 0x02) r = gvram_shadow[yoff_d + 0x08000];
-       if(mask & 0x04) g = gvram_shadow[yoff_d + 0x10000];
-
-       dot = ((g & 0x80) >> 5) | ((r & 0x80) >> 6) | ((b & 0x80) >> 7);
-       p[0] = dpalette_pixel[dot];
-       dot = ((g & 0x40) >> 4) | ((r & 0x40) >> 5) | ((b & 0x40) >> 6);
-       p[1] = dpalette_pixel[dot];
-       dot = ((g & 0x20) >> 3) | ((r & 0x20) >> 4) | ((b & 0x20) >> 5);
-       p[2] = dpalette_pixel[dot];
-       dot = ((g & 0x10) >> 2) | ((r & 0x10) >> 3) | ((b & 0x10) >> 4);
-       p[3] = dpalette_pixel[dot];
-                                       
-       dot = ((g & 0x8) >> 1) | ((r & 0x8) >> 2) | ((b & 0x8) >> 3);
-       p[4] = dpalette_pixel[dot];
-       dot = (g & 0x4) | ((r & 0x4) >> 1) | ((b & 0x4) >> 2);
-       p[5] = dpalette_pixel[dot];
-       dot = ((g & 0x2) << 1) | (r & 0x2) | ((b & 0x2) >> 1);
-       p[6] = dpalette_pixel[dot];
-       dot = ((g & 0x1) << 2) | ((r & 0x1) << 1) | (b & 0x1);
-       p[7] = dpalette_pixel[dot];
+       return RGBA_COLOR(r, g, b, 255);
 }
 
-inline void DISPLAY::GETVRAM_256k(int yoff, scrntype *p, uint32 mask)
+uint8_t DISPLAY::GETVRAM_TEXTPIX(uint8_t bitdata, bool reverse, bool cursor_rev)
 {
-       register uint32 b3, r3, g3;
-       register uint32 b4, r4, g4;
-       register uint32 btmp, rtmp, gtmp;
-       
-       register scrntype b, r, g;
-       scrntype pixel;
-       uint32 yoff_d1, yoff_d2;
-       uint32 _bit;
-       int _shift;
-       int cp;
-       
-       r3 = g3 = b3 = 0;
-       r4 = g4 = b4 = 0;
-       r = g = b = 0;
-       
-       yoff_d1 = offset_point_bak;
-       yoff_d2 = offset_point_bank1_bak;
-       yoff_d1 = (yoff + yoff_d1) & 0x1fff;
-       yoff_d2 = (yoff + yoff_d2) & 0x1fff;
-       if(mask & 0x01) {
-               b3  = gvram_shadow[yoff_d1] << 24;
-               b3 |= gvram_shadow[yoff_d1 + 0x02000] << 16;
-               
-               b3 |= gvram_shadow[yoff_d2 + 0x0c000] << 8;
-               b3 |= gvram_shadow[yoff_d2 + 0x0e000] << 0;
-       
-               b4  = gvram_shadow[yoff_d1 + 0x18000] << 8;
-               b4 |= gvram_shadow[yoff_d1 + 0x1a000] << 0;
+       uint8_t ret = bitdata;
+       if(reverse) {
+               ret = (uint8_t)(~ret);
        }
-       if(mask & 0x02) {
-               r3  = gvram_shadow[yoff_d1 + 0x04000] << 24;
-               r3 |= gvram_shadow[yoff_d1 + 0x06000] << 16;
-               r3 |= gvram_shadow[yoff_d2 + 0x10000] << 8;
-               r3 |= gvram_shadow[yoff_d2 + 0x12000] << 0;
-               r4  = gvram_shadow[yoff_d1 + 0x1c000] << 8;
-               r4 |= gvram_shadow[yoff_d1 + 0x1e000] << 0;
+       if(cursor_rev) {
+           ret = (uint8_t)(~ret);
        }
+       return ret;
+}
 
-       if(mask & 0x04) {
-               g3  = gvram_shadow[yoff_d1 + 0x08000] << 24;
-               g3 |= gvram_shadow[yoff_d1 + 0x0a000] << 16;
-               g3 |= gvram_shadow[yoff_d2 + 0x14000] << 8;
-               g3 |= gvram_shadow[yoff_d2 + 0x16000] << 0;
-               
-               g4  = gvram_shadow[yoff_d1 + 0x20000] << 8;
-               g4 |= gvram_shadow[yoff_d1 + 0x22000] << 0;
-       }
-       
-       cp = 0;
-       for(_shift = 7; _shift >= 0; _shift--) {
-               _bit = 0x01010101 << _shift;
-               r = g = b = 0;
-               if(mask & 0x01) {
-                       btmp = (b3 & _bit) >> _shift;
-                       b = (((btmp & (0x01 << 24)) != 0) ? 0x80 : 0) | (((btmp & (0x01 << 16)) != 0)? 0x40 : 0)
-                               | (((btmp & (0x01 << 8)) != 0) ? 0x20 : 0) | (((btmp & 0x01) != 0) ? 0x10   : 0);
-                       btmp = (b4 & _bit) >> _shift;
-                       b = b | (((btmp & (0x01 << 8)) != 0) ? 0x08 : 0) | (((btmp & 0x01) != 0) ? 0x04 : 0);
-               }
-               if(mask & 0x02) {
-                       rtmp = (r3 & _bit) >> _shift;
-                       r = ((rtmp & (0x01 << 24)) ? 0x80 : 0) | ((rtmp & (0x01 << 16)) ? 0x40 : 0)
-                               | ((rtmp & (0x01 << 8)) ? 0x20 : 0) | ((rtmp & 0x01) ? 0x10   : 0);
-                       rtmp = (r4 & _bit) >> _shift;
-                       r = r | ((rtmp & (0x01 << 8)) ? 0x08 : 0) | ((rtmp & 0x01) ? 0x04 : 0);
-               }
-               if(mask & 0x04) {
-                       gtmp = (g3 & _bit) >> _shift;
-                       g = ((gtmp & (0x01 << 24)) ? 0x80 : 0) | ((gtmp & (0x01 << 16)) ? 0x40 : 0)
-                               | ((gtmp & (0x01 << 8)) ? 0x20 : 0) | ((gtmp & 0x01) ? 0x10   : 0);
-                       gtmp = (g4 & _bit) >> _shift;
-                       g = g | ((gtmp & (0x01 << 8)) ? 0x08 : 0) | ((gtmp & 0x01) ? 0x04 : 0);
-               }
+void DISPLAY::GETVRAM_1_400L(int yoff, scrntype_t *p)
+{
+       uint8_t pixel;
+       uint32_t yoff_d;
+       if(p == NULL) return;
+       yoff_d = yoff & 0x7fff;
+       pixel = gvram_shadow[yoff_d];
+       uint16_vec8_t *ppx = (uint16_vec8_t *)__builtin_assume_aligned(&(bit_trans_table_0[pixel][0]), 16);
+       __DECL_ALIGNED(16) uint16_vec8_t tmp_d;
+       scrntype_vec8_t tmp_dd;
+       scrntype_vec8_t *vp = (scrntype_vec8_t *)__builtin_assume_aligned(p, sizeof(scrntype_vec8_t));
+
+       tmp_d.v = ppx->v;
+       tmp_d.v = tmp_d.v >> 5;
        
-               pixel = RGB_COLOR(r, g, b);
-               p[cp] = pixel;
-               p[cp + 1] = pixel;
-               cp += 2;
+__DECL_VECTORIZED_LOOP
+       for(int i = 0; i < 8; i++) {
+               tmp_dd.w[i] = dpalette_pixel[tmp_d.w[i]];
        }
+
+       vp->v = tmp_dd.v;
+}
+
+void DISPLAY::GETVRAM_1_400L_GREEN(int yoff, scrntype_t *p)
+{
+       uint8_t pixel;
+       uint32_t yoff_d;
+       if(p == NULL) return;
+       yoff_d = yoff & 0x7fff;
+       pixel = gvram_shadow[yoff_d];
+       uint16_vec8_t *ppx = (uint16_vec8_t *)__builtin_assume_aligned(&(bit_trans_table_0[pixel][0]), 16);
+       __DECL_ALIGNED(16) uint16_vec8_t tmp_d;
+       scrntype_vec8_t tmp_dd;
+       scrntype_vec8_t *vp = (scrntype_vec8_t *)__builtin_assume_aligned(p, sizeof(scrntype_vec8_t));
+
+       tmp_d.v = ppx->v;
+       tmp_d.v = tmp_d.v >> 5;
        
+__DECL_VECTORIZED_LOOP
+       for(int i = 0; i < 8; i++) {
+               tmp_dd.w[i] = dpalette_pixel_green[tmp_d.w[i]];
+       }
+       vp->v = tmp_dd.v;
+
 }
 #endif
 
+
 #if defined(_FM77AV_VARIANTS)
-inline void DISPLAY::GETVRAM_4096(int yoff, scrntype *p, uint32 mask, bool window_inv = false)
+void DISPLAY::GETVRAM_4096(int yoff, scrntype_t *p, scrntype_t *px,
+                                                  uint32_t mask,
+                                                  bool window_inv,
+                                                  bool scan_line)
 {
-       uint32 b3, r3, g3;
-       scrntype b, r, g;
-       uint32 idx;;
-       scrntype pixel;
-       uint32 yoff_d1, yoff_d2;
+       uint32_t b3, r3, g3;
+       uint8_t  bb[4], rr[4], gg[4];
+       uint16_vec8_t pixels;
+       __DECL_ALIGNED(16) const uint16_t __masks[8] = {(uint16_t)mask, (uint16_t)mask, (uint16_t)mask, (uint16_t)mask, (uint16_t)mask, (uint16_t)mask, (uint16_t)mask, (uint16_t)mask};
+       scrntype_t b, r, g;
+       uint32_t idx;;
+       scrntype_t pixel;
+       uint32_t yoff_d1;
+       uint32_t yoff_d2;
 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
        int dpage = vram_display_block;
 # endif
+       if(p == NULL) return;
        
-       yoff_d1 = offset_point_bak;
-       yoff_d2 = offset_point_bank1_bak;
-       yoff_d1 = (yoff + yoff_d1) & 0x1fff;
-       yoff_d2 = (yoff + yoff_d2) & 0x1fff;
+       yoff_d1 = yoff;
+       yoff_d2 = yoff;
 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
        if(window_inv) {
                if(dpage == 0) {
@@ -446,395 +821,290 @@ inline void DISPLAY::GETVRAM_4096(int yoff, scrntype *p, uint32 mask, bool windo
                yoff_d2 += 0x18000;
        }
 # endif
-
-       b3  = gvram_shadow[yoff_d1] << 24;
-       b3 |= gvram_shadow[yoff_d1 + 0x02000] << 16;
-       r3  = gvram_shadow[yoff_d1 + 0x04000] << 24;
-       r3 |= gvram_shadow[yoff_d1 + 0x06000] << 16;
+       bb[0] = gvram_shadow[yoff_d1];
+       bb[1] = gvram_shadow[yoff_d1 + 0x02000];
+       rr[0] = gvram_shadow[yoff_d1 + 0x04000];
+       rr[1] = gvram_shadow[yoff_d1 + 0x06000];
+       gg[0] = gvram_shadow[yoff_d1 + 0x08000];
+       gg[1] = gvram_shadow[yoff_d1 + 0x0a000];
                
-       g3  = gvram_shadow[yoff_d1 + 0x08000] << 24;
-       g3 |= gvram_shadow[yoff_d1 + 0x0a000] << 16;
-               
-       b3 |= gvram_shadow[yoff_d2 + 0x0c000] << 8;
-       b3 |= gvram_shadow[yoff_d2 + 0x0e000] << 0;
-               
-       r3 |= gvram_shadow[yoff_d2 + 0x10000] << 8;
-       r3 |= gvram_shadow[yoff_d2 + 0x12000] << 0;
-       g3 |= gvram_shadow[yoff_d2 + 0x14000] << 8;
-       g3 |= gvram_shadow[yoff_d2 + 0x16000] << 0;
-   
-       g = ((g3 & (0x80 << 24)) >> 20) | ((g3 & (0x80 << 16)) >> 13) | ((g3 & (0x80 << 8)) >> 6)  | ((g3 & 0x80) << 1);
-       r = ((r3 & (0x80 << 24)) >> 24) | ((r3 & (0x80 << 16)) >> 17) | ((r3 & (0x80 << 8)) >> 10) | ((r3 & 0x80) >> 3);
-       b = ((b3 & (0x80 << 24)) >> 28) | ((b3 & (0x80 << 16)) >> 21) | ((b3 & (0x80 << 8)) >> 14) | ((b3 & 0x80) >> 7);
-          
-       idx = (g  | b | r ) & mask;
-       pixel = analog_palette_pixel[idx];
-       p[0] = pixel;
-       p[1] = pixel;
-
-       g = ((g3 & (0x40 << 24)) >> 19) | ((g3 & (0x40 << 16)) >> 12) | ((g3 & (0x40 << 8)) >> 5)  | ((g3 & 0x40) << 2);
-       r = ((r3 & (0x40 << 24)) >> 23) | ((r3 & (0x40 << 16)) >> 16) | ((r3 & (0x40 << 8)) >> 9)  | ((r3 & 0x40) >> 2);
-       b = ((b3 & (0x40 << 24)) >> 27) | ((b3 & (0x40 << 16)) >> 20) | ((b3 & (0x40 << 8)) >> 13) | ((b3 & 0x40) >> 6);
-       
-       //g = ((g3 & (0x40 << 24)) ? 0x800 : 0) | ((g3 & (0x40 << 16)) ? 0x400 : 0) | ((g3 & (0x40 << 8)) ? 0x200 : 0) | ((g3 & 0x40) ? 0x100 : 0);
-       //r = ((r3 & (0x40 << 24)) ? 0x80  : 0) | ((r3 & (0x40 << 16)) ? 0x40  : 0) | ((r3 & (0x40 << 8)) ? 0x20  : 0) | ((r3 & 0x40) ? 0x10  : 0);
-       //b = ((b3 & (0x40 << 24)) ? 0x8   : 0) | ((b3 & (0x40 << 16)) ? 0x4   : 0) | ((b3 & (0x40 << 8)) ? 0x2   : 0) | ((b3 & 0x40) ? 0x1   : 0);
-          
-       idx = (g  | b | r ) & mask;
-       pixel = analog_palette_pixel[idx];
-       p[2] = pixel;
-       p[3] = pixel;
-
-//     g = ((g3 & (0x20 << 24)) ? 0x800 : 0) | ((g3 & (0x20 << 16)) ? 0x400 : 0) | ((g3 & (0x20 << 8)) ? 0x200 : 0) | ((g3 & 0x20) ? 0x100 : 0);
-//     r = ((r3 & (0x20 << 24)) ? 0x80  : 0) | ((r3 & (0x20 << 16)) ? 0x40  : 0) | ((r3 & (0x20 << 8)) ? 0x20  : 0) | ((r3 & 0x20) ? 0x10  : 0);
-//     b = ((b3 & (0x20 << 24)) ? 0x8   : 0) | ((b3 & (0x20 << 16)) ? 0x4   : 0) | ((b3 & (0x20 << 8)) ? 0x2   : 0) | ((b3 & 0x20) ? 0x1   : 0);
-       g = ((g3 & (0x20 << 24)) >> 18) | ((g3 & (0x20 << 16)) >> 11) | ((g3 & (0x20 << 8)) >> 4)  | ((g3 & 0x20) << 3);
-       r = ((r3 & (0x20 << 24)) >> 22) | ((r3 & (0x20 << 16)) >> 15) | ((r3 & (0x20 << 8)) >> 8)  | ((r3 & 0x20) >> 1);
-       b = ((b3 & (0x20 << 24)) >> 26) | ((b3 & (0x20 << 16)) >> 19) | ((b3 & (0x20 << 8)) >> 12) | ((b3 & 0x20) >> 5);
-          
-       idx = (g  | b | r ) & mask;
-       pixel = analog_palette_pixel[idx];
-       p[4] = pixel;
-       p[5] = pixel;
-
-       //g = ((g3 & (0x10 << 24)) ? 0x800 : 0) | ((g3 & (0x10 << 16)) ? 0x400 : 0) | ((g3 & (0x10 << 8)) ? 0x200 : 0) | ((g3 & 0x10) ? 0x100 : 0);
-       //r = ((r3 & (0x10 << 24)) ? 0x80  : 0) | ((r3 & (0x10 << 16)) ? 0x40  : 0) | ((r3 & (0x10 << 8)) ? 0x20  : 0) | ((r3 & 0x10) ? 0x10  : 0);
-       //b = ((b3 & (0x10 << 24)) ? 0x8   : 0) | ((b3 & (0x10 << 16)) ? 0x4   : 0) | ((b3 & (0x10 << 8)) ? 0x2   : 0) | ((b3 & 0x10) ? 0x1   : 0);
-       g = ((g3 & (0x10 << 24)) >> 17) | ((g3 & (0x10 << 16)) >> 10) | ((g3 & (0x10 << 8)) >> 3)  | ((g3 & 0x10) << 4);
-       r = ((r3 & (0x10 << 24)) >> 21) | ((r3 & (0x10 << 16)) >> 14) | ((r3 & (0x10 << 8)) >> 7)  | ((r3 & 0x10) >> 0);
-       b = ((b3 & (0x10 << 24)) >> 25) | ((b3 & (0x10 << 16)) >> 18) | ((b3 & (0x10 << 8)) >> 11) | ((b3 & 0x10) >> 4);
-          
-       idx = (g  | b | r ) & mask;
-       pixel = analog_palette_pixel[idx];
-       p[6] = pixel;
-       p[7] = pixel;
-
-
-       //g = ((g3 & (0x8 << 24)) ? 0x800 : 0) | ((g3 & (0x8 << 16)) ? 0x400 : 0) | ((g3 & (0x8 << 8)) ? 0x200 : 0) | ((g3 & 0x8) ? 0x100 : 0);
-       //r = ((r3 & (0x8 << 24)) ? 0x80  : 0) | ((r3 & (0x8 << 16)) ? 0x40  : 0) | ((r3 & (0x8 << 8)) ? 0x20  : 0) | ((r3 & 0x8) ? 0x10  : 0);
-       //b = ((b3 & (0x8 << 24)) ? 0x8   : 0) | ((b3 & (0x8 << 16)) ? 0x4   : 0) | ((b3 & (0x8 << 8)) ? 0x2   : 0) | ((b3 & 0x8) ? 0x1   : 0);
-       g = ((g3 & (0x8 << 24)) >> 16) | ((g3 & (0x8 << 16)) >> 9)  | ((g3 & (0x8 << 8)) >> 2)  | ((g3 & 0x8) << 5);
-       r = ((r3 & (0x8 << 24)) >> 20) | ((r3 & (0x8 << 16)) >> 13) | ((r3 & (0x8 << 8)) >> 6)  | ((r3 & 0x8) << 1);
-       b = ((b3 & (0x8 << 24)) >> 24) | ((b3 & (0x8 << 16)) >> 17) | ((b3 & (0x8 << 8)) >> 10) | ((b3 & 0x8) >> 3);
-          
-       idx = (g  | b | r ) & mask;
-       pixel = analog_palette_pixel[idx];
-       p[8] = pixel;
-       p[9] = pixel;
+       bb[2] = gvram_shadow[yoff_d2 + 0x0c000];
+       bb[3] = gvram_shadow[yoff_d2 + 0x0e000];
+       rr[2] = gvram_shadow[yoff_d2 + 0x10000];
+       rr[3] = gvram_shadow[yoff_d2 + 0x12000];
+       gg[2] = gvram_shadow[yoff_d2 + 0x14000];
+       gg[3] = gvram_shadow[yoff_d2 + 0x16000];
 
-       
-       //g = ((g3 & (0x4 << 24)) ? 0x800 : 0) | ((g3 & (0x4 << 16)) ? 0x400 : 0) | ((g3 & (0x4 << 8)) ? 0x200 : 0) | ((g3 & 0x4) ? 0x100 : 0);
-       //r = ((r3 & (0x4 << 24)) ? 0x80  : 0) | ((r3 & (0x4 << 16)) ? 0x40  : 0) | ((r3 & (0x4 << 8)) ? 0x20  : 0) | ((r3 & 0x4) ? 0x10  : 0);
-       //b = ((b3 & (0x4 << 24)) ? 0x8   : 0) | ((b3 & (0x4 << 16)) ? 0x4   : 0) | ((b3 & (0x4 << 8)) ? 0x2   : 0) | ((b3 & 0x4) ? 0x1   : 0);
-       g = ((g3 & (0x4 << 24)) >> 15) | ((g3 & (0x4 << 16)) >> 8)  | ((g3 & (0x4 << 8)) >> 1) | ((g3 & 0x4) << 6);
-       r = ((r3 & (0x4 << 24)) >> 19) | ((r3 & (0x4 << 16)) >> 12) | ((r3 & (0x4 << 8)) >> 5) | ((r3 & 0x4) << 2);
-       b = ((b3 & (0x4 << 24)) >> 23) | ((b3 & (0x4 << 16)) >> 16) | ((b3 & (0x4 << 8)) >> 9) | ((b3 & 0x4) >> 2);
-          
-       idx = (g  | b | r ) & mask;
-       pixel = analog_palette_pixel[idx];
-       p[10] = pixel;
-       p[11] = pixel;
-
-       //g = ((g3 & (0x2 << 24)) ? 0x800 : 0) | ((g3 & (0x2 << 16)) ? 0x400 : 0) | ((g3 & (0x2 << 8)) ? 0x200 : 0) | ((g3 & 0x2) ? 0x100 : 0);
-       //r = ((r3 & (0x2 << 24)) ? 0x80  : 0) | ((r3 & (0x2 << 16)) ? 0x40  : 0) | ((r3 & (0x2 << 8)) ? 0x20  : 0) | ((r3 & 0x2) ? 0x10  : 0);
-       //b = ((b3 & (0x2 << 24)) ? 0x8   : 0) | ((b3 & (0x2 << 16)) ? 0x4   : 0) | ((b3 & (0x2 << 8)) ? 0x2   : 0) | ((b3 & 0x2) ? 0x1   : 0);
-       g = ((g3 & (0x2 << 24)) >> 14) | ((g3 & (0x2 << 16)) >> 7)  | ((g3 & (0x2 << 8)) >> 0) | ((g3 & 0x2) << 7);
-       r = ((r3 & (0x2 << 24)) >> 18) | ((r3 & (0x2 << 16)) >> 11) | ((r3 & (0x2 << 8)) >> 4) | ((r3 & 0x2) << 3);
-       b = ((b3 & (0x2 << 24)) >> 22) | ((b3 & (0x2 << 16)) >> 15) | ((b3 & (0x2 << 8)) >> 8) | ((b3 & 0x2) >> 1);
-          
-       idx = (g  | b | r ) & mask;
-       pixel = analog_palette_pixel[idx];
-       p[12] = pixel;
-       p[13] = pixel;
-
-       //g = ((g3 & (0x1 << 24)) ? 0x800 : 0) | ((g3 & (0x1 << 16)) ? 0x400 : 0) | ((g3 & (0x1 << 8)) ? 0x200 : 0) | ((g3 & 0x1) ? 0x100 : 0);
-       //r = ((r3 & (0x1 << 24)) ? 0x80  : 0) | ((r3 & (0x1 << 16)) ? 0x40  : 0) | ((r3 & (0x1 << 8)) ? 0x20  : 0) | ((r3 & 0x1) ? 0x10  : 0);
-       //b = ((b3 & (0x1 << 24)) ? 0x8   : 0) | ((b3 & (0x1 << 16)) ? 0x4   : 0) | ((b3 & (0x1 << 8)) ? 0x2   : 0) | ((b3 & 0x1) ? 0x1   : 0);
-       g = ((g3 & (0x1 << 24)) >> 13) | ((g3 & (0x1 << 16)) >> 6)  | ((g3 & (0x1 << 8)) << 1) | ((g3 & 0x1) << 8);
-       r = ((r3 & (0x1 << 24)) >> 17) | ((r3 & (0x1 << 16)) >> 10) | ((r3 & (0x1 << 8)) >> 3) | ((r3 & 0x1) << 4);
-       b = ((b3 & (0x1 << 24)) >> 21) | ((b3 & (0x1 << 16)) >> 14) | ((b3 & (0x1 << 8)) >> 7) | ((b3 & 0x1) >> 0);
-          
-       idx = (g  | b | r ) & mask;
-       pixel = analog_palette_pixel[idx];
-       p[14] = pixel;
-       p[15] = pixel;
-}
+       uint16_t *p0, *p1, *p2, *p3;
+#if !defined(FIXED_FRAMEBUFFER_SIZE)
+       __DECL_ALIGNED(sizeof(scrntype_t) * 8) scrntype_t tmp_dd[8];
+#else
+       __DECL_ALIGNED(sizeof(scrntype_t) * 8) scrntype_t tmp_dd[16];
 #endif
+       uint16_vec8_t tmp_g, tmp_r, tmp_b;
+       __v8hi *vp0, *vp1, *vp2, *vp3;
+       // G
+       vp0 = (__v8hi*)__builtin_assume_aligned(&(bit_trans_table_0[gg[0]][0]), 16);
+       vp1 = (__v8hi*)__builtin_assume_aligned(&(bit_trans_table_1[gg[1]][0]), 16);
+       vp2 = (__v8hi*)__builtin_assume_aligned(&(bit_trans_table_2[gg[2]][0]), 16);
+       vp3 = (__v8hi*)__builtin_assume_aligned(&(bit_trans_table_3[gg[3]][0]), 16);
+       tmp_g.v = *vp0;
+       tmp_g.v = tmp_g.v | *vp1;
+       tmp_g.v = tmp_g.v | *vp2;
+       tmp_g.v = tmp_g.v | *vp3;
+       // R
+       vp0 = (__v8hi*)__builtin_assume_aligned(&(bit_trans_table_0[rr[0]][0]), 16);
+       vp1 = (__v8hi*)__builtin_assume_aligned(&(bit_trans_table_1[rr[1]][0]), 16);
+       vp2 = (__v8hi*)__builtin_assume_aligned(&(bit_trans_table_2[rr[2]][0]), 16);
+       vp3 = (__v8hi*)__builtin_assume_aligned(&(bit_trans_table_3[rr[3]][0]), 16);
+       tmp_r.v = *vp0;
+       tmp_r.v = tmp_r.v | *vp1;
+       tmp_r.v = tmp_r.v | *vp2;
+       tmp_r.v = tmp_r.v | *vp3;
 
-void DISPLAY::draw_screen()
-{
-       int y;
-       int x;
-       scrntype *p, *pp;
-       register int yoff;
-       register uint32 rgbmask;
-       uint16 wx_begin, wx_end, wy_low, wy_high;
-#if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       {
-               wx_begin = window_xbegin;
-               wx_end   = window_xend;
-               wy_low   = window_low;
-               wy_high  = window_high;
-               bool _flag = window_opened; 
-               if((wx_begin < wx_end) && (wy_low < wy_high)) {
-                       window_opened = true;
-               } else {
-                       window_opened = false;
-               }
-               if(_flag != window_opened) vram_wrote_shadow = true;
+       // B
+       vp0 = (__v8hi*)__builtin_assume_aligned(&(bit_trans_table_0[bb[0]][0]), 16);
+       vp1 = (__v8hi*)__builtin_assume_aligned(&(bit_trans_table_1[bb[1]][0]), 16);
+       vp2 = (__v8hi*)__builtin_assume_aligned(&(bit_trans_table_2[bb[2]][0]), 16);
+       vp3 = (__v8hi*)__builtin_assume_aligned(&(bit_trans_table_3[bb[3]][0]), 16);
+       tmp_b.v = *vp0;
+       tmp_b.v = tmp_b.v | *vp1;
+       tmp_b.v = tmp_b.v | *vp2;
+       tmp_b.v = tmp_b.v | *vp3;
+       
+       __v8hi *mp = (__v8hi*)__masks;
+       tmp_g.v = tmp_g.v << 4;
+       tmp_b.v = tmp_b.v >> 4;
+       pixels.v = tmp_b.v;
+       pixels.v = pixels.v | tmp_r.v;
+       pixels.v = pixels.v | tmp_g.v;
+       pixels.v = pixels.v & *mp;
+       
+
+       scrntype_vec8_t *vp = (scrntype_vec8_t*)__builtin_assume_aligned(p, sizeof(scrntype_vec8_t));
+       scrntype_vec8_t *dp = (scrntype_vec8_t*)__builtin_assume_aligned(tmp_dd, sizeof(scrntype_vec8_t));
+#if !defined(FIXED_FRAMEBUFFER_SIZE)
+__DECL_VECTORIZED_LOOP
+       for(int i = 0; i < 8; i++) {
+               tmp_dd[i] = analog_palette_pixel[pixels[i]];
+       }
+       vp->v = dp->v;
+#else
+__DECL_VECTORIZED_LOOP
+       for(int i = 0; i < 8; i++) {
+               tmp_dd[i * 2] = tmp_dd[i * 2 + 1] = analog_palette_pixel[pixels.w[i]];;
        }
+       scrntype_vec8_t *vpx = (scrntype_vec8_t*)__builtin_assume_aligned(px, sizeof(scrntype_vec8_t));
+       scrntype_vec8_t vmask;
+__DECL_VECTORIZED_LOOP
+       for(int i = 0; i < 2; i++) {
+               vp[i].v = dp[i].v;
+       }
+       if(scan_line) {
+/* Fancy scanline */
+__DECL_VECTORIZED_LOOP
+               for(int i = 0; i < 2; i++) {
+#if defined(_RGB888) || defined(_RGBA888)
+                       dp[i].v = dp[i].v >> 3;
+#elif defined(_RGB555)
+                       dp[i].v = dp[i].v >> 2;
+#elif defined(_RGB565)
+                       dp[i].v = dp[i].v >> 2;
 #endif
-       frame_skip_count++;
-#if defined(_FM77AV_VARIANTS)
-       {
-               int factor = (config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28;
-               if(frame_skip_count <= factor) return;
-               frame_skip_count = 0;
+               }
+__DECL_VECTORIZED_LOOP
+               for(int i = 0; i < 8; i++) {
+                       vmask.w[i] = (const scrntype_t)RGBA_COLOR(31, 31, 31, 255);
+               }
+__DECL_VECTORIZED_LOOP
+               for(int i = 0; i < 2; i++) {
+                       dp[i].v = dp[i].v & vmask.v; 
+                       vpx[i].v = dp[i].v;
+               }
+       } else {
+__DECL_VECTORIZED_LOOP
+               for(int i = 0; i < 2; i++) {
+                       vpx[i].v = dp[i].v;
+               }
        }
+#endif 
+}
+#endif
+
+#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
+
+void DISPLAY::GETVRAM_256k(int yoff, scrntype_t *p, scrntype_t *px, bool scan_line)
+{
+       uint32_t b3, r3, g3;
+       uint32_t b4, r4, g4;
+       uint32_t btmp, rtmp, gtmp;
+       
+       scrntype_t b, r, g;
+       scrntype_t pixel;
+       uint32_t _bit;
+       int _shift;
+       int cp;
+       uint32_t yoff_d1;
+       uint32_t yoff_d2;
+       if(p == NULL) return;
+       
+       r3 = g3 = b3 = 0;
+       r4 = g4 = b4 = 0;
+       r = g = b = 0;
+       
+       yoff_d1 = yoff;
+       yoff_d2 = yoff;
+
+       uint8_t  bb[8], rr[8], gg[8];
+
+       uint16_vec8_t _btmp;
+       uint16_vec8_t _rtmp;
+       uint16_vec8_t _gtmp;
+       uint16_vec8_t *vp0, *vp1, *vp2, *vp3, *vp4, *vp5;
+#if !defined(FIXED_FRAMEBUFFER_SIZE)
+       __DECL_ALIGNED(sizeof(scrntype_t) * 8) scrntype_t tmp_dd[8];
 #else
-       {
-               int factor = (config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28;
-               if((frame_skip_count <= factor) || !(vram_wrote)) return;
-               vram_wrote = false;
-               frame_skip_count = 0;
-       }
+       __DECL_ALIGNED(sizeof(scrntype_t) * 8) scrntype_t tmp_dd[16];
 #endif
-         // Set blank
-       if(!crt_flag) {
-               for(y = 0; y < 400; y++) {
-                       memset(emu->screen_buffer(y), 0x00, 640 * sizeof(scrntype));
+//     if(mask & 0x01) {
+       if(!multimode_dispflags[0]) {
+               // B
+               bb[0] = gvram_shadow[yoff_d1];
+               bb[1] = gvram_shadow[yoff_d1 + 0x02000];
+               
+               bb[2] = gvram_shadow[yoff_d2 + 0x0c000];
+               bb[3] = gvram_shadow[yoff_d2 + 0x0e000];
+       
+               bb[4] = gvram_shadow[yoff_d1 + 0x18000];
+               bb[5] = gvram_shadow[yoff_d1 + 0x1a000];
+               
+               vp0 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_0[bb[0]][0]), 16);
+               vp1 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_1[bb[1]][0]), 16);
+               vp2 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_2[bb[2]][0]), 16);
+               vp3 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_3[bb[3]][0]), 16);
+               vp4 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_4[bb[4]][0]), 16);
+               vp5 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_5[bb[5]][0]), 16);
+               _btmp.v = vp0->v;
+               _btmp.v = _btmp.v | vp1->v;
+               _btmp.v = _btmp.v | vp2->v;
+               _btmp.v = _btmp.v | vp3->v;
+               _btmp.v = _btmp.v | vp4->v;
+               _btmp.v = _btmp.v | vp5->v;
+       } else {
+__DECL_VECTORIZED_LOOP
+               for(int i = 0; i < 8; i++) {
+                       _btmp.w[i] = 0;
                }
-               return;
        }
-# if defined(_FM77AV_VARIANTS)
-       if(!vram_wrote_shadow) return;
-# endif        
-       if(display_mode == DISPLAY_MODE_8_200L) {
-               yoff = 0;
-               rgbmask = ~multimode_dispmask;
-               for(y = 0; y < 400; y += 2) {
-                       p = emu->screen_buffer(y);
-                       pp = p;
-                       yoff = (y / 2) * 80;
-# if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-                       if(window_opened && (wy_low <= y) && (wy_high > y)) {
-                                       for(x = 0; x < 80; x++) {
-                                               if((x >= wx_begin) && (x < wx_end)) {
-                                                       GETVRAM_8_200L(yoff, p, rgbmask, true);
-                                               } else {
-                                                       GETVRAM_8_200L(yoff, p, rgbmask, false);
-                                               }
-                                               p += 8;
-                                               yoff++;
-                                       }
-                       } else
-# endif
-                       {
-                               for(x = 0; x < 10; x++) {
-                                       GETVRAM_8_200L(yoff + 0, p, rgbmask, false);
-                                       p += 8;
-                                       
-                                       GETVRAM_8_200L(yoff + 1, p, rgbmask, false);
-                                       p += 8;
-                                       
-                                       GETVRAM_8_200L(yoff + 2, p, rgbmask, false);
-                                       p += 8;
-                                       
-                                       GETVRAM_8_200L(yoff + 3, p, rgbmask, false);
-                                       p += 8;
-                                       
-                                       GETVRAM_8_200L(yoff + 4, p, rgbmask, false);
-                                       p += 8;
-                                       
-                                       GETVRAM_8_200L(yoff + 5, p, rgbmask, false);
-                                       p += 8;
-                                               
-                                       GETVRAM_8_200L(yoff + 6, p, rgbmask, false);
-                                       p += 8;
-                         
-                                       GETVRAM_8_200L(yoff + 7, p, rgbmask, false);
-                                       p += 8;
-                                       yoff += 8;
-                               }
-                       }
-                       if(config.scan_line == 0) {
-                               memcpy((void *)emu->screen_buffer(y + 1), pp, 640 * sizeof(scrntype));
-                       } else {
-                               memset((void *)emu->screen_buffer(y + 1), 0x00, 640 * sizeof(scrntype));
-                       }
+       if(!multimode_dispflags[1]) {
+               //if(mask & 0x02) {
+               // R
+               rr[0] = gvram_shadow[yoff_d1 + 0x04000];
+               rr[1] = gvram_shadow[yoff_d1 + 0x06000];
+               
+               rr[2] = gvram_shadow[yoff_d2 + 0x10000];
+               rr[3] = gvram_shadow[yoff_d2 + 0x12000];
+       
+               rr[4] = gvram_shadow[yoff_d1 + 0x1c000];
+               rr[5] = gvram_shadow[yoff_d1 + 0x1e000];
+               
+               vp0 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_0[rr[0]][0]), 16);
+               vp1 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_1[rr[1]][0]), 16);
+               vp2 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_2[rr[2]][0]), 16);
+               vp3 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_3[rr[3]][0]), 16);
+               vp4 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_4[rr[4]][0]), 16);
+               vp5 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_5[rr[5]][0]), 16);
+               _rtmp.v = vp0->v;
+               _rtmp.v = _rtmp.v | vp1->v;
+               _rtmp.v = _rtmp.v | vp2->v;
+               _rtmp.v = _rtmp.v | vp3->v;
+               _rtmp.v = _rtmp.v | vp4->v;
+               _rtmp.v = _rtmp.v | vp5->v;
+       } else {
+__DECL_VECTORIZED_LOOP
+               for(int i = 0; i < 8; i++) {
+                       _rtmp.w[i] = 0;
                }
-# if defined(_FM77AV_VARIANTS)
-                       vram_wrote_shadow = false;
-# endif                
-               return;
        }
-# if defined(_FM77AV_VARIANTS)
-       if(display_mode == DISPLAY_MODE_4096) {
-               uint32 mask = 0;
-               yoff = 0;
-               rgbmask = multimode_dispmask;
-               if((rgbmask & 0x01) == 0) mask = 0x00f;
-               if((rgbmask & 0x02) == 0) mask = mask | 0x0f0;
-               if((rgbmask & 0x04) == 0) mask = mask | 0xf00;
-               for(y = 0; y < 400; y += 2) {
-                       p = emu->screen_buffer(y);
-                       pp = p;
-                       yoff = y * (40 / 2);
-#  if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-                       if(window_opened && (wy_low <= y) && (wy_high > y)) {
-                                       for(x = 0; x < 40; x++) {
-                                               if((x >= wx_begin) && (x < wx_end)) {
-                                                       GETVRAM_4096(yoff, p, mask, true);
-                                               } else {
-                                                       GETVRAM_4096(yoff, p, mask, false);
-                                               }
-                                               p += 16;
-                                               yoff++;
-                                       }
-                       } else
-#  endif
-                       {
-                               for(x = 0; x < 5; x++) {
-                                       GETVRAM_4096(yoff + 0, p, mask);
-                                       p += 16;
-                                       
-                                       GETVRAM_4096(yoff + 1, p, mask);
-                                       p += 16;
-                                       
-                                       GETVRAM_4096(yoff + 2, p, mask);
-                                       p += 16;
-                                       
-                                       GETVRAM_4096(yoff + 3, p, mask);
-                                       p += 16;
-                                       
-                                       GETVRAM_4096(yoff + 4, p, mask);
-                                       p += 16;
-                         
-                                       GETVRAM_4096(yoff + 5, p, mask);
-                                       p += 16;
-                                       
-                                       GETVRAM_4096(yoff + 6, p, mask);
-                                       p += 16;
-                                       
-                                       GETVRAM_4096(yoff + 7, p, mask);
-                                       p += 16;
-                                       yoff += 8;
-                               }
-                       }
-                       if(config.scan_line == 0) {
-                               memcpy((void *)emu->screen_buffer(y + 1), pp, 640 * sizeof(scrntype));
-                       } else {
-                               memset((void *)emu->screen_buffer(y + 1), 0x00, 640 * sizeof(scrntype));
-                       }
+       if(!multimode_dispflags[2]) {
+               //if(mask & 0x04) {
+               // G
+               gg[0] = gvram_shadow[yoff_d1 + 0x08000];
+               gg[1] = gvram_shadow[yoff_d1 + 0x0a000];
+               
+               gg[2] = gvram_shadow[yoff_d2 + 0x14000];
+               gg[3] = gvram_shadow[yoff_d2 + 0x16000];
+       
+               gg[4] = gvram_shadow[yoff_d1 + 0x20000];
+               gg[5] = gvram_shadow[yoff_d1 + 0x22000];
+               
+               vp0 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_0[gg[0]][0]), 16);
+               vp1 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_1[gg[1]][0]), 16);
+               vp2 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_2[gg[2]][0]), 16);
+               vp3 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_3[gg[3]][0]), 16);
+               vp4 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_4[gg[4]][0]), 16);
+               vp5 = (uint16_vec8_t*)__builtin_assume_aligned(&(bit_trans_table_5[gg[5]][0]), 16);
+               _gtmp.v = vp0->v;
+               _gtmp.v = _gtmp.v | vp1->v;
+               _gtmp.v = _gtmp.v | vp2->v;
+               _gtmp.v = _gtmp.v | vp3->v;
+               _gtmp.v = _gtmp.v | vp4->v;
+               _gtmp.v = _gtmp.v | vp5->v;
+       } else {
+__DECL_VECTORIZED_LOOP
+               for(int i = 0; i < 8; i++) {
+                       _gtmp.w[i] = 0;
                }
-# if defined(_FM77AV_VARIANTS)
-               vram_wrote_shadow = false;
-# endif                
-               return;
        }
-#  if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
-       else if(display_mode == DISPLAY_MODE_8_400L) {
-               yoff = 0;
-               rgbmask = ~multimode_dispmask;
-               for(y = 0; y < 400; y++) {
-                       p = emu->screen_buffer(y);
-                       pp = p;
-                       yoff = y  * 80;
-#    if defined(_FM77AV40EX) || defined(_FM77AV40SX)
-                       if(window_opened && (wy_low <= y) && (wy_high  > y)) {
-                               for(x = 0; x < 80; x++) {
-                                       if((x >= wx_begin) && (x < wx_end)) {
-                                               GETVRAM_8_400L(yoff, p, rgbmask, true);
-                                       } else {
-                                               GETVRAM_8_400L(yoff, p, rgbmask, false);
-                                       }
-                                       p += 8;
-                                       yoff++;
-                               }
-                       } else
-#    endif
-                       for(x = 0; x < 10; x++) {
-                         GETVRAM_8_400L(yoff + 0, p, rgbmask);
-                         p += 8;
-                         
-                         GETVRAM_8_400L(yoff + 1, p, rgbmask);
-                         p += 8;
-
-                         GETVRAM_8_400L(yoff + 2, p, rgbmask);
-                         p += 8;
-
-                         GETVRAM_8_400L(yoff + 3, p, rgbmask);
-                         p += 8;
-
-                         GETVRAM_8_400L(yoff + 4, p, rgbmask);
-                         p += 8;
-                         
-                         GETVRAM_8_400L(yoff + 5, p, rgbmask);
-                         p += 8;
-                         
-                         GETVRAM_8_400L(yoff + 6, p, rgbmask);
-                         p += 8;
-                         
-                         GETVRAM_8_400L(yoff + 7, p, rgbmask);
-                         p += 8;
-                         yoff += 8;
-                       }
+
+       scrntype_vec8_t* vpp = (scrntype_vec8_t*)__builtin_assume_aligned(p, sizeof(scrntype_vec8_t));
+       scrntype_vec8_t* dp = (scrntype_vec8_t*)tmp_dd;
+#if !defined(FIXED_FRAMEBUFFER_SIZE)
+__DECL_VECTORIZED_LOOP
+       for(int i = 0; i < 8; i++) {
+               tmp_dd[i] = RGB_COLOR(_rtmp.w[i], _gtmp.w[i], _btmp.w[i]);
+       }
+       vpp->v = dp->v;
+#else
+__DECL_VECTORIZED_LOOP
+       for(int i = 0; i < 8; i++) {
+               tmp_dd[i * 2] = tmp_dd[i * 2 + 1] = RGB_COLOR(_rtmp.w[i], _gtmp.w[i], _btmp.w[i]);
+       }
+
+__DECL_VECTORIZED_LOOP
+       for(int i = 0; i < 2; i++) {
+               vpp[i].v = dp[i].v;
+       }
+       scrntype_vec8_t* vpx = (scrntype_vec8_t*)__builtin_assume_aligned(px, sizeof(scrntype_vec8_t));
+       if(scan_line) {
+/* Fancy scanline */
+__DECL_VECTORIZED_LOOP
+               for(int i = 0; i < 2; i++) {
+#if defined(_RGB888) || defined(_RGBA888)
+                       dp[i].v = dp[i].v >> 3;
+#elif defined(_RGB555)
+                       dp[i].v = dp[i].v >> 2;
+#elif defined(_RGB565)
+                       dp[i].v = dp[i].v >> 2;
+#endif
                }
-# if defined(_FM77AV_VARIANTS)
-               vram_wrote_shadow = false;
-# endif                
-               return;
-       } else if(display_mode == DISPLAY_MODE_256k) {
-               rgbmask = ~multimode_dispmask;
-               for(y = 0; y < 400; y += 2) {
-# if defined(_FM77AV_VARIANTS)
-                       //if(!vram_wrote_shadow && !vram_draw_table[y >> 1]) continue;
-                       vram_draw_table[y >> 1] = false;        
-# endif                        
-                       p = emu->screen_buffer(y);
-                       pp = p;
-                       yoff = y * (40 / 2);
-                       {
-                               for(x = 0; x < 5; x++) {
-                                       GETVRAM_256k(yoff + 0, p, rgbmask);
-                                       p += 16;
-                                       
-                                       GETVRAM_256k(yoff + 1, p, rgbmask);
-                                       p += 16;
-                                       
-                                       GETVRAM_256k(yoff + 2, p, rgbmask);
-                                       p += 16;
-                                       
-                                       GETVRAM_256k(yoff + 3, p, rgbmask);
-                                       p += 16;
-                                       
-                                       GETVRAM_256k(yoff + 4, p, rgbmask);
-                                       p += 16;
-                         
-                                       GETVRAM_256k(yoff + 5, p, rgbmask);
-                                       p += 16;
-                                       
-                                       GETVRAM_256k(yoff + 6, p, rgbmask);
-                                       p += 16;
-                                       
-                                       GETVRAM_256k(yoff + 7, p, rgbmask);
-                                       p += 16;
-                                       yoff += 8;
-                               }
-                       }
-                       if(config.scan_line == 0) {
-                               memcpy((void *)emu->screen_buffer(y + 1), pp, 640 * sizeof(scrntype));
-                       } else {
-                               memset((void *)emu->screen_buffer(y + 1), 0x00, 640 * sizeof(scrntype));
-                       }
+               scrntype_vec8_t scanline_data;
+__DECL_VECTORIZED_LOOP
+               for(int i = 0; i < 8; i++) {
+                       scanline_data.w[i] = RGBA_COLOR(31, 31, 31, 255);
+               }
+__DECL_VECTORIZED_LOOP
+               for(int i = 0; i < 2; i++) {
+                       dp[i].v = dp[i].v & scanline_data.v;
+                       vpx[i].v = dp[i].v;
+               }
+       } else {
+               for(int i = 0; i < 2; i++) {
+                       vpx[i].v = dp[i].v;
                }
-# if defined(_FM77AV_VARIANTS)
-               vram_wrote_shadow = false;
-# endif                
-               return;
        }
-#  endif // _FM77AV40
-# endif //_FM77AV_VARIANTS
-
+#endif 
 }
+#endif
 
+}