OSDN Git Service

[VM][FM7] Move mb61vh010.[cpp|h] and hd6844.[cpp|h] to source/src/vm .
[csp-qt/common_source_project-fm7.git] / source / src / vm / 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         cmp_status_reg = 0x00;
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 = r = g = 0;
257         b = do_read(addr, 0);
258         r = do_read(addr, 1);
259         g = do_read(addr, 2);
260         for(i = 0; i < 8; i++) {
261                 tmp_stat <<= 1;
262                 tmpcol  = (b & 0x80) >> 7;
263                 tmpcol  = tmpcol | ((r & 0x80) >> 6);
264                 tmpcol  = tmpcol | ((g & 0x80) >> 5);
265                 //tmpcol |= ((t & 0x80) != 0) ? 8 : 0;
266                 tmpcol = tmpcol & disables;
267                 for(j = 0; j < k; j++) {
268                         if(cmp_reg_bak[j] == tmpcol) {
269                                 tmp_stat = tmp_stat | 0x01;
270                                 goto _l0;
271                         }
272                 }
273 _l0:       
274                 b <<= 1;
275                 r <<= 1;
276                 g <<= 1;
277         }
278         cmp_status_reg = tmp_stat;
279         return 0xff;
280 }
281
282 void MB61VH010::do_alucmds_dmyread(uint32 addr)
283 {
284         if(!is_400line) {
285                 addr = addr & 0x3fff;
286         } else {
287                 if(addr >= 0x8000) {
288                         mask_reg = 0xff;
289                         return;
290                 }
291                 addr = addr & 0x7fff;
292         }
293         if((command_reg & 0x80) == 0) {
294                 return;
295         }
296         //busy_flag = true;
297         //cmp_status_reg = 0x00;
298         if((command_reg & 0x40) != 0) do_compare(addr);
299         switch(command_reg & 0x07) {
300                 case 0:
301                         do_pset(addr);
302                         break;
303                 case 1:
304                         do_blank(addr);
305                         break;
306                 case 2:
307                         do_or(addr);
308                         break;
309                 case 3:
310                         do_and(addr);
311                         break;
312                 case 4:
313                         do_xor(addr);
314                         break;
315                 case 5:
316                         do_not(addr);
317                         break;
318                 case 6:
319                         do_tilepaint(addr);
320                         break;
321                 case 7:
322                         do_compare(addr);
323                         break;
324         }
325         //printf("ALU DMYREAD ADDR=%04x, CMD=%02x CMP STATUS=%02x\n", addr, command_reg, cmp_status_reg);
326         //if(eventid_busy >= 0) cancel_event(this, eventid_busy) ;
327         //register_event(this, EVENT_MB61VH010_BUSY_OFF, 1.0 / 16.0, false, &eventid_busy) ;
328 }  
329
330 uint8 MB61VH010::do_alucmds(uint32 addr)
331 {
332         if(!is_400line) {
333                 addr = addr & 0x3fff;
334         } else {
335                 if(addr >= 0x8000) {
336                         mask_reg = 0xff;
337                         return 0xff;
338                 }
339                 addr = addr & 0x7fff;
340         }
341         //cmp_status_reg = 0x00;
342         if((command_reg & 0x40) != 0) do_compare(addr);
343         switch(command_reg & 0x07) {
344                 case 0:
345                         return do_pset(addr);
346                         break;
347                 case 1:
348                         return do_blank(addr);
349                         break;
350                 case 2:
351                         return do_or(addr);
352                         break;
353                 case 3:
354                         return do_and(addr);
355                         break;
356                 case 4:
357                         return do_xor(addr);
358                         break;
359                 case 5:
360                         return do_not(addr);
361                         break;
362                 case 6:
363                         return do_tilepaint(addr);
364                         break;
365                 case 7:
366                         return do_compare(addr);
367                         break;
368         }
369         return 0xff;
370 }
371
372 void MB61VH010::do_line(void)
373 {
374         uint32 x_begin = line_xbegin.w.l;
375         uint32 x_end = line_xend.w.l;
376         uint32 y_begin = line_ybegin.w.l;
377         uint32 y_end = line_yend.w.l;
378         int cpx_t = (int)x_begin;
379         int cpy_t = (int)y_begin;
380         int ax = (int)x_end - (int)x_begin;
381         int ay = (int)y_end - (int)y_begin;
382         int diff = 0;
383         int count = 0;
384         int xcount;
385         int ycount;
386         uint8 mask_bak = mask_reg;
387         uint16 tmp8a;
388         uint8 vmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
389         double usec;
390         bool lastflag = false;
391         
392
393         oldaddr = 0xffffffff;
394         alu_addr = 0xffffffff;
395         //if ((x_begin >= screen_width) && (x_end >= screen_width)) return;
396         //if ((y_begin >= screen_height) && (y_end >= screen_height)) return;
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         //printf("LINE: (%d,%d)-(%d,%d)\n", x_begin, y_begin, x_end , y_end); 
411         if(ycount == 0) {
412                 if(ax > 0) {
413                         //if((x_end >= screen_width) && (x_begin < screen_width)) x_end = screen_width - 1;
414                         //printf("LINE: (%d,%d)-(%d,%d)\n", x_begin, y_begin, x_end , y_end); 
415                         for(; cpx_t <= (int)x_end; cpx_t++) {
416                                 lastflag = put_dot(cpx_t, cpy_t);
417                         }
418                 } else {
419                         for(; cpx_t >= (int)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_begin < screen_height)) y_end = screen_height - 1;
426                         for(; cpy_t <= (int)y_end; cpy_t++) {
427                                 lastflag = put_dot(cpx_t, cpy_t);
428                         }
429                 } else {
430                         for(; cpy_t  >= (int)y_end; cpy_t--) {
431                                 lastflag = put_dot(cpx_t, cpy_t);
432                         }
433                 }
434         } else if(xcount >= ycount) {
435                 diff = (ycount * 32768) / xcount;
436                 if(ax < 0) {
437                         if(x_end < 0) xcount = x_begin;
438                 } else {
439                         if(x_end >= screen_width) xcount = (int)screen_width - (int)x_begin - 1;
440                 }
441                 for(; xcount >= 0; xcount-- ) {
442                         lastflag = put_dot(cpx_t, cpy_t);
443                         count += diff;
444                         if(count > 16384) {
445                                 if(ay < 0) {
446                                         if(cpy_t > (int)y_end) cpy_t--;
447                                 } else {
448                                         if(cpy_t < (int)y_end) cpy_t++;
449                                 }
450                                 count -= 32768;
451                         }
452                         if(ax > 0) {
453                                 cpx_t++;
454                         } else if(ax < 0) {
455                                 cpx_t--;
456                         }
457                 }
458         } else if(xcount == ycount) {
459                 if(ax < 0) {
460                         xcount = x_begin;
461                 } else {
462                         if(x_end >= screen_width) xcount = (int)screen_width - (int)x_begin - 1;
463                 }
464                 for(; xcount >= 0; xcount-- ) {
465                         lastflag = put_dot(cpx_t, cpy_t);
466                         if(ay > 0) {
467                                 cpy_t++;
468                         } else {
469                                 cpy_t--;
470                         }
471                         if(ax > 0) {
472                                 cpx_t++;
473                         } else if(ax < 0) {
474                                 cpx_t--;
475                         }
476                 }
477         } else { // (abs(ax) <= abs(ay)
478                 diff = (xcount  * 32768) / ycount;
479                 if(ay < 0) {
480                         if(y_end < 0) ycount = y_begin;
481                 } else {
482                         if(y_end >= screen_height) ycount = screen_height - y_begin - 1;
483                 }
484                 for(; ycount >= 0; ycount--) {
485                         lastflag = put_dot(cpx_t, cpy_t);
486                         count += diff;
487                         if(count > 16384) {
488                                 if(ax < 0) {
489                                         if(cpx_t > (int)x_end) cpx_t--;
490                                 } else if(ax > 0) {
491                                         if(cpx_t < (int)x_end) cpx_t++;
492                                 }
493                                 count -= 32768;
494                         }
495                         if(ay > 0) {
496                                 cpy_t++;
497                         } else {
498                                 cpy_t--;
499                         }
500                 }
501         }
502         if(!lastflag) total_bytes++;
503         if(alu_addr != 0xffffffff) do_alucmds(alu_addr);
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         //mask_reg = mask_bak;
512 }
513
514 bool MB61VH010::put_dot(int x, int y)
515 {
516         uint8 vmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
517         uint16 tmp8a;
518         bool flag = false;
519         
520         if((x < 0) || (y < 0)) return flag;
521         //if((x >= (int)screen_width) || (y >= (int)screen_height)) return flag;
522         if(y >= (int)screen_height) return flag;
523         //if((command_reg & 0x80) == 0) return flag;
524         
525         alu_addr = (y * screen_width + x)  >> 3;
526         alu_addr = alu_addr + line_addr_offset.w.l;
527         alu_addr = alu_addr & 0x7fff;
528         if(!is_400line) alu_addr = alu_addr & 0x3fff;
529         
530         if(oldaddr != alu_addr) {
531                 if(oldaddr == 0xffffffff) oldaddr = alu_addr;
532                 //printf("** %d %d %04x %04x %02x\n", x, y, line_addr_offset.w, alu_addr, command_reg );
533                 do_alucmds(oldaddr);
534                 mask_reg = 0xff;
535                 oldaddr = alu_addr;
536                 flag = true;
537                 total_bytes++;
538         }
539         //printf("** %d %d %04x %04x %02x\n", x, y, line_addr_offset.w, alu_addr, command_reg );
540         
541         if((line_style.b.h & 0x80) != 0) {
542                 mask_reg &= ~vmask[x & 7];
543         }
544         //tmp8a = (line_style.w.l & 0x8000) >> 15;
545         tmp8a = ((line_style.b.h & 0x80) >> 7) & 0x01;
546         line_style.w.l = (line_style.w.l << 1) | tmp8a;
547         return flag;
548 }
549
550 void MB61VH010::write_data8(uint32 id, uint32 data)
551 {
552         //printf("ALU: ADDR=%02x DATA=%02x\n", id, data);
553         if(id == ALU_CMDREG) {
554                 command_reg = data;
555                 return;
556         }
557         switch(id) {
558                 case ALU_LOGICAL_COLOR:
559                         color_reg = data;
560                         break;
561                 case ALU_WRITE_MASKREG:
562                         mask_reg = data;
563                         break;
564                 case ALU_BANK_DISABLE:
565                         bank_disable_reg = data;
566                         break;
567                 case ALU_TILEPAINT_B:
568                         tile_reg[0] = data;
569                         break;
570                 case ALU_TILEPAINT_R:
571                         tile_reg[1] = data;
572                         break;
573                 case ALU_TILEPAINT_G:
574                         tile_reg[2] = data;
575                         break;
576                 case ALU_TILEPAINT_L:
577                         tile_reg[3] = data;
578                         break;
579                 case ALU_OFFSET_REG_HIGH:
580                         line_addr_offset.b.h &= 0x01;
581                         line_addr_offset.b.h = line_addr_offset.b.h | ((data << 1) & 0x3e);
582                         break;
583                 case ALU_OFFSET_REG_LO:
584                         line_addr_offset.b.l = data << 1;
585                         line_addr_offset.b.h &= 0xfe;
586                         line_addr_offset.b.h = line_addr_offset.b.h | ((data >> 7) & 0x01);
587                         break;
588                 case ALU_LINEPATTERN_REG_HIGH:
589                         line_pattern.b.h = data;
590                         break;
591                 case ALU_LINEPATTERN_REG_LO:
592                         line_pattern.b.l = data;
593                         break;
594                 case ALU_LINEPOS_START_X_HIGH:
595                         line_xbegin.b.h = data & 0x03;
596                         break;
597                 case ALU_LINEPOS_START_X_LOW:  
598                         line_xbegin.b.l = data;
599                         break;
600                 case ALU_LINEPOS_START_Y_HIGH:
601                         line_ybegin.b.h = data & 0x01;
602                         break;
603                 case ALU_LINEPOS_START_Y_LOW:  
604                         line_ybegin.b.l = data;
605                         break;
606                 case ALU_LINEPOS_END_X_HIGH:
607                         line_xend.b.h = data & 0x03;
608                         break;
609                 case ALU_LINEPOS_END_X_LOW:  
610                         line_xend.b.l = data;
611                         break;
612                 case ALU_LINEPOS_END_Y_HIGH:
613                         line_yend.b.h = data & 0x01;
614                         break;
615                 case ALU_LINEPOS_END_Y_LOW:
616                         line_yend.b.l = data;
617                         do_line();
618                         break;
619                 default:
620                         if((id >= (ALU_CMPDATA_REG + 0)) && (id < (ALU_CMPDATA_REG + 8))) {
621                                 cmp_color_data[id - ALU_CMPDATA_REG] = data;
622                         } else  if((id >= ALU_WRITE_PROXY) && (id < (ALU_WRITE_PROXY + 0x18000))) {
623                                 uint32 raddr = id - ALU_WRITE_PROXY;
624                                 if(is_400line) {
625                                         raddr = raddr & 0x7fff;
626                                 } else {
627                                         raddr = raddr & 0x3fff;
628                                 }
629                                 do_alucmds_dmyread(raddr);
630                         }
631                         break;
632         }
633 }
634
635 uint32 MB61VH010::read_data8(uint32 id)
636 {
637         uint32 raddr;  
638         switch(id) {
639                 case ALU_CMDREG:
640                         return (uint32)command_reg;
641                         break;
642                 case ALU_LOGICAL_COLOR:
643                         return (uint32)color_reg;
644                         break;
645                 case ALU_WRITE_MASKREG:
646                         return (uint32)mask_reg;
647                         break;
648                 case ALU_CMP_STATUS_REG:
649                         return (uint32)cmp_status_reg;
650                         break;
651                 case ALU_BANK_DISABLE:
652                         return (uint32)bank_disable_reg;
653                         break;
654                 default:
655                         if((id >= ALU_WRITE_PROXY) && (id < (ALU_WRITE_PROXY + 0x18000))) {
656                                 uint32 dmydata;
657                                 raddr = id - ALU_WRITE_PROXY;
658                                 if(is_400line) {
659                                         raddr = raddr & 0x7fff;
660                                 } else {
661                                         raddr = raddr & 0x3fff;
662                                 }
663                                 //dmydata = target->read_data8(raddr + DISPLAY_VRAM_DIRECT_ACCESS);
664                                 do_alucmds_dmyread(raddr);
665                                 raddr = (id - ALU_WRITE_PROXY) & 0xbfff;
666                                 dmydata = target->read_data8(raddr + DISPLAY_VRAM_DIRECT_ACCESS);
667                                 return dmydata;
668                         }
669                         return 0xffffffff;
670                         break;
671         }
672 }
673
674 uint32 MB61VH010::read_signal(int id)
675 {
676         uint32 val = 0x00000000;
677         switch(id) {
678                 case SIG_ALU_BUSYSTAT:
679                         if(busy_flag) val = 0xffffffff;
680                         break;
681         }
682         return val;
683 }
684
685 void MB61VH010::write_signal(int id, uint32 data, uint32 mask)
686 {
687         bool flag = ((data & mask) != 0);
688         switch(id) {
689                 case SIG_ALU_400LINE:
690                         is_400line = flag;
691                         break;
692                 case SIG_ALU_MULTIPAGE:
693                         multi_page = (data & mask) & 0x07;
694                         break;
695                 case SIG_ALU_PLANES:
696                         planes = (data & mask) & 0x07;
697                         if(planes >= 4) planes = 4;
698                         break;
699                 case SIG_ALU_X_WIDTH:
700                         screen_width = (data << 3) & 0x3ff;
701                         break;
702                 case SIG_ALU_Y_HEIGHT:
703                         screen_height = data & 0x3ff;
704                         break;
705         }
706 }
707
708 void MB61VH010::event_callback(int event_id, int err)
709 {
710         switch(event_id) {
711                 case EVENT_MB61VH010_BUSY_ON:
712                         busy_flag = true;
713                         if(eventid_busy >= 0) cancel_event(this, eventid_busy);
714                         eventid_busy = -1;
715                         break;
716                 case EVENT_MB61VH010_BUSY_OFF:
717                         busy_flag = false;
718                         eventid_busy = -1;
719                         break;
720         }
721 }
722
723 void MB61VH010::initialize(void)
724 {
725         busy_flag = false;
726         is_400line = false;
727         eventid_busy = -1;
728         multi_page = 0x00;
729         planes = 3;
730         screen_width = 640;
731         screen_height = 200;
732 }
733
734 void MB61VH010::reset(void)
735 {
736         int i;
737         busy_flag = false;
738         if(eventid_busy >= 0) cancel_event(this, eventid_busy);
739         eventid_busy = -1;
740         
741         command_reg = 0;        // D410 (RW)
742         color_reg = 0;          // D411 (RW)
743         mask_reg = 0;           // D412 (RW)
744         cmp_status_reg = 0;     // D413 (RO)
745         for(i = 0; i < 8; i++) cmp_color_data[i] = 0x80; // D413-D41A (WO)
746         bank_disable_reg = 0;   // D41B (RW)
747         for(i = 0; i < 4; i++) tile_reg[i] = 0;        // D41C-D41F (WO)
748         
749         line_addr_offset.d = 0; // D420-D421 (WO)
750         line_pattern.d = 0;     // D422-D423 (WO)
751         line_xbegin.d = 0;      // D424-D425 (WO)
752         line_ybegin.d = 0;      // D426-D427 (WO)
753         line_xend.d = 0;        // D428-D429 (WO)
754         line_yend.d = 0;        // D42A-D42B (WO)
755         oldaddr = 0xffffffff;
756         
757         if(planes >= 4) planes = 4;
758 }
759
760 #define STATE_VERSION 1
761 void MB61VH010::save_state(FILEIO *state_fio)
762 {
763         int i;
764         state_fio->FputUint32(STATE_VERSION);
765         state_fio->FputInt32(this_device_id);
766
767         { // V1
768                 state_fio->FputUint8(command_reg);
769                 state_fio->FputUint8(color_reg);
770                 state_fio->FputUint8(mask_reg);
771                 state_fio->FputUint8(cmp_status_reg);
772                 for(i = 0; i < 8; i++)  state_fio->FputUint8(cmp_color_data[i]);
773                 state_fio->FputUint8(bank_disable_reg);
774                 for(i = 0; i < 4; i++)  state_fio->FputUint8(tile_reg[i]);
775                 state_fio->FputUint8(multi_page);
776                 
777                 state_fio->FputUint32_BE(line_addr_offset.d);
778                 state_fio->FputUint16_BE(line_pattern.w.l);
779                 state_fio->FputUint16_BE(line_xbegin.w.l);
780                 state_fio->FputUint16_BE(line_ybegin.w.l);
781                 state_fio->FputUint16_BE(line_xend.w.l);
782                 state_fio->FputUint16_BE(line_yend.w.l);
783                 
784                 state_fio->FputBool(busy_flag);
785                 state_fio->FputInt32_BE(eventid_busy);
786
787                 state_fio->FputUint32_BE(total_bytes);
788                 state_fio->FputUint32_BE(oldaddr);
789                 state_fio->FputUint32_BE(alu_addr);
790
791                 state_fio->FputUint32_BE(planes);
792                 state_fio->FputBool(is_400line);
793                 state_fio->FputUint32_BE(screen_width);
794                 state_fio->FputUint32_BE(screen_height);
795
796                 state_fio->FputUint16_BE(line_style.w.l);
797         }
798    
799 }
800
801 bool MB61VH010::load_state(FILEIO *state_fio)
802 {
803         uint32 version = state_fio->FgetUint32();
804         int i;
805    
806         if(this_device_id != state_fio->FgetInt32()) return false;
807         if(version >= 1) {
808                 command_reg = state_fio->FgetUint8();
809                 color_reg = state_fio->FgetUint8();
810                 mask_reg = state_fio->FgetUint8();
811                 cmp_status_reg = state_fio->FgetUint8();
812                 for(i = 0; i < 8; i++)  cmp_color_data[i] = state_fio->FgetUint8();
813                 bank_disable_reg = state_fio->FgetUint8();
814                 for(i = 0; i < 4; i++)  tile_reg[i] = state_fio->FgetUint8();
815                 multi_page = state_fio->FgetUint8();
816
817                 line_addr_offset.d = state_fio->FgetUint32_BE();
818                 line_pattern.d = 0;
819                 line_xbegin.d = 0;
820                 line_ybegin.d = 0;
821                 line_xend.d = 0;
822                 line_yend.d = 0;
823            
824                 line_pattern.w.l = state_fio->FgetUint16_BE();
825                 line_xbegin.w.l = state_fio->FgetUint16_BE();
826                 line_ybegin.w.l = state_fio->FgetUint16_BE();
827                 line_xend.w.l = state_fio->FgetUint16_BE();
828                 line_yend.w.l = state_fio->FgetUint16_BE();
829
830                 busy_flag = state_fio->FgetBool();
831                 eventid_busy = state_fio->FgetInt32_BE();
832                 
833                 total_bytes = state_fio->FgetUint32_BE();
834                 oldaddr = state_fio->FgetUint32_BE();
835                 alu_addr = state_fio->FgetUint32_BE();
836
837                 planes = state_fio->FgetUint32_BE();
838                 is_400line = state_fio->FgetBool();
839                 screen_width = state_fio->FgetUint32_BE();
840                 screen_height = state_fio->FgetUint32_BE();
841
842                 line_style.d = 0;
843                 line_style.w.l = state_fio->FgetUint16_BE();
844         }
845         return true;
846 }