OSDN Git Service

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