OSDN Git Service

[VM][FM7][MB61VH010] ALULINE: Fix shift count of line style register: Stage 4 of...
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / mb61vh010.cpp
1 /*
2  * FM77AV/FM16β ALU [mb61vh010.cpp]
3  *  of Fujitsu MB61VH010/011
4  *
5  * Author: K.Ohta <whatisthis.sowhat _at_ gmail.com>
6  * License: GPLv2
7  * History:
8  *   Mar 28, 2015 : Initial
9  *
10  */
11
12 #include "mb61vh010.h"
13
14
15 MB61VH010::MB61VH010(VM *parent_vm, EMU *parent_emu) : DEVICE(parent_vm, parent_emu)
16 {
17         p_emu = parent_emu;
18         p_vm = parent_vm;
19         target = NULL;
20 }
21
22 MB61VH010::~MB61VH010()
23 {
24 }
25
26 uint8_t MB61VH010::do_read(uint32_t addr, uint32_t bank)
27 {
28         uint32_t raddr;
29         
30         if(((1 << bank) & multi_page) != 0) return 0xff;
31         if(is_400line) {
32                 if((addr & 0xffff) < 0x8000) {
33                         raddr = (addr  & 0x7fff) | (0x8000 * bank);
34                         return target->read_data8(raddr + DISPLAY_VRAM_DIRECT_ACCESS);
35                 }
36         } else {
37                 raddr = (addr & 0x3fff) | (0x4000 * bank);
38                 return target->read_data8(raddr + DISPLAY_VRAM_DIRECT_ACCESS);
39         }
40         return 0xff;
41 }
42
43 uint8_t MB61VH010::do_write(uint32_t addr, uint32_t bank, uint8_t data)
44 {
45         uint32_t raddr;
46         uint8_t readdata;
47
48         if(((1 << bank) & multi_page) != 0) return 0xff;
49         if((command_reg & 0x40) != 0) { // Calculate before writing
50                 readdata = do_read(addr, bank);
51                 //readdata = data;
52                 if((command_reg & 0x20) != 0) { // NAND
53                         readdata = readdata & cmp_status_reg;
54                         data = data & (~cmp_status_reg);
55                 } else { // AND
56                         readdata = readdata & (~cmp_status_reg);
57                         data = data & cmp_status_reg;
58                 }
59                 readdata = readdata | data;
60         } else {
61                 readdata = data;
62         }
63         if(is_400line) {
64                 if((addr & 0xffff) < 0x8000) {
65                         raddr = (addr & 0x7fff) | (0x8000 * bank);
66                         target->write_data8(raddr + DISPLAY_VRAM_DIRECT_ACCESS, readdata);
67                 }
68         } else {
69                 raddr = (addr & 0x3fff) | (0x4000 * bank);
70                 target->write_data8(raddr + DISPLAY_VRAM_DIRECT_ACCESS, readdata);
71         }
72         return readdata;
73 }
74
75
76 uint8_t MB61VH010::do_pset(uint32_t addr)
77 {
78         int i;
79         uint32_t raddr = addr;  // Use banked ram.
80         uint8_t bitmask;
81         uint8_t srcdata;
82         int planes_b = planes;
83         if(planes_b >= 4) planes_b = 4;
84         for(i = 0; i < planes_b; i++) {
85                 if((bank_disable_reg & (1 << i)) != 0) {
86                         continue;
87                 }
88                 if((color_reg & (1 << i)) == 0) {
89                         bitmask = 0x00;
90                 } else {
91                         bitmask = 0xff;
92                 }
93                 
94                 srcdata = do_read(addr, i);
95                 bitmask = bitmask & (~mask_reg);
96                 srcdata = srcdata & mask_reg;
97                 srcdata = srcdata | bitmask;
98                 do_write(addr, i, srcdata);
99         }
100         return 0xff;
101 }
102
103 uint8_t MB61VH010::do_blank(uint32_t addr)
104 {
105         uint32_t i;
106         uint8_t srcdata;
107
108         if(planes >= 4) planes = 4;
109         for(i = 0; i < planes; i++) {
110                 if((bank_disable_reg & (1 << i)) != 0) {
111                         continue;
112                 }
113                 srcdata = do_read(addr, i);
114                 srcdata = srcdata & mask_reg;
115                 do_write(addr, i, srcdata);
116         }
117         return 0xff;
118 }
119
120 uint8_t MB61VH010::do_or(uint32_t addr)
121 {
122         uint32_t i;
123         uint8_t bitmask;
124         uint8_t srcdata;
125         
126         if(planes >= 4) planes = 4;
127         for(i = 0; i < planes; i++) {
128                 if((bank_disable_reg & (1 << i)) != 0) {
129                         continue;
130                 }
131                 srcdata = do_read(addr, i);
132                 if((color_reg & (1 << i)) == 0) {
133                         bitmask = srcdata; // srcdata | 0x00
134                 } else {
135                         bitmask = 0xff; // srcdata | 0xff
136                 }
137                 bitmask = bitmask & ~mask_reg;
138                 srcdata = (srcdata & mask_reg) | bitmask;
139                 do_write(addr, i, srcdata);
140         }
141         return 0xff;
142 }
143
144 uint8_t MB61VH010::do_and(uint32_t addr)
145 {
146         uint32_t i;
147         uint8_t bitmask;
148         uint8_t srcdata;
149
150         if(planes >= 4) planes = 4;
151         for(i = 0; i < planes; i++) {
152                 if((bank_disable_reg & (1 << i)) != 0) {
153                         continue;
154                 }
155                 srcdata = do_read(addr, i);
156                 if((color_reg & (1 << i)) == 0) {
157                         bitmask = 0x00; // srcdata & 0x00
158                 } else {
159                         bitmask = srcdata; // srcdata & 0xff;
160                 }
161                 bitmask = bitmask & ~mask_reg;
162                 srcdata = (srcdata & mask_reg) | bitmask;
163                 do_write(addr, i, srcdata);
164         }
165         return 0xff;
166 }
167
168 uint8_t MB61VH010::do_xor(uint32_t addr)
169 {
170         uint32_t i;
171         uint8_t bitmask;
172         uint8_t srcdata;
173
174         if(planes >= 4) planes = 4;
175         for(i = 0; i < planes; i++) {
176                 if((bank_disable_reg & (1 << i)) != 0) {
177                         continue;
178                 }
179                 srcdata = do_read(addr, i);
180                 if((color_reg & (1 << i)) == 0) {
181                         bitmask = srcdata ^ 0x00;
182                 } else {
183                         bitmask = srcdata ^ 0xff;
184                 }
185                 bitmask = bitmask & ~mask_reg;
186                 srcdata = (srcdata & mask_reg) | bitmask;
187                 do_write(addr, i, srcdata);
188         }
189         return 0xff;
190 }
191
192 uint8_t MB61VH010::do_not(uint32_t addr)
193 {
194         uint32_t i;
195         uint8_t bitmask;
196         uint8_t srcdata;
197
198         if(planes >= 4) planes = 4;
199         for(i = 0; i < planes; i++) {
200                 if((bank_disable_reg & (1 << i)) != 0) {
201                         continue;
202                 }
203                 srcdata = do_read(addr, i);
204                 bitmask = ~srcdata;
205                 
206                 bitmask = bitmask & ~mask_reg;
207                 srcdata = (srcdata & mask_reg) | bitmask;
208                 do_write(addr, i, srcdata);
209         }
210         return 0xff;
211 }
212
213
214 uint8_t MB61VH010::do_tilepaint(uint32_t addr)
215 {
216         uint32_t i;
217         uint8_t bitmask;
218         uint8_t srcdata;
219
220         if(planes > 4) planes = 4;
221         for(i = 0; i < planes; i++) {
222                 if((bank_disable_reg & (1 << i)) != 0) {
223                         continue;
224                 }
225                 srcdata = do_read(addr, i);
226                 bitmask = tile_reg[i] & (~mask_reg);
227                 srcdata = (srcdata & mask_reg) | bitmask;
228                 do_write(addr, i, srcdata);
229         }
230         return 0xff;
231 }
232
233 uint8_t MB61VH010::do_compare(uint32_t addr)
234 {
235         uint32_t offset = 0x4000;
236         uint8_t r, g, b;
237         uint8_t disables = ~bank_disable_reg;
238
239         uint8_t tmpcol;
240         uint8_t tmp_stat = 0;
241         uint8_t cmp_reg_bak[8];
242         int k;
243         int i;
244         int j;
245         
246         disables = disables & 0x07;
247         k = 0;
248         for(j = 0; j < 8; j++) {
249                 if((cmp_color_data[j] & 0x80) == 0) {
250                         cmp_reg_bak[k] = cmp_color_data[j] & disables;
251                         k++;
252                 }
253         }
254         cmp_status_reg = 0x00;
255         if(k <= 0) return 0xff;
256         b = do_read(addr, 0);
257         r = do_read(addr, 1);
258         g = do_read(addr, 2);
259         for(i = 0; i < 8; i++) {
260                 tmp_stat <<= 1;
261                 tmpcol  = (b & 0x80) >> 7;
262                 tmpcol  = tmpcol | ((r & 0x80) >> 6);
263                 tmpcol  = tmpcol | ((g & 0x80) >> 5);
264                 //tmpcol |= ((t & 0x80) != 0) ? 8 : 0;
265                 tmpcol = tmpcol & disables;
266                 for(j = 0; j < k; j++) {
267                         if(cmp_reg_bak[j] == tmpcol) {
268                                 tmp_stat = tmp_stat | 0x01;
269                                 goto _l0;
270                         }
271                 }
272 _l0:       
273                 b <<= 1;
274                 r <<= 1;
275                 g <<= 1;
276         }
277         cmp_status_reg = tmp_stat;
278         return 0xff;
279 }
280
281 void MB61VH010::do_alucmds_dmyread(uint32_t addr)
282 {
283         if(!is_400line) {
284                 addr = addr & 0x3fff;
285         } else {
286                 if(addr >= 0x8000) {
287                         mask_reg = 0xff;
288                         return;
289                 }
290                 addr = addr & 0x7fff;
291         }
292         if((command_reg & 0x80) == 0) {
293                 return;
294         }
295         //busy_flag = true;
296         //cmp_status_reg = 0x00;
297         if((command_reg & 0x40) != 0) do_compare(addr);
298         switch(command_reg & 0x07) {
299                 case 0:
300                         do_pset(addr);
301                         break;
302                 case 1:
303                         do_blank(addr);
304                         break;
305                 case 2:
306                         do_or(addr);
307                         break;
308                 case 3:
309                         do_and(addr);
310                         break;
311                 case 4:
312                         do_xor(addr);
313                         break;
314                 case 5:
315                         do_not(addr);
316                         break;
317                 case 6:
318                         do_tilepaint(addr);
319                         break;
320                 case 7:
321                         do_compare(addr);
322                         break;
323         }
324         //p_emu->out_debug_log("ALU DMYREAD ADDR=%04x, CMD=%02x CMP STATUS=%02x\n", addr, command_reg, cmp_status_reg);
325         //if(eventid_busy >= 0) cancel_event(this, eventid_busy) ;
326         //register_event(this, EVENT_MB61VH010_BUSY_OFF, 1.0 / 16.0, false, &eventid_busy) ;
327 }  
328
329 uint8_t MB61VH010::do_alucmds(uint32_t addr)
330 {
331         if(!is_400line) {
332                 addr = addr & 0x3fff;
333         } else {
334                 if(addr >= 0x8000) {
335                         mask_reg = 0xff;
336                         return 0xff;
337                 }
338                 addr = addr & 0x7fff;
339         }
340         //cmp_status_reg = 0x00;
341         if((command_reg & 0x40) != 0) do_compare(addr);
342         switch(command_reg & 0x07) {
343                 case 0:
344                         return do_pset(addr);
345                         break;
346                 case 1:
347                         return do_blank(addr);
348                         break;
349                 case 2:
350                         return do_or(addr);
351                         break;
352                 case 3:
353                         return do_and(addr);
354                         break;
355                 case 4:
356                         return do_xor(addr);
357                         break;
358                 case 5:
359                         return do_not(addr);
360                         break;
361                 case 6:
362                         return do_tilepaint(addr);
363                         break;
364                 case 7:
365                         return do_compare(addr);
366                         break;
367         }
368         return 0xff;
369 }
370
371 void MB61VH010::do_line(void)
372 {
373         uint32_t x_begin = line_xbegin.w.l;
374         uint32_t x_end = line_xend.w.l;
375         uint32_t y_begin = line_ybegin.w.l;
376         uint32_t y_end = line_yend.w.l;
377         int cpx_t = (int)x_begin;
378         int cpy_t = (int)y_begin;
379         int ax = (int)x_end - (int)x_begin;
380         int ay = (int)y_end - (int)y_begin;
381         int diff = 0;
382         int count = 0;
383         int xcount;
384         int ycount;
385         //uint8_t mask_bak = mask_reg;
386         uint16_t tmp8a;
387         uint8_t vmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
388         double usec;
389         bool lastflag = false;
390         
391
392         oldaddr = 0xffffffff;
393         alu_addr = 0xffffffff;
394         //if ((x_begin >= screen_width) && (x_end >= screen_width)) return;
395         //if ((y_begin >= screen_height) && (y_end >= screen_height)) return;
396         line_style = line_pattern;
397         busy_flag = true;
398         total_bytes = 0;
399         
400         mask_reg = 0xff;
401         if ((line_style.b.h & 0x80) != 0) {
402                 mask_reg &= ~vmask[cpx_t & 7];
403         }
404         xcount = abs(ax);
405         ycount = abs(ay);
406         //p_emu->out_debug_log("LINE: (%d,%d)-(%d,%d)\n", x_begin, y_begin, x_end , y_end); 
407         if(ycount == 0) {
408                 if(ax > 0) {
409                         if((cpx_t & 0x07) != 7) total_bytes = 1;
410                         //if((x_end >= screen_width) && (x_begin < screen_width)) x_end = screen_width - 1;
411                         for(; cpx_t <= (int)x_end; cpx_t++) {
412                                 if(cpy_t >= screen_width) break;
413                                 lastflag = put_dot(cpx_t, cpy_t);
414                                 if((cpx_t & 0x07) == 7) total_bytes++;
415                         }
416                 } else {
417                         if((cpx_t & 0x07) != 0) total_bytes = 1;
418                         for(; cpx_t >= (int)x_end; cpx_t--) {
419                                 if(cpy_t < 0) break;
420                                 if((cpx_t & 0x07) == 0) total_bytes++;
421                                 lastflag = put_dot(cpx_t, cpy_t);
422                         }
423                 }
424         } else if(xcount == 0) {
425                 if(ay > 0) {
426                         for(; cpy_t <= (int)y_end; cpy_t++) {
427                                 if(cpy_t >= screen_height) break;
428                                 lastflag = put_dot(cpx_t, cpy_t);
429                                 total_bytes++;
430                         }
431                 } else {
432                         for(; cpy_t  >= (int)y_end; cpy_t--) {
433                                 if(cpy_t < 0) break;
434                                 lastflag = put_dot(cpx_t, cpy_t);
435                                 total_bytes++;
436                         }
437                 }
438         } else if(xcount >= ycount) {
439                 diff = (ycount * 32768) / xcount;
440                 if(ax < 0) {
441                         //if(x_end == 0) xcount = x_begin;
442                         if((cpx_t & 0x07) != 0) total_bytes = 1;
443                 } else {
444                         if(x_end >= screen_width) xcount = (int)screen_width - (int)x_begin - 1;
445                         if((cpx_t & 0x07) == 0) total_bytes = 1;
446                 }
447                 for(; xcount >= 0; xcount-- ) {
448                         lastflag = put_dot(cpx_t, cpy_t);
449                         count += diff;
450                         if(count > 16384) {
451                                 if(ay < 0) {
452                                         cpy_t--;
453                                         if(cpy_t < 0) break;
454                                 } else {
455                                         cpy_t++;
456                                         if(cpy_t >= screen_height) break;
457                                 }
458                                 total_bytes++;
459                                 count -= 32768;
460                         }
461                         if(ax > 0) {
462                                 cpx_t++;
463                                 if((cpx_t & 0x07) == 0) total_bytes++;
464                                 if(cpx_t >= screen_width) break;
465                         } else if(ax < 0) {
466                                 if((cpx_t & 0x07) == 0) total_bytes++;
467                                 cpx_t--;
468                                 if(cpx_t < 0) break;
469                         }
470                 }
471         } else { // (abs(ax) <= abs(ay)
472                 diff = (xcount  * 32768) / ycount;
473                 if(ay < 0) {
474                         //if(y_end < 0) ycount = y_begin;
475                 } else {
476                         if(y_end >= screen_height) ycount = screen_height - y_begin - 1;
477                 }
478                 for(; ycount >= 0; ycount--) {
479                         lastflag = put_dot(cpx_t, cpy_t);
480                         count += diff;
481                         if(count > 16384) {
482                                 if(ax < 0) {
483                                         cpx_t--;
484                                         if(cpx_t < 0) break;
485                                 } else if(ax > 0) {
486                                         cpx_t++;
487                                         if(cpx_t > screen_width) break;
488                                 }
489                                 count -= 32768;
490                         }
491                         total_bytes++;
492                         if(ay > 0) {
493                                 cpy_t++;
494                                 if(cpy_t >= screen_height) break;
495                         } else {
496                                 cpy_t--;
497                                 if(cpy_t < 0) break;
498                         }
499                 }
500         }
501         //if(!lastflag) total_bytes++;
502         if(alu_addr < 0x8000) do_alucmds(alu_addr);
503    
504         //if(total_bytes > 16) { // Over 1.0us
505         usec = (double)total_bytes / 16.0;
506         if(eventid_busy >= 0) cancel_event(this, eventid_busy) ;
507         register_event(this, EVENT_MB61VH010_BUSY_OFF, usec, false, &eventid_busy) ;
508         //} else {
509         //      busy_flag = false;
510         //}
511 }
512
513 bool MB61VH010::put_dot(int x, int y)
514 {
515         uint8_t vmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
516         uint16_t tmp8a;
517         bool flag = false;
518         
519         if((x < 0) || (y < 0)) return false;
520         if(y >= (int)screen_height) return false;
521         if((command_reg & 0x80) == 0) return false;
522         
523         alu_addr = (y * screen_width + x)  >> 3;
524         alu_addr = alu_addr + line_addr_offset.w.l;
525         alu_addr = alu_addr & 0x7fff;
526         if(!is_400line) alu_addr = alu_addr & 0x3fff;
527         
528         if(oldaddr != alu_addr) {
529                 if(oldaddr == 0xffffffff) {
530                         if((line_style.b.h & 0x80) != 0) {
531                                 mask_reg &= ~vmask[x & 7];
532                         }
533                         oldaddr = alu_addr;
534                 }
535                 do_alucmds(oldaddr);
536                 mask_reg = 0xff;
537                 oldaddr = alu_addr;
538                 flag = true;
539                 //total_bytes++;
540         }
541         if((line_style.b.h & 0x80) != 0) {
542                 mask_reg &= ~vmask[x & 7];
543         }
544         tmp8a = ((line_style.b.h & 0x80) >> 7) & 0x01;
545         line_style.w.l = (line_style.w.l << 1) | tmp8a;
546         return flag;
547 }
548
549 void MB61VH010::write_data8(uint32_t id, uint32_t data)
550 {
551         //p_emu->out_debug_log("ALU: ADDR=%02x DATA=%02x\n", id, data);
552         if(id == ALU_CMDREG) {
553                 command_reg = data;
554                 return;
555         }
556         switch(id) {
557                 case ALU_LOGICAL_COLOR:
558                         color_reg = data;
559                         break;
560                 case ALU_WRITE_MASKREG:
561                         mask_reg = data;
562                         break;
563                 case ALU_BANK_DISABLE:
564                         bank_disable_reg = data;
565                         break;
566                 case ALU_TILEPAINT_B:
567                         tile_reg[0] = data;
568                         break;
569                 case ALU_TILEPAINT_R:
570                         tile_reg[1] = data;
571                         break;
572                 case ALU_TILEPAINT_G:
573                         tile_reg[2] = data;
574                         break;
575                 case ALU_TILEPAINT_L:
576                         tile_reg[3] = data;
577                         break;
578                 case ALU_OFFSET_REG_HIGH:
579                         line_addr_offset.b.h &= 0x01;
580                         line_addr_offset.b.h = line_addr_offset.b.h | ((data << 1) & 0x3e);
581                         break;
582                 case ALU_OFFSET_REG_LO:
583                         line_addr_offset.b.l = data << 1;
584                         line_addr_offset.b.h &= 0xfe;
585                         line_addr_offset.b.h = line_addr_offset.b.h | ((data >> 7) & 0x01);
586                         break;
587                 case ALU_LINEPATTERN_REG_HIGH:
588                         line_pattern.b.h = data;
589                         break;
590                 case ALU_LINEPATTERN_REG_LO:
591                         line_pattern.b.l = data;
592                         break;
593                 case ALU_LINEPOS_START_X_HIGH:
594                         line_xbegin.b.h = data & 0x03;
595                         break;
596                 case ALU_LINEPOS_START_X_LOW:  
597                         line_xbegin.b.l = data;
598                         break;
599                 case ALU_LINEPOS_START_Y_HIGH:
600                         line_ybegin.b.h = data & 0x01;
601                         break;
602                 case ALU_LINEPOS_START_Y_LOW:  
603                         line_ybegin.b.l = data;
604                         break;
605                 case ALU_LINEPOS_END_X_HIGH:
606                         line_xend.b.h = data & 0x03;
607                         break;
608                 case ALU_LINEPOS_END_X_LOW:  
609                         line_xend.b.l = data;
610                         break;
611                 case ALU_LINEPOS_END_Y_HIGH:
612                         line_yend.b.h = data & 0x01;
613                         break;
614                 case ALU_LINEPOS_END_Y_LOW:
615                         line_yend.b.l = data;
616                         do_line();
617                         break;
618                 default:
619                         if((id >= (ALU_CMPDATA_REG + 0)) && (id < (ALU_CMPDATA_REG + 8))) {
620                                 cmp_color_data[id - ALU_CMPDATA_REG] = data;
621                         } else  if((id >= ALU_WRITE_PROXY) && (id < (ALU_WRITE_PROXY + 0xc000))) {
622                                 uint32_t raddr = id - ALU_WRITE_PROXY;
623                                 if(is_400line) {
624                                         if(raddr >= 0x8000) return;
625                                 } else {
626                                         raddr = raddr & 0x3fff;
627                                 }
628                                 do_alucmds_dmyread(raddr);
629                         }
630                         break;
631         }
632 }
633
634 uint32_t MB61VH010::read_data8(uint32_t id)
635 {
636         uint32_t raddr;  
637         switch(id) {
638                 case ALU_CMDREG:
639                         return (uint32_t)command_reg;
640                         break;
641                 case ALU_LOGICAL_COLOR:
642                         return (uint32_t)color_reg;
643                         break;
644                 case ALU_WRITE_MASKREG:
645                         return (uint32_t)mask_reg;
646                         break;
647                 case ALU_CMP_STATUS_REG:
648                         return (uint32_t)cmp_status_reg;
649                         break;
650                 case ALU_BANK_DISABLE:
651                         return (uint32_t)bank_disable_reg;
652                         break;
653                 default:
654                         if((id >= ALU_WRITE_PROXY) && (id < (ALU_WRITE_PROXY + 0xc000))) {
655                                 uint32_t dmydata;
656                                 raddr = id - ALU_WRITE_PROXY;
657                                 if(is_400line) {
658                                         if(raddr >= 0x8000) return 0xffffffff;
659                                 } else {
660                                         raddr = raddr & 0x3fff;
661                                 }
662                                 //dmydata = target->read_data8(raddr + DISPLAY_VRAM_DIRECT_ACCESS);
663                                 do_alucmds_dmyread(raddr);
664                                 raddr = (id - ALU_WRITE_PROXY) % 0xc000;
665                                 dmydata = target->read_data8(raddr + DISPLAY_VRAM_DIRECT_ACCESS);
666                                 return dmydata;
667                         }
668                         return 0xffffffff;
669                         break;
670         }
671 }
672
673 uint32_t MB61VH010::read_signal(int id)
674 {
675         uint32_t val = 0x00000000;
676         switch(id) {
677                 case SIG_ALU_BUSYSTAT:
678                         if(busy_flag) val = 0xffffffff;
679                         break;
680                 case SIG_ALU_ENABLED:
681                         val = ((command_reg & 0x80) != 0) ? 0xffffffff : 0;
682                         break;
683         }
684         return val;
685 }
686
687 void MB61VH010::write_signal(int id, uint32_t data, uint32_t mask)
688 {
689         bool flag = ((data & mask) != 0);
690         switch(id) {
691                 case SIG_ALU_400LINE:
692                         is_400line = flag;
693                         break;
694                 case SIG_ALU_MULTIPAGE:
695                         multi_page = (data & mask) & 0x07;
696                         break;
697                 case SIG_ALU_PLANES:
698                         planes = (data & mask) & 0x07;
699                         if(planes >= 4) planes = 4;
700                         break;
701                 case SIG_ALU_X_WIDTH:
702                         screen_width = (data << 3) & 0x3ff;
703                         break;
704                 case SIG_ALU_Y_HEIGHT:
705                         screen_height = data & 0x3ff;
706                         break;
707         }
708 }
709
710 void MB61VH010::event_callback(int event_id, int err)
711 {
712         switch(event_id) {
713                 case EVENT_MB61VH010_BUSY_ON:
714                         busy_flag = true;
715                         if(eventid_busy >= 0) cancel_event(this, eventid_busy);
716                         eventid_busy = -1;
717                         break;
718                 case EVENT_MB61VH010_BUSY_OFF:
719                         busy_flag = false;
720                         eventid_busy = -1;
721                         break;
722         }
723 }
724
725 void MB61VH010::initialize(void)
726 {
727         int i;
728         busy_flag = false;
729         is_400line = false;
730         eventid_busy = -1;
731         multi_page = 0x00;
732         planes = 3;
733         screen_width = 640;
734         screen_height = 200;
735 #if 1
736         command_reg = 0;        // D410 (RW)
737         color_reg = 0;          // D411 (RW)
738         mask_reg = 0;           // D412 (RW)
739         cmp_status_reg = 0;     // D413 (RO)
740         for(i = 0; i < 8; i++) cmp_color_data[i] = 0x80; // D413-D41A (WO)
741         bank_disable_reg = 0;   // D41B (RW)
742         for(i = 0; i < 4; i++) tile_reg[i] = 0;        // D41C-D41F (WO)
743         
744         line_addr_offset.d = 0; // D420-D421 (WO)
745         line_pattern.d = 0;     // D422-D423 (WO)
746         line_xbegin.d = 0;      // D424-D425 (WO)
747         line_ybegin.d = 0;      // D426-D427 (WO)
748         line_xend.d = 0;        // D428-D429 (WO)
749         line_yend.d = 0;        // D42A-D42B (WO)
750 #endif  
751 }
752
753 void MB61VH010::reset(void)
754 {
755         int i;
756         busy_flag = false;
757         if(eventid_busy >= 0) cancel_event(this, eventid_busy);
758         eventid_busy = -1;
759 #if 1
760         command_reg = 0;        // D410 (RW)
761         color_reg = 0;          // D411 (RW)
762         mask_reg = 0;           // D412 (RW)
763         cmp_status_reg = 0;     // D413 (RO)
764         for(i = 0; i < 8; i++) cmp_color_data[i] = 0x80; // D413-D41A (WO)
765         bank_disable_reg = 0;   // D41B (RW)
766         for(i = 0; i < 4; i++) tile_reg[i] = 0;        // D41C-D41F (WO)
767         
768         line_addr_offset.d = 0; // D420-D421 (WO)
769         line_pattern.d = 0;     // D422-D423 (WO)
770         line_xbegin.d = 0;      // D424-D425 (WO)
771         line_ybegin.d = 0;      // D426-D427 (WO)
772         line_xend.d = 0;        // D428-D429 (WO)
773         line_yend.d = 0;        // D42A-D42B (WO)
774 #endif  
775         oldaddr = 0xffffffff;
776         
777         if(planes >= 4) planes = 4;
778 }
779
780 #define STATE_VERSION 1
781 void MB61VH010::save_state(FILEIO *state_fio)
782 {
783         int i;
784         state_fio->FputUint32(STATE_VERSION);
785         state_fio->FputInt32(this_device_id);
786         p_emu->out_debug_log("Save State: MB61VH010 : id=%d ver=%d\n", this_device_id, STATE_VERSION);
787
788         { // V1
789                 state_fio->FputUint8(command_reg);
790                 state_fio->FputUint8(color_reg);
791                 state_fio->FputUint8(mask_reg);
792                 state_fio->FputUint8(cmp_status_reg);
793                 for(i = 0; i < 8; i++)  state_fio->FputUint8(cmp_color_data[i]);
794                 state_fio->FputUint8(bank_disable_reg);
795                 for(i = 0; i < 4; i++)  state_fio->FputUint8(tile_reg[i]);
796                 state_fio->FputUint8(multi_page);
797                 
798                 state_fio->FputUint32_BE(line_addr_offset.d);
799                 state_fio->FputUint16_BE(line_pattern.w.l);
800                 state_fio->FputUint16_BE(line_xbegin.w.l);
801                 state_fio->FputUint16_BE(line_ybegin.w.l);
802                 state_fio->FputUint16_BE(line_xend.w.l);
803                 state_fio->FputUint16_BE(line_yend.w.l);
804                 
805                 state_fio->FputBool(busy_flag);
806                 state_fio->FputInt32_BE(eventid_busy);
807
808                 state_fio->FputUint32_BE(total_bytes);
809                 state_fio->FputUint32_BE(oldaddr);
810                 state_fio->FputUint32_BE(alu_addr);
811
812                 state_fio->FputUint32_BE(planes);
813                 state_fio->FputBool(is_400line);
814                 state_fio->FputUint32_BE(screen_width);
815                 state_fio->FputUint32_BE(screen_height);
816
817                 state_fio->FputUint16_BE(line_style.w.l);
818         }
819    
820 }
821
822 bool MB61VH010::load_state(FILEIO *state_fio)
823 {
824         uint32_t version = state_fio->FgetUint32();
825         int i;
826         p_emu->out_debug_log("Load State: MB61VH010 : id=%d ver=%d\n", this_device_id, version);
827         if(this_device_id != state_fio->FgetInt32()) return false;
828         if(version >= 1) {
829                 command_reg = state_fio->FgetUint8();
830                 color_reg = state_fio->FgetUint8();
831                 mask_reg = state_fio->FgetUint8();
832                 cmp_status_reg = state_fio->FgetUint8();
833                 for(i = 0; i < 8; i++)  cmp_color_data[i] = state_fio->FgetUint8();
834                 bank_disable_reg = state_fio->FgetUint8();
835                 for(i = 0; i < 4; i++)  tile_reg[i] = state_fio->FgetUint8();
836                 multi_page = state_fio->FgetUint8();
837
838                 line_addr_offset.d = state_fio->FgetUint32_BE();
839                 line_pattern.d = 0;
840                 line_xbegin.d = 0;
841                 line_ybegin.d = 0;
842                 line_xend.d = 0;
843                 line_yend.d = 0;
844            
845                 line_pattern.w.l = state_fio->FgetUint16_BE();
846                 line_xbegin.w.l = state_fio->FgetUint16_BE();
847                 line_ybegin.w.l = state_fio->FgetUint16_BE();
848                 line_xend.w.l = state_fio->FgetUint16_BE();
849                 line_yend.w.l = state_fio->FgetUint16_BE();
850
851                 busy_flag = state_fio->FgetBool();
852                 eventid_busy = state_fio->FgetInt32_BE();
853                 
854                 total_bytes = state_fio->FgetUint32_BE();
855                 oldaddr = state_fio->FgetUint32_BE();
856                 alu_addr = state_fio->FgetUint32_BE();
857
858                 planes = state_fio->FgetUint32_BE();
859                 is_400line = state_fio->FgetBool();
860                 screen_width = state_fio->FgetUint32_BE();
861                 screen_height = state_fio->FgetUint32_BE();
862
863                 line_style.d = 0;
864                 line_style.w.l = state_fio->FgetUint16_BE();
865         }
866         if(version != STATE_VERSION) return false;
867         return true;
868 }