OSDN Git Service

[VM][General][WIP] Apply new (Upstream 2016-02-21) APIs to VMs.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / display.cpp
1 /*
2  * Common source code project -> FM-7 -> Display
3  * (C) 2015 K.Ohta <whatisthis.sowhat _at_ gmail.com>
4  * History:
5  *  Feb 10, 2015 : Initial.
6  */
7
8 #include "../../fileio.h"
9 #include "fm7_display.h"
10 #if defined(_FM77AV_VARIANTS)
11 # include "mb61vh010.h"
12 #endif
13
14 DISPLAY::DISPLAY(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
15 {
16         p_vm = parent_vm;
17         p_emu = parent_emu;
18 }
19
20 DISPLAY::~DISPLAY()
21 {
22
23 }
24
25 void DISPLAY::reset_cpuonly()
26 {
27         int i;
28         double usec;
29         keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
30         mainio->write_signal(SIG_FM7_SUB_HALT, 0x00, 0xff);
31         sub_busy = true;
32         
33         multimode_accessmask = 0;
34         multimode_dispmask = 0;
35         firq_mask = false;
36         //cancel_request = false;
37         switch(config.cpu_type){
38                 case 0:
39                         clock_fast = true;
40                         break;
41                 case 1:
42                         clock_fast = false;
43                         break;
44         }
45         enter_display();
46    
47         offset_point = 0;
48         for(i = 0; i < 2; i++) {
49                 offset_changed[i] = true;
50                 tmp_offset_point[i].d = 0;
51         }
52
53         vram_wrote_shadow = false;
54 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
55         for(i = 0; i < 400; i++) vram_wrote_table[i] = true;
56         for(i = 0; i < 400; i++) vram_draw_table[i] = true;
57         
58         vsync = true;
59         vblank = true;
60         hblank = false;
61         vblank_count = 0;
62         displine = 0;
63         
64         if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
65         if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
66         if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
67         if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
68         hblank_event_id = -1;
69         hdisp_event_id = -1;
70         vsync_event_id = -1;
71         vstart_event_id = -1;
72         if(display_mode == DISPLAY_MODE_8_400L) {
73                 usec = 0.33 * 1000.0; 
74         } else {
75                 usec = 0.51 * 1000.0;
76         }
77         //usec = 16.0;
78         register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
79         mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
80         mainio->write_signal(SIG_DISPLAY_VSYNC, 0xff, 0xff);
81 #endif
82 #if defined(_FM77AV_VARIANTS)
83         offset_77av = false;
84         offset_point_bank1 = 0;
85         offset_point_bak   = 0;
86         offset_point_bank1_bak = 0;
87         display_page = 0;
88         active_page = 0;
89         
90         subcpu_resetreq = false;
91         subrom_bank_using = subrom_bank;
92    
93         nmi_enable = true;
94         use_alu = false;
95
96 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
97         vram_bank = 0;
98         vram_display_block = 0;
99         vram_active_block = 0;
100         
101 #  if defined(_FM77AV40EX) || defined(_FM77AV40SX)
102         window_low = 0;
103         window_high = 0;
104         window_xbegin = 0;
105         window_xend = 0;
106         window_opened = false;
107 #  endif        
108 # endif
109         
110         alu->reset();
111 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
112         alu->write_signal(SIG_ALU_X_WIDTH, ((mode320 || mode256k) && !(mode400line)) ? 40 : 80, 0xffff);
113         alu->write_signal(SIG_ALU_Y_HEIGHT, (mode400line) ? 400: 200, 0xffff);
114         alu->write_signal(SIG_ALU_400LINE, (mode400line) ? 0xffffffff : 0, 0xffffffff);
115 # else
116         alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
117         alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
118         alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
119 # endif
120         alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
121         alu->write_signal(SIG_ALU_PLANES, 3, 3);
122         
123 #endif
124         for(i = 0; i < 8; i++) set_dpalette(i, i);
125         do_firq(!firq_mask && key_firq_req);
126
127 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
128         kanjisub = false;
129         kanjiaddr.d = 0x00000000;
130 # if defined(_FM77L4)
131         mode400line = false;
132         stat_400linecard = false;
133 # endif 
134 #endif
135         //if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
136         //register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
137         vram_wrote = true;
138         clr_count = 0;
139         frame_skip_count = 3;
140 }
141
142
143 void DISPLAY::reset()
144 {
145         int i;
146         
147         memset(io_w_latch, 0xff, sizeof(io_w_latch));
148         halt_flag = false;
149         vram_accessflag = true;
150         display_mode = DISPLAY_MODE_8_200L;
151         crt_flag = true;
152         screen_update_flag = true;
153         crt_flag_bak = true;
154         
155         cancel_request = false;
156 #if defined(_FM77AV_VARIANTS)
157         mode320 = false;
158         apalette_index.d = 0;
159         for(i = 0; i < 4096; i++) {
160                 analog_palette_r[i] = i & 0x0f0;
161                 analog_palette_g[i] = i & 0xf00;
162                 analog_palette_b[i] = i & 0x00f;
163                 calc_apalette(i);
164         }
165         subrom_bank = 0;
166         cgrom_bank = 0;
167 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
168         monitor_ram = false;
169         ram_protect = true;
170         
171         mode400line = false;
172         mode256k = false;
173 # endif
174 #elif defined(_FM77L4)
175         mode400line = false;
176 #endif
177         emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
178         is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
179         key_firq_req = false;   //firq_mask = true;
180         firq_mask = false;
181         reset_cpuonly();
182         
183 #if defined(_FM77AV_VARIANTS)
184         power_on_reset = false;
185         for(i = 0; i < 411; i++) vram_wrote_table[i] = false;
186         nmi_enable = true;
187 #else
188 # if defined(_FM8)
189         for(i = 0; i < 8; i++) set_dpalette(i, i);
190         multimode_accessmask = 0x00;
191         multimode_dispmask = 0x00;
192 # endif
193 #endif  
194         //enter_display();
195         
196         if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
197         register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
198         subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
199         subcpu->reset();
200 }
201
202 void DISPLAY::update_config()
203 {
204         vram_wrote = true;
205         switch(config.cpu_type) {
206                 case 0:
207                         clock_fast = true;
208                         break;
209                 case 1:
210                         clock_fast = false;
211                         break;
212         }
213 #if !defined(_FM8)
214         is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
215 #endif  
216         enter_display();
217 }
218
219 /*
220  * Vram accessing functions moved to vram.cpp .
221  */
222
223 void DISPLAY::do_irq(bool flag)
224 {
225         subcpu->write_signal(SIG_CPU_IRQ, flag ? 1: 0, 1);
226 }
227
228 void DISPLAY::do_firq(bool flag)
229 {
230         subcpu->write_signal(SIG_CPU_FIRQ, flag ? 1: 0, 1);
231 }
232
233 void DISPLAY::do_nmi(bool flag)
234 {
235 #if defined(_FM77AV_VARIANTS)
236         if(!nmi_enable) flag = false;
237 #endif
238         subcpu->write_signal(SIG_CPU_NMI, flag ? 1 : 0, 1);
239 }
240
241 void DISPLAY::set_multimode(uint8 val)
242 {
243 #if !defined(_FM8)      
244         multimode_accessmask = val & 0x07;
245         multimode_dispmask = (val & 0x70) >> 4;
246         vram_wrote = true;
247 # if defined(_FM77AV_VARIANTS)
248         alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
249 # endif
250 #endif  
251 }
252
253 uint8 DISPLAY::get_multimode(void)
254 {
255 #if defined(_FM8)
256         return 0xff;
257 #else
258         uint8 val;
259         val = multimode_accessmask & 0x07;
260         val |= ((multimode_dispmask << 4) & 0x70);
261         val |= 0x80;
262         return val;
263 #endif  
264 }
265
266 uint8 DISPLAY::get_cpuaccessmask(void)
267 {
268         return multimode_accessmask & 0x07;
269 }
270
271 void DISPLAY::set_dpalette(uint32 addr, uint8 val)
272 {
273         scrntype r, g, b;
274         addr &= 7;
275         dpalette_data[addr] = val | 0xf8; //0b11111000;
276         vram_wrote = true;
277         b =  ((val & 0x01) != 0x00)? 255 : 0x00;
278         r =  ((val & 0x02) != 0x00)? 255 : 0x00;
279         g =  ((val & 0x04) != 0x00)? 255 : 0x00;
280         
281         dpalette_pixel[addr] = RGB_COLOR(r, g, b);
282 }
283
284 uint8 DISPLAY::get_dpalette(uint32 addr)
285 {
286 #if defined(_FM8)
287         return 0xff;
288 #else
289         uint8 data;
290         addr = addr & 7;
291         
292         data = dpalette_data[addr];
293         return data;
294 #endif
295 }
296
297 void DISPLAY::halt_subcpu(void)
298 {
299         subcpu->write_signal(SIG_CPU_BUSREQ, 0x01, 0x01);
300 }
301
302 void DISPLAY::go_subcpu(void)
303 {
304         subcpu->write_signal(SIG_CPU_BUSREQ, 0x00, 0x01);
305 }
306
307 void DISPLAY::enter_display(void)
308 {
309         uint32 subclock;
310         if(clock_fast) {
311                 subclock = SUBCLOCK_NORMAL;
312         } else {
313                 subclock = SUBCLOCK_SLOW;
314         }
315         if(!is_cyclesteal && vram_accessflag) {
316                 subclock = subclock / 3;
317         }
318         if(prev_clock != subclock) p_vm->set_cpu_clock(subcpu, subclock);
319         prev_clock = subclock;
320 }
321
322 void DISPLAY::leave_display(void)
323 {
324 }
325
326 void DISPLAY::halt_subsystem(void)
327 {
328         halt_flag = false;
329         halt_subcpu();
330 }
331
332 void DISPLAY::restart_subsystem(void)
333 {
334         halt_flag = false;
335 #if defined(_FM77AV_VARIANTS)
336         if(subcpu_resetreq) {
337                 firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
338                 reset_cpuonly();
339                 power_on_reset = true;
340                 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
341                 subcpu->reset();
342                 do_firq(!firq_mask && key_firq_req);
343         }
344 #endif
345         go_subcpu();
346 }
347
348 //SUB:D408:R
349 void DISPLAY::set_crtflag(void)
350 {
351         crt_flag = true;
352         vram_wrote = true;
353 }
354
355 //SUB:D408:W
356 void DISPLAY::reset_crtflag(void)
357 {
358         crt_flag = false;
359         vram_wrote = true;
360 }
361
362 //SUB:D402:R
363 uint8 DISPLAY::acknowledge_irq(void)
364 {
365         cancel_request = false;
366         do_irq(false);
367         return 0xff;
368 }
369
370 //SUB:D403:R
371 uint8 DISPLAY::beep(void)
372 {
373         mainio->write_signal(FM7_MAINIO_BEEP, 0x01, 0x01);
374         return 0xff; // True?
375 }
376
377
378 // SUB:D404 : R 
379 uint8 DISPLAY::attention_irq(void)
380 {
381         mainio->write_signal(FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
382         return 0xff;
383 }
384
385 // SUB:D405:W
386 void DISPLAY::set_cyclesteal(uint8 val)
387 {
388 #if !defined(_FM8)
389         vram_wrote = true;
390         val &= 0x01;
391 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)       
392         if(val == 0) {
393                 is_cyclesteal = true;
394         } else {
395                 is_cyclesteal = false;
396         }
397 # endif 
398         enter_display();
399 #endif
400 }
401
402 //SUB:D409:R
403 uint8 DISPLAY::set_vramaccess(void)
404 {
405         vram_accessflag = true;
406         return 0xff;
407 }
408
409 //SUB:D409:W
410 void DISPLAY::reset_vramaccess(void)
411 {
412         vram_accessflag = false;
413 }
414
415 //SUB:D40A:R
416 uint8 DISPLAY::reset_subbusy(void)
417 {
418         sub_busy = false;
419         return 0xff;
420 }
421
422 //SUB:D40A:W
423 void DISPLAY::set_subbusy(void)
424 {
425         sub_busy = true;
426 }
427
428
429 #if defined(_FM77AV_VARIANTS)
430 // D410
431 void DISPLAY::alu_write_cmdreg(uint32 val)
432 {
433         alu->write_data8(ALU_CMDREG, val);
434         if((val & 0x80) != 0) {
435                 use_alu = true;
436         } else {
437                 use_alu = false;
438         }
439 }
440
441 // D411
442 void DISPLAY::alu_write_logical_color(uint8 val)
443 {
444         uint32 data = (uint32)val;
445         alu->write_data8(ALU_LOGICAL_COLOR, data);
446 }
447
448 // D412
449 void DISPLAY::alu_write_mask_reg(uint8 val)
450 {
451         uint32 data = (uint32)val;
452         alu->write_data8(ALU_WRITE_MASKREG, data);
453 }
454
455 // D413 - D41A
456 void DISPLAY::alu_write_cmpdata_reg(int addr, uint8 val)
457 {
458         uint32 data = (uint32)val;
459         addr = addr & 7;
460         alu->write_data8(ALU_CMPDATA_REG + addr, data);
461 }
462
463 // D41B
464 void DISPLAY::alu_write_disable_reg(uint8 val)
465 {
466         uint32 data = (uint32)val;
467         alu->write_data8(ALU_BANK_DISABLE, data);
468 }
469
470 // D41C - D41F
471 void DISPLAY::alu_write_tilepaint_data(uint32 addr, uint8 val)
472 {
473         uint32 data = (uint32)val;
474         switch(addr & 3) {
475                 case 0: // $D41C
476                         alu->write_data8(ALU_TILEPAINT_B, data);
477                         break;
478                 case 1: // $D41D
479                         alu->write_data8(ALU_TILEPAINT_R, data);
480                         break;
481                 case 2: // $D41E
482                         alu->write_data8(ALU_TILEPAINT_G, data);
483                         break;
484                 case 3: // xxxx
485                         //alu->write_data8(ALU_TILEPAINT_L, 0xff);
486                         break;
487         }
488 }
489
490 // D420
491 void DISPLAY::alu_write_offsetreg_hi(uint8 val)
492 {
493         alu->write_data8(ALU_OFFSET_REG_HIGH, val & 0x7f);
494 }
495  
496 // D421
497 void DISPLAY::alu_write_offsetreg_lo(uint8 val)
498 {
499         alu->write_data8(ALU_OFFSET_REG_LO, val);
500 }
501
502 // D422
503 void DISPLAY::alu_write_linepattern_hi(uint8 val)
504 {
505         alu->write_data8(ALU_LINEPATTERN_REG_HIGH, val);
506 }
507
508 // D423
509 void DISPLAY::alu_write_linepattern_lo(uint8 val)
510 {
511         alu->write_data8(ALU_LINEPATTERN_REG_LO, val);
512 }
513
514 // D424-D42B
515 void DISPLAY::alu_write_line_position(int addr, uint8 val)
516 {
517         uint32 data = (uint32)val;
518         switch(addr) {
519                 case 0:  
520                         alu->write_data8(ALU_LINEPOS_START_X_HIGH, data & 0x03); 
521                         break;
522                 case 1:  
523                         alu->write_data8(ALU_LINEPOS_START_X_LOW, data); 
524                         break;
525                 case 2:  
526                         alu->write_data8(ALU_LINEPOS_START_Y_HIGH, data & 0x01); 
527                         break;
528                 case 3:  
529                         alu->write_data8(ALU_LINEPOS_START_Y_LOW, data); 
530                         break;
531                 case 4:  
532                         alu->write_data8(ALU_LINEPOS_END_X_HIGH, data & 0x03); 
533                         break;
534                 case 5:  
535                         alu->write_data8(ALU_LINEPOS_END_X_LOW, data); 
536                         break;
537                 case 6:  
538                         alu->write_data8(ALU_LINEPOS_END_Y_HIGH, data & 0x01); 
539                         break;
540                 case 7:  
541                         alu->write_data8(ALU_LINEPOS_END_Y_LOW, data);
542                         break;
543         }
544 }
545
546 //SUB:D430:R
547 uint8 DISPLAY::get_miscreg(void)
548 {
549         uint8 ret;
550
551         ret = 0x6a;
552         if(!hblank) ret |= 0x80;
553         if(vsync) ret |= 0x04;
554         if(alu->read_signal(SIG_ALU_BUSYSTAT) == 0) ret |= 0x10;
555         if(power_on_reset) ret |= 0x01;
556         return ret;
557 }
558
559 //SUB:D430:W
560 void DISPLAY::set_miscreg(uint8 val)
561 {
562         int old_display_page = display_page;
563
564         nmi_enable = ((val & 0x80) == 0) ? true : false;
565         if(!nmi_enable) do_nmi(false);
566
567         if((val & 0x40) == 0) {
568                 display_page = 0;
569         } else {
570                 display_page = 1;
571         }
572         if(display_page != old_display_page) {
573                         vram_wrote = true;
574         }
575         active_page = ((val & 0x20) == 0) ? 0 : 1;
576         if((val & 0x04) == 0) {
577                 offset_77av = false;
578         } else {
579                 offset_77av = true;
580         }
581         cgrom_bank = val & 0x03;
582 }
583
584 // Main: FD13
585 void DISPLAY::set_monitor_bank(uint8 var)
586 {
587 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
588         if((var & 0x04) != 0){
589                 monitor_ram = true;
590         } else {
591                 monitor_ram = false;
592         }
593 # endif
594         subrom_bank = var & 0x03;
595         vram_wrote = true;
596         if(!halt_flag) {
597                 subcpu_resetreq = false;
598                 power_on_reset = true;
599                 firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
600                 reset_cpuonly();
601                 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
602                 subcpu->reset();
603                 do_firq(!firq_mask && key_firq_req);
604         } else {
605                 subcpu_resetreq = true;
606         }
607 }
608
609
610 // FD30
611 void DISPLAY::set_apalette_index_hi(uint8 val)
612 {
613         apalette_index.b.h = val & 0x0f;
614 }
615
616 // FD31
617 void DISPLAY::set_apalette_index_lo(uint8 val)
618 {
619         apalette_index.b.l = val;
620 }
621
622 void DISPLAY::calc_apalette(uint16 idx)
623 {
624         uint8 r, g, b;
625         idx = idx & 4095;
626         g = analog_palette_g[idx];
627         r = analog_palette_r[idx];
628         b = analog_palette_b[idx];
629         analog_palette_pixel[idx] = RGB_COLOR(r, g, b);
630 }
631
632 // FD32
633 void DISPLAY::set_apalette_b(uint8 val)
634 {
635         uint16 index;
636         uint8 tmp;
637         index = apalette_index.w.l;
638         tmp = (val & 0x0f) << 4;
639         if(analog_palette_b[index] != tmp) {
640                 analog_palette_b[index] = tmp;
641                 calc_apalette(index);
642                 vram_wrote = true;
643         }
644 }
645
646 // FD33
647 void DISPLAY::set_apalette_r(uint8 val)
648 {
649         uint16 index;
650         uint8 tmp;
651         index = apalette_index.w.l;
652         tmp = (val & 0x0f) << 4;
653         if(analog_palette_r[index] != tmp) {
654                 analog_palette_r[index] = tmp;
655                 calc_apalette(index);
656                 vram_wrote = true;
657         }
658 }
659
660 // FD34
661 void DISPLAY::set_apalette_g(uint8 val)
662 {
663         uint16 index;
664         uint8 tmp;
665         index = apalette_index.w.l;
666         tmp = (val & 0x0f) << 4;
667         if(analog_palette_g[index] != tmp) {
668                 analog_palette_g[index] = tmp;
669                 calc_apalette(index);
670                 vram_wrote = true;
671         }
672 }
673
674 #endif // _FM77AV_VARIANTS
675
676
677 // Timing values from XM7 . Thanks Ryu.
678 void DISPLAY::event_callback(int event_id, int err)
679 {
680         double usec;
681         bool f;
682         switch(event_id) {
683                 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
684 #if defined(_FM77AV_VARIANTS)
685                         if(nmi_enable) {
686                                 do_nmi(true);
687                         } else {
688                                 //do_nmi(false);
689                         }
690 #else
691                         do_nmi(true);
692 #endif
693                         break;
694                 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
695                         do_nmi(false);
696                         break;
697 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
698                 case EVENT_FM7SUB_HDISP:
699                         hblank = false;
700                         f = false;
701                         mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x02, 0xff);
702                         //if(displine == 0) enter_display();
703                         if(display_mode == DISPLAY_MODE_8_400L) {
704                                 usec = 30.0;
705                                 if(displine < 400) f = true;
706                         } else {
707                                 usec = 39.5;
708                                 if(displine < 200) f = true;
709                         }
710                         if(f) {
711                                 register_event(this, EVENT_FM7SUB_HBLANK, usec, false, &hblank_event_id); // NEXT CYCLE_
712                                 vsync = false;
713                                 vblank = false;
714                                 enter_display();
715                         }
716                         f = false;
717                         break;
718                 case EVENT_FM7SUB_HBLANK:
719                         hblank = true;
720                         mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
721                         f = false;
722                         if(display_mode == DISPLAY_MODE_8_400L) {
723                                 if(displine < 400) f = true;
724                         } else {
725                                 if(displine < 200) f = true;
726                         }
727                         if(f) {
728                                 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
729                                         if((display_mode == DISPLAY_MODE_4096) || (display_mode == DISPLAY_MODE_256k)){
730 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
731                                                 int planes = 2;
732 # elif defined(_FM77AV40)
733                                                 int planes = 1;
734 # else
735                                                 int planes = 1;
736 #endif
737                                                 if(vram_wrote_table[displine] || vram_wrote) {
738                                                         uint32 baseaddr1 = ((displine) * 40) & 0x1fff;
739                                                         uint32 baseaddr2 = baseaddr1 + 0xc000;
740                                                         vram_wrote_table[displine] = false;
741                                                         for(int i = 0; i < planes; i++) {
742                                                                 for(int j = 0; j < 6; j++) {
743                                                                         memcpy(&gvram_shadow[j * 0x2000 + baseaddr1],
744                                                                                    &gvram[j * 0x2000 + baseaddr1], 40);
745                                                                         memcpy(&gvram_shadow[j * 0x2000 + baseaddr2],
746                                                                                    &gvram[j * 0x2000 + baseaddr2], 40);
747                                                                 }
748                                                                 baseaddr1 += 0x18000;
749                                                                 baseaddr2 += 0x18000;
750                                                         }
751 # if defined(_FM77AV40)
752                                                         for(int j = 0; j < 6; j++) {
753                                                                 memcpy(&gvram_shadow[j * 0x2000 + baseaddr1],
754                                                                            &gvram[j * 0x2000 + baseaddr1], 40);
755                                                         }
756 # endif                                                 
757                                                         //screen_update_flag = true;
758                                                         vram_draw_table[displine] = true;
759                                                 }
760                                         } else if(display_mode == DISPLAY_MODE_8_400L) {
761 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
762                                                 int planes = 2;
763 # elif defined(_FM77AV40)
764                                                 int planes = 1;
765 # else
766                                                 int planes = 0;
767 #endif
768                                                 if(vram_wrote_table[displine] || vram_wrote) {
769                                                         uint32 baseaddr1 = ((displine) * 80) & 0x7fff;
770                                                         vram_wrote_table[displine] = false;
771                                                         for(int i = 0; i < planes; i++) {
772                                                                 for(int j = 0; j < 3; j++) {
773                                                                         memcpy(&gvram_shadow[j * 0x8000 + baseaddr1],
774                                                                                    &gvram[j * 0x8000 + baseaddr1], 80);
775                                                                 }
776                                                                 baseaddr1 += 0x18000;
777                                                         }
778                                                         
779 # if defined(_FM77AV40)
780                                                         for(int j = 0; j < 3; j++) {
781                                                                 memcpy(&gvram_shadow[j * 0x4000 + baseaddr1],
782                                                                            &gvram[j * 0x4000 + baseaddr1], 80);
783                                                         }
784 # endif                                                 
785                                                         //screen_update_flag = true;
786                                                         vram_draw_table[displine] = true;
787                                                 }
788                                         } else {
789 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
790                                                 int planes = 2;
791 # elif defined(_FM77AV40)
792                                                 int planes = 1;
793 # else
794                                                 int planes = 1;
795 #endif
796                                                 if(vram_wrote_table[displine] || vram_wrote) {
797                                                         uint32  baseaddr1 = ((displine) * 80) & 0x3fff;
798                                                         uint32  baseaddr2 = baseaddr1 + 0xc000;
799                                                         for(int i = 0; i < planes; i++) {
800                                                         vram_wrote_table[displine] = false;
801                                                                 for(int j = 0; j < 3; j++) {
802                                                                         memcpy(&gvram_shadow[j * 0x4000 + baseaddr1],
803                                                                                    &gvram[j * 0x4000 + baseaddr1], 80);
804                                                                         memcpy(&gvram_shadow[j * 0x4000 + baseaddr2],
805                                                                                    &gvram[j * 0x4000 + baseaddr2], 80);
806                                                                 }
807                                                                 baseaddr1 += 0x18000;
808                                                                 baseaddr2 += 0x18000;
809                                                         }
810 # if defined(_FM77AV40)
811                                                         for(int j = 0; j < 3; j++) {
812                                                                 memcpy(&gvram_shadow[j * 0x4000 + baseaddr1],
813                                                                    &gvram[j * 0x4000 + baseaddr1], 80);
814                                                         }
815 # endif
816                                                         //screen_update_flag = true;
817                                                         vram_draw_table[displine] = true;
818                                                 }
819                                         }
820                                 }
821                                 if(display_mode == DISPLAY_MODE_8_400L) {
822                                         usec = 11.0;
823                                 } else {
824                                         usec = 24.0;
825                                 }
826                                 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
827                                 
828                         }
829                         //vram_wrote_shadow = true;
830                         displine++;
831                         break;
832                 case EVENT_FM7SUB_VSTART: // Call first.
833                         vblank = true;
834                         vsync = false;
835                         hblank = false;
836                         displine = 0;
837                         // Parameter from XM7/VM/display.c , thanks, Ryu.
838                         mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
839                         mainio->write_signal(SIG_DISPLAY_VSYNC, 0x00, 0xff);
840                         if(vblank_count != 0) {
841                                 if(display_mode == DISPLAY_MODE_8_400L) {
842                                         usec = (0.98 + 16.4) * 1000.0;
843                                 } else {
844                                         usec = (1.91 + 12.7) * 1000.0;
845                                 }
846                                 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
847
848                                 if(display_mode == DISPLAY_MODE_8_400L) {
849                                         usec = 930.0; // 939.0
850                                 } else {
851                                         usec = 1840.0; // 1846.5
852                                 }
853                                 //offset_point_bank1_bak = offset_point_bank1;
854                                 //offset_point_bak = offset_point;
855                                 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
856                                 vblank_count = 0;
857                         } else {
858                                 if(display_mode == DISPLAY_MODE_8_400L) {
859                                         usec = 0.34 * 1000.0;
860                                 } else {
861                                         usec = 1.52 * 1000.0;
862                                 }
863                                 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
864                                 vblank_count++;
865                         }
866                         if(vram_wrote && ((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0)) {
867                                 //for(int i = 0; i < 411; i++) vram_wrote_table[i] = false;
868                                 memcpy(gvram_shadow, gvram, sizeof(gvram_shadow));
869                                 //vram_wrote_shadow = true;
870                                 //for(int i = 0; i < 411; i++) vram_draw_table[i] = true;
871                         } else if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
872                                 if((display_mode == DISPLAY_MODE_4096) || (display_mode == DISPLAY_MODE_256k)){
873                                         int planes;
874                                         bool ff;
875 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
876                                         planes = 24;
877 # elif defined(_FM77AV40)
878                                         planes = 18;
879 # else
880                                         planes = 12;
881 # endif
882                                         ff = vram_wrote;
883                                         if(!ff) {
884                                                 for(int j = 200; j < 206; j++) {
885                                                         if(vram_wrote_table[j]) {
886                                                                 ff = true;
887                                                         }
888                                                         vram_wrote_table[j] = false;
889                                                 }
890                                         }
891                                         if(ff) {
892                                                 for(int j = 200; j < 205; j++) {
893                                                         vram_draw_table[(((j * 40) + offset_point_bak) & 0x1fff) / 40] = true;
894                                                         vram_draw_table[(((j * 40) + offset_point_bank1_bak) & 0x1fff) / 40] = true;
895                                                 }
896                                                 for(int i = 0; i < planes; i++) memcpy(&gvram_shadow[i * 0x2000 + 200 * 40],
897                                                                                         &gvram[i * 0x2000 + 200 * 40], 0x2000 - 200 * 40);
898                                         }
899                                 } else if(display_mode == DISPLAY_MODE_8_400L) {
900                                         int planes;
901                                         bool ff;
902 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
903                                         planes = 6;
904 # elif defined(_FM77AV40)
905                                         planes = 3;
906 # else
907                                         planes = 0;
908 # endif
909                                         ff = vram_wrote;
910                                         if(!ff) {
911                                                 for(int j = 400; j < 411; j++) {
912                                                         if(vram_wrote_table[j]) {
913                                                                 ff = true;
914                                                         }
915                                                 vram_wrote_table[j] = false;
916                                                 }
917                                         }
918                                         if(ff) {
919                                                 for(int j = 400; j < 410; j++) {
920                                                         vram_draw_table[(((j * 80) + offset_point_bak) & 0x7fff) / 80] = true;
921                                                         vram_draw_table[(((j * 80) + offset_point_bank1_bak) & 0x7fff) / 80] = true;
922                                                 }
923                                                 for(int i = 0; i < planes; i++) memcpy(&gvram_shadow[i * 0x8000 + 400 * 80],
924                                                                                    &gvram[i * 0x8000 + 400 * 80], 0x8000 - 400 * 80);
925                                                 //screen_update_flag = true;
926                                         }
927                                 } else {
928                                         int planes;
929                                         bool ff;
930 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
931                                         planes = 12;
932 # elif defined(_FM77AV40)
933                                         planes = 9;
934 # else
935                                         planes = 6;
936 # endif
937                                         ff = vram_wrote;
938                                         if(!ff) {
939                                                 for(int j = 200; j < 206; j++) {
940                                                         if(vram_wrote_table[j]) {
941                                                                 ff = true;
942                                                         }
943                                                         vram_wrote_table[j] = false;
944                                                 }
945                                         }
946                                         if(ff) {
947                                                 for(int j = 200; j < 205; j++) {
948                                                         vram_draw_table[(((j * 80) + offset_point_bak) & 0x3fff) / 80] = true;
949                                                         vram_draw_table[(((j * 80) + offset_point_bank1_bak) & 0x3fff) / 80] = true;
950                                                 }
951                                            for(int i = 0; i < planes; i++) memcpy(&gvram_shadow[i * 0x4000 + 200 * 80],
952                                                                                   &gvram[i * 0x4000 + 200 * 80], 0x4000 - 200 * 80);
953                                                 //screen_update_flag = true;
954                                         }
955                                 }
956                         }
957                         if(vram_wrote) {
958                                 vram_wrote_shadow = true;
959                                 screen_update_flag = true;
960                         } else {
961                                 bool fy = false;
962                                 if(display_mode == DISPLAY_MODE_8_400L) {
963                                         for(int yy = 0; yy < 411; yy++) {
964                                                 if(vram_draw_table[yy]) fy = true;
965                                                 vram_draw_table[yy] = false;
966                                         }
967                                 } else {
968                                         for(int yy = 0; yy < 205; yy++) {
969                                                 if(vram_draw_table[yy]) fy = true;
970                                                 vram_draw_table[yy] = false;
971                                         }
972                                 }
973                                 vram_wrote_shadow |= fy;
974                                 screen_update_flag |= fy;
975                         }
976                         vram_wrote = false;
977                         break;
978         case EVENT_FM7SUB_VSYNC:
979                 vblank = true;
980                 hblank = false;
981                 vsync = true;
982                 displine = 0;
983                 if(display_mode == DISPLAY_MODE_8_400L) {
984                         usec = 0.33 * 1000.0; 
985                 } else {
986                         usec = 0.51 * 1000.0;
987                 }
988                 offset_point_bank1_bak = offset_point_bank1;
989                 offset_point_bak = offset_point;
990                 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x01, 0xff);
991                 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
992                 break;
993 #endif                  
994         case EVENT_FM7SUB_CLR_BUSY:
995                 set_subbusy();
996                 break;
997         case EVENT_FM7SUB_CLR_CRTFLAG:
998                 reset_crtflag();
999                 break;
1000         }
1001 }
1002
1003 void DISPLAY::event_frame()
1004 {
1005 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1006         if(vram_wrote) {
1007                 screen_update_flag = true;
1008                 vram_wrote_shadow = true;
1009         }
1010         vram_wrote = false;
1011         enter_display();
1012 #endif  
1013 }
1014
1015 void DISPLAY::event_vline(int v, int clock)
1016 {
1017 }
1018
1019
1020 uint32 DISPLAY::read_signal(int id)
1021 {
1022         uint32 retval = 0;
1023         switch(id) {
1024                 case SIG_FM7_SUB_HALT:
1025                 case SIG_DISPLAY_HALT:
1026                         retval = (halt_flag) ? 0xffffffff : 0;
1027                         break;
1028                 case SIG_DISPLAY_BUSY:
1029                         retval =  (sub_busy) ? 0x80 : 0;
1030                         break;
1031                 case SIG_DISPLAY_MULTIPAGE:
1032                         retval =  multimode_accessmask;
1033                         break;
1034                 case SIG_DISPLAY_PLANES:
1035                         retval = 3;
1036                         break;
1037 #if defined(_FM77AV_VARIANTS)
1038                 case SIG_DISPLAY_VSYNC:
1039                         retval = (vsync) ? 0x01 : 0x00;
1040                         break;
1041                 case SIG_DISPLAY_DISPLAY:
1042                         retval = (!hblank) ? 0x02: 0x00;
1043                         break;
1044                 case SIG_FM7_SUB_BANK: // Main: FD13
1045                         retval = subrom_bank & 0x03;
1046 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1047                         if(monitor_ram) retval |= 0x04;
1048 #endif
1049                         break;
1050 #endif                  
1051 #if defined(_FM77AV_VARIANTS)
1052                 case SIG_DISPLAY_MODE320:
1053                         retval = (mode320) ? 0x40: 0x00;
1054                         break;
1055 #endif
1056                 case SIG_DISPLAY_Y_HEIGHT:
1057 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1058                         retval = (mode400line) ? 400 : 200;
1059 #else
1060                         retval = 200;
1061 #endif            
1062                         break;
1063                 case SIG_DISPLAY_X_WIDTH:
1064 #if defined(_FM77AV_VARIANTS)
1065 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1066                         retval = (mode320 || mode256k) ? 40 : 80;
1067 # else
1068                         retval = (mode320) ? 40 : 80;
1069 # endif    
1070 #else
1071                         retval = 640;
1072 #endif            
1073                         break;
1074                 default:
1075                         break;
1076         }
1077         return retval;
1078 }
1079
1080 void DISPLAY::write_signal(int id, uint32 data, uint32 mask)
1081 {
1082         bool flag = ((data & mask) != 0);
1083         int y;
1084         switch(id) {
1085                 case SIG_FM7_SUB_HALT:
1086                         if(flag) {
1087                                 sub_busy = true;
1088                         }
1089                         halt_flag = flag;
1090                         //mainio->write_signal(SIG_FM7_SUB_HALT, data, mask);
1091                         break;
1092                 case SIG_DISPLAY_HALT:
1093                         if(flag) {
1094                                 halt_subsystem();
1095                         } else {
1096                                 restart_subsystem();
1097                         }
1098                         break;
1099                 case SIG_FM7_SUB_CANCEL:
1100                         if(flag) {
1101                                 cancel_request = true;
1102                                 do_irq(true);
1103                         }
1104                         break;
1105                 case SIG_DISPLAY_CLOCK:
1106                         clock_fast = flag;
1107                         enter_display();
1108                         break;
1109 #if defined(_FM77AV_VARIANTS)
1110                 case SIG_FM7_SUB_BANK: // Main: FD13
1111                         set_monitor_bank(data & 0xff);
1112                         break;
1113 #endif                  
1114                 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1115 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1116                         {
1117                                 int oldmode = display_mode;
1118                                 int mode;
1119                                 kanjisub = ((data & 0x20) == 0) ? true : false;
1120                                 mode256k = ((data & 0x10) != 0) ? true : false;
1121                                 mode400line = ((data & 0x08) != 0) ? false : true;
1122                                 ram_protect = ((data & 0x04) != 0) ? false : true;
1123                                 if(mode400line) {
1124                                         display_mode = DISPLAY_MODE_8_400L;
1125                                 } else if(mode256k) {
1126                                         display_mode = DISPLAY_MODE_256k;
1127                                 } else {
1128                                         display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1129                                 }
1130                                 if(oldmode != display_mode) {
1131                                         scrntype *pp;
1132                                         if(mode400line) {
1133                                                 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1134                                                 for(y = 0; y < 400; y++) {
1135                                                         pp = emu->get_screen_buffer(y);
1136                                                         if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype));
1137                                                 }
1138                                         } else if(mode320 || mode256k) {
1139                                                 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1140                                                 for(y = 0; y < 200; y++) {
1141                                                         pp = emu->get_screen_buffer(y);
1142                                                         if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype));
1143                                                 }
1144                                         } else {
1145                                                 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1146                                                 for(y = 0; y < 200; y++) {
1147                                                         pp = emu->get_screen_buffer(y);
1148                                                         if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype));
1149                                                 }
1150                                         }
1151                                         vram_wrote = true;
1152                                         alu->write_signal(SIG_ALU_X_WIDTH, ((mode320 || mode256k) && !(mode400line)) ? 40 :  80, 0xffff);
1153                                         alu->write_signal(SIG_ALU_Y_HEIGHT, (mode400line) ? 400 : 200, 0xffff);
1154                                         alu->write_signal(SIG_ALU_400LINE, (mode400line) ? 0xff : 0x00, 0xff);
1155                                         frame_skip_count = 3;
1156                                 }
1157                         }
1158 #elif defined(_FM77_VARIANTS)
1159                         {
1160                                 int oldmode = display_mode;
1161                                 kanjisub = ((data & 0x20) == 0) ? true : false;
1162 # if defined(_FM77L4)                           
1163                                 stat_400linecard = ((data & 0x20) != 0) ? true : false;
1164                                 mode400line = ((data & 0x08) != 0) ? false : true;
1165                                 if(mode400line && stat_400linecard) {
1166                                         display_mode = DISPLAY_MODE_8_400L_TEXT;
1167                                 } else if(stat_400linecard) {
1168                                         display_mode = DISPLAY_MODE_8_200L_TEXT;
1169                                 } else {
1170                                         display_mode = DISPLAY_MODE_8_200L;
1171                                 }
1172 # endif                         
1173                         }                       
1174 #endif
1175                         break;
1176 #if defined(_FM77AV_VARIANTS)
1177                 case SIG_DISPLAY_MODE320: // FD12 bit 6
1178 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1179                         {
1180                                 int oldmode = display_mode;
1181                                 mode320 = flag;
1182                                 if((!mode400line) && (!mode256k)){
1183                                         display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1184                                 }
1185                                 if(oldmode != display_mode) {
1186                                         scrntype *pp;
1187                                         if(mode400line) {
1188                                                 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1189                                                 for(y = 0; y < 400; y++) {
1190                                                         pp = emu->get_screen_buffer(y);
1191                                                         if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype));
1192                                                 }
1193                                         } else if(mode320 || mode256k) {
1194                                                 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1195                                                 for(y = 0; y < 200; y++) {
1196                                                         pp = emu->get_screen_buffer(y);
1197                                                         if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype));
1198                                                 }
1199                                         } else {
1200                                                 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1201                                                 for(y = 0; y < 200; y++) {
1202                                                         pp = emu->get_screen_buffer(y);
1203                                                         if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype));
1204                                                 }
1205                                         }
1206                                         vram_wrote = true;
1207                                         alu->write_signal(SIG_ALU_X_WIDTH, ((mode320 || mode256k) && !(mode400line)) ? 40 :  80, 0xffff);
1208                                         alu->write_signal(SIG_ALU_Y_HEIGHT, (mode400line) ? 400 : 200, 0xffff);
1209                                         alu->write_signal(SIG_ALU_400LINE, (mode400line) ? 0xff : 0x00, 0xff);
1210                                         frame_skip_count = 3;
1211                                 }
1212                         }
1213 # else
1214                         mode320 = flag;
1215                         {
1216                 
1217                                 if(mode320) {
1218                                         emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1219                                         for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype));
1220                                 } else {
1221                                         emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1222                                         for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype));
1223                                 }
1224                         }
1225                         display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1226                         alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 :  80, 0xffff);
1227                         alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1228                         alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
1229                         vram_wrote = true;
1230 # endif
1231 #endif                  
1232                         break;
1233                 case SIG_DISPLAY_MULTIPAGE:
1234                         set_multimode(data);
1235                         break;
1236                 case SIG_FM7_SUB_KEY_MASK:
1237                         if(firq_mask == flag) {
1238                                 do_firq(!flag && key_firq_req);
1239                         }
1240                         firq_mask = !flag;
1241                         break;
1242                 case SIG_FM7_SUB_KEY_FIRQ:
1243                         do_firq(flag & !(firq_mask));
1244                         key_firq_req = flag;
1245                         break;
1246                 case SIG_FM7_SUB_USE_CLR:
1247                         if(flag) {
1248                                 clr_count = data & 0x03;
1249                         } else {
1250                                 clr_count = 0;
1251                         }
1252                         break;
1253                 default:
1254                         break;
1255         }
1256 }
1257    
1258 /*
1259  * Vram accessing functions moved to vram.cpp .
1260  */
1261
1262 uint8 DISPLAY::read_mmio(uint32 addr)
1263 {
1264         uint32 retval = 0xff;
1265         uint32 raddr;   
1266         if(addr < 0xd400) return 0xff;
1267         
1268 #if !defined(_FM77AV_VARIANTS)
1269         raddr = (addr - 0xd400) & 0x000f;
1270 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
1271         raddr = (addr - 0xd400) & 0x003f;
1272 #else // FM77AV40EX || FM77AV40SX
1273         raddr = (addr - 0xd400) & 0x00ff;
1274 #endif
1275         switch(raddr) {
1276                 case 0x00: // Read keyboard
1277                         retval = (keyboard->read_data8(0x00) != 0) ? 0xff : 0x7f;
1278                         break;
1279                 case 0x01: // Read keyboard
1280                         retval = keyboard->read_data8(0x01) & 0xff;
1281                         break;
1282                 case 0x02: // Acknowledge
1283                         acknowledge_irq();
1284                         break;
1285                 case 0x03:
1286                         beep();
1287                         break;
1288                 case 0x04:
1289                         attention_irq();
1290                         break;
1291 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1292      defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
1293                 case 0x06:
1294                         if(!kanjisub) return 0xff;
1295 # if !defined(_FM77_VARIANTS)
1296                         if(kanji_level2) {
1297                                 return (uint8)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1298                         }
1299 # endif
1300                         if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1301                         break;
1302                 case 0x07:
1303                         if(!kanjisub) return 0xff;
1304 # if !defined(_FM77_VARIANTS)
1305                         if(kanji_level2) {
1306                                 return (uint8)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1307                         }
1308 # endif
1309                         if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1310                         break;
1311 #endif
1312                 case 0x08:
1313                         set_crtflag();
1314                         break;
1315                 case 0x09:
1316                         retval = set_vramaccess();
1317                         break;
1318                 case 0x0a:
1319                         reset_subbusy();
1320                         break;
1321                 case 0x0d:
1322                         keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
1323                         break;
1324 #if defined(_FM77AV_VARIANTS)
1325                 // ALU
1326                 case 0x10:
1327                         retval = alu->read_data8(ALU_CMDREG);
1328                         break;
1329                 case 0x11:
1330                         retval = alu->read_data8(ALU_LOGICAL_COLOR);
1331                         break;
1332                 case 0x12:
1333                         retval = alu->read_data8(ALU_WRITE_MASKREG);
1334                         break;
1335                 case 0x13:
1336                         retval = alu->read_data8(ALU_CMP_STATUS_REG);
1337                         break;
1338                 case 0x1b:
1339                         retval = alu->read_data8(ALU_BANK_DISABLE);
1340                         break;
1341 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1342                 case 0x2f: // VRAM BANK
1343                         retval = 0xfc | (vram_bank & 0x03);
1344                         break;
1345 # endif                 
1346                 // MISC
1347                 case 0x30:
1348                         retval = get_miscreg();
1349                         break;
1350                 // KEY ENCODER.
1351                 case 0x31:
1352                         retval = keyboard->read_data8(0x31);
1353                         break;
1354                 case 0x32:
1355                         retval = keyboard->read_data8(0x32);
1356                         break;
1357 #endif                          
1358                 default:
1359                         break;
1360         }
1361         return (uint8)retval;
1362 }
1363
1364 uint32 DISPLAY::read_vram_data8(uint32 addr)
1365 {
1366         uint32 offset;
1367         uint32 page_offset = 0;
1368         uint32 page_mask = 0x3fff;
1369         uint32 color = (addr >> 14) & 0x03;
1370         uint32 pagemod;
1371         
1372 #if defined(_FM77AV_VARIANTS)
1373         if (active_page != 0) {
1374                 offset = offset_point_bank1;
1375         } else {
1376                 offset = offset_point;
1377         }
1378 #else
1379         offset = offset_point;
1380 #endif
1381                 
1382 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1383 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1384                 if(vram_active_block != 0) page_offset = 0x18000;
1385 # endif         
1386                 if(display_mode == DISPLAY_MODE_8_400L) {
1387                         if(addr >= 0x8000) return 0xff;
1388                         color = vram_bank & 0x03;
1389                         if(color > 2) color = 0;
1390                         offset <<= 1;
1391                         pagemod = 0x8000 * color;
1392                         return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
1393                 } else {
1394                         if(mode256k) {
1395 #if defined(_FM77AV40)
1396                                 if(vram_bank < 3) {
1397                                         page_offset = 0xc000 * (vram_bank & 0x03);
1398                                 } else {
1399                                         page_offset = 0; // right?
1400                                 }
1401 #else                   
1402                                 page_offset = 0xc000 * (vram_bank & 0x03);
1403 #endif                  
1404                                 page_mask = 0x1fff;
1405                                 pagemod = addr & 0xe000;
1406                         } else {
1407                                 if(mode320) {
1408                                         page_mask = 0x1fff;
1409                                         pagemod = addr & 0xe000;
1410                                 } else {
1411                                         pagemod = addr & 0xc000;
1412                                 }
1413                                 if(active_page != 0) {
1414                                         page_offset += 0xc000;
1415                                 }
1416                         }                               
1417                         return gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1418                 }
1419 #elif defined(_FM77AV_VARIANTS)
1420                 {               
1421                         if(active_page != 0) {
1422                                 page_offset += 0xc000;
1423                         }
1424                         if(mode320) {
1425                                 page_mask = 0x1fff;
1426                                 pagemod = addr & 0xe000;
1427                         } else {
1428                                 pagemod = addr & 0xc000;
1429                         }
1430                         return gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1431                 }
1432 #elif defined(_FM77L4) //_FM77L4
1433                 {
1434                         if(display_mode == DISPLAY_MODE_8_400L) {
1435                                 return (uint32)read_vram_l4_400l(addr, offset);
1436                         } else {
1437                                 pagemod = addr & 0xc000;
1438                                 return gvram[((addr + offset) & 0x3fff) | pagemod];
1439                         }
1440                         return 0xff;
1441                 }
1442 #else // Others (77/7/8)
1443                 pagemod = addr & 0xc000;
1444                 return gvram[((addr + offset) & 0x3fff) | pagemod];
1445 #endif
1446 }
1447
1448 void DISPLAY::write_dma_data8(uint32 addr, uint32 data)
1449 {
1450         uint32 raddr = addr & 0xffff;
1451         uint32 color;
1452         if(addr < 0xc000) {
1453 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1454                 if(display_mode == DISPLAY_MODE_8_400L) {
1455                         color = vram_bank & 0x03;
1456                         if(color > 2) color = 0;
1457                 } else {
1458                         color = (addr >> 14) & 0x03;
1459                 }
1460 # endif
1461 #if !defined(_FM8)              
1462                 if((multimode_accessmask & (1 << color)) != 0) return;
1463 #endif          
1464                 return write_vram_data8(raddr, (uint8)data);
1465         } else {
1466                 return write_data8_main(raddr, (uint8)data);
1467         }
1468 }
1469
1470
1471 void DISPLAY::write_vram_data8(uint32 addr, uint8 data)
1472 {
1473         uint32 offset;
1474         uint32 page_offset = 0;
1475         uint32 page_mask = 0x3fff;
1476         uint32 color = (addr >> 14) & 0x03;
1477         uint32 pagemod;
1478         
1479 #if defined(_FM77AV_VARIANTS)
1480         if (active_page != 0) {
1481                 offset = offset_point_bank1;
1482         } else {
1483                 offset = offset_point;
1484         }
1485 #else
1486         offset = offset_point;
1487 #endif
1488
1489 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1490 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1491                 if(vram_active_block != 0) page_offset = 0x18000;
1492 # endif         
1493                 if(display_mode == DISPLAY_MODE_8_400L) {
1494                         if(addr >= 0x8000) {
1495                                 return;
1496                         }
1497                         color = vram_bank & 0x03;
1498                         if(color > 2) color = 0;
1499                         offset <<= 1;
1500                         pagemod = 0x8000 * color;
1501                         gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset] = data;
1502                         vram_wrote_table[((addr + offset) % 0x8000) / 80] = true;
1503                 } else  if(display_mode == DISPLAY_MODE_256k) {
1504 #if defined(_FM77AV40)
1505                         if(vram_bank < 3) {
1506                                 page_offset = 0xc000 * (vram_bank & 0x03);
1507                         } else {
1508                                 page_offset = 0; // right?
1509                         }
1510 #else                   
1511                         page_offset = 0xc000 * (vram_bank & 0x03);
1512 #endif                  
1513                         page_mask = 0x1fff;
1514                         pagemod = addr & 0xe000;
1515                         gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1516                         vram_wrote_table[((addr + offset) % 0x2000) / 40] = true;
1517                         return;
1518                 } else if(display_mode == DISPLAY_MODE_4096) {
1519                         if(active_page != 0) {
1520                                 page_offset += 0xc000;
1521                         }
1522                         page_mask = 0x1fff;
1523                         pagemod = addr & 0xe000;
1524                         gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1525                         vram_wrote_table[((addr + offset) % 0x2000) / 40] = true;
1526                 } else { // 200line
1527                         if(active_page != 0) {
1528                                 page_offset += 0xc000;
1529                         }
1530                         page_mask = 0x3fff;
1531                         pagemod = addr & 0xc000;
1532                         gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1533                         vram_wrote_table[((addr + offset) % 0x4000) / 80] = true;
1534                 }                               
1535
1536 #elif defined(_FM77AV_VARIANTS)
1537                 if(display_mode == DISPLAY_MODE_4096) {
1538                         if(active_page != 0) {
1539                                 page_offset = 0xc000;
1540                         }
1541                         page_mask = 0x1fff;
1542                         pagemod = addr & 0xe000;
1543                         gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1544                         vram_wrote_table[((addr + offset) % 0x2000) / 40] = true;
1545                 } else { // 200line
1546                         if(active_page != 0) {
1547                                 page_offset = 0xc000;
1548                         }
1549                         page_mask = 0x3fff;
1550                         pagemod = addr & 0xc000;
1551                         gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1552                         vram_wrote_table[((addr + offset) % 0x4000) / 80] = true;
1553                 }
1554 #elif defined(_FM77L4) //_FM77L4
1555                 {
1556                         if(display_mode == DISPLAY_MODE_8_400L) {
1557                                 write_vram_l4_400l(addr, data, offset);
1558                         } else {
1559                                 pagemod = addr & 0xc000;
1560                                 gvram[((addr + offset) & 0x3fff) | pagemod] = data;
1561                         }
1562                         //vram_wrote_table[((addr + offset) % 0x4000) / 80] = true;
1563                 }
1564 #else // Others (77/7/8)
1565                 pagemod = addr & 0xc000;
1566                 gvram[((addr + offset) & 0x3fff) | pagemod] = data;
1567                 //vram_wrote_table[((addr + offset) % 0x4000) / 80] = true;
1568 #endif
1569 #if defined(_FM77AV_VARIANTS)   
1570         if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
1571 #else
1572         vram_wrote = true;
1573 #endif  
1574 }
1575
1576 uint32 DISPLAY::read_data8_main(uint32 addr)
1577 {
1578         uint32 raddr;
1579         if(addr < 0xc000) return 0xff;
1580         if(addr < 0xd000) { 
1581                 raddr = addr - 0xc000;
1582 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1583                 if(monitor_ram) {
1584                         if(console_ram_bank >= 1) {
1585                                 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
1586                         }
1587                 }
1588 #endif
1589                 return console_ram[raddr];
1590         } else if(addr < 0xd380) {
1591                 raddr = addr - 0xd000;
1592                 return work_ram[raddr];
1593         } else if(addr < 0xd400) {
1594                 raddr = addr - 0xd380;
1595                 return shared_ram[raddr];
1596         } else  if(addr < 0xd800) {
1597 #if defined(_FM77AV_VARIANTS)
1598                 if(addr >= 0xd500) {
1599                         return submem_hidden[addr - 0xd500];
1600                 }
1601 #endif     
1602                 return read_mmio(addr);
1603         } else if(addr < 0x10000) {
1604 #if !defined(_FM77AV_VARIANTS)
1605                 return subsys_c[addr - 0xd800];
1606 #else
1607                 if(addr < 0xe000) {
1608 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
1609                         if(monitor_ram) {
1610                                 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
1611                         }
1612 #endif          
1613                         return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
1614                 } else if(addr < 0x10000) {
1615 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
1616                         if(monitor_ram) {
1617                                 return subsys_ram[addr - 0xe000];
1618                         }
1619 #endif          
1620                         switch(subrom_bank_using & 3) {
1621                         case 0: // SUBSYS_C
1622                                 return subsys_c[addr - 0xd800];
1623                                 break;
1624                         case 1:
1625                                 return subsys_a[addr - 0xe000];
1626                                 break;
1627                         case 2:
1628                                 return subsys_b[addr - 0xe000];
1629                                 break;
1630                         default:
1631                                 return subsys_cg[addr - 0xe000];
1632                                 break;
1633                         }
1634                 }
1635 #endif
1636         }
1637         return 0xff;
1638 }
1639
1640 uint32 DISPLAY::read_dma_data8(uint32 addr)
1641 {
1642         uint32 raddr = addr & 0xffff;
1643         uint32 color;
1644         if(addr < 0xc000) {
1645 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1646                 if(display_mode == DISPLAY_MODE_8_400L) {
1647                         color = vram_bank & 0x03;
1648                         if(color > 2) color = 0;
1649                 } else {
1650                         color = (addr >> 14) & 0x03;
1651                 }
1652 # endif
1653 # if !defined(_FM8)             
1654                 if((multimode_accessmask & (1 << color)) != 0) return 0xff;
1655 # endif         
1656                 return read_vram_data8(raddr);
1657         } else {
1658                 return read_data8_main(raddr);
1659         }
1660 }
1661
1662
1663 uint32 DISPLAY::read_data8(uint32 addr)
1664 {
1665         uint32 raddr = addr;
1666         uint32 offset;
1667         uint32 color = (addr & 0x0c000) >> 14;
1668         if(addr < 0xc000) {
1669 #if defined(_FM77AV_VARIANTS)
1670                 if(use_alu) {
1671                         alu->read_data8(addr + ALU_WRITE_PROXY);
1672                 }
1673 #endif
1674 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1675                 if(display_mode == DISPLAY_MODE_8_400L) {
1676                         color = vram_bank & 0x03;
1677                         if(color > 2) color = 0;
1678                 } else {
1679                         color = (addr >> 14) & 0x03;
1680                 }
1681 # endif
1682 # if !defined(_FM8)             
1683                 if((multimode_accessmask & (1 << color)) != 0) return 0xff;
1684 # endif         
1685                 return read_vram_data8(addr);
1686         } else if(addr < 0x10000) {
1687                 return read_data8_main(addr);
1688         }
1689 #if !defined(_FM8)      
1690         else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
1691                 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
1692         }
1693 #endif  
1694 #if defined(_FM77AV_VARIANTS)
1695         // ACCESS VIA ALU.
1696         else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
1697                 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
1698 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)         
1699                 if(display_mode == DISPLAY_MODE_8_400L) {
1700                         uint32 page_offset = 0;
1701 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1702                         if(vram_active_block != 0) page_offset = 0x18000;
1703 # endif         
1704                         color = (addr & 0x18000) >> 15;
1705                         if(color > 2) color = 0;
1706                         
1707                         if (active_page != 0) {
1708                                 offset = offset_point_bank1 << 1;
1709                         } else {
1710                                 offset = offset_point << 1;
1711                         }
1712                         if(color > 2) color = 0;
1713                         uint32 pagemod = 0x8000 * color;
1714                         return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
1715                 }
1716 # endif         
1717                 return read_vram_data8(addr);
1718         }
1719 #endif
1720         return 0xff;
1721 }       
1722
1723 /*
1724  * Vram accessing functions moved to vram.cpp .
1725  */
1726
1727 void DISPLAY::write_mmio(uint32 addr, uint32 data)
1728 {
1729         uint8 rval = 0;
1730         pair tmpvar;
1731         if(addr < 0xd400) return;
1732         
1733 #if !defined(_FM77AV_VARIANTS)
1734         addr = (addr - 0xd400) & 0x000f;
1735 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
1736         addr = (addr - 0xd400) & 0x003f;
1737 #else // FM77AV40EX || FM77AV40SX
1738         addr = (addr - 0xd400) & 0x00ff;
1739 #endif
1740         io_w_latch[addr] = (uint8)data;
1741         switch(addr) {
1742 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
1743                 // FM77 SPECIFIED
1744                 case 0x05:
1745                         set_cyclesteal((uint8)data);
1746                         break;
1747 #endif
1748 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1749      defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
1750                 // KANJI
1751                 case 0x06:
1752                         if(!kanjisub) return;
1753                         kanjiaddr.w.h = 0x0000;
1754                         kanjiaddr.b.h = (uint8) data;
1755                         break;
1756                 case 0x07:
1757                         if(!kanjisub) return;
1758                         kanjiaddr.w.h = 0x0000;
1759                         kanjiaddr.b.l = (uint8)data;
1760                         break;
1761 #endif                  
1762                 // CRT OFF
1763                 case 0x08:
1764                         reset_crtflag();
1765                         break;
1766                 // VRAM ACCESS
1767                 case 0x09:
1768                         reset_vramaccess();
1769                         break;
1770                 // BUSY
1771                 case 0x0a:
1772                         if(clr_count <= 0) {
1773                                 set_subbusy();
1774                         } else { // Read once when using clr_foo() to set busy flag.
1775                                 double usec;
1776                                 if(clock_fast) {
1777                                         usec = (1000.0 * 1000.0) / 2000000.0;
1778                                 } else {
1779                                         usec = (1000.0 * 1000.0) / 999000.0;
1780                                 }
1781                                 if(!is_cyclesteal) usec = usec * 3.0;
1782                                 usec = (double)clr_count * usec;
1783                                 register_event(this, EVENT_FM7SUB_CLR_BUSY, usec, false, NULL); // NEXT CYCLE_
1784                                 reset_subbusy();
1785                                 clr_count = 0;
1786                         }
1787                         break;
1788                 // LED
1789                 case 0x0d:
1790                         keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
1791                         break;
1792                 // OFFSET
1793                 case 0x0e:
1794                 case 0x0f:
1795                         rval = (uint8)data;
1796                         if(offset_changed[active_page]) {
1797 #if defined(_FM77AV_VARIANTS)
1798                                 if(active_page != 0) {
1799                                         tmp_offset_point[active_page].d = offset_point_bank1;
1800                                 } else {
1801                                         tmp_offset_point[active_page].d = offset_point;
1802                                 }
1803 #else
1804                                 tmp_offset_point[active_page].d = offset_point;
1805 #endif
1806                         }
1807                         tmp_offset_point[active_page].w.h = 0x0000;
1808                         if(addr == 0x0e) {
1809                                 tmp_offset_point[active_page].b.h = rval;
1810                         } else {
1811                                 tmp_offset_point[active_page].b.l = rval;
1812                         }
1813                         offset_changed[active_page] = !offset_changed[active_page];
1814                         if(offset_changed[active_page]) {
1815                                 vram_wrote = true;
1816 #if defined(_FM77AV_VARIANTS)
1817                                 if(active_page != 0) {
1818                                         if(offset_77av) {
1819                                                 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
1820                                         } else {
1821                                                 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
1822                                         }                                  
1823                                 } else {
1824                                         if(offset_77av) {
1825                                                 offset_point = tmp_offset_point[active_page].d & 0x007fff;
1826                                         } else {
1827                                                 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
1828                                         }                                  
1829                                 }
1830 #else
1831                                 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
1832 #endif                             
1833                         }
1834                         break;
1835 #if defined(_FM77AV_VARIANTS)
1836                 // ALU
1837                 case 0x10:
1838                         alu_write_cmdreg(data);
1839                         break;
1840                 case 0x11:
1841                         alu_write_logical_color(data);
1842                         break;
1843                 case 0x12:
1844                         alu_write_mask_reg(data);
1845                         break;
1846                 case 0x1b:
1847                         alu_write_disable_reg(data);
1848                         break;
1849                 case 0x20:
1850                         alu_write_offsetreg_hi(data);
1851                         break;
1852                 case 0x21:
1853                         alu_write_offsetreg_lo(data);
1854                         break;
1855                 case 0x22:
1856                         alu_write_linepattern_hi(data);
1857                         break;
1858                 case 0x23:
1859                         alu_write_linepattern_lo(data);
1860                         break;
1861 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1862                 case 0x2e: //
1863                         console_ram_bank = (data & 0x18) >> 3;
1864                         if(console_ram_bank > 2) console_ram_bank = 0;
1865                         cgram_bank = data & 0x07;
1866                         kanji_level2 = ((data & 0x80) == 0) ? false : true;
1867                         break;
1868                 case 0x2f: // VRAM BANK
1869                         vram_bank = data &  0x03;
1870                         if(vram_bank > 2) vram_bank = 0;
1871                         vram_wrote = true;
1872                         break;
1873 # endif                 
1874                 // MISC
1875                 case 0x30:
1876                         set_miscreg(data);
1877                         break;
1878                 // KEYBOARD ENCODER
1879                 case 0x31:
1880                         keyboard->write_data8(0x31, data);
1881                         break;
1882 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1883                 case 0x33: //
1884                         vram_active_block = data & 0x01;
1885                         if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
1886                         vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
1887                         break;
1888                         // Window
1889                 case 0x38: //
1890                 case 0x39: //
1891                         tmpvar.d = window_xbegin * 8;
1892                         tmpvar.w.h = 0;
1893                         if(addr == 0x38) {
1894                                 tmpvar.b.h = data & 0x03;
1895                         } else {
1896                                 tmpvar.b.l = data & 0xf8;
1897                         }
1898                         if(mode320 || mode256k) {
1899                            if(tmpvar.d > 320) tmpvar.d = 320;
1900                         } else {
1901                            if(tmpvar.d > 640) tmpvar.d = 640;
1902                         }
1903                         window_xbegin = tmpvar.d / 8;
1904                         vram_wrote = true;
1905                         break;
1906                 case 0x3a: //
1907                 case 0x3b: //
1908                         tmpvar.d = window_xend * 8;
1909                         tmpvar.w.h = 0;
1910                         if(addr == 0x3a) {
1911                                 tmpvar.b.h = data & 0x03;
1912                         } else {
1913                                 tmpvar.b.l = data & 0xf8;
1914                         }
1915                         if(mode320 || mode256k) {
1916                            if(tmpvar.d > 320) tmpvar.d = 320;
1917                         } else {
1918                            if(tmpvar.d > 640) tmpvar.d = 640;
1919                         }
1920                         window_xend = tmpvar.d / 8;
1921                         vram_wrote = true;
1922                         break;
1923                 case 0x3c: //
1924                 case 0x3d: //
1925                         tmpvar.d = window_low;
1926                         tmpvar.w.h = 0;
1927                         if(addr == 0x3c) {
1928                                 tmpvar.b.h = data & 0x03;
1929                         } else {
1930                                 tmpvar.b.l = data & 0xff;
1931                         }
1932                         if(mode400line) {
1933                                 if(tmpvar.d > 400) tmpvar.d = 400;
1934                         } else {
1935                                 tmpvar.d <<= 1;
1936                                 if(tmpvar.d > 400) tmpvar.d = 400;
1937                         }
1938                         window_low = tmpvar.d;
1939                         vram_wrote = true;
1940                         break;
1941                 case 0x3e: //
1942                 case 0x3f: //
1943                         tmpvar.d = window_high;
1944                         tmpvar.w.h = 0;
1945                         if(addr == 0x3e) {
1946                                 tmpvar.b.h = data & 0x03;
1947                         } else {
1948                                 tmpvar.b.l = data & 0xff;
1949                         }
1950                         if(mode400line) {
1951                                 if(tmpvar.d > 400) tmpvar.d = 400;
1952                         } else {
1953                                 tmpvar.d <<= 1;
1954                                 if(tmpvar.d > 400) tmpvar.d = 400;
1955                         }
1956                         window_high = tmpvar.d;
1957                         vram_wrote = true;
1958                         break;
1959 # endif
1960 #endif                          
1961                 default:
1962 #if defined(_FM77AV_VARIANTS)
1963                         //ALU
1964                         if((addr >= 0x13) && (addr <= 0x1a)) {
1965                                 alu_write_cmpdata_reg(addr - 0x13, data);
1966                         } else if((addr >= 0x1c) && (addr <= 0x1e)) {
1967                                 alu_write_tilepaint_data(addr, data);
1968                         } else if((addr >= 0x24) && (addr <= 0x2b)) {
1969                                 alu_write_line_position(addr - 0x24, data);
1970                         }
1971 #endif                          
1972                         break;
1973         }
1974 }
1975
1976 void DISPLAY::write_data8_main(uint32 addr, uint8 data)
1977 {
1978         uint32 offset;
1979         uint32 raddr;
1980         uint32 page_offset = 0x0000;
1981
1982         if(addr < 0xc000) return;
1983         
1984         if(addr < 0xd000) { 
1985                 raddr = addr - 0xc000;
1986 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1987                 if(monitor_ram) {
1988                         if(console_ram_bank >= 1) {
1989                                 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
1990                                 return;
1991                         }
1992                 }
1993 #endif
1994                 console_ram[raddr] = data;
1995                 return;
1996         } else if(addr < 0xd380) {
1997                 raddr = addr - 0xd000;
1998                 work_ram[raddr] = data;
1999                 return;
2000         } else if(addr < 0xd400) {
2001                 raddr = addr - 0xd380;
2002                 shared_ram[raddr] = data;
2003                 return;
2004         } else if(addr < 0xd800) {
2005 #if defined(_FM77AV_VARIANTS)
2006                 if(addr >= 0xd500) {
2007                         submem_hidden[addr - 0xd500] = data;
2008                         return;
2009                 }
2010 #endif
2011                 write_mmio(addr, data);
2012                 return;
2013         } else if(addr < 0x10000) {
2014 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2015                 if(ram_protect) return;
2016                 if(monitor_ram) {
2017                         if(addr < 0xe000) {
2018                                 submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)] = data; //FIXME
2019                         } else {
2020                                 subsys_ram[addr - 0xe000] = data;
2021                         }
2022                 }
2023 #endif          
2024                 return;
2025         }
2026 }
2027
2028 void DISPLAY::write_data8(uint32 addr, uint32 data)
2029 {
2030         uint32 offset;
2031         uint32 raddr;
2032         uint32 page_offset = 0x0000;
2033         uint8 val8 = data & 0xff;
2034         uint32 pagemod;
2035         uint32 color = (addr & 0xc000) >> 14;
2036
2037         if(addr < 0xc000) {
2038 #if defined(_FM77AV_VARIANTS)
2039                 if(use_alu) {
2040                         alu->read_data8(addr + ALU_WRITE_PROXY);
2041                         return;
2042                 }
2043 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2044                 if(display_mode == DISPLAY_MODE_8_400L) {
2045                         color = vram_bank & 0x03;
2046                         if(color > 2) color = 0;
2047                 }
2048 # endif
2049 #endif
2050 #if !defined(_FM8)
2051                 if((multimode_accessmask & (1 << color)) != 0) return;
2052 #endif          
2053                 write_vram_data8(addr, val8);
2054                 return;
2055         } else if(addr < 0x10000) {
2056                 write_data8_main(addr, val8);
2057                 return;
2058         }
2059 #if !defined(_FM8)      
2060         else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2061                 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
2062                 return;
2063         }
2064 #endif  
2065 #if defined(_FM77AV_VARIANTS)
2066         // ANALOG PALETTE
2067         else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
2068                 set_apalette_r(val8);
2069                 return;
2070         } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
2071                 set_apalette_g(val8);
2072                 return;
2073         } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
2074                 set_apalette_b(val8);
2075                 return;
2076         } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
2077                 set_apalette_index_hi(val8);
2078                 return;
2079         } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
2080                 set_apalette_index_lo(val8);
2081                 return;
2082         }
2083         // ACCESS VIA ALU.
2084         else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2085                 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS; 
2086 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2087                 if(display_mode == DISPLAY_MODE_8_400L) {
2088                         color = (addr & 0x18000) >> 15;
2089                         if(color > 2) color = 0;
2090                         page_offset = 0;
2091 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2092                         if(vram_active_block != 0) page_offset = 0x18000;
2093 # endif         
2094                         if(color > 2) color = 0;
2095                         if (active_page != 0) {
2096                                 offset = offset_point_bank1 << 1;
2097                         } else {
2098                                 offset = offset_point << 1;
2099                         }
2100                         pagemod = 0x8000 * color;
2101                         gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset] = data;
2102                         if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
2103                         vram_wrote_table[((addr + offset) % 0x8000) / 80] = true;
2104                         return;
2105                 }
2106                 write_vram_data8(addr, data);
2107 # else
2108                 write_vram_data8(addr, data);
2109 # endif
2110                 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
2111         }
2112 #endif
2113         return;
2114 }       
2115
2116
2117 uint32 DISPLAY::read_bios(const _TCHAR *name, uint8 *ptr, uint32 size)
2118 {
2119         FILEIO fio;
2120         uint32 blocks;
2121         const _TCHAR *s;
2122   
2123         if((name == NULL) || (ptr == NULL))  return 0;
2124         s = create_local_path(name);
2125         if(s == NULL) return 0;
2126   
2127         if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
2128         blocks = fio.Fread(ptr, size, 1);
2129         fio.Fclose();
2130
2131         return blocks * size;
2132 }
2133
2134
2135 void DISPLAY::initialize()
2136 {
2137         int i;
2138
2139         screen_update_flag = true;
2140         memset(gvram, 0x00, sizeof(gvram));
2141         vram_wrote_shadow = false;
2142 #if defined(_FM77AV_VARIANTS)
2143         memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
2144         for(i = 0; i < 411; i++) vram_wrote_table[i] = false;
2145         for(i = 0; i < 411; i++) vram_draw_table[i] = false;
2146 #endif  
2147         memset(console_ram, 0x00, sizeof(console_ram));
2148         memset(work_ram, 0x00, sizeof(work_ram));
2149         memset(shared_ram, 0x00, sizeof(shared_ram));
2150         memset(subsys_c, 0xff, sizeof(subsys_c));
2151    
2152         diag_load_subrom_c = false;
2153 #if defined(_FM8)       
2154         if(read_bios(_T("SUBSYS_8.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2155         emu->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2156 #else
2157         if(read_bios(_T("SUBSYS_C.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2158         emu->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2159 #endif
2160 #if defined(_FM77AV_VARIANTS)
2161         memset(subsys_a, 0xff, sizeof(subsys_a));
2162         memset(subsys_b, 0xff, sizeof(subsys_b));
2163         memset(subsys_cg, 0xff, sizeof(subsys_cg));
2164         memset(submem_hidden, 0x00, sizeof(submem_hidden));
2165    
2166         diag_load_subrom_a = false;
2167         if(read_bios(_T("SUBSYS_A.ROM"), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
2168         emu->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
2169
2170         diag_load_subrom_b = false;
2171         if(read_bios(_T("SUBSYS_B.ROM"), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
2172         emu->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
2173
2174         diag_load_subrom_cg = false;
2175         if(read_bios(_T("SUBSYSCG.ROM"), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
2176         emu->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
2177 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2178     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2179         memset(subsys_ram, 0x00, sizeof(subsys_ram));
2180         memset(submem_cgram, 0x00, sizeof(submem_cgram));
2181         memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
2182         ram_protect = true;
2183 # endif
2184 #endif
2185 #if defined(_FM77AV_VARIANTS)
2186         mode320 = false;
2187         apalette_index.d = 0;
2188         for(i = 0; i < 4096; i++) {
2189                 analog_palette_r[i] = i & 0x0f0;
2190                 analog_palette_g[i] = i & 0xf00;
2191                 analog_palette_b[i] = i & 0x00f;
2192                 calc_apalette(i);
2193         }
2194 #endif
2195 #if defined(_FM77AV_VARIANTS)
2196         hblank_event_id = -1;
2197         hdisp_event_id = -1;
2198         vsync_event_id = -1;
2199         vstart_event_id = -1;
2200 #endif
2201 #if defined(_FM8)
2202         clock_fast = false;
2203 #else
2204         clock_fast = true;
2205 #endif
2206 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
2207         is_cyclesteal = true;
2208 #else
2209         is_cyclesteal = false;
2210 #endif  
2211         emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2212         enter_display();
2213         nmi_event_id = -1;
2214         firq_mask = false;
2215         key_firq_req = false;   //firq_mask = true;
2216         frame_skip_count = 3;
2217 }
2218
2219 void DISPLAY::release()
2220 {
2221 }
2222
2223 #define STATE_VERSION 3
2224 void DISPLAY::save_state(FILEIO *state_fio)
2225 {
2226         state_fio->FputUint32_BE(STATE_VERSION);
2227         state_fio->FputInt32_BE(this_device_id);
2228
2229         {
2230                 int i;
2231                 state_fio->FputInt32_BE(clr_count);
2232                 state_fio->FputBool(halt_flag);
2233                 state_fio->FputInt32_BE(active_page);
2234                 state_fio->FputBool(sub_busy);
2235                 state_fio->FputBool(crt_flag);
2236                 state_fio->FputBool(vram_wrote);
2237                 state_fio->FputBool(vram_wrote_shadow);
2238 #if defined(_FM77AV_VARIANTS)
2239                 for(i = 0; i < 411; i++) state_fio->FputBool(vram_wrote_table[i]);
2240                 for(i = 0; i < 411; i++) state_fio->FputBool(vram_draw_table[i]);
2241 #endif          
2242                 state_fio->FputBool(is_cyclesteal);
2243                 
2244                 state_fio->FputBool(clock_fast);
2245                 
2246 #if defined(_FM77AV_VARIANTS)
2247                 state_fio->FputBool(subcpu_resetreq);
2248                 state_fio->FputBool(power_on_reset);
2249 #endif  
2250                 state_fio->FputBool(cancel_request);
2251                 state_fio->FputBool(key_firq_req);
2252
2253                 state_fio->FputInt32_BE(display_mode);
2254                 state_fio->FputUint32_BE(prev_clock);
2255
2256 #if !defined(_FM8)      
2257                 state_fio->Fwrite(dpalette_data, sizeof(dpalette_data), 1);
2258                 state_fio->FputUint8(multimode_accessmask);
2259                 state_fio->FputUint8(multimode_dispmask);
2260 #endif          
2261                 state_fio->FputUint32_BE(offset_point);
2262 #if defined(_FM77AV_VARIANTS)
2263                 state_fio->FputUint32_BE(offset_point_bank1);
2264                 state_fio->FputUint32_BE(offset_point_bak);
2265                 state_fio->FputUint32_BE(offset_point_bank1_bak);
2266 #endif          
2267                 for(i = 0; i < 2; i++) {
2268                         state_fio->FputUint32_BE(tmp_offset_point[i].d);
2269                         state_fio->FputBool(offset_changed[i]);
2270                 }
2271                 state_fio->FputBool(offset_77av);
2272                 state_fio->FputBool(diag_load_subrom_c);
2273                 
2274         
2275                 state_fio->Fwrite(io_w_latch, sizeof(io_w_latch), 1);
2276                 state_fio->Fwrite(console_ram, sizeof(console_ram), 1);
2277                 state_fio->Fwrite(work_ram, sizeof(work_ram), 1);
2278                 state_fio->Fwrite(shared_ram, sizeof(shared_ram), 1);
2279                 state_fio->Fwrite(subsys_c, sizeof(subsys_c), 1);
2280                 state_fio->Fwrite(gvram, sizeof(gvram), 1);
2281 #if defined(_FM77AV_VARIANTS)
2282                 state_fio->Fwrite(gvram_shadow, sizeof(gvram_shadow), 1);
2283 #endif  
2284         
2285 #if defined(_FM77_VARIANTS)
2286                 state_fio->FputBool(kanjisub);
2287                 state_fio->FputUint16_BE(kanjiaddr.w.l);
2288 # if defined(_FM77L4)
2289                 state_fio->FputBool(mode400line);
2290                 state_fio->FputBool(stat_400linecard);
2291 # endif
2292 #elif defined(_FM77AV_VARIANTS)
2293                 state_fio->FputBool(kanjisub);
2294                 state_fio->FputUint16_BE(kanjiaddr.w.l);
2295
2296                 state_fio->FputBool(vblank);
2297                 state_fio->FputBool(vsync);
2298                 state_fio->FputBool(hblank);
2299                 state_fio->FputInt32_BE(vblank_count);
2300                 state_fio->FputUint32_BE(displine);
2301                 
2302                 state_fio->FputBool(mode320);
2303                 state_fio->FputInt32_BE(display_page);
2304                 state_fio->FputInt32_BE(cgrom_bank);
2305 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
2306     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2307                 state_fio->FputInt32_BE(vram_bank);
2308 #endif  
2309         
2310                 state_fio->FputUint8(subrom_bank);
2311                 state_fio->FputUint8(subrom_bank_using);
2312         
2313                 state_fio->FputBool(nmi_enable);
2314                 state_fio->FputBool(use_alu);
2315                 
2316                 state_fio->FputUint8(apalette_index.b.l);
2317                 state_fio->FputUint8(apalette_index.b.h);
2318                 state_fio->Fwrite(analog_palette_r, sizeof(analog_palette_r), 1);
2319                 state_fio->Fwrite(analog_palette_g, sizeof(analog_palette_g), 1);
2320                 state_fio->Fwrite(analog_palette_b, sizeof(analog_palette_b), 1);
2321                 
2322
2323                 state_fio->FputBool(diag_load_subrom_a);
2324                 state_fio->FputBool(diag_load_subrom_b);
2325                 state_fio->FputBool(diag_load_subrom_cg);
2326         
2327                 state_fio->Fwrite(subsys_a, sizeof(subsys_a), 1);
2328                 state_fio->Fwrite(subsys_b, sizeof(subsys_b), 1);
2329                 state_fio->Fwrite(subsys_cg, sizeof(subsys_cg), 1);
2330                 state_fio->Fwrite(submem_hidden, sizeof(submem_hidden), 1);
2331 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2332                 state_fio->FputBool(mode400line);
2333                 state_fio->FputBool(mode256k);
2334                 
2335                 state_fio->FputBool(monitor_ram);
2336 #  if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2337                 state_fio->FputUint16_BE(window_low);
2338                 state_fio->FputUint16_BE(window_high);
2339                 state_fio->FputUint16_BE(window_xbegin);
2340                 state_fio->FputUint16_BE(window_xend);
2341                 state_fio->FputBool(window_opened);
2342 #  endif        
2343                 state_fio->FputBool(kanji_level2);
2344
2345                 state_fio->FputUint8(vram_active_block);
2346                 state_fio->FputUint8(vram_display_block);
2347                 state_fio->FputUint8(console_ram_bank);
2348                 state_fio->FputBool(ram_protect);
2349                 
2350                 state_fio->FputUint32_BE(cgram_bank);
2351                 state_fio->Fwrite(subsys_ram, sizeof(subsys_ram), 1);
2352                 state_fio->Fwrite(submem_cgram, sizeof(submem_cgram), 1);
2353                 state_fio->Fwrite(submem_console_av40, sizeof(submem_console_av40), 1);
2354 # endif
2355 #endif
2356         }
2357         // V2
2358         {
2359                 state_fio->FputInt32_BE(nmi_event_id);
2360 #if defined(_FM77AV_VARIANTS)
2361                 state_fio->FputInt32_BE(hblank_event_id);
2362                 state_fio->FputInt32_BE(hdisp_event_id);
2363                 state_fio->FputInt32_BE(vsync_event_id);
2364                 state_fio->FputInt32_BE(vstart_event_id);
2365 #endif
2366                 state_fio->FputBool(firq_mask);
2367                 state_fio->FputBool(vram_accessflag);
2368                 state_fio->FputUint32_BE(frame_skip_count);
2369         }                       
2370 }
2371
2372 bool DISPLAY::load_state(FILEIO *state_fio)
2373 {
2374
2375         uint32 version = state_fio->FgetUint32_BE();
2376         if(this_device_id != state_fio->FgetInt32_BE()) {
2377                 return false;
2378         }
2379    
2380         if(version >= 1) {
2381                 int addr;
2382                 int i;
2383                 clr_count = state_fio->FgetInt32_BE();
2384                 halt_flag = state_fio->FgetBool();
2385                 active_page = state_fio->FgetInt32_BE();
2386                 sub_busy = state_fio->FgetBool();
2387                 crt_flag = state_fio->FgetBool();
2388                 vram_wrote = state_fio->FgetBool();
2389                 crt_flag_bak = true;
2390                 screen_update_flag = true;
2391                 vram_wrote_shadow = state_fio->FgetBool();
2392 #if defined(_FM77AV_VARIANTS)
2393                 for(i = 0; i < 411; i++) vram_wrote_table[i] = state_fio->FgetBool();
2394                 for(i = 0; i < 411; i++) vram_draw_table[i] = state_fio->FgetBool();
2395 #endif          
2396                 is_cyclesteal = state_fio->FgetBool();
2397         
2398                 clock_fast = state_fio->FgetBool();
2399
2400 #if defined(_FM77AV_VARIANTS)
2401                 subcpu_resetreq = state_fio->FgetBool();
2402                 power_on_reset = state_fio->FgetBool();
2403 #endif          
2404                 cancel_request = state_fio->FgetBool();
2405                 key_firq_req = state_fio->FgetBool();
2406
2407                 display_mode = state_fio->FgetInt32_BE();
2408                 prev_clock = state_fio->FgetUint32_BE();
2409         
2410 #if defined(_FM8)
2411                 for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
2412 #else
2413                 state_fio->Fread(dpalette_data, sizeof(dpalette_data), 1);
2414                 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
2415                 multimode_accessmask = state_fio->FgetUint8();
2416                 multimode_dispmask = state_fio->FgetUint8();
2417 #endif
2418                 offset_point = state_fio->FgetUint32_BE();
2419 #if defined(_FM77AV_VARIANTS)
2420                 offset_point_bank1     = state_fio->FgetUint32_BE();
2421                 offset_point_bak       = state_fio->FgetUint32_BE();
2422                 offset_point_bank1_bak = state_fio->FgetUint32_BE();
2423 #endif          
2424                 for(i = 0; i < 2; i++) {
2425                         tmp_offset_point[i].d = state_fio->FgetUint32_BE();
2426                         offset_changed[i] = state_fio->FgetBool();
2427                 }
2428                 offset_77av = state_fio->FgetBool();
2429                 diag_load_subrom_c = state_fio->FgetBool();
2430                 
2431                 state_fio->Fread(io_w_latch, sizeof(io_w_latch), 1);
2432                 state_fio->Fread(console_ram, sizeof(console_ram), 1);
2433                 state_fio->Fread(work_ram, sizeof(work_ram), 1);
2434                 state_fio->Fread(shared_ram, sizeof(shared_ram), 1);
2435                 state_fio->Fread(subsys_c, sizeof(subsys_c), 1);
2436                 state_fio->Fread(gvram, sizeof(gvram), 1);
2437 #if defined(_FM77AV_VARIANTS)
2438                 state_fio->Fread(gvram_shadow, sizeof(gvram_shadow), 1);
2439 #endif  
2440 #if defined(_FM77_VARIANTS)
2441                 kanjisub = state_fio->FgetBool();
2442                 kanjiaddr.d = 0;
2443                 kanjiaddr.w.l = state_fio->FgetUint16_BE();
2444 # if defined(_FM77L4)           
2445                 mode400line = state_fio->FgetBool();
2446                 stat_400linecard = state_fio->FgetBool();
2447 # endif         
2448 #elif defined(_FM77AV_VARIANTS)
2449                 kanjisub = state_fio->FgetBool();
2450                 kanjiaddr.d = 0;
2451                 kanjiaddr.w.l = state_fio->FgetUint16_BE();
2452                 
2453                 vblank = state_fio->FgetBool();
2454                 vsync = state_fio->FgetBool();
2455                 hblank = state_fio->FgetBool();
2456                 vblank_count = state_fio->FgetInt32_BE();
2457                 displine = state_fio->FgetUint32_BE();
2458
2459                 mode320 = state_fio->FgetBool();
2460                 display_page = state_fio->FgetInt32_BE();
2461                 cgrom_bank = state_fio->FgetInt32_BE();
2462 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
2463     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2464                 vram_bank = state_fio->FgetInt32_BE();
2465 #endif          
2466         
2467                 subrom_bank = state_fio->FgetUint8();
2468                 subrom_bank_using = state_fio->FgetUint8();
2469         
2470                 nmi_enable = state_fio->FgetBool();
2471                 use_alu = state_fio->FgetBool();
2472
2473                 apalette_index.b.l = state_fio->FgetUint8();
2474                 apalette_index.b.h = state_fio->FgetUint8();
2475         
2476                 state_fio->Fread(analog_palette_r, sizeof(analog_palette_r), 1);
2477                 state_fio->Fread(analog_palette_g, sizeof(analog_palette_g), 1);
2478                 state_fio->Fread(analog_palette_b, sizeof(analog_palette_b), 1);
2479                 for(i = 0; i < 4096; i++) calc_apalette(i);
2480                 
2481                 diag_load_subrom_a = state_fio->FgetBool();
2482                 diag_load_subrom_b = state_fio->FgetBool();
2483                 diag_load_subrom_cg = state_fio->FgetBool();
2484         
2485                 state_fio->Fread(subsys_a, sizeof(subsys_a), 1);
2486                 state_fio->Fread(subsys_b, sizeof(subsys_b), 1);
2487                 state_fio->Fread(subsys_cg, sizeof(subsys_cg), 1);
2488                 state_fio->Fread(submem_hidden, sizeof(submem_hidden), 1);
2489            
2490 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2491                 mode400line = state_fio->FgetBool();
2492                 mode256k = state_fio->FgetBool();
2493
2494                 monitor_ram = state_fio->FgetBool();
2495 #  if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2496                 window_low = state_fio->FgetUint16_BE();
2497                 window_high = state_fio->FgetUint16_BE();
2498                 window_xbegin = state_fio->FgetUint16_BE();
2499                 window_xend = state_fio->FgetUint16_BE();
2500                 window_opened = state_fio->FgetBool();
2501 # endif 
2502                 kanji_level2 = state_fio->FgetBool();
2503                 
2504                 vram_active_block = state_fio->FgetUint8();
2505                 vram_display_block = state_fio->FgetUint8();
2506                 console_ram_bank = state_fio->FgetUint8();
2507                 ram_protect = state_fio->FgetBool();
2508
2509                 cgram_bank = state_fio->FgetUint32_BE();
2510                 state_fio->Fread(subsys_ram, sizeof(subsys_ram), 1);
2511                 state_fio->Fread(submem_cgram, sizeof(submem_cgram), 1);
2512                 state_fio->Fread(submem_console_av40, sizeof(submem_console_av40), 1);
2513 # endif
2514 #endif
2515                 bool vram_wrote_shadow_bak = vram_wrote_shadow;
2516                 vram_wrote_shadow = true; // Force Draw
2517                 this->draw_screen();
2518                 vram_wrote_shadow = vram_wrote_shadow_bak;
2519                 if(version == 1) return true;
2520         }
2521         if(version >= 2) {      //V2
2522                 nmi_event_id = state_fio->FgetInt32_BE();
2523 #if defined(_FM77AV_VARIANTS)
2524                 hblank_event_id = state_fio->FgetInt32_BE();
2525                 hdisp_event_id = state_fio->FgetInt32_BE();
2526                 vsync_event_id = state_fio->FgetInt32_BE();
2527                 vstart_event_id = state_fio->FgetInt32_BE();
2528 #endif
2529                 firq_mask = state_fio->FgetBool();
2530                 vram_accessflag = state_fio->FgetBool();
2531                 frame_skip_count = state_fio->FgetUint32_BE();
2532         }                       
2533         if(version == 3) return true;
2534         return false;
2535 }
2536
2537