OSDN Git Service

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