OSDN Git Service

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