OSDN Git Service

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