OSDN Git Service

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