OSDN Git Service

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