OSDN Git Service

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