OSDN Git Service

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