OSDN Git Service

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