OSDN Git Service

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