OSDN Git Service

[VM][FM7] Fix state save/load.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / mb61vh010.cpp
index 4524b8a..744e8e4 100644 (file)
@@ -16,26 +16,23 @@ MB61VH010::MB61VH010(VM *parent_vm, EMU *parent_emu) : DEVICE(parent_vm, parent_
 {
        p_emu = parent_emu;
        p_vm = parent_vm;
+       target = NULL;
 }
 
 MB61VH010::~MB61VH010()
 {
 }
 
-uint8 MB61VH010::do_read(uint32 addr, uint32 bank)
+uint8_t MB61VH010::do_read(uint32_t addr, uint32_t bank)
 {
-       uint32 raddr;
-       uint32 offset;
-       
-       if(((1 << bank) & read_signal(SIG_DISPLAY_MULTIPAGE)) != 0) return 0xff;
-       //if(is_400line) offset = 0x8000;
+       uint32_t raddr;
        
+       if(((1 << bank) & multi_page) != 0) return 0xff;
        if(is_400line) {
                if((addr & 0xffff) < 0x8000) {
-                       raddr = (addr & 0x7fff) | (0x8000 * bank);
+                       raddr = (addr  & 0x7fff) | (0x8000 * bank);
                        return target->read_data8(raddr + DISPLAY_VRAM_DIRECT_ACCESS);
                }
-               return 0xff;
        } else {
                raddr = (addr & 0x3fff) | (0x4000 * bank);
                return target->read_data8(raddr + DISPLAY_VRAM_DIRECT_ACCESS);
@@ -43,24 +40,23 @@ uint8 MB61VH010::do_read(uint32 addr, uint32 bank)
        return 0xff;
 }
 
-uint8 MB61VH010::do_write(uint32 addr, uint32 bank, uint8 data)
+uint8_t MB61VH010::do_write(uint32_t addr, uint32_t bank, uint8_t data)
 {
-       uint32 raddr;
-       uint8 readdata;
+       uint32_t raddr;
+       uint8_t readdata;
 
-       if(((1 << bank) & read_signal(SIG_DISPLAY_MULTIPAGE)) != 0) return 0xff;
+       if(((1 << bank) & multi_page) != 0) return 0xff;
        if((command_reg & 0x40) != 0) { // Calculate before writing
                readdata = do_read(addr, bank);
                //readdata = data;
                if((command_reg & 0x20) != 0) { // NAND
                        readdata = readdata & cmp_status_reg;
-                       data = data & ~cmp_status_reg;
-                       readdata = readdata | data;
+                       data = data & (~cmp_status_reg);
                } else { // AND
-                       readdata = readdata & ~cmp_status_reg;
+                       readdata = readdata & (~cmp_status_reg);
                        data = data & cmp_status_reg;
-                       readdata = readdata | data;
                }
+               readdata = readdata | data;
        } else {
                readdata = data;
        }
@@ -77,18 +73,17 @@ uint8 MB61VH010::do_write(uint32 addr, uint32 bank, uint8 data)
 }
 
 
-uint8 MB61VH010::do_pset(uint32 addr)
+uint8_t MB61VH010::do_pset(uint32_t addr)
 {
-       uint32 i;
-       uint32 raddr = addr;  // Use banked ram.
-       uint8 bitmask;
-       uint8 srcdata;
+       int i;
+       uint32_t raddr = addr;  // Use banked ram.
+       uint8_t bitmask;
+       uint8_t srcdata;
        int planes_b = planes;
-
        if(planes_b >= 4) planes_b = 4;
        for(i = 0; i < planes_b; i++) {
                if((bank_disable_reg & (1 << i)) != 0) {
-                               continue;
+                       continue;
                }
                if((color_reg & (1 << i)) == 0) {
                        bitmask = 0x00;
@@ -97,7 +92,7 @@ uint8 MB61VH010::do_pset(uint32 addr)
                }
                
                srcdata = do_read(addr, i);
-               bitmask = bitmask & ~mask_reg;
+               bitmask = bitmask & (~mask_reg);
                srcdata = srcdata & mask_reg;
                srcdata = srcdata | bitmask;
                do_write(addr, i, srcdata);
@@ -105,10 +100,10 @@ uint8 MB61VH010::do_pset(uint32 addr)
        return 0xff;
 }
 
-uint8 MB61VH010::do_blank(uint32 addr)
+uint8_t MB61VH010::do_blank(uint32_t addr)
 {
-       uint32 i;
-       uint8 srcdata;
+       uint32_t i;
+       uint8_t srcdata;
 
        if(planes >= 4) planes = 4;
        for(i = 0; i < planes; i++) {
@@ -122,11 +117,11 @@ uint8 MB61VH010::do_blank(uint32 addr)
        return 0xff;
 }
 
-uint8 MB61VH010::do_or(uint32 addr)
+uint8_t MB61VH010::do_or(uint32_t addr)
 {
-       uint32 i;
-       uint8 bitmask;
-       uint8 srcdata;
+       uint32_t i;
+       uint8_t bitmask;
+       uint8_t srcdata;
        
        if(planes >= 4) planes = 4;
        for(i = 0; i < planes; i++) {
@@ -146,11 +141,11 @@ uint8 MB61VH010::do_or(uint32 addr)
        return 0xff;
 }
 
-uint8 MB61VH010::do_and(uint32 addr)
+uint8_t MB61VH010::do_and(uint32_t addr)
 {
-       uint32 i;
-       uint8 bitmask;
-       uint8 srcdata;
+       uint32_t i;
+       uint8_t bitmask;
+       uint8_t srcdata;
 
        if(planes >= 4) planes = 4;
        for(i = 0; i < planes; i++) {
@@ -170,11 +165,11 @@ uint8 MB61VH010::do_and(uint32 addr)
        return 0xff;
 }
 
-uint8 MB61VH010::do_xor(uint32 addr)
+uint8_t MB61VH010::do_xor(uint32_t addr)
 {
-       uint32 i;
-       uint8 bitmask;
-       uint8 srcdata;
+       uint32_t i;
+       uint8_t bitmask;
+       uint8_t srcdata;
 
        if(planes >= 4) planes = 4;
        for(i = 0; i < planes; i++) {
@@ -194,11 +189,11 @@ uint8 MB61VH010::do_xor(uint32 addr)
        return 0xff;
 }
 
-uint8 MB61VH010::do_not(uint32 addr)
+uint8_t MB61VH010::do_not(uint32_t addr)
 {
-       uint32 i;
-       uint8 bitmask;
-       uint8 srcdata;
+       uint32_t i;
+       uint8_t bitmask;
+       uint8_t srcdata;
 
        if(planes >= 4) planes = 4;
        for(i = 0; i < planes; i++) {
@@ -216,72 +211,75 @@ uint8 MB61VH010::do_not(uint32 addr)
 }
 
 
-uint8 MB61VH010::do_tilepaint(uint32 addr)
+uint8_t MB61VH010::do_tilepaint(uint32_t addr)
 {
-       uint32 i;
-       uint8 bitmask;
-       uint8 srcdata;
-       //printf("Tilepaint CMD=%02x, ADDR=%04x Planes=%d, tile_reg=(%02x %02x %02x %02x)\n",
-       //       command_reg, addr, planes, tile_reg[0], tile_reg[1], tile_reg[2], tile_reg[3]);
-       if(planes >= 4) planes = 4;
+       uint32_t i;
+       uint8_t bitmask;
+       uint8_t srcdata;
+
+       if(planes > 4) planes = 4;
        for(i = 0; i < planes; i++) {
                if((bank_disable_reg & (1 << i)) != 0) {
                        continue;
                }
                srcdata = do_read(addr, i);
-               bitmask = tile_reg[i] & ~mask_reg;
+               bitmask = tile_reg[i] & (~mask_reg);
                srcdata = (srcdata & mask_reg) | bitmask;
                do_write(addr, i, srcdata);
        }
        return 0xff;
 }
 
-uint8 MB61VH010::do_compare(uint32 addr)
+uint8_t MB61VH010::do_compare(uint32_t addr)
 {
-       uint32 offset = 0x4000;
-       uint8 r, g, b, t;
-       uint8 disables = ~bank_disable_reg;
-       uint8 tmpcol;
-       uint8 tmp_stat = 0;
+       uint32_t offset = 0x4000;
+       uint8_t r, g, b;
+       uint8_t disables = ~bank_disable_reg;
+
+       uint8_t tmpcol;
+       uint8_t tmp_stat = 0;
+       uint8_t cmp_reg_bak[8];
+       int k;
        int i;
        int j;
-       //printf("Compare CMD=%02x, ADDR=%04x\n", command_reg, addr);
+       
+       disables = disables & 0x07;
+       k = 0;
+       for(j = 0; j < 8; j++) {
+               if((cmp_color_data[j] & 0x80) == 0) {
+                       cmp_reg_bak[k] = cmp_color_data[j] & disables;
+                       k++;
+               }
+       }
+       cmp_status_reg = 0x00;
+       if(k <= 0) return 0xff;
        b = do_read(addr, 0);
        r = do_read(addr, 1);
        g = do_read(addr, 2);
-       if(planes >= 4) {
-               t = do_read(addr, 3);
-               disables = disables & 0x0f;
-       } else {
-               t = 0;
-               disables = disables & 0x07;
-       }
-       for(i = 7; i >= 0; i--) {
-               tmpcol  = ((b & 0x80) != 0) ? 1 : 0;
-               tmpcol |= ((r & 0x80) != 0) ? 2 : 0;
-               tmpcol |= ((g & 0x80) != 0) ? 4 : 0;
-               tmpcol |= ((t & 0x80) != 0) ? 8 : 0;
+       for(i = 0; i < 8; i++) {
+               tmp_stat <<= 1;
+               tmpcol  = (b & 0x80) >> 7;
+               tmpcol  = tmpcol | ((r & 0x80) >> 6);
+               tmpcol  = tmpcol | ((g & 0x80) >> 5);
+               //tmpcol |= ((t & 0x80) != 0) ? 8 : 0;
                tmpcol = tmpcol & disables;
-               for(j = 0; j < 8; j++) {
-                       if((cmp_color_data[j] & 0x80) == 0) {
-                               if((cmp_color_data[j] & disables) == tmpcol) {
-                                       tmp_stat = tmp_stat | (1 << i);
-                                       break;
-                               }
+               for(j = 0; j < k; j++) {
+                       if(cmp_reg_bak[j] == tmpcol) {
+                               tmp_stat = tmp_stat | 0x01;
+                               goto _l0;
                        }
                }
+_l0:      
                b <<= 1;
                r <<= 1;
                g <<= 1;
-               t <<= 1;
        }
        cmp_status_reg = tmp_stat;
        return 0xff;
 }
 
-void MB61VH010::do_alucmds_dmyread(uint32 addr)
+void MB61VH010::do_alucmds_dmyread(uint32_t addr)
 {
-       int i;
        if(!is_400line) {
                addr = addr & 0x3fff;
        } else {
@@ -291,13 +289,12 @@ void MB61VH010::do_alucmds_dmyread(uint32 addr)
                }
                addr = addr & 0x7fff;
        }
-       printf("ALU DMYREAD: CMD %02x ADDR=%04x CMP[]=", command_reg, addr);
-       for(i = 0; i < 8; i++) printf("[%02x]", cmp_color_data[i]);
        if((command_reg & 0x80) == 0) {
-               printf("\n");
                return;
        }
-       if(((command_reg & 0x40) != 0) && ((command_reg & 0x07) != 7)) do_compare(addr);
+       //busy_flag = true;
+       //cmp_status_reg = 0x00;
+       if((command_reg & 0x40) != 0) do_compare(addr);
        switch(command_reg & 0x07) {
                case 0:
                        do_pset(addr);
@@ -324,10 +321,12 @@ void MB61VH010::do_alucmds_dmyread(uint32 addr)
                        do_compare(addr);
                        break;
        }
-       printf(" CMP STATUS=%02x\n", cmp_status_reg);
+       //p_emu->out_debug_log("ALU DMYREAD ADDR=%04x, CMD=%02x CMP STATUS=%02x\n", addr, command_reg, cmp_status_reg);
+       //if(eventid_busy >= 0) cancel_event(this, eventid_busy) ;
+       //register_event(this, EVENT_MB61VH010_BUSY_OFF, 1.0 / 16.0, false, &eventid_busy) ;
 }  
 
-uint8 MB61VH010::do_alucmds(uint32 addr)
+uint8_t MB61VH010::do_alucmds(uint32_t addr)
 {
        if(!is_400line) {
                addr = addr & 0x3fff;
@@ -338,8 +337,8 @@ uint8 MB61VH010::do_alucmds(uint32 addr)
                }
                addr = addr & 0x7fff;
        }
-       if((command_reg & 0x07) != 0x00) printf("ALU: CMD %02x ADDR=%08x\n", command_reg, addr);
-       if(((command_reg & 0x40) != 0) && ((command_reg & 0x07) != 7)) do_compare(addr);
+       //cmp_status_reg = 0x00;
+       if((command_reg & 0x40) != 0) do_compare(addr);
        switch(command_reg & 0x07) {
                case 0:
                        return do_pset(addr);
@@ -371,149 +370,187 @@ uint8 MB61VH010::do_alucmds(uint32 addr)
 
 void MB61VH010::do_line(void)
 {
-       int x_begin = line_xbegin.w.l;
-       int x_end = line_xend.w.l;
-       int y_begin = line_ybegin.w.l;
-       int y_end = line_yend.w.l;
-       uint32 addr;
-       int cpx_t = x_begin;
-       int cpy_t = y_begin;
-       int ax = x_end - x_begin;
-       int ay = y_end - y_begin;
-       int diff;
+       uint32_t x_begin = line_xbegin.w.l;
+       uint32_t x_end = line_xend.w.l;
+       uint32_t y_begin = line_ybegin.w.l;
+       uint32_t y_end = line_yend.w.l;
+       int cpx_t = (int)x_begin;
+       int cpy_t = (int)y_begin;
+       int ax = (int)x_end - (int)x_begin;
+       int ay = (int)y_end - (int)y_begin;
+       int diff = 0;
        int count = 0;
-       uint8 mask_bak = mask_reg;
-       //printf("Line: (%d,%d) - (%d,%d) CMD=%02x\n", x_begin, y_begin, x_end, y_end, command_reg);  
+       int xcount;
+       int ycount;
+       //uint8_t mask_bak = mask_reg;
+       uint16_t tmp8a;
+       uint8_t vmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
        double usec;
        bool lastflag = false;
+       
 
-       is_400line = (target->read_signal(SIG_DISPLAY_MODE_IS_400LINE) != 0) ? true : false;
-       planes = target->read_signal(SIG_DISPLAY_PLANES) & 0x07;
-       screen_width = target->read_signal(SIG_DISPLAY_X_WIDTH) * 8;
-       screen_height = target->read_signal(SIG_DISPLAY_Y_HEIGHT);
-
-       //if((command_reg & 0x80) == 0) return;
        oldaddr = 0xffffffff;
        alu_addr = 0xffffffff;
-
-       
+       //if ((x_begin >= screen_width) && (x_end >= screen_width)) return;
+       //if ((y_begin >= screen_height) && (y_end >= screen_height)) return;
        line_style = line_pattern;
-       oldaddr = 0xffff;
        busy_flag = true;
-       total_bytes = 1;
+       total_bytes = 0;
        
-       //mask_reg = 0xff & ~vmask[x_begin & 7];
        mask_reg = 0xff;
-       // Got from HD63484.cpp .
-       if(abs(ax) >= abs(ay)) {
-               if(ax != 0) {
-                       diff = ((abs(ay) + 1) * 1024) / abs(ax);
-                       for(; cpx_t != x_end; ) {
+       if ((line_style.b.h & 0x80) != 0) {
+               mask_reg &= ~vmask[cpx_t & 7];
+       }
+       tmp8a = ((line_style.b.h & 0x80) >> 7) & 0x01;
+       line_style.w.l = (line_style.w.l << 1) | tmp8a;
+   
+       xcount = abs(ax);
+       ycount = abs(ay);
+       //p_emu->out_debug_log("LINE: (%d,%d)-(%d,%d)\n", x_begin, y_begin, x_end , y_end); 
+       if(ycount == 0) {
+               if(ax > 0) {
+                       if((cpx_t & 0x07) != 7) total_bytes = 1;
+                       //if((x_end >= screen_width) && (x_begin < screen_width)) x_end = screen_width - 1;
+                       for(; cpx_t <= (int)x_end; cpx_t++) {
+                               if(cpy_t >= screen_width) break;
                                lastflag = put_dot(cpx_t, cpy_t);
-                               count += diff;
-                               if(count >= 1024) {
-                                       if(ax > 0) {
-                                               lastflag = put_dot(cpx_t + 1, cpy_t);
-                                       } else if(ax < 0) {
-                                               lastflag = put_dot(cpx_t - 1, cpy_t);
-                                       }
-                                       if(ay < 0) {
-                                               cpy_t--;
-                                       } else {
-                                               cpy_t++;
-                                       }
-                                       count -= 1024;
-                               }
-                               if(ax > 0) {
-                                       cpx_t++;
-                               } else if(ax < 0) {
-                                       cpx_t--;
-                               }
+                               if((cpx_t & 0x07) == 7) total_bytes++;
                        }
+               } else {
+                       if((cpx_t & 0x07) != 0) total_bytes = 1;
+                       for(; cpx_t >= (int)x_end; cpx_t--) {
+                               if(cpy_t < 0) break;
+                               if((cpx_t & 0x07) == 0) total_bytes++;
+                               lastflag = put_dot(cpx_t, cpy_t);
+                       }
+               }
+       } else if(xcount == 0) {
+               if(ay > 0) {
+                       for(; cpy_t <= (int)y_end; cpy_t++) {
+                               if(cpy_t >= screen_height) break;
+                               lastflag = put_dot(cpx_t, cpy_t);
+                               total_bytes++;
+                       }
+               } else {
+                       for(; cpy_t  >= (int)y_end; cpy_t--) {
+                               if(cpy_t < 0) break;
+                               lastflag = put_dot(cpx_t, cpy_t);
+                               total_bytes++;
+                       }
+               }
+       } else if(xcount >= ycount) {
+               diff = (ycount * 32768) / xcount;
+               if(ax < 0) {
+                       //if(x_end == 0) xcount = x_begin;
+                       if((cpx_t & 0x07) != 0) total_bytes = 1;
+               } else {
+                       if(x_end >= screen_width) xcount = (int)screen_width - (int)x_begin - 1;
+                       if((cpx_t & 0x07) == 0) total_bytes = 1;
+               }
+               for(; xcount >= 0; xcount-- ) {
                        lastflag = put_dot(cpx_t, cpy_t);
-               } else { // ax = ay = 0
-                       lastflag = put_dot(cpx_t, cpy_t);
-                       total_bytes++;
+                       count += diff;
+                       if(count > 16384) {
+                               if(ay < 0) {
+                                       cpy_t--;
+                                       if(cpy_t < 0) break;
+                               } else {
+                                       cpy_t++;
+                                       if(cpy_t >= screen_height) break;
+                               }
+                               total_bytes++;
+                               count -= 32768;
+                       }
+                       if(ax > 0) {
+                               cpx_t++;
+                               if((cpx_t & 0x07) == 0) total_bytes++;
+                               if(cpx_t >= screen_width) break;
+                       } else if(ax < 0) {
+                               if((cpx_t & 0x07) == 0) total_bytes++;
+                               cpx_t--;
+                               if(cpx_t < 0) break;
+                       }
+               }
+       } else { // (abs(ax) <= abs(ay)
+               diff = (xcount  * 32768) / ycount;
+               if(ay < 0) {
+                       //if(y_end < 0) ycount = y_begin;
+               } else {
+                       if(y_end >= screen_height) ycount = screen_height - y_begin - 1;
                }
-       } else { // (abs(ax) < abs(ay) 
-               diff = ((abs(ax) + 1) * 1024) / abs(ay);
-               for(; cpy_t != y_end; ) {
+               for(; ycount >= 0; ycount--) {
                        lastflag = put_dot(cpx_t, cpy_t);
                        count += diff;
-                       if(count >= 1024) {
-                               if(ay > 0) {
-                                       lastflag = put_dot(cpx_t, cpy_t + 1);
-                               } else if(ay < 0) {
-                                       lastflag = put_dot(cpx_t, cpy_t - 1);
-                               }                                 
+                       if(count > 16384) {
                                if(ax < 0) {
                                        cpx_t--;
+                                       if(cpx_t < 0) break;
                                } else if(ax > 0) {
                                        cpx_t++;
+                                       if(cpx_t > screen_width) break;
                                }
-                               count -= 1024;
+                               count -= 32768;
                        }
+                       total_bytes++;
                        if(ay > 0) {
                                cpy_t++;
+                               if(cpy_t >= screen_height) break;
                        } else {
                                cpy_t--;
+                               if(cpy_t < 0) break;
                        }
                }
-               lastflag = put_dot(cpx_t, cpy_t);
        }
-       do_alucmds(alu_addr);
-
+       //if(!lastflag) total_bytes++;
+       if(alu_addr < 0x8000) do_alucmds(alu_addr);
+   
+       //if(total_bytes > 16) { // Over 1.0us
        usec = (double)total_bytes / 16.0;
-       //if(usec >= 1.0) { // 1MHz
+       if(eventid_busy >= 0) cancel_event(this, eventid_busy) ;
        register_event(this, EVENT_MB61VH010_BUSY_OFF, usec, false, &eventid_busy) ;
-               //} else {
-                       //busy_flag = false;
-               //}
-       mask_reg = mask_bak;
-       line_pattern = line_style;
+       //} else {
+       //      busy_flag = false;
+       //}
 }
 
 bool MB61VH010::put_dot(int x, int y)
 {
-       uint8 vmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
-       uint16 tmp8a;
-       uint8 mask;
+       uint8_t vmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
+       uint16_t tmp8a;
        bool flag = false;
        
-       if((x < 0) || (y < 0)) return flag;
-       if((x >= screen_width) || (y >= screen_height)) return flag;
-       if((command_reg & 0x80) == 0) return flag;
+       if((x < 0) || (y < 0)) return false;
+       if(y >= (int)screen_height) return false;
+       if((command_reg & 0x80) == 0) return false;
        
-       alu_addr = ((y * screen_width) >> 3) + (x >> 3);
-       alu_addr = alu_addr + (line_addr_offset.w.l << 1);
+       alu_addr = (y * screen_width + x)  >> 3;
+       alu_addr = alu_addr + line_addr_offset.w.l;
        alu_addr = alu_addr & 0x7fff;
        if(!is_400line) alu_addr = alu_addr & 0x3fff;
-       if(oldaddr == 0xffffffff) oldaddr = alu_addr;
        
        if(oldaddr != alu_addr) {
+               if(oldaddr == 0xffffffff) oldaddr = alu_addr;
                do_alucmds(oldaddr);
                mask_reg = 0xff;
                oldaddr = alu_addr;
                flag = true;
-               total_bytes++;
+               //total_bytes++;
        }
-       
        if((line_style.b.h & 0x80) != 0) {
                mask_reg &= ~vmask[x & 7];
-        }
-       tmp8a = (line_style.w.l & 0x8000) >> 15;
+       }
+       tmp8a = ((line_style.b.h & 0x80) >> 7) & 0x01;
        line_style.w.l = (line_style.w.l << 1) | tmp8a;
        return flag;
 }
 
-void MB61VH010::write_data8(uint32 id, uint32 data)
+void MB61VH010::write_data8(uint32_t id, uint32_t data)
 {
-       //printf("ALU: ADDR=%02x DATA=%02x\n", id, data);
+       //p_emu->out_debug_log("ALU: ADDR=%02x DATA=%02x\n", id, data);
        if(id == ALU_CMDREG) {
                command_reg = data;
                return;
        }
-       //if((command_reg & 0x80) == 0) return;
        switch(id) {
                case ALU_LOGICAL_COLOR:
                        color_reg = data;
@@ -537,10 +574,13 @@ void MB61VH010::write_data8(uint32 id, uint32 data)
                        tile_reg[3] = data;
                        break;
                case ALU_OFFSET_REG_HIGH:
-                       line_addr_offset.b.h = data;
+                       line_addr_offset.b.h &= 0x01;
+                       line_addr_offset.b.h = line_addr_offset.b.h | ((data << 1) & 0x3e);
                        break;
                case ALU_OFFSET_REG_LO:
-                       line_addr_offset.b.l = data;
+                       line_addr_offset.b.l = data << 1;
+                       line_addr_offset.b.h &= 0xfe;
+                       line_addr_offset.b.h = line_addr_offset.b.h | ((data >> 7) & 0x01);
                        break;
                case ALU_LINEPATTERN_REG_HIGH:
                        line_pattern.b.h = data;
@@ -549,25 +589,25 @@ void MB61VH010::write_data8(uint32 id, uint32 data)
                        line_pattern.b.l = data;
                        break;
                case ALU_LINEPOS_START_X_HIGH:
-                       line_xbegin.b.h = data;
+                       line_xbegin.b.h = data & 0x03;
                        break;
                case ALU_LINEPOS_START_X_LOW:  
                        line_xbegin.b.l = data;
                        break;
                case ALU_LINEPOS_START_Y_HIGH:
-                       line_ybegin.b.h = data;
+                       line_ybegin.b.h = data & 0x01;
                        break;
                case ALU_LINEPOS_START_Y_LOW:  
                        line_ybegin.b.l = data;
                        break;
                case ALU_LINEPOS_END_X_HIGH:
-                       line_xend.b.h = data;
+                       line_xend.b.h = data & 0x03;
                        break;
                case ALU_LINEPOS_END_X_LOW:  
                        line_xend.b.l = data;
                        break;
                case ALU_LINEPOS_END_Y_HIGH:
-                       line_yend.b.h = data;
+                       line_yend.b.h = data & 0x01;
                        break;
                case ALU_LINEPOS_END_Y_LOW:
                        line_yend.b.l = data;
@@ -576,54 +616,95 @@ void MB61VH010::write_data8(uint32 id, uint32 data)
                default:
                        if((id >= (ALU_CMPDATA_REG + 0)) && (id < (ALU_CMPDATA_REG + 8))) {
                                cmp_color_data[id - ALU_CMPDATA_REG] = data;
-                       } else  if((id >= ALU_WRITE_PROXY) && (id < (ALU_WRITE_PROXY + 0x18000))) {
-                               is_400line = (target->read_signal(SIG_DISPLAY_MODE_IS_400LINE) != 0) ? true : false;
-                               do_alucmds_dmyread(id - ALU_WRITE_PROXY);
+                       } else  if((id >= ALU_WRITE_PROXY) && (id < (ALU_WRITE_PROXY + 0xc000))) {
+                               uint32_t raddr = id - ALU_WRITE_PROXY;
+                               if(is_400line) {
+                                       if(raddr >= 0x8000) return;
+                               } else {
+                                       raddr = raddr & 0x3fff;
+                               }
+                               do_alucmds_dmyread(raddr);
                        }
                        break;
        }
 }
 
-uint32 MB61VH010::read_data8(uint32 id)
+uint32_t MB61VH010::read_data8(uint32_t id)
 {
-  
+       uint32_t raddr;  
        switch(id) {
                case ALU_CMDREG:
-                       return (uint32)command_reg;
+                       return (uint32_t)command_reg;
                        break;
                case ALU_LOGICAL_COLOR:
-                       return (uint32)color_reg;
+                       return (uint32_t)color_reg;
                        break;
                case ALU_WRITE_MASKREG:
-                       return (uint32)mask_reg;
+                       return (uint32_t)mask_reg;
                        break;
                case ALU_CMP_STATUS_REG:
-                       return (uint32)cmp_status_reg;
+                       return (uint32_t)cmp_status_reg;
                        break;
                case ALU_BANK_DISABLE:
-                       return (uint32)bank_disable_reg;
+                       return (uint32_t)bank_disable_reg;
                        break;
                default:
-                       if((id >= ALU_WRITE_PROXY) && (id < (ALU_WRITE_PROXY + 0x18000))) {
-                               is_400line = (target->read_signal(SIG_DISPLAY_MODE_IS_400LINE) != 0) ? true : false;
-                               do_alucmds_dmyread(id - ALU_WRITE_PROXY);
+                       if((id >= ALU_WRITE_PROXY) && (id < (ALU_WRITE_PROXY + 0xc000))) {
+                               uint32_t dmydata;
+                               raddr = id - ALU_WRITE_PROXY;
+                               if(is_400line) {
+                                       if(raddr >= 0x8000) return 0xffffffff;
+                               } else {
+                                       raddr = raddr & 0x3fff;
+                               }
+                               //dmydata = target->read_data8(raddr + DISPLAY_VRAM_DIRECT_ACCESS);
+                               do_alucmds_dmyread(raddr);
+                               raddr = (id - ALU_WRITE_PROXY) % 0xc000;
+                               dmydata = target->read_data8(raddr + DISPLAY_VRAM_DIRECT_ACCESS);
+                               return dmydata;
                        }
                        return 0xffffffff;
                        break;
        }
 }
 
-uint32 MB61VH010::read_signal(int id)
+uint32_t MB61VH010::read_signal(int id)
 {
-       uint32 val = 0x00000000;
+       uint32_t val = 0x00000000;
        switch(id) {
                case SIG_ALU_BUSYSTAT:
                        if(busy_flag) val = 0xffffffff;
                        break;
+               case SIG_ALU_ENABLED:
+                       val = ((command_reg & 0x80) != 0) ? 0xffffffff : 0;
+                       break;
        }
        return val;
 }
 
+void MB61VH010::write_signal(int id, uint32_t data, uint32_t mask)
+{
+       bool flag = ((data & mask) != 0);
+       switch(id) {
+               case SIG_ALU_400LINE:
+                       is_400line = flag;
+                       break;
+               case SIG_ALU_MULTIPAGE:
+                       multi_page = (data & mask) & 0x07;
+                       break;
+               case SIG_ALU_PLANES:
+                       planes = (data & mask) & 0x07;
+                       if(planes >= 4) planes = 4;
+                       break;
+               case SIG_ALU_X_WIDTH:
+                       screen_width = (data << 3) & 0x3ff;
+                       break;
+               case SIG_ALU_Y_HEIGHT:
+                       screen_height = data & 0x3ff;
+                       break;
+       }
+}
+
 void MB61VH010::event_callback(int event_id, int err)
 {
        switch(event_id) {
@@ -641,8 +722,30 @@ void MB61VH010::event_callback(int event_id, int err)
 
 void MB61VH010::initialize(void)
 {
+       int i;
        busy_flag = false;
+       is_400line = false;
        eventid_busy = -1;
+       multi_page = 0x00;
+       planes = 3;
+       screen_width = 640;
+       screen_height = 200;
+#if 1
+       command_reg = 0;        // D410 (RW)
+       color_reg = 0;          // D411 (RW)
+       mask_reg = 0;           // D412 (RW)
+       cmp_status_reg = 0;     // D413 (RO)
+       for(i = 0; i < 8; i++) cmp_color_data[i] = 0x80; // D413-D41A (WO)
+       bank_disable_reg = 0;   // D41B (RW)
+       for(i = 0; i < 4; i++) tile_reg[i] = 0;        // D41C-D41F (WO)
+       
+       line_addr_offset.d = 0; // D420-D421 (WO)
+       line_pattern.d = 0;     // D422-D423 (WO)
+       line_xbegin.d = 0;      // D424-D425 (WO)
+       line_ybegin.d = 0;      // D426-D427 (WO)
+       line_xend.d = 0;        // D428-D429 (WO)
+       line_yend.d = 0;        // D42A-D42B (WO)
+#endif 
 }
 
 void MB61VH010::reset(void)
@@ -651,7 +754,7 @@ void MB61VH010::reset(void)
        busy_flag = false;
        if(eventid_busy >= 0) cancel_event(this, eventid_busy);
        eventid_busy = -1;
-       
+#if 1
        command_reg = 0;        // D410 (RW)
        color_reg = 0;          // D411 (RW)
        mask_reg = 0;           // D412 (RW)
@@ -666,12 +769,98 @@ void MB61VH010::reset(void)
        line_ybegin.d = 0;      // D426-D427 (WO)
        line_xend.d = 0;        // D428-D429 (WO)
        line_yend.d = 0;        // D42A-D42B (WO)
-
+#endif 
        oldaddr = 0xffffffff;
        
-       planes = target->read_signal(SIG_DISPLAY_PLANES) & 0x07;
-       is_400line = (target->read_signal(SIG_DISPLAY_MODE_IS_400LINE) != 0) ? true : false;
-       
-       screen_width = target->read_signal(SIG_DISPLAY_X_WIDTH) * 8;
-       screen_height = target->read_signal(SIG_DISPLAY_Y_HEIGHT);
+       if(planes >= 4) planes = 4;
+}
+
+#define STATE_VERSION 1
+void MB61VH010::save_state(FILEIO *state_fio)
+{
+       int i;
+       state_fio->FputUint32(STATE_VERSION);
+       state_fio->FputInt32(this_device_id);
+       p_emu->out_debug_log("Save State: MB61VH010 : id=%d ver=%d\n", this_device_id, STATE_VERSION);
+
+       { // V1
+               state_fio->FputUint8(command_reg);
+               state_fio->FputUint8(color_reg);
+               state_fio->FputUint8(mask_reg);
+               state_fio->FputUint8(cmp_status_reg);
+               for(i = 0; i < 8; i++)  state_fio->FputUint8(cmp_color_data[i]);
+               state_fio->FputUint8(bank_disable_reg);
+               for(i = 0; i < 4; i++)  state_fio->FputUint8(tile_reg[i]);
+               state_fio->FputUint8(multi_page);
+               
+               state_fio->FputUint32_BE(line_addr_offset.d);
+               state_fio->FputUint16_BE(line_pattern.w.l);
+               state_fio->FputUint16_BE(line_xbegin.w.l);
+               state_fio->FputUint16_BE(line_ybegin.w.l);
+               state_fio->FputUint16_BE(line_xend.w.l);
+               state_fio->FputUint16_BE(line_yend.w.l);
+               
+               state_fio->FputBool(busy_flag);
+               state_fio->FputInt32_BE(eventid_busy);
+
+               state_fio->FputUint32_BE(total_bytes);
+               state_fio->FputUint32_BE(oldaddr);
+               state_fio->FputUint32_BE(alu_addr);
+
+               state_fio->FputUint32_BE(planes);
+               state_fio->FputBool(is_400line);
+               state_fio->FputUint32_BE(screen_width);
+               state_fio->FputUint32_BE(screen_height);
+
+               state_fio->FputUint16_BE(line_style.w.l);
+       }
+   
+}
+
+bool MB61VH010::load_state(FILEIO *state_fio)
+{
+       uint32_t version = state_fio->FgetUint32();
+       int i;
+       p_emu->out_debug_log("Load State: MB61VH010 : id=%d ver=%d\n", this_device_id, version);
+       if(this_device_id != state_fio->FgetInt32()) return false;
+       if(version >= 1) {
+               command_reg = state_fio->FgetUint8();
+               color_reg = state_fio->FgetUint8();
+               mask_reg = state_fio->FgetUint8();
+               cmp_status_reg = state_fio->FgetUint8();
+               for(i = 0; i < 8; i++)  cmp_color_data[i] = state_fio->FgetUint8();
+               bank_disable_reg = state_fio->FgetUint8();
+               for(i = 0; i < 4; i++)  tile_reg[i] = state_fio->FgetUint8();
+               multi_page = state_fio->FgetUint8();
+
+               line_addr_offset.d = state_fio->FgetUint32_BE();
+               line_pattern.d = 0;
+               line_xbegin.d = 0;
+               line_ybegin.d = 0;
+               line_xend.d = 0;
+               line_yend.d = 0;
+          
+               line_pattern.w.l = state_fio->FgetUint16_BE();
+               line_xbegin.w.l = state_fio->FgetUint16_BE();
+               line_ybegin.w.l = state_fio->FgetUint16_BE();
+               line_xend.w.l = state_fio->FgetUint16_BE();
+               line_yend.w.l = state_fio->FgetUint16_BE();
+
+               busy_flag = state_fio->FgetBool();
+               eventid_busy = state_fio->FgetInt32_BE();
+               
+               total_bytes = state_fio->FgetUint32_BE();
+               oldaddr = state_fio->FgetUint32_BE();
+               alu_addr = state_fio->FgetUint32_BE();
+
+               planes = state_fio->FgetUint32_BE();
+               is_400line = state_fio->FgetBool();
+               screen_width = state_fio->FgetUint32_BE();
+               screen_height = state_fio->FgetUint32_BE();
+
+               line_style.d = 0;
+               line_style.w.l = state_fio->FgetUint16_BE();
+       }
+       if(version != STATE_VERSION) return false;
+       return true;
 }