OSDN Git Service

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