OSDN Git Service

[VM][FM7][BUILD] Fix FTBFSs for FM-7/77.
[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 // Test header
672 #if !defined(_MSC_VER)
673 #include <SDL2/SDL.h>
674 #endif
675
676 // Timing values from XM7 . Thanks Ryu.
677 void DISPLAY::event_callback(int event_id, int err)
678 {
679         double usec;
680         bool f;
681         switch(event_id) {
682                 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
683 #if defined(_FM77AV_VARIANTS)
684                         if(nmi_enable) {
685                                 do_nmi(true);
686                         } else {
687                                 //do_nmi(false);
688                         }
689 #else
690                         do_nmi(true);
691 #endif
692                         break;
693                 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
694                         do_nmi(false);
695                         break;
696 #if defined(_FM77AV_VARIANTS)
697                 case EVENT_FM7SUB_HDISP:
698                         hblank = false;
699                         vblank = false;
700                         vsync = false;
701                         mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x02, 0xff);
702                         usec = 39.5;
703                         if(display_mode == DISPLAY_MODE_8_400L) usec = 30.0;
704                         register_event(this, EVENT_FM7SUB_HBLANK, usec, false, &hblank_event_id); // NEXT CYCLE_
705                         
706                         break;
707                 case EVENT_FM7SUB_HBLANK:
708                         hblank = true;
709                         vblank = false;
710                         vsync = false;
711                         mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
712                         f = false;
713                         if(display_mode == DISPLAY_MODE_8_400L) {
714                                 if(displine < 400) f = true;
715                         } else {
716                                 if(displine < 200) f = true;
717                         }
718                         if(f) {
719                                 if(display_mode == DISPLAY_MODE_8_400L) {
720                                         usec = 11.0;
721                                 } else {
722                                         usec = 24.0;
723                                 }
724                                 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
725                                 
726                                 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
727                                         if((display_mode == DISPLAY_MODE_4096) || (display_mode == DISPLAY_MODE_256k)){
728 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
729                                                 int planes = 2;
730 # elif defined(_FM77AV40)
731                                                 int planes = 1;
732 # else
733                                                 int planes = 1;
734 #endif
735                                                 if(vram_wrote_table[displine] || vram_wrote) {
736                                                         uint32 baseaddr1 = (displine * 40) & 0x1fff;
737                                                         uint32 baseaddr2 = baseaddr1 + 0xc000;
738                                                         vram_wrote_table[displine] = false;
739                                                         for(int i = 0; i < planes; i++) {
740                                                                 for(int j = 0; j < 6; j++) {
741                                                                         memcpy(&gvram_shadow[j * 0x2000 + baseaddr1],
742                                                                                    &gvram[j * 0x2000 + baseaddr1], 40);
743                                                                         memcpy(&gvram_shadow[j * 0x2000 + baseaddr2],
744                                                                                    &gvram[j * 0x2000 + baseaddr2], 40);
745                                                                 }
746                                                                 baseaddr1 += 0x18000;
747                                                                 baseaddr2 += 0x18000;
748                                                         }
749 # if defined(_FM77AV40)
750                                                         for(int j = 0; j < 6; j++) {
751                                                                 memcpy(&gvram_shadow[j * 0x2000 + baseaddr1],
752                                                                            &gvram[j * 0x2000 + baseaddr1], 40);
753                                                         }
754 # endif                                                 
755                                                         vram_draw_table[displine] = true;
756                                                 }
757                                         } else if(display_mode == DISPLAY_MODE_8_400L) {
758 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
759                                                 int planes = 2;
760 # elif defined(_FM77AV40)
761                                                 int planes = 1;
762 # else
763                                                 int planes = 0;
764 #endif
765                                                 if(vram_wrote_table[displine] || vram_wrote) {
766                                                         uint32 baseaddr1 = (displine * 80) & 0x7fff;
767                                                         vram_wrote_table[displine] = false;
768                                                         for(int i = 0; i < planes; i++) {
769                                                                 for(int j = 0; j < 3; j++) {
770                                                                         memcpy(&gvram_shadow[j * 0x8000 + baseaddr1],
771                                                                                    &gvram[j * 0x8000 + baseaddr1], 80);
772                                                                 }
773                                                                 baseaddr1 += 0x18000;
774                                                         }
775                                                         
776 # if defined(_FM77AV40)
777                                                         for(int j = 0; j < 3; j++) {
778                                                                 memcpy(&gvram_shadow[j * 0x4000 + baseaddr1],
779                                                                            &gvram[j * 0x4000 + baseaddr1], 80);
780                                                         }
781 # endif                                                 
782                                                         vram_draw_table[displine] = true;
783                                                 }
784                                         } else {
785 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
786                                                 int planes = 2;
787 # elif defined(_FM77AV40)
788                                                 int planes = 1;
789 # else
790                                                 int planes = 1;
791 #endif
792                                                 if(vram_wrote_table[displine] || vram_wrote) {
793                                                         uint32  baseaddr1 = (displine * 80) & 0x3fff;
794                                                         uint32  baseaddr2 = baseaddr1 + 0xc000;
795                                                         vram_wrote_table[displine] = false;
796                                                         for(int i = 0; i < planes; i++) {
797                                                                 for(int j = 0; j < 3; j++) {
798                                                                         memcpy(&gvram_shadow[j * 0x4000 + baseaddr1],
799                                                                                    &gvram[j * 0x4000 + baseaddr1], 80);
800                                                                         memcpy(&gvram_shadow[j * 0x4000 + baseaddr2],
801                                                                                    &gvram[j * 0x4000 + baseaddr2], 80);
802                                                                 }
803                                                                 baseaddr1 += 0x18000;
804                                                                 baseaddr2 += 0x18000;
805                                                         }
806 # if defined(_FM77AV40)
807                                                         for(int j = 0; j < 3; j++) {
808                                                                 memcpy(&gvram_shadow[j * 0x4000 + baseaddr1],
809                                                                    &gvram[j * 0x4000 + baseaddr1], 80);
810                                                         }
811 # endif
812                                                         vram_draw_table[displine] = true;
813                                                 }
814                                         }
815                                 }
816                         }
817                         //vram_wrote_shadow = true;
818                         displine++;
819                         break;
820                 case EVENT_FM7SUB_VSTART: // Call first.
821                         vblank = true;
822                         vsync = false;
823                         hblank = false;
824                         displine = 0;
825                         //leave_display();
826                         // Parameter from XM7/VM/display.c , thanks, Ryu.
827                         mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
828                         mainio->write_signal(SIG_DISPLAY_VSYNC, 0x00, 0xff);
829                         if(vblank_count != 0) {
830                                 if(display_mode == DISPLAY_MODE_8_400L) {
831                                         usec = (0.98 + 16.4) * 1000.0;
832                                 } else {
833                                         usec = (1.91 + 12.7) * 1000.0;
834                                 }
835                                 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
836
837                                 if(display_mode == DISPLAY_MODE_8_400L) {
838                                         usec = 930.0; // 939.0
839                                 } else {
840                                         usec = 1840.0; // 1846.5
841                                 }
842                                 offset_point_bank1_bak = offset_point_bank1;
843                                 offset_point_bak = offset_point;
844                                 if(vram_wrote || ((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0)) {
845                                         //for(int i = 0; i < 411; i++) vram_wrote_table[i] = false;
846                                 }
847                                 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
848                                 vblank_count = 0;
849                         } else {
850                                 if(display_mode == DISPLAY_MODE_8_400L) {
851                                         usec = 0.34 * 1000.0;
852                                 } else {
853                                         usec = 1.52 * 1000.0;
854                                 }
855                                 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
856                                 vblank_count++;
857                         }
858                         break;
859         case EVENT_FM7SUB_VSYNC:
860                 vblank = true;
861                 hblank = false;
862                 vsync = true;
863                 displine = 0;
864                 if(display_mode == DISPLAY_MODE_8_400L) {
865                         usec = 0.33 * 1000.0; 
866                 } else {
867                         usec = 0.51 * 1000.0;
868                 }
869                 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x01, 0xff);
870                 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
871                 if(vram_wrote || ((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0)) {
872                         //for(int i = 0; i < 411; i++) vram_wrote_table[i] = false;
873                         memcpy(gvram_shadow, gvram, sizeof(gvram_shadow));
874                         vram_wrote_shadow = true;
875                         vram_wrote = false;
876                         for(int i = 0; i < 411; i++) vram_draw_table[i] = true;
877                 } else {
878                         if((display_mode == DISPLAY_MODE_4096) || (display_mode == DISPLAY_MODE_256k)){
879                                 int planes;
880                                 bool ff;
881 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
882                                 planes = 24;
883 # elif defined(_FM77AV40)
884                                 planes = 18;
885 # else
886                                 planes = 12;
887 # endif
888                                 ff = vram_wrote;
889                                 if(!ff) {
890                                         for(int j = 200; j < 206; j++) {
891                                                 if(vram_wrote_table[j]) {
892                                                         ff = true;
893                                                 }
894                                                 vram_wrote_table[j] = false;
895                                         }
896                                 }
897                                 if(ff) {
898                                         for(int j = 200; j < 205; j++) {
899                                                 vram_draw_table[(((j * 40) + offset_point_bak) & 0x1fff) / 40] = true;
900                                                 vram_draw_table[(((j * 40) + offset_point_bank1_bak) & 0x1fff) / 40] = true;
901                                         }
902                                         for(int i = 0; i < planes; i++) memcpy(&gvram_shadow[i * 0x2000 + 200 * 40],
903                                                                                                                    &gvram[i * 0x2000 + 200 * 40], 0x2000 - 200 * 40);
904                                 }
905                         } else if(display_mode == DISPLAY_MODE_8_400L) {
906                                 int planes;
907                                 bool ff;
908 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
909                                 planes = 6;
910 # elif defined(_FM77AV40)
911                                 planes = 3;
912 # else
913                                 planes = 0;
914 # endif
915                                 ff = vram_wrote;
916                                 if(!ff) {
917                                         for(int j = 400; j < 411; j++) {
918                                                 if(vram_wrote_table[j]) {
919                                                         ff = true;
920                                                 }
921                                                 vram_wrote_table[j] = false;
922                                         }
923                                 }
924                                 if(ff) {
925                                         for(int j = 400; j < 410; j++) {
926                                                 vram_draw_table[(((j * 80) + offset_point_bak) & 0x7fff) / 80] = true;
927                                                 vram_draw_table[(((j * 80) + offset_point_bank1_bak) & 0x7fff) / 80] = true;
928                                         }
929                                         for(int i = 0; i < planes; i++) memcpy(&gvram_shadow[i * 0x8000 + 400 * 80],
930                                                                                                                    &gvram[i * 0x8000 + 400 * 80], 0x8000 - 400 * 80);
931                                 }
932                         } else {
933                                 int planes;
934                                 bool ff;
935 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
936                                 planes = 12;
937 # elif defined(_FM77AV40)
938                                 planes = 9;
939 # else
940                                 planes = 6;
941 # endif
942                                 ff = vram_wrote;
943                                 if(!ff) {
944                                         for(int j = 200; j < 206; j++) {
945                                                 if(vram_wrote_table[j]) {
946                                                         ff = true;
947                                                 }
948                                                 vram_wrote_table[j] = false;
949                                         }
950                                 }
951                                 if(ff) {
952                                         for(int j = 200; j < 205; j++) {
953                                                 vram_draw_table[(((j * 80) + offset_point_bak) & 0x3fff) / 80] = true;
954                                                 vram_draw_table[(((j * 80) + offset_point_bank1_bak) & 0x3fff) / 80] = true;
955                                         }
956                                         for(int i = 0; i < planes; i++) memcpy(&gvram_shadow[i * 0x4000 + 200 * 80],
957                                                                                                                    &gvram[i * 0x4000 + 200 * 80], 0x4000 - 200 * 80);
958                                 }
959                         }
960                 }
961                 if(vram_wrote) {
962                         vram_wrote_shadow = true;
963                 } else {
964                         int fy = false;
965                         if(display_mode == DISPLAY_MODE_8_400L) {
966                                 for(int yy = 0; yy < 400; yy++) {
967                                         if(vram_draw_table[yy]) fy = true;
968                                         vram_draw_table[yy] = false;
969                                 }
970                         } else {
971                                 for(int yy = 0; yy < 200; yy++) {
972                                         if(vram_draw_table[yy]) fy = true;
973                                 vram_draw_table[yy] = false;
974                                 }
975                         }
976                         vram_wrote_shadow = fy;
977                 }
978                 vram_wrote = false;
979                 break;
980 #endif                  
981         case EVENT_FM7SUB_CLR_BUSY:
982                 set_subbusy();
983                 break;
984         case EVENT_FM7SUB_CLR_CRTFLAG:
985                 reset_crtflag();
986                 break;
987         }
988 }
989
990 void DISPLAY::event_frame()
991 {
992         enter_display();
993 }
994
995 void DISPLAY::event_vline(int v, int clock)
996 {
997 }
998
999
1000 uint32 DISPLAY::read_signal(int id)
1001 {
1002         uint32 retval = 0;
1003         switch(id) {
1004                 case SIG_FM7_SUB_HALT:
1005                 case SIG_DISPLAY_HALT:
1006                         retval = (halt_flag) ? 0xffffffff : 0;
1007                         break;
1008                 case SIG_DISPLAY_BUSY:
1009                         retval =  (sub_busy) ? 0x80 : 0;
1010                         break;
1011                 case SIG_DISPLAY_MULTIPAGE:
1012                         retval =  multimode_accessmask;
1013                         break;
1014                 case SIG_DISPLAY_PLANES:
1015                         retval = 3;
1016                         break;
1017 #if defined(_FM77AV_VARIANTS)
1018                 case SIG_DISPLAY_VSYNC:
1019                         retval = (vsync) ? 0x01 : 0x00;
1020                         break;
1021                 case SIG_DISPLAY_DISPLAY:
1022                         retval = (!hblank) ? 0x02: 0x00;
1023                         break;
1024                 case SIG_FM7_SUB_BANK: // Main: FD13
1025                         retval = subrom_bank & 0x03;
1026 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1027                         if(monitor_ram) retval |= 0x04;
1028 #endif
1029                         break;
1030 #endif                  
1031 #if defined(_FM77AV_VARIANTS)
1032                 case SIG_DISPLAY_MODE320:
1033                         retval = (mode320) ? 0x40: 0x00;
1034                         break;
1035 #endif
1036                 case SIG_DISPLAY_Y_HEIGHT:
1037 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1038                         retval = (mode400line) ? 400 : 200;
1039 #else
1040                         retval = 200;
1041 #endif            
1042                         break;
1043                 case SIG_DISPLAY_X_WIDTH:
1044 #if defined(_FM77AV_VARIANTS)
1045 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1046                         retval = (mode320 || mode256k) ? 40 : 80;
1047 # else
1048                         retval = (mode320) ? 40 : 80;
1049 # endif    
1050 #else
1051                         retval = 640;
1052 #endif            
1053                         break;
1054                 default:
1055                         break;
1056         }
1057         return retval;
1058 }
1059
1060 void DISPLAY::write_signal(int id, uint32 data, uint32 mask)
1061 {
1062         bool flag = ((data & mask) != 0);
1063         int y;
1064         switch(id) {
1065                 case SIG_FM7_SUB_HALT:
1066                         if(flag) {
1067                                 sub_busy = true;
1068                         }
1069                         halt_flag = flag;
1070                         //mainio->write_signal(SIG_FM7_SUB_HALT, data, mask);
1071                         break;
1072                 case SIG_DISPLAY_HALT:
1073                         if(flag) {
1074                                 halt_subsystem();
1075                         } else {
1076                                 restart_subsystem();
1077                         }
1078                         break;
1079                 case SIG_FM7_SUB_CANCEL:
1080                         if(flag) {
1081                                 cancel_request = true;
1082                                 do_irq(true);
1083                         }
1084                         break;
1085                 case SIG_DISPLAY_CLOCK:
1086                         if(clock_fast != flag) {
1087                                 uint32 clk;
1088                                 if(flag) {
1089                                         clk = SUBCLOCK_NORMAL;
1090                                 } else {
1091                                         clk = SUBCLOCK_SLOW;
1092                                 }
1093                                 if((config.dipswitch & FM7_DIPSW_CYCLESTEAL) == 0) clk = clk / 3;
1094                                 if(clk != prev_clock) p_vm->set_cpu_clock(subcpu, clk);
1095                                 clock_fast = flag;
1096                                 prev_clock = clk;
1097                         }
1098                         break;
1099 #if defined(_FM77AV_VARIANTS)
1100                 case SIG_FM7_SUB_BANK: // Main: FD13
1101                         set_monitor_bank(data & 0xff);
1102                         break;
1103 #endif                  
1104                 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1105 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1106                         {
1107                                 int oldmode = display_mode;
1108                                 kanjisub = ((data & 0x20) == 0) ? true : false;
1109                                 mode256k = ((data & 0x10) != 0) ? true : false;
1110                                 mode400line = ((data & 0x08) != 0) ? false : true;
1111                                 ram_protect = ((data & 0x04) != 0) ? false : true;
1112                                 if(mode400line) {
1113                                         display_mode = DISPLAY_MODE_8_400L;
1114                                 } else if(mode256k) {
1115                                         display_mode = DISPLAY_MODE_256k;
1116                                 } else {
1117                                         display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1118                                 }
1119                                 if(oldmode != display_mode) {
1120                                         for(y = 0; y < 400; y++) memset(emu->screen_buffer(y), 0x00, 640 * sizeof(scrntype));
1121                                         vram_wrote = true;
1122                                         alu->write_signal(SIG_ALU_X_WIDTH, ((mode320 || mode256k) && !(mode400line)) ? 40 :  80, 0xffff);
1123                                         alu->write_signal(SIG_ALU_Y_HEIGHT, (mode400line) ? 400 : 200, 0xffff);
1124                                         alu->write_signal(SIG_ALU_400LINE, (mode400line) ? 0xff : 0x00, 0xff);
1125                                         frame_skip_count = 3;
1126                                 }
1127                         }
1128 #elif defined(_FM77_VARIANTS)
1129                         {
1130                                 int oldmode = display_mode;
1131                                 kanjisub = ((data & 0x20) == 0) ? true : false;
1132 # if defined(_FM77L4)                           
1133                                 stat_400linecard = ((data & 0x20) != 0) ? true : false;
1134                                 mode400line = ((data & 0x08) != 0) ? false : true;
1135                                 if(mode400line && stat_400linecard) {
1136                                         display_mode = DISPLAY_MODE_8_400L_TEXT;
1137                                 } else if(stat_400linecard) {
1138                                         display_mode = DISPLAY_MODE_8_200L_TEXT;
1139                                 } else {
1140                                         display_mode = DISPLAY_MODE_8_200L;
1141                                 }
1142 # endif                         
1143                         }                       
1144 #endif
1145                         break;
1146 #if defined(_FM77AV_VARIANTS)
1147                 case SIG_DISPLAY_MODE320: // FD12 bit 6
1148 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1149                         {
1150                                 int oldmode = display_mode;
1151                                 mode320 = flag;
1152                                 if((!mode400line) && (!mode256k)){
1153                                         display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1154                                 }
1155                                 if(oldmode != display_mode) {
1156                                         for(y = 0; y < 400; y++) memset(emu->screen_buffer(y), 0x00, 640 * sizeof(scrntype));
1157                                         vram_wrote = true;
1158                                         alu->write_signal(SIG_ALU_X_WIDTH, ((mode320 || mode256k) && !(mode400line)) ? 40 :  80, 0xffff);
1159                                         alu->write_signal(SIG_ALU_Y_HEIGHT, (mode400line) ? 400 : 200, 0xffff);
1160                                         alu->write_signal(SIG_ALU_400LINE, (mode400line) ? 0xff : 0x00, 0xff);
1161                                         frame_skip_count = 3;
1162                                 }
1163                         }
1164 # else
1165                         if(mode320 != flag) {
1166                                 for(y = 0; y < 400; y++) memset(emu->screen_buffer(y), 0x00, 640 * sizeof(scrntype));
1167                         }
1168                         mode320 = flag;
1169                         display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1170                         alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 :  80, 0xffff);
1171                         alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1172                         alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
1173                         vram_wrote = true;
1174 # endif
1175 #endif                  
1176                         break;
1177                 case SIG_DISPLAY_MULTIPAGE:
1178                         set_multimode(data);
1179                         break;
1180                 case SIG_FM7_SUB_KEY_MASK:
1181                         if(firq_mask == flag) {
1182                                 do_firq(!flag && key_firq_req);
1183                         }
1184                         firq_mask = !flag;
1185                         break;
1186                 case SIG_FM7_SUB_KEY_FIRQ:
1187                         do_firq(flag & !(firq_mask));
1188                         key_firq_req = flag;
1189                         break;
1190                 case SIG_FM7_SUB_USE_CLR:
1191                         if(flag) {
1192                                 clr_count = data & 0x03;
1193                         } else {
1194                                 clr_count = 0;
1195                         }
1196                         break;
1197                 default:
1198                         break;
1199         }
1200 }
1201    
1202 /*
1203  * Vram accessing functions moved to vram.cpp .
1204  */
1205
1206 uint8 DISPLAY::read_mmio(uint32 addr)
1207 {
1208         uint32 retval = 0xff;
1209         uint32 raddr;   
1210         if(addr < 0xd400) return 0xff;
1211         
1212 #if !defined(_FM77AV_VARIANTS)
1213         raddr = (addr - 0xd400) & 0x000f;
1214 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
1215         raddr = (addr - 0xd400) & 0x003f;
1216 #else // FM77AV40EX || FM77AV40SX
1217         raddr = (addr - 0xd400) & 0x00ff;
1218 #endif
1219         switch(raddr) {
1220                 case 0x00: // Read keyboard
1221                         retval = (keyboard->read_data8(0x00) != 0) ? 0xff : 0x7f;
1222                         break;
1223                 case 0x01: // Read keyboard
1224                         retval = keyboard->read_data8(0x01) & 0xff;
1225                         break;
1226                 case 0x02: // Acknowledge
1227                         acknowledge_irq();
1228                         break;
1229                 case 0x03:
1230                         beep();
1231                         break;
1232                 case 0x04:
1233                         attention_irq();
1234                         break;
1235 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1236      defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
1237                 case 0x06:
1238                         if(!kanjisub) return 0xff;
1239 # if !defined(_FM77_VARIANTS)
1240                         if(kanji_level2) {
1241                                 return (uint8)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1242                         }
1243 # endif
1244                         retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1245                         break;
1246                 case 0x07:
1247                         if(!kanjisub) return 0xff;
1248 # if !defined(_FM77_VARIANTS)
1249                         if(kanji_level2) {
1250                                 return (uint8)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1251                         }
1252 # endif
1253                         retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1254                         break;
1255 #endif
1256                 case 0x08:
1257                         set_crtflag();
1258                         break;
1259                 case 0x09:
1260                         retval = set_vramaccess();
1261                         break;
1262                 case 0x0a:
1263                         reset_subbusy();
1264                         break;
1265                 case 0x0d:
1266                         keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
1267                         break;
1268 #if defined(_FM77AV_VARIANTS)
1269                 // ALU
1270                 case 0x10:
1271                         retval = alu->read_data8(ALU_CMDREG);
1272                         break;
1273                 case 0x11:
1274                         retval = alu->read_data8(ALU_LOGICAL_COLOR);
1275                         break;
1276                 case 0x12:
1277                         retval = alu->read_data8(ALU_WRITE_MASKREG);
1278                         break;
1279                 case 0x13:
1280                         retval = alu->read_data8(ALU_CMP_STATUS_REG);
1281                         break;
1282                 case 0x1b:
1283                         retval = alu->read_data8(ALU_BANK_DISABLE);
1284                         break;
1285 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1286                 case 0x2f: // VRAM BANK
1287                         retval = 0xfc | (vram_bank & 0x03);
1288                         break;
1289 # endif                 
1290                 // MISC
1291                 case 0x30:
1292                         retval = get_miscreg();
1293                         break;
1294                 // KEY ENCODER.
1295                 case 0x31:
1296                         retval = keyboard->read_data8(0x31);
1297                         break;
1298                 case 0x32:
1299                         retval = keyboard->read_data8(0x32);
1300                         break;
1301 #endif                          
1302                 default:
1303                         break;
1304         }
1305         return (uint8)retval;
1306 }
1307
1308 uint32 DISPLAY::read_vram_data8(uint32 addr)
1309 {
1310         uint32 offset;
1311         uint32 page_offset = 0;
1312         uint32 page_mask = 0x3fff;
1313         uint32 color = (addr >> 14) & 0x03;
1314         uint32 pagemod;
1315         
1316 #if defined(_FM77AV_VARIANTS)
1317         if (active_page != 0) {
1318                 offset = offset_point_bank1;
1319         } else {
1320                 offset = offset_point;
1321         }
1322 #else
1323         offset = offset_point;
1324 #endif
1325                 
1326 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1327 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1328                 if(vram_active_block != 0) page_offset = 0x18000;
1329 # endif         
1330                 if(display_mode == DISPLAY_MODE_8_400L) {
1331                         if(addr >= 0x8000) return 0xff;
1332                         color = vram_bank & 0x03;
1333                         if(color > 2) color = 0;
1334                         offset <<= 1;
1335                         pagemod = 0x8000 * color;
1336                         return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
1337                 } else {
1338                         if(mode256k) {
1339 #if defined(_FM77AV40)
1340                                 if(vram_bank < 3) {
1341                                         page_offset = 0xc000 * (vram_bank & 0x03);
1342                                 } else {
1343                                         page_offset = 0; // right?
1344                                 }
1345 #else                   
1346                                 page_offset = 0xc000 * (vram_bank & 0x03);
1347 #endif                  
1348                                 page_mask = 0x1fff;
1349                                 pagemod = addr & 0xe000;
1350                         } else {
1351                                 if(mode320) {
1352                                         page_mask = 0x1fff;
1353                                         pagemod = addr & 0xe000;
1354                                 } else {
1355                                         pagemod = addr & 0xc000;
1356                                 }
1357                                 if(active_page != 0) {
1358                                         page_offset += 0xc000;
1359                                 }
1360                         }                               
1361                         return gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1362                 }
1363 #elif defined(_FM77AV_VARIANTS)
1364                 {               
1365                         if(active_page != 0) {
1366                                 page_offset += 0xc000;
1367                         }
1368                         if(mode320) {
1369                                 page_mask = 0x1fff;
1370                                 pagemod = addr & 0xe000;
1371                         } else {
1372                                 pagemod = addr & 0xc000;
1373                         }
1374                         return gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1375                 }
1376 #elif defined(_FM77L4) //_FM77L4
1377                 {
1378                         if(display_mode == DISPLAY_MODE_8_400L) {
1379                                 return (uint32)read_vram_l4_400l(addr, offset);
1380                         } else {
1381                                 pagemod = addr & 0xc000;
1382                                 return gvram[((addr + offset) & 0x3fff) | pagemod];
1383                         }
1384                         return 0xff;
1385                 }
1386 #else // Others (77/7/8)
1387                 pagemod = addr & 0xc000;
1388                 return gvram[((addr + offset) & 0x3fff) | pagemod];
1389 #endif
1390 }
1391
1392 void DISPLAY::write_dma_data8(uint32 addr, uint32 data)
1393 {
1394         uint32 raddr = addr & 0xffff;
1395         uint32 color;
1396         if(addr < 0xc000) {
1397 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1398                 if(display_mode == DISPLAY_MODE_8_400L) {
1399                         color = vram_bank & 0x03;
1400                         if(color > 2) color = 0;
1401                 } else {
1402                         color = (addr >> 14) & 0x03;
1403                 }
1404 # endif
1405                 if((multimode_accessmask & (1 << color)) != 0) return;
1406                 return write_vram_data8(raddr, (uint8)data);
1407         } else {
1408                 return write_data8_main(raddr, (uint8)data);
1409         }
1410 }
1411
1412
1413 void DISPLAY::write_vram_data8(uint32 addr, uint8 data)
1414 {
1415         uint32 offset;
1416         uint32 page_offset = 0;
1417         uint32 page_mask = 0x3fff;
1418         uint32 color = (addr >> 14) & 0x03;
1419         uint32 pagemod;
1420         
1421 #if defined(_FM77AV_VARIANTS)
1422         if (active_page != 0) {
1423                 offset = offset_point_bank1;
1424         } else {
1425                 offset = offset_point;
1426         }
1427 #else
1428         offset = offset_point;
1429 #endif
1430
1431 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1432 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1433                 if(vram_active_block != 0) page_offset = 0x18000;
1434 # endif         
1435                 if(display_mode == DISPLAY_MODE_8_400L) {
1436                         if(addr >= 0x8000) return;
1437                         color = vram_bank & 0x03;
1438                         if(color > 2) color = 0;
1439                         offset <<= 1;
1440                         pagemod = 0x8000 * color;
1441                         gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset] = data;
1442                         vram_wrote_table[((addr + offset) % 0x8000) / 80] = true;
1443                 } else  if(display_mode == DISPLAY_MODE_256k) {
1444 #if defined(_FM77AV40)
1445                         if(vram_bank < 3) {
1446                                 page_offset = 0xc000 * (vram_bank & 0x03);
1447                         } else {
1448                                 page_offset = 0; // right?
1449                         }
1450 #else                   
1451                         page_offset = 0xc000 * (vram_bank & 0x03);
1452 #endif                  
1453                         page_mask = 0x1fff;
1454                         pagemod = addr & 0xe000;
1455                         gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1456                         vram_wrote_table[((addr + offset) % 0x2000) / 40] = true;
1457                         return;
1458                 } else if(display_mode == DISPLAY_MODE_4096) {
1459                         if(active_page != 0) {
1460                                 page_offset += 0xc000;
1461                         }
1462                         page_mask = 0x1fff;
1463                         pagemod = addr & 0xe000;
1464                         gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1465                         vram_wrote_table[((addr + offset) % 0x2000) / 40] = true;
1466                 } else { // 200line
1467                         if(active_page != 0) {
1468                                 page_offset += 0xc000;
1469                         }
1470                         page_mask = 0x3fff;
1471                         pagemod = addr & 0xc000;
1472                         gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1473                         vram_wrote_table[((addr + offset) % 0x4000) / 80] = true;
1474                 }                               
1475
1476 #elif defined(_FM77AV_VARIANTS)
1477                 if(display_mode == DISPLAY_MODE_4096) {
1478                         if(active_page != 0) {
1479                                 page_offset = 0xc000;
1480                         }
1481                         page_mask = 0x1fff;
1482                         pagemod = addr & 0xe000;
1483                         gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1484                         vram_wrote_table[((addr + offset) % 0x2000) / 40] = true;
1485                 } else { // 200line
1486                         if(active_page != 0) {
1487                                 page_offset = 0xc000;
1488                         }
1489                         page_mask = 0x3fff;
1490                         pagemod = addr & 0xc000;
1491                         gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1492                         vram_wrote_table[((addr + offset) % 0x4000) / 80] = true;
1493                 }
1494 #elif defined(_FM77L4) //_FM77L4
1495                 {
1496                         if(display_mode == DISPLAY_MODE_8_400L) {
1497                                 write_vram_l4_400l(addr, data, offset);
1498                         } else {
1499                                 pagemod = addr & 0xc000;
1500                                 gvram[((addr + offset) & 0x3fff) | pagemod] = data;
1501                         }
1502                         //vram_wrote_table[((addr + offset) % 0x4000) / 80] = true;
1503                 }
1504 #else // Others (77/7/8)
1505                 pagemod = addr & 0xc000;
1506                 gvram[((addr + offset) & 0x3fff) | pagemod] = data;
1507                 //vram_wrote_table[((addr + offset) % 0x4000) / 80] = true;
1508 #endif
1509
1510 #if defined(_FM77AV_VARIANTS)   
1511         if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
1512 #else
1513         vram_wrote = true;
1514 #endif  
1515 }
1516
1517 uint32 DISPLAY::read_data8_main(uint32 addr)
1518 {
1519         uint32 raddr;
1520         if(addr < 0xc000) return 0xff;
1521         if(addr < 0xd000) { 
1522                 raddr = addr - 0xc000;
1523 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1524                 if(monitor_ram) {
1525                         if(console_ram_bank >= 1) {
1526                                 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
1527                         }
1528                 }
1529 #endif
1530                 return console_ram[raddr];
1531         } else if(addr < 0xd380) {
1532                 raddr = addr - 0xd000;
1533                 return work_ram[raddr];
1534         } else if(addr < 0xd400) {
1535                 raddr = addr - 0xd380;
1536                 return shared_ram[raddr];
1537         } else  if(addr < 0xd800) {
1538 #if defined(_FM77AV_VARIANTS)
1539                 if(addr >= 0xd500) {
1540                         return submem_hidden[addr - 0xd500];
1541                 }
1542 #endif     
1543                 return read_mmio(addr);
1544         } else if(addr < 0x10000) {
1545 #if !defined(_FM77AV_VARIANTS)
1546                 return subsys_c[addr - 0xd800];
1547 #else
1548                 if(addr < 0xe000) {
1549 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
1550                         if(monitor_ram) {
1551                                 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
1552                         }
1553 #endif          
1554                         return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
1555                 } else if(addr < 0x10000) {
1556 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
1557                         if(monitor_ram) {
1558                                 return subsys_ram[addr - 0xe000];
1559                         }
1560 #endif          
1561                         switch(subrom_bank_using & 3) {
1562                         case 0: // SUBSYS_C
1563                                 return subsys_c[addr - 0xd800];
1564                                 break;
1565                         case 1:
1566                                 return subsys_a[addr - 0xe000];
1567                                 break;
1568                         case 2:
1569                                 return subsys_b[addr - 0xe000];
1570                                 break;
1571                         default:
1572                                 return subsys_cg[addr - 0xe000];
1573                                 break;
1574                         }
1575                 }
1576 #endif
1577         }
1578         return 0xff;
1579 }
1580
1581 uint32 DISPLAY::read_dma_data8(uint32 addr)
1582 {
1583         uint32 raddr = addr & 0xffff;
1584         uint32 color;
1585         if(addr < 0xc000) {
1586 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1587                 if(display_mode == DISPLAY_MODE_8_400L) {
1588                         color = vram_bank & 0x03;
1589                         if(color > 2) color = 0;
1590                 } else {
1591                         color = (addr >> 14) & 0x03;
1592                 }
1593 # endif
1594                 if((multimode_accessmask & (1 << color)) != 0) return 0xff;
1595                 return read_vram_data8(raddr);
1596         } else {
1597                 return read_data8_main(raddr);
1598         }
1599 }
1600
1601
1602 uint32 DISPLAY::read_data8(uint32 addr)
1603 {
1604         uint32 raddr = addr;
1605         uint32 offset;
1606         uint32 color = (addr & 0x0c000) >> 14;
1607         if(addr < 0xc000) {
1608 #if defined(_FM77AV_VARIANTS)
1609                 if(use_alu) {
1610                         alu->read_data8(addr + ALU_WRITE_PROXY);
1611                 }
1612 #endif
1613 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1614                 if(display_mode == DISPLAY_MODE_8_400L) {
1615                         color = vram_bank & 0x03;
1616                         if(color > 2) color = 0;
1617                 } else {
1618                         color = (addr >> 14) & 0x03;
1619                 }
1620 # endif
1621                 if((multimode_accessmask & (1 << color)) != 0) return 0xff;
1622                 return read_vram_data8(addr);
1623         } else if(addr < 0x10000) {
1624                 return read_data8_main(addr);
1625         } else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
1626                 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
1627         }
1628 #if defined(_FM77AV_VARIANTS)
1629         // ACCESS VIA ALU.
1630         else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
1631                 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
1632 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)         
1633                 if(display_mode == DISPLAY_MODE_8_400L) {
1634                         uint32 page_offset = 0;
1635 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1636                         if(vram_active_block != 0) page_offset = 0x18000;
1637 # endif         
1638                         color = (addr & 0x18000) >> 15;
1639                         if(color > 2) color = 0;
1640                         
1641                         if (active_page != 0) {
1642                                 offset = offset_point_bank1 << 1;
1643                         } else {
1644                                 offset = offset_point << 1;
1645                         }
1646                         if(color > 2) color = 0;
1647                         uint32 pagemod = 0x8000 * color;
1648                         return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
1649                 }
1650 # endif         
1651                 return read_vram_data8(addr);
1652         }
1653 #endif
1654         return 0xff;
1655 }       
1656
1657 /*
1658  * Vram accessing functions moved to vram.cpp .
1659  */
1660
1661 void DISPLAY::write_mmio(uint32 addr, uint32 data)
1662 {
1663         uint8 rval = 0;
1664         pair tmpvar;
1665         if(addr < 0xd400) return;
1666         
1667 #if !defined(_FM77AV_VARIANTS)
1668         addr = (addr - 0xd400) & 0x000f;
1669 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
1670         addr = (addr - 0xd400) & 0x003f;
1671 #else // FM77AV40EX || FM77AV40SX
1672         addr = (addr - 0xd400) & 0x00ff;
1673 #endif
1674         io_w_latch[addr] = (uint8)data;
1675         switch(addr) {
1676 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
1677                 // FM77 SPECIFIED
1678                 case 0x05:
1679                         set_cyclesteal((uint8)data);
1680                         break;
1681 #endif
1682 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1683      defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
1684                 // KANJI
1685                 case 0x06:
1686                         if(!kanjisub) return;
1687                         kanjiaddr.w.h = 0x0000;
1688                         kanjiaddr.b.h = (uint8) data;
1689                         break;
1690                 case 0x07:
1691                         if(!kanjisub) return;
1692                         kanjiaddr.w.h = 0x0000;
1693                         kanjiaddr.b.l = (uint8)data;
1694                         break;
1695 #endif                  
1696                 // CRT OFF
1697                 case 0x08:
1698                         reset_crtflag();
1699                         break;
1700                 // VRAM ACCESS
1701                 case 0x09:
1702                         reset_vramaccess();
1703                         break;
1704                 // BUSY
1705                 case 0x0a:
1706                         if(clr_count <= 0) {
1707                                 set_subbusy();
1708                         } else { // Read once when using clr_foo() to set busy flag.
1709                                 double usec;
1710                                 if(clock_fast) {
1711                                         usec = (1000.0 * 1000.0) / 2000000.0;
1712                                 } else {
1713                                         usec = (1000.0 * 1000.0) / 999000.0;
1714                                 }
1715                                 if(!is_cyclesteal) usec = usec * 3.0;
1716                                 usec = (double)clr_count * usec;
1717                                 register_event(this, EVENT_FM7SUB_CLR_BUSY, usec, false, NULL); // NEXT CYCLE_
1718                                 reset_subbusy();
1719                                 clr_count = 0;
1720                         }
1721                         break;
1722                 // LED
1723                 case 0x0d:
1724                         keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
1725                         break;
1726                 // OFFSET
1727                 case 0x0e:
1728                 case 0x0f:
1729                         rval = (uint8)data;
1730                         if(offset_changed[active_page]) {
1731 #if defined(_FM77AV_VARIANTS)
1732                                 if(active_page != 0) {
1733                                         tmp_offset_point[active_page].d = offset_point_bank1;
1734                                 } else {
1735                                         tmp_offset_point[active_page].d = offset_point;
1736                                 }
1737 #else
1738                                 tmp_offset_point[active_page].d = offset_point;
1739 #endif
1740                         }
1741                         tmp_offset_point[active_page].w.h = 0x0000;
1742                         if(addr == 0x0e) {
1743                                 tmp_offset_point[active_page].b.h = rval;
1744                         } else {
1745                                 tmp_offset_point[active_page].b.l = rval;
1746                         }
1747                         offset_changed[active_page] = !offset_changed[active_page];
1748                         if(offset_changed[active_page]) {
1749                                 vram_wrote = true;
1750 #if defined(_FM77AV_VARIANTS)
1751                                 if(active_page != 0) {
1752                                         if(offset_77av) {
1753                                                 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
1754                                         } else {
1755                                                 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
1756                                         }                                  
1757                                 } else {
1758                                         if(offset_77av) {
1759                                                 offset_point = tmp_offset_point[active_page].d & 0x007fff;
1760                                         } else {
1761                                                 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
1762                                         }                                  
1763                                 }
1764 #else
1765                                 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
1766 #endif                             
1767                         }
1768                         break;
1769 #if defined(_FM77AV_VARIANTS)
1770                 // ALU
1771                 case 0x10:
1772                         alu_write_cmdreg(data);
1773                         break;
1774                 case 0x11:
1775                         alu_write_logical_color(data);
1776                         break;
1777                 case 0x12:
1778                         alu_write_mask_reg(data);
1779                         break;
1780                 case 0x1b:
1781                         alu_write_disable_reg(data);
1782                         break;
1783                 case 0x20:
1784                         alu_write_offsetreg_hi(data);
1785                         break;
1786                 case 0x21:
1787                         alu_write_offsetreg_lo(data);
1788                         break;
1789                 case 0x22:
1790                         alu_write_linepattern_hi(data);
1791                         break;
1792                 case 0x23:
1793                         alu_write_linepattern_lo(data);
1794                         break;
1795 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1796                 case 0x2e: //
1797                         console_ram_bank = (data & 0x18) >> 3;
1798                         if(console_ram_bank > 2) console_ram_bank = 0;
1799                         cgram_bank = data & 0x07;
1800                         kanji_level2 = ((data & 0x80) == 0) ? false : true;
1801                         break;
1802                 case 0x2f: // VRAM BANK
1803                         vram_bank = data &  0x03;
1804                         if(vram_bank > 2) vram_bank = 0;
1805                         vram_wrote = true;
1806                         break;
1807 # endif                 
1808                 // MISC
1809                 case 0x30:
1810                         set_miscreg(data);
1811                         break;
1812                 // KEYBOARD ENCODER
1813                 case 0x31:
1814                         keyboard->write_data8(0x31, data);
1815                         break;
1816 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1817                 case 0x33: //
1818                         vram_active_block = data & 0x01;
1819                         if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
1820                         vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
1821                         break;
1822                         // Window
1823                 case 0x38: //
1824                 case 0x39: //
1825                         tmpvar.d = window_xbegin * 8;
1826                         tmpvar.w.h = 0;
1827                         if(addr == 0x38) {
1828                                 tmpvar.b.h = data & 0x03;
1829                         } else {
1830                                 tmpvar.b.l = data & 0xf8;
1831                         }
1832                         if(mode320 || mode256k) {
1833                            if(tmpvar.d > 320) tmpvar.d = 320;
1834                         } else {
1835                            if(tmpvar.d > 640) tmpvar.d = 640;
1836                         }
1837                         window_xbegin = tmpvar.d / 8;
1838                         vram_wrote = true;
1839                         break;
1840                 case 0x3a: //
1841                 case 0x3b: //
1842                         tmpvar.d = window_xend * 8;
1843                         tmpvar.w.h = 0;
1844                         if(addr == 0x3a) {
1845                                 tmpvar.b.h = data & 0x03;
1846                         } else {
1847                                 tmpvar.b.l = data & 0xf8;
1848                         }
1849                         if(mode320 || mode256k) {
1850                            if(tmpvar.d > 320) tmpvar.d = 320;
1851                         } else {
1852                            if(tmpvar.d > 640) tmpvar.d = 640;
1853                         }
1854                         window_xend = tmpvar.d / 8;
1855                         vram_wrote = true;
1856                         break;
1857                 case 0x3c: //
1858                 case 0x3d: //
1859                         tmpvar.d = window_low;
1860                         tmpvar.w.h = 0;
1861                         if(addr == 0x3c) {
1862                                 tmpvar.b.h = data & 0x03;
1863                         } else {
1864                                 tmpvar.b.l = data & 0xff;
1865                         }
1866                         if(mode400line) {
1867                                 if(tmpvar.d > 400) tmpvar.d = 400;
1868                         } else {
1869                                 tmpvar.d <<= 1;
1870                                 if(tmpvar.d > 400) tmpvar.d = 400;
1871                         }
1872                         window_low = tmpvar.d;
1873                         vram_wrote = true;
1874                         break;
1875                 case 0x3e: //
1876                 case 0x3f: //
1877                         tmpvar.d = window_high;
1878                         tmpvar.w.h = 0;
1879                         if(addr == 0x3e) {
1880                                 tmpvar.b.h = data & 0x03;
1881                         } else {
1882                                 tmpvar.b.l = data & 0xff;
1883                         }
1884                         if(mode400line) {
1885                                 if(tmpvar.d > 400) tmpvar.d = 400;
1886                         } else {
1887                                 tmpvar.d <<= 1;
1888                                 if(tmpvar.d > 400) tmpvar.d = 400;
1889                         }
1890                         window_high = tmpvar.d;
1891                         vram_wrote = true;
1892                         break;
1893 # endif
1894 #endif                          
1895                 default:
1896 #if defined(_FM77AV_VARIANTS)
1897                         //ALU
1898                         if((addr >= 0x13) && (addr <= 0x1a)) {
1899                                 alu_write_cmpdata_reg(addr - 0x13, data);
1900                         } else if((addr >= 0x1c) && (addr <= 0x1e)) {
1901                                 alu_write_tilepaint_data(addr, data);
1902                         } else if((addr >= 0x24) && (addr <= 0x2b)) {
1903                                 alu_write_line_position(addr - 0x24, data);
1904                         }
1905 #endif                          
1906                         break;
1907         }
1908 }
1909
1910 void DISPLAY::write_data8_main(uint32 addr, uint8 data)
1911 {
1912         uint32 offset;
1913         uint32 raddr;
1914         uint32 page_offset = 0x0000;
1915
1916         if(addr < 0xc000) return;
1917         
1918         if(addr < 0xd000) { 
1919                 raddr = addr - 0xc000;
1920 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1921                 if(monitor_ram) {
1922                         if(console_ram_bank >= 1) {
1923                                 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
1924                                 return;
1925                         }
1926                 }
1927 #endif
1928                 console_ram[raddr] = data;
1929                 return;
1930         } else if(addr < 0xd380) {
1931                 raddr = addr - 0xd000;
1932                 work_ram[raddr] = data;
1933                 return;
1934         } else if(addr < 0xd400) {
1935                 raddr = addr - 0xd380;
1936                 shared_ram[raddr] = data;
1937                 return;
1938         } else if(addr < 0xd800) {
1939 #if defined(_FM77AV_VARIANTS)
1940                 if(addr >= 0xd500) {
1941                         submem_hidden[addr - 0xd500] = data;
1942                         return;
1943                 }
1944 #endif
1945                 write_mmio(addr, data);
1946                 return;
1947         } else if(addr < 0x10000) {
1948 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
1949                 if(ram_protect) return;
1950                 if(monitor_ram) {
1951                         if(addr < 0xe000) {
1952                                 submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)] = data; //FIXME
1953                         } else {
1954                                 subsys_ram[addr - 0xe000] = data;
1955                         }
1956                 }
1957 #endif          
1958                 return;
1959         }
1960 }
1961
1962 void DISPLAY::write_data8(uint32 addr, uint32 data)
1963 {
1964         uint32 offset;
1965         uint32 raddr;
1966         uint32 page_offset = 0x0000;
1967         uint8 val8 = data & 0xff;
1968         uint32 pagemod;
1969         uint32 color = (addr & 0xc000) >> 14;
1970
1971         if(addr < 0xc000) {
1972 #if defined(_FM77AV_VARIANTS)
1973                 if(use_alu) {
1974                         alu->read_data8(addr + ALU_WRITE_PROXY);
1975                         return;
1976                 }
1977 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1978                 if(display_mode == DISPLAY_MODE_8_400L) {
1979                         color = vram_bank & 0x03;
1980                         if(color > 2) color = 0;
1981                 }
1982 # endif
1983 #endif
1984                 if((multimode_accessmask & (1 << color)) != 0) return;
1985                 write_vram_data8(addr, val8);
1986                 return;
1987         } else if(addr < 0x10000) {
1988                 write_data8_main(addr, val8);
1989                 return;
1990         } else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
1991                 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
1992                 return;
1993         }
1994 #if defined(_FM77AV_VARIANTS)
1995         // ANALOG PALETTE
1996         else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
1997                 set_apalette_r(val8);
1998                 return;
1999         } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
2000                 set_apalette_g(val8);
2001                 return;
2002         } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
2003                 set_apalette_b(val8);
2004                 return;
2005         } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
2006                 set_apalette_index_hi(val8);
2007                 return;
2008         } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
2009                 set_apalette_index_lo(val8);
2010                 return;
2011         }
2012         // ACCESS VIA ALU.
2013         else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2014                 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS; 
2015 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2016                 if(display_mode == DISPLAY_MODE_8_400L) {
2017                         color = (addr & 0x18000) >> 15;
2018                         if(color > 2) color = 0;
2019                         page_offset = 0;
2020 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2021                         if(vram_active_block != 0) page_offset = 0x18000;
2022 # endif         
2023                         if(color > 2) color = 0;
2024                         if (active_page != 0) {
2025                                 offset = offset_point_bank1 << 1;
2026                         } else {
2027                                 offset = offset_point << 1;
2028                         }
2029                         pagemod = 0x8000 * color;
2030                         gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset] = data;
2031                         vram_wrote_table[((addr + offset) % 0x8000) / 80] = true;
2032                         return;
2033                 }
2034                 write_vram_data8(addr, data);
2035 # else
2036                 write_vram_data8(addr, data);
2037 # endif
2038                 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
2039         }
2040 #endif
2041         return;
2042 }       
2043
2044
2045 uint32 DISPLAY::read_bios(const char *name, uint8 *ptr, uint32 size)
2046 {
2047         FILEIO fio;
2048         uint32 blocks;
2049         _TCHAR *s;
2050   
2051         if((name == NULL) || (ptr == NULL))  return 0;
2052         s = emu->bios_path((const _TCHAR *)name);
2053         if(s == NULL) return 0;
2054   
2055         if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
2056         blocks = fio.Fread(ptr, size, 1);
2057         fio.Fclose();
2058
2059         return blocks * size;
2060 }
2061
2062
2063 void DISPLAY::initialize()
2064 {
2065         int i;
2066
2067         memset(gvram, 0x00, sizeof(gvram));
2068 #if defined(_FM77AV_VARIANTS)
2069         memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
2070         vram_wrote_shadow = false;
2071         for(i = 0; i < 411; i++) vram_wrote_table[i] = false;
2072         for(i = 0; i < 411; i++) vram_draw_table[i] = false;
2073 #endif  
2074         memset(console_ram, 0x00, sizeof(console_ram));
2075         memset(work_ram, 0x00, sizeof(work_ram));
2076         memset(shared_ram, 0x00, sizeof(shared_ram));
2077         memset(subsys_c, 0xff, sizeof(subsys_c));
2078    
2079         diag_load_subrom_c = false;
2080         if(read_bios(_T("SUBSYS_C.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2081         emu->out_debug_log("SUBSYSTEM ROM Type C READING : %s", diag_load_subrom_c ? "OK" : "NG");
2082  
2083 #if defined(_FM77AV_VARIANTS)
2084         memset(subsys_a, 0xff, sizeof(subsys_a));
2085         memset(subsys_b, 0xff, sizeof(subsys_b));
2086         memset(subsys_cg, 0xff, sizeof(subsys_cg));
2087         memset(submem_hidden, 0x00, sizeof(submem_hidden));
2088    
2089         diag_load_subrom_a = false;
2090         if(read_bios(_T("SUBSYS_A.ROM"), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
2091         emu->out_debug_log("SUBSYSTEM ROM Type A READING : %s", diag_load_subrom_a ? "OK" : "NG");
2092
2093         diag_load_subrom_b = false;
2094         if(read_bios(_T("SUBSYS_B.ROM"), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
2095         emu->out_debug_log("SUBSYSTEM ROM Type B READING : %s", diag_load_subrom_b ? "OK" : "NG");
2096
2097         diag_load_subrom_cg = false;
2098         if(read_bios(_T("SUBSYSCG.ROM"), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
2099         emu->out_debug_log("SUBSYSTEM CG ROM READING : %s", diag_load_subrom_cg ? "OK" : "NG");
2100 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2101     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2102         memset(subsys_ram, 0x00, sizeof(subsys_ram));
2103         memset(submem_cgram, 0x00, sizeof(submem_cgram));
2104         memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
2105         ram_protect = true;
2106 # endif
2107 #endif
2108 #if defined(_FM77AV_VARIANTS)
2109         mode320 = false;
2110         apalette_index.d = 0;
2111         for(i = 0; i < 4096; i++) {
2112                 analog_palette_r[i] = i & 0x0f0;
2113                 analog_palette_g[i] = i & 0xf00;
2114                 analog_palette_b[i] = i & 0x00f;
2115                 calc_apalette(i);
2116         }
2117 #endif
2118 #if defined(_FM77AV_VARIANTS)
2119         hblank_event_id = -1;
2120         hdisp_event_id = -1;
2121         vsync_event_id = -1;
2122         vstart_event_id = -1;
2123 #endif  
2124         switch(config.cpu_type){
2125                 case 0:
2126                         clock_fast = true;
2127                         break;
2128                 case 1:
2129                         clock_fast = false;
2130                         break;
2131         }
2132         is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
2133         enter_display();
2134         nmi_event_id = -1;
2135         firq_mask = false;
2136         key_firq_req = false;   //firq_mask = true;
2137         frame_skip_count = 3;
2138 }
2139
2140 void DISPLAY::release()
2141 {
2142 }
2143
2144 #define STATE_VERSION 2
2145 void DISPLAY::save_state(FILEIO *state_fio)
2146 {
2147         state_fio->FputUint32_BE(STATE_VERSION);
2148         state_fio->FputInt32_BE(this_device_id);
2149
2150         {
2151                 int i;
2152                 state_fio->FputInt32_BE(clr_count);
2153                 state_fio->FputBool(halt_flag);
2154                 state_fio->FputInt32_BE(active_page);
2155                 state_fio->FputBool(sub_busy);
2156                 state_fio->FputBool(crt_flag);
2157                 state_fio->FputBool(vram_wrote);
2158 #if defined(_FM77AV_VARIANTS)
2159                 state_fio->FputBool(vram_wrote_shadow);
2160                 for(i = 0; i < 411; i++) state_fio->FputBool(vram_wrote_table[i]);
2161                 for(i = 0; i < 411; i++) state_fio->FputBool(vram_draw_table[i]);
2162 #endif          
2163                 state_fio->FputBool(is_cyclesteal);
2164                 
2165                 state_fio->FputBool(clock_fast);
2166                 
2167 #if defined(_FM77AV_VARIANTS)
2168                 state_fio->FputBool(subcpu_resetreq);
2169                 state_fio->FputBool(power_on_reset);
2170 #endif  
2171                 state_fio->FputBool(cancel_request);
2172                 state_fio->FputBool(key_firq_req);
2173
2174                 state_fio->FputInt32_BE(display_mode);
2175                 state_fio->FputUint32_BE(prev_clock);
2176
2177                 state_fio->Fwrite(dpalette_data, sizeof(dpalette_data), 1);
2178                 state_fio->FputUint8(multimode_accessmask);
2179                 state_fio->FputUint8(multimode_dispmask);
2180                 state_fio->FputUint32_BE(offset_point);
2181 #if defined(_FM77AV_VARIANTS)
2182                 state_fio->FputUint32_BE(offset_point_bank1);
2183                 state_fio->FputUint32_BE(offset_point_bak);
2184                 state_fio->FputUint32_BE(offset_point_bank1_bak);
2185 #endif          
2186                 for(i = 0; i < 2; i++) {
2187                         state_fio->FputUint32_BE(tmp_offset_point[i].d);
2188                         state_fio->FputBool(offset_changed[i]);
2189                 }
2190                 state_fio->FputBool(offset_77av);
2191                 state_fio->FputBool(diag_load_subrom_c);
2192                 
2193         
2194                 state_fio->Fwrite(io_w_latch, sizeof(io_w_latch), 1);
2195                 state_fio->Fwrite(console_ram, sizeof(console_ram), 1);
2196                 state_fio->Fwrite(work_ram, sizeof(work_ram), 1);
2197                 state_fio->Fwrite(shared_ram, sizeof(shared_ram), 1);
2198                 state_fio->Fwrite(subsys_c, sizeof(subsys_c), 1);
2199                 state_fio->Fwrite(gvram, sizeof(gvram), 1);
2200 #if defined(_FM77AV_VARIANTS)
2201                 state_fio->Fwrite(gvram_shadow, sizeof(gvram_shadow), 1);
2202 #endif  
2203         
2204 #if defined(_FM77_VARIANTS)
2205                 state_fio->FputBool(kanjisub);
2206                 state_fio->FputUint16_BE(kanjiaddr.w.l);
2207 # if defined(_FM77L4)
2208                 state_fio->FputBool(mode400line);
2209                 state_fio->FputBool(stat_400linecard);
2210 # endif
2211 #elif defined(_FM77AV_VARIANTS)
2212                 state_fio->FputBool(kanjisub);
2213                 state_fio->FputUint16_BE(kanjiaddr.w.l);
2214
2215                 state_fio->FputBool(vblank);
2216                 state_fio->FputBool(vsync);
2217                 state_fio->FputBool(hblank);
2218                 state_fio->FputInt32_BE(vblank_count);
2219                 state_fio->FputUint32_BE(displine);
2220                 
2221                 state_fio->FputBool(mode320);
2222                 state_fio->FputInt32_BE(display_page);
2223                 state_fio->FputInt32_BE(cgrom_bank);
2224 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
2225     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2226                 state_fio->FputInt32_BE(vram_bank);
2227 #endif  
2228         
2229                 state_fio->FputUint8(subrom_bank);
2230                 state_fio->FputUint8(subrom_bank_using);
2231         
2232                 state_fio->FputBool(nmi_enable);
2233                 state_fio->FputBool(use_alu);
2234                 
2235                 state_fio->FputUint8(apalette_index.b.l);
2236                 state_fio->FputUint8(apalette_index.b.h);
2237                 state_fio->Fwrite(analog_palette_r, sizeof(analog_palette_r), 1);
2238                 state_fio->Fwrite(analog_palette_g, sizeof(analog_palette_g), 1);
2239                 state_fio->Fwrite(analog_palette_b, sizeof(analog_palette_b), 1);
2240                 
2241
2242                 state_fio->FputBool(diag_load_subrom_a);
2243                 state_fio->FputBool(diag_load_subrom_b);
2244                 state_fio->FputBool(diag_load_subrom_cg);
2245         
2246                 state_fio->Fwrite(subsys_a, sizeof(subsys_a), 1);
2247                 state_fio->Fwrite(subsys_b, sizeof(subsys_b), 1);
2248                 state_fio->Fwrite(subsys_cg, sizeof(subsys_cg), 1);
2249                 state_fio->Fwrite(submem_hidden, sizeof(submem_hidden), 1);
2250 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2251                 state_fio->FputBool(mode400line);
2252                 state_fio->FputBool(mode256k);
2253                 
2254                 state_fio->FputBool(monitor_ram);
2255 #  if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2256                 state_fio->FputUint16_BE(window_low);
2257                 state_fio->FputUint16_BE(window_high);
2258                 state_fio->FputUint16_BE(window_xbegin);
2259                 state_fio->FputUint16_BE(window_xend);
2260                 state_fio->FputBool(window_opened);
2261 #  endif        
2262                 state_fio->FputBool(kanji_level2);
2263
2264                 state_fio->FputUint8(vram_active_block);
2265                 state_fio->FputUint8(vram_display_block);
2266                 state_fio->FputUint8(console_ram_bank);
2267                 state_fio->FputBool(ram_protect);
2268                 
2269                 state_fio->FputUint32_BE(cgram_bank);
2270                 state_fio->Fwrite(subsys_ram, sizeof(subsys_ram), 1);
2271                 state_fio->Fwrite(submem_cgram, sizeof(submem_cgram), 1);
2272                 state_fio->Fwrite(submem_console_av40, sizeof(submem_console_av40), 1);
2273 # endif
2274 #endif
2275         }
2276         // V2
2277         {
2278                 state_fio->FputInt32_BE(nmi_event_id);
2279 #if defined(_FM77AV_VARIANTS)
2280                 state_fio->FputInt32_BE(hblank_event_id);
2281                 state_fio->FputInt32_BE(hdisp_event_id);
2282                 state_fio->FputInt32_BE(vsync_event_id);
2283                 state_fio->FputInt32_BE(vstart_event_id);
2284 #endif
2285                 state_fio->FputBool(firq_mask);
2286                 state_fio->FputBool(vram_accessflag);
2287                 state_fio->FputUint32_BE(frame_skip_count);
2288         }                       
2289 }
2290
2291 bool DISPLAY::load_state(FILEIO *state_fio)
2292 {
2293
2294         uint32 version = state_fio->FgetUint32_BE();
2295         if(this_device_id != state_fio->FgetInt32_BE()) return false;
2296         if(version >= 1) {
2297                 int addr;
2298                 int i;
2299                 clr_count = state_fio->FgetInt32_BE();
2300                 halt_flag = state_fio->FgetBool();
2301                 active_page = state_fio->FgetInt32_BE();
2302                 sub_busy = state_fio->FgetBool();
2303                 crt_flag = state_fio->FgetBool();
2304                 vram_wrote = state_fio->FgetBool();
2305 #if defined(_FM77AV_VARIANTS)
2306                 vram_wrote_shadow = state_fio->FgetBool();
2307                 for(i = 0; i < 411; i++) vram_wrote_table[i] = state_fio->FgetBool();
2308                 for(i = 0; i < 411; i++) vram_draw_table[i] = state_fio->FgetBool();
2309 #endif          
2310                 is_cyclesteal = state_fio->FgetBool();
2311         
2312                 clock_fast = state_fio->FgetBool();
2313
2314 #if defined(_FM77AV_VARIANTS)
2315                 subcpu_resetreq = state_fio->FgetBool();
2316                 power_on_reset = state_fio->FgetBool();
2317 #endif          
2318                 cancel_request = state_fio->FgetBool();
2319                 key_firq_req = state_fio->FgetBool();
2320
2321                 display_mode = state_fio->FgetInt32_BE();
2322                 prev_clock = state_fio->FgetUint32_BE();
2323         
2324                 state_fio->Fread(dpalette_data, sizeof(dpalette_data), 1);
2325                 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
2326
2327                 multimode_accessmask = state_fio->FgetUint8();
2328                 multimode_dispmask = state_fio->FgetUint8();
2329                 offset_point = state_fio->FgetUint32_BE();
2330 #if defined(_FM77AV_VARIANTS)
2331                 offset_point_bank1     = state_fio->FgetUint32_BE();
2332                 offset_point_bak       = state_fio->FgetUint32_BE();
2333                 offset_point_bank1_bak = state_fio->FgetUint32_BE();
2334 #endif          
2335                 for(i = 0; i < 2; i++) {
2336                         tmp_offset_point[i].d = state_fio->FgetUint32_BE();
2337                         offset_changed[i] = state_fio->FgetBool();
2338                 }
2339                 offset_77av = state_fio->FgetBool();
2340                 diag_load_subrom_c = state_fio->FgetBool();
2341                 
2342                 state_fio->Fread(io_w_latch, sizeof(io_w_latch), 1);
2343                 state_fio->Fread(console_ram, sizeof(console_ram), 1);
2344                 state_fio->Fread(work_ram, sizeof(work_ram), 1);
2345                 state_fio->Fread(shared_ram, sizeof(shared_ram), 1);
2346                 state_fio->Fread(subsys_c, sizeof(subsys_c), 1);
2347                 state_fio->Fread(gvram, sizeof(gvram), 1);
2348 #if defined(_FM77AV_VARIANTS)
2349                 state_fio->Fread(gvram_shadow, sizeof(gvram_shadow), 1);
2350 #endif  
2351 #if defined(_FM77_VARIANTS)
2352                 kanjisub = state_fio->FgetBool();
2353                 kanjiaddr.d = 0;
2354                 kanjiaddr.w.l = state_fio->FgetUint16_BE();
2355 # if defined(_FM77L4)           
2356                 mode400line = state_fio->FgetBool();
2357                 stat_400linecard = state_fio->FgetBool();
2358 # endif         
2359 #elif defined(_FM77AV_VARIANTS)
2360                 kanjisub = state_fio->FgetBool();
2361                 kanjiaddr.d = 0;
2362                 kanjiaddr.w.l = state_fio->FgetUint16_BE();
2363                 
2364                 vblank = state_fio->FgetBool();
2365                 vsync = state_fio->FgetBool();
2366                 hblank = state_fio->FgetBool();
2367                 vblank_count = state_fio->FgetInt32_BE();
2368                 displine = state_fio->FgetUint32_BE();
2369
2370                 mode320 = state_fio->FgetBool();
2371                 display_page = state_fio->FgetInt32_BE();
2372                 cgrom_bank = state_fio->FgetInt32_BE();
2373 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
2374     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2375                 vram_bank = state_fio->FgetInt32_BE();
2376 #endif          
2377         
2378                 subrom_bank = state_fio->FgetUint8();
2379                 subrom_bank_using = state_fio->FgetUint8();
2380         
2381                 nmi_enable = state_fio->FgetBool();
2382                 use_alu = state_fio->FgetBool();
2383
2384                 apalette_index.b.l = state_fio->FgetUint8();
2385                 apalette_index.b.h = state_fio->FgetUint8();
2386         
2387                 state_fio->Fread(analog_palette_r, sizeof(analog_palette_r), 1);
2388                 state_fio->Fread(analog_palette_g, sizeof(analog_palette_g), 1);
2389                 state_fio->Fread(analog_palette_b, sizeof(analog_palette_b), 1);
2390                 for(i = 0; i < 4096; i++) calc_apalette(i);
2391                 
2392                 diag_load_subrom_a = state_fio->FgetBool();
2393                 diag_load_subrom_b = state_fio->FgetBool();
2394                 diag_load_subrom_cg = state_fio->FgetBool();
2395         
2396                 state_fio->Fread(subsys_a, sizeof(subsys_a), 1);
2397                 state_fio->Fread(subsys_b, sizeof(subsys_b), 1);
2398                 state_fio->Fread(subsys_cg, sizeof(subsys_cg), 1);
2399                 state_fio->Fread(submem_hidden, sizeof(submem_hidden), 1);
2400            
2401 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2402                 mode400line = state_fio->FgetBool();
2403                 mode256k = state_fio->FgetBool();
2404
2405                 monitor_ram = state_fio->FgetBool();
2406 #  if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2407                 window_low = state_fio->FgetUint16_BE();
2408                 window_high = state_fio->FgetUint16_BE();
2409                 window_xbegin = state_fio->FgetUint16_BE();
2410                 window_xend = state_fio->FgetUint16_BE();
2411                 window_opened = state_fio->FgetBool();
2412 # endif 
2413                 kanji_level2 = state_fio->FgetBool();
2414                 
2415                 vram_active_block = state_fio->FgetUint8();
2416                 vram_display_block = state_fio->FgetUint8();
2417                 console_ram_bank = state_fio->FgetUint8();
2418                 ram_protect = state_fio->FgetBool();
2419
2420                 cgram_bank = state_fio->FgetUint32_BE();
2421                 state_fio->Fread(subsys_ram, sizeof(subsys_ram), 1);
2422                 state_fio->Fread(submem_cgram, sizeof(submem_cgram), 1);
2423                 state_fio->Fread(submem_console_av40, sizeof(submem_console_av40), 1);
2424 # endif
2425 #endif
2426                 if(version == 1) return true;
2427         }
2428         if(version >= 2) {      //V2
2429                 nmi_event_id = state_fio->FgetInt32_BE();
2430 #if defined(_FM77AV_VARIANTS)
2431                 hblank_event_id = state_fio->FgetInt32_BE();
2432                 hdisp_event_id = state_fio->FgetInt32_BE();
2433                 vsync_event_id = state_fio->FgetInt32_BE();
2434                 vstart_event_id = state_fio->FgetInt32_BE();
2435 #endif
2436                 firq_mask = state_fio->FgetBool();
2437                 vram_accessflag = state_fio->FgetBool();
2438                 frame_skip_count = state_fio->FgetUint32_BE();
2439         }                       
2440         return true;
2441 }
2442
2443